ドメインに次のオブジェクトがあるとします。
class Warehouse
{
int Id;
string Address;
Item[] Inventory;
}
class Item
{
int Id;
string Name;
int Price;
int WarehouseId;
}
私はすべての倉庫とすべてのアイテムのコレクションを持っています。私はRESTスタイルでそれらへのアクセスを提供するためにWeb APIを使用しています。したがって、倉庫を取得すると、次のようになります。
{
"Id": 1,
"Address": "123, 1st street",
"Inventory":
[
{ "Id" : "1", "Name": "LED TV", "Price" : "1300", "WarehouseId" : "1" },
{ "Id" : "2", "Name": "Console", "Price" : "500", "WarehouseId" : "1" },
]
}
ウェアハウスエンドポイントへのPUTリクエストの結果はどうなりますか?
明らかに、それは提供されたものでアドレスを上書きするべきです。しかし、それは在庫も上書きするべきでしょうか?
アイテムのコレクションに含まれていない新しいアイテムが含まれている場合はどうなりますか?作成する必要がありますか?
以前に存在したアイテムのいずれかが含まれていない場合はどうなりますか?削除しますか?
倉庫とアイテムを分けます:
GET api/warehouse
Gets a list of warehouses
PUT api/warehouse/{warehouseid}
Updates some meta information on that warehouse (address etc)
GET api/warehouse/{warehouseid}/inventory
Gets the inventory of the warehouse (you can supply some search parameters to narrow
GET api/warehouse/warehouseid}/inventory/{itemid}
Gets a particular item, details, how many in warehouse, etc.
DELETE api/warehouse/warehouseid}/inventory/{itemid}
Delete a particular item from that inventory or at least decrements the qty that is stored in the warehouse by one.
などなど。
Inventoryが本当にWarehouseリソースの一部である場合、PUTはInventory配列の状態をオーバーライドする必要があります。どのようにバックエンドにデータを保存するか。 RDBMSまたはNoSQL DBは、RESTエンドポイントのセマンティクスに影響を与えるべきではありません。コンシューマーが気にするリソースは、基になるデータ構造ではなく、APIのリソースであるため、セマンティクスを作成する必要があります。公開しているリソースと整合性があります。ただし、PUTがSQLテーブルで挿入を実行することになるかどうかに関係なく、バックエンドで動作させると、定義されたリソースのPUTセマンティクスが整合している限り、問題はありません。
とはいえ、この特定のケースでは、@ JonRaynorのようなAPIを提案する方がよいでしょう。この場合、在庫は倉庫のサブリソースです。これにより、IDや住所などのウェアハウスメタデータの更新を、在庫などのトランザクションデータから分離できます。これにより、おそらく(バックエンドデータレイヤーを実装する場合)とコンシューマー( APIの使用方法を理解しようとする場合)。
更新の複雑さを回避する最も簡単な方法は、CRUD指向ではなくユースケース/コマンド指向のエンドポイントを公開することです。たとえば、POST warehouse/{id}/addressChangeエンドポイントには、大規模な更新を行うのではなく、住所の変更に関連するデータのみを取得する場合があります。DDDを実行している場合、これはウェアハウスオブジェクトのパブリックメソッドに直接反映されます。倉庫が集約ルートであると理解されており、在庫アイテム間の(最終的にではなく)トランザクションの一貫性を維持する必要がある場合、在庫アイテムは倉庫オブジェクトを介してのみ変更する必要があります。そして倉庫。