आप गेटर्स और सेटर से कैसे बचें?


85

मैं कक्षाओं में एक ऊँ तरीके से डिजाइन करने के साथ कठिन समय का कुछ कर रहा हूँ। मैंने पढ़ा है कि ऑब्जेक्ट उनके व्यवहार को उजागर करते हैं, न कि उनके डेटा को; इसलिए, डेटा को संशोधित करने के लिए गेटटर / सेटर का उपयोग करने के बजाय, किसी दिए गए वर्ग के तरीके "क्रिया" या ऑब्जेक्ट पर काम करने वाले क्रिया होने चाहिए। उदाहरण के लिए, एक 'खाता' ऑब्जेक्ट में, हमारे पास तरीके Withdraw()और Deposit()बजाय setAmount()आदि होंगे। देखें: क्यों गेट्टर और सेटर तरीके बुरे हैं

उदाहरण के लिए, एक ग्राहक वर्ग, जो ग्राहक के बारे में बहुत सारी जानकारी रखता है, जैसे कि नाम, डीओबी, तेल, पता इत्यादि, उन सभी विशेषताओं को प्राप्त करने और स्थापित करने के लिए गटर / सेटर से कैसे बचेंगे? क्या 'व्यवहार' प्रकार की विधि सभी डेटा को पॉप्युलेट करने के लिए लिख सकती है?




8
मैं कहना है कि आप से निपटने के लिए अगर जावा बीन्स विनिर्देश , आप होगा getters और setters हो रही। बहुत सी चीजें जावा बीन्स (jsps में अभिव्यक्ति भाषा) का उपयोग करती हैं और इस तरह से बचने की कोशिश की जाएगी ... चुनौतीपूर्ण।

4
... और माइकलटी से विपरीत दृष्टिकोण से: यदि आप JavaBeans कल्पना का उपयोग नहीं कर रहे हैं (और मुझे व्यक्तिगत रूप से लगता है कि आपको इसे तब तक बचना चाहिए जब तक आप अपनी वस्तु का उपयोग उस संदर्भ में न करें जहां यह आवश्यक है), तो इसकी कोई आवश्यकता नहीं है गेटर्स पर "गेट" मस्सा, विशेष रूप से ऐसे गुणों के लिए जिनके पास कोई संगत सेटर नहीं है। मुझे लगता है कि एक विधि name()जिस पर बुलाया गया Customerहै वह स्पष्ट है, या स्पष्ट है, जिसे विधि कहा जाता है getName()
डैनियल प्रीडन

2
@ डैनियल प्रीडेन: नाम () का मतलब दोनों को सेट करना या प्राप्त करना हो सकता है? ...
इंटेलीडाटा

जवाबों:


55

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

एक उदाहरण के रूप में, कल्पना करें कि आपकी परियोजना शतरंज या युद्धपोत की तरह एक बोर्ड गेम है। आपके पास प्रस्तुति परत (कंसोल ऐप, वेब सेवा, जीयूआई, आदि) में इसका प्रतिनिधित्व करने के विभिन्न तरीके हो सकते हैं, लेकिन आपके पास एक मुख्य डोमेन भी है। एक वर्ग जो आपके पास हो सकता है Coordinate, वह बोर्ड पर एक स्थिति का प्रतिनिधित्व करता है। इसे लिखने का "दुष्ट" तरीका होगा:

public class Coordinate
{
    public int X {get; set;}
    public int Y {get; set;}
}

