- Add Architecture Beliefs section to manifesto with outcome-focused beliefs: auditability, business language in code, independent evolution, explicit over implicit - Create software-architecture.md as human-readable documentation - Enhance software-architecture skill with beliefs→patterns mapping (DDD, Event Sourcing, event-driven communication) and auto-trigger description - Update work-issue command to reference skill and check project architecture - Update issue-worker agent with software-architecture skill - Add Architecture section template to vision-management skill The skill is now auto-triggered when implementing, reviewing, or planning architectural work. Project-level architecture choices go in vision.md. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
131 lines
4.7 KiB
Markdown
131 lines
4.7 KiB
Markdown
# Software Architecture
|
|
|
|
> **For Claude:** This content is mirrored in `skills/software-architecture/SKILL.md` which is auto-triggered when relevant. You don't need to load this file directly.
|
|
|
|
This document describes the architectural patterns we use to achieve our [architecture beliefs](./manifesto.md#architecture-beliefs). It serves as human-readable organizational documentation.
|
|
|
|
## Beliefs to Patterns
|
|
|
|
| Belief | Primary Pattern | Supporting Patterns |
|
|
|--------|-----------------|---------------------|
|
|
| Auditability by default | Event Sourcing | Immutable events, temporal queries |
|
|
| Business language in code | Domain-Driven Design | Ubiquitous language, aggregates, bounded contexts |
|
|
| Independent evolution | Event-driven communication | Bounded contexts, published language |
|
|
| Explicit over implicit | Commands and Events | Domain events, clear intent |
|
|
|
|
## Event Sourcing
|
|
|
|
**Achieves:** Auditability by default
|
|
|
|
Instead of storing current state, we store the sequence of events that led to it.
|
|
|
|
**Core concepts:**
|
|
- **Events** are immutable facts about what happened, named in past tense: `OrderPlaced`, `PaymentReceived`
|
|
- **State** is derived by replaying events, not stored directly
|
|
- **Event store** is append-only - history is never modified
|
|
|
|
**Why this matters:**
|
|
- Complete audit trail for free
|
|
- Debug by replaying history
|
|
- Answer "what was the state at time X?"
|
|
- Recover from bugs by fixing logic and replaying
|
|
|
|
**Trade-offs:**
|
|
- More complex than CRUD for simple cases
|
|
- Requires thinking in events, not state
|
|
- Eventually consistent read models
|
|
|
|
## Domain-Driven Design
|
|
|
|
**Achieves:** Business language in code
|
|
|
|
The domain model reflects how the business thinks and talks.
|
|
|
|
**Core concepts:**
|
|
- **Ubiquitous language** - same terms in code, conversations, and documentation
|
|
- **Bounded contexts** - explicit boundaries where terms have consistent meaning
|
|
- **Aggregates** - clusters of objects that change together, with one root entity
|
|
- **Domain events** - capture what happened in business terms
|
|
|
|
**Why this matters:**
|
|
- Domain experts can read and validate the model
|
|
- New team members learn the domain through code
|
|
- Changes in business rules map clearly to code changes
|
|
|
|
**Trade-offs:**
|
|
- Upfront investment in understanding the domain
|
|
- Boundaries may need to shift as understanding grows
|
|
- Overkill for pure technical/infrastructure code
|
|
|
|
## Event-Driven Communication
|
|
|
|
**Achieves:** Independent evolution
|
|
|
|
Services communicate by publishing events, not calling each other directly.
|
|
|
|
**Core concepts:**
|
|
- **Publish events** when something important happens
|
|
- **Subscribe to events** you care about
|
|
- **No direct dependencies** between publisher and subscriber
|
|
- **Eventual consistency** - accept that not everything updates instantly
|
|
|
|
**Why this matters:**
|
|
- Add new services without changing existing ones
|
|
- Services can be deployed independently
|
|
- Natural resilience - if a subscriber is down, events queue
|
|
|
|
**Trade-offs:**
|
|
- Harder to trace request flow
|
|
- Eventual consistency requires different thinking
|
|
- Need infrastructure for reliable event delivery
|
|
|
|
## Commands and Events
|
|
|
|
**Achieves:** Explicit over implicit
|
|
|
|
Distinguish between requests (commands) and facts (events).
|
|
|
|
**Core concepts:**
|
|
- **Commands** express intent: `PlaceOrder`, `CancelSubscription`
|
|
- Commands can be rejected (validation, business rules)
|
|
- **Events** express facts: `OrderPlaced`, `SubscriptionCancelled`
|
|
- Events are immutable - what happened, happened
|
|
|
|
**Why this matters:**
|
|
- Clear separation of "trying to do X" vs "X happened"
|
|
- Commands validate, events just record
|
|
- Enables replay - reprocess events with new logic
|
|
|
|
## When to Diverge
|
|
|
|
These patterns are defaults, not mandates. Diverge intentionally when:
|
|
|
|
- **Simplicity wins** - a simple CRUD endpoint doesn't need event sourcing
|
|
- **Performance requires it** - sometimes synchronous calls are necessary
|
|
- **Team context** - patterns the team doesn't understand cause more harm than good
|
|
- **Prototyping** - validate ideas before investing in full architecture
|
|
|
|
When diverging, document the decision in the project's vision.md (see below).
|
|
|
|
## Project-Level Architecture
|
|
|
|
Each project should document its architectural choices in `vision.md` under an **Architecture** section:
|
|
|
|
```markdown
|
|
## Architecture
|
|
|
|
This project follows organization architecture patterns.
|
|
|
|
### Alignment
|
|
- Event sourcing for [which aggregates/domains]
|
|
- Bounded contexts: [list contexts and their responsibilities]
|
|
- Event-driven communication between [which services]
|
|
|
|
### Intentional Divergences
|
|
| Area | Standard Pattern | What We Do Instead | Why |
|
|
|------|------------------|-------------------|-----|
|
|
| [area] | [expected pattern] | [actual approach] | [reasoning] |
|
|
```
|
|
|
|
This creates traceability: org beliefs → patterns → project decisions.
|