知乎看到一个问题,也是当前在软件设计开发中普遍存在的一个问题,如下:
现在要开发一个业务逻辑比较复杂的项目,但是在网上看了设计模式的思想后感觉自己以前写的东西扩展性 都不好,接口定义也不合适,都是一个实体类一个接口,项目施工也感觉不合理,感觉项目施工中应该先集中定义好接口,并完成业务逻辑,然后在具体实现接口, 不知道这样想是不是正确?
对于这个问题,其实在我前面关于领域驱动设计的文章和读书笔记里面已经专门谈到过,再简单回答下。
首先我们看下模式是什么? 模式是特定场景下解决特定问题的方法或最佳实践,因此最重要的是了解清楚有扩展性需求,有需要灵活应对的变更需求的特定场景。场景想清楚了你才可能想应该用什么样的设计模式去解决问题。如果没有这些场景,为何一定要套用设计模式呢?简单的对设计模式的套用往往都是过度设计,并不值得推荐。
根据你的问题描述,初步分析整个系统还是以数据库DB为主导的一个系统设计和实现方法,而不是以对象为主导的设计方法和思路。在原来的项目中我们也看到相当多的这种设计实现方法,虽然用了O/R Mapping,但是实体对象全部是数据库表,接口方法全部是CRUD,这种方法在应对的简单的无相关性表单对象维护可能还可以,但是一旦面对比较复杂的业务系统或业务场景,很难谈得上真正的可扩展性。
对于一个业务逻辑比较复杂的项目,那么就要先考虑我们的业务逻辑层在哪里?业务逻辑层里面是否真正有业务逻辑的抽象和设计?还是业务逻辑都被放到数据库, 数据层或前端去了?很多项目有业务逻辑层的类,但是基本都是空的,没有对业务逻辑进行抽象。这也是领域驱动设计里面谈到的贫血的领域层,一个是没有领域业 务对象的概念(领域模型中的聚合根),一个是没有明确的粗粒度的业务规则逻辑处理层。
如何让业务逻辑层真正起到作用,这里面首先第一重要的还是要从DB数据库对象抽象出真正的领域对象,如订单,合同,项目,这些是领域对象。一个领域对象下 面对应了多张数据库表。一个领域对象本身应该是高内聚的,不应该开放和暴露的坚决不暴露,仅仅暴露领域对象应该暴露的接口方法和能力。这个时候的实体类是 在简单数据库表实体类的上一层。实体类可以有方法,也可以是实体和方法分离,实体类仅仅是DTO对象都没有问题。
在上面这步完成后,接着要解决的是还有些复杂的业务规则是跨了多个实体对象的,也是前面说到的粗粒度的业务规则逻辑处理层。这些规则处理放到任何一个实体 类里面去都不合适,在领域驱动设计里面将其放到service层去处理。但是更加重要的是想说,需要针对这种场景有单独的业务规则或逻辑处理类,这些类似 RUP方法里面的控制类,本身并不会有对应的数据库表操作,而是对已有的各个实体类方法的调用和组合,在过程中增加了业务规则的处理。
这些业务规则类或方法如何寻找?最简单的往往是从需求里面的业务规则入手,首先要需求里面的业务规则同需求基本流,扩展流分离出来,再来看这些业务对象的 处理和实现是否需要跨多个领域对象实体。其次需要对关键用例实现进行分析,在关键用例的实现流中,类似序列图这种分析中,是否出现了跨多个领域对象多次操 作后才需要返回前端的业务场景。那么就说明这些多次操作和规则可以在逻辑层完成,而不是暴露到前端或action层去组装。
最后简单总结下上面的内容
1.我所谈的复杂业务规则究竟在哪里?我能否清楚描述和定义并从基本流或扩展流剥离?
2.我需要的可扩展性究竟是应对何种场景扩展和变更?是否真正需要可扩展性设计?
3.从领域对象和专门业务逻辑处理类两个层面来解决贫血的逻辑层的问题。
4.转变传统的围绕数据库对象为中心的逆向设计方法,为围绕领域对象的业务处理和交互分析的方法。