क्या वैध स्थिति बनाए रखने के लिए एक कक्षा में एक बड़े निजी समारोह को परिभाषित करना एक अच्छा विचार है, जो कि ऑब्जेक्ट के डेटा सदस्यों को अपडेट करना है?


18

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

मैंने प्रासंगिक वाक्यांशों के रूप में "स्थिरता" और "राज्य बुराई है" पाया, यहां चर्चा की: https://en.wikibooks.org/wiki/Object_Oriented_Programming#.22State.22_is_Evil1.1

<?php

class CartItem {
  private $price = 0;
  private $shipping = 5; // default
  private $tax = 0;
  private $taxPC = 5; // fixed
  private $totalCost = 0;

  /* private function to update all relevant data members */
  private function updateAllDataMembers() {
    $this->tax =  $this->taxPC * 0.01 * $this->price;
    $this->totalCost = $this->price + $this->shipping + $this->tax;
  }

  public function setPrice($price) {
      $this->price = $price;
      $this->updateAllDataMembers(); /* data is now in valid state */
  }

  public function setShipping($shipping) {
    $this->shipping = $shipping;
    $this->updateAllDataMembers(); /* call this in every setter */
  }

  public function getPrice() {
    return $this->price;
  }
  public function getTaxAmt() {
    return $this->tax;
  }
  public function getShipping() {
    return $this->shipping;
  }
  public function getTotalCost() {
    return $this->totalCost;
  }
}
$i = new CartItem();
$i->setPrice(100);
$i->setShipping(20);
echo "Price = ".$i->getPrice(). 
  "<br>Shipping = ".$i->getShipping().
  "<br>Tax = ".$i->getTaxAmt().
  "<br>Total Cost = ".$i->getTotalCost();

किसी भी नुकसान, या ऐसा करने के लिए शायद बेहतर तरीके?

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

EDIT: यह एक संबंधित प्रश्न है, लेकिन मान्य स्थिति बनाए रखने के लिए किसी बड़े कार्य के संबंध में सर्वोत्तम अभ्यास की अनुशंसा नहीं है: /programming/1122346/c-sharp-object-oriented-nignign-maintain- वैध-वस्तु राज्य

EDIT2: हालाँकि @ eignesheep का उत्तर सबसे अच्छा है, यह उत्तर - /software//a/148109/208591 है - जो @ eigensheep के उत्तर के बीच की रेखाओं को भरता है और जो मैं जानना चाहता था - कोड केवल प्रक्रिया होना चाहिए, और वैश्विक राज्य को वस्तुओं के बीच डीआई-सक्षम राज्य द्वारा प्रतिस्थापित किया जाना चाहिए।


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

जवाबों:


29

बाकी सभी समान हैं, आपको अपने आक्रमणकारियों को कोड में व्यक्त करना चाहिए। इस मामले में आपके पास अपरिवर्तनीय है

$this->tax =  $this->taxPC * 0.01 * $this->price;

अपने कोड में इसे व्यक्त करने के लिए, कर सदस्य चर निकालें और getTaxAmt () के साथ बदलें

public function getTaxAmt() {
  return $this->taxPC * 0.01 * $this->price;
}

कुल लागत सदस्य चर से छुटकारा पाने के लिए आपको कुछ ऐसा ही करना चाहिए।

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


3
कई भाषाओं में गेटर्स हैं ताकि इस तरह के कार्यों का दिखावा होगा कि वे गुण हैं। दोनों का सबसे अच्छा!
जिज्ञासु 12

उत्कृष्ट बिंदु है, लेकिन मेरा सामान्य उपयोग मामला है जहां कोड एक रिलेशनल डेटाबेस (MySQL में) में कई टेबलों में कई कॉलमों में डेटा संग्रहीत करता है और संग्रहीत करता है और मैं संग्रहीत प्रक्रियाओं (अपने दम पर एक और विषय) और अन्य का उपयोग नहीं करना चाहता। अपने इनवेरिएंट्स-इन-कोड विचार को और आगे ले जाने का अर्थ है कि सभी गणनाओं को "जंजीर": getTotalCost()कॉल getTaxAmt()और इतने पर होना चाहिए । इसका मतलब है कि हम केवल गैर-गणना की गई चीजों को संग्रहीत करते हैं । क्या हम कार्यात्मक प्रोग्रामिंग की ओर थोड़ा बढ़ रहे हैं? यह भी त्वरित पहुँच के लिए तालिकाओं में परिकलित संस्थाओं के भंडारण को जटिल बनाता है ... प्रयोग की आवश्यकता है!
site80443

13

कोई नुकसान [?]

ज़रूर। यह विधि हमेशा कुछ करने के लिए याद रखने वाले सभी पर निर्भर करती है। सभी पर भरोसा करने वाली कोई भी विधि और हमेशा कभी-कभी असफल होने के लिए बाध्य होती है

शायद यह करने के लिए बेहतर तरीके?

याद करने के समारोह के बोझ से बचने का एक तरीका उस वस्तु के गुणों की गणना करना है जो कि अन्य गुणों पर निर्भर करती है, जैसा कि @eigensep ने सुझाया है।

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

$i = new CartItem();
$i->setPrice(100);
$i->setShipping(20);

आपको खुद से पूछना चाहिए; क्या बिना मूल्य का कार्ट आइटम मायने रखता है? क्या किसी वस्तु की कीमत बदल सकती है? इसके बनने के बाद? इसकी कर गणना के बाद? आदि शायद आपको निर्माता में CartItemअपरिवर्तनीय और आत्मसात कीमत और शिपिंग करना चाहिए :

$i = new CartItem(100, 20);

क्या एक कार्ट आइटम उस कार्ट के बिना समझ में आता है जो उसका है?

यदि नहीं, तो मैं $cart->addItem(100, 20)इसके बजाय उम्मीद करूंगा ।


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

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

1
@ site80443 जो मैं देख रहा हूं, उसके आधार पर यह गलत तरीका है। अपने डेटा को ऐसे मॉडल बनाने का प्रयास करें जिसमें केवल वह डेटा जो इसके विरुद्ध मान्य है वह स्वयं शामिल है। उदाहरण के लिए किसी वस्तु की कीमत नकारात्मक नहीं हो सकती, केवल उस पर निर्भर करती है। यदि कोई आइटम छूट जाता है, तो मूल्य में छूट का पहलू न रखें - बाद में छूट के साथ सजाएं। आइटम के लिए $ 4.99 और एक अलग इकाई के रूप में 20% छूट, और 5% कर को किसी अन्य इकाई के रूप में संग्रहीत करें। यह वास्तव में ऐसा लगता है कि आपको डेकोरेटर पैटर्न पर विचार करना चाहिए यदि उदाहरण आपके वास्तविक जीवन कोड का प्रतिनिधित्व करते हैं।
corsiKa 17
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.