Clean architecture is often explained like a long-term purity exercise. Contract work is different: you have 4-8 weeks, fixed milestones, and almost zero tolerance for rework. In this model, architecture exists to protect throughput, not to maximize abstraction.
Constraint-first architecture for sprint contracts
In short contracts, four constraints dominate:
- Scope changes every week.
- API contracts are still evolving.
- QA cycles are short and under-staffed.
- Handovers happen while features are still moving.
So the target is not "perfect" structure. The target is stable change boundaries.
Module shape that keeps PRs reviewable
We used vertical feature modules with a small shared core:
- feature/* owns UI, use-cases, and data adapters for one domain.
- core/network, core/storage, core/telemetry stay thin and boring.
- No feature imports another feature directly.
When a feature needed cross-domain data, it used contract interfaces, not implementation imports. This kept PR size and blast radius predictable.
Dependency rules that stop architecture drift
We kept three explicit rules:
- UI depends on use-case interfaces, not concrete repositories.
- Data layer can depend on core infra, never the reverse.
- Feature-to-feature calls happen through shared contracts only.
These rules were linted and reviewed in CI. If violated, build failed.
Delivery lane design
Architecture only helps if delivery flow supports it. We split work into lanes:
- Lane A: feature implementation with interface-first stubs.
- Lane B: backend contract updates and integration tests.
- Lane C: hardening (telemetry, retries, offline behavior).
Because lanes ran in parallel, blockers were isolated. A delayed API endpoint did not freeze all UI work.
CI/CD controls for short projects
For sprint contracts, CI/CD must be strict but lightweight:
- Pull request checks: unit tests, lint, contract tests.
- Daily internal distribution build for stakeholder review.
- Release candidate gate: smoke E2E + crash regression checks.
This reduced late surprises and gave clients visible progress every 24 hours.
Common traps and rescue moves
Trap: over-abstracting early. Rescue: start with simple interfaces and refactor only repeated pain points.
Trap: shared "utils" becoming hidden dependency graph. Rescue: move utility code into explicit domains or core infra.
Trap: architecture docs diverge from implementation. Rescue: keep a one-page decision log updated per sprint.
What to copy for your next contract
If you have 4-8 weeks, prioritize:
- Stable module boundaries
- Enforced dependency rules
- Parallel delivery lanes
- Non-negotiable CI gates
That combination keeps velocity high without turning the final handover into a cleanup project.
Related reading:
Comments
Threaded replies are enabled. Upvote useful ideas.