स्टाइल गाइड बनाएं

समस्या की शिकायत करें सोर्स देखें ठीक

BUILD फ़ाइल फ़ॉर्मैटिंग, Go के तरीके जैसा ही है. यहां एक मानक टूल, फ़ॉर्मैटिंग की ज़्यादातर समस्याओं को ठीक कर देता है. Buildifier एक ऐसा टूल है जो सोर्स कोड को स्टैंडर्ड स्टाइल में पार्स और बेहतरीन बनाते हैं. इसलिए, हर BUILD फ़ाइल को एक ही तरह से अपने-आप फ़ॉर्मैट किया जाता है. इससे कोड की समीक्षाओं के दौरान फ़ॉर्मैटिंग में कोई समस्या नहीं होती. इससे टूल के लिए, BUILD फ़ाइलों को समझना, उनमें बदलाव करना, और उन्हें जनरेट करना भी आसान हो जाता है.

BUILD की फ़ाइल फ़ॉर्मैटिंग, buildifier के आउटपुट से मेल खानी चाहिए.

फ़ॉर्मैट करने का उदाहरण

# Test code implementing the Foo controller.
package(default_testonly = True)

py_test(
    name = "foo_test",
    srcs = glob(["*.py"]),
    data = [
        "//data/production/foo:startfoo",
        "//foo",
        "//third_party/java/jdk:jdk-k8",
    ],
    flaky = True,
    deps = [
        ":check_bar_lib",
        ":foo_data_check",
        ":pick_foo_port",
        "//pyglib",
        "//testing/pybase",
    ],
)

फ़ाइल का स्ट्रक्चर

सुझाव: नीचे दिए गए क्रम का इस्तेमाल करें (हर एलिमेंट ज़रूरी नहीं है):

  • पैकेज का ब्यौरा (एक टिप्पणी)

  • सभी load() स्टेटमेंट

  • package() फ़ंक्शन.

  • नियमों और मैक्रो को कॉल करने की सुविधा

बिल्डिफ़ायर, स्टैंडअलोन टिप्पणी और किसी एलिमेंट से जुड़ी टिप्पणी के बीच फ़र्क़ करता है. अगर कोई टिप्पणी किसी खास एलिमेंट के साथ अटैच नहीं है, तो उसके बाद वाली खाली लाइन इस्तेमाल करें. अपने-आप होने वाले बदलाव करते समय यह फ़र्क़ करना ज़रूरी होता है कि किसी नियम को मिटाते समय टिप्पणी को सेव रखना या हटाना.

# Standalone comment (such as to make a section in a file)

# Comment for the cc_library below
cc_library(name = "cc")

मौजूदा पैकेज में टारगेट के रेफ़रंस

फ़ाइलों को पैकेज डायरेक्ट्री के पाथ से रेफ़र किया जाना चाहिए (.. जैसे किसी अप-रेफ़रंस का इस्तेमाल किए बिना). जनरेट की गई फ़ाइलों के प्रीफ़िक्स के तौर पर ":" लगा होना चाहिए. इससे यह पता चलता है कि वे सोर्स नहीं हैं. सोर्स फ़ाइलों के आगे : नहीं होना चाहिए. नियमों की शुरुआत में : होना चाहिए. उदाहरण के लिए, यह मानते हुए कि x.cc एक सोर्स फ़ाइल है:

cc_library(
    name = "lib",
    srcs = ["x.cc"],
    hdrs = [":gen_header"],
)

genrule(
    name = "gen_header",
    srcs = [],
    outs = ["x.h"],
    cmd = "echo 'int x();' > $@",
)

टारगेट का नाम

टारगेट के नामों में पूरी जानकारी होनी चाहिए. अगर टारगेट में एक सोर्स फ़ाइल है, तो आम तौर पर टारगेट का नाम उस सोर्स से लिया गया होना चाहिए (उदाहरण के लिए, chat.cc के लिए cc_library का नाम chat या DirectMessage.java के लिए java_library का नाम direct_message हो सकता है).

