कितना सही है "व्यावसायिक तर्क एक सेवा में होना चाहिए, एक मॉडल में नहीं"?


397

परिस्थिति

इससे पहले शाम को मैंने StackOverflow पर एक प्रश्न का उत्तर दिया ।

प्रश्न:

किसी मौजूदा ऑब्जेक्ट का संपादन रिपॉजिटरी लेयर या सर्विस में किया जाना चाहिए?

उदाहरण के लिए यदि मेरे पास एक उपयोगकर्ता है जिसमें ऋण है। मैं उसका कर्ज बदलना चाहता हूं। क्या मुझे UserRepository में या उदाहरण के लिए BuyService में एक ऑब्जेक्ट प्राप्त करके, उसे संपादित करके और सहेज कर सेवा में करना चाहिए?

मेरा जवाब:

आपको किसी ऑब्जेक्ट को उसी ऑब्जेक्ट पर म्यूट करने की जिम्मेदारी छोड़नी चाहिए और इस ऑब्जेक्ट को पुनः प्राप्त करने के लिए रिपॉजिटरी का उपयोग करना चाहिए।

उदाहरण स्थिति:

class User {
    private int debt; // debt in cents
    private string name;

    // getters

    public void makePayment(int cents){
        debt -= cents;
    }
}

class UserRepository {
    public User GetUserByName(string name){
        // Get appropriate user from database
    }
}

एक टिप्पणी मुझे प्राप्त हुई:

व्यावसायिक तर्क वास्तव में एक सेवा में होना चाहिए। किसी मॉडल में नहीं।

इंटरनेट क्या कहता है?

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

एनीमिक डोमेन मॉडल के विरोधी पैटर्न पर मार्टिन फाउलर द्वारा इस लेख का उदाहरण लें :

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

(...) जो तर्क एक डोमेन ऑब्जेक्ट में होना चाहिए, वह डोमेन लॉजिक है - सत्यापन, गणना, व्यावसायिक नियम - जो भी आप इसे कॉल करना पसंद करते हैं।

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

मुझे यह भी महसूस हुआ कि उस लेख में (नीचे देखें), एक सर्विस लेयर को एक बहाना के रूप में माना जाता है जो वास्तविक मॉडल की तरह काम करने वाली परत की तुलना में अंतर्निहित मॉडल पर काम करता है।

एप्लीकेशन लेयर [सर्विस लेयर के लिए उसका नाम]: उन नौकरियों को परिभाषित करता है जो सॉफ्टवेयर को करना है और समस्याओं को हल करने के लिए अभिव्यंजक डोमेन ऑब्जेक्ट को निर्देशित करता है। यह परत जिन कार्यों के लिए जिम्मेदार है, वे व्यवसाय के लिए सार्थक हैं या अन्य प्रणालियों के अनुप्रयोग परतों के साथ बातचीत के लिए आवश्यक हैं। इस परत को पतला रखा जाता है। इसमें व्यावसायिक नियम या ज्ञान शामिल नहीं है, लेकिन केवल अगली परतों में डोमेन ऑब्जेक्ट्स के सहयोग के लिए कार्यों का समन्वय करता है और प्रतिनिधि काम करता है। इसमें व्यवसाय की स्थिति को दर्शाते हुए राज्य नहीं है, लेकिन इसमें वह राज्य हो सकता है जो उपयोगकर्ता या कार्यक्रम के लिए किसी कार्य की प्रगति को दर्शाता है।

जो यहाँ प्रबलित है :

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

और यहाँ :

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

यह सेवा लेयर के बारे में बात करने वाले अन्य संसाधनों के लिए एक गंभीर विपरीत है :

सेवा परत में उन विधियों के साथ कक्षाएं शामिल होनी चाहिए जो एक ही लेनदेन में काम करने वाली इकाइयों के साथ काम करती हैं।

या एक प्रश्न का दूसरा उत्तर जो मैंने पहले ही लिंक कर दिया है:

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

"उपाय"?

इस उत्तर में दिशानिर्देशों के बाद , मैं निम्नलिखित दृष्टिकोण के साथ आया, जो सेवा परत का उपयोग करता है:

class UserController : Controller {
    private UserService _userService;

    public UserController(UserService userService){
        _userService = userService;
    } 

    public ActionResult MakeHimPay(string username, int amount) {
        _userService.MakeHimPay(username, amount);
        return RedirectToAction("ShowUserOverview");
    }