(मैं जावा के बजाय संक्षिप्तता के लिए C # में कोड उदाहरण लिखने जा रहा हूं और क्योंकि मैं इससे अधिक परिचित हूं। उम्मीद है कि यह कोई समस्या नहीं है। अवधारणाएं समान हैं और अनुवाद सरल होना चाहिए।)

निष्कासन सेटर्स: अपरिवर्तनीयता

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

public class Coordinate
{
    public int X {get; private set;}
    public int Y {get; private set;}

    public Coordinate(int x, int y)
    {
        X = x;
        Y = y;
    }
}

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

गेटिंग रिमूवर्स, पार्ट 1: बिहेवियर के लिए डिजाइनिंग

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

तो चलिए बताते हैं कि पहली जगह जो आपने खुद को मिली Coordinateथी वह टक्कर का पता लगाने के लिए थी: यदि आप जांचना चाहते हैं कि क्या दो टुकड़े बोर्ड पर एक ही स्थान पर हैं। यहां "बुराई" तरीका है (निर्माणकर्ता संक्षिप्तता के लिए छोड़ दिया गया है):

public class Piece
{
    public Coordinate Position {get; private set;}
}

public class Coordinate
{
    public int X {get; private set;}
    public int Y {get; private set;}
}

    //...And then, inside some class
    public bool DoPiecesCollide(Piece one, Piece two)
    {
        return one.X == two.X && one.Y == two.Y;
    }

और यहाँ अच्छा तरीका है:

public class Piece
{
    private Coordinate _position;
    public bool CollidesWith(Piece other)
    {
        return _position.Equals(other._position);
    }
}

public class Coordinate
{
    private readonly int _x;
    private readonly int _y;
    public bool Equals(Coordinate other)
    {
        return _x == other._x && _y == other._y;
    }
}

( IEquatableकार्यान्वयन सादगी के लिए संक्षिप्त)। मॉडलिंग डेटा के बजाय व्यवहार के लिए डिजाइन करके, हम अपने गेटर्स को हटाने में कामयाब रहे।

ध्यान दें कि यह आपके उदाहरण के लिए भी प्रासंगिक है। आप एक ORM का उपयोग कर रहे होंगे, या किसी वेबसाइट या किसी चीज़ पर ग्राहक की जानकारी प्रदर्शित कर सकते हैं, जिस स्थिति में किसी प्रकार का CustomerDTO शायद समझ में आएगा। लेकिन सिर्फ इसलिए कि आपके सिस्टम में ग्राहक शामिल हैं और वे डेटा मॉडल में प्रतिनिधित्व करते हैं, इसका मतलब यह नहीं है कि Customerआपके डोमेन में एक वर्ग होना चाहिए । हो सकता है कि जैसा आप व्यवहार के लिए डिज़ाइन करते हैं, एक उभर जाएगा, लेकिन यदि आप गेटर्स से बचना चाहते हैं, तो एक पूर्व-खाली न बनाएं।

रिमूवल गेटर्स, भाग 2: बाहरी व्यवहार

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

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

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

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

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

हमारी समस्या के लिए, इस पैटर्न का उपयोग करने वाला एक समाधान होगा:

public class Coordinate
{
    private readonly int _x;
    private readonly int _y;

    public T Transform<T>(IPositionTransformer<T> transformer)
    {
        return transformer.Transform(_x,_y);
    }
}

public interface IPositionTransformer<T>
{
    T Transform(int x, int y);
}

//This one lives in the presentation layer
public class CoordinateToVectorTransformer : IPositionTransformer<Vector2>
{
    private readonly float _tileWidth;
    private readonly float _tileHeight;
    private readonly Vector2 _topLeft;

    Vector2 Transform(int x, int y)
    {
        return _topLeft + new Vector2(_tileWidth*x + _tileHeight*y);
    }
}

आप शायद बता सकते हैं, के रूप में _xऔर _yनहीं कर रहे हैं वास्तव में किसी भी अधिक समझाया। हम उन्हें बनाकर निकाल सकते हैं IPositionTransformer<Tuple<int,int>>जो उन्हें सीधे लौटाता है। स्वाद के आधार पर, आप महसूस कर सकते हैं कि यह संपूर्ण व्यायाम को बेकार कर देता है।

हालांकि, सार्वजनिक गेटर्स के साथ, चीजों को गलत तरीके से करना बहुत आसान है, बस डेटा को सीधे बाहर निकालना और इसे टेल, डोंट आस्क के उल्लंघन में उपयोग करना है । इस पैटर्न का उपयोग करते हुए यह वास्तव में इसे सही तरीके से करने के लिए सरल है: जब आप व्यवहार बनाना चाहते हैं, तो आप स्वचालित रूप से इसके साथ एक प्रकार बनाकर शुरू करेंगे। TDA के उल्लंघन बहुत स्पष्ट रूप से बदबूदार होंगे और शायद एक सरल, बेहतर समाधान के आसपास काम करने की आवश्यकता होती है। व्यवहार में, ये बिंदु इसे सही करने के लिए बहुत आसान बनाते हैं, ओओ, जिस तरह से "बुराई" तरीके से यह प्रोत्साहित करता है कि गेटर्स प्रोत्साहित करते हैं।

अंत में , यहां तक ​​कि अगर यह शुरू में स्पष्ट नहीं है, तो वास्तव में आपके द्वारा राज्य को उजागर करने की आवश्यकता से बचने के लिए व्यवहार के रूप में आपके द्वारा आवश्यक व्यवहार को उजागर करने के तरीके हो सकते हैं । उदाहरण के लिए, हमारे पिछले संस्करण का उपयोग करना Coordinateजिसका एकमात्र सार्वजनिक सदस्य है Equals()(व्यवहार में इसे पूर्ण IEquatableकार्यान्वयन की आवश्यकता होगी ), आप अपनी प्रस्तुति परत में निम्न वर्ग लिख सकते हैं:

public class CoordinateToVectorTransformer
{
    private Dictionary<Coordinate,Vector2> _coordinatePositions;

    public CoordinateToVectorTransformer(int boardWidth, int boardHeight)
    {
        for(int x=0; x<boardWidth; x++)
        {
            for(int y=0; y<boardWidth; y++)
            {
                _coordinatePositions[new Coordinate(x,y)] = GetPosition(x,y);
            }
        }
    }

    private static Vector2 GetPosition(int x, int y)
    {
        //Some implementation goes here...
    }

    public Vector2 Transform(Coordinate coordinate)
    {
        return _coordinatePositions[coordinate];
    }
}

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

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


खूबसूरती से जवाब दिया! मैं स्वीकार करना चाहूंगा, लेकिन पहले कुछ टिप्पणियां: 1। मुझे लगता है कि toDTO () महान है, bcuz उर गेट / सेट को एक्सेस नहीं कर रहा है, जो यू को डीटीओ w / o को दिए गए फ़ील्ड को मौजूदा कोड को बदलने की अनुमति देता है। 2. कहो ग्राहक के पास इसे इकाई बनाने का औचित्य साबित करने के लिए पर्याप्त व्यवहार है, आप उन्हें संशोधित करने के लिए कैसे प्रॉप्स का उपयोग करेंगे, जैसे पता / टेली परिवर्तन आदि
इंटेलीडाटा

@IntelliData 1. जब आप "फ़ील्ड्स बदलते हैं" कहते हैं, तो आपका मतलब वर्ग परिभाषा बदलना या डेटा को म्यूट करना है? बाद के लोगों को बसने से दूर किया जा सकता है, लेकिन गेटर्स को छोड़ दिया जाता है, इसलिए डोटो पहलू अप्रासंगिक है। पूर्व वास्तव में (संपूर्ण) कारण नहीं है कि सार्वजनिक गेटर्स "बुराई" हैं। उदाहरण के लिए programmers.stackexchange.com/questions/157526/… देखें ।
बेन आरोनसन

@IntelliData 2. व्यवहार को जाने बिना उत्तर देना कठिन है। लेकिन शायद, जवाब है: आप नहीं करेंगे। एक ऐसा Customerवर्ग क्या व्यवहार कर सकता है जिसे अपने टेलीफोन नंबर को बदलने में सक्षम होना चाहिए शायद ग्राहक का टेलीफोन नंबर बदल जाता है और मुझे डेटाबेस में उस बदलाव को जारी रखने की आवश्यकता होती है, लेकिन इसमें से कोई भी व्यवहार-प्रदान डोमेन ऑब्जेक्ट की जिम्मेदारी नहीं है। यह एक डेटा-एक्सेस चिंता है, और संभवतः एक डीटीओ के साथ और, एक रिपॉजिटरी कहेगी।
बेन आरोनसन

@IntelliData Customerडोमेन ऑब्जेक्ट के डेटा को अपेक्षाकृत ताज़ा रखना (db के साथ सिंक में) अपने जीवनचक्र को प्रबंधित करने का विषय है, जो कि स्वयं की ज़िम्मेदारी भी नहीं है, और शायद फिर से एक रिपॉजिटरी या एक फैक्ट्री या IOC कंटेनर में रहना होगा। जो कुछ को दर्शाता Customerहै।
बेन आरोनसन

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

71

बसने से बचने का सबसे सरल तरीका यह है कि जब आप newऑब्जेक्ट को बनाते हैं तो कंस्ट्रक्टर विधि को मान सौंप दें । जब आप किसी ऑब्जेक्ट को अपरिवर्तनीय बनाना चाहते हैं तो यह भी सामान्य पैटर्न है उस ने कहा, वास्तविक दुनिया में चीजें हमेशा स्पष्ट नहीं होती हैं।

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

आगे पढ़ना
जब गेटर्स और सेटर्स जायज़ हैं


3
तो 'गेट्टर / सेटर्स' के बारे में सभी प्रचार बुराई क्यों हैं?
इंटेलीडाटा

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

12
@IntelliData कुछ लोग आपको बताएंगे कि जावा अपने आप में बुराई है।
अशक्त

18
@MetaFightsetEvil(null);

4
निश्चित रूप से ईविल इंकारनेट है। या चचेरी बहन के पास।
बिशप

58

यह एक वस्तु है जो व्यवहार के बजाय डेटा को उजागर करता है पूरी तरह से ठीक है। हम इसे "डेटा ऑब्जेक्ट" कहते हैं। पैटर्न डेटा ट्रांसफर ऑब्जेक्ट या वैल्यू ऑब्जेक्ट जैसे नामों के तहत मौजूद है। यदि ऑब्जेक्ट का उद्देश्य डेटा को होल्ड करना है, तो डेटा को एक्सेस करने के लिए गेटर्स और सेटर मान्य हैं।

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

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

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

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


ओओपी में, तथाकथित विशेषज्ञों को लगता है कि यह मामला नहीं है।
इंटेलीडाटा

8
फिर फिर से, कुछ लोगों ने कहा है कि 'Never use OOP': हानिकारक.cat-v.org/software/OO_programming
जैक्सबी

7
एफटीआर, मुझे लगता है कि अधिक "विशेषज्ञ" अभी भी सब कुछ के लिए बिना किसी चीज के बनाने के लिए, बिना किसी चीज के गेटर्स / सेटर बनाना अर्थहीन बनाना सिखाते हैं । IMO, उत्तरार्द्ध कम भ्रामक सलाह है।
लेफ्टरनैबाउट

4
@leftaroundabout: ठीक है, लेकिन मैं 'हमेशा' और 'कभी नहीं' के बीच एक मध्य मैदान का सुझाव दे रहा हूं, जो 'उचित होने पर उपयोग' है।
जैक्सबी

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

11

Customerडेटा ऑब्जेक्ट से -class को रूपांतरित करने के लिए , हम स्वयं से डेटा फ़ील्ड के बारे में निम्नलिखित प्रश्न पूछ सकते हैं:

हम {डेटा फ़ील्ड} का उपयोग कैसे करना चाहते हैं? {डेटा फ़ील्ड} का उपयोग कहां किया जाता है? क्या {डेटा फ़ील्ड} का उपयोग कक्षा में किया जा सकता है?

उदाहरण के लिए:

  • का उद्देश्य क्या है Customer.Name?

    संभव उत्तर, लॉगिन वेब पेज में नाम प्रदर्शित करें, ग्राहक को डाक में नाम का उपयोग करें।

    जो तरीकों की ओर जाता है:

    • Customer.FillInTemplate (...)
    • Customer.IsApplicableForMailing (...)
  • का उद्देश्य क्या है Customer.DOB?

    ग्राहक की आयु को मान्य करना। ग्राहक के जन्मदिन पर छूट। डाक से।

    • Customer.IsApplicableForProduct ()
    • Customer.GetPersonalDiscount ()
    • Customer.IsApplicableForMailing ()

टिप्पणियों को देखते हुए, उदाहरण ऑब्जेक्ट Customer- दोनों डेटा ऑब्जेक्ट के रूप में और अपनी जिम्मेदारियों के साथ "वास्तविक" ऑब्जेक्ट के रूप में - बहुत व्यापक है; अर्थात इसमें बहुत अधिक गुण / जिम्मेदारियाँ हैं। जिसके आधार पर या तो बहुत सारे घटक होते हैं Customer(इसके गुणों को पढ़कर) या Customerबहुत सारे घटकों के आधार पर। शायद ग्राहक के विभिन्न विचार मौजूद हैं, शायद प्रत्येक की अपनी अलग कक्षा 1 होनी चाहिए :

  • Accountऔर मौद्रिक लेन-देन के संदर्भ में ग्राहक शायद केवल इसका उपयोग करते हैं:

    • मनुष्यों को यह पहचानने में सहायता करें कि उनका धन अंतरण सही व्यक्ति के पास जाए; तथा
    • समूह Accountएस।

    इस ग्राहक ने जैसे क्षेत्रों की जरूरत नहीं है DOB, FavouriteColour, Tel, और शायद यह भी नहीं Address

  • ग्राहक एक बैंकिंग वेबसाइट में प्रवेश करने वाले उपयोगकर्ता के संदर्भ में।

    प्रासंगिक क्षेत्र हैं:

    • FavouriteColour, जो व्यक्तिगत थीमिंग के रूप में आ सकता है;
    • LanguagePreferences, तथा
    • GreetingName

    गेटर्स और बसने वाले गुणों के बजाय, इन्हें एक ही तरीके से कैप्चर किया जा सकता है:

    • PersonaliseWebPage (टेम्पलेट पेज);
  • विपणन और व्यक्तिगत मेलिंग के संदर्भ में ग्राहक।

    यहां डेटाबजेक्ट के गुणों पर भरोसा नहीं किया जाता है, बल्कि ऑब्जेक्ट की जिम्मेदारियों से शुरू होता है; उदाहरण के लिए:

    • IsCustomerInterestedInAction (); तथा
    • GetPersonalDiscounts ()।

    तथ्य यह है कि इस ग्राहक वस्तु में एक FavouriteColourसंपत्ति है, और / या एक Addressसंपत्ति अप्रासंगिक हो जाती है: शायद कार्यान्वयन इन गुणों का उपयोग करता है; लेकिन यह कुछ मशीन सीखने की तकनीक का उपयोग भी कर सकता है और ग्राहक के साथ पिछले इंटरैक्शन का उपयोग करके पता लगा सकता है कि ग्राहक को किन उत्पादों में रुचि हो सकती है।


1. बेशक, Customerऔर Accountकक्षाएं उदाहरण थे, और एक साधारण उदाहरण या होमवर्क अभ्यास के लिए, इस ग्राहक को विभाजित करना ओवरकिल हो सकता है, लेकिन विभाजन के उदाहरण के साथ, मुझे उम्मीद है कि डेटा ऑब्जेक्ट को ऑब्जेक्ट में बदलने की विधि जिम्मेदारियां काम आएंगी।


4
अपवोट करें क्योंकि आप वास्तव में प्रश्न का उत्तर दे रहे हैं :) हालांकि यह भी स्पष्ट है कि प्रस्तावित समाधान केवल गेट्स / सेटर होने से बहुत खराब हैं - उदाहरण के लिए FillInTemplate स्पष्ट रूप से चिंताओं के सिद्धांत को अलग करता है। जो सिर्फ यह दिखाने के लिए जाता है कि प्रश्न का आधार त्रुटिपूर्ण है।
जैक्सबी

