DDDドメイン駆動設計で

演習の例を見つけるためにマイクロタイムサービスとドメイン駆動設計DDD、次のを見ました。

読み取りカタログ

DDDドメイン駆動設計スタディ 1

はじめに:ほぼ半分の月が書き込み何かをしなかったし、このような自分のために非常に残念な感じがあります。より多くの忙しい人がブログを書く時間を持っている:今日は書いたブログ記事を見ました。ああ、それは自分自身に忙しい人々を証明するために、ブロガー、少しの真実と思われる、それは次のDDD背の高い音のようなことを学ぶ必要はありません。MEFとAOPの下で知識の前に導入され、後者はAutomapper、ストレージモード、WCFや他のものを共有していきますが、毎回の手は、このようなストレージモードとして、デモが困惑して書き込み、書き込み何かに準備ができてその友人を通じて、あなたはこの読む前に、あなたのプロジェクトがDDDアーキテクチャ設計とストレージの導入に合わせていない場合、それは、非常に苦痛になる悪いと、それは非常に「弱い」ようになりますことを知っている必要があり  ブログの大きな庭をあなたが被害を受けている牛は、Entity Frameworkのは、リポジトリのデザインパターンの記述する必要はありません  記事の友人をするだけでなく記事の著者を覚えておく必要があり、公園内のコメントで友人の多くも、悪い気分でそれを使用して言及しました。ブロガーはまた後で完全な感覚を維持することがより困難なコードを書くにつながる、ストレージモードの導入が、良いアーキテクチャ、統一されたデータアクセス層のインターフェイスとストレージの実装の有無にかかわらず、同様の問題に遭遇し突出さ倉庫にはほとんど利益をもたらしました。この本:ブロガーは、共有ストレージモードが一緒に最近、「対策のソフトウェアの複雑道路.Eric.Evaコアドメイン駆動設計」を見ていると、「モードに」誤解を読者のために非常に簡単です単純だと思うので、ブログのダニエルdax.netパークDDDシリーズ、私は、倉庫Automapper、WCFおよびその他の知識のポイントを説明するためにデモモードを共有するようにします。

まず、ドメイン駆動設計の基本的な考え方

よる「ドメイン駆動設計:道路.Eric.Evaコアソフトウェアの複雑さに対処するために、」ブックの表示、ドメインモデルは、ソフトウェアプロジェクトの共通言語のコアは、普遍的な言語は、その後、DDDを遵守するために、ドメインの専門家や開発者がルールですそう、より良い、ドメイン駆動設計を理解し、ビルド理解とドメインモデルがかなり必要になる分割するためには、言うまでもなくをモデル化することの重要性内部。もっと重要な概念のいくつかの内部DDDファーストルック:

図1に示すように、ドメインモデル:フィールドと、各クラス間の関係を表現するデータ・モデルにモデルの異なる領域、ビューのドメイン駆動設計点の観点から、データベースが外部エンティティを格納するための唯一の機構であり、それは技術レベルに属するものです。データモデルは主に永続モードのモデルオブジェクト記述フィールドに使用され、この点から最初のドメインモデル、データのみのモデル、マッピングのいくつかの種類を介して対応するデータモデルに起因するドメインモデルのニーズ、EFの最新があるはずコードファーストは良い表現です。ドメインモデルは、エンティティ、値オブジェクトおよびサービスにオブジェクト。

2は、エンティティは:どのフィールド駆動設計では、エンティティは、個々のモデルオブジェクトを区別する必要があります。ここでは、エンティティ内のエンティティとEntityFrameworkは概念ではありません、実体データへのEFのエンティティは、オブジェクトの振る舞いが含まれていません。ブロガーへの理解DDDの概念、エンティティは、(EFのモデル)の組み合わせと動作を備えたエンティティデータです

図3に示すように、オブジェクトの値:全体的な概念に関連する複数の属性の組み合わせであるオブジェクト属性値によって識別されるオブジェクト。比較すると、エンティティ、値オブジェクトは物理的アイデンティティよりも一つだけ少ないです。論争の対象の設計値の比較、私たちはオブジェクトとエンティティ間の差の値があることを覚えてみましょう:(1)企業が一意の識別子を持っており、オブジェクトの値がありません。(2)実体が変化することが許可されていますが、オブジェクトの値の変更を許可していません。(3)裁判官すべてのオブジェクトの属性値の等しい2つのエンティティを決定するエンティティの識別に等しい等しく、物体の決定された値は、2つの内部標準の値に等しいです。

4、聚合(以及聚合根):聚合表示一组领域对象(包括实体和值对象),用来表述一个完整的领域概念。而每个聚合都有一个根实体,这个根实体又叫做聚合根。举个简单的例子,一个电脑包含硬盘、CPU、内存条等,这一个组合就是一个聚合,而电脑就是这个组合的聚合根。博主觉得关于聚合的划分学问还是挺大的,需要在实践中慢慢积累。同一个实体,在不同的聚合中,它可能是聚合根,也可能不是,需要根据实际的业务决定。聚合根是聚合所表述的领域概念的主体,外部对象需要访问聚合内的实体时,只能通过聚合根进行访问,而不能直接访问

