研究领域驱动设计(后面简称DDD)有半年之多,初识DDD是由于了解何为充血模式,何为贫血模式,进而顺蔓摸瓜触及DDD,初次了解有种相见恨晚的感受,为何到如今才了解到有DDD这么个东西,以后,一个伴随我成长的疑惑,在我成长过程当中不断致力于去解决,终于在DDD帮助下云拨雾散。 个人疑惑,第一点就是对于咱们采用了不知道多久的开发模式,即Controller->Service->Dao,Service层扮演者上帝类,全部的逻辑都往里塞,这种模式形成Service层的无限膨胀真的是对的吗,很显然答案是不对的,但事实上不少人对此仍是无动于衷,可是究竟要如何改进?之前在大学的时候,本身一直在给本身找外包项目作,曾经对本身放下豪言壮语,多复杂的系统,只要一次性过不要求对其进行维护以及加和改需求,我都能作出来,由于这种开发模式,确实是将CURD表现淋漓尽致,一个资深工程师的代码实现结果,一个菜鸟也一样作到(这里说的是结果,不是过程,然而实际是过程也可能同样,这就很难受了)。第二点,其实也是延续着第一点而来,随着经验的丰富,开始领悟到面向对象和软件工程,那么问题来了,在这种传统的开发模式下,面向对象究竟体如今哪里,咱们学到的设计模式,究竟在哪里展开实践,而实际上咱们每每是挂羊头卖狗肉,羊头是面向对象,狗肉是面向过程。html
下面我将一点点的引导你们进入DDD的思惟模式中,将咱们习惯的开发方式面向过程开发与DDD所倡导的面向模型开发进行对比,逐步进入面向对象。注意,本篇仅仅告诉你们何为DDD,以及DDD的好处和缺点,具体如何实践将在后面展开探讨。DDD提出了一个所谓的领域建模,其实本质是面向对象开发原则中的类的单一职责,咱们的第一个问题是如何处置承担过多的职责的Service上帝类。一个字很好解决,就是拆,笔者曾经尝试按着类的单一职责的指导,将一个依赖注入过多其余类的一个Service类,可能有十几二十个,读者你能够检查一下本身的项目,这就是坏代码,这带来的好处其实只有功能点封装,并不能解决不让Service类臃肿的问题,他仍是会慢慢臃肿起来的,而本质还是面向过程开发,还有一个问题是,就算是这种作法解决Service类臃肿的问题,他没法解决一个很关键的东西,即这里面的代码,没有体现出业务性。什么叫作没有体现出业务性?好比说激活用户,咱们通常会怎么开发?程序员
public class UserService{
public void updateAvailableById(long id,boolean available){
userDao.updateAvailableById(id,available);
}
}
复制代码
这是很典型的面向过程开发的代码,在咱们的项目中到处可见,丧失了面向对象中对象的概念,而现现在咱们在开发的时候,反而被由于使用了数据库而束缚了咱们的思惟,咱们在接收到需求的第一时刻,在分析设计阶段,每每是以数据表为核心进行分析设计, 也就是根据需求首先获得数据表名和字段,而后培训程序员学会SQL语句如何操做这些数据表,那么程序员为实现数据表的先后顺序操做,必然会将代码写成过程式的风格,以数据表为核心进行分析设计,代码很难避免不演变成过程式的代码,由于咱们的重点放在了操做某张表,以及相关的某个字段。 这里就是所谓的贫血模型了,UserDao是关于用户表的SQL语句的集合,在项目中的表现就是写了一堆SQL语句,UserService则是做为Transaction Script的入口以及夹杂着其余杂七杂八的Service类。而这一整个过程当中,user对象都没出现过。 而领域驱动倡导的作法以下。spring
@Data
public class User{
private Long id;
private Boolean available;
public void activate(){
this.setAvailable(true);
}
}
//领域驱动服务
@Service
public class UserOperationService{
@Autowired
private UserRepository userRepository;
public void activate(User user){
user.activate();
userRepository.save(user);
}
}
复制代码
首先第一点是类富含行为(即充血模式),这才是真正倡导的面向对象开发,业务系统所关注的点是业务功能而不是想着这个功能咱们应该如何建表,如何写SQL语句,一直以来咱们的思惟都由于使用了数据库而被绑架了,一上来就开始建表写代码,代码写的很是冗余,彻底是过程式的思考方式,最后致使系统很是难以维护。业务功能只须要明白是激活功能,而不是把user表中available设为true,数据库只是基础设施,咱们不该该关注以及知会对应的SQL语句是怎么样的,因此DDD强调的是Repository而不是DAO,Repository翻译为仓库资源,所需即所得,不用去关注其背后,而DAO咱们不得不去关心SQL语句如何写。能够前往阅读这篇文章进入更深刻的思考对象和数据库的自然阻抗,若是看完以后还不是很明白的话能够在留言区留下疑惑。数据库
咱们不该将原属于领域模型的行为方法等划放在服务中实现,对象不但有属性还有行为将数据和行为封装在一块儿,并与现实世界的业务对象相映射。回归到咱们最初刚学习面向对象教咱们的那样,万物皆是类,而不是只有一个上帝类,咱们须要多建立有合适逻辑的类,各种具有明确的职责划分,使得逻辑分散到合适对象中。这样的对象就是“充血模型”,而这个过程咱们也称之为领域建模,这才是面向对象的真谛啊!设计模式
说到这里,你们可能对以上的示例存在着一点疑惑,1.“怎么这么简单的功能,用DDD的方式下却整的这么复杂?”,2.“你说的不就是要使用ORM框架hibernate吗”。3.“可是一切说到底不都是须要对数据的增删查改吗”bash
第一点,DDD为何称之为复杂软件的设计之道?由于系统够复杂,才能全面展示DDD的功效,业务逻辑站在至高点使得任何业务逻辑的修改扩展都能作到兵来将挡水来土掩,极大的下降了刚接触该系统的同事上手入门的门槛,以及更好的避免存在隐藏BUG(你总会由于不当心改了一行代码,而致使出现了业务异常)。简单的系统功能,只有简单的增删查改,全部的业务逻辑实际只有简单的增长和查询,根本没法提炼出来领域模型,若直接运用DDD的所有理论,实则浪费时间,杀鸡用牛刀。可是没有亘古不变的代码,重构是一直伴随着整个系统的演变,所以建议是即使是简单系统,最好一开始就搭好DDD的样子,后面我会继续出几篇文章,总结我对于DDD理论的实践。架构
对于第二点,建议你们前往阅读此篇文章 领域驱动设计(DDD)的实践经验分享之ORM的思考,仍是那句话,若是看完还不是很明白的话,请到留言区进行留言。其实目的就是为了不进行数据建模, 数据模型,数据库技术绑架了面向对象开发的思路,无形中致使开发人员率先输出表设计,而忽略本来的模型设计,进行造成思惟习惯,“你这样表很差设计啊”。而Hibernate实际上是根据DDD中的JPA理论指导下设计,就是为了让开发人员更加专一于业务逻辑实现,进行领域建模。框架
还有一个问题是一直以来不少人都错误的使用了像hibernate这种全ORM框架,建议你们前往阅读此片文章如何对 JPA 或者 MyBatis 进行技术选型学习
第三点,初步认识DDD并想展开实践的,确实会存在这个疑惑,DDD难在一点的是,他须要你思惟的转变,你须要开始不去关注数据库,不去关心SQL语句, 从数据建模转向领域建模,而这个过程又会将你面向对象过车功能的思惟短板暴露出来,很抱歉,长期以来你并无用面向对象的思惟来开发。 Alistair Cockburn 提出了六边形架构,旨在解决了传统的分层架构所带来的问题。倡导的是屏蔽技术细节,强调业务逻辑,最终目的是实现业务逻辑可重用,组织为一个可重用的自封闭的业务模型,即拷贝不走样。仔细想一想在贫血模式下,最大的不足就是业务逻辑不能重用,业务逻辑没有组织为一个可重用的自封闭的业务模型。 this