Spring Web 应用的最大败笔 开发人员在使用Spring应用是非常擅长谈论依赖注入的好处。不幸的是,他们不是那么真的利用它的好处,如单一职责原则,分离关注原则。如果我们一起来看看大部分Spring的Web应用程序,常见的错误的设计如下:1.领域模型对象用来存储应用的数据(当作DTO使用),领域模型是贫血模型这样的反模式。2.服务层每个实体有一个服务。问题是这样很普遍,错误在哪里呢?Spring的web应用程序之所以这样是因为他们做事物的方式一直都是这样做的,老习惯难改,特别是如果他们是高级开发人员或软件架构师,这些人捍卫这样做的论据之一是:我们的应用程序遵循关注分离的原则,因为它已经被分为若干层,每个层有自己的特定职责。1. Web层负责处理用户输入,并返回正确的响应返回给用户。 web层与服务层通信。2.服务层作为一个事务边界。它也负责授权和包含我们的应用程序的业务逻辑。服务层管理的域模型对象,并与其他服务和存储库层进行通信。3.存储库/数据访问层负责与所使用的数据的存储进行通信。分离关
贫血模型不只是存在Spring应用,EJB更是普遍,只有架构分层是不够的,还需要更详细的逻辑分层,DDD领域驱动设计正是一个详细帮助建立丰富的有行为的领域模型的方法学。
理论大片,缺少些例子。让我看的云里雾里,姑且认为又是一贫血模式批判片。
目
前我的认知,打个比喻:领域模型就是人物刻画,比如萧峰、段誉、慕容复,这些人物有着各自的武功、特长、技能、秉性。如果他们都呆在各自的小房间与世隔
绝,那也就不会发生什么事情。而服务就是发生业务的舞台,比如“比武”这个服务,将这些领域模型放入进去,就会发挥领域模型——人物,自身的武功进行交
互。
我举个例子吧。以网上书店为案例,原帖:http://www.jdon.com/44851
业务需求:用户浏览选择书籍,放入购物车,生成订单,付款,等待书籍送上门。
原来服务设计的问题:
一个bookstoreService中又要处理订单,又处理购物车管理,还和Account等实体依赖,也就是说,Account一旦修改,bookstoreService也要修改,这些都违反单一职责和分离关注原则:
如果反映在代码,那么bookstoreService接口代码如下:
public interface BookstoreService{
//将书籍加入购物车
void addShoppingcart(Book book);
//从购物车去除
void removeShoppingcart(Book book);
void addOrder(Book book);
void removeOrder(Book book);
}
好了,如果看得懂这个代码和图,下面我们就要进行分离。
一般很容易将BookstoreService拆成OrderService和CartService。
其实这种区分可能是一种直觉,没有反映内在规律,也就是没有考虑Order和Cart两个实体之间的关系。那么如何考虑这两个实体之间关系呢?一般思路到这里就堵住了。
如果我们从DDD和
事件角度考虑,Order和Cart为什么存在?是因为什么上下文存在?显然是在购书这个活动场景中才有这两个实体存在,而且这两个实体是一种先后关系,
先有购物车,后有订单,而且购物车好像是订单的预先准备,草稿一样,这决定了这两个实体应该在同一个上下文,也就是模块中,同时两者存在逻辑关系。
我们设计一个DDD聚合,聚合根分别是Order和Cart两个,可以认为主副之分。
那么订单Cart的类是如洗:
|
订单比Cart复杂一些:
|
而BookStoreService就变成OrderService
|