Maison >développement back-end >Tutoriel Python >Création d'applications Python maintenables avec une architecture hexagonale et une conception basée sur le domaine

Création d'applications Python maintenables avec une architecture hexagonale et une conception basée sur le domaine

Patricia Arquette
Patricia Arquetteoriginal
2024-12-10 01:53:08265parcourir

Dans le paysage actuel du développement logiciel, en évolution rapide, il est crucial de créer des applications faciles à maintenir, à adapter et à faire évoluer. L'architecture hexagonale (également connue sous le nom de ports et adaptateurs) et la conception pilotée par domaine (DDD) constituent une combinaison efficace pour relever ces défis. L'architecture hexagonale favorise une séparation nette des préoccupations, facilitant ainsi le remplacement, le test ou l'amélioration de parties du système sans perturber la logique de base. Pendant ce temps, DDD se concentre sur l’alignement de votre code avec des concepts commerciaux réels, garantissant ainsi que votre système est à la fois intuitif et résilient. Ensemble, ces approches permettent aux développeurs de créer des systèmes robustes, résilients et conçus pour s'adapter de manière transparente aux exigences changeantes et à la croissance future.

1. Introduction à l'architecture hexagonale

L'architecture hexagonale, également connue sous le nom de modèle de ports et d'adaptateurs, a été introduite par Alistair Cockburn pour répondre à la rigidité et à la complexité de l'architecture en couches traditionnelle. Son objectif principal est de rendre la logique centrale (domaine) de l'application indépendante des systèmes externes, permettant ainsi des tests, une maintenance et une adaptabilité plus faciles.

À la base, Hexagonal Architecture divise l'application en trois couches principales :

  • Core (Business Logic/Domain) : Le cœur du système où résident les règles métier et la logique de domaine. Cette couche est indépendante et ne s'appuie pas sur des bibliothèques ou des frameworks externes.
    Exemple : Calculer les intérêts d'un prêt ou valider l'action d'un utilisateur par rapport aux règles métier.

  • Ports (interfaces) : Définitions abstraites (par exemple, interfaces ou protocoles) pour la manière dont le noyau interagit avec le monde extérieur. Les ports représentent des cas d'utilisation ou des API spécifiques à une application. Ils définissent ce qui doit être fait sans préciser comment.
    Exemple : Le port du référentiel définit des méthodes pour interagir avec les sources de données telles que :

    • get(id: ID): Entity : Récupère une entité par son identifiant unique.
    • insert(entity: Entity): void : Ajouter une nouvelle entité.
    • update(entity: Entity): void : Mettre à jour une entité existante.
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
  • Adaptateurs (Implémentations) : Implémentations concrètes des ports. Ils gèrent l'interaction réelle avec les systèmes externes tels que les bases de données, les API ou l'interface utilisateur. Exemple : PostgresRepository Adapter implémente le port de référentiel pour PostgreSQL à l'aide de SQLAlchemy.
# 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()

L'architecture est souvent visualisée comme un hexagone, symbolisant plusieurs façons d'interagir avec le noyau, chaque côté représentant un adaptateur ou un port différent.

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

2. Introduction à la conception pilotée par domaine (DDD)

Domain-Driven Design (DDD) est une approche de conception de logiciels qui met l'accent sur un alignement étroit entre les objectifs commerciaux et le logiciel construit pour les atteindre. Cette méthodologie a été introduite par Eric Evans dans son livre Domain-Driven Design: Tackling Complexity in the Heart of Software.

