एक `कर्मचारी` वर्ग को कैसे डिज़ाइन किया जाना चाहिए?


11

मैं कर्मचारियों के प्रबंधन के लिए एक कार्यक्रम बनाने की कोशिश कर रहा हूं। हालाँकि, मैं यह पता नहीं लगा सकता कि Employeeकक्षा को कैसे डिज़ाइन किया जाए । मेरा लक्ष्य किसी Employeeऑब्जेक्ट का उपयोग करके डेटाबेस पर कर्मचारी डेटा बनाने और हेरफेर करने में सक्षम होना है ।

बुनियादी कार्यान्वयन जिसे मैंने सोचा था, यह सरल था:

class Employee
{
    // Employee data (let's say, dozens of properties).

    Employee() {}
    Create() {}
    Update() {}
    Delete() {}
}

इस कार्यान्वयन का उपयोग करते हुए, मुझे कई मुद्दों का सामना करना पड़ा।

  1. IDएक कर्मचारी की तो अगर मैं एक नए कर्मचारी वर्णन करने के लिए वस्तु का उपयोग करें, डेटाबेस द्वारा दिया जाता है, वहाँ कोई नहीं होगा IDअभी तक स्टोर करने के लिए, जबकि एक वस्तु एक मौजूदा कर्मचारी का प्रतिनिधित्व करेंगे एक है ID। इसलिए मेरे पास एक संपत्ति है जो कभी-कभी वस्तु का वर्णन करती है और कभी-कभी ऐसा नहीं करती है (जो यह संकेत दे सकती है कि हम SRP का उल्लंघन करते हैं ? चूंकि हम नए और मौजूदा कर्मचारियों का प्रतिनिधित्व करने के लिए एक ही वर्ग का उपयोग करते हैं ...)।
  2. Createविधि, डेटाबेस पर एक कर्मचारी बनाने के लिए माना जाता है, जबकि है Updateऔर Deleteएक मौजूदा कर्मचारी (फिर से, पर कार्य करने की अपेक्षा की जाती SRP ...)।
  3. Parameters क्रिएट ’विधि के लिए क्या पैरामीटर होना चाहिए? कर्मचारी के सभी डेटा या शायद एक Employeeवस्तु के लिए दर्जनों पैरामीटर ?
  4. क्या कक्षा अपरिवर्तनीय होनी चाहिए?
  5. कैसे होगा Updateकाम? क्या यह गुण लेगा और डेटाबेस को अपडेट करेगा? या शायद यह दो वस्तुओं को ले जाएगा - एक "पुराना" एक और एक "नया" एक, और डेटाबेस को उनके बीच के अंतर से अपडेट करें? (मुझे लगता है कि उत्तर को कक्षा की उत्परिवर्तन के बारे में उत्तर के साथ करना होगा)।
  6. निर्माणकर्ता की जिम्मेदारी क्या होगी? इसके लिए क्या पैरामीटर होंगे? क्या यह एक idपैरामीटर का उपयोग करके डेटाबेस से कर्मचारी डेटा प्राप्त करेगा और उन्हें गुणों को पॉप्युलेट करेगा?

इसलिए, जैसा कि आप देख सकते हैं, मेरे सिर में थोड़ी गड़बड़ है, और मैं बहुत भ्रमित हूं। क्या आप मुझे यह समझने में मदद कर सकते हैं कि इस तरह की कक्षा कैसे दिखनी चाहिए?

कृपया ध्यान दें कि मुझे राय नहीं चाहिए, बस यह समझने के लिए कि इस तरह के अक्सर उपयोग किए जाने वाले वर्ग को कैसे डिज़ाइन किया जाता है।


3
एसआरपी का आपका कड़ा उल्लंघन है कि आपके पास एक वर्ग है जो एक इकाई का प्रतिनिधित्व करता है और सीआरयूडी तर्क के लिए जिम्मेदार है। यदि आप इसे अलग करते हैं, कि सीआरयूडी संचालन और इकाई संरचना अलग-अलग कक्षाएं होंगी, तो 1. और 2. एसआरपी नहीं तोड़ेंगे। 3.Employee अमूर्तता प्रदान करने के लिए एक वस्तु लेनी चाहिए , प्रश्न 4. और 5. आम तौर पर अचूक होते हैं, आपकी आवश्यकताओं पर निर्भर करते हैं, और यदि आप संरचना और सीआरयूडी के संचालन को दो वर्गों में अलग करते हैं, तो यह काफी स्पष्ट है, Employeeडेटा का निर्माता डेटा प्राप्त नहीं कर सकता है db से और अधिक, ताकि उत्तर ६.
एंडी

