vlambda博客
学习文章列表

《领域驱动设计之php实现》-入门(译)

Getting Started with Domain Driven Design

不用大惊小怪,如果你已经读过 Vaughn Vernon 和 Eric Evans 著作里的这些主题,你可能会很熟悉我们讲的是什么,因为我们大量借鉴了他们的定义和解释。领域驱动设计(DDD)是一种帮助我们理解和构建软件模型设计的方法。它提供了战略和战术模型工具来帮助我们设计高质量的软件从而达到我们的业务目标

本书的主要目的是向你展示领域驱动设计战略模式的 PHP 代码实例。如果你想了解更多战略模式和领域驱动设计的核心,你最好去读 Vaughn Vernon 的《Domain Driven Design Distilled》和 Eric Evans 的《Domain Driven Design Reference: Definitions and Pattern Summaries》

更重要的是,领域驱动设计不关乎于技术。相反的,它是围绕业务挖掘知识,用技术来提供商业价值的。只有当你有能力理解你公司的业务时,你才可能参与到软件模型的探索过程从而挖掘出一个通用语言(Ubiquitous Language)

Why Domain-Driven Design Matters

软件不仅仅是代码。如果你好好思考过这一点,代码绝非我们所追求的最终目标。代码只不过是解决业务问题的手段。领域驱动设计强调要确保业务和软件使用同一语言。所以为什么非要用不同的语言来讲述呢?只要打破其中壁垒,就不再需要翻译或者繁琐的同步过程,信息也不会丢失。每个人都可以为探索业务领域做出贡献,而不仅仅是程序员。最终所产出的软件就是公共语言的真实体现。

领域驱动设计同时提供了战略和战术设计的框架 -- 战略设计精确定位业务中最重要的领域,根据业务价值来进行开发;战术设计则通过久经考验构建块和模式来建立可工作的领域模型。

The Three Pillars of Domain-Driven Design

领域驱动设计是一种交付软件的方法,它主要关注三个方面

通用语言(Ubiquitous Language) :领域专家和软件开发人员需要为开发的业务一起工作,并为业务领域的建立通用语言。这里没有我们与他们之分,这里只有我们。开发软件是一种商业投资而不仅是花销。为构建通用语言而作出的努力将帮助团队所有成员对领域有更深的认识。

战略设计(Strategic Design) :领域驱动设计不仅指明技术层面战略方向,同时也指明业务方向背后的战略。这有助于定义内部关系和早期预警反馈系统。在技术面,战略设计通过提供如何实现面向服务架构的动机来保护每个业务服务。

战术设计(Tactical Design):领域驱动设计为可交付的迭代软件提供了工具和构建块。战术设计工具产生的软件不仅是正确的,而且是可测试的和较少出错的。



通用语言(Ubiquitous Language)

与第12章“整合边界上下文”一样,通用语言也是领域驱动设计的主要优势

上下文 现在,设想一个有界上下文是一个围绕系统的概念边界。边界内的泛在语言具有特定的语境意义。这个上下文之外的概念可以有不同的含义。

所以,如何找到,探索和捕获这种非常特殊的语言,下面将列出几个要点

识别业务流程如输入,输出等的关键点创建术语和定义的词汇表用某种文档来捕获重要的软件概念与团队的其他成员(领域专家和开发者)分享和扩展收集到的知识

自从领域驱动设计诞生以来,改进构建泛在语言过程的新技术已经出现。而事件风暴是最重要的,也是现在经常使用的

事件风暴(Event Storming)

Alberto Brandolini在一篇博客文章中解释了事件风暴及其优势,他做得比我们更简洁。事件风暴是一种研讨会格式,用于快速探索复杂的业务领域

它非常powerful:它使我和许多实践者能够在数小时而不是数周内提出一个完整业务流程的comprehensive model(全面模型)它是 engaging:整个想法是把有问题的人和知道答案的人带到同一个房间,一起建立一个模型它是efficient:生成的模型与领域驱动完美地结合在一起设计实现风格(特别适合事件来源方法),并允许快速确定上下文和聚合边界它是easy:符号非常简单。没有任何复杂的UML会将参与者从讨论的中心切断这是fun:我总是有很好的时间领导研讨会,人们都很有活力,并交付比他们预期的更多。恰当的问题出现了,气氛也恰当

如果你想对事件风暴了解更多,请查阅 Brandolini 的书 《Introducing EventStorming》

领域驱动设计考虑(Considering Domain-Driven Design)

领域驱动设计不是灵丹妙药(不是银弹),就像软件中的一切一样,它取决于上下文。作为一个经验法则,使用它来简化你的领域,而不是增加更多的复杂性

如果您的应用程序是以数据为中心的,并且您的用例主要操作数据库中的行并执行CRUD操作——即增删改查——那么您就不需要域驱动设计。相反,你所需要的仅仅是在数据库之上做一个漂亮的前端

