क्या अधिकांश कक्षाओं को डेटा फ़ील्ड में केवल क्लास और मेथड से अलग किया जा सकता है (यदि संभव हो तो) एक अच्छा या एक एंटी-पैटर्न?


10

उदाहरण के लिए, एक वर्ग में आमतौर पर वर्ग के सदस्य और विधियाँ होती हैं, जैसे:

public class Cat{
    private String name;
    private int weight;
    private Image image;

    public void printInfo(){
        System.out.println("Name:"+this.name+",weight:"+this.weight);
    }

    public void draw(){
        //some draw code which uses this.image
    }
}

लेकिन एकल जिम्मेदारी सिद्धांत और ओपन क्लोज्ड सिद्धांत के बारे में पढ़ने के बाद, मैं डीटीओ और हेल्पर क्लास में अलग-अलग क्लास को स्टैटिक तरीकों से ही पसंद करता हूं, जैसे:

public class CatData{
    public String name;
    public int weight;
    public Image image;
}

public class CatMethods{
    public static void printInfo(Cat cat){
        System.out.println("Name:"+cat.name+",weight:"+cat.weight);
    }

    public static void draw(Cat cat){
        //some draw code which uses cat.image
    }
}

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

मेरा प्रश्न यह है कि क्या यह एक अच्छा या एक प्रतिमान है?


15
हर जगह आँख बंद करके कुछ भी करना क्योंकि आपने एक नई अवधारणा सीखी है जो हमेशा एक विरोधी पैटर्न है।
कायमान

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

4
एक और सवाल यह साबित करता है कि एसआरपी इतनी बुरी तरह से गलत समझा गया है कि इसे प्रतिबंधित किया जाना चाहिए। सार्वजनिक क्षेत्रों के एक समूह में डेटा रखना कोई ज़िम्मेदारी नहीं है
user949300

1
@ user949300, यदि वर्ग उन क्षेत्रों के लिए जिम्मेदार है, तो उन्हें ऐप पर कहीं और ले जाने से निश्चित रूप से शून्य प्रभाव पड़ेगा। या इसे दूसरे तरीके से रखने के लिए, आपसे गलती की जाती है: वे 100% एक जिम्मेदारी हैं।
डेविड अर्नो

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

जवाबों:


10

आपने दो चरम सीमाएं ("एक चीज में निजी और सभी (शायद असंबंधित) तरीके" बनाम "सब कुछ सार्वजनिक और वस्तु के अंदर कोई विधि नहीं" दिखाया है)। IMHO अच्छा OO मॉडलिंग उनमें से कोई नहीं है , मधुर स्थान कहीं बीच में है।

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

इसलिए न तो आपको हर सदस्य को सार्वजनिक करना चाहिए, न ही आपको कक्षा के अंदर किसी वस्तु पर हर ऑपरेशन के लिए तरीकों को लागू करने की आवश्यकता है। यहाँ एक वैकल्पिक सुझाव दिया गया है:

public class Cat{
    private String name;
    private int weight;
    private Image image;

    public String getInfo(){
        return "Name:"+this.name+",weight:"+this.weight;
    }
    public Image getImage(){
        return image;
    }
}

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

मैं कल्पना कर सकता हूं कि CatDrawingControllerकौन सा उपकरण draw(और शायद कैनवस ऑब्जेक्ट प्राप्त करने के लिए निर्भरता इंजेक्शन का उपयोग करता है)। मैं एक अन्य वर्ग की भी कल्पना कर सकता हूं जो कुछ कंसोल आउटपुट और उपयोग को लागू करता है getInfo(इसलिए printInfoइस संदर्भ में अप्रचलित हो सकता है)। लेकिन इस पर समझदार निर्णय लेने के लिए, संदर्भ को जानने की आवश्यकता है और Catवर्ग वास्तव में कैसे उपयोग किया जाएगा।

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

नोट भी ऊपर (im) उत्परिवर्तन के बारे में निर्णय लेने के लिए अभी भी जगह छोड़ देता है। यदि Catवर्ग किसी भी बसने वाले व्यक्ति को उजागर नहीं करेगा, और Imageस्वयं अपरिवर्तनीय है, तो यह डिज़ाइन Catअपरिवर्तनीय बनाने की अनुमति देगा (जो डीटीओ दृष्टिकोण नहीं होगा)। लेकिन अगर आपको लगता है कि अपरिवर्तनीयता की आवश्यकता नहीं है या आपके मामले के लिए सहायक नहीं है, तो आप उस दिशा में भी जा सकते हैं।