    public ActionResult ShowUserOverview() {
        return View();
    }
}

class UserService {
    private IUserRepository _userRepository;

    public UserService(IUserRepository userRepository) {
        _userRepository = userRepository;
    }

    public void MakeHimPay(username, amount) {
        _userRepository.GetUserByName(username).makePayment(amount);
    }
}

class UserRepository {
    public User GetUserByName(string name){
        // Get appropriate user from database
    }
}

class User {
    private int debt; // debt in cents
    private string name;

    // getters

    public void makePayment(int cents){
        debt -= cents;
    }
}

निष्कर्ष

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

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

  • क्या यह नियंत्रक से तर्क निकालने और उसे एक सेवा के अंदर रखने का एक साधन है?

  • क्या यह नियंत्रक और डोमेन के बीच एक अनुबंध बनाने वाला है?

  • क्या डोमेन और सेवा परत के बीच एक परत होनी चाहिए?

और, अंतिम लेकिन कम से कम नहीं: मूल टिप्पणी के बाद

व्यावसायिक तर्क वास्तव में एक सेवा में होना चाहिए। किसी मॉडल में नहीं।

  • क्या ये सही है?

    • मैं मॉडल के बजाय किसी सेवा में अपने व्यावसायिक तर्क का परिचय कैसे दूंगा?

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

मुझे लगा कि सेवाएं मॉडल लेयर का हिस्सा थीं। क्या मैं ऐसा सोचने में गलत हूँ?
फ्लोरियन मार्गाइन

मैं अंगूठे के नियम का उपयोग करता हूं: इस बात पर निर्भर न करें कि आपको क्या चाहिए; अन्यथा मैं (आमतौर पर नकारात्मक रूप से) उस हिस्से पर परिवर्तन से प्रभावित हो सकता हूं जिसकी मुझे आवश्यकता नहीं है। परिणामस्वरूप, मैं स्पष्ट रूप से परिभाषित कई भूमिकाओं के साथ अंत करता हूं। मेरे डेटा ऑब्जेक्ट में तब तक व्यवहार होता है जब तक सभी क्लाइंट इसका उपयोग करते हैं। अन्यथा मैं व्यवहार को आवश्यक भूमिका को लागू करने वाली कक्षाओं में ले जाता हूं।
बेलुचिन

1
अनुप्रयोग प्रवाह नियंत्रण तर्क नियंत्रक में है। डेटा एक्सेस लॉजिक एक रिपॉजिटरी का है। सत्यापन तर्क एक सेवा परत में है। एक सेवा परत ASP.NET MVC अनुप्रयोग में एक अतिरिक्त परत है जो एक नियंत्रक और रिपॉजिटरी परत के बीच संचार की मध्यस्थता करती है। सेवा परत में व्यावसायिक सत्यापन तर्क सम्‍मिलित है। भंडार। asp.net/mvc/overview/older-versions-1/models-data/…
Kbdavis07

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

जवाबों:


367

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

सेवा एक विहित या सामान्य सॉफ़्टवेयर शब्द नहीं है। वास्तव में, Serviceएक वर्ग के नाम पर प्रत्यय बहु-निंदित प्रबंधक की तरह है : यह आपको लगभग कुछ भी नहीं बताता है कि वस्तु वास्तव में क्या करती है