किसी पैकेज (किसी मौजूदा डायरेक्ट्री के नाम वाला टारगेट) के लिए, उसी नाम वाले टारगेट से डायरेक्ट्री के नाम में बताया जाने वाला फ़ंक्शन मिलना चाहिए. अगर ऐसा कोई टारगेट नहीं है, तो नाम वाला कोई टारगेट न बनाएं.

किसी मिलते-जुलते टारगेट को रेफ़र करते समय, //x:x के बजाय //x का इस्तेमाल करें. अगर आप एक ही पैकेज में हैं, तो स्थानीय पहचान फ़ाइल (//x के बजाय :x) को प्राथमिकता दें.

खास मतलब वाले "रिज़र्व किए गए" टारगेट नामों का इस्तेमाल करने से बचें. इसमें all, __pkg__, और __subpackages__ शामिल हैं. इन नामों के खास सिमैंटिक होते हैं. इसलिए, इनका इस्तेमाल करते समय भ्रम की स्थिति पैदा हो सकती है और इनसे कुछ गलत व्यवहार हो सकते हैं.

मौजूदा टीम कन्वेंशन के बिना, ये कुछ ऐसे सुझाव हैं जिन्हें मानना ज़रूरी नहीं है. Google पर इन सुझावों का ज़्यादा इस्तेमाल किया जाता है:

  • आम तौर पर, "ONE_case" का इस्तेमाल करें
    • एक src वाले java_library के लिए इसका मतलब ऐसे नाम का इस्तेमाल करना है जो एक्सटेंशन के बिना फ़ाइल नाम से मेल नहीं खाता
    • Java *_binary और *_test के नियमों के लिए, "Upper CamelCase" का इस्तेमाल करें. इससे टारगेट का नाम, src में से किसी एक से मैच हो जाता है. java_test के लिए, इसकी मदद से test_class एट्रिब्यूट को टारगेट के नाम से लिया जा सकता है.
  • अगर किसी खास टारगेट के कई वैरिएंट हैं, तो उनके बीच अंतर बताने के लिए सफ़िक्स जोड़ें (जैसे कि :foo_dev, :foo_prod या :bar_x86, :bar_x64)
  • _test, _unittest, Test या Tests वाले _test टारगेट को सफ़िक्स पर लागू करें
  • _lib या _library जैसे बिना मतलब के सफ़िक्स का इस्तेमाल न करें. ऐसा तब करें, जब _library टारगेट और उससे जुड़े _binary के बीच टकराव से बचने के लिए ज़रूरी हो
  • प्रोटो से जुड़े टारगेट के लिए:
    • proto_library टारगेट के नाम _proto से खत्म होने चाहिए
    • अलग-अलग भाषाओं के लिए *_proto_library के नियम, दिए गए प्रोटो से मेल खाने चाहिए. हालांकि, _proto को भाषा के हिसाब से सफ़िक्स से बदल देना चाहिए, जैसे कि:
      • cc_proto_library: _cc_proto
      • java_proto_library: _java_proto
      • java_lite_proto_library: _java_proto_lite

किसको दिखे

विज़िबिलिटी का दायरा जितना हो सके उतना सटीक होना चाहिए. साथ ही, टेस्ट और रिवर्स डिपेंडेंसी से ऐक्सेस दिया जाना चाहिए. ज़रूरत के हिसाब से __pkg__ और __subpackages__ इस्तेमाल करें.

default_visibility पैकेज को //visibility:public पर सेट न करें. //visibility:public को सिर्फ़ प्रोजेक्ट के सार्वजनिक एपीआई में मौजूद टारगेट के लिए अलग-अलग सेट किया जाना चाहिए. ये ऐसी लाइब्रेरी हो सकती हैं जिन्हें किसी बाहरी प्रोजेक्ट या बाइनरी पर निर्भर रहने के लिए डिज़ाइन किया गया है. इनका इस्तेमाल बाहरी प्रोजेक्ट की बिल्ड प्रोसेस में किया जा सकता है.

