व्यावसायिक वस्तुएं - कंटेनर या कार्यात्मक?


19

यह एक ऐसा सवाल है जो मैंने SO पर कुछ समय पहले पूछा था, लेकिन यहां बेहतर चर्चा हो सकती है ...

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

उदाहरण - एक ग्राहक वस्तु लें, इसमें संभवतः कुछ सामान्य गुण (नाम, आईडी, आदि) शामिल हैं, क्या उस ग्राहक वस्तु में फ़ंक्शन (सहेजें, कैल्क, आदि) भी शामिल होना चाहिए?

रीज़निंग की एक पंक्ति ऑब्जेक्ट को कार्यक्षमता (एकल जिम्मेदारी प्रिंसिपल) से अलग करती है और कार्यक्षमता को एक व्यापार तर्क परत या ऑब्जेक्ट में डालती है।

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

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

जो अधिक समझ में आता है और क्यों ??


1
क्या आप हमें अपनी परियोजना के बारे में अधिक बता सकते हैं? आपकी परियोजना की प्रकृति निर्धारित करेगी कि कौन सा समाधान बेहतर है।

जवाबों:


5

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

इसके साथ ही, हालांकि, मुझे लगता है कि आपके द्वारा उपयोग किया गया उदाहरण एक खराब है, और तर्क का एक कारण है। यदि आप दृढ़ता के बारे में बात कर रहे हैं, तो ग्राहक आम तौर पर खुद को 'नहीं बचाते' हैं; आप जो कुछ भी दृढ़ता के लिए उपयोग कर रहे हैं। यह समझ में आता है कि किसी भी तरह की दृढ़ता दृढ़ता परत / विभाजन से संबंधित होनी चाहिए। यह आम तौर पर रिपॉजिटरी पैटर्न के पीछे की सोच है। ** Customer.UpgradWar कुंवारी () या Customer.PromoteToPreferred () जैसी विधि तर्क को स्पष्ट करती है।

यह डीटीओ होने की संभावना को भी दूर नहीं करता है । उस स्थिति पर विचार करें जहां आप ग्राहक जानकारी को दूरस्थ सेवा को उदाहरण के लिए पास करने जा रहे हैं। ग्राहक के लिए परिवहन के लिए खुद का डीटीओ बनाने के लिए कोई मतलब नहीं हो सकता है, यह एक वास्तुशिल्प चिंता है, लेकिन दृढ़ता या नेटवर्क परत / विभाजन / कोड / कोड-व्हाट्स-यू-यू में इसके लिए एक मामला बनाया जा सकता है। उस मामले में, इस तरह के ऑब्जेक्टकॉल्ड में ऐसे तरीके होते हैं जो इस तरह दिखते हैं

public static CustomerDTO GetDTO(Customer c) { /* ... */ }

public static Customer GetCustomer(CustomerDTO cdto) { /* ... */ }

तो, संक्षेप में, यह एक डोमेन ऑब्जेक्ट पर ऑपरेशन करने के लिए सही समझ में आता है जो कि डोमेन में तार्किक संचालन के साथ अनुरूप है।

Google इस मामले पर कई अच्छी चर्चाओं के लिए 'अज्ञानता अज्ञानता' ( यह SO प्रश्न , और इसका स्वीकृत उत्तर शुरू करने के लिए एक अच्छी जगह है)।

** यह कुछ ओआरडी / एम सॉफ़्टवेयर के साथ थोड़ा गड़बड़ हो जाता है, जहां आपको 'सेव' विधि के साथ एक स्थायी आधार से विरासत में मिला जाता है।


3

मैंने वास्तव में हाल ही में डेटा से ऑब्जेक्ट्स को अलग करने के लिए कुछ कोड को फिर से काम किया है। कारण यह है कि डेटा को एक अलग सेवा के माध्यम से प्राप्त किया जाता है, और पूरे डेटा को सर्वर से / कच्चे सर्वर से पास करने के बजाय पूरे ऑब्जेक्ट को आगे और पीछे से पास करना आसान होता है और सर्वर पर सत्यापन त्रुटियों से निपटना आसान होता है।

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


3

मुझे लगता है कि ऐसा करने के दोनों तरीके उनके लाभ हो सकते हैं, लेकिन मैं इसे एक वस्तु उन्मुख या डोमेन संचालित दृष्टिकोण से देखूंगा: विभिन्न वर्गों और वस्तुओं की जिम्मेदारियां क्या हैं।

इसलिए, मैं आपके ठोस मामले में खुद से यह पूछूंगा: क्या किसी ग्राहक को पता होना चाहिए कि खुद को कैसे बचाया जाए?

