क्या इंटरफ़ेस पृथक्करण सिद्धांत ठोस तरीकों पर लागू होता है?


10

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

लेकिन ठोस तरीकों के बारे में कैसे? क्या मुझे उन तरीकों को अलग करना चाहिए जो हर ग्राहक उपयोग नहीं करेगा? निम्नलिखित वर्ग पर विचार करें:

public class Car{
    ....

    public boolean isQualityPass(){
        ...
    }

    public int getTax(){
        ...
    }

    public int getCost(){
        ...
    }
}

public class CarShop{
    ...
    public int getCarPrice(int carId){
        Car car=carList[carId];
        int price=car.getTax() + car.getCost()... (some formula);
        return price;
    }
}

उपरोक्त कोड में, CarShop कार में isQualityPass () का उपयोग नहीं करता है, क्या मुझे isQualityPass () को एक नए वर्ग में अलग करना चाहिए:

public class CheckCarQualityPass{
    public boolean isQualityPass(Car car){
    }
}

कारशॉप के युग्मन को कम करने के लिए? क्योंकि मुझे लगता है कि एक बार अगर qQualityPass () को अतिरिक्त निर्भरता की आवश्यकता होती है, जैसे:

public boolean isQualityPass(){
    HttpClient client=...
}

CarShop HttpClient पर निर्भर करेगा यहां तक ​​कि यह कभी भी HttpClient का उपयोग नहीं करता है। तो मेरा सवाल यह है: इंटरफ़ेस-अलगाव के सिद्धांत के अनुसार, क्या मुझे ऐसे ठोस तरीकों को अलग करना चाहिए जो हर ग्राहक उपयोग न करें, ताकि उन तरीकों को केवल क्लाइंट पर निर्भर करें जब ग्राहक वास्तव में उपयोग करता है, ताकि युग्मन को कम किया जा सके?


2
क्या आमतौर पर एक कार को पता है कि यह "गुणवत्ता" कब गुजरती है? या यह शायद एक व्यावसायिक नियम है जो अपने स्वयं के द्वारा समझाया जा सकता है?
Laiv

2
जैसा कि ISP में इंटरफ़ेस शब्द का अर्थ है कि यह इंटरफेस के बारे में है । इसलिए यदि आपके पास अपनी Carकक्षा में एक ऐसी विधि है, जिसे आप (सभी) उपयोगकर्ता नहीं जानना चाहते हैं, तब (एक से अधिक) इंटरफ़ेस बनाएं जिसके बारे में वह Carक्लास लागू करता है जो केवल इंटरफेस के संदर्भ में उपयोगी विधियों की घोषणा करता है।
टिमोथी ट्रक

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

1
एक कार को पता चल जाएगा कि उसका निर्माता उसे क्या जानना चाहता है। वोक्सवैगन जानता है कि मैं किस बारे में बात कर रहा हूं :-)
Laiv

1
आप एक इंटरफ़ेस का उल्लेख करते हैं, लेकिन आपके उदाहरण में कोई इंटरफ़ेस नहीं है। क्या हम कार को एक इंटरफेस में बदलने की बात कर रहे हैं और उक्त इंटरफेस में किन तरीकों को शामिल किया जाना है?
नील

जवाबों:


6

आपके उदाहरण में, CarShopनिर्भर नहीं करता है isQualityPass, और यह एक विधि के लिए खाली कार्यान्वयन करने के लिए मजबूर नहीं है। इसमें एक इंटरफ़ेस भी शामिल नहीं है। इसलिए "आईएसपी" शब्द का यहां कोई मेल नहीं है। और जब तक एक विधि की तरह isQualityPassएक विधि है जो Carऑब्जेक्ट में अच्छी तरह से फिट होती है, बिना अतिरिक्त जिम्मेदारियों या निर्भरता के साथ इसे ओवरबर्डन के बिना, यह ठीक है। किसी वर्ग की सार्वजनिक पद्धति को किसी अन्य स्थान पर केवल इसलिए रिफैक्ट करने की आवश्यकता नहीं है क्योंकि वहाँ एक क्लाइंट मौजूद है जो विधि का उपयोग नहीं कर रहा है।

हालाँकि, किसी Carचीज़ पर सीधे निर्भर होने की तरह एक डोमेन वर्ग बनाना HttpClientशायद एक अच्छा विचार नहीं है, चाहे जो भी ग्राहक इस पद्धति का उपयोग करें या न करें। तर्क को एक अलग वर्ग में ले जाने CheckCarQualityPassको केवल "आईएसपी" नहीं कहा जाता है, इसे "चिंताओं का पृथक्करण" कहा जाता है । एक पुन: प्रयोज्य कार ऑब्जेक्ट की चिंता शायद किसी भी बाहरी HTTP कॉल करने के लिए नहीं होनी चाहिए, कम से कम सीधे नहीं, यह पुन: प्रयोज्य को सीमित करता है और परीक्षण की क्षमता को बहुत अधिक बढ़ाता है।