@ कैस्पर वैन डेन बर्ग: और जब आपके पास ग्राहक में कई विशेषताएं हैं जैसा कि आमतौर पर होता है, तो आप शुरुआत में उन्हें कैसे सेट करेंगे?
इंटेलीडाटा

2
@IntelliData आपके मान संभवतः डेटाबेस, XML, आदि से आ रहा है। ग्राहक, या एक ग्राहक ग्राहक, उन्हें पढ़ता है, फिर सेट करता है (अर्थात जावा में) निजी / पैकेज / आंतरिक वर्ग का उपयोग, या (ick) प्रतिबिंब। सही नहीं है, लेकिन आप आमतौर पर सार्वजनिक बसने से बच सकते हैं। (कुछ और विवरणों के लिए मेरा उत्तर देखें)
user949300

6
मुझे नहीं लगता कि ग्राहक वर्ग को इनमें से किसी भी चीज के बारे में जानना चाहिए।
कोडइन्चोस

क्या कुछ पसंद है Customer.FavoriteColor?
गाबे

8

टी एल; डॉ

  • व्यवहार के लिए मॉडलिंग अच्छी है।

  • अच्छे (!) सार के लिए मॉडलिंग बेहतर है।

  • कभी-कभी डेटा ऑब्जेक्ट की आवश्यकता होती है।


व्यवहार और अमूर्तता

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

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

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

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


ग्राहक वर्ग

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

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

फिर भी, वासी गैर-तुच्छ सेवाएँ प्रदान कर सकते हैं / देना चाहिए: वे ईमेल-अड्रेस का सही प्रारूप, डाक अड्रेस का सत्यापन इत्यादि सुनिश्चित कर सकते हैं। इसी तरह, "गेटर्स" उच्च-स्तरीय सेवाएं प्रदान कर सकते हैं जैसे कि Name <user@server.com>प्रारूप में ई-एड्रेस प्रदान करना। नाम फ़ील्ड और जमा किए गए ईमेल पते का उपयोग करना, या निश्चित रूप से एक सही स्वरूपित डाक पता आदि प्रदान करना, निश्चित रूप से यह उच्च स्तर की कार्यक्षमता समझ में आता है कि आपके उपयोग-मामले पर बहुत अधिक निर्भर करता है। यह पूरा ओवरकिल हो सकता है, या इसे ठीक करने के लिए किसी अन्य वर्ग के लिए कॉल कर सकता है। अमूर्त स्तर का चुनाव एक आसान नहीं है।


सही लगता है, हालाँकि मैं सेक्स पार्ट पर असहमत हूँ ...;)
इंटेलीडाटा

