加载中 ...
首页 > 新闻资讯 > 经验心得 正文

领域驱动设计实现之路

2019-03-23 07:30:22 来源:沈阳软件公司 作者:沈阳软件开发

  应用层虽然很薄,但却很是主要,由于软件系统的领域逻辑都是通过它袒露出去的,此时的应用层饰演了系统门面(Facade)的角色。

  DDD之战术设计

  战略设计为我们提供一种高层视野来审阅我们的软件系统,而战术设计则将战略设计举行详细化和细节化,它主要关注的是手艺层面的实行,也是对我们程序员来得最着实的地方。

  行为丰满的领域工具

  我们希望领域工具能够准确地表达出营业意图,可是多数时间,我们所看到的却是充满getter和setter的领域工具,此时的领域工具已经不是领域工具了,而是Martin Fowler所称之为的血虚工具。

  放到Java天下中,多年以来,Java Bean规范都引诱着程序员们以“自然而然又合乎情理”的方式建立着无数的血虚工具,而一些框架也划定工具必须提供getter和setter要领,好比Hibernate的早期版本。那么,血虚工具到底有什么坏处呢?来看一个例子:要修改一个客户(Customer)的邮箱地址,在使用setter要领时为:

public class Customer {    private String email;    public void setEmail(String email) {        this.email = email;    }} 

  虽然以上代码可以完成“修改邮箱地址”的功效,可是当你读到这段代码时,你能否推测出系统中就一定存在着一个“修改邮箱地址”的营业用例呢?

  你可能会说,可以在另一个Service类内里建立一个changeCustomerEmail()要领,再在该要领中挪用Customer的setEmailAddress()要领,这样营业意图不就明晰了吗?问题在于,修改邮箱地址这样的职责原来就应该放在Customer上,而不应该由Service和Customer配合完成。遵照诸如信息封装这样的基本面向工具原则是在实行DDD时最基本的素养。

  要建立行为丰满的领域工具并不难,我们需要转变一下头脑,将领域工具当做是服务的提供方,而不是数据容器,多思索一个领域工具能够提供哪些行为,而不是数据。

  近几年又重新盛行起来的函数式编程也能够资助我们编写越发具有营业表达力的营业代码,好比C#和Java 8都提供了Lambda功效,同时还包罗多数动态语言(好比Ruby和Groovy等)。再进一步,我们完全可以通过领域特定语言(DSL)的方式实现领域模子。

  笔者曾经设想过这么一个软件系统:它的焦点功效完全由一套DSL袒露给外界,所有营业操作都通过这套DSL举行,这个领域的营业规则可以通过一套规则引擎举行设置,于是这套DSL可以像上文提到的知识产权核一样拿到市面上举行销售。此时,我们的焦点域被严严实实地封装在这套DSL之内,不允许外界的任何污染。

  实体vs值工具(Entity vs Value Object)

  在一个软件系统中,实体表现那些具有生命周期而且会在其生命周期中发生改变的工具;而值工具则表现起形貌性作用的而且可以相互替换的观点。统一个观点,在一个软件系统中被建模成了实体,可是在另一个系统中则有可能是值工具。例如钱币,在通常生意业务中,我们都将它建模成了一个值工具,由于我们花了20元买了一本书,我们只是体贴钱币的数目而已,而不是体贴详细使用了哪一张20元的钞票,也即两张20元的钞票是可以交换的。可是,若是现在中国人民银行需要建设一个系统来治理所有刊行的钱币,而且希望对每一张钱币举行跟踪,那么此时的钱币便酿成了一个实体,而且具有唯一标识(Identity)。在这个系统中,即便两张钞票都是20元,他们依然表现两个差别的实体。

  详细到实现层面,值工具是没有唯一标识的,他的equals()要领(好比在Java语言中)可以用它所包罗的形貌性属性字段来实现。可是,对于实体而言,equals()要领便只能通过唯一标识来实现了,由于即便两个实体所拥有的状态是一样的,他们依然是差别的实体,就像两小我私家的名字都叫张三,可是他们却是两个差别的人的个体。

  我们发现,多数领域观点都可以建模成值工具,而非实体。值工具就像软件系统中的过客一样,具有“建立后不管”的特征,因此,我们不需要像体贴实体那样去体贴诸如生命周期和持久化等问题。

“沈阳软件公司”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与

我们联系删除或处理,客服QQ:55506560,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同

其观点或证实其内容的真实性。