2011-12-06 10 views
5

私のプログラミング言語はC#です。ドメインモデル内で永続性の無知に関する質問があります。永続的な無知のドメイン層

のは、私はそうのような人のクラスを持っていると仮定しましょう:

public class Person 
{ 
    private string email; 

    public string Email 
    { 
     get { return email; } 
     set { email = value; } 
    } 

    public Person(string email) 
    { 
     this.email = email; 
    } 
} 

さて、私のドメインモデル内で、同じメールアドレスを持つ二人がすることができないというルールがあります。したがって、新しい人物をインスタンス化するときは、電子メールのプロパティを変更するときだけでなく、検証する必要があります。だから私はあなたが永遠の無知のドメイン層内でそのような検証を解決する方法を考えていた。私が現在行っていることは、人間のインスタンスリポジトリを注入するためのファクトリパターンを使用することです。そこに私は同じ電子メールアドレスを持つ他の人を検索することができます。これと同じように:

public class PersonFactory 
{ 
    private static readonly IPersonRepository personRepository; 

    public Person CreateNewPerson(string email) 
    { 
     Person personWithSameMail = personRepository.GetPersonByEmail(email); 

     if (personWithSameMail != null) 
      throw new ApplicationException("Email already exists."); 

     return new Person(email); 
    } 

    public PersonFactory(IPersonRepository personRepository) 
    { 
     this.personRepository = personRepository; 
    } 
} 

しかし、このソリューションを使用して、(有効なビジネスケースもできる)者の電子メールアドレスを変更し、チェックがまだカバーされていません。さらに、Personクラスはまだ公共のコンストラクタを公開しており、工場をバイパスしても、重複した電子メールアドレスを持つ人は引き続き可能です。

これに対する任意の解決策はありますか?

P.S.すべてのデータに中心の人:いいえ、私はデータアクセス層にだまされやすい人の電子メールを検証する必要はありません。)

UPDATE:

おそらく、この全体の問題はとにかく廃止されました。ドメインモデルの文脈の点で重複した電子メールをチェックするには、常にすべての人物、すなわちルートを意識した「何か」が必要です。 「何か」は、アドレス帳、または電子メールアドレスを持つすべての人を含む全世界である可能性があります。だから、おそらく私は、プログラマーが技術的に洗練された問題解決の必要性を混ぜ合わせているのかもしれません。これはここに当てはまりますか?スペースの中に浮かんでいる電子メールアドレスを持つ人だけではないということです(ちょっと、スペースは私の根源になります)。しかし、これがアドレス帳アプリケーションのような本当のビジネスケースであれば、アドレス帳は人の集約ルートとなり、電子メールアドレスが重複しないように内部コレクションのすべての人物をチェックすることができます。

+0

コンストラクタを内部で作成し、更新時に電子メールアドレスも確認してみませんか?そして私はそれが工場にリポジトリを与えるのはいい解決策だとは思わない。ファクトリを呼び出すサービス関数は、電子メールアドレスがすでに存在するかどうかを確認する必要があります。 –

+0

@WouterdeKort:私はあなたのコメントに同意しません:(1)ctorを内部的にすることは何の助けにもなりません。重複したメールアドレスを持つユーザーを作成することはできます。 (2)工場を呼び出すメソッドをチェックすると、そのビジネスルールが効果的に削除されます。このルールを適用するのは呼び出し側の責任です。それはちょうど非常に貧弱なAPIデザインです。 –

+0

@DanielHilgarth彼は、公共のコンストラクタが問題であることを明示しています。ファクトリは、すべての依存関係と必要な値を持つオブジェクトを作成する必要があります。工場とビジネスロジックを混在させることは、私が悪いデザインと呼ぶものです。 –

答えて

2

私はDDDのエキスパートではありませんが、私はこのようにしています。

まず、あなたのデザインの最大の欠陥は、エンティティ上のセッターを許可することです。これは、を変更することができることを意味します。集約ルートなしでエンティティの状態を知ることができます。私はそれをリファクタリングしてセッターを取り除き、オブジェクト作成時にコンストラクタに設定するだけです。

別の点。個人エンティティは、電子メールが既に使用されているかどうかをチェックする形で電子メールの検証を行うべきではありません。なぜなら、電子メールが自分の州および関連する子エンティティのみを知ることができるからです。それからあなたは、悪いデザインの私のためのエンティティからのリポジトリへの参照を持っている必要があります。だからこそ、私が思う工場をあなたが使ったのです。

私は検証ができるだけ早く失敗するUIで発生する必要がありますと思う。しかしそれは十分ではありません。あなたのドメインの状態を持続させるときには、その人がユニークな電子メールを持っているというルールを強制する必要があります。私は検証がIPersonRepositoryへの参照を持っているでしょうし、個人の電子メールがある場合に持続するために、そのコレクションにPersonエンティティを追加する前に、それは最初にチェックしますPersonRegistrationService呼ば例えばドメインサービスで行われるべきだと思いますユニーク。そうでない場合、ユーザーにエラーを通知し、エンティティを追加しません。

あなたはどう思いますか?

+0

私があなたの提案から理解しているように、人の作成はドメイン内部でなければなりません。そして、登録サービスがあります。これは、ドメインに存在する人物の許可を正当なものとして検証するもののようなものですか?したがって、このサービスは引数としてすべての必要な初期人物プロパティを取得し、リポジトリを挿入することで、「与えられたデータを持つ人は存在しますか?」を世話することができます。 – Chris

+0

私はこのサービスが最初にドメインのコンセプトの一種だと思います。私は登録サービスを提案しました。なぜなら、薄い空気から人を作り出すことは私には意味がないからです。したがって、そのサービスの責任は、議論(または現時点ではドメインの状態に属していないPerson Entity)を取ることです。電子メールがユニークであればリポジトリで確認し、その人を追加します内部のコレクション(これはORMやその他によって保持されますが、ここでは重要ではありません)。 –

+0

多分、他の人がこれに別のことをするでしょうが、ドメインサービスに合格するのは合理的です。実際はあなたの工場と非常に似ていますが、違いはサービスがドメインの意味を持ち、リポジトリ(永続化されたPersonエンティティのコレクションです)に検証を成功させた人を追加することです。 –

関連する問題