2009-08-15 6 views
43

दिन तक मैं सी # लिखता हूं। मैं जो कुछ भी करता हूं वह माइक्रोसॉफ्ट कोड विश्लेषण और स्थिर विश्लेषण उपकरण के माध्यम से जाता है, इसलिए मेरे सी # में एक बहुत ही नियमित संरचना और लेआउट है। जाहिर है, मैं एक निश्चित शैली के साथ कोड लिखता हूं। यह आंशिक रूप से है, क्योंकि मेरे पास कोई विकल्प नहीं है (अगर मैं उस अल्पविराम से पहले किसी स्थान को याद करता हूं तो यह संकलित नहीं होगा), लेकिन नियमित रूप से दिखने वाला कोड होना, यह जानना भी अच्छा है कि चीजों को कहां देखना है, आदिस्कैला शैली के तत्व?

पर सप्ताहांत मैं स्कैला में जा रहा हूँ। स्कैला एपीआई और Lift वेब ढांचे स्रोत को देखते हुए, मैं स्पष्ट रूप से किसी भी मानकीकृत शैली को नहीं देख सकता। एक बात जो मुझ पर कूदती है, उदाहरण के लिए, प्रति वर्ग एक अलग फ़ाइल की कमी है। ब्रैकेट और ब्रेसिज़ के साथ स्थिरता की कमी एक और उदाहरण है।

मैं समझता हूं कि शायद इसे चलाने के कुछ कारण हैं: सबसे पहले, ओपन सोर्स (या शौक) कोड के साथ यह सुनिश्चित करने के लिए कि एक स्पष्ट विधि पूरी तरह से प्रलेखित नहीं है, प्राथमिकता से कम है। दूसरा, केस कक्षाओं जैसी चीजें एक पंक्ति में 20-पंक्ति वर्ग घोषणाओं को काट देती हैं। तीसरा, सी # एक बहुत ही 'चापलूसी' भाषा है: जब तक यह एक जटिल LINQ कथन नहीं है, नेस्टेड माता-पिता, ब्रेसिज़ और ब्रैकेट की संख्या गहरी नहीं है। स्कैला में, चीजें थोड़ा घोंसला मिलता है।

नियमित स्कैला उपयोगकर्ताओं के पास एक विशिष्ट शैली है जो वे चिपकते हैं? क्या मैं सिर्फ [विदेशी] सम्मेलन के लिए अपनी फाइल में एक-लाइन केस-क्लास डाल रहा हूं? कोई सुझाव?

+0

श्री ओडर्स्की ने 'स्टाला के साथ स्केल' पर स्कैला दिवस 2013 में एक मुख्य नोट दिया - http://www.parleys.com/play/51c1994ae4b0d38b54f4621b/chapter0/about –

उत्तर

45

एक फ़ाइल के अंदर कई वर्गों और वस्तुओं को स्केल में अच्छा रूप माना जाता है, जब तक कि कक्षाएं कड़ाई से संबंधित हों।

आवश्यक नहीं होने पर, एक विधि द्वारा लौटाया गया प्रकार - एक विशेषता, वर्ग या वस्तु पर घोषित नामित फ़ंक्शन - गैर-निजी तरीकों के लिए घोषित होने की उम्मीद है। : के बाद रिक्त स्थान की उम्मीद है, लेकिन इससे पहले नहीं।

// methods declared on a class, trait or object 
def length: Int = ... 
def multiply(other: Foo): Foo = ... 

def hypotenuse(a: Double, b: Double): Double = { 
    // function inside a method, so effectively private 
    def square(x: Double) = x * x 

    math.sqrt(square(a) + square(b)) 
} 

रिक्त स्थान कीवर्ड और कोष्ठक के बीच होने की संभावना है, लेकिन एक विधि नाम और निम्नलिखित कोष्ठक, डॉट नोटेशन के बीच नहीं। ऑपरेटर नोटेशन के लिए, ब्रांड्स के संबंध में एक स्वीकार्य शैली प्रतीत नहीं होती है - या उस नोटेशन का उपयोग करने के लिए, उस मामले के लिए, लेकिन इस तरह के नोटेशन में गैर-अल्फान्यूमेरिक तरीकों के आसपास रिक्त स्थान की अपेक्षा की जाती है।

// keywords 
if (foo) ... 

// dot notation 
foo.doSomething(bar) 

