领域模型(domain model)是对领域内的概念类或现实世界中对象的可视化表示。领域模型也称为概念模型、领域对象模型和分析对象模型。

——《UML和模式应用》

我们在日常开发中,经常针对一些功能点争论“这个功能不应该我改,应该是你那边改”,最终被妥协改了之后都改不明白为什么这个功能要在自己这边改。区别于传统的架构设计,领域驱动设计(DDD)也许在这个时候能帮助你做到清晰的划分。

什么是DDD

领域驱动设计最初由Eric Evans提出,但是多年以来一直停留在理念阶段,真正能实现并且落地的项目和公司少之又少,而进来阿里内部其实在大力推行DDD的理念,它主要可以帮助我们解决传统单体式集中架构难以快速响应业务需求落地的问题,并且针对中台和微服务盛行的场景做出指导。

DDD为我们提供的是架构设计的方法论,既面向技术也面向业务,从业务的角度来把握设计方案。

DDD的作用

统一思想:统一项目各方业务、产品、开发对问题的认知,而不是开发和产品统一,业务又和产品统一从而产生分歧。

明确分工:域模型需要明确定义来解决方方面面的问题,而针对这些问题则形成了团队分钟的理解。

反映变化:需求是不断变化的,因此我们的模型也是在不断的变化的。领域模型则可以真实的反映这些变化。

边界分离:领域模型与数据模型分离,用领域模型来界定哪些需求在什么地方实现,保持结构清晰。

DDD的概念

实体

有唯一标志的核心领域对象,且这个标志在整个软件生命周期中都不会发生变化。这个概念和我们平时软件模型中和数据库打交道的Model实例比较接近,唯一不同的是DDD中这些实体会包含与该实体相关的业务逻辑,它是操作行为的载体。

值对象

依附于实体存在,通过对象属性来识别的对象,它将一些相关的实体属性打包在一起处理,形成一个新的对象。

举个栗子:比如用户实体,包含用户名、密码、年龄、地址,地址又包含省市区等属性,而将省市区这些属性打包成一个属性集合就是值对象。

聚合

实体和值对象表现的是个体的能力,而我们的业务逻辑往往很复杂,依赖个体是无法完成的,这时候就需要多个实体和值对象一起协同工作,而这个协同的组织就是聚合。聚合是数据修改和持久化的基本单元,同一个聚合内要保证事务的一致性,所以在设计的时候要保证聚合的设计拆分到最小化以保证效率和性能。

聚合根

也叫做根实体,一个特殊的实体,它是聚合的管理者,代表聚合的入口,抓住聚合根可以抓住整个聚合。

领域服务

有些领域的操作是一些动词,并不能简单的把他们归类到某个实体或者值对象中。这样的行为从领域中识别出来之后应该将它声明成一个服务,它的作用仅仅是为领域提供相应的功能。

领域事件

在特定的领域由用户动作触发,表示发生在过去的事件。比如充值成功、充值失败的事件。

四种模式

失血模型

模型中只有简单的get set方法,是对一个实体最简单的封装,其他所有的业务行为由服务类来完成。

@Data
@ToString
public class User {
private Long id;
private String username;
private String password;
private Integer status;
private Date createdAt;
private Date updatedAt;
private Integer isDeleted;
}
public class UserService{
public boolean isActive(User user){
return user.getStatus().equals(StatusEnum.ACTIVE.getCode());
}
}

贫血模型

在失血模型基础之上聚合了业务领域行为,领域对象的状态变化停留在内存层面,不关心数据持久化。

@Data
@ToString
public class User {
private Long id;
private String username;
private String password;
private Integer status;
private Date createdAt;
private Date updatedAt;
private Integer isDeleted; public boolean isActive(User user){
return user.getStatus().equals(StatusEnum.ACTIVE.getCode());
} public void setUsername(String username){
return username.trim();
}
}

充血模型

在贫血模型基础上,负责数据的持久化。

@Data
@ToString
public class User {
private Long id;
private String username;
private String password;
private Integer status;
private Date createdAt;
private Date updatedAt;
private Integer isDeleted; private UserRepository userRepository; public boolean isActive(User user){
return user.getStatus().equals(StatusEnum.ACTIVE.getCode());
} public void setUsername(String username){
this.username = username.trim();
userRepository.update(user);
}
}

胀血模型

service都不需要,所有的业务逻辑、数据存储都放到一个类中。

对于DDD来说,失血和胀血都是不合适的,失血太轻量没有聚合,胀血那是初学者才这样写代码。那么充血模型和贫血模型该怎么选择?充血模型依赖repository接口,与数据存储紧密相关,有破坏程序稳定性的风险。

建模方法

用例分析法

用例分析法是领域建模最简单可行的方式。大致可以分为获取用例、收集实体、添加关联、添加属性、模型精化几个步骤。

  1. 获取用例:提取领域规则描述

  2. 收集实体:定位实体,

  3. 添加关联:两个实体间用动词关联起来

  4. 添加属性:获取实体属性

  5. 模型精化:可选的步骤,可以用UML的泛华和组合来表达模型间的关系,同时可以做子领域的划分

四色建模法

四色建模法源于《Java Modeling In Color With UML》,它是一种模型的分析和设计方法,通过把所有模型分为四种类型,帮助模型做到清晰、可追溯。

简单来说,四色关注的是某个人的角色在某个地点的角色用某个东西的角色做了某件事情。

事件风暴法

事件风暴法类似头脑风暴,简单来说就是谁在何时基于什么做了什么,产生了什么,影响了什么事情。

架构分层

区别于左图传统架构的分层,一般DDD分层会有一些变化。

Application:包含事件注册、业务逻辑等