@DavidPacker - धन्यवाद। क्या आप इसे एक उत्तर में रख सकते हैं?
सिपो

5
मत करो, मैं दोहराता हूं, अपने ctor को डेटाबेस तक नहीं पहुंचाएं। इतना कसकर जोड़े डेटाबेस के लिए कोड और चीजों को परीक्षण करने के लिए भगवान कठिन बनाता है (यहां तक ​​कि मैनुअल परीक्षण कठिन हो जाता है)। रिपॉजिटरी पैटर्न में देखें। एक सेकंड के लिए इसके बारे में सोचें, क्या आप Updateएक कर्मचारी हैं, या क्या आप एक कर्मचारी रिकॉर्ड अपडेट करते हैं? क्या आप Employee.Delete(), या करता है Boss.Fire(employee)?
रबरडुक

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

जवाबों:


10

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


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

संक्षेप में, एक सक्रिय रिकॉर्ड एक वस्तु है, जो:

  • आपके डोमेन में किसी ऑब्जेक्ट का प्रतिनिधित्व करता है (व्यावसायिक नियमों को शामिल करता है, जानता है कि ऑब्जेक्ट पर कुछ कार्यों को कैसे प्रबंधित किया जाए, जैसे कि आप उपयोगकर्ता नाम बदल सकते हैं और आगे नहीं कर सकते हैं),
  • इकाई को पुनः प्राप्त करना, अद्यतन करना, सहेजना और हटाना जानता है।

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

लेकिन इकाई प्रतिनिधित्व और CRUD तर्क को दो (या अधिक) वर्गों में विभाजित करके डिज़ाइन को ठीक करना बहुत सरल है।

यह वही है जो आपका डिज़ाइन अब जैसा दिखता है:

  • Employee- कर्मचारी संरचना (इसकी विशेषताओं) और इकाई को संशोधित करने के तरीके (यदि आप परिवर्तनशील तरीके से जाने का निर्णय लेते हैं) के बारे में जानकारी शामिल है Employee, इकाई के लिए CRUD तर्क Employeeहैं, वस्तुओं की एक सूची वापस कर सकते हैं , Employeeजब आप चाहते हैं तब एक वस्तु को स्वीकार करता है। एक कर्मचारी को अपडेट करें, Employeeजैसे कि एक विधि के माध्यम से एकल वापस कर सकते हैंgetSingleById(id : string) : Employee

वाह, वर्ग बहुत बड़ा लगता है।

यह प्रस्तावित समाधान होगा:

  • Employee - कर्मचारी संरचना (इसकी विशेषताओं) और इकाई को संशोधित करने के तरीकों के बारे में जानकारी शामिल है (यदि आप पारस्परिक तरीके से जाने का निर्णय लेते हैं)
  • EmployeeRepository- इसमें Employeeइकाई के लिए CRUD तर्क होता है , Employeeवस्तुओं की एक सूची वापस कर सकता है , एक Employeeवस्तु को स्वीकार करता है जब आप एक कर्मचारी को अपडेट करना चाहते हैं, Employeeएक विधि के माध्यम से एकल वापस कर सकते हैं जैसेgetSingleById(id : string) : Employee

क्या आपने चिंताओं को अलग करने के बारे में सुना है ? नहीं, अब आप करेंगे। यह सिंगल रिस्पॉन्सिबिलिटी सिद्धांत का कम सख्त संस्करण है, जो कहता है कि एक वर्ग को वास्तव में केवल एक जिम्मेदारी होनी चाहिए, या अंकल बॉब के रूप में:

एक मॉड्यूल को बदलने का एक और केवल एक कारण होना चाहिए।

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

रिपॉजिटरी पैटर्न के बारे में बहुत अच्छा है, यह न केवल डेटाबेस के बीच एक मध्य परत प्रदान करने के लिए एक अमूर्त के रूप में कार्य करता है (जो कुछ भी हो सकता है, फ़ाइल, noSQL, SQL, ऑब्जेक्ट-ओरिएंटेड), लेकिन इसके लिए एक ठोस होने की भी आवश्यकता नहीं है कक्षा। कई OO भाषाओं में, आप इंटरफ़ेस को वास्तविक interface(या शुद्ध वर्चुअल विधि के साथ एक वर्ग यदि आप C ++ में हैं) के रूप में परिभाषित कर सकते हैं और फिर कई कार्यान्वयन कर सकते हैं।

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

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

