Open je project. Nu. Kijk naar de bestandsstructuur. Ziet het er zo uit?
models.py (5.000 regels, 50 modellen)
services.py (4.000 regels, 30 services)
views.py (3.000 regels, 40 endpoints)
schemas.py (2.000 regels, 60 schema's) Dit is organisatie per laag. Elke tutorial doet het zo. En het maakt AI werkeloos.
Waarom? Je vraagt AI om een scheduling endpoint toe te voegen. Het moet 16.000 regels doorploegen. Daarvan is 2 tot 5 procent relevant. De rest is ruis. Naald in een hooiberg. Geen wonder dat de output de helft van de tijd niet klopt.
Het domein-gebaseerde alternatief
domains/scheduling/
__init__.py (Public API: wat andere domeinen mogen importeren)
models.py (65 regels: alleen de scheduling-tabel)
schemas.py (55 regels: Create, Response, filters)
service.py (100 regels: business logic leeft hier)
router.py (40 regels: dunne routeringslaag)
events.py (domain events)
exceptions.py (domein-specifieke fouten)
tests/
test_service.py
test_router.py Ongeveer 260 regels. 100% relevant. AI houdt het hele domein in z'n werkgeheugen. De code die eruit komt? Past alsof iemand uit je team het geschreven heeft.
De cijfers liegen niet
| Metriek | Laag-gebaseerd | Domein-gebaseerd |
|---|---|---|
| Context voor AI | ~16.000 regels | ~1.000 regels |
| Relevant signaal | 2-5% | 95-100% |
| AI first-try succes | ~40% | ~88% |
| Tijd om AI-output te fixen | 20-30 min | 2-5 min |
| Merge conflicts per week | 6+ | 0,4 |
De regels die het laten werken
- De service layer bezit de business logic. Endpoints zijn dun. Ze ontvangen HTTP, roepen de service aan, geven een response terug. Klaar. Geen business logic in routes. Nooit.
- Geen directe imports tussen domeinen. Scheduling moet iets weten over users? Communiceer via events of een shared interface. Niet door
domains.users.modelsrechtstreeks te importeren. - Public API staat in __init__.py. Dat is het contract van je domein met de buitenwereld. Expose alleen wat andere domeinen echt nodig hebben.
- Events bevatten IDs, geen objecten.
UserDeactivatedEvent(user_id=uuid), nietUserDeactivatedEvent(user=full_user_object). Houdt de koppeling minimaal.
Hoe je een bestaande codebase migreert
Reorganiseer niet alles tegelijk. Pak je kleinste, meest geïsoleerde feature. Verplaats die naar een domeindirectory. Zorg dat het werkt. Pak dan de volgende.
- Identificeer de feature met de minste cross-dependencies
- Maak de domeindirectory aan met de standaard structuur
- Verplaats models, schemas, services en routes naar het domein
- Werk imports bij door de hele codebase
- Run de tests, alles moet nog steeds slagen
- Herhaal met de volgende feature
De meeste teams doen een domein per dag. Twee weken later ziet je project er compleet anders uit. En AI? Wordt ineens bruikbaar.