DDD OOP से मिलता है: ऑब्जेक्ट-ओरिएंटेड रिपॉजिटरी को कैसे लागू किया जाए?


12

DDD रिपॉजिटरी का एक विशिष्ट कार्यान्वयन बहुत OO नहीं दिखता है, उदाहरण के लिए एक save()विधि:

package com.example.domain;

public class Product {  /* public attributes for brevity */
    public String name;
    public Double price;
}

public interface ProductRepo {
    void save(Product product);
} 

इन्फ्रास्ट्रक्चर हिस्सा:

package com.example.infrastructure;
// imports...

public class JdbcProductRepo implements ProductRepo {
    private JdbcTemplate = ...

    public void save(Product product) {
        JdbcTemplate.update("INSERT INTO product (name, price) VALUES (?, ?)", 
            product.name, product.price);
    }
} 

इस तरह के एक इंटरफ़ेस से Productएनेमिक मॉडल होने की उम्मीद है , कम से कम गेटर्स के साथ।

दूसरी ओर, OOP का कहना है कि एक Productवस्तु को पता होना चाहिए कि खुद को कैसे बचाया जाए।

package com.example.domain;

public class Product {
    private String name;
    private Double price;

    void save() {
        // save the product
        // ???
    }
}

बात यह है कि, जब Productखुद को बचाना जानता है, तो इसका मतलब है कि इन्फ्रास्ट्रक्चर कोड डोमेन कोड से अलग नहीं है।

हो सकता है कि हम बचत को किसी अन्य वस्तु में सौंप सकें:

package com.example.domain;

public class Product {
    private String name;
    private Double price;

    void save(Storage storage) {
        storage
            .with("name", this.name)
            .with("price", this.price)
            .save();
    }
}

public interface Storage {
    Storage with(String name, Object value);
    void save();
}

इन्फ्रास्ट्रक्चर हिस्सा:

package com.example.infrastructure;
// imports...

public class JdbcProductRepo implements ProductRepo {        
    public void save(Product product) {
        product.save(new JdbcStorage());
    }
}

class JdbcStorage implements Storage {
    private final JdbcTemplate = ...
    private final Map<String, Object> attrs = new HashMap<>();

    private final String tableName;

    public JdbcStorage(String tableName) {
        this.tableName = tableName;
    }

    public Storage with(String name, Object value) {
        attrs.put(name, value);
    }
    public void save() {
        JdbcTemplate.update("INSERT INTO " + tableName + " (name, price) VALUES (?, ?)", 
            attrs.get("name"), attrs.get("price"));
    }
}

इसे प्राप्त करने के लिए सबसे अच्छा तरीका क्या है? क्या वस्तु-उन्मुख भंडार को लागू करना संभव है?


6
OOP का कहना है कि एक उत्पाद वस्तु को खुद को बचाने का तरीका पता होना चाहिए - मुझे यकीन नहीं है कि यह वास्तव में सही है ... OOP वास्तव में यह निर्धारित नहीं करता है, यह एक डिज़ाइन / पैटर्न समस्या (जो कि DDD / जो कुछ भी है, आपको अधिक है)
-उपयोग

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

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

1
@jleach आप सही कह रहे हैं, OOP की हमारी निस्संकोचता अलग है, मेरे लिए गेटर्स + सेटर कोई OOP नहीं हैं, अन्यथा मेरे सवाल का कोई मतलब नहीं था। वैसे भी धन्यवाद! :-)
ttulka

1
यहाँ मेरी बात के बारे में एक लेख है: martinfowler.com/bliki/AnemicDomainModel.html मैं सभी मामलों में फिर से एनीमिक मॉडल नहीं हूँ, उदाहरण के लिए यह कार्यात्मक प्रोग्रामिंग के लिए एक अच्छी रणनीति है। सिर्फ OOP नहीं।
ttulka

जवाबों:


7

आप ने लिखा

दूसरी ओर, OOP का कहना है कि एक उत्पाद वस्तु को पता होना चाहिए कि खुद को कैसे बचाया जाए

और एक टिप्पणी में

... इसके साथ किए गए सभी ऑपरेशन के लिए जिम्मेदार होना चाहिए

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

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