ट्रिगर खुश downvoters, यह उबाऊ हो जाता है। यदि आपके कुछ आलोचक हैं, तो कृपया मुझे बताएं। यदि आपके पास कुछ गलतफहमी है, तो मैं स्पष्ट करूंगा।
डॉक्टर ब्राउन

जबकि मैं आम तौर पर आपके उत्तर से सहमत हूं ... मुझे लगता getInfo()है कि यह प्रश्न पूछने वाले के लिए भ्रामक हो सकता है। यह कक्षा printInfo()के उद्देश्य को पराजित करते हुए, प्रस्तुति की जिम्मेदारियों को सूक्ष्मता से मिलाता हैDrawingController
Adriano Repetti

@ AdrianoRepetti मुझे नहीं लगता कि यह उद्देश्य को हरा रहा है DrawingController। मैं सहमत हूँ कि getInfo()और printInfo()भयानक नाम हैं। विचार करें toString()औरprintTo(Stream stream)
candied_orange

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

@ AdrianoRepetti: ईमानदारी से, यह सिर्फ एक विवादित उदाहरण है, मूल प्रश्न पर फिट होने और मेरी बात को प्रदर्शित करने के लिए। एक वास्तविक प्रणाली में, आसपास के संदर्भ होंगे जो बेहतर तरीकों और नामों के बारे में निर्णय लेने की अनुमति देंगे, ज़ाहिर है।
डॉक ब्राउन

6

देर से जवाब लेकिन मैं विरोध नहीं कर सकता।

क्या X अधिकांश कक्षाओं में Y अच्छा है या एक विरोधी पैटर्न है?

ज्यादातर मामलों में, ज्यादातर नियम, बिना सोचे-समझे लागू किए गए, ज्यादातर गलत तरीके से गलत होंगे (इस एक सहित)।

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

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

अब ऐसा करते हुए मैंने कुछ स्थैतिक तरीकों को तैयार किया। मेरे इंटर्न ने एक डीटीओ क्लास बनाया, जो आपको बहुत पसंद आया CatData

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

इसलिए मैंने अपनी जीभ को पकड़ रखा था। मैंने देखा कि जब उन्होंने इस चीज़ को इस्तेमाल करने से पहले अपने स्थिर तरीकों का इस्तेमाल किया। हम उनमें से लगभग 14 थे। यह बदसूरत था, लेकिन हमारे पास देखभाल करने का कोई कारण नहीं था।

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

अनिच्छा से मैंने पूछा, "क्या आप किसी वस्तु पर विचार करेंगे?"

उसने अपने डीटीओ को पीछे देखा और भ्रम में अपना चेहरा खराब कर दिया। "यह एक वस्तु है"।

"मेरा मतलब एक वास्तविक वस्तु है"

"ओह?"

"मुझे आपको कुछ दिखाने दें। आप तय करें कि क्या यह उपयोगी है"

मैंने एक नया नाम चुना और जल्दी से कुछ इस तरह से देखा कि कुछ इस तरह से फुसफुसाया:

public class Cat{
    CatData(string catPage) {
        this.catPage = catPage
    }
    private readonly string catPage;

    public string name() { return chop("name prefix", "name suffix"); }
    public string weight() { return chop("weight prefix", "weight suffix"); }
    public string image() { return chop("image prefix", "image suffix"); }

    private string chop(string prefix, string suffix) {
        int start = catPage.indexOf(prefix) + prefix.Length;
        int end = catPage.indexOf(suffix);
        int length = end - start;
        return catPage.Substring(start, length);
    }
}

यह कुछ भी नहीं किया स्थिर तरीकों पहले से ही नहीं कर रहे थे। लेकिन अब मैं 14 स्थिर तरीकों को एक कक्षा में चूसा हूँ जहाँ वे उस डेटा के साथ अकेले हो सकते हैं जिस पर उन्होंने काम किया था।

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

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

क्या मैं कह रहा हूं कि आपको हमेशा डीटीओ के ऊपर ओओ ऑब्जेक्ट्स से चिपके रहना चाहिए? नहीं, डीटीओ की चमक जब आपको एक सीमा पार करने की आवश्यकता होती है जो आपको चलती विधियों से रखती है। डीटीओ का अपना स्थान है।

