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

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 में बड़े पैमाने पर किया जाता है:

  • सामान्य तौर पर, "snake_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 वर्णों से ज़्यादा के हों. जहां तक हो सके लेबल, स्ट्रिंग की लिटरल वैल्यू होने चाहिए. वजह: इससे ढूंढना और बदलना आसान हो जाता है. इससे ऐप्लिकेशन को पढ़ना भी आसान हो जाता है.

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

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

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

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

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

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

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

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

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