हालाँकि, जैसे ही आपका आवेदन वास्तविक व्यावसायिक कार्यों का समर्थन करता है, जैसे उत्पादों को खरीदना या बेचना, उन्हें स्टॉक में रखना और उनका प्रबंधन करना, या उनके लिए करों की गणना करना, यह काफी आम है कि आप उन ऑपरेशनों की खोज करना शुरू कर देते हैं जिन्हें एक Productकक्षा में समझदारी से रखा जा सकता है । उदाहरण के लिए, एक ऑपरेशन हो सकता है CalcTotalPrice(int noOfItems)जो खाते में वॉल्यूम छूट लेते समय एक निश्चित उत्पाद के `एन आइटम के लिए मूल्य की गणना करता है।

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


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

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

1
मैं मानता हूं कि दृढ़ता आमतौर पर डोमेन संचालन का हिस्सा नहीं है, हालांकि इसे उस वस्तु के अंदर "वास्तविक" डोमेन संचालन का हिस्सा होना चाहिए, जिसे इसकी आवश्यकता है। उदाहरण के लिए Account.transfer(amount)स्थानांतरण जारी रहना चाहिए। यह कैसे होता है कि वस्तु की जिम्मेदारी है, कुछ बाहरी संस्था की नहीं। दूसरी ओर वस्तु का प्रदर्शन आमतौर पर एक डोमेन ऑपरेशन है! आवश्यकताओं को आमतौर पर महान विवरण में वर्णित किया जाता है कि सामान कैसे दिखना चाहिए। यह परियोजना के सदस्यों, व्यापार या अन्यथा के बीच भाषा का हिस्सा है।
रॉबर्ट ब्रुटिगम 19

@ RobertBräutigam: Account.transferआमतौर पर क्लासिक में दो खाता ऑब्जेक्ट और कार्य ऑब्जेक्ट की एक इकाई शामिल होती है। ट्रांसेक्शनल प्रिस्टेंट ऑपरेशन तब बाद का हिस्सा हो सकता है (संबंधित रिपॉजिट के लिए कॉल के साथ टॉगल), इसलिए यह "ट्रांसफर" विधि से बाहर रहता है। इस तरह, Accountदृढ़ता-अज्ञानी रह सकते हैं। मैं यह नहीं कह रहा हूं कि यह आपके लिए आवश्यक समाधान से बेहतर है, लेकिन आपका भी कई संभावित दृष्टिकोणों में से एक है।
डॉक्टर ब्राउन

1
@ RobertBräutigam बहुत यकीन है कि आप वस्तु और मेज के बीच संबंध के बारे में बहुत सोच रहे हैं। स्मृति में सभी के लिए एक राज्य के रूप में वस्तु के बारे में सोचो। अपने खाते की वस्तुओं में स्थानान्तरण करने के बाद, आपको नई स्थिति वाली वस्तुओं के साथ छोड़ दिया जाएगा। यह वही है जिसे आप जारी रखना चाहते हैं, और सौभाग्य से खाता ऑब्जेक्ट आपको उनके राज्य के बारे में बताने का एक तरीका प्रदान करते हैं। इसका मतलब यह नहीं है कि उनके राज्य को डेटाबेस में तालिकाओं के बराबर होना चाहिए - यानी हस्तांतरित राशि एक ऐसी वस्तु हो सकती है जिसमें कच्ची राशि और मुद्रा शामिल हो।
स्टीव चामिलार्ड 19

5

ट्रम्प सिद्धांत का अभ्यास करें।

अनुभव हमें सिखाता है कि Product.Save () बहुत सारी समस्याओं की ओर ले जाता है। उन समस्याओं के आसपास जाने के लिए हमने रिपॉजिटरी पैटर्न का आविष्कार किया।

यकीन है कि यह उत्पाद डेटा को छिपाने के OOP नियम को तोड़ता है। लेकिन यह अच्छी तरह से काम करता है।

सुसंगत नियमों का एक सेट बनाने के लिए बहुत कठिन है जो कुछ सामान्य से अच्छे नियमों को बनाने के लिए है।


3

DDD OOP से मिलता है

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

दूसरी ओर, OOP का कहना है कि एक उत्पाद वस्तु को पता होना चाहिए कि खुद को कैसे बचाया जाए।

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

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

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

हो सकता है कि हम बचत को किसी अन्य वस्तु में सौंप सकें:

यह निश्चित रूप से काम करता है - आपका लगातार भंडारण प्रभावी रूप से कॉलबैक बन जाता है। मैं शायद इंटरफ़ेस को सरल बनाऊंगा:

interface ProductStorage {
    onProduct(String name, double price);
}

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

यह दृष्टिकोण - कॉलबैक के माध्यम से डेटा पास करना, टीडीडी में मोक्स के विकास में महत्वपूर्ण भूमिका निभाई ।

ध्यान दें कि कॉल बैक करने के लिए जानकारी पास करना सभी समान प्रतिबंधों की जानकारी है जो किसी क्वेरी से जानकारी वापस करते समय - आपको अपने डेटा संरचनाओं की परस्पर-योग्य प्रतियों के आसपास से गुजरना नहीं चाहिए।

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

मैं डीडीडी को एक ओओपी तकनीक के रूप में समझता हूं और इसलिए मैं उस विरोधाभास को पूरी तरह से समझना चाहता हूं।

एक बात ध्यान में रखनी चाहिए - ब्लू बुक पंद्रह साल पहले लिखी गई थी, जब जावा 1.4 पृथ्वी पर घूमता था। विशेष रूप से, पुस्तक जावा जेनेटिक्स से पहले की है - हमारे पास अभी बहुत अधिक तकनीक उपलब्ध हैं, जब इवांस अपने विचारों को विकसित कर रहे थे।


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

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

1
"यह दृष्टिकोण ब्लू बुक में वर्णित इवांस के लिए थोड़ा सा विपरीत है" - इसलिए सभी के बाद कुछ तनाव है :-) यह वास्तव में मेरे सवाल का बिंदु था, मैं डीडीडी को एक ओओपी तकनीक के रूप में समझता हूं और इसलिए मैं चाहता हूं पूरी तरह से समझते हैं कि विरोधाभास प्रतीत होता है।
ttulka

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

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

1

बहुत अच्छी टिप्पणियों, मैं पूरी तरह से उन पर आपके साथ सहमत हूं। यहां इस विषय पर मेरा (सुधार: स्लाइड केवल) की बात है: ऑब्जेक्ट-ओरिएंटेड डोमेन-ड्रिवेन डिज़ाइन

संक्षिप्त उत्तर: नहीं। आपके आवेदन में ऐसी कोई वस्तु नहीं होनी चाहिए जो विशुद्ध रूप से तकनीकी हो और जिसकी कोई डोमेन-प्रासंगिकता न हो। यह एक लेखांकन अनुप्रयोग में लॉगिंग ढांचे को लागू करने जैसा है।

आपका Storageइंटरफ़ेस उदाहरण एक उत्कृष्ट एक है, यह मानते हुए कि Storageकुछ बाहरी रूपरेखा पर विचार किया जाता है, भले ही आप इसे लिखें।

इसके अलावा, save()किसी ऑब्जेक्ट में केवल तभी अनुमति दी जानी चाहिए जब वह डोमेन ("भाषा") का हिस्सा हो। उदाहरण के लिए Accountमुझे कॉल करने के बाद स्पष्ट रूप से "सेव" करने की आवश्यकता नहीं होनी चाहिए transfer(amount)। मुझे सही उम्मीद करनी चाहिए कि व्यावसायिक फ़ंक्शन transfer()मेरे स्थानांतरण को जारी रखेगा।

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


क्या आपकी बात कहीं देखने लायक है? (मुझे लगता है कि लिंक के नीचे केवल स्लाइड हैं)। धन्यवाद!
ttulka

मेरे पास केवल बात की एक जर्मन रिकॉर्डिंग है, यहाँ: javadevguy.wordpress.com/2018/11/26/…
रॉबर्ट Brututigam

बड़ी अच्छी बात! (सौभाग्य से मैं जर्मन बोलता हूं)। मुझे लगता है कि आपका पूरा ब्लॉग पढ़ने लायक है ... आपके काम के लिए धन्यवाद!
ttulka

बहुत आनंदमय स्लाइडर रॉबर्ट। मुझे यह बहुत निराशाजनक लगा लेकिन मुझे यह महसूस हुआ कि अंत में एन्कैप्सुलेशन और LoD को नहीं तोड़ने के लिए संबोधित समाधानों में से कई डोमेन ऑब्जेक्ट को बहुत अधिक जिम्मेदारियां देने पर आधारित हैं: मुद्रण, क्रमांकन, यूआई स्वरूपण, आदि। t जो डोमेन और तकनीकी (कार्यान्वयन विवरण) के बीच युग्मन को बढ़ाता है? उदाहरण के लिए, AccountNumber अपाचे विकेट एपीआई के साथ मिलकर। या जोसन ऑब्जेक्ट के साथ खाता है? क्या आपको लगता है कि यह एक युग्मन के लायक है?
Laiv

@Laiv आपके प्रश्न का व्याकरण बताता है कि व्यावसायिक कार्यों को लागू करने के लिए प्रौद्योगिकी का उपयोग करने में कुछ गड़बड़ है? इसे इस तरह से रखें: यह डोमेन और प्रौद्योगिकी के बीच युग्मन नहीं है जो समस्या है, यह विभिन्न अमूर्त स्तरों के बीच युग्मन है। उदाहरण के लिए पता AccountNumber होना चाहिए कि यह एक के रूप में प्रतिनिधित्व किया जा सकता है TextField। यदि अन्य (जैसे "दृश्य") को यह पता होगा, कि युग्मन मौजूद नहीं होना चाहिए, क्योंकि उस घटक को यह जानना आवश्यक है कि AccountNumberइसमें क्या शामिल हैं, अर्थात आंतरिक।
राबर्ट ब्राटिगैम

1

शायद हम बचत को किसी अन्य वस्तु में सौंप सकते हैं

खेतों का ज्ञान अनावश्यक रूप से फैलाने से बचें। एक व्यक्ति के क्षेत्र के बारे में जितनी अधिक चीजें पता होती हैं, उतना ही मुश्किल होता है कि वह किसी क्षेत्र को जोड़ना या हटाना मुश्किल हो जाता है:

public class Product {
    private String name;
    private Double price;

    void save(Storage storage) {
        storage.save( toString() );
    }
}

यदि आप लॉग फ़ाइल या डेटाबेस या दोनों में बचत कर रहे हैं तो यहां उत्पाद का कोई पता नहीं है। यदि आपके पास 4 या 40 क्षेत्र हैं, तो यहां सेव विधि का कोई पता नहीं है। यह शिथिल युग्मित है। ये अच्छी बात है।

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

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


यह वास्तव में मेरे प्रश्न में पोस्ट किया गया कोड है, है ना? मैंने a का उपयोग किया Map, आपने a Stringया a का प्रस्ताव दिया List। लेकिन, जैसा कि @VoiceOfUnreason ने अपने उत्तर में उल्लेख किया है, युग्मन अभी भी है, बस स्पष्ट नहीं है। किसी डेटाबेस या लॉग फ़ाइल दोनों को सहेजने के लिए उत्पाद की डेटा संरचना को जानना अभी भी अनावश्यक है, कम से कम किसी ऑब्जेक्ट के रूप में वापस पढ़ने पर।
ttulka

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


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

यह एक गलत धारणा है। कंपाइलर लॉग फ़ाइल या DB की जाँच नहीं कर सकता है। यह सब जाँच रहा है यदि एक कोड फ़ाइल किसी अन्य कोड फ़ाइल के अनुरूप है जो लॉग फ़ाइल या DB के अनुरूप होने की गारंटी नहीं है।
candied_orange

0

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

इस विषय पर अधिक जानकारी के लिए, मैं महान पुस्तक की सलाह देता हूं: स्कॉट मिलेट और निक ट्यून द्वारा "पैटर्न, सिद्धांत और डोमेन-संचालित डिज़ाइन के अभ्यास"।

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