वास्तव में, एक सेवा को जो करना चाहिए वह अत्यधिक वास्तुकला-विशिष्ट है:

  1. एक पारंपरिक स्तरित वास्तुकला में, सेवा वस्तुतः व्यावसायिक तर्क परत का पर्याय है । यह UI और डेटा के बीच की परत है। इसलिए, सभी व्यावसायिक नियम सेवाओं में जाते हैं। डेटा लेयर को केवल बेसिक CRUD ऑपरेशंस को समझना चाहिए, और यूआई लेयर को केवल व्यावसायिक ऑब्जेक्ट्स से प्रेजेंटेशन डीटीओ के मैपिंग से निपटना चाहिए।

  2. RPC- शैली में वितरित आर्किटेक्चर (SOAP, UDDI, BPEL, आदि) में, सेवा एक भौतिक बिंदु का तार्किक संस्करण है । यह अनिवार्य रूप से संचालन का एक संग्रह है जो अनुचर एक सार्वजनिक एपीआई के रूप में प्रदान करना चाहता है। विभिन्न सर्वोत्तम प्रथाओं के मार्गदर्शक बताते हैं कि वास्तव में एक सेवा ऑपरेशन एक व्यवसाय-स्तरीय ऑपरेशन होना चाहिए न कि सीआरयूडी, और मैं सहमत हूं।

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

  3. एमवीपी / एमवीसी / एमवीवीएम / एमवी * आर्किटेक्चर में सेवाएं बिल्कुल भी मौजूद नहीं हैं। या अगर वे करते हैं, तो इस शब्द का उपयोग किसी भी सामान्य वस्तु को संदर्भित करने के लिए किया जाता है जिसे नियंत्रक या दृश्य मॉडल में इंजेक्ट किया जा सकता है। व्यावसायिक तर्क आपके मॉडल में है । यदि आप जटिल ऑपरेशन को ऑर्केस्ट्रेट करने के लिए "सर्विस ऑब्जेक्ट" बनाना चाहते हैं, तो इसे कार्यान्वयन विवरण के रूप में देखा जाता है। बहुत से लोग, दुख की बात है कि एमवीसी को इस तरह से लागू करते हैं, लेकिन इसे एक एंटी-पैटर्न ( एनीमिक डोमेन मॉडल ) माना जाता है क्योंकि मॉडल खुद कुछ नहीं करता है, यह यूआई के लिए गुणों का एक गुच्छा है।

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

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

  4. DDD में, सेवाएं विशेष रूप से उस स्थिति के लिए होती हैं जब आपके पास एक ऑपरेशन होता है जो किसी भी कुल रूट से ठीक से संबंधित नहीं होता है । आपको यहां सावधान रहना होगा, क्योंकि अक्सर एक सेवा की आवश्यकता का मतलब यह हो सकता है कि आपने सही जड़ों का उपयोग नहीं किया। लेकिन यह मानते हुए कि, एक सेवा का उपयोग कई जड़ों में परिचालन को समन्वित करने के लिए किया जाता है, या कभी-कभी उन चिंताओं को संभालने के लिए किया जाता है जो डोमेन मॉडल को बिल्कुल भी शामिल नहीं करते हैं (जैसे, शायद, बीआई / ओएलएपी डेटाबेस को जानकारी लिखना)।

    DDD सेवा का एक उल्लेखनीय पहलू यह है कि इसे लेनदेन स्क्रिप्ट का उपयोग करने की अनुमति है । बड़े अनुप्रयोगों पर काम करते समय, आप अंततः ऐसे उदाहरणों में भाग लेने की संभावना रखते हैं, जहां टी-एसक्यूएल या पीएल / एसक्यूएल प्रक्रिया के साथ कुछ पूरा करना आसान होता है, क्योंकि यह डोमेन मॉडल के साथ उपद्रव करना है। यह ठीक है, और यह एक सेवा में है।

    यह सेवाओं की स्तरित-वास्तुकला परिभाषा से एक मौलिक प्रस्थान है। एक सर्विस लेयर डोमेन ऑब्जेक्ट्स को एनकैप्सुलेट करता है; DDD सेवा डोमेन ऑब्जेक्ट्स में जो कुछ भी नहीं है , उसका एनकाउंटर करती है और इसका कोई मतलब नहीं है।

  5. सेवा-उन्मुख वास्तुकला में, एक सेवा को व्यावसायिक क्षमता के लिए तकनीकी प्राधिकरण माना जाता है। इसका मतलब है कि यह व्यापार डेटा के एक निश्चित सबसेट का अनन्य स्वामी है और कुछ और को उस डेटा को छूने की अनुमति नहीं है - यहां तक ​​कि इसे पढ़ने के लिए भी नहीं ।

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

    तो, SOA परिभाषा के अनुसार, व्यापार तर्क का हर टुकड़ा कहीं भी सेवा के भीतर समाहित है, लेकिन फिर से, पूरी प्रणाली है । SOA में सेवाओं के घटक हो सकते हैं , और उनके पास समापन बिंदु हो सकते हैं , लेकिन किसी भी कोड को किसी सेवा को कॉल करना काफी खतरनाक है क्योंकि यह मूल "S" के साथ संघर्ष करता है, जिसका अर्थ है।

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

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

कोई सही या गलत उत्तर नहीं है, केवल वही जो आपकी स्थिति पर लागू होता है।


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

