MVC 服务架构在 Symfony 项目中非常常见,感觉像是唯一的方法。它简单、熟悉、有效……直到它不起作用为止。随着项目的增长,裂缝开始显现:业务逻辑无处不在,应用程序行为不清楚,维护代码变得痛苦。虽然这是最常见的方法,但 Symfony 并不强迫您坚持使用它。
如果有更好的方法呢?
随着项目的发展,业务逻辑往往会分布在整个代码库中。项目的每一层——控制器、服务、表单、实体——最终都包含域模型的各个部分。这使得专注于任何特定部分变得越来越困难。
当您的架构是围绕技术层组织的时,随着项目的发展,识别不同上下文之间的清晰边界变得更加困难。这种缺乏清晰度可能会导致紧密耦合的代码和维护挑战。
由于默认架构强调技术层,因此理解项目的行为变得相当具有挑战性。您可能会推断某些实体由特定服务管理或猜测数据库模式,但项目的实际行为(最重要的方面)仍然不清楚和隐含。
当业务逻辑分散在整个项目中并与实现细节混合时,很难独立地发展它们。随着时间的推移,业务逻辑的生命周期往往比实现细节(例如框架、第三方 API 或数据库)的生命周期长得多。每当依赖项中发生哪怕是很小的更改时,这种不匹配都会迫使您重写大部分代码。
为了在需要时更容易专注于业务逻辑,第一步是将其与项目的其余部分隔离。为此,请创建一个 Domain 文件夹。该文件夹成为项目的核心,其中业务逻辑使用纯 PHP 对象进行建模,不依赖于实现细节。虽然项目的其余部分依赖于此文件夹,但 Domain 文件夹不依赖于任何人。
在“域”文件夹内,文件应按域目的而不是技术目的进行分组。这意味着这里没有实体、服务或控制器文件夹,只有与功能或域概念相对应的文件夹名称。
项目最重要的方面是它做什么,它可以处理的操作。这些操作代表了项目的行为,并且应该作为访问业务逻辑的唯一方法。为了反映这一点,请创建一个 Application 文件夹,明确展示项目的所有行为。例如,作为项目的新开发人员,我应该能够通过查看此文件夹一眼就了解该项目能够做什么。
使用 App 和 Domain 文件夹,可以轻松专注于业务逻辑。然而,在某些时候,这个业务逻辑需要与外部系统进行交互。要处理此问题,请创建第三个名为 Infrastruct 的文件夹,其中包含所有实现细节,例如特定于框架的代码、数据库连接和库。
Infra设施文件夹中的文件取决于App和Domain文件。例如,他们可能从 App 文件夹调用应用程序处理程序或实现 Domain 文件夹中定义的接口。
具体来说,在 Symfony 中,这涉及修改 Controller 文件夹并声明哪些服务实现哪些接口。
# config/routes.yaml controllers: resource: path: ../src/Catalog/Infrastructure/Controller/ namespace: App\Catalog\Infrastructure\Controller type: attribute
随着项目的发展,您可能会注意到业务逻辑的某些部分值得在架构中拥有自己的空间。一个好的指标是同一个术语根据上下文开始具有不同的含义。例如,“产品”一词可能指的是工厂产品、仓库产品或电子商务产品,每种产品都需要自己的模型。神物也可以是一个很好的指标; User 类在 Symfony 项目中经常出现此类问题。
当这种情况发生时,就该将其提取出来并让其业务逻辑独立演化。
一些上下文将构成您项目的核心,而其他上下文将支持它。通用上下文(例如 Auth)可以使用更简单的架构,因为它们不是您的域的中心
在这张图中,我们可以看到 Auth 上下文使用标准的 Symfony 结构,Order 和 Catalog 上下文使用以域为中心的架构,Shipping 上下文使用以功能为中心的架构。
如果特定上下文增长到需要独立扩展的程度,请考虑将其拆分为单独的部署单元。
但是,不要急于进行这一步。首先使您的项目模块化,如果您发现上下文需要单独扩展,则单独部署它。
仅当出现组织挑战时才拆分代码库,例如两个团队在同一代码库上难以协作。
在探索这些解决方案时,我们应用了一些工艺概念。让我们命名并简要解释它们,以便您可以更深入地了解每一个。
这个不寻常的术语背后隐藏着一个非常简单的概念。通用语言是您的团队用来描述域模型的词汇。这些词汇应该记录在案,并在产品对话、代码库等各处一致使用。
具体来说,在有界上下文的根部创建一个 markdown 文件,并将产品人员、领域专家和技术团队聚集在一起来定义项目的每个概念。
有界上下文定义了项目内的语言边界,分隔了系统中通用语言不再对齐的部分。上下文地图和事件风暴等工具可以帮助识别这些边界。
有界上下文是一个抽象概念;它可以通过多种方式实现,从模块化整体中的简单文件夹到微服务架构中的集群。
所有这些架构的目的是将业务逻辑与实现细节隔离。无论您使用端口和适配器、六角形还是干净架构,核心思想都是使业务逻辑框架与框架无关并且易于测试。
一旦您记住了这一点,就会有各种各样的实现,而最好的实现取决于您的上下文和偏好。这种架构的一个主要优点是,通过隔离您的业务逻辑,它可以实现更高效的测试。
组织文件夹和文件以“尖叫”业务逻辑的想法被称为尖叫架构。这个概念强调代码的结构应该使项目的目的立即清晰。目标是让新开发人员一目了然地了解项目的用途。
我强烈建议阅读鲍勃叔叔关于该主题的文章 - 他与房屋规划的比较特别富有洞察力。
垂直切片按功能组织您的项目,允许每个功能独立发展。它使您能够根据复杂性和成熟度将不同的架构应用于不同的功能。
虽然这个想法很有趣,但它需要高技能的工程师来有效地实现和维护这样的架构。
构建 Symfony 项目的方式对其可扩展性、可维护性和清晰度有着深远的影响。通过隔离您的业务逻辑并使行为明确,您将创建一个更易于理解和发展的系统。
如果您对这些想法不熟悉,请不要担心,软件工艺是一个旅程,而不是目的地。这些概念一开始可能看起来令人难以接受,但每个概念都将帮助您为您的业务创造更多价值。
有疑问或想分享您的经验吗?将它们放入评论中!请继续关注下一篇文章?
以上是构建 Symfony 项目的另一种方法的详细内容。更多信息请关注PHP中文网其他相关文章!