डिपेंडेंसी

डिपेंडेंसी को डायरेक्ट डिपेंडेंसी तक सीमित होना चाहिए (नियम में बताए गए सोर्स के लिए ज़रूरी डिपेंडेंसी). ट्रांज़िटिव डिपेंडेंसी को सूची में शामिल न करें.

पैकेज-लोकल डिपेंडेंसी को पहले सूची में शामिल किया जाना चाहिए. साथ ही, इनका रेफ़रंस ऊपर दिए गए मौजूदा पैकेज में टारगेट के रेफ़रंस सेक्शन के साथ इस तरीके से दिया जाना चाहिए (न कि पैकेज के पूरे नाम के हिसाब से).

डिपेंडेंसी को एक ही सूची के तौर पर सीधे तौर पर लिस्ट करना है. एक वैरिएबल में कई टारगेट की "सामान्य" डिपेंडेंसी डालने से रखरखाव में कमी आ जाती है और टूल के लिए टारगेट की डिपेंडेंसी को बदलना नामुमकिन हो जाता है. साथ ही, इसकी वजह से इस्तेमाल न होने वाली डिपेंडेंसी हो सकती है.

ग्लोब

[] से "कोई टारगेट नहीं" दिखाएं. किसी ऐसे ग्लोब का इस्तेमाल न करें जो किसी भी चीज़ से मेल न खाता हो: उस ग्लोब में गड़बड़ी होने की ज़्यादा संभावना होती है और यह खाली सूची की तुलना में कम साफ़ होता है.

बार-बार होने वाला

सोर्स फ़ाइलों से मिलान करने के लिए, बार-बार इस्तेमाल होने वाले ग्लब का इस्तेमाल न करें (उदाहरण के लिए, glob(["**/*.java"])).

बार-बार होने वाले ग्लब्स BUILD फ़ाइलों के बारे में सोचना मुश्किल बना देते हैं क्योंकि वे BUILD फ़ाइलों वाली सबडायरेक्ट्री को छोड़ देते हैं.

आम तौर पर, हर डायरेक्ट्री में BUILD फ़ाइल होने के मुकाबले, बार-बार होने वाले ग्लोब कम काम करते हैं. इन फ़ाइलों के बीच डिपेंडेंसी ग्राफ़ होता है. ऐसा इसलिए होता है, क्योंकि इससे रिमोट तरीके से कैश मेमोरी में सेव करने और एक साथ काम करने की सुविधा मिलती है.

हर डायरेक्ट्री में BUILD फ़ाइल लिखना और उनके बीच डिपेंडेंसी ग्राफ़ बनाना अच्छी बात है.

बार-बार नहीं होने वाला

आम तौर पर, नॉन-रिकर्सिव ग्लोब का इस्तेमाल किया जा सकता है.

अन्य कन्वेंशन

  • कॉन्सटेंट की जानकारी देने के लिए, अंग्रेज़ी के बड़े अक्षरों और अंडरस्कोर का इस्तेमाल करें, जैसे कि GLOBAL_CONSTANT. वैरिएबल के बारे में जानकारी देने के लिए, अंग्रेज़ी के छोटे अक्षरों और अंडरस्कोर का इस्तेमाल करें, जैसे कि my_variable.

  • लेबल को कभी भी बांटा नहीं जाना चाहिए, भले ही वे 79 वर्णों से ज़्यादा लंबे हों. जब भी हो सके, लेबल को स्ट्रिंग की लिटरल वैल्यू होना चाहिए. तथ्यों के हिसाब से: इससे पता लगाना और बदलना आसान हो जाता है. इससे कॉन्टेंट को पढ़ना भी आसान हो जाता है.

  • नाम एट्रिब्यूट की वैल्यू, एक लिटरल कॉन्सटैंट स्ट्रिंग होनी चाहिए (मैक्रो को छोड़कर). तथ्यों के हिसाब से: बाहरी टूल किसी नियम के बारे में बताने के लिए, नाम वाले एट्रिब्यूट का इस्तेमाल करते हैं. उन्हें कोड समझने की ज़रूरत के बिना ही, नियम तलाशने होते हैं.

  • बूलियन-टाइप एट्रिब्यूट सेट करते समय, बूलियन वैल्यू का इस्तेमाल करें, न कि पूर्णांक वैल्यू का. लेगसी वजहों से, नियम अब भी इंटीजर को ज़रूरत के हिसाब से बूलियन में बदल देते हैं. हालांकि, ऐसा करने की सलाह नहीं दी जाती है. तथ्यों के हिसाब से: flaky = 1 को गलती से यह कहा जा सकता है कि "इस टारगेट को एक बार फिर से चलाकर, डिफ़ेक करें". flaky = True साफ़ तौर पर कहता है, "यह टेस्ट सही नहीं है".