लेकिन इसलिए OO ऑब्जेक्ट करते हैं। दोनों उपकरणों का उपयोग करना सीखें। जानें कि प्रत्येक लागत क्या है। समस्या, स्थिति और आंतरिक निर्णय लेने देना सीखें। डोगमा यहाँ तुम्हारा दोस्त नहीं है।


चूंकि मेरा जवाब पहले से ही हास्यास्पद है, इसलिए मुझे अपने कोड की समीक्षा के साथ कुछ गलतफहमियों से अवगत कराएं।

उदाहरण के लिए, एक वर्ग में आमतौर पर वर्ग के सदस्य और विधियाँ होती हैं, जैसे:

public class Cat{
    private String name;
    private int weight;
    private Image image;

    public void printInfo(){
        System.out.println("Name:"+this.name+",weight:"+this.weight);
    }

    public void draw(){
        //some draw code which uses this.image
    }
}

आपका निर्माता कहां है? यह मुझे पता करने के लिए पर्याप्त नहीं है कि क्या यह उपयोगी है।

लेकिन एकल जिम्मेदारी सिद्धांत और ओपन क्लोज्ड सिद्धांत के बारे में पढ़ने के बाद, मैं डीटीओ और हेल्पर क्लास में अलग-अलग क्लास को स्टैटिक तरीकों से ही पसंद करता हूं, जैसे:

public class CatData{
    public String name;
    public int weight;
    public Image image;
}

public class CatMethods{
    public static void printInfo(Cat cat){
        System.out.println("Name:"+cat.name+",weight:"+cat.weight);
    }

    public static void draw(Cat cat){
        //some draw code which uses cat.image
    }
}

मुझे लगता है कि यह एकल जिम्मेदारी सिद्धांत पर फिट बैठता है क्योंकि अब कैटडेटा की जिम्मेदारी केवल डेटा रखने की है, तरीकों की भी परवाह नहीं करता (कैटमेथोड्स के लिए भी)।

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

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

और यह खुले बंद सिद्धांत को भी फिट करता है क्योंकि नए तरीकों को जोड़ने से कैटडेटा क्लास को बदलने की आवश्यकता नहीं है।

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

मेरा प्रश्न यह है कि क्या यह एक अच्छा या एक प्रतिमान है?

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

यदि यह आपको बेहतर महसूस कराता है तो आप उस चीज़ से दूर नहीं हैं जो मार्टिन फॉलर किसी ऑब्जेक्ट को कहते हैं । आपको केवल प्राथमिक वस्तु को अपनी वस्तु में नहीं रखना है।

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


2

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

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

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

तो आपके पास एक इंटरफ़ेस हो सकता है:

public interface CatMethods {
    void printInfo(Cat cat);
    void draw(Cat cat);
}

और एक कार्यान्वयन जो रनटाइम के दौरान आपके सिस्टम के बाकी हिस्सों में इंजेक्ट हो जाता है (परीक्षण के लिए उपयोग किए जा रहे अन्य कार्यान्वयन के साथ):

internal class CatMethodsForScreen implements CatMethods {
    public void printInfo(Cat cat) {
        System.out.println("Name:"+cat.name+",weight:"+cat.weight);
    }

    public void draw(Cat cat) {
        //some draw code which uses cat.image
    }
}

या उन तरीकों से दुष्प्रभावों को हटाने के लिए अतिरिक्त पैरामीटर जोड़ें:

public static class CatMethods {
    public static void printInfo(Cat cat, OutputHandler output) {
        output.println("Name:"+cat.name+",weight:"+cat.weight);
    }

    public static void draw(Cat cat, Canvas canvas) {
        //some draw code which uses cat.image and draws it on canvas
    }
}

लेकिन आप शुरू से ही एक कार्यात्मक भाषा के साथ जाने के बजाय जावा की तरह एक ओओ भाषा को एक कार्यात्मक भाषा में ढालने की कोशिश क्यों करेंगे? क्या यह किसी प्रकार का "मुझे जावा से नफरत है, लेकिन हर कोई इसका उपयोग करता है इसलिए मुझे करना होगा, लेकिन कम से कम मैं इसे अपने तरीके से लिखने जा रहा हूं"। जब तक आप यह दावा नहीं कर रहे हैं कि OO प्रतिमान किसी तरह से अप्रचलित और पुराना है। मैं "यदि आप एक्स चाहते हैं, तो आप जानते हैं कि इसे कहाँ प्राप्त करना है" स्कूल ऑफ थिंक।
कयामन

