ठोस बनाम स्थिर तरीके


11

यहाँ एक समस्या है जिसे मैं अक्सर चलाता हूं: एक वेब शॉप प्रोजेक्ट हो जिसमें प्रोडक्ट क्लास हो। मैं एक फीचर जोड़ना चाहता हूं जो उपयोगकर्ताओं को किसी उत्पाद के लिए समीक्षा पोस्ट करने की अनुमति देता है। इसलिए मेरे पास एक समीक्षा वर्ग है जो एक उत्पाद का संदर्भ देता है। अब मुझे एक ऐसी विधि की आवश्यकता है जो किसी उत्पाद की सभी समीक्षाओं को सूचीबद्ध करे। दो संभावनाएँ हैं:

(ए)

public class Product {
  ...
  public Collection<Review> getReviews() {...}
}

(बी)

public class Review {
  ...
  static public Collection<Review> forProduct( Product product ) {...}
}

कोड को देखने से, मैं चुनता हूं (ए): यह स्थिर नहीं है और इसे पैरामीटर की आवश्यकता नहीं है। हालांकि, मुझे लगता है कि (ए) एकल जिम्मेदारी सिद्धांत (एसआरपी) और ओपन-क्लोज्ड सिद्धांत (ओसीपी) का उल्लंघन करता है जबकि (बी) ऐसा नहीं करता है:

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

  • (OCP) मुझे इस सुविधा के साथ इसे विस्तारित करने के लिए उत्पाद वर्ग को बदलना होगा। मुझे लगता है कि यह सिद्धांत के 'क्लोज्ड फॉर चेंज' भाग का उल्लंघन करता है। इससे पहले कि मुझे समीक्षाओं को लागू करने के लिए ग्राहक का अनुरोध मिले, मैंने उत्पाद को समाप्त मान लिया, और इसे "बंद" कर दिया।

क्या अधिक महत्वपूर्ण है: ठोस सिद्धांतों का पालन करना, या एक सरल इंटरफ़ेस होना?

या मैं यहां कुछ गलत कर रहा हूं?

परिणाम

वाह, आपके सभी महान उत्तरों के लिए धन्यवाद! आधिकारिक उत्तर के रूप में इसे चुनना कठिन है।

मुझे उत्तर से मुख्य तर्क संक्षेप में प्रस्तुत करने चाहिए:

  • समर्थक (ए): OCP कानून नहीं है और कोड मामलों की पठनीयता भी है।
  • समर्थक (ए): इकाई संबंध नौगम्य होना चाहिए। दोनों वर्गों को इस संबंध के बारे में पता हो सकता है।
  • समर्थक (ए) + (बी): दोनों (और ए) में (बी) को सौंपते हैं ताकि उत्पाद को फिर से बदलने की संभावना कम हो।
  • समर्थक (सी): खोजक विधियों को तृतीय श्रेणी (सेवा) में रखें जहां यह स्थिर नहीं है।
  • गर्भनिरोधक (बी): परीक्षणों में नकल।

मेरे काम में कुछ अतिरिक्त चीजों ने योगदान दिया:

  • प्रो (बी): हमारा ओआरएम ढांचा स्वचालित रूप से (बी) के लिए कोड उत्पन्न कर सकता है।
  • समर्थक (ए): हमारे ओआरएम ढांचे के तकनीकी कारणों के लिए, कुछ मामलों में "बंद" इकाई को बदलना आवश्यक होगा, स्वतंत्र रूप से जहां खोजकर्ता जाता है। इसलिए मैं हमेशा एसओएलआईडी से नहीं रह पाऊंगा, वैसे भी।
  • गर्भनिरोधक (सी): बहुत अधिक उपद्रव ;-)

निष्कर्ष

मैं अपने वर्तमान प्रोजेक्ट के लिए प्रतिनिधिमंडल के साथ दोनों (ए) + (बी) का उपयोग कर रहा हूं। एक सेवा-उन्मुख वातावरण में, हालांकि, मैं (सी) के साथ जाऊंगा।


2
जब तक यह एक स्थिर चर नहीं है तब तक सब कुछ ठंडा है। स्थैतिक तरीकों का परीक्षण करने के लिए एक सरल, और ट्रेस करने के लिए सरल है।
कोडर

3
सिर्फ एक ProductReviews वर्ग क्यों नहीं है? फिर उत्पाद और समीक्षा एक समान रहें। या शायद मुझे गलतफहमी है।
ElGringoGrande

