From tdder
Guides progressive architectural decisions, starting simple and adding complexity only when it reduces complexity. Useful during TDD refactor phases and when starting new projects.
How this skill is triggered — by the user, by Claude, or both
Slash command
/tdder:unfolding-architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Progressive architectural decisions: start simple, add complexity only when it reduces complexity.
Progressive architectural decisions: start simple, add complexity only when it reduces complexity.
Architecture is not a blueprint drawn before construction. It unfolds from working code under concrete pressure. Each dimension of architecture starts at its simplest form (Level 0) and only moves to a higher level when a specific, demonstrable problem forces the change.
Level 0 in all dimensions. No deviation without a concrete reason backed by a violated constraint, or measurable complexity increase. "It might be useful later" is never a valid reason to unfold.
| Level | Style | Description |
|---|---|---|
| 0 | OOP: data + logic together | Data and the logic that operates on it live in the same class. Logic hides data. This is the natural OOP default. |
| 1 | DOP: separate data from algorithms | Stable data structures with varying algorithms applied externally. Data is transparent; logic is separate. |
Unfold to Level 1 when:
Do NOT unfold when:
| Level | Style | Description |
|---|---|---|
| 0 | Direct dependencies | Everything knows about everything it uses. No interfaces, no layers, no DTOs. Persistence lives next to domain. |
| 1 | Targeted abstraction | Interface or anti-corruption layer at a specific pain point — persistence, external API, or unstable component. |
| 2 | Ports & adapters (hexagonal) | Full separation of domain from infrastructure via IoC: the domain defines ports (interfaces), adapters implement them, dependencies point inward. Persistence is just one adapter among many. A composition root wires adapters to ports. |
Unfold to Level 1 when:
Unfold to Level 2 when:
Do NOT unfold when:
Note: Even hexagonal architecture can evolve step-by-step. You do not need to introduce all ports and adapters at once. Start with a single targeted abstraction (Level 1) where the pressure is highest, then add more ports as concrete needs arise. Full hexagonal (Level 2) is the result of multiple incremental unfoldings, not a single architectural decision.
| Level | Style | Description |
|---|---|---|
| 0 | Direct method calls | Components call each other directly. Simple, traceable, debuggable. |
| 1 | Domain events (in-process) | Components publish events that other components react to, but within the same process. |
| 2 | Async messaging (broker) | Communication through a message broker. Full decoupling of sender and receiver in time and space. |
Unfold to Level 1 when:
Unfold to Level 2 when:
Do NOT unfold when:
| Level | Style | Description |
|---|---|---|
| 0 | Manual | No enforced dependency rules between packages. Any class can use any other class (as long as it's public). |
| 1 | Package dependency tests | Packages exist with clear responsibilities. Dependency rules between packages are enforced by tests. |
| 2 | Modulith | Separate modules within one deployable unit, each with explicit API boundaries and enforced encapsulation. |
| 3 | Microservices | Independent services, separately built and deployed, communicating over network boundaries. |
Unfold to Level 1 when:
Unfold to Level 2 when:
Unfold to Level 3 when:
Do NOT unfold to Level 1 when:
Do NOT unfold to Level 2 when:
Do NOT unfold to Level 3 when:
| Level | Style | Description |
|---|---|---|
| 0 | Exceptions | Throw exceptions for errors. Catch at appropriate boundaries. Simple and conventional. |
| 1 | Result types | Return result objects that explicitly model success and failure for business outcomes. |
| 2 | Circuit breakers / resilience | Resilience patterns for dealing with unreliable external dependencies. |
Unfold to Level 1 when:
Unfold to Level 2 when:
Do NOT unfold when:
Products for ProductUnfolding happens during the TDD refactor phase:
AskUserQuestion to confirm:
The decision checklist at decision-checklist.md provides a quick rubric.
Adding layers, interfaces, or patterns "because we might need them." If no concrete test or requirement demands it, do not add it.
Making all dimensions the same level. A system might legitimately need Level 2 indirection but Level 0 communication. Each dimension is independent.
Copying the architecture of a different system or a reference application. Architecture must emerge from the specific pressures of this system.
Separating data from logic before multiple algorithms actually exist. Data and logic that change together should stay together.
Adding layers for the sake of "proper architecture": Controller → Service → Repository → DAO, each doing nothing but delegating to the next. Every layer must justify its existence.
npx claudepluginhub t1/tdder --plugin tdderEvaluates architecture options (onion, MVC, simple) enforcing dependency direction and YAGNI-based abstraction decisions. Calls when deciding layer structure or dependency rules.
Guides structured conversations to define repository architecture principles in clean (default), hexagonal/ports & adapters, modular monolith, or custom styles. Produces formal architecture.md document for project standards.
Guides applying Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to structure systems with isolated business logic, layer boundaries, and dependency rules.