PHP前端开发

干净的架构:从哪里开始?

百变鹏仔 5天前 #Python
文章标签 架构

在上一篇文章中我们有:

因此,一些决定已经完成。我们拥有一些工具并已经决定了存储库的外观。

这是我喜欢 polylith 的原因之一:无论您编码什么或您的组织有多大,所有存储库看起来都一样 - 如果您需要多个存储库。

无论您使用 fastapi、flask 还是 django,构建单个或多个库,还是使用 celery 运行后台任务,您的存储库结构都是一致的。

主要优势之一是简化新开发人员的入职流程。假设他们掌握了 polylith,他们将很快熟悉项目结构:可重用组件位于 components 文件夹中,入口点位于 bases 文件夹中,演示脚本位于development 文件夹中,等等。

实体

来自 bob 叔叔的“清洁架构”实体是我们架构的基石,它们是我们架构的最内层。所以我们需要从它们开始,在 polylith 中实体应该作为组件存在。

有多少个组件?

我相信组件的数量取决于解决方案的大小和复杂性。但是,我建议从实体的单个多块组件开始。这种方法有助于保持清晰且重点突出的架构,特别是对于较小的项目。

为什么实体只有一个组件?

避免第三方依赖

为了最大限度地减少外部依赖并增强架构灵活性,请努力使用python的标准库来表示实体。这包括利用字典、列表、枚举、函数、类和最近的数据类等数据结构。

为什么要避免使用 pydantic 或 django models 等第三方库?

通过遵守这些原则,您可以创建一个健壮且可维护的架构,能够适应未来的变化。

待办事项实体

我们的示例很简单,核心实体是 gordon 的“待办事项”。我们可以向我们的存储库添加一个新组件,但选择正确的名称至关重要。

虽然使用“core”或“main”等通用名称可能很诱人,但选择在域上下文中有意义的名称至关重要。理想情况下,这些名称应与客户或产品所有者使用的术语一致。通过使用特定于域的名称,我们增强了代码的可读性和可维护性,使开发人员和利益相关者更容易理解项目的结构。

存储库工作区名称定义为 todo。因此,我们所有的导入都将遵循以下格式:

from todo.xyz import ...import todo.xyz

为了简单起见,在本示例中,我们将使用实体作为组件名称。但是,在现实场景中,请考虑反映您的域的命名约定。例如,如果您的应用程序围绕文档恢复,则名为恢复的组件将是合适的。同样,为了清晰起见,游戏应用程序可能会使用锦标赛实体。

使用 python polylith 创建组件很简单:

poetry poly create component --name=entitiespoetry poly syncpoetry install # it may be necessary

这将在组件文件夹中添加一个 python 包,这是源树中的新条目:

./components└── todo    └── entities        ├── __init__.py        └── core.py./test/components└── todo    └── entities        ├── __init__.py        └── test_core.py

python-polylith 工具将为我们生成测试示例,这是一个很好的功能。可以通过在 [tool.polylith.test] 部分中将enabled = true 值设置为 false 来更改workspace.toml 文件中的此行为。

在新的实体组件中,添加了两个文件:__init__.py 和 core.py。您可以重命名 core.py 模块以更好地满足您的需求。常见的做法是通过 __init__.py 公开包的公共 api,同时在 core.py 等其他模块中维护内部组织。

根据要求,目前我们只有一个实体,即 todo 项:

@dataclassclass TodoItem:    owner: str    title: str    description: str    is_done: bool = False    due_date: Optional[date] = None

测试这样一个简单的实体似乎没有必要,但我更喜欢至少测试所有字段的存在。虽然这在贡献者较少的小型项目中似乎并不重要,但它可以防止在拥有许多开发人员的大型项目中出现重大问题。从实体中删除单个字段可能会无意中破坏应用程序的各个部分。

在这部分的拉取请求中,您将看到我为该实体添加了一些基本测试。

已经定义了一些测试,我借此机会添加了 github 工作流程来自动运行每个拉取请求的测试。

结论

接下来:我们来谈谈坚持