प्रश्न 6: तो नवनिर्मित Employeeवर्ग में निर्माणकर्ता को क्या करना चाहिए ? यह आसान है। यह तर्क लेना चाहिए, जांच लें कि क्या वे वैध हैं (जैसे कि एक उम्र नकारात्मक नहीं होनी चाहिए या नाम खाली नहीं होना चाहिए), डेटा अमान्य होने पर एक त्रुटि उठाएं और यदि मान्यता पारित हुई तो निजी चर को तर्क दें इकाई का। यह अब डेटाबेस के साथ संवाद नहीं कर सकता है, क्योंकि इसे बस यह पता नहीं है कि इसे कैसे करना है।


प्रश्न 4: सभी पर उत्तर नहीं दिया जा सकता है, आम तौर पर नहीं, क्योंकि उत्तर बहुत हद तक इस बात पर निर्भर करता है कि आपको वास्तव में क्या चाहिए।


प्रश्न 5: अब जब कि तुम दो भागों में फूला हुआ वर्ग अलग है, तो आप पर सीधे कई अद्यतन तरीकों हो सकता है Employeeवर्ग, जैसे changeUsername, markAsDeceased, के डेटा में हेरफेर होगा जो Employeeवर्ग केवल रैम में और उसके बाद आप इस तरह के रूप में एक विधि को लागू कर सकता registerDirtyसे रिपॉजिटरी वर्ग को कार्य पैटर्न की इकाई , जिसके माध्यम से आप रिपॉजिटरी को बताएंगे कि इस ऑब्जेक्ट ने गुण बदल दिए हैं और आपको commitविधि को कॉल करने के बाद अपडेट करने की आवश्यकता होगी ।

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


प्रश्न 3: यदि आप यूनिट ऑफ़ वर्क पैटर्न के साथ जाने का निर्णय लेते हैं, तो createविधि अब होगी registerNew। यदि आप नहीं करते हैं, तो मैं शायद इसके saveबजाय कहूंगा । एक रिपॉजिटरी का लक्ष्य डोमेन और डेटा लेयर के बीच एक अमूर्तता प्रदान करना है, इस वजह से मैं आपको सलाह दूंगा कि यह विधि (हो registerNewया हो save) Employeeऑब्जेक्ट को स्वीकार करती है और यह रिपॉजिटरी इंटरफ़ेस को लागू करने वाली कक्षाओं तक है, जो विशेषताएँ वे इकाई से बाहर निकालने का फैसला करते हैं। संपूर्ण ऑब्जेक्ट को पास करना बेहतर है, इसलिए आपको कई वैकल्पिक मापदंडों की आवश्यकता नहीं है।


प्रश्न 2: दोनों विधियाँ अब रिपॉजिटरी इंटरफ़ेस का एक हिस्सा होंगी और वे एकल जिम्मेदारी सिद्धांत का उल्लंघन नहीं करती हैं। रिपॉजिटरी की जिम्मेदारी Employeeवस्तुओं के लिए सीआरयूडी संचालन प्रदान करना है, यही वह करता है (इसके अलावा पढ़ें और हटाएं, सीआरयूडी क्रिएट और अपडेट दोनों में अनुवाद करता है)। जाहिर है, आप आगे EmployeeUpdateRepositoryऔर पीछे होने से भी रिपॉजिटरी को विभाजित कर सकते हैं, लेकिन इसकी शायद ही कभी आवश्यकता होती है और एक एकल कार्यान्वयन में आमतौर पर सभी सीआरयूडी ऑपरेशन शामिल हो सकते हैं।


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

एक इकाई के पास एक आईडी है या नहीं, आमतौर पर इससे कोई फर्क नहीं पड़ता कि आप उस पर कुछ दृढ़ता-तर्क करने की कोशिश करते हैं। जैसा कि प्रश्न 5 के उत्तर में उल्लेख किया गया है, यह पता लगाने के लिए रिपॉजिटरी की ज़िम्मेदारी है कि आप किसी ऐसी इकाई को बचाने की कोशिश नहीं कर रहे हैं जो पहले से ही बच गई है या बिना आईडी के किसी इकाई को अपडेट करने की कोशिश कर रही है।


