कैसे व्यापार वस्तु वर्ग डिजाइन के इस "पूरी तरह से सार्वजनिक" मानसिकता के खिलाफ बहस करने के लिए


9

हम अपनी व्यावसायिक वस्तुओं की बहुत सी इकाई परीक्षण और पुन: प्रसंस्करण कर रहे हैं, और मुझे अन्य साथियों की तुलना में कक्षा के डिजाइन पर बहुत अलग राय है।

एक उदाहरण वर्ग जिसका मैं प्रशंसक नहीं हूं:

public class Foo
{
    private string field1;
    private string field2;
    private string field3;
    private string field4;
    private string field5;

    public Foo() { }

    public Foo(string in1, string in2)
    {
        field1 = in1;
        field2 = in2;
    }

    public Foo(string in1, string in2, string in3, string in4)
    {
        field1 = in1;
        field2 = in2;
        field3 = in3;
    }

    public Prop1
    { get { return field1; } }
    { set { field1 = value; } }

    public Prop2
    { get { return field2; } }
    { set { field2 = value; } }

    public Prop3
    { get { return field3; } }
    { set { field3 = value; } }

    public Prop4
    { get { return field4; } }
    { set { field4 = value; } }

    public Prop5
    { get { return field5; } }
    { set { field5 = value; } }

}

"वास्तविक" वर्ग में, वे सभी स्ट्रिंग नहीं हैं, लेकिन कुछ मामलों में हमारे पास पूरी तरह से सार्वजनिक संपत्तियों के लिए 30 बैकिंग फ़ील्ड हैं।

मैं इस वर्ग से नफरत करता हूं , और मुझे नहीं पता कि मैं सिर्फ चुगली कर रहा हूं। नोट की कुछ बातें:

  • गुणों में कोई तर्क नहीं के साथ निजी समर्थन क्षेत्र, अनावश्यक लगता है और वर्ग को दोष देता है
  • मल्टीपल कंस्ट्रक्टर (कुछ हद तक ठीक है) लेकिन के साथ मिलकर
  • एक सार्वजनिक सेटर होने के सभी गुणों, मैं एक प्रशंसक नहीं हूँ।
  • खाली कंस्ट्रक्टर के कारण संभावित रूप से कोई भी गुण निर्दिष्ट नहीं किया जाएगा, यदि कोई कॉलर अनजान है, तो आप व्यवहार के लिए परीक्षण करने के लिए संभावित रूप से कुछ बहुत ही अवांछित और कठोर हो सकते हैं।
  • यह बहुत सारे गुण है! (30 मामले में)

मुझे वास्तव में यह जानना बहुत मुश्किल है किFoo किसी भी समय वस्तु किस स्थिति में है, एक कार्यान्वयनकर्ता के रूप में। तर्क दिया गया था "हमारे पास Prop5ऑब्जेक्ट निर्माण के समय सेट करने के लिए आवश्यक जानकारी नहीं हो सकती । ठीक है, मुझे लगता है कि मैं इसे समझ सकता हूं, लेकिन अगर मामला केवल Prop5सेटर को सार्वजनिक करता है, तो हमेशा एक क्लास में 30 संपत्तियों तक नहीं।

क्या मैं सिर्फ क्लास लेने के लिए नाइट-पिकी और / या पागल हो रहा हूं जो "आसान लिखने के लिए" (सब कुछ सार्वजनिक) होने के विपरीत "उपयोग करने में आसान" है? उपरोक्त जैसी कक्षाएं मेरे लिए चिल्लाती हैं, मुझे नहीं पता कि यह कैसे उपयोग किया जा रहा है, इसलिए मैं सिर्फ मामले में सब कुछ सार्वजनिक करने जा रहा हूं ।

अगर मैं बहुत अयोग्य नहीं हूं, तो इस प्रकार की सोच का मुकाबला करने के लिए अच्छे तर्क क्या हैं? मैं तर्कपूर्ण कलाकृतियों में बहुत अच्छा नहीं हूं, क्योंकि मैं अपनी बात को पूरी तरह से जानने की कोशिश कर रहा हूं (जानबूझकर नहीं)।



