एकल जिम्मेदारी सिद्धांत के साथ संघर्ष


11

इस उदाहरण पर विचार करें:

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

Postपोस्ट बनाने, पोस्ट हटाने, पोस्ट अपडेट करने आदि Tagका ध्यान रखता है, टैग बनाने, टैग हटाने, टैग अपडेट करने आदि का ध्यान रखता है।

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

एक तरफ, Postकक्षा में एक फ़ंक्शन हो सकता है जो Tagएक पैरामीटर के रूप में लेता है , और फिर इसे टैग की सूची में संग्रहीत करता है। दूसरी ओर, Tagकक्षा में एक फ़ंक्शन हो सकता है जो Postएक पैरामीटर के रूप में लेता है और से लिंक करता Tagहै Post

उपरोक्त मेरी समस्या का एक उदाहरण मात्र है। मैं वास्तव में कई वर्गों के साथ चल रहा हूं जो सभी समान हैं। यह दोनों में समान रूप से अच्छी तरह से फिट हो सकता है। वास्तव में दोनों वर्गों में कार्यक्षमता को कम करने में, इस समस्या को हल करने में मेरी मदद करने के लिए कौन सी परंपराएं या डिजाइन शैली मौजूद हैं। मुझे लगता है कि वहाँ सिर्फ एक उठा कुछ कमी हो गई है?

शायद इसे दोनों वर्गों में रखना सही उत्तर है?

जवाबों:


11

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

यह एक अच्छा, ठोस (दंड का बहाना) दिशानिर्देश है, लेकिन इसे अनदेखा करना लगभग उतना ही खतरनाक है जितना कि इसे लटका देना।

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

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

// C-style-language pseudo-code
class Post {
    string _title;
    string _content;
    Date _date;
    List<Tag> _tags;

    Post(string title, string content) {
        _title = title;
        _content = content;
        _date = Now;
        _tags = new List<Tag>();
    }

    Tag[] getTags() {
        return _tags.toArray();
    }

    void addTag(Tag tag) {
        if (_tags.contains(tag)) {
            throw "Cannot add tag twice";
        }

        _tags.Add(tag);
        tag.referencePost(this);
    }

    // more stuff here, obviously
}

class Tag {
    string _name;
    List<Post> _posts;

    Tag(string name) {
        _name = name;
    }

    Post[] getPosts() {
        return _posts.toArray();
    }

    void referencePost(Post post) {
        if (!post.getTags().contains(this) || _posts.contains(post)) {
            throw "Only reference a post by calling Post.addTag()";
        }

        _posts.Add(post);
    }

    // more stuff here too
}

यदि, बाद में, आपको पोस्ट्स को टैग में जोड़ने की आवश्यकता है, तो बस टैग क्लास में एक पोस्ट विधि जोड़ें और पोस्ट क्लास के लिए एक संदर्भटैग विधि जोड़ें। जाहिर है, मैंने उन्हें अलग नाम दिया है ताकि आप गलती से AddPost से addTag और addTag से addPost कहकर स्टैक ओवरफ्लो का कारण न बनें।


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

@AndresF .: मैं आपसे सहमत हूं, इसलिए मैंने स्पष्ट रूप से अपना जवाब बहुत अच्छा नहीं लिखा। मैंने काफी एडिट किया है। (यदि आपने इसे देखा था तो इसका अर्थ पिछले परिवर्तन करने वाले से माफी माँगता है।)
पीडीआर

6

नहीं, दोनों में नहीं! यह एक ही स्थान पर होना चाहिए।

आपके प्रश्न में मुझे जो भी मिल रहा है वह यह तथ्य है कि आप कहते हैं कि " Postपोस्ट बनाने, पोस्ट हटाने, पोस्ट अपडेट करने " का ध्यान रखता है Tag। खैर, यह सही नहीं है। Postकेवल अद्यतन करने का ध्यान रख सकता है, उसी के लिए Tag। बनाना और हटाना किसी और का काम है, बाहरी Postऔर Tag(चलो इसे कॉल करें Store)।

इसके लिए अच्छी ज़िम्मेदारी Post"इसके लेखक, विषयवस्तु और अंतिम अद्यतन की तिथि को जानता है"। इसके लिए अच्छी ज़िम्मेदारी Tag"इसके नाम और उद्देश्य (पढ़ें: वर्णन) को जानता है"। के लिए अच्छी जिम्मेदारी Storeहै "सभी पोस्ट और सभी टैग्स को जानता है और उन्हें जोड़, हटा और खोज सकता है"।

