केवल सेट-प्रॉपर्टी रखने की अनुशंसा क्यों नहीं की जाती है?


9

आज काम पर मेरे एक सहयोगी ने मेरे कोड की समीक्षा की, और सुझाव दिया कि मैं एक सेट-प्रॉपर्टी को हटा देता हूं और इसके बजाय एक विधि का उपयोग करता हूं।

जैसा कि हम दोनों अन्य चीजों में व्यस्त थे, उसने मुझे Property Design"फ्रेमवर्क डिज़ाइन दिशानिर्देश" पुस्तक के अनुभाग को देखने के लिए कहा । पुस्तक में लेखक ने सिर्फ बचने के लिए कहा है:

गेटटर की तुलना में व्यापक पहुंच वाले सेटर के साथ गुण

और अब मैं सोच रहा हूँ कि केवल सेट-प्रॉपर्टी रखने की सिफारिश क्यों नहीं की जाती है? क्या कोई मेरे लिए स्पष्ट कर सकता है?


6
क्या आप उस स्थिति का वर्णन कर सकते हैं जहां आपको लगा कि केवल-सेट संपत्ति उपयुक्त थी? यह जवाबों को थोड़ा और प्रासंगिक बना सकता है।
जॉन एफएक्स 22'11

1
मैं एक ऐसे उदाहरण के बारे में सोचने की कोशिश कर रहा हूं, जो अर्थपूर्ण रूप से अर्थपूर्ण है। केवल एक चीज जो दिमाग में आती है वह Passwordएक Userवर्ग पर एक संपत्ति है । आप इसे सेट कर सकते हैं, लेकिन आप इसे प्राप्त नहीं कर सकते। तब आपके पास आसानी से HashedPasswordसंपत्ति हो सकती है। सेट पर कॉल करने से हैश होता और HashedPasswordप्रॉपर्टी बदल जाती । अगर आप ऐसा करते तो मैं आप पर चिल्लाता नहीं।
स्कॉट व्हिटलॉक

जवाबों:


15

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

यहां Microsoft के संपत्ति उपयोग दिशानिर्देशों का एक प्रासंगिक अनुभाग दिया गया है :

गुण बनाम विधियाँ

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

  • जब सदस्य तार्किक डेटा सदस्य है, तो किसी संपत्ति का उपयोग करें। निम्नलिखित सदस्य घोषणाओं में, Nameएक संपत्ति है क्योंकि यह वर्ग का एक तार्किक सदस्य है।
public string Name
{
    get 
    {
        return name;
    }
    set 
    {
        name = value;
    }
}

एक विधि का उपयोग करें जब:

  • ऑपरेशन एक रूपांतरण है, जैसे कि Object.ToString
  • ऑपरेशन इतना महंगा है कि आप उपयोगकर्ता से संवाद करना चाहते हैं कि उन्हें परिणाम को कैशिंग करने पर विचार करना चाहिए।
  • एक्सेसर का उपयोग करके एक संपत्ति मूल्य प्राप्त getकरना एक नमूदार साइड इफेक्ट होगा।
  • उत्तराधिकार में दो बार सदस्य को बुलाने से अलग परिणाम मिलते हैं।
  • निष्पादन का क्रम महत्वपूर्ण है। ध्यान दें कि एक प्रकार के गुण किसी भी क्रम में सेट और पुनर्प्राप्त करने में सक्षम होना चाहिए।
  • सदस्य स्थिर है, लेकिन एक मूल्य देता है जिसे बदला जा सकता है।
  • सदस्य एक सरणी देता है। गुण जो सरणियाँ लौटाते हैं, वे बहुत भ्रामक हो सकते हैं। आमतौर पर आंतरिक सरणी की एक प्रति वापस करना आवश्यक होता है ताकि उपयोगकर्ता आंतरिक स्थिति को बदल न सके। यह, इस तथ्य के साथ युग्मित है कि एक उपयोगकर्ता आसानी से मान सकता है कि यह एक अनुक्रमित संपत्ति है, अक्षम कोड की ओर जाता है। निम्नलिखित कोड उदाहरण में, मेथड्स प्रॉपर्टी के लिए प्रत्येक कॉल सरणी की एक प्रति बनाता है। परिणामस्वरूप, सरणी के 2 ^ n + 1 प्रतियां निम्नलिखित लूप में बनाई जाएंगी।