3
एक वस्तु हमेशा एक मान्य स्थिति में होनी चाहिए; अर्थात् , आपको आंशिक रूप से तात्कालिक वस्तुएं रखने की आवश्यकता नहीं होनी चाहिए । कुछ जानकारी किसी वस्तु की मुख्य स्थिति का हिस्सा नहीं होती है, जबकि अन्य जानकारी होती है (जैसे एक टेबल में पैर होने चाहिए लेकिन कपड़ा वैकल्पिक है); वैकल्पिक जानकारी तात्कालिकता के बाद प्रदान की जा सकती है, तात्कालिकता में मुख्य जानकारी प्रदान की जानी चाहिए। यदि कुछ जानकारी कोर है, लेकिन तात्कालिकता में नहीं जाना जाता है, तो मैं कहूंगा कि कक्षाओं को फिर से तैयार करने की आवश्यकता है। वर्ग के संदर्भ को जाने बिना अधिक कहना मुश्किल है।
मार्विन

1
यह कहते हुए कि "हमारे पास ऑब्जेक्ट निर्माण के समय Prop5 सेट करने के लिए आवश्यक जानकारी नहीं हो सकती है" मुझे पूछता है "क्या आप कह रहे हैं कि कुछ समय होगा कि आपके पास निर्माण के समय और अन्य समय पर वह जानकारी होगी जब आप नहीं करेंगे वह जानकारी है? " यह मुझे आश्चर्यचकित करता है कि क्या वास्तव में दो अलग-अलग चीजें हैं जो यह एक वर्ग प्रतिनिधित्व करने की कोशिश कर रहा है, या शायद इस वर्ग को छोटी कक्षाओं में तोड़ दिया जाना चाहिए। लेकिन अगर यह "बस के मामले में" किया गया है तो यह भी बुरा है, आईएमओ; मुझे लगता है कि वस्तुओं के निर्माण / आबादी के लिए एक स्पष्ट डिजाइन नहीं है।
डॉ। विली का अपरेंटिस

3
गुणों में कोई तर्क नहीं वाले निजी समर्थन वाले क्षेत्रों के लिए, क्या कोई कारण है कि आप ऑटो गुणों का उपयोग नहीं कर रहे हैं ?
कार्सन 63000

2
@ ऑटो-गुणों की संपूर्ण बात यह है कि यदि आपको भविष्य में वहां वास्तविक तर्क की आवश्यकता है, तो आप इसे ऑटो getया set:-) के स्थान पर जोड़ सकते हैं
Carson63000

जवाबों:


10

पूरी तरह से सार्वजनिक वर्गों के पास कुछ स्थितियों के साथ-साथ अन्य चरम के लिए एक औचित्य है, केवल एक सार्वजनिक विधि के साथ कक्षाएं (और शायद बहुत सारे निजी तरीके)। और कुछ सार्वजनिक, कुछ निजी तरीकों के साथ कक्षाएं भी।

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

कब किस तरह का डिज़ाइन पसंद करना है, इस बारे में पूरी किताबें लिखी गई हैं, इसलिए मैं इसके बारे में यहाँ कोई नियम नहीं बताने जा रहा हूँ, इस खंड में जगह पर्याप्त नहीं होगी। हालांकि, यदि आपके पास एक अमूर्त के लिए एक वास्तविक दुनिया उदाहरण है जिसे आप एक वर्ग के साथ मॉडल करना पसंद करते हैं, तो मुझे यकीन है कि यहां का समुदाय आपको डिजाइन को बेहतर बनाने में खुशी से मदद करेगा।

अपने अन्य बिंदुओं को संबोधित करने के लिए:

  • "गुणों में कोई तर्क नहीं के साथ निजी बैकिंग फ़ील्ड": हाँ, आप सही हैं, तुच्छ पाने वालों के लिए और बसने वाला यह केवल अप्राकृतिक "शोर" है। इस तरह के "ब्लोट" से बचने के लिए, C # में प्रॉपर्टी पाने / सेट करने के तरीकों के लिए एक शॉर्ट-कट सिंटैक्स है:

इसलिए इसके बजाय

   private string field1;
   public string Prop1
   { get { return field1; } }
   { set { field1 = value; } }

लिखो

   public string Prop1 { get;set;}

