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

किसी समस्या की शिकायत करना सोर्स देखना Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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() फ़ंक्शन.

  • नियमों और मैक्रो के लिए कॉल

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

# 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 को प्रोजेक्ट के सार्वजनिक एपीआई में मौजूद टारगेट के लिए ही अलग से सेट किया जाना चाहिए. ये ऐसी लाइब्रेरी हो सकती हैं जिन्हें बाहरी प्रोजेक्ट पर निर्भर रहने के लिए डिज़ाइन किया गया हो या ऐसी बाइनरी हो जिनका इस्तेमाल, बाहरी प्रोजेक्ट की बिल्ड प्रोसेस में किया जा सकता हो.

डिपेंडेंसी

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

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

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

Globs

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

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

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

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

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

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

नॉन-रीकर्सिव

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

अन्य समझौते

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

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

  • नाम एट्रिब्यूट की वैल्यू, मैक्रो को छोड़कर, लिटरल कॉन्स्टेंट स्ट्रिंग होनी चाहिए. Rationale: बाहरी टूल, किसी नियम का रेफ़रंस देने के लिए नाम एट्रिब्यूट का इस्तेमाल करते हैं. उन्हें कोड को समझे बिना नियम ढूंढने होंगे.

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

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

Python स्टाइल गाइड के साथ काम करने की सुविधा उपलब्ध कराना हमारा लक्ष्य है. हालांकि, इसमें कुछ अंतर हैं:

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

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

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

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

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