2
@ कोडर "स्टैटिक विधियां परीक्षण के लिए सरल हैं", वास्तव में? उन्हें अधिक मज़ाक में नहीं देखा जा सकता है: अधिक जानकारी के लिए googletesting.blogspot.com/2008/12/…
स्टुपरयूजर

1
@StuperUser: नकली करने के लिए कुछ भी नहीं है। Assert(5 = Math.Abs(-5));
कोडर

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

जवाबों:


7

क्या अधिक महत्वपूर्ण है: ठोस सिद्धांतों का पालन करना, या एक सरल इंटरफ़ेस होना?

सॉलिड विज़न-ए-विज़ SOLID

ये परस्पर अनन्य नहीं हैं। इंटरफ़ेस को आपके व्यवसाय मॉडल की प्रकृति को आदर्श रूप से व्यवसाय मॉडल की शर्तों में व्यक्त करना चाहिए। SOLID सिद्धांत ऑब्जेक्ट ओरिएंटेड कोड मेंटेनेंस को अधिकतम करने के लिए एक Koan है (और मेरा अर्थ है "व्यापक अर्थ में" स्थिरता ")। पूर्व आपके व्यवसाय मॉडल के उपयोग और हेरफेर का समर्थन करता है और बाद वाला कोड रखरखाव का अनुकूलन करता है।

खुला / बंद सिद्धांत

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

अंत में मैं ओसीपी को मौजूदा डिजाइन गुणवत्ता के एक संकेतक के रूप में देखता हूं। अगर मैं अपने आप को खुली कक्षाओं (या तरीकों) को अक्सर तोड़ता हुआ पाता हूं, और / या वास्तव में ऐसा करने के ठोस (हा, हा) कारणों के बिना तो यह मुझे बता सकता है कि मुझे कुछ बुरा डिज़ाइन मिला है (और / या मैं नहीं पता है कि OO कोड कैसे करें)।

इसे अपना सर्वश्रेष्ठ शॉट दें, हमारे पास डॉक्टरों की एक टीम है

यदि आपकी आवश्यकताओं का विश्लेषण आपको बताता है कि आपको दोनों दृष्टिकोणों से उत्पाद-समीक्षा संबंध को व्यक्त करने की आवश्यकता है, तो ऐसा करें।

इसलिए, वोल्फगैंग, आपके पास उन मौजूदा वर्गों को संशोधित करने का एक अच्छा कारण हो सकता है। नई आवश्यकताओं को देखते हुए, यदि रिव्यू अब किसी उत्पाद का एक मौलिक हिस्सा है, यदि उत्पाद के प्रत्येक विस्तार की समीक्षा की आवश्यकता है, यदि ऐसा करने से क्लाइंट कोड उचित रूप से स्पष्ट हो जाता है, तो इसे उत्पाद में एकीकृत करें।


1
+1 यह ध्यान देने के लिए कि OCP अच्छी गुणवत्ता का सूचक है, किसी भी कोड के लिए तेज़ नियम नहीं है। यदि आप पाते हैं कि ओसीपी का ठीक से पालन करना मुश्किल या असंभव है, तो यह एक संकेत है कि आपके मॉडल को अधिक लचीली पुन: उपयोग के लिए अनुमति देने के लिए फिर से तैयार करना होगा।
कोडेक्सअर्बनम

मैंने उत्पाद और समीक्षा का उदाहरण चुना है कि उत्पाद परियोजना की एक मुख्य इकाई है, जबकि समीक्षा मात्र ऐड-ऑन है। इसलिए उत्पाद पहले से मौजूद है, समाप्त हो गया है, और समीक्षा बाद में आती है और इसे मौजूदा कोड (इंकलाब उत्पाद) को खोले बिना पेश किया जाना चाहिए।
वोल्फगैंग

10

SOLID दिशानिर्देश हैं, इसलिए निर्णय लेने के बजाय निर्णय लेने को प्रभावित करते हैं।

स्थैतिक तरीकों का उपयोग करते समय एक बात का ध्यान रखना टेस्टिबिलिटी पर उनका प्रभाव है ।


परीक्षण में forProduct(Product product)कोई समस्या नहीं होगी।

किसी चीज का परीक्षण करना जो उस पर निर्भर करता है।

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

चलो एक विधि है जिसे CUT()कॉल कहा जाता हैforProduct()

अगर forProduct()है staticकि आप परीक्षण नहीं कर सकते CUT()एक परमाणु इकाई के रूप में और अपने परीक्षण के सभी कि परीक्षण इकाई तर्क एकीकरण परीक्षणों हो जाते हैं।

CUT के लिए एक परीक्षण में विफलता, CUT()या forProduct()(या इसके किसी भी आश्रित कोड की) समस्या के कारण हो सकती है जो इकाई परीक्षणों के निदान लाभों को हटा देती है।

अधिक विस्तृत जानकारी के लिए इस उत्कृष्ट ब्लॉग पोस्ट को देखें: http://googletesting.blogspot.com/2008/12/static-methods-are-death-to-testability.html


यह असफल परीक्षणों और अच्छी प्रथाओं और उन्हें घेरने वाले लाभों को छोड़ने के साथ हताशा का कारण बन सकता है।


1
यह बहुत अच्छी बात है। सामान्य तौर पर, हालांकि मेरे लिए नहीं। ;-) मैं इकाई परीक्षण लिखने के बारे में इतना सख्त नहीं हूं जो एक से अधिक वर्ग को कवर करता है। वे सभी डेटाबेस के लिए नीचे जाते हैं, यह मेरे लिए ठीक है। इसलिए मैं व्यावसायिक वस्तु का मजाक नहीं बनाऊंगा या यह खोजक नहीं होगा।
वोल्फगैंग

