DDD战术3 领域设计模型 I

GitChat课程《领域驱动设计--战术篇》笔记,课程作者张逸

一.表达领域设计模型

1.企业应用架构中表达领域逻辑的常见模式:事务脚本、表模块、领域模型

1.1事务脚本
  • 事务脚本将整个领域场景按顺序分解为多个子任务,然后组合为一个完整过程。多数情况一个事务脚本会对应一个数据库事务,该模式仍然从数据库的角度进行思考和设计
  • 面向对象语言可以由一个类实现事务脚本,通常有以下两种实现方式
    1)类的每个public方法等同于一个事务脚本,完成一个完整的领域场景。在public方法内部可以通过组合方法模式(即通过其他方法的调用来组合新的方法)来改进代码的可读性,避免重复逻辑。
    2)引入命令模式,每个事务脚本对应到一个类中,然后根据其通用特征抽象为公共的命令接口或抽象类,每个封装了事务脚本的类都实现该命令接口。
    如下推荐朋友服务的代码采用的就是上述第一种事务脚本模式
public class FriendInvitationService {
    public void inviteUserAsFriend(String ownerId, String friendId) {
        try {
            bool isFriend = friendshipDao.isExisted(ownerId, friendId);
            if (isFriend) {
                throw new FriendshipException(String.format("Friendship with user id %s is existed.", friendId));
            }
            bool beInvited = invitationDao.isExisted(ownerId, friendId);
            if (beInvited) {
                throw new FriendshipException(String.format("User with id %s had been invited.", friendId));
            }

            FriendInvitation invitation = new FriendInvitation();
            invitation.setInviterId(ownerId);
            invitation.setFriendId(friendId);
            invitation.setInviteTime(DateTime.now());

            User friend = userDao.findBy(friendId);
            sendInvitation(invitation, friend.getEmail());

            invitationDao.create(invitation);
        } catch (SQLException ex) {
            throw new ApplicationException(ex);
        }
    } 
}
  • 事务脚本直接而简单,在业务逻辑相对简单时,事务脚本在处理性能和代码可读性都有明显的优势。但这种过程式的设计可能设计出一个庞大的服务类,又由于缺乏明晰的领域概念,随需求的变化与增加,代码容易膨胀,整个软件系统较难维护
1.2表模板
  • 表模块模式持有整个表的数据(而不是数据表的一行),数据库中的一个表对应一个表模块对象,是数据模型驱动设计的直观体现。该对象封装领域逻辑,并包含对表数据进行操作(持久化)的方法
  • 表模块更像是为了解决关系表数据结构的存取问题而定制的模式,能够让领域逻辑与关系数据库的衔接更加简单。表模块对象拥有的数据基本上是自给自足的,可以避免贫血模型的出现,但违背单一职责原则,变得过于臃肿
1.3领域模型
  • 领域模型合并了行为和数据,复杂领域模型按照领域逻辑设计对象,广泛运用继承、策略和其他设计模式,通过数据映射器实现对象与数据的映射
  • 软件复杂度来自重复和变化,领域驱动设计遵循高内聚低耦合的“正交设计”,从角色、职责和协作三个方面考虑职责分配以减少重复,从间接、抽象与分离三个方面考虑抽象接口以应对变化
DDD通过正交设计减少软件复杂度

2.DDD现实对象模型中的问题与解决

现实的对象模型需要考虑外部资源、依赖、性能和数据一致性,与理想模型相比,有诸多设计约束,DDD引入实体、值对象、聚合、资源库、工厂、领域事件等设计要素
2.1领域模型对象如何与数据库协作?
  • 引入资源库(Repository)隔离领域逻辑与数据库实现,并将领域模型对象当做资源,将存储领域对象的介质抽象为仓库
2.2领域模型对象的加载以及对象间的关系如何处理?
  • 引入聚合(Aggregate)划分对象之间的边界,在边界内保证所有对象的一致性,并在对象协作与独立之间取得平衡
2.3领域模型对象在身份上是否存在差别?
  • 区分实体(Entity)与值对象(Value Object),避免不必要的身份跟踪与并发控制
2.4领域模型对象彼此之间如何能弱依赖地完成状态的变更通知?
  • 引入领域事件(Domain Event),通过发布者/订阅者来发布与订阅领域事件
现实世界、对象图模型与领域设计模型三者间关系

3.领域设计要素间关系图

  • Eric Evans 规定只能是实体(Entity)、值对象(Value Object)、领域服务(Domain Service)与领域事件(Domain Event)表示模型。这样的约束就可以避免将太多的领域逻辑泄漏到领域层外的其他地方,例如应用层或基础设施层
  • 其次,图中明确提及使用聚合(Aggregate)来封装实体和值对象,并维持边界内所有对象的完整性。若要访问聚合,需要通过资源库(Repository)来访问,这就隐式地划定了边界和入口,若能做到这一点,对聚合内所有类型的领域对象都可以得到有效的控制。当然,若牵涉到复杂或可变的创建逻辑,还可以利用工厂(Factory)来创建聚合内的领域对象
  • 最后,若牵涉到实体的状态变更(注意,值对象是不牵涉到状态变更的),则通过领域事件来推动
设计要素在DDD中的作用(Eric Evans)

4.领域模型对象的哲学依据

  • 亚里士多德范畴学术将范畴分为十类:实体、数量、性质、关系、地点、时间、形态、状况、活动(主动)、遭遇(被动)
  • 对应DDD中的四种领域模型对象
    1)实体:实体范畴,包含了其他范畴,包括引起属性变化和状态迁移的活动
    2)值对象:为主体对象的属性,通常代表数量、性质、关系、地点、时间或形态
    3)领域事件:封装了主体的状况,代表了因为主动活动导致的状态变迁产生的被动遭遇
    4)领域服务:范畴必须“内居”于一主体,若活动与遭遇代表的业务行为无法找到一个主体对象来“内居”,就以领域服务作为特殊的主体来封装

二.实体

三.值对象

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353