मेरे लिए, इसका उत्तर नहीं होगा: तार्किक रूप से मेरे लिए इसका कोई मतलब नहीं है, और एक ग्राहक को किसी भी दृढ़ता ढांचे के बारे में कुछ भी नहीं जानना चाहिए (जिम्मेदारियों को अलग करना)।

के रूप में SnOrfus के उदाहरण के लिए Customer.UpgradeWar कुंवारी () या Customer.PromoteToPreferred (), वे स्पष्ट रूप से Customer.Save () की तुलना में अधिक व्यापार तर्क उन्मुख हैं। इसके लिए अलग-अलग दृष्टिकोण हैं, लेकिन फिर अगर आप खुद से पूछते हैं कि क्या ग्राहक को अपनी वारंटी को अपग्रेड करने में सक्षम होना चाहिए, तो इसका जवाब हां या नहीं दोनों पर हो सकता है, यह इस बात पर निर्भर करता है कि आप इसे कैसे देखते हैं:

  • हाँ: एक ग्राहक बेशक अपनी वारंटी को अपग्रेड कर सकता है
  • नहीं: कोई ग्राहक अपग्रेड किए जाने के लिए कह सकता है, लेकिन अपग्रेड किसी और द्वारा किया जाता है

अपने मूल प्रश्न पर वापस जाएं; कौन सा तरीका अधिक समझ में आता है यह संभवतः इस बात पर निर्भर करेगा कि आप किससे पूछते हैं और उनका पसंदीदा तरीका क्या है, लेकिन सबसे महत्वपूर्ण बात यह है कि इसे करने का एक तरीका है।

मेरे अनुभव में, हालांकि, डेटा और (व्यवसाय) तर्क को अलग करना एक सरल वास्तुकला के लिए बनाता है, हालांकि उतना रोमांचक नहीं है।


2

मुझे लगता है कि आप विशेष रूप से ActiveRecordपैटर्न और पैटर्न के बीच अंतर के बारे में बात कर रहे हैं Repository। पूर्व में, संस्थाओं को पता है कि खुद को कैसे बनाए रखना है, और बाद में, रिपॉजिटरी दृढ़ता के बारे में जानता है। मुझे लगता है कि उत्तरार्द्ध चिंताओं का बेहतर अलगाव प्रदान करता है।

एक व्यापक अर्थ में, यदि संस्थाएं डेटा संरचना की तरह कार्य करती हैं, तो उनके पास व्यवहार नहीं होना चाहिए, लेकिन यदि उनके पास व्यवहार है, तो उन्हें डेटा संरचना की तरह उपयोग नहीं किया जाना चाहिए। उदाहरण:

डेटा संरचना:

class CustomerController
{
    public int MostRecentOrderLines(Customer customer)
    {
        var o = (from order in customer.Orders
                orderby order.OrderDate desc
                select order).First();
        return o.OrderLines.ToList().Count;
    }
}

गैर-डेटा संरचना:

class Customer
{
    public int MostRecentOrderLines()
    {
        // ... same ...
    }
}

पहले मामले में, आप अपने कार्य कोड में कहीं से भी, बिना किसी समस्या के अपने मॉडल के डेटा संरचना ट्री को नेविगेट कर सकते हैं, और यह ठीक है, क्योंकि आप इसे डेटा संरचना की तरह मान रहे हैं। बाद के मामले में, ग्राहक किसी दिए गए ग्राहक के लिए एक सेवा की तरह है, इसलिए आपको परिणाम पर तरीकों को नहीं बुलाना चाहिए। ग्राहक के बारे में जानने के लिए आपको ग्राहक के बारे में सभी चीजें उपलब्ध होनी चाहिए।

तो क्या आप चाहते हैं कि आपकी इकाइयाँ डेटा संरचनाएँ या सेवाएँ हों? स्थिरता के लिए, एक के साथ रहना बेहतर लगता है। पूर्व मामले में, अपनी "सेवा" -टाइप तर्क को कहीं और रखें, न कि इकाई में।


1

मैं वास्तव में आपके सवाल का जवाब नहीं दे सकता, लेकिन मुझे यह अजीब लगता है कि हम स्कूल में हमारी एक परियोजना में भी इस चर्चा में हैं। स्वयं डेटा से तर्क को अलग करना चाहेंगे। लेकिन मेरे बहुत से सहपाठियों का कहना है कि ऑब्जेक्ट को सभी लॉजिक और डेटा को होल्ड करना है।

