web-dev-qa-db-ja.com

DDDでアドレスタイプをモデル化する方法は?

Userエンティティがあり、SetAddressである場合、Addressは値オブジェクトです。

_class User{
    ...
    private Set<Address> addresses;
    ...
    public setAddresses(Set<Address> addresses){
        //set all addresses as a batch
    }
    ...
}
_

Userには_home address_と_work address_を含めることができるので、データベースのルックアップとして機能するものが必要です。

tbl_address_type

 --------------------------------------------- --- 
 | address_type_id | address_type | 
 ------------------------------------------- ----- 
 | 1 |仕事| 
 ------------------------------------------- ----- 
 | 2 |ホーム| 
 ------------------------------------------- ----- 

そして対応してtbl_address

 --------------------------------------------- ---------------------------------------- 
 | address_id | address_description | address_type_id | user_id | 
 ------------------------------------------- ------------------------------------------ 
 | 1 | 123メインストリート| 1 | 100 | 
 ------------------------------------------- ------------------------------------------ 
 | 2 | 456別の通り| 1 | 100 | 
 ------------------------------------------- ------------------------------------------ 
 | 3 | 789ロングストリート| 2 | 200 | 
 ------------------------------------------- ------------------------------------------ 
 | 4 | 023ショートストリート| 2 | 200 | 
 ------------------------------------------- ------------------------------------------ 
  1. 住所タイプはエンティティタイプまたは値タイプとしてモデル化する必要がありますか?なぜ?
  2. Address ValueオブジェクトがエンティティAdressTypeへの参照を保持してもよいですか(エンティティとしてモデル化されている場合)?これはHibernate/NHibernateを使用して実現可能ですか?
  3. ユーザーが自宅の住所を変更できる場合、Userエンティティ自体にUser.updateHomeAddress(Address homeAddress)関数を公開する必要がありますか?この場合、クライアントが職場の住所ではなく自宅の住所を渡すように強制するにはどうすればよいですか? (サンプル実装は大歓迎です)
  4. User.getHomeAddress()関数を介してユーザーのホームアドレスを取得する場合、アドレス配列全体をロードしてから、ループして、正しいタイプが見つかるまでそれぞれのタイプをチェックし、それを返す必要がありますか?これよりも効率的な方法はありますか?
7
Songo

タイプはアドレスのプロパティではなく、ユーザーとアドレス間の接続のプロパティだと思います。

アドレスは通常、世界の特定の場所を表します。タイプは、ユーザーがアドレスを使用する用途に関連付けられます。

アドレスは、一部のユーザーの自宅と会社の両方に使用される場合もあります。または、あるユーザーのホームと別のユーザーの職場になります。

そう:

  1. アドレスは値タイプである必要があります。
  2. AddressTypeに接続しないでください
  3. 私にとっては、ユーザーが持つと予想されるアドレスの数と、型が静的になるかどうかに依存します。
  4. ある種のマップの方が効率的です...
5
Adagios

DDDの観点から、私が自分に尋ねる質問は、「住所はそれが自宅または会社であるか、またはあなたは何を知っているか」です。

答えはおそらくノーです。少し良いモデルは、ユーザーに表示されているようなアドレスコレクションを持たせることですが、必要に応じて自宅/ビジネス/プライマリアドレスを指すプロパティを追加することもできます。

技術的な注意点の1つは、パッケージの配達の目的で、住所に「Is Residential」フラグを設定し、「Is PO Box」フラグを設定してそれらを除外することで、アドレスオブジェクトが理解する必要のあるもの。

2
Wyatt Barnett

ユーザーは3つ以上のアドレスを必要としますか?めったにありません。アドレスのコレクションを非正規化することをお勧めします。

ユーザーは単にフィールドaddress_homeaddress_workaddress_otherここで、3つすべてがAddressタイプになり、値タイプになります。

このモデルは、99.99%のユースケースをカバーし、はるかに理解しやすく、コードに簡単に実装でき、リレーショナルモデルとドキュメントモデルの両方にはるかによくマッピングされます。