यदि isQualityPassआसानी से किसी अन्य वर्ग में नहीं ले जाया जा सकता है, तो विकल्प Httpएक अमूर्त इंटरफ़ेस के माध्यम से कॉल करने के लिए होगा IHttpClientजो Carनिर्माण समय पर इंजेक्ट किया जाता है, या Carऑब्जेक्ट में पूरी "क्वालिटीपास" चेकिंग रणनीति (एचटीपी अनुरोध के साथ गुप्त) को इंजेक्ट करके। । लेकिन यह IMHO केवल दूसरा सबसे अच्छा समाधान है, क्योंकि यह इसे कम करने के बजाय समग्र जटिलता को बढ़ाता है।


isQualityPass विधि को हल करने के लिए रणनीति पैटर्न के बारे में क्या?
Laiv

@Laiv: तकनीकी रूप से, यह काम करेगा, निश्चित रूप से (मेरा संपादन देखें), लेकिन इसका परिणाम अधिक जटिल Carवस्तु होगा। यह एक समाधान के लिए मेरी पहली पसंद नहीं होगी (कम से कम इस आकस्मिक उदाहरण के संदर्भ में नहीं)। हालाँकि, यह "वास्तविक" कोड में अधिक समझ में आता है, मुझे नहीं पता।
डॉक्टर ब्राउन

6

तो मेरा सवाल यह है: इंटरफ़ेस-अलगाव के सिद्धांत के अनुसार, क्या मुझे ऐसे ठोस तरीकों को अलग करना चाहिए जो हर ग्राहक उपयोग न करें, ताकि उन तरीकों को केवल क्लाइंट पर निर्भर करें जब ग्राहक वास्तव में उपयोग करता है, ताकि युग्मन को कम किया जा सके?

इंटरफ़ेस पृथक्करण सिद्धांत आपको उस चीज़ तक पहुंच को रोकने के बारे में नहीं है जिसकी आपको आवश्यकता नहीं है। यह उस चीज पर जोर देने के बारे में नहीं है जिसकी आपको आवश्यकता नहीं है।

इंटरफेसेस उस वर्ग के स्वामित्व में नहीं हैं जो उन्हें लागू करता है। वे उन वस्तुओं के स्वामित्व में हैं जो उनका उपयोग करते हैं।

public class CarShop{
    ...
    public int getCarPrice(int carId){
        Car car=carList[carId];
        int price=car.getTax() + car.getCost()... (some formula);
        return price;
    }
}

यहाँ क्या प्रयोग किया जाता है है getTax()और getCost()। जिस चीज पर जोर दिया जा रहा है वह सब कुछ सुलभ है Car। समस्या का Carअर्थ है कि यह उस तक पहुंच पर जोर दे रहा है isQualityPass()जिसकी आवश्यकता नहीं है।

यह तय किया जा सकता है। आप पूछते हैं कि क्या इसे ठीक से तय किया जा सकता है। यह।

public class CarShop{
    ...
    public int getCarPrice(int carId){
        CarLiability carLiability=carLiabilityList[carId];
        int price=carLiability.getTax() + carLiability.getCost()... (some formula);
        return price;
    }
}

उस कोड में से कोई भी नहीं जानता है कि CarLiabilityक्या एक इंटरफ़ेस या एक ठोस वर्ग है। ये अच्छी बात है। यह जानना नहीं चाहता।

यदि यह एक इंटरफ़ेस है तो इसे Carलागू कर सकते हैं। यह ISP का उल्लंघन नहीं करेगा क्योंकि भले ही isQuality()वह Car CarShopइस पर जोर न दे। यह ठीक है।

यदि यह ठोस है isQuality()तो यह हो सकता है कि या तो मौजूद नहीं है या कहीं और स्थानांतरित कर दिया गया है। यह ठीक है।

यह भी हो सकता है कि CarLiabilityचारों ओर एक ठोस आवरण है Carजो इसे काम सौंप रहा है। तो जब तक CarLiabilityखुलासा नहीं करता isQuality()तो CarShopठीक है। बेशक, यह सड़क को गिरा सकता है और CarLiabilityयह पता लगाना है कि आईएसपी का पालन कैसे करना Carहै उसी तरह CarShopसे करना था।