5、领域服务:博主的理解,领域模型主张富领域模式,也就是说把领域逻辑尽量写在领域实体里面,也就是常说的“充血模式”,而对于业务逻辑,最好是以服务的形式提供。至于领域逻辑和业务逻辑的界定,这个要根据实际情况来定。总之,领域服务是用来处理那些领域模型里面不好定义或者某些可变逻辑的的时候才会用到。待验证!

6、工厂、仓储等概念留在Demo里面说明。

 

二、领域驱动设计开始之旅

1、项目分层

领域驱动设计将软件系统分为四层:基础结构层、领域层、应用层和表现层。来看看书中的分层:

其实在dax.net的系列中这张图更能说明这种架构

 

2、项目架构

博主打算用权限系统的案例说明的领域驱动设计的项目架构。项目严格按照表现层、应用层、领域层、基础设施层来划分。

表现层:MVC的Web项目,负责UI呈现。

应用层:WCF服务,负责协调领域层的调用,向UI层提供需要的接口。

领域层:定义领域实体和领域逻辑。

基础设施层:一些通用的技术,比如AOP、MEF注入、通用的工具类、DTO模型层,这里为什么要有一个DTO模型层,DTO是用于UI展现用的纯数据Model,它不包含实体行为,是一种贫血的模型。

整个项目的调用方式严格按照DDD设计来进行,UI层通过WCF服务调用应用层的WCF接口,WCF服务通过仓储调用领域层里面的接口,基础设施层贯穿其他各层,在需要的项目中都可以引用基础设施层里面的内库。

 

3、代码示例

接下来,博主就根据自己的理解,从零开始使用这种架构写一个简单的权限管理系统。由于是领域驱动设计,所以,文章的重点会放在领域层,项目使用了EF的Model First来进行,先设计实体,后生成数据库。

3.1 首先来看看表结构

 

首先建好对应的表实体,然后根据模型生成数据库

将生成的sql语句执行后就可以得到对应的表结构。

 

3.2 聚合的划分

在领域层里面我们新建一个BaseModel,里面有三个类

这三个类IEntity、IAggregateRoot、AggregateRoot分别定义了实体的接口、聚合根的接口、聚合根的抽象实现类。

复制代码
    //用作泛型约束,表示继承自该接口的为领域实体
    public interface IEntity
    {

    }
复制代码
复制代码
复制代码
    /// <summary>
    /// 聚合根接口,用作泛型约束,约束领域实体为聚合根,表示实现了该接口的为聚合根实例,由于聚合根也是领域实体的一种,所以也要实现IEntity接口
    /// </summary>
    public interface IAggregateRoot:IEntity
    {

    }
复制代码
复制代码
复制代码
复制代码
   /// <summary>
    /// 聚合根的抽象实现类,定义聚合根的公共属性和行为
    /// </summary>
    public abstract class AggregateRoot:IAggregateRoot
    {
        
    }
复制代码
复制代码

这里定义接口的作用是定义实体和聚合根的泛型约束,抽象类用来定义聚合根的公共行为,目前为止,这些接口和类里面都是空的,后面会根据项目的需求一步一步往里面加入逻辑。

在EF里面由edmx文件会生成实体的属性,前面说到领域模型主张充血模式,所以要在EF的实体model里面加入实体的行为,为了不改变EF生成实体的代码,我们使用partial类来定义实体的行为。我们来看Model文件夹下面的代码

复制代码
复制代码
    public partial class TB_DEPARTMENT: AggregateRoot
    {
        public override string ToString()
        {
            return base.ToString();
        }
    }
复制代码
复制代码
    public partial class TB_MENU : AggregateRoot
    {

    }
复制代码
    /// <summary>
    /// 由于不会直接操作此表,所以TB_MENUROLE实体不必作为聚合根,只是作为领域实体即可
    /// </summary>
    public partial class TB_MENUROLE:IEntity
    {
    }
复制代码
    public partial class TB_ROLE:AggregateRoot
    {
    }
    public partial class TB_USERROLE:IEntity
    {
    }
    public partial class TB_USERS:AggregateRoot
    {
    }

我们看到,这些实体,只有TB_MENUROLE和TB_USERROLE不是聚合根,其他实体都是聚合根。我这里大概划分为4个聚合:

聚合1:TB_DEPARTMENT实体

聚合2:TB_MENU实体

聚合3:TB_USERS、TB_USERROLE、TB_DEPARTMENT、TB_ROLE这4个为一个聚合,聚合根是TB_USERS。

聚合4:TB_ROLE、TB_USERS、TB_USERROLE、TB_MENUROLE、TB_MENU这5个表为一个聚合,聚合根是TB_ROLE。

可能这样分会有一定的问题,后续出现再慢慢纠正。

到这里,聚合的划分基本完了。


发布了18 篇原创文章 · 获赞 4 · 访问量 2万+

おすすめ

転載: blog.csdn.net/ostriches/article/details/80195658