Domain:聚合、实体、值对象

InfraStructure:基础设施封装、数据库访问等

总结

DDD是一套完善的方法论,他能帮助我们合理的对系统进行架构设计,同时,好的模板应该是在不断的适应变化,而DDD也能帮助我们更快速更方便的支撑业务的发展。

面试官:谈一下你对DDD的理解?我:马什么梅?的更多相关文章

  1. 看完这篇HTTP,跟面试官扯皮就没问题了

    我是一名程序员,我的主要编程语言是 Java,我更是一名 Web 开发人员,所以我必须要了解 HTTP,所以本篇文章就来带你从 HTTP 入门到进阶,看完让你有一种恍然大悟.醍醐灌顶的感觉. 最初在有 ...

  2. 【MySQL】面试官:如何添加新数据库到MySQL主从复制环境?

    写在前面 今天,一名读者反馈说:自己出去面试,被面试官一顿虐啊!为什么呢?因为这名读者面试的是某大厂的研发工程师,偏技术型的.所以,在面试过程中,面试官比较偏向于问技术型的问题.不过,技术终归还是要服 ...

  3. 浅谈MySQL日志文件|手撕MySQL|对线面试官

    关注微信公众号[程序员白泽],进入白泽的知识分享星球 前言 上周五面试了字节的第三面,深感数据库知识的重要,我也意识到在平时的学习中,自己对于数据库的学习较为薄弱.甚至在有过一定实习经验之后,依旧因为 ...

  4. 面试官的七种武器:Java篇

    起源 自己经历过的面试也不少了,互联网的.外企的,都有.总结一下这些面试的经验,发现面试官问的问题其实不外乎几个大类,玩不出太多新鲜玩意的.细细想来,面试官拥有以下七种武器.恰似古龙先生笔下的武侠世界 ...

  5. 我是面试官--"自我介绍"

    工作10余年,经历过很多次面试,也面试了N多人.这些年来,已经有好些位朋友(或同事)与我聊起相关话题,涉及面试,更关乎职业生涯规划.感触颇多,就借助自媒体的浪潮,与更多的程序员一起共谈面试经历,希望可 ...

  6. 如何写出面试官欣赏的Java单例

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 今天我们不谈单例模式的用途,只说一说如果在面试的时候面试官让你敲一段代码 ...

  7. 如何解释vue的生命周期才能令面试官满意?

    当面试官问:"谈谈你对vue的生命周期的理解",听到这句话你是不是心里暗自窃喜:这也太容易了吧,不就是beforeCreate.created.beforeMount.mounte ...

  8. 金三银四,如何征服面试官,拿到Offer

    又到了茶余饭后的时间,想想写点什么,掐指一算,噢呦,快到3月份了,职场的金三银四跳槽季又来了,不同的是今年比往年「冷」一些,形式更加严峻一些,大家多多少少可能都听到或看到一些信息,就是好多公司在优化裁 ...

  9. 跟面试官聊.NET垃圾收集,直刺面试官G点

    装逼的面试官和装逼的程序员 我面试别人的时候,经常是按这种路子来面试: 看简历和面试题,从简历和面试题上找到一些技术点,然后跟应聘者聊. 聊某个技术点的时候,应聘者的回答会牵涉到其他的技术点,然后我会 ...

随机推荐

  1. Series结构(常用)

    1.创建 Series 对象 fandango = pd.read_csv("xxx.csv") series_rt = fandango["RottenTomatoes ...

  2. Python os.remove() 方法

    概述 os.remove() 方法用于删除指定路径的文件.如果指定的路径是一个目录,将抛出OSError.高佣联盟 www.cgewang.com 在Unix, Windows中有效 语法 remov ...

  3. PHP rmdir() 函数

    定义和用法 rmdir() 函数删除空的目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 rmdir(dir,context) 参数 描述 dir 必需.规定要删除的目录. ...

  4. 2020牛客暑假多校训练营 第二场 E Exclusive OR FWT

    LINK:Exclusive OR 没做出 原因前面几篇说过了. 根据线性基的知识容易推出 不超过\(w=log Mx\)个数字即可拼出最大值 其中Mx为值域. 那么考虑w+2个数字显然也为最大值.. ...

  5. CF R 639 div2 F Review 贪心 二分

    LINK:Résumé Review 这道题让我眼前一亮没想到二分这么绝. 由于每个\(b_i\)都是局部的 全局只有一个限制\(\sum_{i=1}^nb_i=k\) 所以dp没有什么用 我们只需要 ...

  6. Hive和HBase

    1. 两者分别是什么? Apache Hive是一个构建在Hadoop基础设施之上的数据仓库.通过Hive可以使用HQL语言查询存放在HDFS上的数据.HQL是一种类SQL语言,这种语言最终被转化为M ...

  7. HA模式下的java api访问要点

    在非HA架构的HDFS中,客户端要通过java接口调用HDFS时一般是在JobRunner的类中按照下面的方式: 因为nodename只有一个节点所以会在代码中显式的指明要连接哪一个节点:但是在HA模 ...

  8. 快速构建一个springboot项目(一)

     前言: springcloud是新一代的微服务框架而springboot作为springcloud的基础,很有必要对springboot深入学习一下. springboot能做什么? (1)spri ...

  9. SSH整合-hibernate

    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property& ...

  10. Hotspot GC研发工程师也许漏掉了一块逻辑

    本文来自: PerfMa技术社区 PerfMa(笨马网络)官网 概述 今天要说的这个问题,是我经常面试问的一个问题,只是和我之前排查过的场景有些区别,属于另外一种情况.也许我这里讲了这个之后,会成为不 ...