Back to catalog

composable-architecture

Apply functional and compositional architecture patterns when designing systems, modules, and components. Use when creating architecture definitions, designing system boundaries, defining interfaces, or building modular systems.

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
name: composable-architecture
description: Apply functional and compositional architecture patterns when designing systems, modules, and components. Use when creating architecture definitions, designing system boundaries, defining interfaces, or building modular systems.
---

# Composable Architecture Patterns

Apply these patterns when designing systems for modularity, testability, and maintainability.

## Core Principles

### Functional Core, Imperative Shell
- **Pure core**: Business logic as pure functions (no side effects, immutable)
- **Imperative shell**: I/O and side effects pushed to system edges
- **Clear boundary**: Ports define interaction points between core and shell
- **Testing strategy**: Unit test the core, integration test the shell

### Composition Over Inheritance
- Build systems from small, composable functions
- Combine simple components to create complex behaviors
- Use function pipelines and modifier chaining
- Prefer data transformation over stateful mutation

## Architecture Patterns

### Hexagonal Architecture (Ports & Adapters)
```
[External World] → [Adapter] → [Port] → [Core Logic] → [Port] → [Adapter] → [External World]
```

**Components**:
- **Core**: Pure business logic, no external dependencies
- **Ports**: Interfaces defining capabilities (what the core needs/provides)
- **Adapters**: Implementations connecting to external systems
- **Primary ports**: API the application provides (commands/queries)
- **Secondary ports**: Services the application needs (persistence/messaging)

### C4 Model Hierarchy
1. **System Context**: Boundaries and external actors
2. **Container/Module**: Major architectural components
3. **Component**: Internal module structure
4. **Code**: Implementation details

**Key practices**:
- Single model, multiple views
- Version-controlled definitions
- Automated diagram generation
- Clear labeling and relationships

## Implementation Patterns

### Architecture-as-Code
Define architecture in YAML/JSON for automated generation:

```yaml
system:
  name: OrderProcessing
  boundary:
    internal: [OrderService, PaymentService]
    external: [Customer, PaymentGateway]

modules:
  - id: order-service
    responsibility: Manages order lifecycle
    ports:
      primary: [CreateOrder, GetOrderStatus]
      secondary: [SaveOrder, NotifyCustomer]
```

**Benefits**:
- Version control alongside code
- CI/CD pipeline generation
- Consistent documentation
- Automated validation

### Modular Component Design
```yaml
component:
  name: TireModel
  module: physics
  interface:
    inputs: [WheelState, ChassisVelocity]
    outputs: [TireForces]
  behavior:
    pure: true  # No side effects
    deterministic: true
```

**Characteristics**:
- Self-contained units
- Clear input/output contracts
- Minimal dependencies
- Independent scalability

### State Machine Composition
```
State A --event1--> State B
     └---event2--> State C
```

**Best practices**:
- Pure state transition functions
- Effects separated from transitions
- Composable sub-machines
- Explicit state representation

## Interface Design

### Port Definition
```typescript
// Primary port (provided by core)
interface OrderCommands {
  createOrder(items: Item[]): OrderId
  cancelOrder(id: OrderId): Result
}

// Secondary port (required by core)
interface OrderRepository {
  save(order: Order): Promise<void>
  findById(id: OrderId): Promise<Order>
}
```

### Adapter Pattern
```typescript
// Adapter implements port interface
class PostgresOrderRepository implements OrderRepository {
  // Connects pure core to impure database
}
```

## Quality Checklist

Before finalizing architecture:
- [ ] Core logic is pure (testable without mocks)
- [ ] Dependencies flow inward (no core → shell references)
- [ ] Ports defined as interfaces/contracts
- [ ] Each module has single responsibility
- [ ] Components compose without tight coupling
- [ ] State mutations isolated to shell
- [ ] Configuration externalized (YAML/env)
- [ ] Clear boundaries between layers

## Anti-patterns to Avoid

**DON'T**:
- Mix business logic with I/O operations
- Create circular dependencies between modules
- Use inheritance for code reuse (use composition)
- Scatter state mutations throughout the system
- Couple core logic to specific technologies
- Create "god" modules with multiple responsibilities

**DO**:
- Keep core logic pure and deterministic
- Push side effects to system edges
- Define clear ports between layers
- Use dependency injection for flexibility
- Test core logic without external dependencies
- Build from small, composable pieces

## Practical Application

### When designing a new system:
1. **Define boundaries**: What's inside vs. outside?
2. **Identify ports**: What capabilities needed/provided?
3. **Design pure core**: Business rules as functions
4. **Create adapters**: Connect to external world
5. **Configure composition**: Wire components together

### When refactoring existing code:
1. **Extract pure functions** from mixed logic
2. **Identify boundaries** between concerns
3. **Define interfaces** for dependencies
4. **Move I/O to edges** of the system
5. **Replace inheritance** with composition

## Example Architecture

```yaml
# Functional payment processor
system:
  core:
    # Pure business logic
    - validatePayment(amount, card) -> ValidationResult
    - calculateFees(amount, type) -> FeeBreakdown
    - determineRiskScore(transaction) -> RiskScore

  ports:
    primary:
      - ProcessPayment  # Command
      - GetTransaction  # Query
    secondary:
      - PaymentGateway  # External API
      - TransactionStore # Persistence
      - FraudDetector   # External service

  adapters:
    inbound:
      - REST API → ProcessPayment port
      - GraphQL → GetTransaction port
    outbound:
      - StripeAdapter → PaymentGateway port
      - PostgresAdapter → TransactionStore port
```

**Remember**: Composable architecture is about building systems from simple, pure, testable pieces that combine predictably. Keep the complex logic in the pure core, push the messy reality to the edges.