从领先的软件设计人员开始将领域建模及设计视为关键性课题到现在至少已经有20年的时间了,然而令人惊讶的是,几乎没有相关的文献来告诉大家应该做什么和如何做。尽管领域建模和设计并没有被明确形式化,然而在对象领域中出现了一种潜在的哲学体系,它就是我所说的领域驱动设计(domain-driven design)。
每个软件程序都会与其用户的活动或兴趣相关。用户在其中使用程序的主要环境称为软件的领域(domain)。
软件的核心是它为用户解决领域相关问题的能力。
创建能够处理非常复杂任务的程序要求分离关注点,这样允许隔离地关注设计的不同部分。同时不管是否分离,都要维护好系统中复杂的交互。
分层的意义在于每层都专门负责计算机程序中一个特定方面。这种基于专责的划分,可以使各方面的设计更加具有内聚性,并且使得这些设计更加容易解释。当然,如何选择层次,来隔离最重要的内聚设计方面是非常重要的。还好,经验和管理可以再一次帮助我们。尽管有许多变体,但是大多数成功的分层架构都会使用这四种概念层的某些版本。
用于界面层(表示层):负责向用户显示信息,并且解析用户命令。外部的执行者有时可能会是其他的计算机系统,不一定非是人。
应用层:定义软件可以完成的工作,并且指挥具有丰富含义的领域对象来解决问题。这个层所负责的任务对业务影响深远,对跟其它系统地应用层进行交互非常必要。这个层要保持简练。它不包括处理业务规则或知识,只是给下一层中相互协作的领域对象协调任务、委托工作。这个层次不反映业务情况的状态,但反映用户或程序的任务进度的状态。
领域层(模型层):负责表示业务概念、业务状况的信息以及业务规则。尽管保存这些内容的技术细节由基础结构层来完成,反映业务状况的状态在该层中被控制和使用。这一层是业务软件的核心。
基础结构层:为上层提供通用的技术能力:应用的消息发送、领域持久化,为用户界面绘制窗口等。通过架构框架,基础结构层还可以支持这四层之间的交互模式。
将一个复杂的程序进行层次划分。为每一层进行设计,每层都是内聚的而且只依赖与它的下层。采用标准的架构模式来完成与上层的松散关联。将所有与领域模型相关的代码都集中在一层,并且将它与用户界面层、应用层和基础结构层的代码分离。领域对象可以将重点放在表达领域模型上,不需要关心它们自己的显示、存储和管理应用任务等内容。这样使模型发展得足够丰富和清晰,足以抓住本质的业务知识并实现它。
将领域层从基础结构层和用户界面分离出来,可以使各层的设计更加清晰。相互隔离的层的维护开销小得多,因为它们往往是以不同的速度发展并且响应不同的要求。分离同样可以有助于分布式系统的部署,为了使通信开销最小、提高性能,可以把各层灵活地放在不同的服务器或者客户端上。
层是一种松散关联结构,因为设计的依赖是单向的。上层可以直接使用或者操纵下层的元素,这可以通过直接调用下层的公关接口,维护对它们的引用或者使用常规的交互方法来完成。但是当一个下层的对象需要跟上层通信时,我们就需要另一种机制,采用架构模式把各层联系起来,例如使用回调或Observer模式。
最早用来连接用户界面层、应用层和领域的模式是MVC。
基础结构层通常不在领域层发起动作。
应用层和领域层调用由基础结构层提供的服务。
集成了许多基础结构的框架,常常要求其他层按照非常特定的方式来实现,例如,作为框架类的子类或者使用构造好的方法签名。最好的架构框架在解决复杂技术问题的同时,允许领域开发人员集中精力表达一个模型。但是框架很容易造成障碍,要么假设的东西太多,限制了领域设计的选择;要么实现的东西太多,影响了开发的速度。
如今,在绝大多数系统中都用了分层架构,只是各个系统的分层的方案可能不同而已。许多开发风格能够从分层种获得帮助。可是领域驱动设计要求只能有一个特定的层存在。
领域模型是一组概念。“领域层”是模型和所有与其相关设计元素的显现。业务逻辑的设计和实现构成了领域层。在一个模型驱动设计中,领域层的软件结构反映出模型的概念。
当领域逻辑和程序的其他关注点混在一起时,要达到一致是很不现实的。隔离领域实现是领域驱动设计的前提条件。
反模式——智能UI
许多软件项目采用而且还将继续采用一种不太成熟的设计方法,我把它叫做智能UI。但是智能UI走上了另一面,如同道路上互斥的岔道,与领域驱动设计的方法格格不入。
把所有的业务的业务逻辑交给用户界面处理。将整个应用程序分割成小的功能函数,并且把它们作为相互独立的用户界面实现,同时把业务规则嵌入到这些界面中。用一个关系数据库作为数据的共享仓储。使用最自动得UI结构,以及可利用的可视化编程工具。
纯粹是旁门左道!
(现在流行的,包括在本书中提倡的)真理是领域和UI应该被分离。
因此,在领域驱动设计的上下文中,可以把这个智能UI看成是一个“反模式”,虽然他在一些上下文中是一个合理的模式。
在智能UI和分层架构之间还有其他的解决方案。例如Fowler提出的事务脚本(Transaction Script )模式,它从应用程序中把用户界面分离出来,但是并不提供一个对象模型。
遗憾的是,除了基础结构和用户界面外,还有其他因素会破坏您精致的领域模型。您必须考虑到那些没有完全集成到模型中的领域组件。