TLDR: リッチ ドメイン モデルと「重い」セッターを単純な HTML フォーム マッピングと組み合わせる方法は?
あるプロパティのセッターが他のプロパティを変更すると問題が発生します (直接またはセッターを使用して - これは問題ではありません)。
よりよく説明するためのサンプルクラス(PHPでは、これは問題ではありません-私は思います):
class Product {
private $name;
private $cost;
private $profit;
private $price;
public function getName() {
return $this->name;
}
public function getCost() {
return $this->cost;
}
public function getProfit() {
return $this->profit;
}
public function getPrice() {
return $this->price;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function setCost($cost) {
if ($this->cost !== $cost) {
$this->cost = $cost;
$this->setPrice($this->getCost() + $this->getProfit());
}
return $this;
}
public function setProfit($profit) {
if ($this->profit !== $profit) {
$this->profit = $profit;
$this->setPrice($this->getCost() + $this->getProfit());
}
return $this;
}
public function setPrice($price) {
if ($this->price !== $price) {
$this->price = $price;
$this->setProfit($this->getPrice() - $this->getCost());
}
return $this;
}
}
このサンプルのアイデアは、(製品の購入/作成の) コストと獲得したい利益を設定できるということです。次に、(製品を販売するための) 価格が計算されます。また、価格を変更することもできます-その後、利益が計算されます。(コストを変更すると、価格ではなく利益が変更される可能性がありますが、問題には関係ありません)。
例えば:
$foo = new Product();
$foo->setName("Foo");
$foo->setCost(100);
$foo->setPrice(110);
assert($foo->getProfit() == 10);
$foo->setProfit(30);
assert($foo->getPrice() == 130);
多くの理由 (つまり、コマンド ライン フロントエンドと CRON ジョブ) により、「バックエンド」コードにリッチ オブジェクトが必要です。
HTML フロントエンドでは、コスト、利益、価格に対応する 3 つの入力を含むフォームを取得します。ユーザーが値を変更してフォームを送信すると、セッターの順序が問題になり、混乱する可能性があります。例えば:
- ユーザーは製品ボタンをクリックして編集します
- 次の値を持つフォームを見る: cost=100、profit=10、price=110
- 利益を 20 に変更します
- フォームを送信
問題は、バックエンド マッパーが POST フォームから値を取得し、setCost(100)、setProfit(20)、次に setPrice(110) を呼び出すことです。これは、120 に変更する必要がある古い価格であるため、不適切です (ユーザーは 20 を希望していました)。利益と 100 コスト)。
私が見る唯一の解決策は、すべてのドメイン モデル ロジックをフロントエンド (JavaScript) にも実装することです。そのため、コスト/利益入力を変更すると、価格入力の値が変更されます。次に、すべての入力に正しい値があり、POST されたデータは「オーバーライド」の問題なしに配置できます。このサンプルでは簡単ですが、多くのフィールドがある場合 (2 つの異なる言語で同じコードを記述すると時間がかかり、エラーが発生しやすくなります)、またはそれらの間のロジックが非常に複雑な場合 (すべてが JS で簡単に実装できるわけではありません) の場合は不可能です。
これを解決する方法はありますか?:)
PS: 一時的なプロパティと遅延評価 (つまり、コストと価格のみがプロパティであり、編集可能であり、利益は常に計算されます) を使用することはできません。私は両方の方法から変更することができなければなりません。また、一部の重い計算には不便です。すべての小道具が存在し、データベースに保存する必要があります。