6

कैस्पर के जवाब पर विस्तार करने की कोशिश कर रहा है, इसके खिलाफ शेख़ी करना और बसने को खत्म करना सबसे आसान है। नहीं बल्कि अस्पष्ट, हाथ में (और उम्मीद है कि हास्य) तर्क में:

ग्राहक कब होगा। कभी भी बदल जाएगा?

शायद ही कभी। शायद उन्होंने शादी कर ली। या साक्षी संरक्षण में चले गए। लेकिन उस मामले में आप भी जांच करना चाहेंगे और संभवतः अपने निवास, परिजनों और अन्य सूचनाओं को बदल सकते हैं।

कब DOB कभी बदलेगा?

केवल प्रारंभिक निर्माण पर, या डेटा प्रविष्टि स्क्रूप पर। या अगर वे एक डोमिनिकन बेसबॉल खिलाड़ी हैं। :-)

इन क्षेत्रों को नियमित, सामान्य बसने वालों के लिए सुलभ नहीं होना चाहिए। हो सकता है कि आपके पास कोई Customer.initialEntry()विधि हो, या ऐसी Customer.screwedUpHaveToChange()विधि जिसमें विशेष अनुमतियों की आवश्यकता हो। लेकिन एक सार्वजनिक Customer.setDOB()तरीका नहीं है ।

