首页 >后端开发 >Python教程 >使用六边形架构和领域驱动设计构建可维护的Python应用程序

使用六边形架构和领域驱动设计构建可维护的Python应用程序

Patricia Arquette
Patricia Arquette原创
2024-12-10 01:53:08335浏览

在当今快节奏的软件开发环境中,构建易于维护、适应和扩展的应用程序至关重要。六边形架构(也称为端口和适配器)和领域驱动设计(DDD)是应对这些挑战的有效组合。六边形架构促进了关注点的清晰分离,使得在不破坏核心逻辑的情况下更容易替换、测试或增强系统的各个部分。同时,DDD 专注于使您的代码与现实世界的业务概念保持一致,确保您的系统既直观又具有弹性。这些方法共同使开发人员能够构建强大、有弹性的系统,并且旨在无缝适应不断变化的需求和未来的增长。

1. 六边形架构简介

六边形架构,也称为端口和适配器模式,由Alistair Cockburn引入,以解决传统分层架构的刚性和复杂性。其主要目标是使应用程序的核心逻辑(域)独立于外部系统,从而更容易测试、维护和适应性。

六边形架构的核心将应用程序分为三个主要层:

  • 核心(业务逻辑/域):系统的核心,业务规则和域逻辑所在。该层是独立的,不依赖外部库或框架。
    示例:计算贷款利息或根据业务规则验证用户的操作。

  • 端口(接口):核心与外界交互方式的抽象定义(例如接口或协议)。端口代表用例或特定于应用程序的 API。他们定义了需要做什么,但没有指定如何
    示例: 存储库端口定义与数据源交互的方法,例如:

    • get(id: ID): 实体:通过唯一标识符检索实体。
    • insert(entity: Entity): void: 添加新实体。
    • update(entity: Entity): void:更新现有实体。
src/ports/repository.py
from abc import ABC, abstractmethod
from typing import List
from src.entities import Entity

class Repository(ABC):
    @abstractmethod
    def get(self, id: str) -> Entity:
        pass

    @abstractmethod
    def insert(self, entity: Entity) -> None:
        pass

    @abstractmethod
    def update(self, entity: Entity) -> None:
        pass
  • 适配器(实现): 端口的具体实现。它们处理与数据库、API 或 UI 等外部系统的实际交互。 示例: PostgresRepository Adapter 使用 SQLAlchemy 实现 PostgreSQL 的存储库端口。
# src/adapters/postgres_repository.py
from sqlalchemy import create_engine, Column, String
from sqlalchemy.orm import declarative_base, sessionmaker
from src.entities import Entity
from src.ports.repository import Repository

Base = declarative_base()

# Define the database table for Entity
class EntityModel(Base):
    __tablename__ = "entities"
    id = Column(String, primary_key=True)
    name = Column(String, nullable=False)
    description = Column(String)

class PostgresRepository(Repository):
    def __init__(self, db_url: str):
        """
        Initialize the repository with the PostgreSQL connection URL.
        Example db_url: "postgresql+psycopg2://username:password@host:port/dbname"
        """
        self.engine = create_engine(db_url)
        Base.metadata.create_all(self.engine)
        self.Session = sessionmaker(bind=self.engine)

    def get(self, id: str) -> Entity:
        session = self.Session()
        try:
            entity_model = session.query(EntityModel).filter_by(id=id).first()
            if not entity_model:
                raise ValueError(f"Entity with id {id} not found")
            return Entity(id=entity_model.id, name=entity_model.name, description=entity_model.description)
        finally:
            session.close()

    def insert(self, entity: Entity) -> None:
        session = self.Session()
        try:
            entity_model = EntityModel(id=entity.id, name=entity.name, description=entity.description)
            session.add(entity_model)
            session.commit()
        finally:
            session.close()

    def update(self, entity: Entity) -> None:
        session = self.Session()
        try:
            entity_model = session.query(EntityModel).filter_by(id=entity.id).first()
            if not entity_model:
                raise ValueError(f"Entity with id {entity.id} not found")
            entity_model.name = entity.name
            entity_model.description = entity.description
            session.commit()
        finally:
            session.close()

该架构通常被形象化为六边形,象征着与核心交互的多种方式,每一面代表不同的适配器或端口。

Building Maintainable Python Applications with Hexagonal Architecture and Domain-Driven Design

2. 领域驱动设计(DDD)简介

领域驱动设计 (DDD) 是一种软件设计方法,强调业务目标与为实现这些目标而构建的软件之间的紧密结合。这种方法是由 Eric Evans 在他的书领域驱动设计:解决软件核心的复杂性

中介绍的。

