加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 程序设计 > 正文

.NET领域驱动设计―看DDD是如何运用设计模式颠覆传统架构

发布时间:2020-05-22 15:28:49 所属栏目:程序设计 来源:互联网
导读:阅读目录: 1.开篇介绍 2.简单了解缘由(本文的前期事宜) 3.DomainModel扩展性(运用设计模式设计模型变化点) 3.1.模型扩展性 3.2.设计模式的使用(苦心专研的设计模式、设计思想可以随意使用了) 3.3.部分类的使用(封装内部对象) 3.4.高强度的OO设计(面

阅读目录:

  • 1.开篇介绍

  • 2.简单了解缘由(本文的前期事宜)

  • 3.DomainModel扩展性(运用设计模式设计模型变化点)

    • 3.1.模型扩展性

    • 3.2.设计模式的使用(苦心专研的设计模式、设计思想可以随意使用了)

    • 3.3.部分类的使用(封装内部对象)

    • 3.4.高强度的OO设计(面向特定领域的高度抽象设计形成特定领域框架)


  • 4.DomainModel业务逻辑规则配置(将扩展点分离后使用适当的配置将规则IOC进去)

  • 5.DDD简单总结(DDD是什么?它是“战术”)


1】开篇介绍

这篇文章不会太长,但是绝对让你对DDD有一个比较直观的认可;

这篇文章所讲到的内容虽然不多但是不太容易被领悟(因为多数人对DDD的理解还是存在很大误区的;),当然也不是多么神奇的东西,只不过是本人最近一直研究DDD的成果一个小小的心得与大家分享一下;本文讲的这些设计方式本身就存在着很大优势,你会发现它与传统三层架构最明显的区别,这也是最有经典优势的地方,最有价值的地方;

本来这篇文章是“[置顶].NET领域驱动设计―实践(穿过迷雾走向光明)”一文的一部分但是由于时间关系,完整的示例并没有跟文章同步发布,说实话时间太紧,写示例的目的是想全面的且细致的阐述DDD的分析、设计各个环节的最佳实践;原本想将文章的示例做好后在发布,但是由于工作关系和一些私人原因可能有一段时间不更新博客,又不想这篇文章拖的太久,所以我总结了两点比较有价值的地方分享给大家,目的不是让大家能会使用DDD来设计系统,而是能有一个突破点来衡量DDD到底比传统三层好在哪里,因为大部分人还没有DDD的开发经验所以能体会到应该没有相关途径;

网上很多的DDD文章有的还很不错,但是本人也是从对DDD一窍不通再到目前对DDD有一个整体的了解,觉得最大的问题是让能没有接触DDD的朋友能最贴切的体会到DDD到底哪里好,而不是一上来就大片的理论还一些UML模型图;其实完整的示例也只有这两点最有价值了,因为它是DDD所强调的中心;

2】.简单了解缘由(本文的前期事宜)

开始本文下面的章节之前先来了解一下我们将要做什么设计,我假设您没有时间阅读“[置顶].NET领域驱动设计―实践(穿过迷雾走向光明)”一文,比较文章也有点长了,所以这里简单介绍一下连续性的内容;

这篇文章我们将运用两个常规的框架设计方法来对核心的业务进行细粒度的分解设计,在以往这点很难实现,所以我为什么要说框架的设计思想,因为我们对设计模式的运用主要在框架、组件这些非业务需求性的基础设施上;那么这里我们将用这些强大的武器来对最难对付的业务扩展性的设计;

本文全部的业务其实是一个简单的学习考试系统的背景,我们下面将要运用强大的设计能力来对【Employee】聚合进行细粒度的设计、配置;之前的设计已经全部结束,数据持久化也设计完成,就剩下编码阶段;编码的最大挑战就在于前期的相关接口的设计,这里是细粒度的接口设计,不是简单的分分层;

图1:

.NET领域驱动设计―看DDD是如何运用设计模式颠覆传统架构

(查看大图)

上图中我用红圈标记出我们下面要扩展的【Employee】聚合,在将模型落实到代码后我们将要通过规约模式来将【Employee】的验证对象化,然后通过设计模式的策略模式将规则策略化,再通过Configuraion Manager来管理所有的业务规则的配置,这个时候IOC就派上用场了,一切都很顺手;传统三层你是无法做到的;

请看下面【Employee】实体类代码:

/*==============================================================================
 * Author:深度训练
 * Create time: 2013-07-08
 * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 * Author Description:特定领域软件工程实践;
 * ==============================================================================*/
namespace Domain.DomainModel.ExaminationModule.Aggregates.EmployeeAgg
{
    using System;
    using System.Collections.Generic;
    using Domain.DomainModel.ApproveModule.Aggregates.ParentMesAgg;
    using Domain.DomainModel.ExaminationModule.Aggregates.FieldExaminationAgg;
    using Domain.Seedwork;
    public partial class Employee : EntityObject
    {
        public Employee()
        {
            this.ParentMessage = new HashSet<ParentMessage>();
            this.TeacherCheckGroup = new HashSet<TeacherCheckGroup>();
        }
        public string EID { get; set; }
        public string EName { get; set; }
        public Nullable<Employee_Marry> IsMarry { get; set; }
        public Nullable<int> Age { get; set; }
        public string UserName { get; set; }
        public string PassWord { get; set; }
        public Nullable<Employee_Switch> SWitch { get; set; }
        public Nullable<Employee_Role> EmpRole { get; set; }
        public Nullable<Employee_Sex> Sex { get; set; }
        public virtual ICollection<ParentMessage> ParentMessage { get; set; }
        public virtual ICollection<TeacherCheckGroup> TeacherCheckGroup { get; set; }
        public void ReSwitch()
        {
            if (this.SWitch.Value == Employee_Switch.IsFalse)
                this.SWitch = Employee_Switch.IsTure;
            else
                this.SWitch = Employee_Switch.IsFalse;
        }
        public void Reinitial()
        {
            PassWord = "000000";
        }
    }
}


【Employee】聚合跟一般的聚合没多大区别,比较简单的结构,为了看起来完整一点,我加入了两个初始化的行为;ReSwitch是用来启用、关闭当前账户;

Reinitial是初始化当前【Employee】的初始默认密码,完全是演示而用;

那么我们下面要做什么呢?在以【Employee】为聚合根里面我们聚合了【ParentMessage】家长留言、【TeacherCheckGroup】站考,两个集合,其实这是用来做导航属性的;实体框架需要这些信息做实体导航使用,在设计的时候你需要权衡你需要多少这样的关联;

现在经过我们对需求的深入分析之后可能会存在这样的变动情况:

【Parent家长】向【Employee教师】【留言】后,教师需要对留言内容做出反馈,比如要【及时的回复】,对于不同的【留言级别】需要给出不同的处理;

这个需求很简单,但是它里面透露出来的是什么?设计的扩展性,这个扩展性在哪里?对于不同的【留言级别】需要给出不同的【处理】,很显然是一个可能随时会变化的点;

【Employee_Priority】代码:

/*==============================================================================
 * Author:深度训练
 * Create time: 2013-07-08
 * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 * Author Description:特定领域软件工程实践;
 * ==============================================================================*/
namespace Domain.DomainModel.ApproveModule.Aggregates.ParentMesAgg
{
    using Domain.DomainModel.ExaminationModule.Aggregates.EmployeeAgg;
    using System;
    public partial class ParentMessage
    {
        public string PMID { get; set; }
        public string PID { get; set; }
        public string EID { get; set; }
        public string Content { get; set; }
        public Nullable<Message_Priority> Priority { get; set; }
        public Nullable<System.DateTime> Datetime { get; set; }
        public virtual Employee Employee { get; set; }
        public virtual Parent Parent { get; set; }
    }
}

有一个Priority属性,是标记该留言的紧急情况,看代码:

/*==============================================================================
 * Author:深度训练
 * Create time: 2013-07-08
 * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 * Author Description:特定领域软件工程实践;
 * ==============================================================================*/
namespace Domain.DomainModel.ExaminationModule.Aggregates.EmployeeAgg
{
    using System;
    public enum Message_Priority : int
    {
        Normal = 1,Pressing = 2
    }
}

有两种级别,Normal表示普通的,Pressing表示紧急的,对于紧急的肯定是需要先处理的,而且处理的逻辑或多或少有点不同;在DDD中所有的业务逻辑都要在DomainModel Layer 中处理,这是原则;所有的逻辑都不是直接使用,比如在登录的时候我们通常是验证用户名密码是否真确,但是通常还会有很多其他的条件,比如说当前用户是否是高级会员、是否欠费等等,这些都是在聚合规约工厂中统一获取的,这就便于我们将变化的点抽到专门的地方进行设计;

逻辑判断的地方原则是不直接写IFELSE,逻辑处理地方原则是不直接写实现代码,通过接口实现策略类;

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读