Heim >Backend-Entwicklung >Python-Tutorial >Erstellen wartbarer Python-Anwendungen mit hexagonaler Architektur und domänengesteuertem Design

Erstellen wartbarer Python-Anwendungen mit hexagonaler Architektur und domänengesteuertem Design

Patricia Arquette
Patricia ArquetteOriginal
2024-12-10 01:53:08272Durchsuche

In der heutigen schnelllebigen Softwareentwicklungslandschaft ist die Entwicklung von Anwendungen, die einfach zu warten, anzupassen und zu skalieren sind, von entscheidender Bedeutung. Hexagonale Architektur (auch bekannt als Ports und Adapter) und Domain-Driven Design (DDD) sind eine wirksame Kombination zur Bewältigung dieser Herausforderungen. Die hexagonale Architektur fördert eine saubere Trennung von Belangen und macht es einfacher, Teile des Systems zu ersetzen, zu testen oder zu verbessern, ohne die Kernlogik zu stören. In der Zwischenzeit konzentriert sich DDD darauf, Ihren Code an realen Geschäftskonzepten auszurichten und sicherzustellen, dass Ihr System sowohl intuitiv als auch belastbar ist. Zusammengenommen ermöglichen diese Ansätze Entwicklern, Systeme zu entwickeln, die robust und belastbar sind und sich nahtlos an sich ändernde Anforderungen und zukünftiges Wachstum anpassen lassen.

1. Einführung in die sechseckige Architektur

Hexagonale Architektur, auch als Ports- und Adaptermuster bekannt, wurde von Alistair Cockburn eingeführt, um die Starrheit und Komplexität der traditionellen Schichtarchitektur anzugehen. Sein Hauptziel besteht darin, die Kernlogik (Domäne) der Anwendung unabhängig von externen Systemen zu machen und so einfachere Tests, Wartung und Anpassungsfähigkeit zu ermöglichen.

Im Kern unterteilt Hexagonal Architecture die Anwendung in drei Hauptschichten:

  • Kern (Geschäftslogik/Domäne): Das Herzstück des Systems, in dem sich Geschäftsregeln und Domänenlogik befinden. Diese Ebene ist unabhängig und nicht auf externe Bibliotheken oder Frameworks angewiesen.
    Beispiel: Berechnung der Zinsen für einen Kredit oder Validierung der Aktion eines Benutzers im Hinblick auf Geschäftsregeln.

  • Ports (Schnittstellen): Abstrakte Definitionen (z. B. Schnittstellen oder Protokolle) für die Art und Weise, wie der Kern mit der Außenwelt interagiert. Ports repräsentieren Anwendungsfälle oder anwendungsspezifische APIs. Sie definieren, was getan werden muss, ohne wie anzugeben.
    Beispiel: Repository-Port definiert Methoden zur Interaktion mit Datenquellen wie:

    • get(id: ID): Entität: Rufen Sie eine Entität anhand ihrer eindeutigen Kennung ab.
    • insert(entity: Entity): void: Eine neue Entität hinzufügen.
    • update(entity: Entity): void: Eine vorhandene Entität aktualisieren.
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
  • Adapter (Implementierungen): Konkrete Implementierungen der Ports. Sie kümmern sich um die eigentliche Interaktion mit externen Systemen wie Datenbanken, APIs oder UI. Beispiel: Der PostgresRepository-Adapter implementiert den Repository-Port für PostgreSQL mithilfe von 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()

Die Architektur wird oft als Sechseck dargestellt, das mehrere Möglichkeiten der Interaktion mit dem Kern symbolisiert, wobei jede Seite einen anderen Adapter oder Port darstellt.

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

2. Einführung in Domain-Driven Design (DDD)

Domain-Driven Design (DDD) ist ein Software-Design-Ansatz, der eine enge Abstimmung zwischen Geschäftszielen und der Software, die zu deren Erreichung entwickelt wird, betont. Diese Methodik wurde von Eric Evans in seinem Buch Domain-Driven Design: Tackling Complexity in the Heart of Software.

eingeführt

Im Kern konzentriert sich DDD darauf, die Domäne (den Geschäftsproblembereich) mithilfe von Domänenexperten zu verstehen und zu modellieren und dieses Verständnis in das Softwaresystem zu übertragen. DDD fördert die Entkopplung von Domänen und stellt so sicher, dass verschiedene Teile des Systems unabhängig, klar und einfach zu verwalten bleiben.
Schlüsselkonzepte des domänengesteuerten Designs:

  • Domäne: Der spezifische Wissens- oder Aktivitätsbereich, den die Software anspricht. In einer Bankanwendung umfasst die Domäne beispielsweise Konzepte wie Konten, Transaktionen und Kunden.

  • Allgegenwärtige Sprache: Eine gemeinsame Sprache, die gemeinsam von Entwicklern und Fachexperten entwickelt wurde. Dieses gemeinsame Vokabular gewährleistet eine klare Kommunikation und ein einheitliches Verständnis aller Beteiligten.

  • Entitäten und Wertobjekte:

    • Entitäten:Objekte, die eine eindeutige Identität und einen bestimmten Lebenszyklus haben, z. B. ein Kunde oder eine Bestellung.
    • Wertobjekte: Unveränderliche Objekte, die durch ihre Attribute definiert werden und nicht durch eine eindeutige Identität, wie ein Datum oder einen Geldbetrag.
  • Aggregate: Cluster verwandter Entitäten und Wertobjekte, die bei Datenänderungen als eine einzige Einheit behandelt werden. Jedes Aggregat verfügt über eine Root-Entität, die die Integrität des gesamten Clusters gewährleistet.

  • Repositorys: Mechanismen zum Abrufen und Speichern von Aggregaten, die eine Abstraktionsebene über den Datenzugriff bereitstellen.

  • Dienste: Vorgänge oder Prozesse, die nicht von Natur aus in Entitäten oder Wertobjekte passen, aber für die Domäne wesentlich sind, wie z. B. die Verarbeitung einer Zahlung.

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

