Zpět na domů

DDD a Clean Architecture v Go: pragmatický přístup

Článek vysvětluje, jak pragmaticky aplikovat DDD a Clean Architecture v Go a vyhnout se nadměrné struktuře. Uvedeny jsou příklady kódu, doporučení k organizaci projektu a klíčová pravidla pro snížení technického dluhu.

Go: DDD a Clean Architecture bez 200 souborů
Advertisement 728x90

# DDD a Clean Architecture v Go: pragmatický přístup bez přehnaného inženýrství

Technický dluh vyplývající z architektonických problémů pohlcuje až 40 % IT rozpočtů firem. V Go projektech se to často projevuje nadbytečnou strukturou: 200 souborů s prázdnými rozhraními a vrstvami, kde se ztrácí obchodní logika. Příčiny spočívají v nesprávném použití DDD a Clean Architecture převzatém z Javy nebo C#. Tyto vzory však, pokud se aplikují pragmaticky, řeší problém složitosti. Ukážeme, jak se vyhnout přehnanému inženýrství a vytvořit udržitelný systém.

Proč se Go projekty mění v labyrint souborů?

Vývojáři přicházející do Go z jiných jazyků často přenášejí architektonické návyky, které nejsou vhodné pro idiomatické Go. Podle Go Developer Survey 2024 je hlavním problémem udržování jednotných standardů kódu kvůli rozdílné úrovni zkušeností a neidiomatickým vzorům. Například vytváření struktury se složkami domain, application, infrastructure podle vzoru Javy, ale bez porozumění podstatě.

Výzkum Carnegie Mellon potvrzuje: architektonické problémy jsou hlavním zdrojem technického dluhu. V Go to vypadá takto:

Google AdInline article slot
  • Složka dto s duplicitními strukturami.
  • mappers mezi vrstvami, kde je konverze triviální.
  • Rozhraní v domain, která závisí na infrastruktuře (např. database/sql).
  • Use case, který pouze volá repozitář bez obchodní logiky.

Výsledek: 200 souborů, ale žádný, kde je popsána skutečná obchodní pravidla. Clean Architecture a DDD se stávají ne řešením, ale příčinou problému.

DDD: ne o složkách, ale o jazyce a hranicích

Domain-Driven Design – to není sada složek, ale přístup k modelování doménové oblasti. Klíčové koncepty:

Společný jazyk (Ubiquitous Language)

Vývojáři a obchodní tým musí používat stejné termíny všude: v kódu, dokumentaci, jednáních. Pokud manažer říká „potvrdit objednávku“, v kódu musí být metoda Confirm(), ne SetStatus(). To eliminuje nejasnosti a urychluje onboarding.

Google AdInline article slot

Omezený kontext (Bounded Context)

Velký systém se skládá z několika kontextů. Například „klient“ v prodejním oddělení (lead s prodejní trychtýř) a v podpoře (tickety) – to jsou různé modely. Bounded Context stanovuje jasné hranice, uvnitř kterých je model konzistentní. V mikroservisích obvykle odpovídá jeden servis jednomu kontextu.

Entita (Entity) a hodnotový objekt (Value Object)

  • Entity má unikátní ID a zachovává identitu (např. Order). Obsahuje obchodní pravidla.
  • Value Object je neměnný a definován atributy (např. Money). Dva objekty se stejnými poli jsou ekvivalentní.

Příklad Value Object v Go:

type Money struct {
    Amount   int64
    Currency string
}

func (m Money) Add(other Money) (Money, error) {
    if m.Currency != other.Currency {
        return Money{}, errors.New("currency mismatch")
    }
    return Money{Amount: m.Amount + other.Amount, Currency: m.Currency}, nil
}

Agregát (Aggregate)

Skupina objektů zpracovávaná jako jednotný celek. Má kořen (Aggregate Root), přes který probíhá přístup. Například Order (kořen) zahrnuje OrderItem. Pravidlo: změny se provádějí pouze přes kořen, což zaručuje integritu.

Google AdInline article slot

Clean Architecture: pravidlo závislostí jako základ

Podstata Clean Architecture spočívá v tom, že obchodní logika nesmí záviset na detailech (databáze, frameworky). Jediné pravidlo: závislosti směřují dovnitř (Dependency Rule).

Jak to funguje v Go

  • domain: obsahuje obchodní model (Entity, Value Object, rozhraní repozitářů). Žádné externí importy kromě stdlib.
  • application: use cases orchestrující doménu. Závisí pouze na domain.
  • infrastructure: implementace adaptérů (databáze, HTTP klienti). Závisí na domain přes rozhraní.
  • delivery: vstupní body (HTTP, gRPC). Závisí na application.

Pokud domain importuje database/sql – architektura je porušena. Správný příklad: rozhraní repozitáře je deklarováno v domain, implementace v infrastructure/postgres.

Výhody kombinace DDD a Clean Architecture

| Aspekt | Efekt | Metrika zlepšení |

|----------------|---------------------------------|------------------|

| Testovatelnost | Izolace domény od infrastruktury | +40% coverage |

| Flexibilita | Výměna adaptérů za hodiny | -90% času |

| Porozumění | Jasné hranice komponentů | -70% onboarding |

Reálná struktura projektu: jak se vyhnout 200 souborům

Optimální struktura pro Go servis:

internal/
  domain/
    order.go        # agregát Order
    order_repo.go   # rozhraní repozitáře
  application/
    create_order.go # use case
  infrastructure/
    postgres/
      order_repo.go # implementace
  delivery/
    http/
      order_handler.go

Klíčové principy:

  • Rozhraní repozitářů – v domain, ne v infrastructure.
  • Žádné složky dto a mappers bez nutnosti: používejte stejné struktury ve vrstvách, pokud to neporušuje hranice.
  • Obchodní logika – pouze v domain. Například metoda Cancel() pro Order kontroluje stav:
func (o *Order) Cancel() error {
    if o.status == StatusShipped {
        return errors.New("cannot cancel shipped order")
    }
    o.status = StatusCancelled
    return nil
}

Co je důležité

  • Ubiquitous Language – základ DDD. Pokud termíny v kódu neodpovídají businessu, model bude chybný.
  • Dependency Rule – jádro Clean Architecture. Porušení vede ke spaghetti kódu.
  • Pragmatismus – nevytvářejte vrstvy bez potřeby. V Go často stačí bez dto, pokud struktury odpovídají.
  • Agregáty – hranice transakcí. Měňte pouze přes kořen pro konzistenci.
  • Testování – doména se testuje bez infrastruktury, což urychluje vývoj.

— Editorial Team

Advertisement 728x90

Číst dál