Type type = // Get a type.
for (int i = 0; i < type.Methods.Length; i++)
{
   if (type.Methods[i].Name.Equals ("text"))
   {
      // Perform some operation.
   }
}

[... लंबा उदाहरण छोड़ दिया ...]

केवल-पढ़ने और लिखने के लिए केवल गुण

जब उपयोगकर्ता उपयोगकर्ता के तार्किक डेटा सदस्य को परिवर्तित नहीं कर सकता, तो आपको केवल-पढ़ने के लिए गुण का उपयोग करना चाहिए। केवल लिखने के गुणों का उपयोग न करें।


हां - कम से कम आश्चर्य का सिद्धांत यहां संचालित होता है।
पॉल बुचर

6

क्योंकि यह ज्यादातर मामलों में कोई मतलब नहीं रखता है। आपके पास कौन सी संपत्ति हो सकती है जिसे आप सेट कर सकते हैं लेकिन पढ़ नहीं सकते हैं?

यदि OO वास्तविक दुनिया का बेहतर प्रतिनिधित्व करने के लिए है, तो एक सेट केवल संपत्ति का सुझाव देने की संभावना है कि आपका मॉडलिंग सुंदर है।

संपादित करें : यह भी देखें: /programming/4564928/are-set-only-properties-bad-ults जो अनिवार्य रूप से कहते हैं कि यह अनजाने में है और एक सेट केवल संपत्ति मूल रूप से दूसरे नाम से एक विधि है, इसलिए आप इसका उपयोग कर सकते हैं तरीका।


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

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

@MasonWheeler कि लगभग नहीं है Foo Foo { private get; set; }? मैं केवल कि लिखने फोन नहीं होगा
Caleth

6

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

सेट-ओनली प्रॉपर्टी के बजाय मेथड का इस्तेमाल करना यूजर के लिए थोड़ा कम भ्रमित करने वाला होगा। नाम विधि का आम तौर पर दर्शाता सेट या मिल- , लेकिन संपत्ति के नाम सामान्य रूप से मतलब नहीं होता कि कुछ कर सकते हैं केवल और सेट किया जा नहीं मिल जा। मुझे लगता है कि अगर संपत्ति "ReadOnlyBackgroundColour" की तरह कुछ थी, तो यह अन्य कोडर के लिए भ्रमित नहीं होगा, लेकिन यह सिर्फ अजीब लगेगा।


मैं सहमत हूं, लेकिन इस मामले में एक सेटर विधि अलग कैसे होगी?
ट्रैविस क्रिश्चियन

1
@ ट्राविस क्रिश्चियन: ऐसा लगता है कि ओपी ऐसी स्थिति के साथ काम कर रहा है, जहां एक सेटर है लेकिन कोई गेट्टर नहीं है। इसलिए वे कुछ सेट कर सकते हैं, लेकिन वे कभी नहीं जान पाएंगे कि क्या यह बाद में बदलता है।
FrustratedWithFormsDesigner

@ सौंपे गए, लेकिन वे यह भी कभी नहीं जान पाएंगे कि क्या किसी विधि के साथ फिर से कुछ बदल दिया गया था।
एडम लेअर

@ एना लर्न ♦: यदि कोई गेटर है, तो आप इसका उपयोग करने से पहले कम से कम मूल्य का परीक्षण कर सकते हैं यदि आपके पास अपने कोड में एक बिंदु है जहां आपके द्वारा निर्धारित मूल्य अचानक संदेह में हो सकता है।
FrustratedWithFormsDesigner

3
@ मैं सहमत हूँ। यह सिर्फ इतना है कि सवाल सेट-प्रॉपर्टी बनाम एक ही काम करने के तरीके का उपयोग करने के बारे में था।
एडम लेअर