// operator notation 
foo doSomething bar 
foo + bar 

असाधारण, जब + साथ तार श्रृंखलाबद्ध, की सिफारिश की शैली इसके चारों ओर रिक्त स्थान का उपयोग नहीं है। उदाहरण के लिए:

// concatenate strings 
println("Name: "+person.name+"\tAge: "+person.age) 

घोषणा कि हो सकता है एक-लाइनर्स एक-लाइनर्स हो सकता है, जब तक कि घोंसले स्पष्ट नहीं है की संभावना है।

// one-liners 
lazy val foo = calculateFoo 
def square(x: Int) = x * x 

तरीके है कि मानकों की उम्मीद नहीं है, और साइड इफेक्ट नहीं है,, कोष्टक के बिना इस्तेमाल किया जा जावा तरीकों, जो कोष्ठक के साथ इस्तेमाल किया जा करने की संभावना है के लिए छोड़कर अपेक्षा की जाती है। साइड इफेक्ट्स के साथ पैरामीटर-कम विधियों को ब्रांड्स के साथ उपयोग किया जाना चाहिए।

// without side-effects 
val x = foo.length 
val y = bar.coefficient 

// with side-effects 
foo.reverse() 

घोषणाएं जो एक अभिव्यक्ति होता है घुंघराले ब्रेसिज़ के अंदर संलग्न होने की नहीं जब तक कि अन्य वाक्यात्मक विचार हैं जिनका असंभव बना उम्मीद कर रहे हैं। मल्टी-लाइन एक्सप्रेशन सक्षम करने के लिए ब्रांड्स के भीतर एक अभिव्यक्ति को संलग्न करना स्वीकार किया जाता है, लेकिन मैंने इसका बहुत कम उपयोग देखा है।

// single-line expression 
def sum(list: List[Int]): Int = if (!list.isEmpty) list reduceLeft (_ + _) else 0 

// multi-line expression 
val sum = (
    getItems 
    reduceLeft (_ + _) 
) 

समझ में, जेनरेटर और शर्तों को लंबवत रूप से गठबंधन रखने के लिए एक स्वीकार्य शैली प्रतीत होती है। yield के लिए, मैंने इसे for के साथ गठबंधन किया है और इंडेंट किया है।

// for-comprehensions 
val squares = 
    for (x <- numbers) 
    yield x * x 

// Curly brackets-style identation 
val cells = for { 
    x <- columns 
    y <- rows 
    if x != y 
} yield Cell(x, y) 

// Parameter-style identation 
val cells = for (x <- columns; 
       y <- rows; 
       if x != y) 
      yield Cell(x, y) 

यह कक्षा घोषणा के पैरामीटर को लंबवत रूप से संरेखित करने के लिए भी स्वीकार्य शैली है।

इंडेंटेशन की बात करते हुए, दो-स्थान स्वीकार्य सम्मेलन है।

घुंघराले ब्रेसिज़ घोषणा की एक ही पंक्ति पर शुरू होने की उम्मीद है, और लंबवत रूप से उस रेखा के साथ गठबंधन समाप्त हो जाएगा।

// procedures 
def complain { 
    println("Oh, no!") 
} 

कुछ लोगों को लगता:

// another example 
def factorial(n: Int): Int = { 
    def fact(n: Int, acc: Int): Int = n match { 
    case 0 => acc 
    case x => fact(x - 1, x * acc) 
    } 

    fact(n, 1) 
} 

प्रक्रियाओं के लिए - - कार्यों जिसका वापसी प्रकार Unit है, उम्मीद शैली विधि के प्रकार और बराबर के चिह्न बाहर छोड़ने के लिए होना चाहिए था यह शैली त्रुटि प्रवण है, हालांकि, एक मिस्ड बराबर चिह्न एक प्रक्रिया में Unit के अलावा कुछ और लौटने वाला फ़ंक्शन बदल देगा।

पहचानकर्ता ऊंट मामले में लिखे गए हैं (उदाहरण: identifiersHaveHumps), जैसे जावा में। फ़ील्ड, विधि पैरामीटर, स्थानीय चर और फ़ंक्शंस के नाम के लिए, लोअर केस लेटर से शुरू करें। कक्षाओं, लक्षणों और प्रकारों के लिए, ऊपरी केस अक्षर से शुरू करें।

जावा सम्मेलन से प्रस्थान निरंतर नाम हैं। स्कैला में, अभ्यास ऊपरी केस अक्षर से शुरू होने वाले मानक ऊंट मामले का उपयोग करना है। उदाहरण के लिए Pi और PI, एक्स ऑफसेट और X_OFFSET नहीं। यह नियम आमतौर पर किसी भी सिंगलटन के बाद होता है।

import scala.Math.Pi 

val pi = Pi // this identifier will be shadowed by the identifier in the function below 

def isPi(n: Double): Boolean = n match { 
    case Pi => println("I got a true Pi."); true 
    case pi => println("I got "+pi+" and bounded it to an identifier named pi."); false 
} 

पैकेज का नाम लिखा जाता है एक लोअर केस अक्षरों से शुरू होने: मामले से मेल खाता है के लिए रखना एक स्थिरांक और एकमात्र कि जिस तरह से प्रतिनिधित्व किया, एक व्यावहारिक परिणाम है। आयात विवरण में अंतर करते समय यह विशेष रूप से सहायक होता है कि पैकेज क्या होता है और क्या नहीं है। पिछले उदाहरण में, Math पैकेज नहीं है (यह एक सिंगलटन है), क्योंकि यह ऊपरी केस अक्षर से शुरू होता है।

अंडरलाइन वर्ण का उपयोग - _ - अनुशंसित नहीं है, क्योंकि उस चरित्र में स्कैला में कई विशेष अर्थ हैं। पहचानकर्ताओं के लिए ये नियम ओल्डस्की, स्पून & वेनेर्स द्वारा स्कैला में प्रोग्रामिंग के पेज 141 और 142 पर पाए जा सकते हैं।

अभी, मैं अन्य परिस्थितियों को याद नहीं कर सकता, लेकिन विशिष्ट बिंदुओं पर स्पष्टीकरण मांगने के लिए स्वतंत्र महसूस करता हूं। इनमें से कुछ नियमों को स्पष्ट रूप से बताया गया था, अन्य समुदाय की सर्वसम्मति से अधिक हैं। मैंने अपनी प्राथमिकताओं को छोड़ने की कोशिश की, लेकिन मैं असफल हो सकता था।

अधिक महत्वपूर्ण बात यह है कि शायद वास्तव में एक एकीकृत सम्मेलन का अधिक हिस्सा नहीं है। इसके लिए एक कारण यह हो सकता है कि स्कैला कई अलग-अलग पृष्ठभूमि से लोगों को आकर्षित कर रहा है, जैसे कार्यात्मक भाषा मावेन, जावा प्रोग्रामर और वेब 2.0 उत्साही।

+3

असल में, मुझे लगता है कि "बराबर छोड़ें" शैली * कम * त्रुटि प्रवण है क्योंकि यह स्पष्ट रूप से एनोटेटिंग यूनिट के लिए प्रभावी रूप से एक छोटा सा हाथ है। इरादा बहुत स्पष्ट है, और यह एक स्पष्ट एनोटेशन से कहीं अधिक संक्षिप्त है। यह ध्यान देने योग्य है कि * सभी * दुष्प्रभावों को कोष्ठक के साथ घोषित किया जाना चाहिए, विशेष रूप से arity-1 के साथ। पेंटिचेस-कम विधियां * केवल * शुद्ध कार्यों और तार्किक संपत्ति एक्सेसर्स के लिए हैं। –

+0

ठीक है, मैं जवाब सही कर दूंगा। वास्तव में, मैं इसे समुदाय बना दूंगा। हालांकि, सभी मामलों में पैरामीटर-कम विधियों और कार्यों * नहीं * कोष्ठक बनाने के बारे में कुछ चर्चा हुई थी। –

+4