आमतौर पर एक ग्राहक एक डेटाबेस, एक REST एपीआई, कुछ XML, जो भी पढ़ा जाता है। एक विधि है Customer.readFromDB(), या, यदि आप SRP / चिंताओं को अलग करने के बारे में सख्त हैं, तो आपके पास एक अलग बिल्डर होगा, उदाहरण CustomerPersisterके लिए एक read()विधि। आंतरिक रूप से, वे किसी तरह खेतों को सेट करते हैं (मैं पैकेज एक्सेस या एक आंतरिक वर्ग, वाईएमएमवी का उपयोग करना पसंद करता हूं)। लेकिन फिर, सार्वजनिक बसने से बचें।

(प्रश्न के रूप में परिशिष्ट कुछ हद तक बदल गया है ...)

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

हालांकि, IMO, यह पूरी तरह से एक के लिए जोड़े को ग्राहक के लिए स्वीकार्य है सार मानक , ResultSet। एक अलग सहायक वस्तु (मैं इसे कॉल करूंगा CustomerDBHelper, जो शायद एक उपवर्ग है AbstractMySQLHelper) आपके डीबी के सभी जटिल कनेक्शनों के बारे में जानता है, मुश्किल अनुकूलन विवरण जानता है, टेबल, क्वेरी, जॉइन आदि जानता है ... (या एक का उपयोग करता है) परिणाम को उत्पन्न करने के लिए ORM (जैसे हाइबरनेट)। आपकी वस्तु उससे बात करती है ResultSet, जो एक अमूर्त मानक है, जिसे बदलने की संभावना नहीं है। जब आप अंतर्निहित डेटाबेस को बदलते हैं, या स्कीमा को बदलते हैं, तो ग्राहक नहीं बदलता है , लेकिन CustomerDB हेल्पर करता है। यदि आप भाग्यशाली हैं, तो यह केवल AbstractMySQLHelper है जो खुद ही ग्राहक, व्यापारी, शिपिंग आदि के लिए परिवर्तन करता है।

इस तरह से आप (शायद) गेटर्स और सेटर की आवश्यकता को टाल या कम कर सकते हैं।

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

इसी तरह, मान लें कि आप बहुत सारे XML का उपयोग करते हैं। IMO, यह आपके ग्राहक को एक अमूर्त मानक, जैसे पायथन xml.etree.ElementTree या Java org.w3c.dom.Element के रूप में जोड़े जाने के लिए ठीक है । ग्राहक मिलता है और उसी से सेट करता है। फिर, आप (शायद) गेटर्स और सेटर की आवश्यकता को कम कर सकते हैं।


क्या आप कहेंगे कि बिल्डर पैटर्न का उपयोग करना उचित है?
इंटेलीडाटा

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

1