2
मैं इस तथ्य से सहमत नहीं हूं कि एक पारंपरिक स्तरित वास्तुकला में, सेवा व्यापार तर्क परत का एक पर्याय है।
कोडार्ट

1
@ कोडर्ट: यह 3 स्तरीय वास्तुकला में है। मैं है 4 स्तरीय आर्किटेक्चर देखा जहां एक "अनुप्रयोग परत" प्रस्तुति और व्यापार परतों के बीच, जो कभी कभी भी एक "सेवा" परत कहा जाता है, लेकिन ईमानदारी से, केवल स्थानों मैंने आज तक देखा यह लागू किया है सफलतापूर्वक विशाल विशाल हैं एसएपी या ओरेकल की पसंद से असीम रूप से कॉन्फ़िगर-योग्य रन-योर-बिज़नेस-फॉर-यू-प्रोडक्ट्स, और मुझे नहीं लगता कि यह वास्तव में यहाँ उल्लेख के लायक था। यदि आप चाहें तो मैं एक स्पष्टीकरण जोड़ सकता हूं।
Aaronaught

1
लेकिन अगर हम 100+ लाइन कंट्रोलर लेते हैं (उदाहरण के लिए नियंत्रक उस संदेश को स्वीकार करता है - तो JSON ऑब्जेक्ट को डिसेर्बलाइज करें, सत्यापन करें, व्यावसायिक नियम लागू करें, db को सेव करें, रिजल्ट ऑब्जेक्ट को लौटाएं) और उस लॉजिक सर्विस में से किसी एक में कुछ लॉजिक ले जाएं। t जो हमें अलग-अलग इकाई की मदद करता है, उसके प्रत्येक भाग को दर्द रहित तरीके से जांचता है?
Artjom

2
@Aaronaught मैं एक बात स्पष्ट करना चाहता था कि क्या हमारे पास ORM के माध्यम से डोमेन ऑब्जेक्ट्स मैप किए गए हैं और इसमें कोई व्यावसायिक तर्क नहीं है, यह anemic डोमेन मॉडल है या नहीं?
आर्टजोम

40

आपके शीर्षक के लिए , मुझे नहीं लगता कि सवाल समझ में आता है। MVC मॉडल में डेटा और व्यावसायिक तर्क होते हैं। कहने के लिए तर्क सेवा में होना चाहिए न कि मॉडल यह कहने में है कि "यात्री को सीट पर बैठना चाहिए, कार में नहीं"।

तब फिर से, "मॉडल" शब्द एक अतिभारित शब्द है। शायद आप MVC मॉडल का मतलब नहीं था लेकिन आप डेटा ट्रांसफर ऑब्जेक्ट (DTO) अर्थ में मॉडल था। AKA एक इकाई। यह मार्टिन फॉलर के बारे में बात कर रहा है।

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

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

इस पृथक्करण का लाभ यह है कि यह दृढ़ता की परत को दूर करता है। आप JPA से JDBC (या इसके विपरीत) पर जा सकते हैं और किसी भी व्यावसायिक तर्क को बदलना नहीं पड़ेगा। यह सिर्फ डीटीओ पर निर्भर करता है, यह परवाह नहीं करता है कि कैसे उन डीटीओ को आबादी मिलती है।

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

" एक सेवा" के रूप में, बॉब मार्टिन एक वर्ग नाम रखने के खिलाफ होगा FooBarService। वह वस्तु उन्मुख नहीं है। एक सेवा क्या करती है? से संबंधित कुछ भीFooBars । यह लेबल किया जा सकता है FooBarUtils। मुझे लगता है कि वह एक सर्विस लेयर की वकालत करेगा (एक बेहतर नाम बिजनेस लॉजिक लेयर होगा) लेकिन उस लेयर के हर वर्ग का एक सार्थक नाम होगा।


2
ORM पर अपनी बात से सहमत; वे एक झूठ का प्रचार करते हैं कि आप अपनी इकाई को सीधे उनके साथ डीबी पर मैप करते हैं, जब वास्तव में एक इकाई को कई तालिकाओं में संग्रहीत किया जा सकता है।
एंडी

@ डैनियल कपलान क्या आप जानते हैं कि बॉब मार्टिन वीडियो के लिए अद्यतन लिंक क्या है?
ब्रायन मोरारी

25

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

हमें यह ही मिला:

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

