चाचा बॉब की स्वच्छ वास्तुकला - प्रत्येक परत के लिए एक इकाई / मॉडल वर्ग?


44

पृष्ठभूमि :

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

मुझे क्या सूचित किया गया:

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

सवाल :

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

जवाबों:


52

मेरी राय में, यह बिल्कुल नहीं है कि यह कैसे मतलब है। और यह DRY का उल्लंघन है।

विचार यह है कि बीच में इकाई / डोमेन ऑब्जेक्ट को डोमेन को अच्छे और यथासंभव सुविधाजनक बनाने के लिए मॉडल किया गया है। यह सब कुछ के केंद्र में है और सब कुछ इस पर निर्भर कर सकता है क्योंकि डोमेन स्वयं अधिकांश समय नहीं बदलता है।

यदि बाहर की ओर आपका डेटाबेस उन वस्तुओं को सीधे स्टोर कर सकता है, तो उन्हें अलग-अलग परतों की खातिर किसी अन्य प्रारूप में मैप करना न केवल व्यर्थ है, बल्कि मॉडल के डुप्लिकेट बनाना है और यह इरादा नहीं है।

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

हल्के ओआरएम के साथ जो ऑब्जेक्ट को लोड और स्टोर करते हैं, ऐसा नहीं है। वे अपने आंतरिक SQLRowऔर आपके डोमेन के बीच मैपिंग करते हैं। यहां तक ​​कि अगर आपको @Entitiyअपने डोमेन ऑब्जेक्ट में ORM का एनोटेशन डालने की आवश्यकता है , तो मैं तर्क दूंगा कि यह बाहरी परत का "उल्लेख" स्थापित नहीं करता है। क्योंकि एनोटेशन केवल मेटाडेटा हैं, कोई भी कोड जो विशेष रूप से उनकी तलाश नहीं कर रहा है उन्हें देखेगा। और इससे भी महत्वपूर्ण बात, यदि आप उन्हें हटाते हैं या उन्हें अलग डेटाबेस के एनोटेशन के साथ बदलने की आवश्यकता नहीं है।

इसके विपरीत, यदि आप अपना डोमेन बदलते हैं और आपने उन सभी मैपर्स को बनाया है, तो आपको बहुत कुछ बदलना होगा।


संशोधन: ऊपर एक छोटा सा निरीक्षण है और गलत भी हो सकता है। क्योंकि स्वच्छ वास्तुकला में एक हिस्सा है जो आपको प्रति परत एक प्रतिनिधित्व बनाना चाहता है। लेकिन उस आवेदन के संदर्भ में देखा जाना चाहिए।

निम्नलिखित यहाँ https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean- RGBecture.html

महत्वपूर्ण बात यह है कि सीमाओं के पार पृथक, सरल, डेटा संरचनाएं हैं। हम Entities या डेटाबेस पंक्तियों को धोखा और पारित नहीं करना चाहते हैं। हम नहीं चाहते हैं कि डेटा संरचनाओं में किसी भी प्रकार की निर्भरता हो जो निर्भरता नियम का उल्लंघन करती हो।

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

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

और वहाँ https://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html पते हैं:

अन्य लोगों ने चिंतित किया है कि मेरी सलाह का शुद्ध परिणाम बहुत सारे डुप्लिकेट किए गए कोड होंगे, और सिस्टम की परतों के पार एक डेटा संरचना से दूसरे में डेटा की बहुत सारी नकल। निश्चित रूप से मुझे यह नहीं चाहिए; और मैंने जो कुछ भी सुझाया है वह अनिवार्य रूप से डेटा संरचनाओं की पुनरावृत्ति और क्षेत्र की नकल का एक कारण होगा।

उस IMO का तात्पर्य है कि वस्तुओं की 1: 1 कॉपी करना वास्तुकला में एक गंध है क्योंकि आप वास्तव में उचित परतों और / या अमूर्त का उपयोग नहीं कर रहे हैं।

बाद में उन्होंने बताया कि कैसे वे सभी "नकल" की कल्पना करते हैं

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

