Skip to content

Commit 0d09dc2

Browse files
committed
docs(adr,plan): record Hexagonal Architecture decision in ADR-0002 and update migration plan
1 parent 81e01eb commit 0d09dc2

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

docs/MIGRATION_PLAN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Steps
4848
- [x] Update `docs/DEVELOPER.md` paths
4949
- [x] Add Hexagonal code examples in `apps/backend/core`
5050
- [ ] Add contribution notes for adapters and ports
51+
- [x] Record decision: add ADR for Hexagonal Architecture (Ports & Adapters)
5152

5253
Notes
5354
- Keep migrations and Django app structure working while extracting domain/application code.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
ADR-0002: Adopt Hexagonal Architecture (Ports & Adapters)
2+
3+
Status: Accepted
4+
Date: 2025-09-14
5+
6+
Context
7+
- We are consolidating services in a monorepo and need a structure that keeps domain logic independent from frameworks, databases, and delivery mechanisms (REST/WS/CLI).
8+
- The project integrates multiple external systems (Binance, Redis, RabbitMQ, Object Storage) and must remain testable and evolvable as technologies change.
9+
- Existing Django code mixes domain rules with framework concerns, making tests and substitutions harder.
10+
11+
Decision
12+
- Adopt Hexagonal Architecture (Ports & Adapters) as the central architectural pattern.
13+
- Organize backend code into:
14+
- `domain/`: entities, value objects, domain services (no framework imports)
15+
- `application/`: use cases and ports (interfaces)
16+
- `adapters/`: implementations of ports (driven: DB/cache/broker/external APIs; driving: REST/WS/CLI)
17+
- `wiring/`: composition root for dependency injection and transactions
18+
- Keep infrastructure (Terraform, Ansible, K8s manifests) outside application packages under `infra/`.
19+
20+
Consequences
21+
- Positive
22+
- Domain logic remains independent from frameworks and I/O technologies.
23+
- High testability via port fakes/mocks; contract tests for adapters.
24+
- Easier technology swaps (e.g., replace RabbitMQ or HTTP client) without touching domain/application.
25+
- Trade-offs
26+
- Requires discipline on import boundaries and an initial migration cost.
27+
- Some duplication in mapping DTOs <-> persistence/API until generators or shared contracts are in place.
28+
29+
Implementation Notes
30+
- Repository layout: see `docs/ARCHITECTURE.md` and `apps/backend/core/*`.
31+
- Initial use case: `PlaceOrderUseCase` in `apps/backend/core/application/place_order.py`.
32+
- Example ports: `apps/backend/core/application/ports.py`.
33+
- Example adapters:
34+
- Persistence: `apps/backend/core/adapters/driven/persistence/django_order_repo.py`
35+
- External (Binance MD): `apps/backend/core/adapters/driven/external/binance_client.py`
36+
- Messaging (noop): `apps/backend/core/adapters/driven/messaging/noop_bus.py`
37+
- Time: `apps/backend/core/adapters/driven/time/clock.py`
38+
- Wiring: `apps/backend/core/wiring/container.py`.
39+
- Frontend follows the same idea client-side with `src/{domain,application,ports,adapters}`.
40+
41+
Related
42+
- ADR-0001: BinanceService Singleton (legacy service compatibility and testing strategy)
43+
- docs/ARCHITECTURE.md
44+
- docs/MIGRATION_PLAN.md
45+

0 commit comments

Comments
 (0)