+1, परीक्षणों के लिए लाल झंडा लगाने के लिए धन्यवाद! मैं वुल्फगैंग के साथ सहमत हूं, आमतौर पर मैं बहुत सख्त नहीं हूं, लेकिन जब मुझे उस तरह के परीक्षणों की आवश्यकता होती है तो मुझे वास्तव में स्थैतिक तरीकों से नफरत होती है। आमतौर पर अगर कोई स्टैटिक मेथड अपने मापदंडों के साथ बहुत ज्यादा इंटरैक्ट करता है या किसी अन्य स्टैटिक मेथड के साथ इंटरैक्ट करता है तो मैं इसे एक इंस्टेंस मेथड बनाना पसंद करता हूं।
Adriano Repetti

क्या यह पूरी तरह से इस्तेमाल की जा रही भाषा पर निर्भर नहीं करता है? ओपी ने जावा उदाहरण का उपयोग किया, लेकिन कभी भी प्रश्न में भाषा का उल्लेख नहीं किया, न ही टैग में कोई निर्दिष्ट है।
इज़काता

1
@StuperUser If forProduct() is static you can't test CUT() as an atomic unit and all of your tests become integration tests that test unit logic.- मेरा मानना ​​है कि जावास्क्रिप्ट और पायथन दोनों स्थैतिक तरीकों को ओवरराइड / बाहर करने की अनुमति देते हैं। मैं 100% निश्चित नहीं हूँ, हालाँकि।
इजाकाता

1
@Izkata JS डायनामिक रूप से टाइप किया गया है, इसलिए ऐसा नहीं है static, आप इसे एक क्लोजर और सिंगलटन पैटर्न के साथ अनुकरण करते हैं। पायथन (विशेष रूप से stackoverflow.com/questions/893015/… ) पर पढ़ना , आपको विरासत और विस्तार करना होगा। ओवरराइडिंग मजाक नहीं है; लगता है कि आपके पास परमाणु इकाई के रूप में कोड के परीक्षण के लिए अभी भी सीम नहीं है।
स्टॉपरयूजर

4

यदि आपको लगता है कि उत्पाद उत्पाद की समीक्षा खोजने के लिए सही जगह है, तो आप हमेशा उत्पाद को इसके लिए काम करने के लिए एक सहायक वर्ग दे सकते हैं। (आप बता सकते हैं क्योंकि आपका व्यवसाय किसी उत्पाद के संदर्भ में समीक्षा के बारे में कभी बात नहीं करेगा)।

उदाहरण के लिए, मुझे कुछ ऐसा इंजेक्ट करने के लिए लुभाया जाएगा जिसने समीक्षा की भूमिका निभाई हो। मैं शायद इसे इंटरफ़ेस दूंगा IRetrieveReviews। आप इसे उत्पाद (डिपेंडेंसी इंजेक्शन) के कंस्ट्रक्टर में डाल सकते हैं। एक - आप को बदलने का तरीका समीक्षा प्राप्त किए गए हैं आप एक अलग सहयोगी इंजेक्शन लगाने के द्वारा आसानी से कर सकते हैं TwitterReviewRetrieverया एक AmazonReviewRetrieverया MultipleSourceReviewRetrieverआप की जरूरत है या जो कुछ भी।