इस एप्लिकेशन में, अभ्यावेदन के बीच एक बड़ा अंतर है। जो डेटा प्रवाहित होता है वह केवल इकाइयाँ नहीं है। और यह वारंट और विभिन्न वर्गों की मांग करता है।

हालाँकि, फोटो दर्शक की तरह एक साधारण एंड्रॉइड एप्लिकेशन पर लागू किया जाता है, जहां Photoइकाई के पास लगभग 0 व्यावसायिक नियम और "उपयोग का मामला" है, जो उनके साथ व्यवहार करता है, लगभग गैर-मौजूद है और वास्तव में कैशिंग और डाउनलोडिंग के बारे में अधिक चिंतित है (यह प्रक्रिया IMO होनी चाहिए। अधिक स्पष्ट रूप से प्रतिनिधित्व किया गया), एक तस्वीर के अलग-अलग प्रतिनिधित्व करने का बिंदु गायब होने लगता है। मुझे यह भी महसूस हो रहा है कि फोटो ही डेटा ट्रांसफर ऑब्जेक्ट है जबकि असली बिजनेस-लॉजिक-कोर-लेयर गायब है।

"दोनों के बीच सरल डेटा संरचनाओं को पारित करके" व्यापार के नियमों से यूआई को अलग करने के बीच एक अंतर है " और जब आप रास्ते में 3 बार एक फोटो का नाम बदलना चाहते हैं"

इसके अलावा, जिस बिंदु पर मैं उन डेमो एप्लिकेशन को साफ आर्किटेक्चर का प्रतिनिधित्व करने में विफल रहता हूं, वह यह है कि वे परतों को अलग करने के लिए परतों को अलग करने पर बहुत जोर देते हैं लेकिन प्रभावी रूप से यह छिपाते हैं कि एप्लिकेशन क्या करता है। जो कि https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html - अर्थात् में कही गई बातों के विपरीत है

एक सॉफ्टवेयर अनुप्रयोग की वास्तुकला अनुप्रयोग के उपयोग के मामलों के बारे में चिल्लाती है

मैं साफ वास्तुकला में परतों को अलग करने पर जोर नहीं देता। यह निर्भरता दिशा के बारे में है और आवेदन के मूल का प्रतिनिधित्व करने पर ध्यान केंद्रित कर रहा है - संस्थाओं और उपयोग के मामले - आदर्श रूप से सादे जावा में बाहर की ओर निर्भरता के बिना। यह उस कोर के प्रति निर्भरता के बारे में इतना नहीं है।

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


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

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

1
@RamiJemli ऐसे फ्रेमवर्क का उपयोग करना अच्छा है जो जीवन को सरल बनाते हैं, मुद्दा यह है कि आपको सावधान रहना चाहिए जब आपका आर्किटेक्चर उन पर निर्भर हो और आप उन्हें हर चीज के केंद्र में रखना शुरू करें। यहाँ RxJava के बारे में भी एक लेख है blog.8thlight.com/uncle-bob/2015/08/06/let-the-magic-die.html - यह नहीं कह रहा है आप इसका इस्तेमाल नहीं करना चाहिए। यह अधिक पसंद है: मैंने इसे देखा है, यह एक वर्ष में अलग होने जा रहा है और जब आपका आवेदन अभी भी आसपास है तो आप इसके साथ फंस गए हैं। इसे विस्तार दें और सादे पुराने सोल में सबसे महत्वपूर्ण चीजें करें, जबकि पुराने पुराने ठोस सिद्धांतों को लागू करें।
zapl

1
@zapl क्या आप वेब सेवा परत के बारे में भी ऐसा ही महसूस करते हैं? दूसरे शब्दों में, क्या आप @SerializedNameएक डोमेन मॉडल पर Gson एनोटेशन डालेंगे? या आप डोमेन मॉडल के लिए वेब प्रतिक्रिया मैप करने के लिए जिम्मेदार एक नई वस्तु बनाएंगे?
tir38