@Kayaman, " मैं" यदि आप X चाहते हैं, तो आप जानते हैं कि आपको यह कहाँ जाना है "विचार का विद्यालय "। मैं नही। मुझे वह रवैया अदूरदर्शी और थोड़ा आक्रामक दोनों लगता है। मैं जावा का उपयोग नहीं करता, लेकिन मैं C # का उपयोग करता हूं और मैं कुछ "वास्तविक OO" विशेषताओं को अनदेखा करता हूं। मुझे इनहेरिटेंस, स्टेटफुल ऑब्जेक्ट्स और इस तरह की परवाह नहीं है और मैं बहुत सारे स्टैटिक तरीके और सीलबंद (फाइनल) क्लासेस लिखता हूं। C # के आस-पास टूलिंग और समुदाय का आकार किसी से पीछे नहीं है। F # के लिए, यह रास्ता गरीब है। इसलिए मैं "यदि आप एक्स चाहते हैं, तो इसे अपने वर्तमान टूलिंग में जोड़ने के लिए कहें" स्कूल ऑफ थिंक।
डेविड अर्नो

1
मैं कहूंगा कि किसी भाषा के पहलुओं को अनदेखा करना अन्य भाषाओं की विशेषताओं को मिलाने और मेल करने की कोशिश से बहुत अलग है। मैं "वास्तविक ऊ" लिखने की कोशिश नहीं करता, या तो प्रोग्रामिंग का काम नहीं करता है, जैसे कि एक अक्षम विज्ञान में नियमों (या सिद्धांतों) का पालन करने की कोशिश कर रहा है। बेशक आपको नियमों को जानने की जरूरत है ताकि आप उन्हें तोड़ सकें। नेत्रहीन रूप से सुविधाओं का दोहन भाषा के विकास के लिए बुरा हो सकता है। कोई अपराध नहीं है, लेकिन IMHO एफपी दृश्य का एक हिस्सा लगता है "एफपी कटा हुआ ब्रेड के बाद से सबसे बड़ी बात है, लोग इसे क्यों नहीं समझेंगे"। मैं कभी नहीं कहूँगा (या लगता है) OO या Java "सबसे अच्छा" है।
कायमान

1
@ कायमन, लेकिन "अन्य भाषाओं से सुविधाओं को मिलाने और मिलान करने की कोशिश" क्या मतलब है? क्या आप तर्क दे रहे हैं कि कार्यात्मक सुविधाओं को जावा में नहीं जोड़ा जाना चाहिए, क्योंकि "जावा एक ओओ भाषा है"? यदि हां, तो मेरे विचार में यह एक अदूरदर्शी तर्क है। डेवलपर्स की इच्छा से भाषा को विकसित होने दें। उन्हें दूसरी भाषा में जाने के लिए मजबूर करना गलत दृष्टिकोण है, मुझे लगता है। यकीन है कि कुछ "एफपी अधिवक्ता" एफपी के बारे में सबसे अच्छी बात है। और कुछ "OO अधिवक्ता" OO के बारे में शीर्ष पर जाते हैं, "लड़ाई जीत ली क्योंकि यह स्पष्ट रूप से श्रेष्ठ है"। उन दोनों को नजरअंदाज करें।
डेविड अरनो

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

0

डीटीओ - डेटा ट्रांसपोर्ट ऑब्जेक्ट

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

OO का पूरा बिंदु डेटा और उस डेटा पर काम करने वाले कोड को एक साथ बांधना है। एक तार्किक वस्तु को अलग-अलग वर्गों में अलग करना आमतौर पर एक बुरा विचार है।


-1

कई डिज़ाइन पैटर्न और सिद्धांत संघर्ष, और अंततः एक अच्छे प्रोग्रामर के रूप में केवल आपका निर्णय आपको यह तय करने में मदद करेगा कि किसी विशिष्ट समस्या के लिए कौन से पैटर्न लागू होने चाहिए।

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

