विभिन्न तर्क परतों पर इंटरफेस

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

यह शानदार है जब आप पहली बार यूआई कोड लिखते हैं, क्योंकि आपके पास एक साफ परिभाषित इंटरफ़ेस है जिसे आप भरोसा कर सकते हैं।

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

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

मुझे आशा है कि मैंने समस्या को स्पष्ट रूप से पर्याप्त समझाया है। आप इंटरफ़ेस एरोडिंग को कैसे रोकते हैं, सूचना छिपाने और encapsulation को बनाए रखने, और फिर भी विभिन्न परतों के बीच विभिन्न इंटरफ़ेस आवश्यकताओं को समायोजित करते हैं?

0
ro fr bn

9 उत्तर

यह एक क्लासिक समस्या है - अपने डोमेन मॉडल को अपने डेटाबेस मॉडल से अलग करना। इस पर हमला करने के कई तरीके हैं, यह वास्तव में मेरी राय में आपकी परियोजना के आकार पर निर्भर करता है। आप भंडार पैटर्न का उपयोग कर सकते हैं जैसा कि अन्य ने कहा है। यदि आप .NET या जावा का उपयोग कर रहे हैं तो आप NHibernate या हाइबरनेट

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

पीएस सवाल का शीर्षक थोड़ा गलत है

0
जोड़ा

आप अपने इंटरफेस को दो प्रकारों में विभाजित करना चाहते हैं, अर्थात्:

  • इंटरफेस देखें - जो इंटरफेस हैं जो आपके यूआई के साथ आपकी इंटरैक्शन निर्दिष्ट करते हैं, और
  • डेटा इंटरफेस - जो इंटरफेस हैं जो आपको अपने डेटा के साथ इंटरैक्शन निर्दिष्ट करने की अनुमति देंगे

दोनों इंटरफेस के सेट को हासिल करना और कार्यान्वित करना संभव है जैसे कि:

public class BusinessObject : IView, IData

इस तरह, आपकी डेटा परत में आपको केवल आईडीटा के इंटरफ़ेस कार्यान्वयन को देखने की आवश्यकता है, जबकि आपके यूआई में आपको केवल IView के इंटरफ़ेस कार्यान्वयन को देखने की आवश्यकता है।

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

public class BusinessObject : DomainObject

public class ViewManager where T : DomainObject

public class DataManager where T : DomainObject

यह बदले में आपके व्यावसायिक ऑब्जेक्ट को यूआई/व्यू लेयर और डेटा लेयर दोनों से अनजान रहने की अनुमति देता है।

0
जोड़ा

यह एक समाधान हो सकता है, क्योंकि यह इंटरफ़ेस को खराब नहीं करेगा। मुझे लगता है कि आपके पास इस तरह की कक्षा हो सकती है:

public class BusinessObjectRecord : BusinessObject
{
}
0
जोड़ा

इसका मतलब क्या है कि डेटा स्तर को व्यावसायिक तर्क स्तर से अवगत नहीं होना चाहिए? आप एक व्यापार वस्तु को डेटा के साथ कैसे भरेंगे?

मैं अक्सर यह करता हूं:

namespace Data
{
    public class BusinessObjectDataManager
    {
         public void SaveObject(BusinessObject object)
         {
               //Exec stored procedure
         {
    }
}
0
जोड़ा

मैं हमेशा एक अलग असेंबली बनाता हूं जिसमें निम्न शामिल हैं:

