21

私のチームは、アーキテクチャ戦略としてドメイン駆動設計に固執しようと懸命に努力しています。しかし、ほとんどの場合、私たちのドメイン エンティティはかなり貧弱です。ドメイン エンティティに、より多くのビジネス/ドメインの動作を追加したいと考えています。

たとえば、アクティブ レコードはエンティティにデータ アクセスを配置します。私たちは喜んでデータ アクセスにリポジトリ パターンを使用しているため、これは望ましくありません。

また、ソフトウェアを SOLID (ボブおじさんがまとめた 5 つのソフトウェア設計原則) になるように設計しています。したがって、エンティティを設計する際に、単一の責任、開閉、リスコフ、インターフェイスの分離、および依存関係の逆転に注意を払うことが重要です。

では、どのような種類の動作を含める必要がありますか? どのような種類のものを避けるべきですか?

4

4 に答える 4

29

この質問をしてからほぼ 1 年が経ちましたが、それ以来、私と私のチームは多くのことを学びました。今日、この質問に私が答える方法は次のとおりです。

ドメインは、ビジネスが何であるか、または (実生活で) 何を行っているかを (コードで) 表す必要があります。したがって、ドメイン エンティティは、実際のビジネスで見られるアーティファクトまたはアクターです。それらの現実のアーティファクトと俳優はどのような行動をとりますか? それのすべて。次に、ドメインエンティティはどのような振る舞いをすべきでしょうか? それのすべて。

たとえば、実生活では、マネージャーは新しい従業員を雇うことができます。そのドメインの表現には、「マネージャー」や「新入社員」などのエンティティが含まれている必要があります。マネージャーは俳優です、ここで。

//newEmployee comes from somewhere else... possibly the UI
//someManagerId comes from the logged in user
var manager = _repository.Get<Manager>(someManagerId);
manager.Hire(newEmployee);

したがって、マネージャー エンティティは、現実のビジネスの行動をモデル化/反映します。別の方法は、マネージャ エンティティをアクターとしてスキップし、彼を追い詰めて、面倒な「ドメイン サービス」がすべての作業を実行できるようにすることです...次のように:

//newEmployeeService comes from somewhere else... possibly injected using IOC
newEmployeeService.Create(newEmployee, someManagerId);

貧血ドメインでは、このようなドメイン サービスを使用して従業員を作成または雇用します。機能しますが、表現力がなく、動作がわかりにくいです。誰が何をしますか?マネージャーが新しい従業員を作成する必要があるのはなぜですか?


最初に質問したとき、エンティティにもっと多くの動作を含めたいと思ったのですが、エンティティにサービスを注入しないと (たとえば、コンストラクター注入を使用して) どうすればよいかわかりませんでした。それ以来、私たちはいくつかの新しいトリックを学び、私たちのチームのエンティティは非常に表現力豊かです. 簡単に言えば、私たちがやっていることは次のとおりです。

  1. 可能であれば、アクター エンティティを使用して、アクションを実行している人または物を表現しようとします。
  2. アクターには、実行できるアクションを表現するメソッドがあります
  3. サービスが必要な場合は、それが使用されるメソッドに引数として挿入されます。
  4. すべてのドメイン エンティティのすべてのメソッドでBlingBagを使用してドメイン イベントを発生させ、拡張性を提供し、エンティティに自己永続化機能を提供します。
于 2012-08-28T20:40:50.760 に答える
4

ドメインエンティティにどのような動作をさせる必要があるかを尋ねる必要がある場合は、おそらくDDDは必要ありません。私はここで役立つように努めています。なぜなら、DDDが属していない場所にDDDを収めようとするのに多くの苦労があったからです。

DDDまたはドメインモデルでさえ、ドメインの複雑さが高すぎて他のパターンが機能しないことが発見されたに従うことができるパターンです。したがって、CRUDだけではDDDには適していません。私の理解では、DDDは、集約ルートの状態を遷移する前に実行する必要のある複雑なビジネスルールを含む制限されたコンテキストがある場合に適しています。したがって、複合体の定義には検証を含めません。

エンティティに入れたい動作の種類は、解決しようとしているビジネス上の問題と密接に関連しています。永続性(リポジトリなど)に関する懸念は後で発生する必要があります(実際、永続性はワークフローまたはイベントストアにある可能性があります)。

お役に立てれば。

于 2012-03-08T14:08:56.080 に答える
1

ドメイン、エンティティ、または値オブジェクトに入れようとするいくつかの動作。

永続化前の検証。新しい状態に移行する前の検証。たとえば、注文集約ルート エンティティは、Sent 状態になる前に、その内部状態とその集約子を検証できます。get set プロパティを最小限に抑え、値オブジェクトをできるだけ使用します。まず、モデルの動作がより豊かになります。エンティティはより説明的になります。次に、パラメーターとしてアドレス値オブジェクトを取る人物エンティティで ApplyAdress メソッドのような値オブジェクト メソッドを使用する必要がある場合、エンティティを無効な状態にすることはめったにありません。

さらに...情報インテリジェンス。エンティティとその値オブジェクトを使用して、集計情報を制御および制限します。personidentity と同様に、個人の一意性を処理する値オブジェクトにすることができます。ssn、ssn アルゴリズムをカプセル化し、ssn の性別チェックサムを処理します。

于 2011-10-17T18:36:21.877 に答える
0

エンティティでの動作は、ビジネスモデルを反映している必要があります。そのエンティティに対して、またはそのエンティティによって実行できることは、ビジネスの世界は、エンティティクラスに対して、またはエンティティクラスによって実行できる洗練されたものでなければならないということです。例えば:

オンラインショッピングシステムでは、商品をカートに追加できます。したがって、Cartクラスは次のようになります。

public class Cart
{
    //...

    public void AddProduct(Product product)
    {
        ...code to add product to cart.
    }
}

methidsはユースケースを反映する必要があると主張することができます。

于 2012-03-08T13:20:06.443 に答える