Python स्टाइल गाइड के साथ अंतर

हालांकि, एक लक्ष्य Python स्टाइल गाइड के साथ काम करना है, लेकिन इनमें कुछ अंतर हैं:

  • लाइन की लंबाई की कोई सख्त सीमा नहीं है. लंबी टिप्पणियों और लंबी स्ट्रिंग को अक्सर 79 कॉलम में बांटा जाता है, लेकिन ऐसा करना ज़रूरी नहीं है. इसे कोड की समीक्षाओं में या स्क्रिप्ट को पहले से सबमिट करते समय लागू नहीं किया जाना चाहिए. ज़रूरी वजह: लेबल लंबे हो सकते हैं और तय सीमा से ज़्यादा हो सकते हैं. आम तौर पर, BUILD फ़ाइलों को टूल की मदद से जनरेट किया जाता है या उनमें बदलाव किया जाता है. हालांकि, लाइनों की लंबाई की सीमा तय करना सही नहीं है.

  • इंप्लिसिट स्ट्रिंग को जोड़ने की सुविधा काम नहीं करती. + ऑपरेटर का इस्तेमाल करें. खास जानकारी: BUILD फ़ाइलों में कई स्ट्रिंग की सूचियां होती हैं. एक कॉमा को भूलना आसान है, जो एक अलग परिणाम देता है. इस गड़बड़ी की वजह से, पहले कई गड़बड़ियां हुई हैं. यह चर्चा भी देखें.

  • नियमों में कीवर्ड आर्ग्युमेंट के लिए, = निशान के आस-पास स्पेस का इस्तेमाल करें. Rationale: Python के मुकाबले, नाम वाले आर्ग्युमेंट ज़्यादा बार इस्तेमाल किए जाते हैं और ये हमेशा एक अलग लाइन पर होते हैं. स्पेसेज़ का इस्तेमाल करके, कॉन्टेंट को आसानी से पढ़ा जा सकता है. ऐसा काफ़ी समय से हो रहा है. इसलिए, सभी मौजूदा BUILD फ़ाइलों में बदलाव करना सही नहीं है.

  • डिफ़ॉल्ट रूप से, स्ट्रिंग के लिए डबल कोटेशन मार्क का इस्तेमाल करें. Rationale: इस बारे में Python स्टाइल गाइड में जानकारी नहीं दी गई है, लेकिन यह एक जैसा रखने का सुझाव देता है. इसलिए, हमने सिर्फ़ डबल-कोट वाली स्ट्रिंग इस्तेमाल करने का फ़ैसला किया. कई भाषाओं में, स्ट्रिंग की लिटरल वैल्यू के लिए डबल कोट का इस्तेमाल किया जाता है.

  • दो टॉप लेवल परिभाषाओं के बीच एक खाली लाइन का इस्तेमाल करें. खास जानकारी: किसी BUILD फ़ाइल का स्ट्रक्चर, किसी आम Python फ़ाइल की तरह नहीं होता. इसमें सिर्फ़ टॉप-लेवल स्टेटमेंट हैं. एक खाली लाइन का इस्तेमाल करने से, BUILD फ़ाइलें छोटी हो जाती हैं.