# 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:
- Složka
dtos duplicitními strukturami. mappersmezi 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.
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.
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 vinfrastructure. - Žádné složky
dtoamappersbez nutnosti: používejte stejné struktury ve vrstvách, pokud to neporušuje hranice. - Obchodní logika – pouze v
domain. Například metodaCancel()proOrderkontroluje 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
Zatím žádné komentáře.