क्या कार्यात्मक प्रोग्रामिंग के संदर्भ में एनीमिक मॉडल के बारे में बात करना अभी भी मान्य है?


40

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

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

अद्यतन : हाल ही में प्रकाशित पुस्तक और वीडियो विषय पर।


1
यदि आप कह रहे हैं कि मुझे लगता है कि आप यहाँ कह रहे हैं, तो डीटीओ के एनेमिक, लेकिन डीडीडी में प्रथम श्रेणी के ऑब्जेक्ट हैं, और डीटीओ की सेवाओं के बीच एक प्राकृतिक अलगाव है जो उन्हें संसाधित करता है। मैं सिद्धांत रूप में सहमत हूं। तो यह ब्लॉग पोस्ट करता है , जाहिरा तौर पर।
रॉबर्ट हार्वे


1
"क्या शब्द 'एनीमिक मॉडल' अभी भी उस मामले में मौजूद है" लघु उत्तर, एओमिक मॉडल शब्द ओओ के संदर्भ में गढ़ा गया था। एफपी के संदर्भ में एनीमिक मॉडल की बात करने से कोई मतलब नहीं है। मुहावरेदार एफपी क्या है इसका वर्णन करने के अर्थ में समकक्ष हो सकते हैं, लेकिन इसका एनीमिक मॉडल से कोई लेना-देना नहीं है।
०४

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

2
@ JörgWMittag: आप सामान्य परिभाषा के अलावा अन्य मतलब है? बहुत सारे चित्रमय मंच हैं, हास्केल सबसे स्पष्ट है।
रॉबर्ट हार्वे

जवाबों:


24

जिस तरह से "एनीमिक मॉडल" समस्या का वर्णन किया गया है वह एफपी के लिए अच्छी तरह से अनुवाद नहीं करता है। पहले इसे उपयुक्त रूप से सामान्यीकृत करने की आवश्यकता है। यह दिल में है, एक एनीमिक मॉडल एक मॉडल है जिसमें इस बारे में ज्ञान होता है कि इसे कैसे ठीक से उपयोग किया जाए जो मॉडल द्वारा खुद को समझाया नहीं गया है। इसके बजाय, यह ज्ञान संबंधित सेवाओं के ढेर के आसपास फैला हुआ है। उन सेवाओं को केवल मॉडल का ग्राहक होना चाहिए , लेकिन इसके एनीमिया के कारण उन्हें इसके लिए जिम्मेदार माना जाता है। उदाहरण के लिए, एक Accountवर्ग पर विचार करें जिसका उपयोग खातों को सक्रिय करने या निष्क्रिय करने या किसी खाते के बारे में जानकारी देखने के लिए नहीं किया जा सकता है जब तक कि एक AccountManagerवर्ग के माध्यम से नियंत्रित नहीं किया जाता है । खाते को मूल संचालन के लिए जिम्मेदार होना चाहिए, न कि कुछ बाहरी प्रबंधक वर्ग को।

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

इस समस्या का समाधान आमतौर पर कुछ चरणों में होता है। एक सरल पहली कटौती यह है कि "ठीक है, एक UserIDस्ट्रिंग के बराबर का प्रतिनिधित्व किया जाता है, लेकिन वे अलग-अलग प्रकार के होते हैं और आप एक का उपयोग नहीं कर सकते जहां आप दूसरे की अपेक्षा करते हैं।" हास्केल (और कुछ अन्य टाइप की गई कार्यात्मक भाषाएं) इस सुविधा को प्रदान करती हैं newtype:

newtype UserID = UserID String

यह एक को परिभाषित करता है UserIDसमारोह जो जब दिए गए एक Stringकि है एक मूल्य के निर्माण की तरह व्यवहार एक UserIDप्रकार प्रणाली द्वारा, लेकिन जो अभी भी सिर्फ एक है Stringरनटाइम पर। अब फ़ंक्शंस यह घोषित कर सकते हैं कि उन्हें UserIDएक स्ट्रिंग के बजाय आवश्यकता है ; UserIDएस का उपयोग करते हुए जहां आप पहले कोड को UserIDएक साथ दो एस के साथ तार गार्ड का उपयोग कर रहे थे । प्रकार प्रणाली की गारंटी है कि ऐसा नहीं हो सकता है, कोई परीक्षण की आवश्यकता नहीं है।