À la base, DDD se concentre sur la compréhension et la modélisation du domaine (l'espace des problèmes commerciaux) avec l'aide d'experts du domaine et sur la traduction de cette compréhension dans le système logiciel. DDD favorise le découplage des domaines, garantissant que les différentes parties du système restent indépendantes, claires et faciles à gérer.
Concepts clés de la conception basée sur le domaine :

  • Domaine : Le domaine de connaissances ou d'activité spécifique abordé par le logiciel. Par exemple, dans une application bancaire, le domaine inclut des concepts tels que les comptes, les transactions et les clients.

  • Langage omniprésent : Un langage commun développé en collaboration par des développeurs et des experts du domaine. Ce vocabulaire partagé garantit une communication claire et une compréhension cohérente entre toutes les parties prenantes.

  • Entités et objets de valeur :

    • Entités : Objets qui ont une identité et un cycle de vie distincts, comme un client ou une commande.
    • Objets de valeur : Objets immuables définis par leurs attributs plutôt que par une identité unique, comme une date ou un montant monétaire.
  • Agrégats : Clusters d'entités associées et d'objets de valeur traités comme une seule unité pour les modifications de données. Chaque agrégat possède une entité racine qui garantit l'intégrité de l'ensemble du cluster.

  • Dépôts : Mécanismes de récupération et de stockage des agrégats, fournissant une couche d'abstraction sur l'accès aux données.

  • Services :Opérations ou processus qui ne correspondent pas naturellement à des entités ou à des objets de valeur mais qui sont essentiels au domaine, comme le traitement d'un paiement.

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

Dans cette section, je ne fournis pas d'exemple détaillé de mise en œuvre de la conception pilotée par domaine (DDD) car il s'agit d'une méthodologie complète principalement axée sur la résolution de défis complexes en matière de logique métier. DDD excelle dans la structuration et la gestion de règles métier complexes, mais pour réaliser pleinement son potentiel et répondre à d'autres problèmes de codage, il est préférable de l'utiliser dans un cadre architectural complémentaire. Ainsi, dans la section suivante, la conception pilotée par domaine sera combinée à l'architecture hexagonale pour mettre en évidence ses points forts et fournir une base solide pour résoudre des problèmes de codage supplémentaires au-delà de la logique métier, accompagnée d'un exemple détaillé.

3. Comment l'architecture hexagonale et la conception axée sur le domaine se complètent

Pourquoi une architecture hexagonale et une conception pilotée par domaine ?

La conception pilotée par domaine (DDD) et l'architecture hexagonale se complètent en mettant l'accent sur des limites claires et en alignant les logiciels sur les besoins de l'entreprise. DDD se concentre sur la modélisation du domaine principal et l'isolation de la logique métier, tandis que l'architecture hexagonale garantit que cette logique reste indépendante des systèmes externes via des ports et des adaptateurs. Ils répondent à des préoccupations distinctes mais complémentaires :

  • L'architecture hexagonale comme cadre :

    • L'architecture hexagonale définit la façon dont le système global est organisé et comment les différentes parties (par exemple, le domaine, l'infrastructure, les interfaces utilisateur) interagissent.
    • Il fournit l'environnement dans lequel la logique de domaine peut fonctionner indépendamment des préoccupations externes, offrant une liberté par rapport aux détails de l'infrastructure.
  • Conception basée sur le domaine comme logique de base :

    • DDD enrichit le domaine principal défini par l'architecture hexagonale en garantissant que la logique métier est non seulement encapsulée, mais reflète également les besoins commerciaux réels.
    • Il se concentre sur la façon de concevoir et de mettre en œuvre efficacement la couche de domaine, en garantissant qu'elle reste significative et adaptable.

Ensemble, ils permettent des systèmes évolutifs, testables et flexibles où le domaine reste au centre de l'attention, à l'abri des changements d'infrastructure ou de technologie. Cette synergie garantit une conception robuste qui s'adapte facilement aux exigences métier évolutives.
La section suivante offre un exemple pratique de la façon dont la conception pilotée par domaine (DDD) et l'architecture hexagonale fonctionnent ensemble pour créer des systèmes logiciels robustes, maintenables et adaptables.

Exemple pratique

Ce projet applique l'architecture hexagonale et la conception pilotée par domaine (DDD) pour créer des systèmes évolutifs et maintenables, fournissant une base moderne et robuste pour le développement d'applications. Construit avec Python, il utilise FastAPI comme framework Web et DynamoDB comme base de données.

Le projet est organisé comme suit :

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

Vous pouvez trouver le code source dans mon référentiel GitHub.

4. Conclusion

L'intégration de l'architecture hexagonale et de la conception pilotée par domaine (DDD) dans les applications Python favorise le développement de systèmes maintenables, adaptables et étroitement alignés sur les objectifs commerciaux. L'architecture hexagonale garantit une séparation claire entre la logique métier principale et les systèmes externes, favorisant la flexibilité et la facilité de test. DDD met l'accent sur la modélisation précise du domaine, ce qui aboutit à un logiciel qui reflète véritablement les processus et les règles métier. En intégrant ces méthodologies, les développeurs peuvent créer des applications robustes qui non seulement répondent aux exigences actuelles, mais sont également bien préparées pour évoluer avec les futurs besoins de l'entreprise.

Connectez-moi si vous avez apprécié cet article !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn