2

我有一个简单的Store类,其中包含一个Inventory. Inventory包含 s 的列表Item。为了修改Items 中的一个Inventory,我必须写:

Store store( /*parameters*/ );
store.accessInventory(/*password*/).accessItem(/*item name*/).setPrice(9.50);

据我了解,这违反了得墨忒耳法则,因为Store必须通过Inventory并进入Item才能调用setPrice()

我想调和这种违法行为与典型案例中的违法行为,即纸童和客户。在报童的例子中,报童通过假设他会用钱包付款而对客户“了解”太多。如果客户的付款方式发生变化,报童也必须改变。

我的代码中的哪些假设可能会导致类似纸男孩示例中遇到的问题?

我知道法律实际上更像是一个指导方针,在这种情况下遵守它可能不是最好的主意,但我想在继续之前至少了解一下法律。谢谢。

4

3 回答 3

4

您的代码假设 Inventory 对象是价格变化时唯一需要通知的对象。

想象一下,除了包含物品清单外,您的商店还挂有一些广告海报。

如果你遵循得墨忒耳法则,你的 Store 对象可能有一个像这样的好方法:

void Store :: SetItemPrice(string item_name, float item_price)
{
   inventory.SetItemPrice(item_name, item_price);

   for (int i=0; i<num_advertising_posters; i++)
   {
      // Update any posters with the new price!
      if (advertising_posters[i].advertised_item == item_name)
      {
         advertising_posters[i].SetAdvertisedPrice(item_price);
      }
   }
}

...但是如果您改为允许调用代码直接访问库存对象,那么就没有简单/万无一失的方法来确保在价格更新时始终更新广告,因此很有可能在某些时候您的商店广告海报将显示产品的旧/错误价格。得墨忒耳法则更容易避免这种错误。

于 2012-05-28T04:40:44.770 回答
1

您的示例非常接近报童示例。您的代码依赖于具有 setPrice(float) 方法的当前 Item 接口。如果您更改该界面,则需要更新

store.accessInventory(password).accessItem(name).setPrice(price)

它发生的任何地方。

更好的解决方案是为表单的 Store 和 Inventory 创建函数

void Store::setItemPrice(string password, string name, float price)
{
  accessInventory(password).setItemPrice(name, price);
}

void Inventory::setItemPrice(string name, float price)
{
accessItem(name).setPrice(price);
}

这样,您可以在其余代码中使用这些函数,并在您的 Item 或 Inventory 接口发生更改时相应地更改它们。

于 2012-05-28T04:47:51.000 回答
1

我的代码中的哪些假设可能会导致类似纸男孩示例中遇到的问题?

愤怒的顾客。愤怒的人员。愤怒的经理。愤怒的会计师。

当列出的价格高于他们收取的价格时,客户不介意感到惊讶,但当他们收取的价格高于他们预期的价格时,他们肯定会得到 PO。工蜂不喜欢愤怒的顾客来找他们,因为愚蠢的新手店长没有遵守协议,直接在库存中更改价格。低层和中层管理者也不喜欢这样,因为他们从四面八方感到悲痛。Bean 计数器也喜欢在其 bean 的值突然变化时得到通知。

杰里米在回答中提到的不仅仅是广告海报。需要告诉某人更改指定价格的一堆物品旁边的小定价标签。需要派出一群人使用便携式打印机来更改印在该类型每件商品上的价格。这些人需要被安排,你最好不要在没有与部门经理交谈的情况下这样做。等等等等。通过库存来改变价格是一个坏主意。

顺便说一句,以上所有内容都来自认为得墨忒耳法则更好地称为得墨忒耳的偶尔有用建议的人。

于 2012-05-28T05:24:13.527 回答