महत्वपूर्ण लेख

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


हम्म मेरे जवाब के समान है, लेकिन नहीं के रूप में 'तेज' रंगों पर डालता है
इवान

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

1
अच्छा और सारगर्भित उत्तर। चिंता के अलगाव के साथ सिर पर कील ठोकता है। और मुझे यह चेतावनी पसंद है कि एक सटीक जटिल डिजाइन और एक अच्छा समझौता के बीच बनाने के लिए महत्वपूर्ण विकल्प पिंटपॉइंट्स।
क्रिस्टोफ़

सच है, आपका जवाब बेहतर है
इवान

जब पहली बार एक नया कर्मचारी ऑब्जेक्ट बनाते हैं, तो आईडी के लिए कोई मूल्य नहीं होगा। आईडी फ़ील्ड शून्य मान के साथ छोड़ सकता है लेकिन यह कारण होगा कि कर्मचारी वस्तु अमान्य स्थिति में है ????
सुसंथा 7

2

पहले वैचारिक कर्मचारी के गुणों से युक्त एक कर्मचारी संरचना बनाएँ।

फिर मिलान तालिका संरचना के साथ एक डेटाबेस बनाएं, उदाहरण के लिए mssql कहें

फिर उस डेटाबेस के लिए एक कर्मचारी रिपॉजिटरी बनाएं जिसमें आपको आवश्यक विभिन्न CRUD ऑपरेशन के साथ EmployeeRepoMsSql।

फिर CRUD ऑपरेशन को उजागर करने के लिए एक IEmployeeRepo इंटरफ़ेस बनाएं

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

जब यह आईडी से शंकू करता है तो मैं आपको एक GUID का उपयोग करने का सुझाव देता हूं, जिसे कंस्ट्रक्टर में कोड के माध्यम से उत्पन्न किया जा सकता है।

मौजूदा ऑब्जेक्ट के साथ काम करने के लिए आपका कोड उनके अपडेट विधि को कॉल करने से पहले रिपॉजिटरी के माध्यम से डेटाबेस से उन्हें पुनः प्राप्त कर सकता है।

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

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

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

***** उदाहरण कोड

public class Employee
{
    public string Id { get; set; }

    public string Name { get; set; }

    private IEmployeeRepo repo;

    //with the OOP approach you want the save method to be on the Employee Object
    //so you inject the IEmployeeRepo in the Employee constructor
    public Employee(IEmployeeRepo repo)
    {
        this.repo = repo;
        this.Id = Guid.NewGuid().ToString();
    }

    public bool Save()
    {
        return repo.Save(this);
    }
}

public interface IEmployeeRepo
{
    bool Save(Employee employee);

    Employee Get(string employeeId);
}

public class EmployeeRepoSql : IEmployeeRepo
{
    public Employee Get(string employeeId)
    {
        var sql = "Select * from Employee where Id=@Id";
        //more db code goes here
        Employee employee = new Employee(this);
        //populate object from datareader
        employee.Id = datareader["Id"].ToString();

    }

    public bool Save(Employee employee)
    {
        var sql = "Insert into Employee (....";
        //db logic
    }
}

public class MyADMProgram
{
    public void Main(string id)
    {
        //with ADM don't inject the repo into employee, just use it in your program
        IEmployeeRepo repo = new EmployeeRepoSql();
        var emp = repo.Get(id);

        //do business logic
        emp.Name = TextBoxNewName.Text;

        //save to DB
        repo.Save(emp);

    }
}

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

वास्तव में, इस मामले में रेपो सेवा है और फ़ंक्शन सीआरयूडी ऑपरेशन हैं।
इवान

@DavidPacker क्या आप कह रहे हैं कि एनीमिक डोमेन मॉडल एक अच्छी बात है?
कैंडिड_ऑरेंज

1
@CandiedOrange मैंने टिप्पणी में अपनी राय व्यक्त नहीं की है, लेकिन नहीं, यदि आप अपने आवेदन को उन परतों तक डाइविंग के रूप में जाने का निर्णय लेते हैं जहां एक परत केवल व्यावसायिक तर्क के लिए जिम्मेदार है, तो मैं श्री फाउलर के साथ हूं कि एक एनीमिक डोमेन मॉडल वास्तव में एक विरोधी पैटर्न है। मुझे UserUpdateएक changeUsername(User user, string newUsername)विधि के साथ एक सेवा की आवश्यकता क्यों होनी चाहिए , जब मैं सीधे changeUsernameकक्षा में विधि जोड़ सकता हूं User। उसके लिए एक सेवा बनाना एक गैर-समझदारी है।
एंडी