हम निम्नलिखित के साथ समाप्त होते हैं:

ग्राहक -> सेवा -> डोमेन -> डेटा

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

यह सब कहने के बाद, मुझे लगता है कि मार्टिन फाउलर के कहने का यह मतलब काफी करीब है

ये सेवाएँ डोमेन मॉडल के शीर्ष पर रहती हैं और डेटा के लिए डोमेन मॉडल का उपयोग करती हैं।

नीचे दिया गया चित्र बहुत अच्छी तरह से दिखाता है:

http://martinfowler.com/eaaCatalog/serviceLayer.html

http://martinfowler.com/eaaCatalog/ServiceLayerSketch.gif


2
आपने कल ही SOAP के लिए निर्णय लिया था? क्या यह एक आवश्यकता है या क्या आपके पास कोई बेहतर विचार नहीं है?
जेन्सजी

1
REST इसे हमारी आवश्यकताओं के लिए नहीं काटेगा। SOAP या REST, इससे उत्तर पर कोई फ़र्क नहीं पड़ता है। मेरी समझ से, सेवा डोमेन लॉजिक का एक प्रवेश द्वार है।
कोडार्ट

गेटवे के साथ बिल्कुल सहमत हैं। SOAP (मानकीकृत) ब्लोटवेयर है, इसलिए मुझे पूछना पड़ा। और हाँ, प्रश्न / उत्तर पर कोई प्रभाव भी नहीं।
जेन्सजी

6
अपने आप को एक एहसान करो और अपनी सेवा परत को मार डालो। आपके ui को सीधे अपने डोमेन का उपयोग करना चाहिए। Ive ने इसे पहले देखा था और आपका डोमेन हमेशा के लिए एनीमिया dtos का एक समूह बन जाता है, अमीर मॉडल नहीं।
एंडी

: उन स्लाइड्स सेवा परत और बहुत साफ ऊपर इस ग्राफिक के बारे में विवरण को कवर slideshare.net/ShwetaGhate2/...
मार्क Juchli

9

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

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


2
व्यावसायिक तर्क के साथ एक सेवा परत के पक्ष में आपका रुख बहुत मायने रखता है, लेकिन यह अभी भी कुछ सवाल छोड़ देता है। अपनी पोस्ट में मैंने कई सम्मानजनक स्रोतों का हवाला दिया है जो सेवा परत के बारे में किसी भी व्यावसायिक तर्क के बहाने के रूप में बात करते हैं। यह आपके उत्तर के साथ सीधे विपरीत है, क्या आप शायद इस अंतर को स्पष्ट कर सकते हैं?
जीरो वेनवेल

5
मुझे लगता है कि यह वास्तव में व्यावसायिक तर्क और अन्य कारकों के प्रकार पर निर्भर करता है, जैसे कि भाषा का उपयोग किया जा रहा है। कुछ व्यावसायिक तर्क डोमेन ऑब्जेक्ट पर बहुत अच्छी तरह से फिट नहीं होते हैं। एक उदाहरण डेटाबेस से उन्हें वापस खींचने के बाद परिणामों को फ़िल्टर / सॉर्ट करना है। यह व्यावसायिक तर्क है, लेकिन यह डोमेन ऑब्जेक्ट पर कोई मतलब नहीं रखता है। मुझे लगता है कि सरल लॉजिक के लिए सेवाओं का सबसे अच्छा उपयोग किया जाता है या डोमेन पर परिणाम और तर्क को बदलना सबसे अधिक उपयोगी होता है जब यह डेटा को बचाने या ऑब्जेक्ट से डेटा की गणना करने से संबंधित होता है।
4

8

यह बताने का सबसे आसान तरीका है कि प्रोग्रामर डोमेन लॉजिक को डोमेन ऑब्जेक्ट्स में डालने से क्यों कतराते हैं, वह यह है कि वे आमतौर पर "मैं लॉजिकेशन लॉजिक कहां डालूं?" जैसी स्थिति का सामना करना पड़ता है। उदाहरण के लिए इस डोमेन ऑब्जेक्ट को लें:

public class MyEntity
{
    private int someProperty = 0;

    public int SomeProperty
    {
        get { return this.someProperty; }
        set
        {
            if(value < 0) throw new ArgumentOutOfRangeException("value");
            this.someProperty = value;
        }
    }
}

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

इसलिए लोग सत्यापन तर्क को किसी तरह की सेवा में स्थानांतरित करते हैं, जैसे कि MyEntityValidator। तब इकाई और कॉलिंग लॉजिक दोनों सत्यापन सेवा के लिए एक संदर्भ प्राप्त कर सकते हैं और इसे फिर से उपयोग कर सकते हैं।

यदि आप ऐसा नहीं करते हैं और आप अभी भी सत्यापन तर्क का उपयोग करना चाहते हैं, तो आप इसे इकाई वर्ग के स्थिर तरीकों में डालते हैं:

public class MyEntity
{
    private int someProperty = 0;

    public int SomeProperty
    {
        get { return this.someProperty; }
        set
        {
            string message;
            if(!TryValidateSomeProperty(value, out message)) 
            {
                throw new ArgumentOutOfRangeException("value", message);
            }
            this.someProperty = value;
        }
    }

    public static bool TryValidateSomeProperty(int value, out string message)
    {
        if(value < 0)
        {
            message = "Some Property cannot be negative.";
            return false;
        }
        message = string.Empty;
        return true;
    }
}

यह आपके डोमेन मॉडल को "एनीमिक" कम कर देगा, और संपत्ति के बगल में सत्यापन तर्क रखेगा, जो महान है, लेकिन मुझे नहीं लगता कि किसी को भी वास्तव में स्थिर तरीके पसंद हैं।


1
तो आपकी राय में सत्यापन के लिए सबसे अच्छा समाधान क्या है?
फ्लैशरनर

3
@Flashrunner - मेरा सत्यापन तर्क व्यापार तर्क परत में निश्चित रूप से है, लेकिन कुछ मामलों में इकाई और डेटाबेस परतों में भी नकल की जाती है। व्यावसायिक परत उपयोगकर्ता, आदि को सूचित करके इसे अच्छी तरह से संभालती है, लेकिन अन्य परतें केवल त्रुटियों / अपवादों को फेंक देती हैं और प्रोग्रामर (स्वयं) को गलत डेटा बनाने से रोकती हैं।
स्कॉट व्हिटलॉक

6

मुझे लगता है कि यदि आप मार्टिन फाउलर के एनीमिक डोमेन मॉडल लेख को पढ़ते हैं तो उत्तर स्पष्ट है ।

डोमेन मॉडल से व्यावसायिक तर्क, जो कि डोमेन है, को हटाना अनिवार्य रूप से ऑब्जेक्ट ओरिएंटेड डिज़ाइन को तोड़ रहा है।

आइए सबसे मूल वस्तु उन्मुख अवधारणा की समीक्षा करें: एक ऑब्जेक्ट डेटा और संचालन को एन्क्रिप्ट करता है। उदाहरण के लिए, किसी खाते को बंद करना एक ऑपरेशन है जिसे एक खाता वस्तु को स्वयं पर प्रदर्शन करना चाहिए; इसलिए, सेवा परत का प्रदर्शन करना एक ऑपरेशन उन्मुख वस्तु नहीं है। यह प्रक्रियात्मक है, और यह वह है जब मार्टिन फावलर का उल्लेख है जब वह एनीमिक डोमेन मॉडल के बारे में बात कर रहा है।

यदि आपके पास खाता स्तर पास होने के बजाय खाता बंद करने की सेवा परत है, तो आपके पास वास्तविक खाता वस्तु नहीं है। आपका खाता "ऑब्जेक्ट" केवल एक डेटा संरचना है। जैसा कि आप के साथ समाप्त होता है, जैसा कि मार्टिन फाउलर सुझाव देते हैं, गेटर्स और सेटर के साथ बैग का एक गुच्छा है।


1
संपादित। मुझे वास्तव में यह काफी मददगार समझ में आया और यह नहीं लगता कि यह पतन के योग्य है।
BadHorsie

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

4

आप सेवा परत में अपने व्यावसायिक तर्क को कैसे लागू करेंगे? जब आप किसी उपयोगकर्ता से भुगतान करते हैं, तो आप भुगतान करते हैं, न कि किसी संपत्ति से मूल्य घटाते हैं।

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


2

Tl; डॉस वर्जन:
मेरे अनुभव और राय कहती है कि जिन वस्तुओं का व्यावसायिक तर्क है, वे डोमेन मॉडल का हिस्सा होना चाहिए। डेटा मॉडल में संभवतः कोई तर्क नहीं होना चाहिए। सेवाओं की संभावना दो को एक साथ बाँधना चाहिए, और क्रॉस-कटिंग चिंताओं (डेटाबेस, लॉगिंग, आदि) से निपटना चाहिए। हालांकि, स्वीकृत उत्तर सबसे व्यावहारिक है।

लंबे समय तक संस्करण, जिसे दूसरों ने पसंद किया है, यह है कि "मॉडल" शब्द पर एक समीकरण है। पोस्ट डेटा मॉडल और डोमेन मॉडल के बीच स्विच करता है जैसे कि वे एक ही हैं, जो एक बहुत ही सामान्य गलती है। "सेवा" शब्द पर थोड़ा सा समीकरण भी हो सकता है।

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

यहाँ एक लंबी समस्या है कि मैं इसमें नहीं जाऊँगा, लेकिन यह है: हार्डकोर ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग का कहना है कि संबंधित ऑब्जेक्ट के बाहर कोई भी ऑब्जेक्ट के भीतर किसी संपत्ति के मूल्य को बदलने में सक्षम नहीं होना चाहिए, न ही " देखें "वस्तु के भीतर संपत्ति का मूल्य। यह केवल डेटा को पढ़ने के द्वारा कम किया जा सकता है। आप अभी भी ऐसे मुद्दों पर चल सकते हैं जब बहुत से लोग डेटा का उपयोग केवल पढ़ने के लिए भी करते हैं और आपको उस डेटा के प्रकार को बदलना होगा। यह संभव है कि सभी उपभोक्ताओं को इसे समायोजित करने के लिए बदलना होगा। यही कारण है कि, जब आप API को किसी और किसी के द्वारा उपभोग किए जाने के लिए बनाते हैं, तो आपको सार्वजनिक या संरक्षित संपत्तियों / डेटा को नहीं करने की सलाह दी जाती है; यह बहुत कारण है कि ओओपी का आविष्कार किया गया था, अंततः।

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

DDD में, सेवाएं विशेष रूप से उस स्थिति के लिए होती हैं जब आपके पास एक ऑपरेशन होता है जो किसी भी कुल रूट से ठीक से संबंधित नहीं होता है। आपको यहां सावधान रहना होगा, क्योंकि अक्सर एक सेवा की आवश्यकता का मतलब यह हो सकता है कि आपने सही जड़ों का उपयोग नहीं किया। लेकिन आपने यह मानते हुए, एक सेवा का उपयोग कई जड़ों में संचालन को समन्वित करने के लिए किया जाता है, या कभी-कभी उन चिंताओं को संभालने के लिए किया जाता है जो डोमेन मॉडल को किसी भी स्थान पर शामिल नहीं करते ...


1

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

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

आप आदर्श रूप से क्या कर सकते हैं मॉडल सेवाएं जो राज्य को बनाए रखने के लिए डोमेन मॉडल पर काम करने के लिए व्यावसायिक तर्क को शामिल करती हैं । आपको जितना संभव हो सेवाओं को डिकोड करने का प्रयास करना चाहिए।


0

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

मॉडल में एप्लिकेशन डेटा, व्यावसायिक नियम, तर्क और कार्य शामिल हैं। http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller


0

सेवा परत की अवधारणा को DDD के नजरिए से देखा जा सकता है। आरोनियोथ ने अपने उत्तर में इसका उल्लेख किया है, मैं इसे थोड़ा विस्तार से बताता हूं।

सामान्य दृष्टिकोण वहाँ एक नियंत्रक है जो ग्राहक के एक प्रकार के लिए विशिष्ट है। कहते हैं, यह एक वेब-ब्राउज़र हो सकता है, यह कुछ अन्य अनुप्रयोग हो सकता है, यह एक कार्यात्मक परीक्षण हो सकता है। अनुरोध और प्रतिक्रिया प्रारूप भिन्न हो सकते हैं। इसलिए मैं एक हेक्सागोनल वास्तुकला के उपयोग के लिए एक उपकरण के रूप में एप्लिकेशन सेवा का उपयोग करता हूं । मैं एक ठोस अनुरोध के लिए विशिष्ट बुनियादी ढांचे वर्गों को इंजेक्ट करता हूं। उदाहरण के लिए, यह है कि वेब-ब्राउज़र अनुरोधों की सेवा करने वाला मेरा नियंत्रक कैसा दिख सकता है:

class WebBroserController
{
    public function purchaseOrder()
    {
        $data = $_POST;

        $responseData =
            new PurchaseOrderApplicationService(
                new PayPalClient(),
                new OrderRepository()
            )
        ;

        $response = new HtmlView($responseData);
    }
}

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

class FunctionalTestController
{
    public function purchaseOrder()
    {
        $data = $_POST;

        $responseData =
            new PurchaseOrderApplicationService(
                new FakePayPalClient(),
                new OrderRepository(),
                $data
            )
        ;

        return new JsonData($responseData);
    }
}

इसलिए एप्लिकेशन सेवा एक ऐसा वातावरण है जिसे मैंने व्यापार-तर्क चलाने के लिए स्थापित किया है। यह वह जगह है जहां मॉडल कक्षाओं को बुलाया जाता है - एक बुनियादी ढांचे के कार्यान्वयन के अज्ञेय।

इसलिए, इस दृष्टिकोण से अपने प्रश्नों का उत्तर दें:

क्या यह नियंत्रक से तर्क निकालने और उसे एक सेवा के अंदर रखने का एक साधन है?

नहीं।

क्या यह नियंत्रक और डोमेन के बीच एक अनुबंध बनाने वाला है?

वैसे, कोई भी इसे कॉल कर सकता है।

क्या डोमेन और सेवा परत के बीच एक परत होनी चाहिए?

नहीं।


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


-2

रिकार्ड के लिए।

SRP:

  1. मॉडल = डेटा, यहां सेटर और गेटर्स जाता है।
  2. तर्क / सेवा = यहाँ निर्णय लिया जाता है।
  3. रिपॉजिटरी / डीएओ = यहां हम सूचनाओं को स्टोर या पुनः प्राप्त करते हैं।

इस स्थिति में, अगले चरण करना ठीक है:

यदि ऋण को कुछ गणना की आवश्यकता नहीं होगी:

userObject.Debt = 9999;

हालाँकि, यदि इसके लिए कुछ गणना की आवश्यकता हो तो:

userObject.Debt= UserService.CalculateDebt(userObject)

या भी

UserService.UpdateDebt(userObject)

लेकिन यह भी, अगर गणना दृढ़ता परत में की जाती है, तो ऐसी स्टोर प्रक्रिया

UserRepository.UpdateDebt(userObject)

इस स्थिति में, हम उपयोगकर्ता को डेटाबेस से पुनर्प्राप्त करना चाहते हैं और फिर ऋण को अद्यतन करना चाहते हैं, हमें इसे कई चरणों में करना चाहिए (वास्तव में, दो) और इसे किसी सेवा के कार्य में लपेटने / अतिक्रमण करने की आवश्यकता नहीं है।

User userObject=UserRepository.GetUserByName(somename);
UserService.UpdateDebt(userObject)

और अगर इसे इसे स्टोर करने की आवश्यकता है, तो हम एक तीसरा चरण जोड़ सकते हैं

User userObject=UserRepository.GetUserByName(somename);
UserService.UpdateDebt(userObject)
UserRepository.Save(userobject);

प्रस्तावित समाधान के बारे में

क) हमें अंतिम-डेवलपर को एक फ़ंक्शन में इनकैप्सुलेट करने के बजाय कुछ लिखने से डरना नहीं चाहिए।

b) और इंटरफ़ेस के बारे में, कुछ डेवलपर्स इंटरफ़ेस से प्यार करते हैं और वे ठीक हैं लेकिन कई मामलों में, उन्हें बिल्कुल भी ज़रूरत नहीं है।

ग) एक सेवा का लक्ष्य बिना विशेषताओं के एक बनाना है, मुख्यतः क्योंकि हम साझा / स्टेटिक कार्यों का उपयोग कर सकते हैं। यूनिट टेस्ट करना भी आसान है।


यह पूछे गए प्रश्न का उत्तर कैसे देता है: "व्यावसायिक तर्क एक सेवा में होना चाहिए, एक मॉडल में नहीं"?
सूक्ति

3
किस तरह की सजा है "We shouldn't be afraid to left the end-developer to write a couple of instead of encapsulate it in a function."? मैं केवल लुईस ब्लैक को उद्धृत कर सकता हूं" अगर यह मेरे घोड़े के लिए नहीं होता तो मैं कॉलेज में खर्च नहीं करता। "
मालाची
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.