संक्षेप में, ISP की वजह isQuality()से इसे हटाने की आवश्यकता नहीं है Car। इसके लिए isQuality()जरूरत से हटने की जरूरत है, CarShopक्योंकि CarShopइसके लिए जरूरत नहीं है, इसलिए इसे इसके लिए नहीं पूछना चाहिए।


4

क्या इंटरफ़ेस पृथक्करण सिद्धांत ठोस तरीकों पर लागू होता है?

लेकिन ठोस तरीकों के बारे में कैसे? क्या मुझे उन तरीकों को अलग करना चाहिए जो हर ग्राहक उपयोग नहीं करेगा?

ज़रुरी नहीं। वहाँ छिपाने के लिए विभिन्न तरीके हैं Car.isQualityPassसे CarShop

1. पहुँच संशोधक

से Demeter के कानून की दृष्टि में, हम विचार कर सकते हैं Carऔर CardShopहोने के लिए नहीं मित्र । यह हमें अगले करने के लिए वैध करता है।

package com.my.package.domain.model
public class Car{
    ...
    protected boolean isQualityPass(){...}
}

package com.my.package.domain.services
public class CarShop{
    ...
}

दोनों घटकों के बारे में पता होना अलग पैकेज में हैं। अब संरक्षित व्यवहार CarShopपर कोई दृश्यता नहीं है। (मुझे अग्रिम में माफ करना अगर ऊपर का उदाहरण इतना सरल दिखता है)।Car

2. इंटरफ़ेस अलगाव

आईएसपी आधार है कि हम कपोल-कल्पना के साथ काम, ठोस वर्गों के साथ नहीं से काम करता है। मैं मान लूंगा कि आप पहले से ही आईएसपी कार्यान्वयन और भूमिका इंटरफेस के साथ परिचित हैं ।

वास्तविक Carकार्यान्वयन के बावजूद , कुछ भी हमें आईएसपी का अभ्यास करने से नहीं रोकता है।

//role interfaces 
public interface Billable{
   public int getCosts();
   public int getTaxs();
}

//role interfaces
public interface QualityAssurance{
   public boolean isQualityPass();
}

public class Car implements Billable, QualityAssurance{
   ...
}

public class CarShop {
  ...
  public int getPrice(Billable billable){
     return billable.getCosts() * billable.getTaxs();
  }
}

मैंने यहां क्या किया है। मैंने बिल इंटरफ़ेस के बीच Carऔर उसके CarShopमाध्यम से सहभागिता को संकुचित कर दिया है । हस्ताक्षर पर परिवर्तन के बारे में पता होना । मैंने जानबूझकर तर्क को संशोधित किया है। मैं यह स्पष्ट करना चाहता था कि उपलब्ध भूमिका इंटरफेस में से केवल "बंधा हुआ / बाध्य" है। मैं वास्तविक कार्यान्वयन का पालन कर सकता था, लेकिन मुझे वास्तविक कार्यान्वयन विवरण का पता नहीं है और मुझे डर है कि वास्तविक का कंक्रीट क्लास पर पहुंच (दृश्यता) है। यदि यह है, तो आईएसपी के साथ किए गए सभी कार्य बेकार हो जाते हैं क्योंकि यह कास्टिंग करने के लिए डेवलपर के हाथों में है और केवल इंटरफ़ेस के साथ काम करने योग्य है । हम चाहे कितने भी विधर्मी क्यों न हों, मोह हमेशा रहने वाला है।getPriceCarShopgetPrice(String carId)

3. एकल जिम्मेदारी

मुझे डर है कि मैं यह कहने की स्थिति में नहीं हूं कि अगर निर्भरता पर्याप्त है Carऔर HttpClientपर्याप्त है, लेकिन मैं @DocBrown से सहमत हूं, यह कुछ चेतावनियों को बढ़ाता है जो एक डिजाइन समीक्षा के लायक है। इस बिंदु पर न तो डेमेटर का नियम और न ही आईएसपी आपके डिजाइन को "बेहतर" बनाएगा। वे सिर्फ इस मुद्दे को सुलझाएंगे, इसे ठीक नहीं करेंगे।

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

उपसंहार

नहीं, आपको बाहरी वर्गों के लिए ठोस तरीकों को स्थानांतरित करने की आवश्यकता नहीं है, ताकि उन्हें सुलभ न बनाया जा सके। अनगिनत उपभोक्ता हो सकते हैं। क्या आप एक नए उपभोक्ता के खेलने में आने के बाद हर बार सभी ठोस तरीकों को बाहरी कक्षाओं में ले जाएंगे ? मुझे आशा है कि आप नहीं करेंगे।

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