1
मुझे लगता है कि इस मामले में रेप को इंजेक्ट करने के लिए सिर्फ मॉडल आइडेंट इष्टतम पर CRUD तर्क को रखना है।
इवान

1

अपने डिजाइन की समीक्षा करें

आपका Employeeवास्तव में डेटाबेस में लगातार बने किसी ऑब्जेक्ट के लिए एक प्रकार का प्रॉक्सी है।

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

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

आपको ऑब्जेक्ट के लिए स्थिति का प्रबंधन करने की भी आवश्यकता होगी। उदाहरण के लिए:

  • जब कोई कर्मचारी अभी तक डीबी ऑब्जेक्ट के साथ लिंक या डेटा पुनर्प्राप्ति के माध्यम से लिंक नहीं किया जाता है, तो आपको हटाए गए प्रदर्शन करने में सक्षम नहीं होना चाहिए
  • डेटाबेस के साथ सिंक में ऑब्जेक्ट में कर्मचारी डेटा है या परिवर्तन किए गए हैं?

इसे ध्यान में रखते हुए, हम इसका विकल्प चुन सकते हैं:

class Employee
{
    ...
    Employee () {}       // Initialize an empty Employee
    Load(IDType ID) {}   // Load employee with known ID from the database
    bool Create() {}     // Create an new employee an set its ID 
    bool Update() {}     // Update the employee (can ID be changed?)
    bool Delete() {}     // Delete the employee (and reset ID because there's no corresponding ID. 
    bool isClean () {}   // true if ID empty or if all properties match database
}

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

आपके सवाल

  1. मुझे लगता है कि आईडी प्रॉपर्टी एसआरपी का उल्लंघन नहीं करती है। इसकी एकल जिम्मेदारी एक डेटाबेस ऑब्जेक्ट को संदर्भित करना है।

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

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

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

  3. मैं दर्जन भर मापदंडों को नहीं जोड़ूंगा Create(), क्योंकि व्यापारिक वस्तुएं विकसित हो सकती हैं और यह सब बनाए रखना बहुत मुश्किल है। और कोड अपठनीय हो जाएगा। आपके पास यहां 2 विकल्प हैं: या तो मापदंडों का एक न्यूनतम सेट (4 से अधिक नहीं) पास करना जो डेटाबेस में एक कर्मचारी बनाने और अद्यतन के माध्यम से शेष परिवर्तन करने के लिए बिल्कुल आवश्यक हैं, या आप एक वस्तु पास करते हैं। वैसे, आपके डिजाइन में मैं समझता हूं कि आपने पहले ही चुना है my_employee.Create():।

  4. क्या कक्षा अपरिवर्तनीय होनी चाहिए? ऊपर चर्चा देखें: अपने मूल डिजाइन सं। मैं एक अपरिवर्तनीय आईडी का विकल्प चुनूंगा लेकिन एक अपरिवर्तनीय कर्मचारी का नहीं। एक कर्मचारी वास्तविक जीवन (नई नौकरी की स्थिति, नया पता, नई वैवाहिक स्थिति, यहां तक ​​कि नए नाम ...) में विकसित होता है। मुझे लगता है कि कम से कम व्यावसायिक तर्क परत में इस वास्तविकता को ध्यान में रखते हुए काम करना आसान और अधिक स्वाभाविक होगा।

  5. यदि आप अपडेट के लिए एक कमांड का उपयोग करने पर विचार करते हैं और वांछित बदलावों के लिए एक अलग ऑब्जेक्ट (GUI?) के लिए आप पुराने / नए दृष्टिकोण का विकल्प चुन सकते हैं। अन्य सभी मामलों में, मैं एक परिवर्तनशील वस्तु को अपडेट करने का विकल्प चुनूंगा। ध्यान दें: अपडेट डेटाबेस कोड को ट्रिगर कर सकता है ताकि आप सुनिश्चित करें कि अपडेट के बाद ऑब्जेक्ट अभी भी वास्तव में डीबी के साथ सिंक हो।

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

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