Agent Skills: Modularity Patterns

Recommends modularity, composition, and decoupling patterns for design challenges. Use when designing plugin architectures, reducing coupling, improving testability, or separating cross-cutting concerns.

UncategorizedID: jdubray/puffin/modularity-patterns

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jdubray/puffin/tree/HEAD/.claude/skills/modularity-patterns

Skill Files

Browse the full folder contents for modularity-patterns.

Download Skill

Loading file tree…

.claude/skills/modularity-patterns/SKILL.md

Skill Metadata

Name
modularity-patterns
Description
Recommends modularity, composition, and decoupling patterns for design challenges. Use when designing plugin architectures, reducing coupling, improving testability, or separating cross-cutting concerns.

Modularity Patterns

Apply these patterns when designing or refactoring code for modularity, extensibility, and decoupling.

Trigger Conditions

Apply this skill when:

  • Designing plugin or extension architectures
  • Reducing coupling between components
  • Improving testability through dependency management
  • Creating flexible, configurable systems
  • Separating cross-cutting concerns

Select the Right Pattern

| Problem | Apply These Patterns | |---------|---------------------| | Hard-coded dependencies | DI, IoC, Service Locator, SAM | | Need runtime extensions | Plugin, Microkernel, Extension Points | | Swappable algorithms | Strategy, Abstract Factory | | Additive behavior | Decorator, Chain of Responsibility, SAM | | Feature coupling | Package by Feature | | Scattered concerns | AOP, Interceptors, Mixins, SAM | | Temporal coupling | Observer, Event Bus, Event Sourcing, SAM | | Read/write optimization | CQRS | | Deployment flexibility | Feature Toggles, Microservices |


Implementation Checklist

When applying any modularity pattern:

  1. Define clear interfaces - Contracts before implementations
  2. Minimize surface area - Expose only what's necessary
  3. Depend on abstractions - Not concrete implementations
  4. Favor composition - Over inheritance
  5. Isolate side effects - Push to boundaries
  6. Make dependencies explicit - Visible in signatures
  7. Design for substitution - Any implementation satisfying contract works
  8. Consider lifecycle - Creation, configuration, destruction
  9. Plan for versioning - APIs evolve, maintain compatibility
  10. Test boundaries - Verify contracts, mock implementations

Pattern Reference

Inversion Patterns

Dependency Injection (DI) - Provide dependencies externally rather than creating internally.

  • Constructor injection (preferred, immutable)
  • Setter injection (optional dependencies)
  • Interface injection (framework-driven)

Inversion of Control (IoC) - Let framework control flow, calling your code. Use IoC containers (Spring, Guice, .NET DI) to manage object lifecycles and wiring.

Service Locator - Query central registry for dependencies at runtime. Achieves decoupling but hides dependencies. Prefer DI for explicitness.


Plugin & Extension Architectures

Plugin Pattern - Load and integrate external code at runtime via defined contracts.

  • Discovery: directory scanning, manifests, registries
  • Lifecycle: load, initialize, unload
  • Isolation: classloaders, processes, sandboxes
  • Versioning: API compatibility

Microkernel Architecture - Build minimal core with all domain functionality in plugins. Examples: VS Code, Eclipse IDE.

Extension Points & Registry - Define multiple specific extension points rather than single plugin interface. Extensions declare which points they extend.


Structural Composition

Strategy Pattern - Encapsulate interchangeable algorithms behind common interface.

Context → Strategy Interface → Concrete Strategies

Use for runtime behavioral swapping (sorting, validation, pricing).

Decorator Pattern - Wrap objects to add behavior without modification.

Component → Decorator → Decorator → Concrete Component

Use for composable behavior chains (logging, caching, validation).

Composite Pattern - Treat individuals and compositions uniformly via shared interface. Use for tree structures, UI hierarchies, file systems.

Chain of Responsibility - Create pipeline of handlers where each processes or forwards. Use for middleware stacks, request processing pipelines.

Bridge Pattern - Separate abstraction from implementation hierarchies. Use to prevent subclass explosion with multiple varying dimensions.


Module Boundaries

Module Pattern - Encapsulate private state, expose public interface. Modern implementations: ES Modules, CommonJS, Java 9 modules.

Facade Pattern - Provide simplified interface to complex subsystem. Use to establish clean module boundaries.

Package Organization

  • By Layer: Group controllers, repositories, services separately
  • By Feature: Group everything for "orders" together (preferred for modularity)

Event-Driven Decoupling

Observer Pattern - Implement publish-subscribe where subjects notify observers without knowing them.

Event Bus / Message Broker - Enable system-wide pub-sub with fully decoupled publishers and subscribers. Add behaviors by adding subscribers without publisher changes.

Event Sourcing - Store state changes as event sequence, not snapshots. Enable new projections via event replay; new behaviors react to stream.

CQRS - Separate read and write models.

Commands → Write Model (validation, rules, persistence)
Queries → Read Model (optimized for reading)

Cross-Cutting Concerns

Aspect-Oriented Programming (AOP) - Modularize scattered concerns (logging, security, transactions). Define pointcuts (where) and advice (what).

Interceptors & Middleware - Explicitly wrap method calls or request pipelines. Less magical than AOP, more traceable.

Mixins & Traits - Compose behaviors from multiple sources without deep inheritance. Examples: Scala traits, Rust traits, TypeScript intersections.


Configuration Patterns

Feature Toggles - Decouple deployment from release by shipping new code behind flags. Enables trunk-based development, A/B testing, gradual rollouts.

Strategy Configuration - Externalize algorithmic choices to configuration files.

Convention over Configuration - Reduce wiring through established defaults and naming conventions.


Component Models

Component-Based Architecture - Build self-contained components with defined interfaces managing own state. Examples: React, Vue, server-side component frameworks.

Entity-Component-System (ECS) - Separate identity (entities), data (components), behavior (systems). Use for game development, highly dynamic systems.

Service-Oriented / Microservices - Apply component thinking at system level with process isolation boundaries.


Creational Patterns

Registry Pattern - Maintain collection of implementations keyed by type/name, queried at runtime.

Abstract Factory - Create families of related objects without specifying concrete classes.

Prototype Pattern - Create objects by cloning prototypes, avoiding direct class instantiation.


SAM Pattern (State-Action-Model)

Functional decomposition for reactive systems:

  • State: Pure representation of current state
  • Action: Pure functions proposing state changes
  • Model: State acceptor enforcing business rules

Loop: View renders State → Actions propose → Model accepts/rejects → State updates.

Provides natural boundaries between representation, proposals, and validation.