Skip to content

Articles VII & VIII: Simplicity

Two articles work together to keep projects simple:

  • Article VII (Simplicity): Minimize moving parts
  • Article VIII (Anti-Abstraction): Don’t abstract until you must

Every component you add is a component you must maintain, monitor, deploy, and debug. Simplicity means choosing the architecture with the fewest moving parts that still meets requirements.

During planning, count your components:

CountAssessment
1-2 projectsSimple — default approval
3 projectsReview — is the third necessary?
4+ projectsRequires justification for each

A “project” is anything independently deployable: a server, a frontend app, a worker process, a database.

Over-engineered:

- React frontend
- Express API server
- Redis cache
- PostgreSQL database
- RabbitMQ message queue
- Worker process

Six components for a dashboard that shows readings from a smart meter.

Right-sized:

- React frontend
- Express API server with SQLite

Two components. SQLite eliminates the need for a separate database server. No cache needed at this scale. No queue needed for synchronous reads.

Don’t create abstractions (interfaces, base classes, factories, wrappers) until you have concrete evidence they’re needed.

Abstract when you have three concrete cases — not before:

// Too early — one case, one abstraction
class BaseDataSource { ... }
class SqliteDataSource extends BaseDataSource { ... }
// Right — direct implementation
const db = new Database('readings.db')

When you eventually need PostgreSQL support and MySQL support, then create the abstraction. Until then, the direct approach is simpler, more readable, and easier to change.

PatternWhy It’s Premature
Repository pattern for one databaseExtra layer with no benefit
Event bus for two componentsDirect function calls are clearer
Plugin system for one pluginBuild the plugin, not the system
Config file for three settingsConstants in code are simpler
Factory for one product typeDirect construction is clearer

During planning, the constitution gate flags:

SignalAction
Plan includes “abstraction layer”Require three concrete use cases
Plan mentions “future-proofing”Flag — build for now, not later
Plan adds indirection with one consumerSimplify — remove the indirection

Simplicity and Anti-Abstraction reinforce each other:

  • Simplicity asks: “Can we use fewer components?”
  • Anti-Abstraction asks: “Can we use fewer layers?”

The result is code that’s direct, readable, and easy to change — exactly what you want when working with AI agents that need to understand your codebase quickly.