यहाँ कुछ सवाल दिए गए हैं जो आप आवेदन के बारे में खुद से पूछ सकते हैं:

  • क्या मुझे कभी भी कैट इमेज प्रदान करने का एक वैकल्पिक तरीका प्रदान करने की आवश्यकता होगी? यदि हां, तो विरासत क्या ऐसा करने का एक सुविधाजनक तरीका नहीं होगा?
  • क्या मेरे कैट क्लास को किसी अन्य वर्ग से विरासत में प्राप्त करने या इंटरफ़ेस को संतुष्ट करने की आवश्यकता है?

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


-1

क्या यह एक अच्छा पैटर्न है?

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


"सच" OOP

जहाँ तक मेरी जानकारी है, OOP की 2 व्याख्याएँ हैं। ज्यादातर लोगों के लिए, यह "एक वस्तु एक वर्ग" है।

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

डेटा धारकों

आप Catएक डेटा धारक के प्रमुख उदाहरण हैं। यकीन है, आपके कार्यक्रम के बाहर एक बिल्ली एक ऐसी चीज है जो कुछ करती है , लेकिन आपके कार्यक्रम के अंदर, Catएक स्ट्रिंग name, एक इंट weightऔर एक छवि है image

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

वस्तुओं

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

बिल्ली की जानकारी छापना किसी वस्तु का काम है। उदाहरण के लिए, आप इस ऑब्जेक्ट को " CatInfoLogger" कह सकते हैं , एक सार्वजनिक विधि के साथ Log(Cat)। यह सब हमें बाहर से जानने की जरूरत है: यह ऑब्जेक्ट एक बिल्ली की जानकारी को लॉग करता है और ऐसा करने के लिए, इसे ए की जरूरत है Cat

अंदर पर, इस ऑब्जेक्ट में बिल्लियों को लॉग करने की अपनी एकल जिम्मेदारी को पूरा करने के लिए जो कुछ भी आवश्यक है, उसका संदर्भ होगा । इस मामले में, यह है कि केवल के लिए एक संदर्भ है Systemके लिए System.out.println, लेकिन ज्यादातर मामलों में, यह अन्य वस्तुओं के लिए निजी संदर्भ हो जाएगा। यदि मुद्रण से पहले आउटपुट को स्वरूपित करने का तर्क बहुत जटिल हो जाता है, तो CatInfoLoggerबस एक नई वस्तु का संदर्भ प्राप्त कर सकते हैं CatInfoFormatter। यदि बाद में, हर लॉग को फ़ाइल में लिखा जाना चाहिए, तो आप एक CatToFileLoggerऑब्जेक्ट जोड़ सकते हैं जो ऐसा करता है।

डेटा धारक बनाम ऑब्जेक्ट - सारांश

अब, आप वह सब क्यों करेंगे? क्योंकि अब एक वर्ग बदलने से केवल एक चीज बदलती है ( जिस तरह एक बिल्ली उदाहरण में लॉग इन होती है)। यदि आप किसी ऑब्जेक्ट को बदल रहे हैं, तो आप केवल एक निश्चित कार्रवाई करने के तरीके को बदल रहे हैं; यदि आप एक डेटा धारक को बदलते हैं, तो आप केवल यह देखते हैं कि कौन सा डेटा आयोजित किया गया है और / या किस तरीके से आयोजित किया गया है।

डेटा बदलने का मतलब हो सकता है कि जिस तरह से कुछ किया जाना है उसे भी बदलना है, लेकिन यह तब तक नहीं होगा जब तक आप इसे स्वयं नहीं करते हैं जब तक कि आप जिम्मेदार वस्तु को बदलकर खुद नहीं होते।

Overkill?

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

हालांकि, कोई भी "गंभीर" (= एक स्क्रिप्ट या 2 से अधिक) सॉफ्टवेयर शायद इतना बड़ा है कि यह इस तरह की संरचना से लाभान्वित होगा।


उत्तर

डीटीओ और हेल्पर वर्गों में अधिकांश वर्गों को अलग कर रहा है [...] एक अच्छा या एक विरोधी पैटर्न?

डीटीओ / डेटा धारकों में "अधिकांश वर्गों" (बिना किसी और योग्यता के) को बदलना एक विरोधी पैटर्न नहीं है, क्योंकि यह वास्तव में कोई पैटर्न नहीं है - यह कम या ज्यादा यादृच्छिक है।

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


* पुस्तक शीर्षक की तरह एक राजधानी सी के साथ "द क्लीन" है, क्योंकि - पहले पैराग्राफ को याद रखें - यह विचार के एक स्कूल के बारे में है, जबकि अन्य भी हैं।

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