当前位置: 首页 > 后端技术 > PHP

DDD浅析——一个PHP程序员的自述

时间:2023-03-30 01:42:45 PHP

什么是DDD(首先,它不是什么)DDD是DomainDrivenDesign的缩写,中文常译为DomainDrivenDesign。在我们了解DDD是什么之前,让我们讨论一下它不是什么。DDD不是软件框架。但是基于DDD思想的框架是存在的,比如Axon,它是一个基于DDD的Java实现的微服务软件框架。DDD不是软件设计模式。不是factory、singleton之类的设计模式。但是在DDD思想中提出了Repository等设计模式。DDD不是系统架构模式。它不是像MVC这样的架构模式。但是DDD思想中提出了EventSouring、CommandQueryResponsibilitySegregation等架构模式。那么DDD到底是什么?软件是为人类服务的工具,是提高人类生产力的工具。每个软件都服务于特定领域。例如,CRM是一种专注于管理客户数据并帮助商家与客户保持联系的工具。软件的本质是运行在计算机中的代码。如何将抽象的代码更准确地映射到人类关心的领域,是软件开发者一直在探索的课题,无论是函数式编程(FP)还是面向对象编程(OOP),都是为了帮助开发者开发更接近领域的软件模型。在传统的软件开发方式中,我们经常会遇到一系列影响软件质量的技术和非技术问题:开发人员热衷于技术,但缺乏设计和商业思维。开发人员在没有完全了解业务需求的情况下闭门造车,即使功能上线也无人问津。代码录入而不是业务录入。技术人员对技术实现情有独钟,存在杀鸡用大锤不成的情况。过于强调数据库。以数据库设计为中心而不是业务开发,结果往往是软件无法适应不断变化的业务逻辑。DDD是一种设计思想,一种从领域(业务)出发,旨在解决软件建模复杂性的设计思想。我们也可以理解为一种建模方法论。DDD的设计思想分为战略和战术两部分。我们可以把战略设计理解为宏观层面的设计。其目的包括分析业务复杂度、拆分业务范围、指导业务集成方式等。我们可以把战术设计理解为微观层面(代码层面)的设计,它为我们提供了一系列实现业务逻辑的工具。无处不在的语言(UbiquitousLanguage)是用于战略设计的一种人类交流的基本工具。但是,开发人员习惯于使用技术术语。不关心,从而造成不可避免的沟通问题。一旦出现沟通问题,开发出来的软件就很难解决领域专家真正的痛点。通用语言是DDD思维的基石。它是开发人员和领域专家共同打造的一套沟通语言,是团队中流行的通用沟通语言,团队成员可以使用通用语言进行无障碍沟通。这就需要开发者摒弃技术味浓的技术行话,与领域专家合作,像领域专家一样关注业务问题,共同挖掘和打磨业务术语,打造通用语言。通用语言往往可以直接应用到代码中,可以直接写成类或者类的方法。例如,在开发购物车时,不要使用技术术语:Cart::create():创建购物车。Cart::updateStatus():更新购物车状态。Cart::remove():移除购物车。我们不妨使用更贴近业务的通用语言:Cart::init():创建购物车。Cart::addItemToCart():添加商品。Cart::removeItemFromCart():移除商品。Cart::empty():清空购物车。使用后者时,开发者无需解释每个类方法的含义,领域专家可以直接理解每个类方法的用途。开发人员甚至可以与领域专家坐在一起,使用代码来完善业务流程。限界上下文(BoundedContext)在实现了通用语言的自由性之后,我们需要使用限界上下文来指定每套通用语言的使用边界。有界上下文是语义和上下文的边界,其中的每个元素都有自己特定的含义,也就是说,每个概念在有界上下文中都是唯一的,不允许多义。我们可以用一个简单的例子来解释限界上下文。例如,在购物车的限界上下文中,我们可以使用User一词来表示购买商品的客户。在注册系统中,我们可以使用术语用户来指代具有用户名和密码的帐户。虽然词相同,但在不同的限界上下文中它们具有不同的含义。我们使用限界上下文和通用语言在语言层面拆分业务。有界上下文给领域中的每个元素一个清晰的概念,开发者会情不自禁地在脑海中闪现支持一个元素的多个概念,避免写出“bigballofmud”(大泥球)代码。子域如果说限界上下文是在语言层面拆分业务,那么子域就是拆分业务的业务价值。每个企业都有自己的重点。即使电子商务平台看起来一样,淘宝是开放平台模式,京东是价值链整合模式。一个明显的区别是淘宝使用第三方物流,而京东自建物流体系。.那么作为一个开发者,你为什么要关心一个看起来与你无关的商业模式呢?相反,只有了解了一个业务的结构,才能制定出一个主次分明的系统,来支撑一个业务的快速发展。子域就是这样一种帮助我们确定优先级的工具。子域分为三类:核心域:这是系统中投入最大的区域,代表了整个业务的核心竞争力。我们需要花费大量的资源和资源去打磨核心领域,这关系到一个企业的生死存亡。比如京东自建的物流体系。支撑领域:这个领域不是企业的核心业务,但核心领域离不开它,可以通过外包和定制来实现。比如认证上下文,权限上下文。通用域:如果有成熟的方案,通用域可以购买现成的方案。如果没有,也可以使用外包。对通用域的投资应该是最小的。比如淘宝,物流就是它的通用领域。关于限界上下文和子域的关系,有不同的看法。有的专家提倡1:1,有的专家提倡1:N。个人比较主张1:1,因为深受《实现领域驱动设计》一书作者的影响。上下文映射(ContextMapping)在一个庞大的系统中,限界上下文之间必然存在一定的依赖关系。您如何将概念从一种情况映射到另一种情况?我们使用上下文映射。以下是上下文映射的几种关系类型:Partnership(伙伴关系)SharedKernel(共享内核)Customer-SupplierDevelopment(客户-供应商开发)Conformist(反腐败层)OpenHostService(开放主机)Service),PublishedLanguage,SeparateWay,和BigBallofMud都是比较抽象的概念,有时两个限界上下文之间可以有多种关系。以上就是DDD战略设计的几个核心概念。战术设计如何在限界上下文中对概念进行建模,我们将使用DDD提供的战术设计。实体(Entity)我们首先谈到的是实体。实体是领域内独立事物的模型,每个实体都有一个唯一的标识符,比如ID、UUID、Username等。在大多数情况下,实体是可变的,它的状态会随着时间而改变,但是,一个实体不必是可变的。一个实体最大的特点就是它的个性和独特性。例如,在一个简单的购物车上下文中,Order是一个实体,ID是它的标识符,它的状态可以在placed、confirmed和refunded之间变化。值对象(ValueObject)值对象是用于描述、量化或度量领域中实体的模型。与实体不同,值对象没有唯一标识符,两个等价的值对象是可以互换的。值对象具有不变性(Immutability)。一旦创建,值对象的属性就确定了并且不能更改。理解价值对象最直接的方式就是想象我们现实生活中的纸币。日常生活中,甲的十元人民币和乙的十元人民币可以等额兑换。在上面购物车的上下文中,金额(Money)是一个值对象,金额由货币(currency)和金额(amount)组成:classMoney{public$currency;公共金额;函数__construct($currency,$amount){$this->currency=$currency;$this->金额=$金额;使用值对象进行建模可以帮助我们用代码更准确地构建领域模型。聚合(Aggregate)什么是聚合?聚合是业务域在上下文中更细的划分,每个聚合保证自身的业务一致性。那么什么是业务不变性呢?业务不变性是指一种业务规则,在业务领域内不能被违反,必须保证其一致性。例如,订单退款时,退款金额不能超过已支付的金额。聚合的组成部分是实体、值对象,有时只是实体。为了保护聚合的业务一致性,每个聚合只能通过某个实体进行操作,这个实体称为聚合根。领域事件(DomainEvent)领域事件是用通用语言分析的事件。与常见的事务事件不同,它与业务密切相关,因此其命名往往包含业务术语,不应与数据库挂钩。例如,如果将产品添加到购物车,则相应的领域事??件应该是ProductAddedToCart,而不是CartUpdated。综上所述,DDD还提供了ApplicationService和DomainService等战术设计。DDD还提出了文章开头提到的事件溯源、六边形等架构模式。这里我们不一一讨论。介绍。DDD的核心是从业务角度为软件建立模型。其目的是创造更贴近业务的代码,能够更直观地从代码中理清业务流程。但是DDD的实现不是一日之功,需要不断的实践,不断的打磨。本文转载自【WhyDecoupling】:https://codedecoupled.com/intro-ddd.html,如果你也对TDD、DDD和简洁代码感兴趣,欢迎关注公众号【WhyDecoupling】,一起探索软件的发展之路。