अब दोनों के पास एक ही जिम्मेदारी है (उत्पाद से संबंधित सभी चीज़ों के लिए, और क्रमशः समीक्षा प्राप्त करना), और भविष्य में समीक्षाओं के संबंध में उत्पाद के व्यवहार को वास्तव में उत्पाद को बदले बिना संशोधित किया जा सकता है (आप इसे आगे बढ़ा सकते हैं। एक के रूप में ProductWithReviewsयदि आप वास्तव में) अपने ठोस सिद्धांतों के बारे में पंडिताऊ बनना चाहता था, लेकिन यह मेरे लिए अच्छा पर्याप्त होगा।


DAO पैटर्न की तरह लगता है जो सेवा / घटक उन्मुख सॉफ़्टवेयर में बहुत आम है। मुझे यह विचार पसंद है क्योंकि यह व्यक्त करता है कि वस्तुओं को पुनः प्राप्त करना इन वस्तुओं की जिम्मेदारी नहीं है। हालांकि, चूंकि मैं सेवा उन्मुख पर एक वस्तु उन्मुख तरीका पसंद करता हूं।
वोल्फगैंग

1
एक इंटरफ़ेस का उपयोग करना IRetrieveReviewsइसे सेवा-उन्मुख होने से रोकता है - यह निर्धारित नहीं करता है कि समीक्षाओं को क्या मिलता है, या कैसे, या कब। शायद यह इस तरह की चीजों के लिए बहुत सारी विधियों के साथ एक सेवा है। शायद यह एक ऐसा वर्ग है जो एक काम करता है। शायद यह एक रिपॉजिटरी है, या एक सर्वर से HTTP अनुरोध करता है। तुम्हें पता नहीं है। आपको नहीं पता होना चाहिए यही तो बात है।
लुनिवर

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

3

मैं एक ProductReview वर्ग होगा। आप कहते हैं कि समीक्षा वैसे भी नई है। इसका मतलब यह नहीं है कि यह कुछ भी हो सकता है। अभी भी इसे बदलने का केवल एक कारण होना चाहिए। यदि आप बदलते हैं कि आपको रिव्यू क्लास बदलने के लिए जो भी कारण मिलेंगे, उसके लिए आपको समीक्षा कैसे मिलेगी।

यह सही नहीं है।

आप स्थैतिक विधि की समीक्षा कक्षा में कर रहे हैं क्योंकि ... क्यों? नहीं है कि आप के साथ क्या संघर्ष कर रहे हैं? क्या यह पूरी समस्या नहीं है?

तब नहीं। एक वर्ग बनाओ कि पूरी जिम्मेदारी उत्पादों की समीक्षा को मिल रही है। फिर आप जो भी ProductReviewsByStartRating के लिए इसे उपवर्ग कर सकते हैं। या उत्पादों के एक वर्ग के लिए समीक्षा प्राप्त करने के लिए इसे उपवर्ग।


मैं इस बात से सहमत नहीं हूँ कि समीक्षा पर विधि SRP का उल्लंघन करेगी। उत्पाद पर, यह समीक्षा पर नहीं होगा। मेरी समस्या यह थी कि यह स्थिर है। अगर मैंने विधि को कुछ तीसरी कक्षा में स्थानांतरित कर दिया, तो यह अभी भी स्थिर होगा और उत्पाद पैरामीटर होगा।
वोल्फगैंग

तो आप कह रहे हैं कि समीक्षा वर्ग के लिए एकमात्र जिम्मेदारी, इसे बदलने का एकमात्र कारण है, यदि forProduct स्थैतिक विधि को बदलना आवश्यक है? समीक्षा वर्ग में कोई अन्य कार्यक्षमता नहीं है?
ElGringoGrande

समीक्षा पर बहुत सारा सामान है। लेकिन मुझे लगता है कि एक उत्पाद (उत्पाद) अच्छी तरह से इसके लिए उपयुक्त होगा। समीक्षा ढूंढना विशेषताओं और संरचना की समीक्षा पर बहुत निर्भर करता है (जो विशिष्ट पहचानकर्ता हैं, जो विशेषताओं को बदलते हैं?)। उत्पाद, हालांकि नहीं जानता है और समीक्षा के बारे में पता नहीं होना चाहिए।
वोल्फगैंग

3

मैं 'प्रोडक्ट के लिए रिव्यू फॉर प्रोडक्ट' फंक्शनल को Productन तो क्लास में रखूंगा और न ही Reviewक्लास में ...

आपके पास एक जगह है जहाँ आप अपने उत्पादों को पुनः प्राप्त करते हैं, है ना? कुछ के साथ GetProductById(int productId)और शायद GetProductsByCategory(int categoryId)और इसी तरह।

इसी तरह, आपके पास अपनी समीक्षा को पुनः प्राप्त करने के लिए एक जगह होनी चाहिए, एक GetReviewbyId(int reviewId)और शायद एक के साथ GetReviewsForProduct(int productId)

जब मैं किसी उत्पाद के लिए समीक्षा के तरीके को बदलना चाहता हूं, तो मुझे उत्पाद वर्ग को बदलना होगा।

यदि आप अपनी डेटा एक्सेस को अपनी डोमेन कक्षाओं से अलग करते हैं, तो आपको समीक्षा को एकत्र करने के तरीके को बदलने पर डोमेन वर्ग को बदलने की आवश्यकता नहीं होगी ।


यह है कि मैं इसे कैसे संभालूंगा, और इस जवाब की कमी से चिंतित हूं (और इस बारे में चिंतित हूं कि क्या मेरे खुद के विचार उचित हैं)। स्पष्ट रूप से न तो किसी रिपोर्ट का प्रतिनिधित्व करने वाला वर्ग और न ही किसी उत्पाद का प्रतिनिधित्व वास्तव में दूसरे को पुनः प्राप्त करने के लिए जिम्मेदार होना चाहिए। किसी तरह की डेटा प्रदान करने वाली सेवाएं इसे संभाल रही होंगी।
कोडेक्सअर्बनम

@CodexArcanum खैर, आप अकेले नहीं हैं। :-)
एरिक किंग

2

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

इस मामले में मैं समाधान (बी) को प्राथमिकता दूंगा क्योंकि मेरे लिए शुरुआती बिंदु उत्पाद है, समीक्षा नहीं है लेकिन कल्पना कीजिए कि आप समीक्षाओं को प्रबंधित करने के लिए एक सॉफ्टवेयर लिख रहे हैं। उस मामले में केंद्र की समीक्षा है तो समाधान (ए) बेहतर हो सकता है।

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


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

मुझे लगता है कि कक्षाओं के एक छोटे से सेट के लिए भी बीओटीएच तरीकों (ए) और (बी) प्रदान करना अच्छा हो सकता है। बहुत बार यूआई इस तर्क को लिखने के क्षण में अच्छी तरह से ज्ञात नहीं है।
Adriano Repetti

1

आपका उत्पाद सिर्फ आपके स्थिर समीक्षा पद्धति को सौंप सकता है, इस स्थिति में आप प्राकृतिक स्थान (Product.getReviews) में एक सुविधाजनक इंटरफ़ेस प्रदान कर रहे हैं, लेकिन आपके कार्यान्वयन का विवरण Review.getForProduct में है।

ठोस दिशानिर्देश हैं और एक सरल, समझदार इंटरफ़ेस में परिणाम होना चाहिए। वैकल्पिक रूप से, आप SOLID को सरल, समझदार इंटरफेस से प्राप्त कर सकते हैं। यह कोड के भीतर निर्भरता प्रबंधन के बारे में है। लक्ष्य निर्भरता को कम करना है जो घर्षण पैदा करता है और अपरिहार्य परिवर्तन के लिए बाधाएं पैदा करता है।


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

OCP की कुंजी यह है कि आप अपने कोड को बदले बिना कार्यान्वयन को प्रतिस्थापित कर सकते हैं। व्यवहार में यह Liskov प्रतिस्थापन के साथ निकटता से जुड़ा हुआ है। एक कार्यान्वयन दूसरे के लिए स्थानापन्न होना चाहिए। आपके पास अलग-अलग वर्गों जैसे कि IGetReviews.getReviews और getReviewsForProducts को लागू करने के लिए डेटाबेसरीव्यू और साबुन साक्षात्कार हो सकते हैं। फिर आपका सिस्टम एक्सटेंशन के लिए ओपन है (संशोधन की समीक्षा कैसे की जाती है) और संशोधन के लिए बंद (IGetReviews पर निर्भरताएं टूट जाती हैं)। मुझे निर्भरता प्रबंधन से यही मतलब है। आपके मामले में, आपको अपना व्यवहार बदलने के लिए अपना कोड संशोधित करना होगा।
पीएफ

