web-dev-qa-db-ja.com

アイテムごとに複数の場所を持つ倉庫/在庫管理システムの構築

[〜#〜] wms [〜#〜]を次の基本要件で構築しています:

  1. Itemは複数のLocationに含めることができます。
  2. Locationには複数のItem sを含めることができます。
  3. Location/itemの組み合わせごとに、追跡できる必要があります:QtyOnHandQtyReserved、およびQtyAvailable
  4. Locationには別のLocationを含めることができます。

ロケーションに必要な基本的な動作は次のとおりです。

  1. ItemQuantityで追加/削除します。
  2. ネストされたLocationの追加/削除。
  3. Location内の各Itemの追跡量。

OOP設計原則に忠実でありながら、コードを記述しようとしています:

  1. dataではなくbehaviourを反映するようにクラスインターフェイスを設計する。
  2. Getter/Setter sの回避。
  3. 教えてください、尋ねないでください、可能な限り。

これを念頭に置いて、次はLocationの基本コードです。

public class Location{

    private final Map<InventoryItem, Integer> items = new HashMap<>();
    private final Set<Location> locations = new HashSet<>();

    public void add(InventoryItem item, int quantity) {
         if (items.containsKey(item)) {
             InventoryQuantity inventoryQuantity = items.get(item);
             items.put(item, inventoryQuantity.addQuantityOnHand(quantity));
         } else {
             items.put(item, quantity);
         }
    }

    public void add(Location location) {
        locations.add(location);
    }

    public void remove(InventoryItem item, int quantity) {
        if (items.keySet().contains(item)) {
            if ((items.get(item) - quantity) == 0) {
                items.remove(item);
            } else {
                items.put(item, items.get(item) - quantity);
            }
        }
    }

    public void remove(Location location) {
        locators.remove(location);
    }

}

追加/削除の基本的な振る舞いができたので、数量を追跡するための最良の方法を理解するのに苦労しています。 InventoryQuantityクラスを次のように作成できます。

 public class InventoryQuantity {

    private InventoryItem item;

    private int quantityOnHand;

    private int quantityReserved;

    private int quantityAvailable;

    public InventoryItem getItem() {
        return item;
    }

    public void setItem(InventoryItem item) {
        this.item = item;
    }

    public int getQuantityOnHand() {
        return quantityOnHand;
    }

    public void setQuantityOnHand(int quantityOnHand) {
        this.quantityOnHand = quantityOnHand;
    }

    public int getQuantityReserved() {
        return quantityReserved;
    }

    public void setQuantityReserved(int quantityReserved) {
        this.quantityReserved = quantityReserved;
    }

    public int getQuantityAvailable() {
        return quantityAvailable;
    }

    public void setQuantityAvailable(int quantityAvailable) {
        this.quantityAvailable = quantityAvailable;
    }
}

InventoryItemごとに1つのInventoryQuantityLocationに格納します。

private final Map<InventoryItem, InventoryQuantity> items = new HashMap<>();

私の質問/問題は次のとおりです。

  1. InventoryQuantityは、定義されたbehavior;を持つ実際のオブジェクトではないようです。むしろ、それはデータ構造の量を格納することを唯一の目的とするようですデータ(ゲッター/セッターの存在によって証明されるように);もっと良い方法はありますか?
  2. getQuantityOnHandForItem(item)に場所を尋ねることはTell、do n't Askの違反ですか?一方、データを取得するためのより良い方法はないようです...

実際にもっと質問がありましたが、今はこれを覚えています。誰かが原理を効果的に理解/適用するのを手伝ってくれるなら、私はそれを大いに感謝します!

3
IntelliData

次のようなクラスがあることは、システムで意味がありますか?

public class QuantifiedInventoryItem extends InventoryItem
{
    private int quantityOnHand;

    private int quantityReserved;

    private int quantityAvailable;

    /* getters and setters for fields above, if necessary */
}

上記のように、InventoryQuantityのようなオブジェクトを持つのはlittleと思われることに同意します。これには動作がなく、実際のオブジェクトにマップされません。

A quantifiedInventoryItemは、実際のオブジェクトにマッピングできます(まあ、InventoryQuantityよりもよくマッピングされます)。 。

の限り:

GetQuantityOnHandForItem(item)の場所を尋ねると、Tellの違反になりますか?

いいえ、それは違反ではないと思います。 "Tell、Do n't Ask"は、オブジェクトの内部状態に依存する複雑なロジックがあり、その状態が多くのゲッターを介してアクセスされる状況を指していると思います。原則は、そのロジック/動作intoをオブジェクトに移動することを指します。これは、それを駆動するデータがすでに存在する場所だからです。

getQuantityOnHandForItemの場合、この関数によって引き起こされる特定の動作について尋ねているわけではないので、関数の単純な存在はおそらく問題ではありません。 Locationのゲッターを常に呼び出す一連のロジックステートメントがある場合、そのロジックを新しい関数withinLocationにリファクタリングすることを検討する価値があります。

参照: https://martinfowler.com/bliki/TellDontAsk.html