गेटर्स और सेटर होने का मुद्दा इस बात का हो सकता है कि एक क्लास को बिजनेस लॉजिक में एक तरह से इस्तेमाल किया जा सकता है, लेकिन डेटाबेस या फाइल या अन्य परसेंटेज स्टोरेज से डेटा को सीरीज़ / डीसर्लाइज़ करने के लिए आपके पास हेल्पर क्लास भी हो सकती हैं।

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

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

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

यदि आपकी भाषा विशेष रूप से C ++ है, तो इसके आस-पास का एक तरीका डेटा की सार्वजनिक "संरचना" है और फिर आपकी कक्षा के लिए एक सदस्य के रूप में इस "संरचना" का एक उदाहरण होना चाहिए और वास्तव में आपके द्वारा संग्रहीत सभी डेटा / इसमें संग्रहित किया जाना है। फिर आप आसानी से कई स्वरूपों में अपने डेटा को पढ़ने / लिखने के लिए "रैपर" लिख सकते हैं।

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


0

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

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

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

इस मामले में, या कई अन्य (जैसे डेटाबेस तक पहुंच) आप वास्तव में साझा डेटा के साथ काम करते हैं। जैसे कि इसे छिपाने का कोई कारण नहीं है, इसके विपरीत आप इसे उपलब्ध कराना चाहते हैं। पढ़ने या लिखने की पहुंच या डेटाचेक स्थिरता पर चिंता हो सकती है, लेकिन इस मूल में, अगर यह सार्वजनिक है तो कोर अवधारणा।

ऐसी डिजाइन आवश्यकता के लिए जहां आप इनकैप्सुलेशन से बचना चाहते हैं और चीजों को सार्वजनिक करना चाहते हैं और स्पष्ट रूप से, आप वस्तुओं से बचना चाहते हैं। क्या आप वास्तव में जरूरत tuples, सी संरचना या उनके समकक्ष हैं, नहीं वस्तुओं।

लेकिन यह जावा जैसी भाषाओं में भी होता है, केवल एक चीज जिसे आप मॉडल कर सकते हैं वह है ऑब्जेक्ट या ऑब्जेक्ट की सरणियाँ। विषय-वस्तु में कुछ मूल प्रकार (int, float ...) हो सकते हैं, लेकिन यह सब है। लेकिन वस्तुएं भी केवल सार्वजनिक क्षेत्रों और कि सभी के साथ एक सरल संरचना की तरह व्यवहार कर सकती हैं।

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

वहाँ भी तर्क आप सेटर विधि में कुछ तर्क / जाँच जोड़ सकते हैं।

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

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

