Meskipun dalam kode di bawah ini digunakan pembelian barang tunggal sederhana dalam situs e-commerce, pertanyaan umum saya adalah tentang memperbarui semua anggota data untuk menjaga data objek dalam keadaan valid setiap saat.
Saya menemukan "konsistensi" dan "negara itu jahat" sebagai frasa yang relevan, dibahas di sini: 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();
Adakah kerugian, atau mungkin cara yang lebih baik untuk melakukan ini?
Ini adalah masalah berulang dalam aplikasi dunia nyata yang didukung oleh basis data relasional, dan jika Anda tidak menggunakan prosedur tersimpan secara ekstensif untuk mendorong semua validasi ke dalam basis data. Saya pikir bahwa penyimpanan data harus hanya menyimpan data, sementara kode harus melakukan semua kondisi run-time.
EDIT: ini adalah pertanyaan terkait tetapi tidak memiliki rekomendasi praktik terbaik mengenai fungsi besar tunggal untuk mempertahankan status yang valid: /programming/1122346/c-sharp-object-oriented-design-maintaining- valid-object-state
EDIT2: Meskipun jawaban @ eignesheep adalah yang terbaik, jawaban ini - /software//a/148109/208591 - adalah apa yang mengisi garis antara jawaban @ eigensheep dan apa yang ingin saya ketahui - kode hanya boleh diproses, dan negara global harus diganti dengan lewatnya keadaan yang diaktifkan oleh DI di antara objek.
sumber
Jawaban:
Semuanya sama, Anda harus mengekspresikan invarian Anda dalam kode. Dalam hal ini Anda memiliki invarian
Untuk mengekspresikan ini dalam kode Anda, hapus variabel anggota pajak dan ganti getTaxAmt () dengan
Anda harus melakukan sesuatu yang serupa untuk menghilangkan variabel total biaya anggota.
Mengekspresikan invarian Anda dalam kode Anda dapat membantu menghindari bug. Dalam kode asli, total biaya tidak benar jika diperiksa sebelum setPrice atau setShipping dipanggil.
sumber
getTotalCost()
panggilangetTaxAmt()
dan sebagainya. Ini artinya kita hanya menyimpan barang yang tidak dihitung . Apakah kita bergerak sedikit ke arah pemrograman fungsional? Ini juga mempersulit penyimpanan entitas yang dihitung dalam tabel untuk akses cepat ... Membutuhkan eksperimen!Tentu. Metode ini bergantung pada semua orang yang selalu ingat untuk melakukan sesuatu. Metode apa pun yang mengandalkan semua orang & selalu gagal kadang-kadang.
Salah satu cara untuk menghindari beban upacara mengingat adalah menghitung properti objek yang bergantung pada properti lain sesuai kebutuhan, seperti yang disarankan @eigensheep.
Lain adalah membuat item keranjang tidak dapat diubah dan menghitungnya dalam konstruktor / metode pabrik. Anda biasanya akan pergi dengan metode "menghitung sesuai kebutuhan", bahkan jika Anda membuat objek tidak berubah. Tetapi jika perhitungannya terlalu memakan waktu dan akan dibaca berkali-kali; Anda dapat memilih opsi "menghitung selama pembuatan".
Anda harus bertanya pada diri sendiri; Apakah barang keranjang tanpa harga masuk akal? Bisakah harga suatu barang berubah? Setelah dibuat? Setelah pajaknya dihitung? dll. Mungkin Anda harus membuat
CartItem
harga dan pengiriman yang tidak berubah dan penting dalam konstruktor:Apakah item keranjang masuk akal tanpa kereta miliknya?
Jika tidak, saya harapkan
$cart->addItem(100, 20)
sebagai gantinya.sumber