また、リレーショナルDBを使用する場合は、Userテーブルにすべてのデータを含めることができるため、検索が大幅に高速化されます。

非正規化がオプションでない場合の場合、アドレスをMap/Dictionaryとしてモデル化し、アドレスを値として、文字列または何らかの列挙型をキーとして使用します。 Addressは不変の値オブジェクトであり、リレーショナルモデルは、userIdからの複合主キーとマップのキーを持つ単一のテーブルになります。したがって、アドレス自体には識別子がありません。テーブルの残りの部分は住所のデータです。これにより、モデルがシンプルで理解しやすくなります。しかし、ディクショナリーとリレーショナル・テーブルの間のマッピングはそれほど単純ではないかもしれません。しかし、それはまだ実行可能です。

2
Euphoric

誰もが欠けているように見えるのは、単一のアドレスが複数のユーザーによって使用される可能性があることです。

だからあなたは次のようなものが必要です:

User  Usage Addr
   1      1    1
   1      2    2
   2      1    3
   2      2    2
   3      1    1

Id  Number     Street        Town
1   23         Accai Drive   Hoboken
2   15         Wall Street   N.Y.C
3   99         First Street  Armonk       

このようにして、カレッジ間でオフィスの場所を共有し、同棲者間で自宅の住所を共有できます。また、在宅勤務者の「勤務先」アドレスに何を入力するかという問題も解決します。

1
James Anderson

住所タイプは、エンティティタイプまたは値タイプとしてモデル化する必要がありますか?なぜ?

そのアドレスはドメインモデルの候補だと思います。アドレスオブジェクトが検証動作を行うことはよくあります。たとえば、特定のフィールドが設定されていること、または設定する前に郵便番号が有効であることを確認できます。郵便番号の検証は住所オブジェクトで行われるべきではないと主張する人もいます。これは議論の余地があります。

(エンティティとしてモデル化されている場合)アドレス値オブジェクトがエンティティAdressTypeへの参照を保持しても問題ありませんか?これはHibernate/NHibernateを使用して実現可能ですか?

AddressTypeがデータアクセスレイヤーで定義されていることを前提としています。この場合、ある時点で、プレゼンテーション層またはサービス層でアドレスを公開する必要があります。突然、データレイヤーロジックがプレゼンテーションレイヤーとサービスレイヤーにリークします。

ユーザーが自宅の住所を変更できる場合、Userエンティティ自体にUser.updateHomeAddress(Address homeAddress)関数を公開する必要がありますか?この場合、クライアントが職場の住所ではなく自宅の住所を渡すようにするにはどうすればよいですか? (サンプル実装は大歓迎です)

User.updateHomeAddress(Address homeAddress)が正しい方法だとは思いません。私はあなたのシステムでユーザーが主要な役割を果たすと想定しています。ユーザー関連の懸念を1つのUserクラスにまとめません。ユーザーに多くの責任を与えるほど、コードの保守が難しくなります。

解決策の1つは、アドレスを更新するためのコマンドクラスを持つことです。

例えば。

public class UpdateHomeAddressCommand 
{
   private User _user;
   private Address _address;

   public UpdateHomeAddressCommand(User user, Address address)
   {
      _user = user;
      _address = address;
   }       

   public void Execute()
   {
       // Update logic
   }
}

上記の例では、簡単なコマンドを使用して住所を更新しています。自宅と職場の住所を更新するロジックが非常に似ている場合は、抽象クラスに移動してUpdateHomeAddressCommandを抽象UpdateAddressCommandから継承させることができます。

User.getHomeAddress()関数を介してユーザーのホームアドレスを取得する場合、アドレス配列全体をロードし、ループして、正しいタイプが見つかるまでそれぞれのタイプをチェックし、それを返す必要がありますか?これよりも効率的な方法はありますか?

理想的には、データレイヤーは必要なデータのみを返す必要があります。それ以外の場合は、ネットワーク上を移動する不要なデータです。

0
CodeART