यहां कमजोरी यह है कि कोड अभी भी किसी भी Stringतरह की मनमानी ले सकता है "hello"और इससे निर्माण कर UserIDसकता है। आगे के चरणों में एक "स्मार्ट कंस्ट्रक्टर" फ़ंक्शन बनाना शामिल है, जब एक स्ट्रिंग कुछ इन्वर्टर की जांच करता है और केवल तभी वापस लौटता है UserIDजब वे संतुष्ट होते हैं। फिर "डंब" UserIDकंस्ट्रक्टर को निजी बनाया जाता है, इसलिए यदि कोई ग्राहक चाहता है तो UserIDउन्हें स्मार्ट कंस्ट्रक्टर का उपयोग करना चाहिए , जिससे विकृत यूजरआईडी को अस्तित्व में आने से रोका जा सके।

इससे भी आगे के कदम UserIDडेटा प्रकार को इस तरह से परिभाषित करते हैं कि यह असंभव है कि "विकृत" या "अनुचित", बस परिभाषा से। उदाहरण के लिए, UserIDअंकों की सूची के रूप में परिभाषित करना :

data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine
data UserID = UserID [Digit]

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


2
और कुलियों और कुलीन जड़ों की रक्षा के बारे में क्या invariantы की देखरेख कर रहे हैं, क्या पिछले वाले भी व्यक्त किए जा सकते हैं और आसानी से डेवलपर्स द्वारा समझे जा सकते हैं? मेरे लिए DDD का सबसे मूल्यवान हिस्सा कोड के लिए व्यवसाय मॉडल का प्रत्यक्ष मानचित्रण है। और आप उत्तर देते हैं कि वास्तव में इसके बारे में है।
पावेल वोरोनिन

2
अच्छा भाषण, लेकिन ओपी सवाल का कोई जवाब नहीं।
सेरग

10

एक बड़ी हद तक, अपरिवर्तनीयता OOP अधिवक्ताओं के रूप में आपके डेटा के साथ अपने कार्यों को कसकर करने के लिए अनावश्यक बनाती है। आप जितनी चाहें उतनी प्रतियां बना सकते हैं, यहां तक ​​कि व्युत्पन्न डेटा संरचनाएं भी बना सकते हैं, मूल कोड से हटाए गए कोड में, मूल डेटा संरचना के डर के बिना अप्रत्याशित रूप से आपके नीचे से बदल सकते हैं।

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

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


2
"एक बड़ी डिग्री में, अपरिवर्तनीयता OOP अधिवक्ताओं के रूप में आपके डेटा के साथ आपके कार्यों को कसकर जोड़े रखने के लिए अनावश्यक बनाता है।": डेटा और प्रक्रियाओं को युग्मित करने का एक अन्य कारण गतिशील प्रेषण हालांकि बहुरूपता को लागू कर रहा है।
जियोर्जियो

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

7

OOP में DDD का उपयोग करते समय, व्यापार तर्क को डोमेन ऑब्जेक्ट्स में रखने के मुख्य कारणों में से एक यह है कि व्यावसायिक तर्क आमतौर पर ऑब्जेक्ट की स्थिति को म्यूट करके लागू किया जाता है। यह एन्कैप्सुलेशन से संबंधित है: Employee.RaiseSalaryसंभवतः उदाहरण के salaryक्षेत्र को म्यूट करता है Employee, जिसे सार्वजनिक रूप से व्यवस्थित नहीं होना चाहिए।

एफपी में, उत्परिवर्तन से बचा जाता है, इसलिए आप इस व्यवहार को एक ऐसा RaiseSalaryफ़ंक्शन बनाकर कार्यान्वित करेंगे जो मौजूदा Employeeउदाहरण लेता है और नए वेतन के साथ एक नया Employee उदाहरण देता है । तो कोई उत्परिवर्तन शामिल नहीं है: केवल मूल वस्तु से पढ़ना और नई वस्तु बनाना। इस कारण से, इस तरह के RaiseSalaryफ़ंक्शन को Employeeक्लास पर एक विधि के रूप में परिभाषित करने की आवश्यकता नहीं है , लेकिन कहीं भी रह सकते हैं।

इस स्थिति में, डेटा को व्यवहार से अलग करना स्वाभाविक हो जाता है: एक संरचना Employeeडेटा (पूरी तरह से एनीमिक) का प्रतिनिधित्व करती है , जबकि एक (या कई) मॉड्यूल में ऐसे कार्य होते हैं जो उस डेटा पर काम करते हैं (अपरिवर्तनीयता का संरक्षण)।