  • बहुत से छोटे इंटरफेस (आईसीआरएट रिपोजिटरी, आईआरडीड रिपोजिटरी, आईआरडलिस्टस्टीसिटरी सोचें .. सूची चालू है और उनमें से अधिकतर जेनेरिक पर भारी निर्भर करती हैं)
  • बहुत सारे कंक्रीट इंटरफेस, जैसे एक आईपीएससन रिपोजिटरी, जो इरेड रिपोजिटरी से प्राप्त होता है, आपको बिंदु मिल जाता है ..
    कुछ भी जो आप केवल छोटे इंटरफेस के साथ वर्णन नहीं कर सकते हैं, आप कंक्रीट इंटरफ़ेस में डालते हैं।
    जब तक आप अपनी ऑब्जेक्ट घोषित करने के लिए IPersonRepository का उपयोग करते हैं, तब तक आपको काम करने के लिए एक साफ, सुसंगत इंटरफ़ेस मिलता है। लेकिन किकर है, आप एक कक्षा भी बना सकते हैं जो f.x लेता है। एक आईसीआरएट रिपोजिटरी अपने कन्स्ट्रक्टर में, इसलिए कोड कुछ सचमुच फंकी सामान करने के लिए बहुत आसान हो जाएगा। व्यापार स्तर में सेवाओं के लिए इंटरफेस भी हैं।
  • अंत में मैं सभी डोमेन ऑब्जेक्ट्स को अतिरिक्त असेंबली में चिपकाता हूं, बस कोड बेस को थोड़ा क्लीनर बनाने के लिए और अधिक कमजोर युग्मित करने के लिए। इन ऑब्जेक्ट्स में कोई तर्क नहीं है, वे सभी 3+ परतों के डेटा का वर्णन करने का एक आम तरीका हैं।

Btw। डेटा स्तर को समायोजित करने के लिए आप व्यवसाय तर्क स्तर में विधियों को परिभाषित क्यों करेंगे?
डेटा स्तरीय के पास कोई व्यवसाय कारण नहीं है, यह जानने का कोई कारण नहीं होना चाहिए ..

0
जोड़ा

@ बर्फ ^^ हीट:

इसका मतलब क्या है कि डेटा स्तर को व्यावसायिक तर्क स्तर से अवगत नहीं होना चाहिए? आप डेटा के साथ एक व्यावसायिक वस्तु कैसे भरेंगे?

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

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

यूआई व्यापार स्तर में सेवा जानता है जो फिर डेटा स्तर के बारे में जानता है।

यूआई ऑब्जेक्ट्स से उपयोगकर्ताओं के डेटा इनपुट को मैप करने के लिए ज़िम्मेदार है, और डेटा स्तरीय ऑब्जेक्ट्स से डीबी में डेटा मैप करने के लिए ज़िम्मेदार है। बिजनेस टियर पूरी तरह से व्यवसाय रहता है। :)

0
जोड़ा

मैं अनाज के खिलाफ जाने की अपनी आदत जारी रखने जा रहा हूं और कहता हूं कि आपको सवाल करना चाहिए कि आप इन सभी जटिल जटिल परतों का निर्माण क्यों कर रहे हैं।

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

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

आपको किसी से अपना डेटा छिपाने की कोशिश नहीं करनी चाहिए। डेवलपर्स को यह समझने की आवश्यकता है कि वे भौतिक डेटा स्टोर के साथ कैसे और कब बातचीत कर रहे हैं।

ऑब्जेक्ट-रिलेशनल मैपर शैतान हैं। उनका उपयोग बंद करो।

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

0
जोड़ा
नहीं, मैं उन ऐप्स के बारे में बात नहीं कर रहा हूं जो कि सरल हैं। मैं जटिल एंटरप्राइज़ ऐप्स में अपने सभी व्यावसायिक तर्कों को संभालने के लिए मोटे अनाज वाली प्रोसेस लिखने और कोड को रखने के बारे में बात कर रहा हूं जो प्रोसेस को यथासंभव सरल कहता है।
जोड़ा लेखक Eric Z Beard, स्रोत
मैं नहीं देखता कि संग्रहीत प्रक्रियाओं में व्यापार तर्क कैसे चल रहा है, मामलों में मदद करता है। मैं उन्हें अच्छी यूनिट परीक्षण का समर्थन करने वाली भाषा में एक अच्छी व्यावसायिक परत में रखना पसंद करूंगा।
जोड़ा लेखक Ben Fulton, स्रोत
मुझे लगता है कि यह काम कर सकता है यदि आप जो कुछ भी कर रहे हैं वह डेटाबेस तालिका के शीर्ष पर एक स्क्रीन डाल रहा है।
जोड़ा लेखक JC., स्रोत

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

आप इन दो-इंटरफेस दृष्टिकोण को किसी भी ऑब्जेक्ट पर लागू कर सकते हैं जिसे यूआई और डेटा परतों दोनों को पारित करने की आवश्यकता है।

public class BusinessLayer : ISimpleBusiness
{}

public class Some3LayerObject : ISimpleSome3LayerObject
{}
0
जोड़ा

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

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

उदा

public class User
{
    private string name;
    private AccountStatus status;

    private User()
    {
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public AccountStatus Status
    {
        get { return status; }
    }

    public void Activate()
    {
        status = AccountStatus.Active;
    }

    public void Suspend()
    {
        status = AccountStatus.Suspended;
    }

    public static User GetById(int id)
    {
        User fetchedUser = new User();

       //Lots of database and error-checking code
       //omitted for clarity
       //...

        fetchedUser.name = (string) reader["Name"];
        fetchedUser.status = (int)reader["statusCode"] == 0 ? AccountStatus.Suspended : AccountStatus.Active;

        return fetchedUser;
    }

    public static void Save(User user)
    {
       //Code to save User's internal structure to database
       //...
    }
}

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

The second option is to have a second class that is responsible for the mapping. This has the advantage of seperating out the different concerns of business logic and persistence which can allow your design to be more testable and flexible. The challenge with this method is how to expose the name and status fields to the external class. Some options are: 1. Use reflection (which has no qualms about digging deep into your object's private parts) 2. Provide specially-named, public setters (उदा. prefix them with the word 'Private') and hope no one uses them accidentally 3. If your language suports it, make the setters internal but grant your data mapper module access. उदा. use the InternalsVisibleToAttribute in .NET 2.0 onwards or friend functions in C++

अधिक जानकारी के लिए, मैं मार्टिन फाउलर की क्लासिक पुस्तक 'एंटरटेनमेंट आर्किटेक्चर के पैटर्न' की सिफारिश करता हूं

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

0
जोड़ा