क्या यह निर्भरता उलटा सिद्धांत (DIP) नहीं है जिसका आप वर्णन कर रहे हैं?
वोल्फगैंग

वे संबंधित सिद्धांत हैं। आपका प्रतिस्थापन बिंदु डीआईपी द्वारा हासिल किया गया है।
pfries

1

मैं अन्य उत्तरों की तुलना में इस पर थोड़ा अलग है। मुझे लगता है कि Productऔर Reviewमूल रूप से डेटा ट्रांसफर ऑब्जेक्ट्स (डीटीओ) हैं। अपने कोड में मैं अपने DTO / Entities बनाने के लिए व्यवहार करने से बचने की कोशिश करता हूं। वे मेरे मॉडल की वर्तमान स्थिति को संग्रहीत करने के लिए सिर्फ एक अच्छा एपीआई हैं।

जब आप OO और SOLID के बारे में बात करते हैं तो आप आम तौर पर एक "ऑब्जेक्ट" के बारे में बात करते हैं जो राज्य (आवश्यक रूप से) का प्रतिनिधित्व नहीं करता है, लेकिन इसके बजाय किसी तरह की सेवा का प्रतिनिधित्व करता है जो आपके लिए सवालों के जवाब देता है, या जिससे आप अपने कुछ काम सौंप सकते हैं। । उदाहरण के लिए:

interface IProductRepository
{
    void SaveNewProduct(IProduct product);
    IProduct GetProductById(ProductId productId);
    bool TryGetProductByName(string name, out IProduct product);
}

interface IProduct
{
    ProductId Id { get; }
    string Name { get; }
}

class ExistingProduct : IProduct
{
    public ProductId Id { get; private set; }
    public string Name { get; private set; }
}

फिर आपका वास्तविक विधि के लिए ProductRepositoryवापस आ जाएगा , आदि।ExistingProductGetProductByProductId

अब आप एकल जिम्मेदारी सिद्धांत का पालन कर रहे हैं (जो कुछ भी विरासत में मिला है, IProductवह केवल राज्य के लिए है, और जो कुछ भी विरासत में मिला है IProductRepositoryवह आपके डेटा मॉडल को जारी रखने और पुन: व्यवस्थित करने के तरीके को जानने के लिए पुन: प्रयोज्य है)।

यदि आप अपना डेटाबेस स्कीमा बदलते हैं, तो आप अपने डीटीओ आदि को बदले बिना अपने रिपॉजिटरी कार्यान्वयन को बदल सकते हैं।

इसलिए, संक्षेप में, मुझे लगता है कि मैं आपके विकल्पों में से कोई भी नहीं चुनूंगा। :)


0

स्थैतिक तरीकों का परीक्षण करना कठिन हो सकता है, लेकिन इसका मतलब यह नहीं है कि आप उनका उपयोग नहीं कर सकते हैं - आपको बस उन्हें सेट करने की आवश्यकता है ताकि आपको उन्हें परीक्षण करने की आवश्यकता न हो।

दोनों Product.GetReviews और Review.ForProduct एक लाइन विधियों को बनाएं जो कुछ इस तरह हैं

new ReviewService().GetReviews(productID);

ReviewService में सभी अधिक जटिल कोड होते हैं और इसमें एक इंटरफ़ेस होता है जो परीक्षण क्षमता के लिए डिज़ाइन किया गया है, लेकिन उपयोगकर्ता के सीधे संपर्क में नहीं आता है।

यदि आपके पास 100% कवरेज होना चाहिए, तो अपने एकीकरण परीक्षणों को उत्पाद / समीक्षा वर्ग विधियों को कॉल करें।

यदि आप क्लास डिज़ाइन के बजाय सार्वजनिक एपीआई डिज़ाइन के बारे में सोचते हैं तो यह मदद कर सकता है - इस संदर्भ में लॉजिकल ग्रुपिंग के साथ एक सरल इंटरफ़ेस वह सब कुछ मायने रखता है - वास्तविक कोड संरचना केवल डेवलपर्स के लिए मायने रखती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.