如果你的应用少于 30 个用例,那 用Symfony 或者 Laravel 这样的框架来处理你的业务逻辑将会更简单 ,但是如果你的应用超 30 个用例,你的系统可能走向一个可怕的大泥球( Big Ball of Mud)。如果你知道你的系统确定无疑会变得越来越复杂,那么你应该考虑用领域驱动设计来应对这些复杂度

如果你并不理解你工作中那些领域,因为它们很陌生,之前也没有任何人给出解决方案,那么对你来说应用领域驱动设计将变得很复杂。在这种情况下,你最需要与领域专家紧密工作来得到正确的模型

棘手的部分(The Tricky Parts)

应用领域驱动设计并不容易。它需要时间和努力来投入到业务领域、术语、研究以及与领域专家协作,而不是代码堆里。你需要领域专家承诺参与到整个进程当中。这将需要一个开放和健康的持续对话,来将他们的行话(spoken lauguage)转化为我们的软件模型。最重要的是,我们必须努力避免使用技术思维,而应该首先认真思考对象的行为和通用语言

战略的概述(Strategical Overview)

为了提供一个领域驱动设计的战略方面的总体概述,我们将使用Jimmy Nilsson的书《 Applying Domain-Driven Design and Patterns》中的一个方法,应用领域驱动设计和模式。考虑两个不同的空间:问题空间和解决方案空间(the problem space and the solution space)

问题空间中,域驱动设计使用域和子域来分组和组织公司想要解决的问题。在在线旅行社(OTA)的例子中,问题是关于处理机票和预订酒店等事情。这样的域可以组织成不同的子域,如定价、库存、用户管理等

解决方案空间中,领域驱动设计提供了两种模式: 限界上下文 和 上下文映射图 (Bounded Contexts and Context Maps)。目标是定义如何为所有被识别的对象提供实现,通过定义子域的交互以及这些交互的细节。继续以OTA为例,每个子域都将通过一个有界上下文实现来解决——例如,设想一个由定价管理子域开发团队开发的自定义Web应用程序,以及一个为用户提供的现成解决方案管理子域。上下文映射将显示每个有界上下文是如何的。上下文映射图将展示每个限界上下文是怎样与其它部分发生关联的。在 Context Map 内部,我们可以看到两个bound的关系类型上下文(例如:客户-供应商,合作伙伴)。理想的方法是两者兼得,子域由一个有界上下文实现,但现实并非如此。在实现方面,当遵循领域驱动设计时,您将以分布式架构结束。正如您可能已经知道的,分布式体系结构比单一体系结构更复杂,那么为什么这种方法有趣,特别是对于大型和复杂的公司?这真的值得吗?没错,它值得!

分布式架构被证明可以提高公司的整体生产力,因为它们为您的产品定义了可以由集中的团队开发的边界.但是如果您的领域——您需要解决的问题——并不复杂,那么应用领域驱动设计的战略部分会增加不必要的开销并降低您的开发速度

如果你想了解更多关于领域驱动设计的战略部分,你应该去看看Vaughn Vernon的书《实现领域驱动设计》的前三章,或者Eric Evans的《领域驱动设计:软件核心复杂性应对之道》,二者对于这方面都有专门的讲解

相关行动:微服务与自包含系统

还有其他一些运动遵循领域驱动设计的相关运动正在积极推广发展。微服务和自包含系统就是很好的例子。James Lewis 和 Martin Fowler 在 《Microservices Resource Guide》 里是这样定义微服务:

Micro-service体系结构样式是一种将单个应用程序开发为一套小型服务的方法,每个服务都运行在自己的进程中,并通过轻量级机制(通常是HTTP资源API)进行通信。这些服务是围绕业务能力构建的,并且可以使用完全自动化的机器独立部署。这些服务的集中管理达到了最低限度,这些服务可以用不同的编程语言编写,也可以使用不同的数据存储技术

如果你想了解更多关于微服务的内容,他们的指导就是一个良好的开端。微服务是怎样与领域驱动设计发生关系的?按照 Sam Newman 《 Building Microservices》 一书中的解释,微服务就是领域驱动设计的限界上下文的实现

除了微服务,另外一个相关的趋势就是自包含系统(SCS),依据自包含系统官网的解释:

自包含系统方法是一种架构,它将功能分离到许多独立的系统中,使完整的逻辑系统成为许多较小软件系统的协作。这可以避免单体系统不断成长导致最后变得不可维护的问题。在过去的几年里,我们已经在许多大中型项目中看到了它的好处。其思想是将一个大系统分解成几个较小的独立系统,或称SCSs,它们遵循一定的规则:

每个SCS都是一个独立的web应用程序。对于SCS领域的所有数据,处理这些数据的逻辑以及渲染web界面的所有代码都包含在SCS中。一个SCS可以完成它自己的主要用例,而不需要依赖其他可用的系统每个SCS由一个团队拥有。这并不一定意味着只有一个团队可以更改代码,但是拥有代码的团队对代码库中的内容有最终决定权,例如通过合并pull-requests不同自包含系统或者第三方系统间的通信任何情况下都应该是异步的。尤其是其他自包含系统或扩展系统不应该同步访问自包含系统内的请求/回复。这一点能帮助解耦系统,减少失败结果,因此能支持自治性。其目的是关于时间上的解耦:一个自包含系统可以很好的工作即使其它自包含系统临时离线。即使通信技术层次是同步的也能实现,例如复制数据或缓存请求一个SCS可以有一个可选的服务API。因为SCS有自己的web UI,它可以与用户交互——而无需通过UI服务。但是,为移动客户端或其他sc提供的API可能仍然有用。每个SCS必须包括数据和逻辑。要真正实现任何有意义的功能,两者都是必需的。一个SCS应该实现它自己的特性,因此必须包含这两个特性一个自包含系统通过自身的UI将功能交给最终用户使用。因此自包含系统不应该与其他自包含系统共享UI。自包含系统可能仍旧与其它系统有关联。不过,异步整合意味着即使在其他自包含系统不可用的情况下还应该能正常工作。为避免紧耦合,一个自包含系统不应该与其他自包含系统共享业务代码。也许可以通过创建一个自包含系统或者公共库,例如:数据驱动层或者认证客户端

小结(Wrap-Up)

在这一章里你将学到:

领域驱动设计不是关于技术的;它的价值实际上是通过聚焦你工作领域中的模型体现的。每个人都参与到领域发现的过程,开发人员和领域专家用相同的语言来共同建立知识,即通用语言。领域驱动设计提供战术和战略模型工具来设计高质量软件。战略设计关注业务方向,帮助明确内部关系,用明确的强边界严格地保护好每个业务服务。战术则为迭代设计提供有用的构建块。领域驱动设计只有在明确的上下文中才有意义。它并不是软件中所有问题的银弹,所以是否用它应根据你手中工作的复杂度来决定。领域驱动设计是一项长期投资;它需要长期努力。开发人员需要与领域专家紧密合作,同时要根据业务思考。最后,业务中的客户因素也是需要你考虑的。

实现领域驱动设计需要努力。如果它很简单,那每个人都可以写出高质量代码了。准备好了,因为你马上就要开始学习怎么写这些代码了,在读的过程中,你将可以完美地描述清晰你公司现有的业务。享受这段旅程吧!

欢迎大家购买并阅读原文:https://leanpub.com/ddd-in-php


关于作者(About the Authors)

Carlos Buenosvinos是一名PHP极限程序员,拥有超过15年的web应用开发经验,以及超过10年的技术领导和CTO经验,领导20到100人的团队。他是一名经过认证的ScrumMaster (CSM),作为一名员工和一名顾问,他指导和培训了近二十多家不同的公司进行敏捷实践。在技术方面,他是Zend PHP工程师,一个Zend框架工程师,MySQL认证。他也是PHP的董事会成员巴塞罗那的用户组。他的工作领域包括电子商务(Atrapalo和eBay)、支付处理(Vendo)、分类广告(Emagister)和B2B招聘工具(XING)。他对JavaScript、DevOps和Scala很感兴趣。他喜欢开发手机、Raspberry Pi和游戏 Twitter: @buenosvinos Web: https://carlosbuenosvinos.com GitHub: https://github.com/carlosbuenosvinos

Christian Soronellas是一个充满激情的软件开发人员,软件自由客,和Craftsman Apprentice。他是一个拥有超过10年web开发经验的极限程序员。他还是一名Zend PHP 5.3认证工程师框架认证工程师,和senolabs认证Symfony开发人员。他曾作为自由职业者,以及在Privalia, Emagister, Atrapalo和Enalquiler作为软件架构师 Twitter: @theUniC GitHub: https://github.com/theUniC

Keyvan Akbary是一名通晓多种语言的软件开发人员,他热爱软件基础,工艺运动,极限编程,SOLID原则,干净的代码,设计模式和测试。他也是一个sporadic Functional 工程师。他认为技术是一种提供价值的媒介。作为一名自由职业者,他参与了无数的项目,参与了视频流媒体(Youzee),参与了在线市场(MyBuilder)——除了创建一家众筹公司(Funddy)之外,所有这些都是他参与的。目前,凯文正在工作作为TransferWise London的首席开发人员 Twitter: @keyvanakbary Web: http://keyvanakbary.com GitHub: https://github.com/keyvanakbary