2
@ tir38 पृथक्करण स्वयं को लाभ प्रदान नहीं करता है, यह भविष्य के परिवर्तनों की लागत है जो इसके साथ नीचे जाते हैं। => आवेदन पर निर्भर करता है। 1) यह आपको अलग-अलग अभ्यावेदन के बीच बदलने वाले अतिरिक्त चरण को बनाने और बनाए रखने के लिए समय देता है। उदाहरण के लिए एक क्षेत्र को डोमेन से जोड़ना और इसे कहीं और जोड़ना न भूलें। सरल दृष्टिकोण के साथ नहीं हो सकता। 2) बाद में यदि आपको इसकी आवश्यकता हो, तो अधिक जटिल सेटअप में संक्रमण करने की लागत है। परतों को जोड़ना आसान नहीं है, इसलिए बड़े अनुप्रयोगों में अधिक परतों को औचित्य देना आसान है जो तुरंत आवश्यक नहीं हैं
zapl

7

आप वास्तव में यह सही है। और DRY का कोई उल्लंघन नहीं है क्योंकि आप SRP स्वीकार करते हैं।

उदाहरण के लिए: आपके पास एक व्यवसाय-विधि createX (स्ट्रिंग नाम) है, तो आपके पास DAO- लेयर में एक विधि createX (स्ट्रिंग नाम) हो सकती है, जिसे व्यवसाय-विधि के भीतर कहा जाता है। उनके पास एक ही हस्ताक्षर हो सकता है और हो सकता है कि केवल एक प्रतिनिधिमंडल हो लेकिन उनके अलग उद्देश्य हैं। आप UseCase पर एक createX (स्ट्रिंग नाम) भी रख सकते हैं। तब भी यह बेमानी नहीं है। इससे मेरा मतलब है: समान हस्ताक्षर का अर्थ एक ही शब्दार्थ नहीं है। शब्दार्थ को स्पष्ट करने के लिए अन्य नाम चुनें। इसका नामकरण एसआरपी को बिल्कुल भी प्रभावित नहीं करता है।

UseCase अनुप्रयोग-विशिष्ट तर्क के लिए ज़िम्मेदार है, व्यावसायिक ऑब्जेक्ट अनुप्रयोग-स्वतंत्र तर्क के लिए ज़िम्मेदार है और DAO भंडारण के लिए ज़िम्मेदार है।

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

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

मैं स्वच्छ वास्तुकला और SOLID के आवेदन को "सामाजिक रूप से स्वीकार्य नहीं" कहता हूं। अगर मुझे अनुमति दी जाती है तो मैं इसके साथ काम करूंगा। वर्तमान में मुझे इसे करने की अनुमति नहीं है। मैं उस पल का इंतजार करता हूं जब हमें SOLID को गंभीरता से लेने के बारे में सोचना होगा।


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

मैं रामी के साथ कंसर्ट करता हूं, मैपर अनावश्यक है क्योंकि आप मैपिंग को सीधे इंटरएक्टर कार्यान्वयन में कर सकते हैं।
क्रिस्टोफर पेरी

5

नहीं, आपको हर परत में मॉडल कक्षाएं बनाने की आवश्यकता नहीं है।

इकाई ( DATA_LAYER) - डेटाबेस ऑब्जेक्ट का पूर्ण या आंशिक प्रतिनिधित्व है।DATA_LAYER

मैपर ( DOMAIN_LAYER) - वास्तव में एक वर्ग है जो एंटिटी को मॉडलक्लास में परिवर्तित करता है, जिसका उपयोग किया जाएगाDOMAIN_LAYER

नज़र डालें: https://github.com/lifedemons/photoviewer


1
बेशक, मैं डेटा लेयर में संस्थाओं के खिलाफ नहीं हूँ, लेकिन, आपके उदाहरण में, प्रस्तुति परत में PhotoModel क्लास में डोमेन लेयर में Photo क्लास के समान गुण हैं। यह तकनीकी रूप से एक ही वर्ग है। क्या यह आवश्यक है?

मुझे लगता है कि आपके उदाहरण में कुछ बंद है क्योंकि डोमेन लेयर अन्य परतों पर निर्भर नहीं होना चाहिए क्योंकि आपके उदाहरण में आपके मैपर्स आपके डेटा लेयर में मौजूद संस्थाओं पर निर्भर करते हैं जो IMO है, यह इसके विपरीत होना चाहिए
navid_gh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.