In diesem Abschnitt gebe ich kein detailliertes Beispiel für die Implementierung von Domain-Driven Design (DDD), da es sich um eine umfassende Methodik handelt, die sich hauptsächlich auf die Bewältigung komplexer Herausforderungen der Geschäftslogik konzentriert. DDD zeichnet sich durch die Strukturierung und Verwaltung komplexer Geschäftsregeln aus. Um jedoch sein Potenzial voll auszuschöpfen und andere Codierungsprobleme anzugehen, wird es am besten in einem ergänzenden Architekturrahmen eingesetzt. Daher wird im folgenden Abschnitt Domain-Driven Design mit Hexagonal Architecture kombiniert, um dessen Stärken hervorzuheben und eine solide Grundlage für die Lösung zusätzlicher Codierungsprobleme über die Geschäftslogik hinaus zu schaffen, begleitet von einem detaillierten Beispiel.

3. Wie sich hexagonale Architektur und domänengesteuertes Design gegenseitig ergänzen

Warum hexagonale Architektur und domänengesteuertes Design?

Domain-Driven Design (DDD) und Hexagonal Architecture ergänzen einander, indem sie klare Grenzen betonen und Software an den Geschäftsanforderungen ausrichten. DDD konzentriert sich auf die Modellierung der Kerndomäne und die Isolierung der Geschäftslogik, während die Hexagonal-Architektur durch Ports und Adapter sicherstellt, dass diese Logik unabhängig von externen Systemen bleibt. Sie gehen auf unterschiedliche, aber komplementäre Anliegen ein:

  • Hexagonale Architektur als Rahmen:

    • Hexagonale Architektur definiert, wie das Gesamtsystem organisiert ist und wie verschiedene Teile (z. B. Domäne, Infrastruktur, Benutzeroberflächen) interagieren.
    • Es stellt die Umgebung bereit, in der die Domänenlogik unabhängig von externen Bedenken funktionieren kann und Freiheit von Infrastrukturdetails bietet.
  • Domänengesteuertes Design als Kernlogik:

    • DDD bereichert die von der Hexagonal Architecture definierte Kerndomäne, indem es sicherstellt, dass die Geschäftslogik nicht nur gekapselt ist, sondern auch die realen Geschäftsanforderungen widerspiegelt.
    • Der Schwerpunkt liegt auf der effektiven Gestaltung und Implementierung der Domänenschicht, um sicherzustellen, dass sie sinnvoll und anpassungsfähig bleibt.

Zusammen ermöglichen sie skalierbare, testbare und flexible Systeme, bei denen die Domäne im Mittelpunkt bleibt und von Änderungen in der Infrastruktur oder Technologie isoliert ist. Diese Synergie gewährleistet ein robustes Design, das sich leicht an sich ändernde Geschäftsanforderungen anpassen lässt.
Der folgende Abschnitt bietet ein praktisches Beispiel dafür, wie Domain-Driven Design (DDD) und Hexagonal Architecture zusammenarbeiten, um robuste, wartbare und anpassungsfähige Softwaresysteme zu schaffen.

Praxisbeispiel

Dieses Projekt wendet Hexagonal Architecture und Domain-Driven Design (DDD) an, um skalierbare und wartbare Systeme zu erstellen und eine moderne und robuste Grundlage für die Anwendungsentwicklung zu schaffen. Es wurde mit Python erstellt und verwendet FastAPI als Web-Framework und DynamoDB als Datenbank.

Das Projekt ist wie folgt organisiert:

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

Den Quellcode finden Sie in meinem GitHub-Repository.

4. Fazit

Die Integration von Hexagonal Architecture und Domain-Driven Design (DDD) in Python-Anwendungen fördert die Entwicklung von Systemen, die wartbar, anpassbar und eng an den Geschäftszielen ausgerichtet sind. Die hexagonale Architektur sorgt für eine klare Trennung zwischen der Kerngeschäftslogik und externen Systemen und fördert so Flexibilität und einfache Tests. DDD legt Wert auf die genaue Modellierung der Domäne, was zu einer Software führt, die Geschäftsprozesse und -regeln wirklich widerspiegelt. Durch die Integration dieser Methoden können Entwickler robuste Anwendungen erstellen, die nicht nur aktuelle Anforderungen erfüllen, sondern auch gut auf die Weiterentwicklung zukünftiger Geschäftsanforderungen vorbereitet sind.

Verbinden Sie mich, wenn Ihnen dieser Artikel gefallen hat!

Das obige ist der detaillierte Inhalt vonErstellen wartbarer Python-Anwendungen mit hexagonaler Architektur und domänengesteuertem Design. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn