परिस्थिति
इससे पहले शाम को मैंने 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;
}
}
निष्कर्ष
सभी एक साथ बहुत कुछ यहां नहीं बदले हैं: नियंत्रक से कोड सेवा परत में स्थानांतरित हो गया है (जो एक अच्छी बात है, इसलिए इस दृष्टिकोण के लिए एक उल्टा है)। हालाँकि ऐसा नहीं लगता है कि इसका मेरे मूल उत्तर से कोई लेना-देना था।
मुझे लगता है कि डिजाइन पैटर्न दिशा-निर्देश हैं, जब भी संभव हो लागू करने के लिए पत्थर में निर्धारित नियम नहीं। फिर भी मुझे सेवा परत का एक निश्चित विवरण नहीं मिला है और इसे कैसे माना जाना चाहिए।
क्या यह नियंत्रक से तर्क निकालने और उसे एक सेवा के अंदर रखने का एक साधन है?
क्या यह नियंत्रक और डोमेन के बीच एक अनुबंध बनाने वाला है?
क्या डोमेन और सेवा परत के बीच एक परत होनी चाहिए?
और, अंतिम लेकिन कम से कम नहीं: मूल टिप्पणी के बाद
व्यावसायिक तर्क वास्तव में एक सेवा में होना चाहिए। किसी मॉडल में नहीं।
क्या ये सही है?
- मैं मॉडल के बजाय किसी सेवा में अपने व्यावसायिक तर्क का परिचय कैसे दूंगा?