आप सभी theses गेटर्स / बसने वाले बॉयलरप्लेट कोड की सवारी पाने के लिए भाषा को बदलने की आवश्यकता होगी। (जैसे सी # या लिस्प)। मेरे लिए गेटर्स / सेटर सिर्फ एक बिलियन डॉलर की गलती है ...


6
सी # गुण वास्तव में किसी भी अधिक पाने और
बसने

1
[जीएस] एटर्स का लाभ यह है कि आप उन चीजों को कर सकते हैं जो आप आमतौर पर नहीं करते हैं (मानों को देखें, पर्यवेक्षकों को सूचित करें), गैर-मौजूदा क्षेत्रों आदि का अनुकरण करें, और मुख्य रूप से यह कि आप इसे बाद में बदल सकते हैं । साथ लंबोक , बॉयलरप्लेट चला गया है: @Getter @Setter class MutablePoint3D {private int x, y, z;}
माआर्टिनस

1
@maaartinus निश्चित रूप से [gs] etter किसी भी अन्य विधि के रूप में कुछ भी कर सकता है। इसका मतलब यह है कि किसी भी कॉलर कोड को किसी भी मूल्य के बारे में पता होना चाहिए जो वे सेट कर सकते हैं एक अपवाद फेंक सकते हैं, बदल सकते हैं या संभावित रूप से परिवर्तन की सूचना भेज सकते हैं ... या जो कुछ भी हो। वह कमोबेश [gs] etter किसी क्षेत्र में पहुँच प्रदान नहीं कर रहा है बल्कि मध्यस्थ कोड कर रहा है।
निकोलस बॉस्केट

@IntelliData C # गुण बॉयलरप्लेट के 1 बेकार एकल चरित्र को न लिखने और इस सभी गटर / सेटर सामान की परवाह नहीं करने की अनुमति देता है ... यह प्रोजेक्ट लोमबोक की तुलना में पहले से ही बेहतर उपलब्धि है। मेरे साथ केवल गेटर्स / सेटर के साथ एक पीओजेओ भी एनकैप्सुलेशन प्रदान करने के लिए नहीं है, बल्कि एक डेटा प्रारूप को प्रकाशित करने के लिए है जो एक सेवा के साथ एक्सचेंज के रूप में पढ़ने या लिखने के लिए स्वतंत्र है। एनकैप्सुलेशन तब डिज़ाइन आवश्यकता के विपरीत है।
निकोलस बॉस्केट

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

0

उदाहरण के लिए, एक ग्राहक वर्ग दिया जाता है जो ग्राहक के बारे में जानकारी रखता है, जैसे नाम, डीओबी, तेल, पता इत्यादि, अगर वह उन सभी विशेषताओं को प्राप्त करने और स्थापित करने के लिए गेट्टर / सेटर से कैसे बचता है? क्या 'व्यवहार' प्रकार की विधि सभी डेटा को पॉप्युलेट करने के लिए लिख सकती है?

मुझे लगता है कि यह सवाल कांटेदार है क्योंकि आप डेटा को आबाद करने के लिए व्यवहार के तरीकों के बारे में चिंतित हैं लेकिन मुझे इस बात का कोई संकेत नहीं दिखता है कि Customerवस्तुओं के वर्ग के व्यवहार का उद्देश्य क्या है ।

उपयोगकर्ता / अभिनेता के रूप में 'ग्राहक' के साथ वस्तुओं केCustomer एक वर्ग के रूप में भ्रमित न करें जो आपके सॉफ़्टवेयर का उपयोग करके विभिन्न कार्य करता है।

जब आप कहते हैं कि एक ग्राहक वर्ग दिया गया है जो ग्राहक के बारे में जानकारी रखता है तो जहाँ तक व्यवहार की बात है तो ऐसा लगता है कि आपके ग्राहक वर्ग ने इसे एक चट्टान से अलग किया है। एक Rockरंग हो सकता है, आप इसे एक नाम दे सकते हैं, आपके पास इसके वर्तमान पते को संग्रहीत करने के लिए एक क्षेत्र हो सकता है लेकिन हम किसी चट्टान से किसी भी प्रकार के बुद्धिमान व्यवहार की उम्मीद नहीं करते हैं।

गेटर्स / सेटर्स के बुरे होने के बारे में जुड़े हुए लेख से:

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

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

आपका ऑर्डर सिस्टम Rockएक खरीद ऑर्डर के साथ संबद्ध हो सकता है और जब तक कि Rockएक पता परिभाषित हो जाता है तब सिस्टम का कुछ हिस्सा यह सुनिश्चित कर सकता है कि कोई वस्तु किसी चट्टान तक पहुंचाई जाए।

इन सभी मामलों में Rockसिर्फ एक डेटा ऑब्जेक्ट है और जब तक हम काल्पनिक परिणामों के बजाय उपयोगी परिणामों के साथ विशिष्ट व्यवहार को परिभाषित नहीं करते हैं, तब तक एक ही रहेगा।


इसे इस्तेमाल करे:

जब आप 2 संभावित विभिन्न अर्थों के साथ 'ग्राहक' शब्द को ओवरलोड करने से बचते हैं तो इससे चीजों को अवधारणा को आसान बनाना चाहिए।

क्या कोई Rockऑब्जेक्ट ऑर्डर करता है या ऐसा कुछ है जो एक इंसान आपके सिस्टम में कार्रवाई को ट्रिगर करने के लिए यूआई तत्वों पर क्लिक करके करता है?


ग्राहक एक ऐसा अभिनेता है जो कई चीजें करता है, लेकिन इसके साथ जुड़ी जानकारी का एक बहुत कुछ होता है; क्या यह एक डेटा ऑब्जेक्ट के रूप में 2 अलग-अलग वर्गों, 1 को एक अभिनेता और 1 के रूप में बनाने का औचित्य साबित करता है?
इंटेलीडाटा

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

0

मैं एसक्यूएल-बोलने वाली वस्तुओं के दृष्टिकोण का उल्लेख करते हुए अपने 2 सेंट यहां जोड़ रहा हूं ।

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

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

अंत में, मैं यह नोट करना चाहूंगा कि सबसिस्टम में सिस्टम अपघटन के साथ ऑब्जेक्ट खोजने की प्रक्रिया बहुत समान है । दोनों व्यवहार पर आधारित हैं, कुछ और नहीं।

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