ध्यान दें कि जब आप डेटा और व्यवहार को DDD के रूप में लेते हैं, तो आप आमतौर पर सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल (SRP) का उल्लंघन करते हैं: Employeeयदि वेतन परिवर्तन के नियम बदल जाते हैं, तो इसे बदलने की आवश्यकता हो सकती है; लेकिन यह भी बदलना पड़ सकता है अगर ईओवाई बोनस परिवर्तन की गणना के नियम। विघटित दृष्टिकोण के साथ यह मामला नहीं है, क्योंकि आपके पास कई मॉड्यूल हो सकते हैं, प्रत्येक एक जिम्मेदारी के साथ।

इसलिए, हमेशा की तरह एफपी दृष्टिकोण अधिक से अधिक प्रतिरूपकता / रचनाशीलता प्रदान करता है।


-1

मुझे लगता है कि इस मामले का सार यह है कि सभी डोमेन लॉजिक वाले एनेमिक मॉडल, जो मॉडल पर काम करते हैं, मूल रूप से प्रक्रियात्मक प्रोग्रामिंग हैं - जैसा कि "वास्तविक" OO प्रोग्रामिंग के विपरीत है, जहां आपके पास ऐसी वस्तुएं हैं जो "स्मार्ट" हैं और जिनमें केवल डेटा नहीं है लेकिन यह भी तर्क है कि डेटा के सबसे निकट से जुड़ा हुआ है।

और एक ही विपरीत कार्यात्मक प्रोग्रामिंग के साथ मौजूद है: "वास्तविक" एफपी का अर्थ है फर्स्ट-क्लास संस्थाओं के रूप में फ़ंक्शंस का उपयोग करना, जो मापदंडों के रूप में पास किए जाते हैं, साथ ही साथ फ्लाई पर निर्मित होते हैं और रिटर्न वैल्यू के रूप में लौटते हैं। लेकिन जब आप उस सभी शक्ति का उपयोग करने में विफल हो जाते हैं और केवल ऐसे फ़ंक्शन होते हैं जो डेटा संरचनाओं पर काम करते हैं जो उनके बीच पारित हो जाते हैं, तो आप उसी स्थान पर समाप्त होते हैं: आप मूल रूप से प्रक्रियात्मक प्रोग्रामिंग कर रहे हैं।


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

-3

मैं जानना चाहता हूं कि डीडीडी एफपी प्रतिमान में कैसे फिट बैठता है

मुझे लगता है कि ऐसा होता है, लेकिन मोटे तौर पर अपरिवर्तनीय मूल्य वस्तुओं के बीच संक्रमण के लिए एक सामरिक दृष्टिकोण के रूप में या संस्थाओं पर तरीकों को ट्रिगर करने के तरीके के रूप में । (जहां अधिकांश तर्क अभी भी इकाई में रहते हैं।)

और क्या उस मामले में 'एनीमिक मॉडल' शब्द अभी भी मौजूद है।

ठीक है, अगर आपका मतलब "पारंपरिक ओओपी के अनुरूप" है, तो यह सामान्य कार्यान्वयन विवरणों को अनदेखा करने और मूल बातें पर वापस जाने में मदद करता है: आपके डोमेन-विशेषज्ञ किस भाषा का उपयोग करते हैं? आपके उपयोगकर्ताओं से आपकी मंशा क्या है ?

मान लें कि वे प्रक्रियाओं और कार्यों को एक साथ चलाने के बारे में बात करते हैं, तो ऐसा लगता है कि फ़ंक्शन (या कम से कम "डू-एर" ऑब्जेक्ट) मूल रूप से आपके डोमेन-ऑब्जेक्ट हैं!

तो उस परिदृश्य में, एक "एनीमिक मॉडल" शायद तब होगा जब आपके "फ़ंक्शंस" वास्तव में निष्पादन योग्य नहीं होते हैं, और इसके बजाय केवल मेटाडाटा के तारामंडल होते हैं जो एक सेवा द्वारा व्याख्या की जाती हैं जो वास्तविक काम करती है।


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

इसलिए "फ़ंक्शन" के आसपास उद्धरण-चिह्नों, यह जोर देने के लिए कि एनीमिक होने पर लेबल कितना अनुपयुक्त हो जाता है।
डेरेन

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