Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
6.1 KiB
6.1 KiB
Design Patterns — When to Use
Creational
Factory Method
- When: Object creation depends on runtime conditions, need to decouple
newfrom business logic - Signal:
if/switchchoosing which class to instantiate - Implementation: Abstract creator + concrete creators
- Avoid when: Only one product type, no variation expected
Abstract Factory
- When: Families of related objects that must be used together (UI themes, DB dialects)
- Signal: Multiple factories that produce related objects
- Avoid when: Single family — use Factory Method instead
Builder
- When: Object needs 4+ constructor params, optional fields, step-by-step construction
- Signal: Telescoping constructors, many optional params, config objects
- Implementation: Builder class with fluent API,
.build()validates - Avoid when: Simple object with 1-3 required params
Singleton
- When: ONLY for true global state — DB connection pool, config, logger
- Signal:
getInstance()pattern - DANGER: Overused. Prefer dependency injection. Singletons hide dependencies and break tests
- Modern alternative: DI container (NestJS providers, Spring beans)
Prototype
- When: Cloning complex objects is cheaper than creating from scratch
- Signal: Objects with heavy initialization, deep nested state
- Avoid when: Objects are simple to construct
Structural
Adapter
- When: Integrating incompatible interfaces (3rd party lib, legacy API)
- Signal: Wrapper that translates interface A to interface B
- Rule: Adapter should be thin — only translate, no business logic
Facade
- When: Complex subsystem needs a simple entry point
- Signal: Client talks to 5+ classes to do one thing
- Rule: Facade doesn't prevent direct access to subsystem
Decorator
- When: Add responsibilities dynamically without subclassing
- Signal: Need multiple optional behaviors that compose (logging + caching + auth)
- Implementation: Same interface as wrapped object
- Modern: Middleware chains (Express/NestJS), Python decorators, TypeScript decorators
Proxy
- When: Control access, lazy loading, caching, logging
- Signal: Same interface but with intercepted behavior
- Modern: JS Proxy, ORM lazy loading, API rate limiting
Composite
- When: Tree structures — UI components, file systems, org charts
- Signal: "Part-whole" hierarchy where leaf and composite treated same
- Modern: React component tree, AST nodes
Behavioral
Strategy
- When: Multiple algorithms interchangeable at runtime
- Signal:
if/elseorswitchon algorithm type - Implementation: Interface + concrete strategies + context
- Modern: Function params (pass algorithm as callback)
Observer / Event Emitter
- When: One-to-many dependency, reactive updates
- Signal: "When X happens, notify Y, Z, W"
- Implementation: EventEmitter, pub/sub, webhooks
- Modern: RxJS, EventEmitter, Redis pub/sub, WebSocket broadcasts
Command
- When: Undo/redo, queue operations, macro recording
- Signal: Need to parametrize actions, defer execution, support undo
- Implementation: Command object with execute() + undo()
State Machine
- When: Object behavior changes based on internal state
- Signal: Multiple
if (state === 'X')checks scattered in code - Implementation: State interface + concrete states + transitions map
- Modern: XState, finite state machines, workflow engines
Repository
- When: Abstract data access from business logic
- Signal: Business logic directly queries DB
- Implementation: Interface with CRUD + query methods, concrete per storage
- Rule: Repository returns domain objects, NOT raw DB rows
Middleware / Chain of Responsibility
- When: Sequential processing with optional short-circuit
- Signal: Request passes through auth → validation → rate limit → handler
- Modern: Express/Koa middleware, NestJS guards/pipes/interceptors
Dependency Injection
- When: ALWAYS for non-trivial apps
- Signal: Classes create their own dependencies with
new - Implementation: Constructor injection (preferred), setter injection
- Modern: NestJS modules, Spring, tsyringe, InversifyJS
- Rule: Depend on abstractions (interfaces), not concretions
Architectural Patterns
MVC / MVVM
- When: UI applications with clear data-view separation
- Modern: React (View) + Zustand/Redux (Model) + hooks/services (Controller)
Clean Architecture / Hexagonal
- When: Business logic must be independent of framework/DB/UI
- Layers: Domain → Use Cases → Interface Adapters → Frameworks
- Rule: Dependencies point INWARD only
CQRS
- When: Read and write patterns differ significantly
- Signal: Complex queries + simple writes, or read scaling needed
- Avoid when: Simple CRUD — overkill
Event Sourcing
- When: Need full audit trail, time-travel debugging, complex domain events
- Signal: "What happened" matters more than "current state"
- DANGER: Massive complexity increase. Only if truly needed
Microservices
- When: Independent deployment, team autonomy, different scaling needs
- DANGER: Overused. Start with monolith, extract when pain points emerge
- Rule: If you can't build a well-structured monolith, microservices won't help
Selection Rules
Need to create objects?
├── Many optional params → Builder
├── Runtime type selection → Factory Method
├── Related object families → Abstract Factory
└── Expensive initialization → Prototype
Need to structure code?
├── Incompatible interface → Adapter
├── Simplify complex system → Facade
├── Add optional behavior → Decorator
├── Control access → Proxy
└── Tree structure → Composite
Need to manage behavior?
├── Multiple algorithms → Strategy
├── React to changes → Observer
├── Undo/redo needed → Command
├── State-dependent behavior → State Machine
├── Sequential processing → Middleware
└── Decouple creation from use → DI