DDD quickly的翻译者之一,孙向晖总结的DDD的中心思想是:关注精简的业务模型及实现的匹配。看了之后,五体投地,总结的太精辟了。
我们知道,软件开发通常被应用到真实世界中已经存在的自动化流程,或者给真实的业务问题提供解决方案,即要自动化的业务流程或者可以用软件解决的现实问题。既然要解决现实问题,唯物辩证思想给我们指了条光明大道:分析问题,解决问题。
毛主席告诉我们说:没有调查,就没有发言权。软件开发也是如此,我们的软件是要为某一领域服务的,如果我们不了解这个领域,那么我们的所有软件开发方面的技巧,都有如神兵(神奇的兵器),没有高手使用,作用等同于废铜烂铁。所以,软件开发的第一步,是找到高手(领域专家)。第二步,和领域专家交流。问题来了,怎么经行有效的沟通?
鸡同鸭讲,算有效的沟通吗?我觉得不算,答对了,嘿嘿。如果鸡鸭讲同一种语言,问题自然迎刃而解,我们把这种语言叫通用语言(Ubiquitous Language),这里我们简称为“鸟语”。鸟语的制定,大致情况应该是这样:鸡看着蚯蚓说鸭说:蚯蚓咯咯,i'm love in it;鸭说:我明白了,你们把这个动物叫蚯蚓咯咯,对吧?鸡:咯咯是语气助词;鸭:就是叫蚯蚓,对吧?鸡:对。和领域专家沟通,大致也是这样一个情况。
我们的最终产品是软件,如果领域专家,软件开发人员,模型,软件,都讲同一种语言,那么,软件也一定是领域专家想要的样子。这里,反馈是非常重要的,通过反馈,可以确保通用语言的语义一致性。
领域专家、软件开发人员是人,模型、软件是沟通方式。先说模型,模型是对现实世界的抽象和描述,也是交流的主要形式(如果领域专家能深入程序代码,并指出错误,那软件开发从业者,也该考虑改行了)。DDD的模型建立,是比较困难的,因为模型既要能够描述领域,又要能够映射到程序,而且还能和领域专家交流。为之奈何???圣人说过:软件的问题,无非是加个层的事。那么分层吧,也该没错。
用户界面/展现层 负责向用户展现信息以及解释用户命令。
应用层 很薄的一层,用来协调应用的活动。它不包含业务逻辑。它不保留业务对象的状态,但它保有应用任务的进度状态。
领域层 本层包含关于领域的信息。这是业务软件的核心所在。在这里保留业务对象的状态,对业务对象和它们状态的持久化被委托给了基础设施层。
基础设施层 本层作为其他层的支撑库存在。它提供了层间的通信,实现对业务对象的持久化,包含对用户界面层的支撑库等作用。
领域层的主导地位不言而喻,而我们建立领域层的方法是紧密关联领域建模和设计,于是,领域里的名词在模型中得到表现,一般表现为实体,为了防止实体泛滥,实体相关的名词,表现为值对象。实体和值对象是关联关系。领域里的动词,表现为实体方法。跨越多个实体的动词,表现为服务。当模型大到超出人脑一个线程能够处理的程度,应该分模块了,免得内存溢出(脑溢血?)。
简单总是让人痴迷,易经就是最好的例子。那么,怎样保持模型的简单呢?高聚合,低耦合,永远是面向对象的最高追求,也是保持简单的不二法则。家长制是不错的办法,即所谓齐家,具体方法是:是一个家族(一个领域对象),其所以的族人,都由家长统一管理(生杀予夺),从外看,一个家族就如同一个人。用软件的术语,叫做聚合,定义是:是针对数据变化可以考虑成一个单元的一组相关的对象。
有得必有失,我们的辩证唯物思想如是说。我们得到高聚合,低耦合,我们的代价是:实体可能变得比较重,比较复杂(不是所有的家族都是一家三口的小家庭)。怎么解决这个问题呢?工厂模式,这个大家最熟悉的设计模式,自认而然的浮现在了我们眼前,工厂很好的解决了实体的创建问题。如果好容易创建出来,用完就扔掉,那是败家子的作风,不是我们实事求是,勤俭节约、勤劳勇敢(此处省去1w赞美词)的程序员的作风。我们会把这些珍贵、昂贵的实体放入容器存起来,用的时候再拿出来(容器有大小,当然放的东西不能无限多,这就涉及到容器的具体策略)。勤俭节约、谦虚谨慎,是计算机也认同的道德标准。
人非圣贤,当我们对领域不断深入,或者通过和领域专家交流,肯定会发现以前的理解有谬误,这时,无情的重构吧!重构是痛苦的,尤其在时间紧、任务急的情况下,但,生存还是死亡,这是个问题,而这个问题在中国,有标准答案的:好死不如赖活着。为了赖活的更好,重构的痛苦是可以接受的,痛并快乐着,诚如斯言。
很久很久以前(大概石器时代到猛犸象灭绝),猎杀猛犸象,需要整个部落的人协同作战,各司其职。大型项目正如猛犸象,甚至比猛犸象更凶恶,更庞大,个人英雄主义在这里是没有市场的,我们需要多个团队协同作战,各司其职。各司其职,意味着将一个系统界定为多个模型,每个模型拥有独立的上下文,或者同一个模型里的分为多个模块,由不同的团队完成。并行的优点是效率高,适合团队开发,可缺点是难以保持统一的模型,如果引入持续集成,可以将混乱保持在一个可以容忍的范围,当然,这是技术层面上讲的。实际开发中,只有每个开发人员对整个系统有统一完整的认识,才能正本清源,避免不必要的混乱。如果有一个描述各个上下文之间的关系的文档,帮助大家理解系统,岂不美哉?这个文档,就叫上下文映射吧。上下文间的关系,无非共享内核、客户-供应商、顺从者、无关几种关系。
如果所创建的新应用需要和遗留软件或者其他独立应用相交互,考虑到扩展性、可维护性,最好封装交互,加一个交互层(无非是加个层的事),这个层有个直观好听的名字:“防崩溃层”。当同一个防崩溃层被多个子系统需要时,应该考虑把这个层做成开放主机服务,DRY原则。
矛盾分主次,系统内的各个模型也有主次之分,核心域当然需要重点照顾,其他的普通子域,可以考虑购买现成方案、外包、使用已有模型、锻炼新人等方式。
推理完毕,打完收工。
说白了,DDD就是面向对象思想:高聚合、低耦合的扩展和升华,并在此基础上,定义了相应的开发过程。
原文链接:https://www.f2er.com/javaschema/288104.html