वास्तव में, स्कैला पुस्तक में प्रोग्रामिंग अनुशंसा करता है कि यदि विधि में कोई तर्क नहीं है * और * कोई साइड इफेक्ट नहीं है (उदाहरण के लिए किसी ऑब्जेक्ट की स्थिति तक पहुंचने पर) आप किसी विधि के कंस्ट्रैसिस को छोड़ सकते हैं। इसलिए, 'println()' जैसे कॉल में अभी भी कंस्ट्रैसिस होना चाहिए, लेकिन 'queue.size' या' array.length' नहीं है (समान पहुंच सिद्धांत देखें - http://en.wikipedia.org/wiki/ Uniform_access_principle)। उत्तरार्द्ध उदाहरण जावा में 'queue.size() 'और' array.length' होगा, जो इस सिद्धांत का सम्मान नहीं करता है। –

2

यह एक बहुत ही महत्वपूर्ण सवाल है। आम तौर पर, स्कैला शैली को स्कैला समुदाय के अन्य सदस्यों के साथ लटककर, स्कैला स्रोत कोड इत्यादि को पढ़कर उठाया जाता है।यह नवागंतुकों के लिए भाषा में बहुत उपयोगी नहीं है, लेकिन यह इंगित करता है कि कुछ प्रकार के वास्तविक मानक मौजूद हैं (जैसा कि जनता के ज्ञान द्वारा चुना गया है)। मैं वर्तमान में स्कैला के लिए पूरी तरह से एहसास शैली मार्गदर्शिका पर काम कर रहा हूं, जो समुदाय-चुने हुए सम्मेलनों और सर्वोत्तम प्रथाओं को दस्तावेज करता है। हालांकि, ए) यह अभी तक समाप्त नहीं हुआ है, और बी) मुझे अभी तक यकीन नहीं है कि मुझे इसे प्रकाशित करने की अनुमति होगी (मैं इसे काम के लिए लिख रहा हूं)।

अपने दूसरे प्रश्न (प्रकार) का उत्तर देने के लिए: सामान्य रूप से, प्रत्येक कक्षा/विशेषता/ऑब्जेक्ट को जावा नामकरण सम्मेलनों के अनुसार नामित अपनी फ़ाइल प्राप्त करनी चाहिए। हालांकि, ऐसी परिस्थितियों में जहां आपके पास बहुत सी कक्षाएं हैं जो एक आम अवधारणा साझा करती हैं, कभी-कभी यह सभी को एक ही फ़ाइल में रखने के लिए सबसे आसान (अल्पकालिक और लंबी अवधि में) दोनों होती है। जब आप ऐसा करते हैं, तो फ़ाइल का नाम लोअर-केस अक्षर (अभी भी कैमेलकेस) से शुरू होना चाहिए और उस साझा अवधारणा के वर्णनात्मक होना चाहिए।

+0

कृपया, मेरे उत्तर में कोई त्रुटि इंगित करें। मैं गलत शैली की जानकारी का प्रचार नहीं करना चाहता - हम उतने ही फैल गए हैं जितना कि यह है। –

2

मुझे वास्तव में सामान्य शैली की परवाह नहीं है कि कई स्कैला कोडर उपयोग करते हैं, इसलिए मैं उसी मानक को लागू करता हूं जो मैं सी #, जावा या विशेष रूप से जावास्क्रिप्ट में उपयोग करता हूं।

स्कैला बहुत अभिव्यक्तिपूर्ण हो सकता है, लेकिन एक अपरिचित प्रारूप का उपयोग करके आपके बाधा को प्रवेश में वृद्धि होगी। विशेष रूप से आंतरिक DSLs पर विचार करते हुए, जो संभवतः "मानक" नहीं हो सका।

तो, मैं आपसे कहता हूं कि जो कुछ भी आपके कोड को और आपकी टीम के लिए अधिक पठनीय बनाता है।

12

अब एक पूर्ण स्कैला शैली मार्गदर्शिका है जो proposed to the community है। यह अभी तक दूरस्थ रूप से आधिकारिक भी नहीं है, लेकिन यह समुदाय-स्वीकार्य सम्मेलनों का एकमात्र (मेरे ज्ञान के लिए) कोडिफिकेशन है।

+4

नवीनतम संस्करण यहां है: http://davetron5000.github.com/scala-style/ – robinst

+0

इस शैली मार्गदर्शिका में निर्णयों के पीछे वास्तव में और अधिक तर्क होना चाहिए। – sdkfasldf

+0

मुझे लगता है [ली हाओई के नए लेख] (http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html) एक चिल्लाओ के लायक हैं। – metasim

7

अब Scala Style Guide उपलब्ध है। यह 100% आधिकारिक नहीं है ("Community-driven documentation for Scala" साइट पर स्थित है) लेकिन स्कैला के लिए सबसे मानक शैली मार्गदर्शिका प्रतीत होती है।

संबंधित मुद्दे