यदि आप इन तीन प्रतिभागियों को देखते हैं, तो स्वाभाविक रूप से वह कौन है जिसे पोस्ट-टैग रिश्ते का ज्ञान होना चाहिए?

(मेरे लिए, यह पोस्ट है, यह स्वाभाविक लगता है कि यह "इसके टैग्स को जानता है"; रिवर्स सर्च (एक टैग के लिए सभी पोस्ट) स्टोर का काम लगता है; हालांकि मुझसे गलती हो सकती है)


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

3

समीकरण से गायब एक महत्वपूर्ण विवरण है। टैग में पोस्ट और वीजा-वर्सा क्यों होता है? इस प्रश्न का उत्तर प्रत्येक दिए गए सेट के समाधान को निर्धारित करता है।

सामान्य तौर पर मैं ऐसी स्थिति के बारे में सोच सकता हूं जो समान हो। एक बॉक्स और सामग्री। एक बॉक्स में सामग्री है इसलिए एक संबंध उचित है। क्या सामग्री में एक बॉक्स हो सकता है? ज़रूर, एक बॉक्स के साथ एक बॉक्स। एक बॉक्स सामग्री है। लेकिन IS-A सभी बॉक्स के लिए एक अच्छा डिज़ाइन नहीं है। ऐसे मामले में मैं डेकोरेटर पैटर्न पर विचार करूंगा। इस तरह एक बॉक्स को आवश्यक समय पर सामग्री के साथ सजाया जाता है।

टैग में पोस्ट भी हो सकते हैं, लेकिन मेरे लिए यह एक स्थिर संबंध नहीं है। बल्कि यह सभी पोस्टों की एक रिपोर्ट हो सकती है जिसमें कहा गया है कि टैग। इस मामले में इसकी एक नई इकाई, नहीं है-ए।


2

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

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


1

व्यक्तिगत रूप से, मैं उनमें से किसी में भी उस कार्यक्षमता को नहीं जोड़ूंगा।

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

इसके बजाय, मेरे पास एक और वर्ग होगा जो आपके वेब पेज से संबंधित आपके व्यवसाय तर्क और डेटा के लिए जिम्मेदार है। यदि आपका पृष्ठ एक पोस्ट प्रदर्शित कर रहा है और उपयोगकर्ताओं को टैग जोड़ने की अनुमति दे रहा है, तो कक्षा में एक Postवस्तु होगी, और इसमें जोड़ने के Tagsलिए कार्यक्षमता होगी Post। यदि आपका पृष्ठ टैग प्रदर्शित कर रहा है और उपयोगकर्ताओं को उन टैग में पोस्ट जोड़ने की अनुमति दे रहा है, तो इसमें एक Tagऑब्जेक्ट होगा और इसमें जोड़ने के Postsलिए कार्यक्षमता होगी Tag

हालांकि यह सिर्फ मुझे है। यदि आपको लगता है कि आपको अपने डेटा ऑब्जेक्ट्स में डेटाबेस कार्यक्षमता को संभालना होगा, तो मैं पीडीआर के जवाब की सिफारिश करूंगा


0

जैसा कि मैंने इस प्रश्न को पढ़ा था जो पहली बात यह थी कि यह एक से कई डेटाबेस संबंध थे। पोस्ट में कई टैग हो सकते हैं ... टैग में कई पोस्ट हो सकते हैं .... यह मुझे प्रतीत होता है कि दोनों वर्गों को कुछ हद तक इस रिश्ते को प्रबंधित करने की क्षमता की आवश्यकता है।

पोस्ट के दृष्टिकोण से ...
यदि आपका संपादन या पोस्ट बनाना एक माध्यमिक गतिविधि टैग संबंधों का प्रबंधन करता है ।

  1. मौजूदा टैग को पोस्ट में जोड़ें
  2. पोस्ट से Revove टैग

IMO, बिलकुल नए TAG का निर्माण यहाँ नहीं होता है।

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

यह केवल तभी काम करेगा जब एक डेटाबेस लिंकिंग टेबल हो जो कई से कई रिश्तों को हल करता है

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