2010-11-30 13 views
8

हाल ही में मैं अपने ऑब्जेक्ट मॉडल और उनके परिणामी परिस्थितियों और साइड इफेक्ट्स में पढ़ने-लिखने निर्भरता मुद्दों पर नाटकीय रूप से कटौती करने के लिए अपरिवर्तनीय वस्तुओं का लाभ उठा रहा हूं (अंततः कुछ कोड का उपयोग करने के लिए, अंततः कोड को सरल बनाने के लिए प्रबंधन (कार्यात्मक-प्रोग्रामिंग-एस्क्यू की तरह)।इंटरफेस का उपयोग करके पढ़ने और लिखने की चिंताओं को अलग करने का सबसे अच्छा तरीका?

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

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

public interface IValuableItem { 
    decimal Amount {get;} 
    string Currency {get;} 
} 

हालांकि मैं सोच कैसे मैं एक प्रदान करना चाहिए करने के लिए मिल गया:

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

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

// companion writer 
public interface IValuableModifier { 
    decimal Amount {set;} 
    string Currency {set;} 
} 

या

// explicit methods to enforce importance of or deviance in the programming 
public interface IValuableModifier { 
    void SetAmount(decimal val); 
    void SetCurrency(string cur); 
} 

या

// companion writer that inherits the original interface 
public interface IValuableModifier : IValuableItem { //... 

या

// Let a concrete class choose one and/or the other. 
class Concrete : IValuableModifer, IValuableItem { //... 

या

आदि ..
मेरे अन्यथा अपरिवर्तनीय प्रोग्रामिंग मॉडल पर लिखने में मुझे और क्या मदद कर सकता है और इसे कम से कम लचीला रखने के लिए या कम से कम चिंताओं को बेहतर नियंत्रण के लिए अलग करने में मदद कर सकता है?

+0

एक ऐसी कक्षा जिसमें 'सार्वजनिक' या 'संरक्षित' संपत्ति है जो केवल 'सेट' एक्सेसर प्रदान करती है, कोड विश्लेषण चेतावनी [CA1044: गुण केवल लिखना नहीं चाहिए] (https://msdn.microsoft.com/ en-us/पुस्तकालय/ms182165.aspx)। – DavidRR

उत्तर

9

मुझे लगता है कि मैं इस तरह अपने विचारों का एक प्रकार है, कुछ का उपयोग हो सकता है:

public interface IValuableItem 
{ 
    decimal Amount { get; } 
    string Currency { get; } 
} 

public interface IMutableValuable : IValuableItem 
{ 
    new decimal Amount { set; get; } 
    new string Currency { set; get; } 
} 

class Item : IMutableValuable 
{ 
    public decimal Amount { get; set; } 
    public string Currency { get; set; } 
} 

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

+0

+1: * मुझे नहीं लगता कि यह एक इंटरफेस रखने के लिए समझ में आता है जिसमें सेटर्स हैं लेकिन कोई गेटर्स * नहीं है - जब तक इसके लिए वैध औचित्य न हो। –

+0

@ KMån - मैं सहमत हूं। मैंने केवल कुछ बार सेटर इंटरफेस रखने की कोशिश की है, लेकिन लगभग हमेशा आपको थोड़ी सी "क्षमता-योग्यता" की आवश्यकता होती है, इसलिए यह इसके लायक नहीं है। आप उत्परिवर्तनीय और अपरिवर्तनीय इंटरफेस को विरासत में प्राप्त करके 'IMutableValuable' बना सकते हैं, लेकिन यह यागनी है। – Kit

+0

@ केएमएएन: यह उचित हो सकता है जब आप एक कार्यात्मक अर्थपूर्ण को लागू करना चाहते हैं, मूल्यांकन के दौरान साइड इफेक्ट से परहेज करना, जैसे किसी वस्तु का जटिल मूल्यांकन सुनिश्चित करना वस्तु के राज्यों पर अपने मूल्यांकन के दौरान निर्भर नहीं होता है। ऐसे मामले में, इसे पढ़ने के लिए केवल एक इंटरफ़ेस प्रदान करने के लिए उचित ठहराया जा सकता है। यद्यपि उचित रूप से डिज़ाइन करना आसान नहीं है, खासकर यदि आप विधियों को सही तरीके से निर्दिष्ट करना चाहते हैं, जिन्हें आम तौर पर पढ़ने के तरीकों को पढ़ने के संदर्भ की आवश्यकता होती है। – Hibou57

1

मेरा मानना ​​है कि आपकी तीसरी और चौथी पसंद का संयोजन म्यूटेबल & अपरिवर्तनीय प्रकारों को लागू करने का एक बेहतर तरीका है।

Public interface ImmutableItem { 
    decimal Amount {get;} 
    string Currency {get;} 
} 

Public interface MutableItem: ImmutableItem { 
    decimal Amount {set;} 
    string Currency {set;} 
} 

class Concrete : ImmutableItem { 
    //Only getters 
} 


class Concrete : MutableItem { 
    //Both getters & setters 
} 

यह साफ है और यह ठोस वर्ग तय करने के लिए अस्थिरता किस तरह की बाहरी दुनिया को बेनकाब करना चाहता था कर रहा है।

+2

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

3

यदि आपकी वस्तुएं अपरिवर्तनीय हैं (और आप अपरिवर्तनीय डेटा की अवधारणा के आसपास अपना आवेदन डिज़ाइन करते हैं) तो ऑब्जेक्ट्स वास्तव में अपरिवर्तनीय रहना चाहिए।

अपरिवर्तनीय परिदृश्यों में डेटा संशोधित करने के लिए विहित विधि नई वस्तुओं को बनाने के लिए है, इसलिए मैं कुछ इस तरह का सुझाव देते हैं:

public interface IValuableItem<T> 
{ 
    decimal Amount { get; } 
    string Currency { get; } 
    T CreateCopy(decimal amount, string currency); 
} 

public class SomeImmutableObject : IValuableItem<SomeImmutableObject> 
{ 
    public decimal Amount { get; private set; } 
    public string Currency { get; private set; } 

    public SomeImmutableObject(decimal amount, string currency) 
    { 
     Amount = amount; 
     Currency = currency; 
    } 

    public SomeImmutableObject CreateCopy(decimal amount, string currency) 
    { 
     return new SomeImmutableObject(amount, currency); 
    } 
} 

SomeImmutableObject obj = new SomeImmutableObject(123.33m, "GBP"); 
SomeImmutableObject newObj = obj.CreateCopy(120m, obj.Currency); 
2

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

ध्यान दें कि बिल्डर ऑब्जेक्ट पूरी तरह से लक्षित ऑब्जेक्ट बनाने के लिए मौजूद हैं - बिल्डर्स लक्ष्य ऑब्जेक्ट के उदाहरण नहीं हैं/लक्ष्य को लागू नहीं करते हैं स्वयं इंटरफेस।

यह आपके सिस्टम को अपरिवर्तनीय वस्तुओं पर चलाने के प्रयास के लायक है, क्योंकि अपरिवर्तनीयता थ्रेडिंग/समरूपता/समांतर निष्पादन परिदृश्यों के साथ-साथ डेटा कैशिंग/डेटा संस्करण परिदृश्यों में बहुत से सिरदर्द को धो देती है।

4

आपके पास पठनीय फू, इम्यूटेबलफू और म्यूटेबलफू के लिए अलग-अलग इंटरफेस होना चाहिए। बाद वाले दो को पहले से ही उत्तराधिकारी होना चाहिए। पठनीय फू में एक "AsImutable" विधि होनी चाहिए जो एक फू को वापस कर देगी जो अपरिवर्तनीय होने की गारंटी है (एक अपरिवर्तनीय उदाहरण स्वयं को वापस करना चाहिए; एक परिवर्तनीय उदाहरणों को एक नया अपरिवर्तनीय उदाहरण लौटा देना चाहिए जिसमें इसका डेटा शामिल है), और शायद एक "AsNewMutable" सदस्य (जो एक नया डेटा परिवर्तनीय उदाहरण बनाएगा जिसमें एक ही डेटा होगा, चाहे मूल म्यूटेबल हो या नहीं)।

कोई कक्षा इम्यूटेबलफू और म्यूटेबलफू दोनों को लागू नहीं करनी चाहिए।

+0

मुझे यह उत्तर भी दिलचस्प लगता है।आप कह रहे हैं 'चाहिए' - क्या यह एक सामान्य अभ्यास या कल्पना पर आधारित है जिसे मैं और अधिक पढ़ सकता हूं? –

+0

@ जॉन के: यदि कोई वस्तु अपरिवर्तनीय होने का दावा करती है, तो यह किसी भी व्यक्ति का वादा करता है जो इसका उपयोग करता है कि यह कभी नहीं बदलेगा। यदि कोई वस्तु उत्परिवर्तनीय होने का दावा करती है, तो यह वादा करता है कि इसका उपयोग करने वाले किसी भी व्यक्ति को इसे बदलने की अनुमति दी जाएगी, और (जब तक वापस नहीं बदला जाता) तो परिवर्तन अगली बार ऑब्जेक्ट पढ़ने पर दिखाई देगा। मुझे लगता है कि किसी के पास "ModelTFordColor" वर्ग हो सकता है जो अपरिवर्तनीय और परिवर्तनीय दोनों था (जब भी आप चाहें इसे सेट कर सकते हैं, जो भी रंग आप चाहते हैं, जब तक कि यह काला हो, और उसका रंग आपके द्वारा सेट किया जाएगा) लेकिन मैं ' एक वर्ग के लिए उत्परिवर्तनीय और अपरिवर्तनीय दोनों के लिए किसी उपयोगी परिदृश्य के बारे में सोचें। – supercat

+1

@ जॉन के: मैं यह नहीं कहूंगा कि कोई वर्ग "इम्यूटेबलफू और म्यूटेबलफू दोनों को लागू नहीं कर सकता है (क्योंकि कुछ भी कक्षा को ऐसा करने से रोकता है) लेकिन मामूली मामलों को छोड़कर जहां एक म्यूटेटर का कोई वास्तविक प्रभाव नहीं हो सकता, कोई भी वर्ग दोनों इंटरफेस लागू करता है उनमें से कम से कम एक के अनुबंध का उल्लंघन करेगा। – supercat

संबंधित मुद्दे