-1

यह एक बहुत पुराना विषय है, लेकिन इस अंतिम चरण में मेरे विचार में कूद गया है और मुझे कुछ टिप्पणियां पसंद हैं क्योंकि मैं केवल लिखने के गुणों के लिए मामला बनाने की कोशिश करता हूं ...

मेरे पास ऐसी ActiveReportकक्षाओं का एक सेट है जो एक वेबसाइट का हिस्सा हैं जो कि कई उपयोगकर्ता चयनों के बाद तुरंत चालू हो जाते हैं और पोस्टबैक पर चलते हैं।

VB कोड कुछ इस तरह दिखता है:

  Public Class SomeReport
    Private greader As New GenericReporting.CommonReader("AStoredProcedure", 
                                      {New SqlParameter("budget_id", 0)})

    Public WriteOnly Property BudgetID As Integer
      Set(value As Integer)
        greader.Parameters("budget_id").Value = value
      End Set
    End Property

    Public Sub New(Optional budget_id As Integer = 0)
      ' This call is required by the designer.
      InitializeComponent()

      ' Add any initialization after the InitializeComponent() call.
      BudgetID = budget_id
    End Sub
  End Class

ये रिपोर्ट जेनेरिक हिम्मत का उपयोग करती हैं, CommonReaderएक संग्रहीत प्रक्रिया और डिफ़ॉल्ट SqlParameterएस का एक सरणी लेती है , जिनमें से प्रत्येक में एक संबद्ध संपत्ति होती है, जो रिपोर्ट डिजाइन के आधार पर, इंस्टेंटेशन पर एक पैरामीटर के रूप में पारित किया जा सकता है या उपयोगकर्ता द्वारा इंस्टेंटेशन से पहले सेट किया जा सकता है रिपोर्ट Runविधि को कॉल करना ।

  '''''''''''''''''''''''
  ' Parameter taken from a user selected row of a GridView
  '
  Dim SomeBudgetID As Integer = gvBudgets.SelectedDataKey.Values(budget_id)

  '''''''''''''''''''''''      
  ' On Instantiation
  '
  Dim R as ActiveReport = New SomeReport(SomeBudgetID)
  R.Run()

  '''''''''''''''''''''''      
  ' Or On Instantiation using "With" syntax
  '
  Dim R as ActiveReport = New SomeReport() With {.BudgetID = SomeBudgetID}
  R.Run()

  '''''''''''''''''''''''
  ' Or After
  '
  Dim R as ActiveReport = New SomeReport()
  R.BudgetID = SomeBudgetID
  R.Run()

इसलिए, जैसा कि मैं इसे देखता हूं, इस मामले में केवल-लेखन संपत्ति है

  1. अनुमति देता है मजबूत प्रकार की जाँच के रूप में SqlParameterएस सामान्य की तरह हैं
  2. रिपोर्ट बनाने पर अधिक लचीलापन, रिपोर्ट तत्काल उपलब्ध हो सकती है यदि सभी पैरामीटर उपलब्ध हैं या बाद में जोड़े जाते हैं जैसे वे उपलब्ध हो जाते हैं।
  3. गुण तात्कालिकता पर "वाक्य रचना" के साथ समर्थन करते हैं
  4. क्या "गेट्टर" वास्तव में आवश्यक है क्योंकि पैरामीटर उपयोगकर्ता को ज्ञात हैं और रिपोर्ट द्वारा परिवर्तित नहीं किए गए हैं?
  5. चूँकि SqlParameters एक वर्ग हैं और आदिम मूल्य नहीं हैं, इसलिए WriteOnly गुण पैरामीटर सेट करने के लिए एक सरल इंटरफ़ेस की अनुमति देते हैं

तो यह मेरे विचार हैं।

क्या मैं इसे एक विधि में बदल सकता हूं? यकीन है लेकिन इंटरफ़ेस लगता है ... कम अच्छा

  R2.BudgetID = SomeBudgetID

बनाम

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