tl-first-principles
First Principles of Software Design
The foundational axioms of quality software, traced to their intellectual origins.
"First Principles" carries a deliberate double meaning:
- Epistemological — Reasoning from irreducible truths rather than by analogy
- Historical — The first people who articulated these principles; the founders
This skill provides the why behind best practices by connecting modern conventions to their intellectual lineage.
When to Use
- Making architectural decisions with trade-offs
- Evaluating whether code violates design principles
- Understanding why a pattern exists, not just how
- Teaching or explaining software design
- Code review with principled reasoning
Principles Index
| Principle | Founder(s) | Key Work | Link |
|---|---|---|---|
| Information Hiding | Parnas | 1972 | Decompose by secrets |
| Separation of Concerns | Dijkstra | 1974 | One thing at a time |
| Abstraction & Contracts | Liskov, Hoare | 1974, 1969 | Interfaces as promises |
| Single Source of Truth | Hunt & Thomas | 1999 | Every fact once |
| Conceptual Integrity | Brooks | 1975 | One coherent vision |
| Fail Fast | Hamilton, Shore | 1960s, 2004 | Early detection |
| Composition Over Inheritance | GoF | 1994 | Flexible assembly |
| Explicit Over Implicit | Peters | 1999 | Clarity always |
Founders Index
| Name | Era | Primary Contribution | Link |
|---|---|---|---|
| David Parnas | 1970s | Modularity, information hiding | |
| Edsger Dijkstra | 1960s-70s | Structured programming, SoC | |
| Barbara Liskov | 1970s-90s | Data abstraction, substitutability | |
| C.A.R. Hoare | 1960s-70s | Contracts, formal reasoning | |
| Frederick Brooks | 1970s | Conceptual integrity, system design | |
| Margaret Hamilton | 1960s | Software engineering, reliability | |
| Andy Hunt & Dave Thomas | 1990s | DRY, pragmatic practice | |
| Gang of Four | 1990s | Design patterns |
How to Use This Skill
For Decision-Making
When evaluating a design choice, identify which principles are at stake:
"Should we duplicate this validation logic in both services?"
→ Principle: Single Source of Truth (Hunt & Thomas)
→ Risk: Drift when one copy changes but the other doesn't
→ Decision: Extract to shared module or single service
For Code Review
Cite the principle and its lineage when explaining why something matters:
"This component fetches data AND renders AND handles errors.
That's three concerns in one place.
→ Principle: Separation of Concerns (Dijkstra, 1974)
→ Why it matters: Each concern changes for different reasons
→ Suggestion: Extract data fetching to a hook"
For Learning
Trace modern patterns back to their origins:
React hooks → Composition over Inheritance → GoF (1994)
TypeScript interfaces → Contracts → Hoare (1969), Liskov (1987)
Redux single store → SSOT → Hunt & Thomas (1999)
Microservices → Information Hiding → Parnas (1972)
Convergence Map
These principles emerged from different lineages but converge on the same goal: managing complexity in systems that must change over time.
┌─────────────────────────────────────â”
│ MANAGING COMPLEXITY IN SYSTEMS │
│ THAT MUST CHANGE OVER TIME │
└───────────────┬─────────────────────┘
│
┌──────────────┬───────────────┼───────────────┬──────────────â”
â–¼ â–¼ â–¼ â–¼ â–¼
┌─────────────┠┌───────────┠┌─────────────┠┌─────────────┠┌──────────â”
│ MODULARITY │ │ LEGIBILITY│ │ ABSTRACTION │ │ INTEGRITY │ │ FEEDBACK │
│ Parnas │ │ Dijkstra │ │Liskov/Hoare │ │ Brooks │ │ Hamilton │
└─────────────┘ └───────────┘ └─────────────┘ └─────────────┘ └──────────┘
│ │ │ │ │
â–¼ â–¼ â–¼ â–¼ â–¼
Information Separation Contracts & Conceptual Fail Fast
Hiding of Concerns Substitution Integrity
│ │ │ │ │
└──────────────┴───────────────┴───────────────┴──────────────┘
│
┌───────────────┼───────────────â”
â–¼ â–¼ â–¼
┌─────────────┠┌─────────────┠┌─────────────â”
│ SOLID │ │ DRY │ │ PATTERNS │
│ Uncle Bob │ │ Hunt/Thomas │ │ GoF │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└───────────────┼───────────────┘
â–¼
┌─────────────────────────────────────â”
│ MODERN PRACTICE │
│ Clean Architecture, Microservices, │
│ Functional Core, React Composition │
└─────────────────────────────────────┘
Primary Sources
See sources/primary-sources.md for annotated bibliography with links to original papers and books.
Decision Heuristics
When principles appear to conflict, use these heuristics:
Information Hiding vs Explicitness
| Choose Information Hiding | Choose Explicitness |
|---|---|
| Implementation will change | Interface is the value |
| Multiple consumers | Single-use utility |
| Encapsulation aids testing | Debugging requires visibility |
SRP vs DRY
| Choose SRP (accept duplication) | Choose DRY (accept coupling) |
|---|---|
| Code changes for different reasons | Code truly represents one concept |
| Teams own different copies | Central ownership is clear |
| Coupling cost > duplication cost | Duplication cost > coupling cost |
YAGNI vs Extensibility
| Choose YAGNI (build less) | Choose Extensibility (build hooks) |
|---|---|
| Uncertain requirements | Known variation points |
| Prototype or MVP | Library or framework |
| Single consumer | Multiple consumers |
Scale Considerations
| Context | Principle Emphasis |
|---|---|
| Solo developer | Conceptual Integrity (one mind) |
| Team | Separation of Concerns (parallel work) |
| Prototype | YAGNI, Fail Fast |
| Production | Information Hiding, Contracts |
| Library | Liskov Substitution, Stable APIs |
| Application | Composition, Flexibility |
Anti-Pattern Catalog
| Anti-Pattern | Violated Principle | Consequence |
|---|---|---|
| God Object | SRP | Changes ripple everywhere; untestable |
| Leaky Abstraction | Information Hiding | Consumers depend on implementation details |
| Shotgun Surgery | SoC | One change requires editing many files |
| Primitive Obsession | Abstraction | Scattered validation; unclear semantics |
| Feature Envy | Information Hiding | Method uses another object's data more than its own |
| Divergent Change | SRP | One class changes for multiple unrelated reasons |
| Parallel Inheritance | Composition | Adding one class requires adding another |
| Dead Code | Explicit over Implicit | Confusion about what's active |
| Speculative Generality | YAGNI | Complexity for unused flexibility |
| Inappropriate Intimacy | Information Hiding | Classes know too much about each other |
Diagnostic Questions
- Does this change for multiple reasons? → SRP violation
- Could I swap this implementation? → Information Hiding check
- Is this fact represented once? → DRY/SSOT check
- Can I test this in isolation? → Coupling smell
- Does the name explain the purpose? → Abstraction quality
Principle Interactions
Reinforcing Relationships
graph LR
SoC[Separation of Concerns] --> SRP[Single Responsibility]
SRP --> Testability
InfoHide[Information Hiding] --> Abstraction
Abstraction --> Substitutability
Testability --> SRP
DI[Dependency Injection] --> Testability
Tension Relationships
| Tension | Resolution |
|---|---|
| DRY ↔ Coupling | Accept duplication when coupling is worse |
| YAGNI ↔ Extensibility | Build for known requirements only |
| Explicitness ↔ Hiding | Hide implementation, expose intent |
| Performance ↔ Abstraction | Optimize measured bottlenecks only |
Related Skills
This skill provides the theory. For practice, see:
| Need | Skill |
|---|---|
| Database patterns | drizzle-patterns |
| Code quality setup | code-quality-setup |
| Codebase audit | codebase-audit |
| Complexity assessment | tl-complexity-assessment |
References
Quilted Skills
- sickn33/software-architecture — Architecture patterns
- athola/code-quality-principles — KISS, YAGNI
- ramziddin/solid-skills — SOLID principles
First-Party Academic Sources
- Parnas 1972 — On the Criteria To Be Used in Decomposing Systems into Modules
- Dijkstra — On the Role of Scientific Thought (EWD447)
- Liskov 1987 — Data Abstraction and Hierarchy
- Brooks 1975 — The Mythical Man-Month
Modern Interpretation
- Martin Fowler's Bliki — Contemporary patterns
- Clean Coder Blog — Robert Martin on SOLID
- Refactoring.Guru — Pattern explanations
Books
- Clean Architecture (Martin)
- Domain-Driven Design (Evans)
- Patterns of Enterprise Application Architecture (Fowler)
Skill References
- sources/primary-sources.md — Annotated bibliography
- principles/ — Individual principle deep-dives
- founders/ — Biographical context for key figures
More from toddlevy/tl-agent-skills
tl-openmeter-api
Works with the OpenMeter REST API for usage metering, billing, and entitlements. Covers CloudEvents ingestion, meters, features, plans, customers, subscriptions, entitlements, notifications, billing profiles, invoices, apps, addons, grants, and the Stripe marketplace. Use when integrating OpenMeter, debugging metering, building catalog sync scripts, or when the user mentions OpenMeter API.
15tl-knip
Find and remove unused files, dependencies, and exports in TypeScript/JavaScript projects using Knip. Covers configuration-first workflow, plugin system, barrel file handling, CI integration, monorepo support, and agent-specific cleanup guidance.
14tl-docs-create
Create documentation from scratch for codebases. Covers SSOT-driven generation, writing standards, and templates for README/AGENTS.md/CHANGELOG. Use when creating new docs or documenting an undocumented codebase.
14tl-devlog
Maintain a structured development changelog (DEVLOG.md) capturing architectural decisions, milestones, incidents, and insights. Use when the user says "log this", "devlog", "archive this", or at natural pause points after significant decisions. Trigger on changelog, decision log, work log, or progress tracking.
14tl-docs-audit
Audit existing documentation for gaps, staleness, and sync issues. Generates sync reports with actionable findings. Use when reviewing doc coverage, finding outdated docs, or syncing docs with code.
14tl-pg-boss
PostgreSQL-backed job queue with exactly-once delivery using SKIP LOCKED. Use when adding background jobs, task scheduling, cron jobs, or async processing to Node.js apps already using Postgres.
14