着手一个复杂的项目需要全面的背景收集,同时利用领域专家的见解从全新的角度接近领域知识。这种方法使技术团队与业务目标保持一致,并为整个产品生命周期中的明智决策建立了基础路线图。
与之前的团队和当前应用程序用户进行的初步知识收集会议被证明没有成效。 尽管存在固有风险,我们还是短暂考虑过独立进行。
作为技术主管,考虑到项目的复杂性和团队对所有权的需求,我从一开始就倡导领域驱动的方法。这以领域为中心,促进了共同的理解(无处不在的语言),从而简化了沟通并促进了应用程序当前状态的映射。
我们使用 Miro 模板启动了 EventStorming 会议,提供了有效聚焦的结构和图例。 通过会前准备或初步解释提前熟悉 EventStorming 概念是非常有益的。
我们的结构化 EventStorming 流程包括:
EventStorming 不仅提供了领域理解,还为战略和战术上应用领域驱动设计 (DDD) 原则奠定了基础。
关键的第一步涉及战略性地构建领域。 系统的复杂性和技术/业务协调的需要导致采用 DDD 原则。 上下文映射被证明是无价的,即使在我们等待重构的整体中也是如此。 我们确定了限界上下文,在具有共享内核的单一技术上下文中运行。 这种分析虽然没有深入探讨,但指导项目走向面向领域的架构,改善了技术开发和跨团队协作。
识别有界上下文澄清了系统间和外部系统的关系,简化了复杂性,为未来的模块化奠定了基础。 这些初始决策将指导整体结构分解为与定义的上下文一致的可管理组件。 这也有助于确定优先级并确定需要简化、解耦或消除的领域。 我们专注于实施用于外部系统交互的反腐败层 (ACL),以保持系统完整性。
确定了五个关键背景:
这些决策促进了可持续架构的发展,并使开发与业务需求保持一致。
事实证明,建立一种强大的通用语言至关重要。 通过领域专家和开发人员之间的协作创建的共享语言的好处远远超过翻译工作或误解。 这种活跃的资源将技术团队与领域专家联系起来,改善了沟通,减少了误解,并确保代码中准确的领域表示。 这促进了高效、符合业务的技术解决方案。
按照战略框架,我们实施了战术 DDD 原则来构建代码,反映领域现实并确保长期可持续性。
理解实体和值对象之间的区别至关重要。
实体拥有唯一、持久的身份,即使属性发生变化也是如此。 示例包括:
值对象缺乏个体身份;他们的价值定义了他们。 相同的属性意味着等同。 它们是不可变的,非常适合封装跨领域出现的概念。示例包括:
这种方法创建了更易于理解和模块化的代码,并具有明确定义的职责。
示例值对象:
<code class="language-php"><?php readonly class ProductEan13 { public string $value; public function __construct(string $value) { $pattern = '/^\d{13}$/'; if (!preg_match($pattern, $value)) { throw new \Exception('Invalid product Ean13'); } $this->value = $value; } }</code>
服务按目的和实施模式进行分类。
域服务封装了不适合实体或值的业务逻辑,严格在域规则内运行,无需基础设施依赖。
<code class="language-php"><?php readonly class ProductEan13 { public string $value; public function __construct(string $value) { $pattern = '/^\d{13}$/'; if (!preg_match($pattern, $value)) { throw new \Exception('Invalid product Ean13'); } $this->value = $value; } }</code>
应用服务协调域操作与外部交互,集中复杂的操作并将域和基础设施分开。 其中包括用例、命令处理程序和事件处理程序。
基础设施服务处理外部组件交互(数据库、文件系统等),充当适配器来维护领域不可知论。
<code class="language-php"><?php class CheapestCarrierGetter { public function get( DeliveryOptionCarrierCollection $deliveryOptionCarriers, Weight $orderWeight, Country $country, PostalCode $postalCode, bool $isCashOnDelivery = false, ): Carrier { // Logic to get the cheapest carrier } }</code>
服务按功能和相关设计模式进行分类:Transformers、Builders、Factories、Presenters、Notifiers、Validators 和 Clients。
这个最初的领域建模虽然不完整且迭代,但促进了团队的参与和承诺。 预计将进一步完善和重组。
推荐的 DDD 资源:
采用 DDD 与团队组建并行,遵循塔克曼的阶段(形成、风暴、规范、执行)。
初始团队成员审查了项目,记录了操作,并建立了技术和组织基础(流程、标准、工具)。
微小的分歧导致了工作方式、沟通方法和决策过程的定义。
建立了团队协议、编码标准、开发流程、WIP 限制、部署规则、技术债务管理和 ADR。
建立的框架实现了高效的产品开发,优先考虑有价值的举措,并培育持续改进的文化。
使用 GitLab Pages 和 Jekyll 以及 Just the Docs 主题来管理文档,遵循 Diátaxis 模型:教程、指南、解释和参考。 使用事件目录和 AsyncAPI 自动化文档已计划但尚未完全实施。
以上是了解领域并建设团队:变革的基础(II)的详细内容。更多信息请关注PHP中文网其他相关文章!