2

を含む単純なStoreクラスがありますInventory。にはのInventoryリストが含まれていますItem。の の1 つを変更するには、次ItemInventoryように記述する必要があります。

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

私が理解しているように、これはデメテルの法則破っStoreています。InventoryItemsetPrice()

この法律違反を、ペーパーボーイと顧客の典型的な例における法律違反と調和させたいと思います。ペーパーボーイの例では、ペーパーボーイは、顧客が財布で支払いを行うと想定することで、顧客について「よく知っている」。顧客の支払い方法が変われば、ペーパーボーイも変更しなければなりません。

ペーパーボーイの例で発生したような問題を引き起こす可能性がある、コード内のどのような仮定が行われていますか?

法律は実際にはガイドラインであり、この場合それを遵守することは最善の考えではないことを理解していますが、先に進む前に少なくとも法律を理解したい. ありがとう。

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

紙の少年の例で遭遇したような問題を引き起こす可能性のある、私のコードのどのような仮定がなされていますか?

怒っている顧客。怒っている人員。怒っているマネージャー。怒っている会計士。

記載されている価格が請求価格よりも高い場合でも、顧客は驚かされることはありませんが、予想よりも高い価格が請求された場合は必ずPOになります。愚かな初心者の店長がプロトコルに従わず、在庫で直接価格を変更したため、怒っている顧客が彼らに近づいたとき、働き蜂はそれを嫌います。低レベルおよび中レベルのマネージャーは、あらゆる側面から悲しみを感じるため、これも好きではありません。Beanカウンターは、Beanの値が突然変化したときにも通知されることを望んでいます。

ジェレミーが彼の答えで言及したのは広告ポスターだけではありません。価格を指定するアイテムのスタックの横にある小さな価格タグを変更するように指示する必要がある人もいます。そのタイプの各アイテムに刻印されている価格を変更するには、乗組員がポータブルプリンターを派遣する必要があります。これらの人々はスケジュールを組む必要があります、そしてあなたは部門マネージャーと話さずにそれをしないほうがよいです。などなど。価格を変更するために在庫に手を伸ばすことは悪い、悪い考えです。

ところで、上記のすべては、デメテルの法則がデメテルの時折有用な提案と呼ばれる方が良いと考える人から来ています。

于 2012-05-28T05:24:13.527 に答える
1

あなたの例は、ペーパーボーイの例に非常によく似ています。コードは、メソッド setPrice(float) を持つ現在の Item インターフェイスに依存しています。そのインターフェースを変更する場合は、更新する必要があります

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

それが発生するすべての場所。

より良い解決策は、フォームのストアとインベントリの機能を作成することです

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 に答える