या

   public string Prop1 { get;private set;}
  • "मल्टीपल कंस्ट्रक्टर": यह अपने आप में कोई समस्या नहीं है। जब कोई अनावश्यक कोड डुप्लीकेशन होता है, तो यह एक समस्या हो जाती है, जैसे कि आपके उदाहरण में दिखाया गया है, या कॉलिंग पदानुक्रम को दोषी माना गया है। सामान्य भागों को एक अलग कार्य में बदलकर, और एक यूनिडायरेक्शनल तरीके से निर्माण श्रृंखला को व्यवस्थित करके इसे आसानी से हल किया जा सकता है।

  • "संभावित रूप से किसी भी गुण को खाली निर्माता के कारण एक मान नहीं दिया जाएगा": C # में, प्रत्येक डेटाटाइप में स्पष्ट रूप से डिफ़ॉल्ट मान होता है। यदि गुणों को किसी निर्माता में स्पष्ट रूप से प्रारंभ नहीं किया गया है, तो उन्हें यह डिफ़ॉल्ट मान असाइन किया गया है। यदि यह जानबूझकर उपयोग किया जाता है , तो यह पूरी तरह से ठीक है - इसलिए एक खाली निर्माता ठीक हो सकता है यदि लेखक जानता है कि वह क्या कर रहा है।

  • "यह बहुत अधिक गुण हैं! (30 मामले में)": हाँ, अगर आप ग्रीनफ़ील्ड तरीके से इस तरह की क्लास डिजाइन करने के लिए स्वतंत्र हैं, तो 30 बहुत अधिक हैं, मैं सहमत हूं। हालाँकि, हममें से सभी के पास यह लक्जरी नहीं है (क्या आपने नीचे टिप्पणी में नहीं लिखा है कि यह एक विरासत प्रणाली है?)। कभी-कभी आपको किसी मौजूदा डेटाबेस, या फ़ाइल, या आपके सिस्टम के लिए किसी तीसरे पक्ष के एपीआई से डेटा रिकॉर्ड करना पड़ता है। तो इन मामलों के लिए, 30 विशेषताएँ कुछ ऐसी हो सकती हैं जिनके साथ रहना है।


धन्यवाद, हाँ, मुझे पता है कि POCO / POJOs का अपना स्थान है, और मेरा उदाहरण काफी सार है। मुझे नहीं लगता कि मैं एक उपन्यास में जाए बिना अधिक विशिष्ट हो सकता था।
Kritner

@ किटनर: मेरा संपादन देखें
डॉक्टर ब्राउन

हाँ आम तौर पर जब मैं एक नया वर्ग बनाता हूं तो मैं ऑटो प्रॉपर्टी रूट पर जाता हूं। निजी समर्थन क्षेत्र "सिर्फ इसलिए" (मेरे दिमाग में) अनावश्यक होने और यहां तक ​​कि मुद्दों का कारण बनता है। जब आपके पास एक वर्ग और 100+ वर्गों के लिए ~ 30 गुण हैं, तो यह कहना दूर की बात नहीं है कि कुछ गुण स्थापित करने या गलत बैकिंग फ़ील्ड से प्राप्त करने जा रहे हैं ... मैं वास्तव में हमारे रिफैक्टरिंग में कई बार इसका सामना कर चुका हूं। :)
क्रिटनर

धन्यवाद, स्ट्रिंग के लिए डिफ़ॉल्ट मान nullक्या यह नहीं है? इसलिए यदि कोई ऐसा गुण है जो वास्तव में एक में उपयोग किया जाता है .ToUpper(), लेकिन इसके लिए कोई मूल्य निर्धारित नहीं किया जाता है, तो यह रनटाइम अपवाद को फेंक देगा। यह एक और अच्छा उदाहरण क्यों है आवश्यक वर्ग के लिए डेटा चाहिए है वस्तु निर्माण के दौरान स्थापित किया जाना। न केवल उपयोगकर्ता के लिए इसे छोड़ दें। धन्यवाद
Kritner

बहुत सारे परेशान गुणों के अलावा, इस वर्ग के साथ मुख्य समस्या यह है कि इसमें शून्य तर्क (ZRP) है और यह एक एनीमिक मॉडल के लिए एक प्रकार का शब्द है। इसकी आवश्यकता के बिना, जिसे डीटीओ जैसे शब्दों में व्यक्त किया जा सकता है, यह एक खराब डिज़ाइन है।
user949300

