Chociaż w poniższym kodzie użyto prostego zakupu pojedynczego elementu w witrynie e-commerce, moje ogólne pytanie dotyczy aktualizacji wszystkich członków danych, aby dane obiektu były zawsze aktualne.
Znalazłem „spójność” i „stan jest zły” jako odpowiednie wyrażenia, omówione tutaj: https://en.wikibooks.org/wiki/Object_Oriented_Programming#.22State.22_is_Evil.21
<?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();
Jakieś wady, a może lepsze sposoby na zrobienie tego?
Jest to powtarzający się problem w rzeczywistych aplikacjach wspieranych przez relacyjną bazę danych, a jeśli nie korzystasz z procedur przechowywanych w celu wypchnięcia całej weryfikacji do bazy danych. Myślę, że magazyn danych powinien po prostu przechowywać dane, podczas gdy kod powinien wykonywać cały stan wykonywania pracy utrzymując pracę.
EDYCJA: jest to powiązane pytanie, ale nie ma zalecenia najlepszych praktyk dotyczących jednej dużej funkcji do utrzymania prawidłowego stanu: /programming/1122346/c-sharp-object-oriented-design-maintaining- valid-object-state
EDIT2: Chociaż odpowiedź @ eignesheep jest najlepsza, ta odpowiedź - /software//a/148109/208591 - wypełnia linie między odpowiedzią @ eigensheep a tym, co chciałem wiedzieć - kod powinien tylko przetwarzać, a stan globalny powinien zostać zastąpiony przekazywaniem stanu między obiektami przez DI.
źródło
Odpowiedzi:
Wszystkie pozostałe są równe, powinieneś wyrazić niezmienniki w kodzie. W tym przypadku masz niezmiennik
Aby wyrazić to w kodzie, usuń zmienną podatkową i zamień getTaxAmt () na
Powinieneś zrobić coś podobnego, aby pozbyć się zmiennej członka kosztu całkowitego.
Wyrażenie niezmienników w kodzie może pomóc uniknąć błędów. W oryginalnym kodzie całkowity koszt jest niepoprawny, jeśli zostanie sprawdzony przed wywołaniem setPrice lub setShipping.
źródło
getTotalCost()
wywołaniagetTaxAmt()
i tak dalej. Oznacza to, że zawsze przechowujemy tylko rzeczy nieobliczone . Czy przechodzimy trochę w stronę programowania funkcjonalnego? To także komplikuje przechowywanie obliczonych jednostek w tabelach w celu szybkiego dostępu ... Potrzebuje eksperymentów!Pewnie. Ta metoda polega na tym, że każdy zawsze pamięta o zrobieniu czegoś. Każda metoda polegająca na wszystkich i zawsze zawiedzie się czasami.
Jednym ze sposobów uniknięcia ciężaru zapamiętywania ceremonii jest obliczanie właściwości obiektu, które zależą od innych właściwości w razie potrzeby, jak sugeruje @eigensheep.
Kolejnym jest unieruchomienie koszyka i obliczenie go w metodzie konstruktora / fabryce. Zwykle wybrałbyś metodę „oblicz w razie potrzeby”, nawet jeśli uczynisz obiekt niezmiennym. Ale jeśli obliczenia są zbyt czasochłonne i zostaną odczytane wiele, wiele razy; możesz wybrać opcję „oblicz podczas tworzenia”.
Powinieneś zadać sobie pytanie; Czy produkt w koszyku bez ceny ma sens? Czy cena przedmiotu może się zmienić? Po utworzeniu? Po obliczeniu podatku? itp. Może powinieneś zrobić
CartItem
niezmienną i przypisać cenę i wysyłkę do konstruktora:Czy produkt w koszyku ma sens bez koszyka, do którego należy?
Jeśli nie, oczekiwałbym
$cart->addItem(100, 20)
zamiast tego.źródło