मैं उन तथ्यों को गर्म करने की कोशिश करूंगा जो वे लाते हैं:

  • एक बिजनेस क्लास ऑब्जेक्ट एक चीज़ का प्रतिनिधित्व करता है, इसलिए सभी डेटा और लॉजिक को समाहित किया जाना चाहिए। (उदाहरण के लिए यदि आप एक दरवाजा खोलना चाहते हैं, तो आप इसे स्वयं करते हैं, आप किसी और से नहीं पूछते। बुरा उदाहरण मुझे पता है)

  • एक बू ऑब्जेक्ट के कोड और कार्यक्षमता को समझने में आसान है।

  • डिजाइन में कम जटिलता

मैं उन्हें बता रहा हूं कि वे आलसी हैं और मैं इसे इस तरह बनाऊंगा:

  • हां बिजनेस क्लास चीजों का प्रतिनिधित्व करती है, इसलिए यह डेटा रखती है। लेकिन खुद को बचाना, या कॉपी करना भी गलत लगता है। आप आरएल में ऐसा नहीं कर सकते।

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

  • डेटा को बनाए रखने में सक्षम एक वस्तु होने से, वह ऑब्जेक्ट एक डेटाबेस कनेक्शन पकड़ सकता है और सभी डेटाबेस ट्रैफ़िक को उस ऑब्जेक्ट पर निर्देशित किया जाता है। (बुनियादी तौर पर इसके डेटा लेयर में वृद्धि होती है) अन्यथा सभी बिजनेस ऑब्जेक्ट को एक कनेक्शन रखना होगा। (जो जटिलता जोड़ता है)

खैर एक रास्ता या कोई अन्य, मैं एक शिक्षक से पूछने जा रहा हूं। जब मैंने ऐसा कर लिया है, तो मैं उसका उत्तर यहां भी पोस्ट करूंगा, अगर आप चाहें। ;)

संपादित करें:

मैं इस परियोजना का उल्लेख करना भूल गया, एक पुस्तक भंडार के बारे में था।


आपके सहपाठी सही हैं, सिवाय इसके कि वे तर्क के अन्य रूपों (इस मामले में, वास्तुशिल्प या दृढ़ता तर्क) के साथ व्यावसायिक तर्क को भ्रमित कर रहे हैं।
स्टीवन एवर्स

1

इसका उत्तर वास्तव में इस बात पर निर्भर करता है कि आपकी वास्तुकला / डिज़ाइन क्या है - एक डोमेन मॉडल वाला एक DDD आर्किटेक्चर CRUD डेटा-केंद्रित मॉडल से बहुत अलग होने वाला है जब यह ऑब्जेक्ट डिज़ाइन की बात आती है।

सामान्य तौर पर, इस बात को ध्यान में रखें कि ऑब्जेक्ट-ओरिएंटेड-डिज़ाइन में आप राज्य को एनकैप्सुलेट करने और व्यवहार को उजागर करने की कोशिश कर रहे हैं। इसका मतलब यह है कि आप आमतौर पर किसी व्यवहार से जुड़े राज्य को उस व्यवहार के जितना संभव हो सके, पाने की कोशिश करेंगे - जब आप ऐसा करने में विफल होते हैं, तो आप राज्य को एक या दूसरे रूप में उजागर करने के लिए मजबूर होते हैं।

एक डोमेन मॉडल में आप बिजनेस मॉडल को बुनियादी ढांचे की चिंताओं से अलग करना चाहते हैं - इसलिए आप '.Save' जैसे तरीकों से बचना चाहते हैं। मुझे याद नहीं है कि पिछली बार मैंने वास्तविक जीवन में किसी ग्राहक को "बचाया" था!

एक CRUD आवेदन में तो डेटा प्रथम श्रेणी का नागरिक है इसलिए ".Save" पूरी तरह से उपयुक्त है।

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


0

मैं कुछ समय से एक ही प्रश्न पर विचार कर रहा हूं - मुझे लगता है कि डेटा घटक और तर्क घटक अलग होना चाहिए। मेरा यह मानना ​​है क्योंकि यह आपको डेटा के इंटरफ़ेस के रूप में व्यावसायिक तर्क के बारे में मन के सही फ्रेम में लाता है जो अर्थ प्रदान करता है।

मैं स्कॉट व्हिटलॉक के बिंदु को ऊपर से मॉडिफाई करूंगा (मेरे पास कोई नया सदस्य होने के अलावा कोई बिंदु नहीं है), डेटा या व्यावसायिक तर्क वर्गों को वास्तव में चिंता नहीं करनी चाहिए कि ऑब्जेक्ट लगातार कैसे संग्रहीत किया जाता है।

कहा जा रहा है, यदि आप एक मौजूदा उत्पाद के साथ काम कर रहे हैं, जब तक कि आपके पास साफ, संविदात्मक इंटरफेस है - यह ठीक है और बनाए रखने योग्य भी है ...

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