2
  1. यह कहकर कि "निजी बैकिंग फ़ील्ड्स जिसमें गुणों में कोई तर्क नहीं है, अनावश्यक लगता है और वर्ग को दोष देता है" आपके पास पहले से ही एक सभ्य तर्क है।

  2. ऐसा लगता नहीं है कि कई निर्माता यहां मुद्दा हैं।

  3. सभी संपत्तियों को सार्वजनिक करने के रूप में ... हो सकता है कि इस तरह से सोचें, यदि आप कभी भी थ्रेड के बीच इन सभी गुणों की पहुंच को सिंक्रनाइज़ करना चाहते थे, तो आपके लिए कठिन समय होगा क्योंकि आपको हर जगह सिंक्रनाइज़ेशन कोड लिखना पड़ सकता है। उपयोग किया गया। हालाँकि, यदि सभी संपत्तियों को गेटर्स / सेटर्स द्वारा संलग्न किया गया था, तो आप आसानी से कक्षा में सिंक्रनाइज़ेशन का निर्माण कर सकते थे।

  4. मुझे लगता है कि जब आप "व्यवहार का परीक्षण करने के लिए कठिन" कहते हैं तो तर्क अपने लिए बोलता है। आपके परीक्षण को यह जांचना पड़ सकता है कि क्या यह अशक्त या ऐसा कुछ नहीं है (हर एक जगह संपत्ति का उपयोग किया जाता है)। मैं वास्तव में नहीं जानता क्योंकि मुझे नहीं पता कि आपका परीक्षण / आवेदन कैसा दिखता है।

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


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

एह। यदि कक्षा अपरिवर्तनीय थी, तो कक्षा के अंदर किसी भी सिंक्रनाइज़ेशन कोड को लिखने का कोई कारण नहीं होगा।
रबरडुक

@RubberDuck क्या यह वर्ग अपरिवर्तनीय है? क्या मतलब?
स्नूप

3
यह निश्चित रूप से @StevieV अपरिवर्तनीय नहीं है । प्रॉपर्टी सेटलर्स के साथ कुछ भी क्लास म्यूट है।
रबरडॉक

1
@ किटनर प्राथमिक कुंजी के रूप में गुणों का उपयोग कैसे किया जाता है? संभवतः इसके लिए कुछ तर्क (अशक्त जांच) या नियमों (जैसे NAME को AGE से प्राथमिकता लेना आवश्यक है) की आवश्यकता होती है। OOP के अनुसार, यह कोड इस वर्ग का है। क्या आप इसे एक तर्क के रूप में इस्तेमाल कर सकते हैं?
user949300 16

2

जैसा कि आपने मुझे बताया, Fooएक व्यावसायिक वस्तु है। यह आपके डोमेन के अनुसार तरीकों में कुछ व्यवहार को एनकैप्सुलेट करना चाहिए और इसका डेटा यथासंभव एन्कैप्सुलेटेड रहना चाहिए।

आपके द्वारा दिखाए गए उदाहरण में, Fooएक डीटीओ की तरह दिखता है और सभी ओओपी सिद्धांतों के खिलाफ जाता है (देखें एनीमिक डोमेन मॉडल )!

सुधार के रूप में मैं सुझाव दूंगा:

  • इस वर्ग को यथासंभव अपरिवर्तनीय बनाएं । जैसा कि आपने कहा, आप कुछ इकाई परीक्षण करना चाहते हैं। इकाई परीक्षण के लिए एक अनिवार्य क्षमता नियतात्मकता है , और नियतावाद को अपरिवर्तनीयता के माध्यम से प्राप्त किया जा सकता है क्योंकि यह साइड-इफेक्ट्स की समस्याओं को हल करता है।
  • इस देव वर्ग को कई वर्गों में विभाजित करें जो केवल 1 कार्य करते हैं ( SRP देखें )। यूनिट वास्तव में एक PITA में एक 30 विशेषताओं वर्ग का परीक्षण करता है ।
  • केवल 1 मुख्य कंस्ट्रक्टर और दूसरों को मुख्य कंस्ट्रक्टर कहकर निर्माता अतिरेक निकालें ।
  • अनावश्यक गेटर्स निकालें, मुझे गंभीरता से संदेह है कि सभी गेटर्स वास्तव में उपयोगी हैं।
  • व्यावसायिक वर्गों में व्यावसायिक तर्क वापस लाओ, यह वह जगह है जहाँ यह है!