DDD 的核心是在领域专家的帮助下理解和建模领域(业务问题空间),并将这种理解转化为软件系统。 DDD 促进了领域的解耦,确保系统的不同部分保持独立、清晰、易于管理。
领域驱动设计的关键概念:

  • 领域: 软件涉及的知识或活动的特定领域。例如,在银行应用程序中,域包括帐户、交易和客户等概念。

  • 通用语言:由开发人员和领域专家协作开发的通用语言。这种共享词汇确保所有利益相关者之间的清晰沟通和一致理解。

  • 实体和值对象:

    • 实体:具有独特身份和生命周期的对象,例如客户或订单。
    • 值对象: 由其属性而不是唯一标识定义的不可变对象,例如日期或货币金额。
  • 聚合: 相关实体和值对象的集群被视为数据更改的单个单元。每个聚合都有一个根实体,保证整个集群的完整性。

  • 存储库:检索和存储聚合的机制,提供数据访问的抽象层。

  • 服务:自然不适合实体或值对象但对域至关重要的操作或流程,例如处理付款。

src/ports/repository.py
from abc import ABC, abstractmethod
from typing import List
from src.entities import Entity

class Repository(ABC):
    @abstractmethod
    def get(self, id: str) -> Entity:
        pass

    @abstractmethod
    def insert(self, entity: Entity) -> None:
        pass

    @abstractmethod
    def update(self, entity: Entity) -> None:
        pass

在本节中,我不会提供实现领域驱动设计 (DDD) 的详细示例,因为它是一种综合方法,主要致力于解决复杂的业务逻辑挑战。 DDD 擅长构建和管理复杂的业务规则,但为了充分发挥其潜力并解决其他编码问题,最好在互补的架构框架中使用它。因此,在接下来的部分中,领域驱动设计将与六边形架构相结合,以突出其优势,并为解决业务逻辑之外的其他编码问题提供坚实的基础,并附有详细的示例。

3. 六边形架构和领域驱动设计如何相辅相成

为什么采用六边形架构和领域驱动设计?

领域驱动设计 (DDD) 和六边形架构通过强调清晰的边界并使软件与业务需求保持一致来相辅相成。 DDD 专注于对核心域进行建模并隔离业务逻辑,而六边形架构则通过端口和适配器确保该逻辑独立于外部系统。他们解决了不同但互补的问题:

  • 以六角形建筑为框架:

    • 六边形架构定义了整个系统的组织方式以及不同部分(例如域、基础设施、用户界面)如何交互。
    • 它提供了域逻辑可以独立于外部问题运行的环境,不受基础设施细节的影响。
  • 领域驱动设计作为核心逻辑:

    • DDD 丰富了六角架构定义的核心领域,确保业务逻辑不仅被封装,而且反映了现实世界的业务需求。
    • 它重点关注如何有效地设计和实现领域层,确保其保持有意义和适应性。

它们共同实现了可扩展、可测试和灵活的系统,其中领域仍然是中心焦点,不受基础设施或技术变化的影响。这种协同作用确保了强大的设计,可以轻松适应不断变化的业务需求。
以下部分提供了一个实际示例,说明领域驱动设计 (DDD) 和六边形架构如何协同工作来创建健壮、可维护和适应性强的软件系统。

实际例子

该项目应用六边形架构和领域驱动设计(DDD)来创建可扩展和可维护的系统,为应用程序开发提供现代且强大的基础。它使用 Python 构建,使用 FastAPI 作为 Web 框架,使用 DynamoDB 作为数据库。

项目组织如下:

src/ports/repository.py
from abc import ABC, abstractmethod
from typing import List
from src.entities import Entity

class Repository(ABC):
    @abstractmethod
    def get(self, id: str) -> Entity:
        pass

    @abstractmethod
    def insert(self, entity: Entity) -> None:
        pass

    @abstractmethod
    def update(self, entity: Entity) -> None:
        pass

您可以在我的 GitHub 存储库中找到源代码。

4. 结论

将六边形架构和领域驱动设计 (DDD) 合并到 Python 应用程序中,可以促进可维护、适应性强且与业务目标紧密结合的系统的开发。六边形架构确保核心业务逻辑和外部系统之间的明确分离,提高灵活性和易于测试。 DDD 强调准确地对领域进行建模,从而产生真正反映业务流程和规则的软件。通过集成这些方法,开发人员可以创建强大的应用程序,这些应用程序不仅可以满足当前的要求,而且还可以根据未来的业务需求进行发展。

如果您喜欢这篇文章,请联系我!

以上是使用六边形架构和领域驱动设计构建可维护的Python应用程序的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn