Aunque en el siguiente código se usa una compra simple de un solo artículo en un sitio de comercio electrónico, mi pregunta general es sobre la actualización de todos los miembros de datos para mantener los datos de un objeto en estado válido en todo momento.
Encontré "consistencia" y "estado es malo" como frases relevantes, discutidas aquí: 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();
¿Alguna desventaja, o quizás mejores maneras de hacer esto?
Este es un problema recurrente en las aplicaciones del mundo real respaldadas por una base de datos relacional, y si no utiliza los procedimientos almacenados de forma exhaustiva para insertar toda la validación en la base de datos. Creo que el almacén de datos solo debería almacenar datos, mientras que el código debería hacer todo el estado de tiempo de ejecución manteniendo el trabajo.
EDITAR: esta es una pregunta relacionada, pero no tiene una recomendación de mejores prácticas con respecto a una sola función grande para mantener un estado válido: /programming/1122346/c-sharp-object-oriented-design-maintaining- estado-objeto-válido
EDIT2: Aunque la respuesta de @ eignesheep es la mejor, esta respuesta - /software//a/148109/208591 - es lo que llena las líneas entre la respuesta de @ eigensheep y lo que quería saber: el código solo debe procesarse, y el estado global debe sustituirse por el paso de estado habilitado por DI entre objetos.