यह इन टिप्पणियों के साथ एक संभावित रिफलेक्टेड क्लास हो सकता है:

public sealed class Foo
{
    private readonly string field1;
    private readonly string field2;
    private readonly string field3;
    private readonly string field4;

    public Foo() : this("default1", "default2")
    { }

    public Foo(string in1, string in2) : this(in1, in2, "default3", "default4")
    { }

    public Foo(string in1, string in2, string in3, string in4)
    {
        field1 = in1;
        field2 = in2;
        field3 = in3;
        field4 = in4;
    }

    //Methods with business logic

    //Really needed ?
    public Prop1
    { get; }

    //Really needed ?
    public Prop2
    { get; }

    //Really needed ?
    public Prop3
    { get; }

    //Really needed ?
    public Prop4
    { get; }

    //Really needed ?
    public Prop5
    { get; }
}

2

कैसे व्यापार वस्तु वर्ग डिजाइन के इस "पूरी तरह से सार्वजनिक" मानसिकता के खिलाफ बहस करने के लिए

  • "क्लाइंट क्लास (तों) में बिखरे हुए कई तरीके 'मात्र डीटीओ ड्यूटी' से अधिक हैं। वे एक साथ हैं।"
  • "यह एक 'डीटीओ' हो सकता है, लेकिन इसकी व्यावसायिक पहचान है - हमें इक्वाल्स को ओवरराइड करने की आवश्यकता है।"
  • "हमें इन्हें क्रमबद्ध करने की आवश्यकता है - हमें अमल में लाने की आवश्यकता है"
  • "हम इन गुणों में से कई को एक साथ जोड़ रहे हैं। चलो ToString को ओवरराइड करते हैं ताकि हर ग्राहक को यह कोड लिखना न पड़े।"
  • "हमारे पास इस वर्ग के लिए एक ही काम करने वाले कई ग्राहक हैं। हमें कोड की जरूरत है।"
  • "ग्राहक इन चीजों के संग्रह में हेरफेर कर रहा है। यह स्पष्ट है कि यह एक कस्टम संग्रह वर्ग होना चाहिए; और पहले के कई बिंदु उस कस्टम संग्रह को वर्तमान की तुलना में अधिक कार्यात्मक बनाएंगे।"
  • "सभी थकाऊ, उजागर, स्ट्रिंग हेरफेर को देखें! व्यावसायिक-प्रासंगिक तरीकों में इनकैप्सुलेट करना हमारी कोडिंग उत्पादकता को बढ़ाएगा।"
  • "इन विधियों को कक्षा में एक साथ खींचने से उन्हें परीक्षण योग्य बनाया जा सकेगा क्योंकि हमें अधिक जटिल ग्राहक वर्ग के साथ व्यवहार नहीं करना है।"
  • "हम अब उन रिफैक्ट किए गए तरीकों का परीक्षण कर सकते हैं। जैसा कि x, y, z क्लाइंट के परीक्षण योग्य नहीं है।

  • उपरोक्त तर्क के किसी भी हद तक, कुल मिलाकर किया जा सकता है:

    • कार्यक्षमता को फिर से प्रयोग करने योग्य हो जाता है।
    • यह DRY है
    • यह ग्राहकों से decoupled है।
    • वर्ग के खिलाफ कोडिंग तेज और कम त्रुटि प्रवण है।
  • "एक अच्छी तरह से किया गया वर्ग राज्य को छुपाता है और कार्यक्षमता को उजागर करता है। यह ओओ कक्षाओं को डिजाइन करने के लिए प्रारंभिक प्रस्ताव है।"
  • "अंतिम परिणाम व्यापार डोमेन को व्यक्त करने का बेहतर काम करता है; अलग-अलग संस्थाएँ और उनकी स्पष्ट बातचीत।"
  • "यह ओवरहेड की कार्यक्षमता (अर्थात स्पष्ट कार्यात्मक आवश्यकताएं नहीं है, लेकिन यह किया जाना चाहिए) स्पष्ट रूप से बाहर खड़ा है और एकल जिम्मेदारी सिद्धांत का पालन करता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.