Skip to content

Instantly share code, notes, and snippets.

@mfilipelino
Last active May 24, 2025 17:42
Show Gist options
  • Save mfilipelino/d1dd4286e01e9c27a64b172313188ed3 to your computer and use it in GitHub Desktop.
Save mfilipelino/d1dd4286e01e9c27a64b172313188ed3 to your computer and use it in GitHub Desktop.

🔑 Core Development Principles

These principles guide sound decision-making throughout the lifecycle of any software project, fostering clarity, maintainability, and robustness.


1. Simple > Complex

Simplicity is the foundation of reliable software. As Dijkstra stated: "Simplicity is a prerequisite for reliability." Complex systems fail in unpredictable ways; simple systems fail predictably and are easier to fix.

Simplicity is measured exclusively by cognitive workload—the mental effort required to understand, modify, and debug code. All other metrics (lines of code, cyclomatic complexity, function count) are misleading proxies.

Critical: Only peers and teammates can judge cognitive workload. Developers are inherently biased toward their own code due to familiarity and context. Never accept "it's simple" from the code author without peer validation.

Nuance: Cognitive workload varies by audience. Consider the experience level and mental models of those who will work with the code. What's simple to experts may be complex to beginners—calibrate accordingly.


2. Efficiency > Efficacy

Efficacy is getting things done—the ability to produce a desired amount of the desired effect, or success in achieving a given goal. Efficiency is doing things in the most economical way.

Efficacy is about the outcome, while efficiency is about the process.

In software development, prioritize efficiency over mere efficacy. Anyone can build software that works (efficacy), but building software that works with minimal resources, cognitive effort, and maintenance overhead requires efficiency. Efficient solutions are sustainable; purely efficacious ones often collapse under their own complexity.

Efficiency manifests as elegant algorithms, optimal resource usage, streamlined processes, and code that accomplishes its purpose with minimal waste—whether that waste is computational cycles, developer time, or cognitive energy.


3. Make It Work, Make It Simpler, Make It Fast

Simplicity is a Goal, Not a Starting Point

First, deliver working functionality. Then, refine for simplicity and cognitive clarity. Finally, optimize performance only after profiling identifies actual bottlenecks. Premature optimization destroys simplicity and creates unnecessary complexity.


4. Avoid Repetition Unless Repetition Makes It Simpler

DRY often leads to premature abstractions that make code harder to understand and change than simple, duplicated solutions.

Eliminate redundant code only when extraction reduces cognitive workload. Forced abstractions often increase mental complexity. Strategic duplication that preserves clarity is better than clever abstractions that confuse.


5. Automate Tests

Automated tests are non-negotiable. They build confidence, enable rapid development, and catch regressions. Manual testing alone is insufficient for reliable software delivery.


6. Separate Concerns

Divide systems into distinct modules with clear responsibilities. This separation reduces cognitive overhead when working with any single component and makes reasoning about the system manageable.


7. Design for Failure

Failure is inevitable. Design systems to handle it gracefully with circuit breakers, timeouts, retries, and fallback mechanisms. Failure-aware design prevents cascading problems and enables recovery.


8. Only Build What's Needed

Focus on current requirements. Speculative features add complexity without proven value. Build minimally viable solutions that solve real problems rather than imagined future needs.


9. Minimize Dependencies

Dependencies introduce complexity, security vulnerabilities, and maintenance overhead. Use them only when the functionality is essential and would be costly to implement safely. Choose mature, well-maintained libraries.


10. Make Interfaces Explicit

Clear contracts between components eliminate guesswork and reduce cognitive load. Explicit interfaces make systems easier to understand, test, and modify independently.


11. Minimize Mutable State

Immutable structures prevent subtle bugs and make code easier to reason about. Limit mutable state to where absolutely necessary and handle it explicitly with clear boundaries.


12. Don't Trust—Verify

Validate all inputs, outputs, and assumptions. Verification ensures system integrity and prevents failures from propagating. Build defensive systems that fail safely when assumptions are violated.


13. Document Decisions, Not Code

Code should be self-documenting through clear naming and structure. Documentation should explain why decisions were made, what alternatives were considered, and what trade-offs were accepted. Context, not functionality, is what requires documentation.


14. Use Logging Strategically

Logging is your window into production behavior. Structure logs for both human debugging and automated monitoring. Use appropriate levels (ERROR, WARN, INFO, DEBUG) to support both real-time alerting and post-incident analysis.


15. Fail Fast, Learn Faster

Detect problems immediately rather than allowing them to propagate. When failures occur, extract maximum learning value to prevent recurrence. Fast feedback loops accelerate improvement and prevent larger failures.


The Foundation: Cognitive Workload

Cognitive workload is the universal measure of software quality. It determines how much mental effort is required to understand, modify, debug, and reason about code.

Good software minimizes cognitive effort through:

  • Intuitive mental models that match expectations
  • Minimal context switching between concepts
  • Explicit behavior with no hidden surprises
  • Predictable failure modes that are easy to diagnose

Remember: You cannot judge your own code's simplicity. Cognitive workload must be measured by those who will work with your code, not by you as its author.


Implementation

These principles work together to create software that is reliable, maintainable, and comprehensible. They prioritize human cognitive limitations over technical cleverness, recognizing that software is ultimately built and maintained by people.

Apply these principles consistently, measure their effectiveness through peer feedback, and adapt them to your team's context while maintaining their core focus on reducing cognitive complexity.

The goal: Software that works reliably and can be understood, modified, and debugged by anyone on the team with minimal mental effort.

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment