Master Essential Programming Principles: KISS, YAGNI, SOLID and More
This article compiles core programming principles such as KISS, YAGNI, Separation of Concerns, DRY, Inversion of Control and the SOLID rules, explaining why each matters, how to apply them, and providing reference links for deeper study.
Every programmer can benefit from understanding programming principles and patterns. This overview, originally translated from the "Programming Principles" site, lists key guidelines and offers brief explanations, reasons, practical steps, and further reading.
KISS
Most systems work best when they stay simple rather than complex.
Why
Less code means less time to write, fewer bugs, and easier modifications.
Simplicity is the highest form of sophistication.
Perfection is achieved by eliminating unnecessary complexity.
Related resources:
KISS principle – https://en.wikipedia.org/wiki/KISS_principle
Keep It Simple Stupid – http://principles-wiki.net/principles:keep_it_simple_stupid
YAGNI
"You Aren't Gonna Need It": do not implement features before they are actually required.
Why
Working on future‑only features diverts effort from current goals.
It inflates code, making software larger and more complex.
How
Implement features only when you truly need them, not when you anticipate a need.
Related resources:
You Aren't Gonna Need It – http://c2.com/xp/YouArentGonnaNeedIt.html
You’re NOT gonna need it! – http://www.xprogramming.com/Practices/PracNotNeed.html
You ain’t gonna need it – http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it
Do the Simplest Thing
Ask yourself: "What is the simplest thing that could possibly work?"
Related resource:
Do The Simplest Thing That Could Possibly Work – http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html
Separation of Concerns
Divide a program into distinct parts, each focusing on a single concern (e.g., business logic vs. UI). Changes to one part should not require changes to the other.
Quote from Edsger W. Dijkstra (1974): "I sometimes call it ‘separation of concerns’, even though it cannot be achieved perfectly, it is the only effective mental‑organising technique I know. It means focusing on one aspect while ignoring others, not that the ignored aspects are unimportant."
Why
Simplifies development and maintenance.
Well‑separated concerns enable reuse and independent evolution.
How
Split functionality into as few modules as possible, each with a clear responsibility.
Related resource:
Separation of Concerns – https://en.wikipedia.org/wiki/Separation_of_concerns
Don’t Repeat Yourself (DRY)
Each piece of knowledge should have a single, authoritative representation within a system.
Why:
Duplication leads to maintenance nightmares, inconsistencies, and logical contradictions.
Modifying one element should not require changes to unrelated parts.
Related logic changes become predictable and uniform.
How:
Write business rules, long expressions, if‑statements, formulas, metadata, etc., in only one place.
Identify the single source of truth for each concept and generate all required artifacts from it.
Apply the Rule of Three – http://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)
Related resources:
Don’t Repeat Yourself – http://c2.com/cgi/wiki?DontRepeatYourself
DRY Wikipedia – http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
DRY O'Reilly – http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Repeat_Yourself
Write Code for the Maintainer
Maintenance is the most expensive phase of any project.
How:
Think of the future maintainer as a person who knows where they live and is a bit crazy – write code that is pleasant to read.
Make the code and comments enjoyable for newcomers.
Don’t Make Me Think – http://www.sensible.com/dmmt.html
Principle of Least Astonishment – http://en.wikipedia.org/wiki/Principle_of_least_astonishment
Related resources:
Code For The Maintainer – http://c2.com/cgi/wiki?CodeForTheMaintainer
The Noble Art of Maintenance Programming – http://blog.codinghorror.com/the-noble-art-of-maintenance-programming/
Avoid Premature Optimization
Programmers waste time optimizing non‑critical parts, which harms debugging and maintenance. As Donald Knuth said, 97% of development time should ignore low‑efficiency; only the critical 3% deserves optimization.
Why:
The bottleneck is unknown.
Optimizing early can make code harder to read and maintain.
How:
Make it work, make it right, then make it fast – http://c2.com/cgi/wiki?MakeItWorkMakeItRightMakeItFast
Only optimize after identifying a real bottleneck.
Related resources:
Program optimization – http://en.wikipedia.org/wiki/Program_optimization
Premature Optimization – http://c2.com/cgi/wiki?PrematureOptimization
Minimize Coupling
Coupling measures how much modules depend on each other; lower coupling is better.
Why:
Changes in one module can ripple to others.
Higher dependency increases assembly effort.
Highly coupled modules are harder to reuse and test.
Developers may fear changes due to unknown impact.
How:
Eliminate, minimize, and reduce unnecessary connections.
Hide implementation details to lower coupling.
Apply the Law of Demeter – https://mouse0w0.github.io/2018/10/04/Programming-Principles/#%E8%BF%AA%E7%B1%B3%E6%B3%95
Related resources:
Coupling – http://en.wikipedia.org/wiki/Coupling_(computer_programming)
Coupling and Cohesion – http://c2.com/cgi/wiki?CouplingAndCohesion
Law of Demeter
"Talk only to your immediate friends." Avoid talking to strangers.
Why:
Prevents tight coupling.
Reduces exposure of implementation details.
How:
Only call methods of the object itself.
Only call methods of objects passed as parameters.
Only call methods of objects created within the method.
Only call methods of the object's direct fields.
Related resources:
Law of Demeter – http://en.wikipedia.org/wiki/Law_of_Demeter
Law of Demeter is not a dot‑counting exercise – http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/
Composition Over Inheritance
Why:
Reduces coupling between classes.
Inheritance can break the Liskov Substitution Principle.
How:
Test LSP to decide when inheritance is appropriate.
Use composition when a "has" relationship exists; use inheritance for an "is" relationship.
Related resource:
Favor Composition Over Inheritance – http://blogs.msdn.com/b/thalesc/archive/2012/09/05/favor-composition-over-inheritance.aspx
Orthogonality
The basic idea of orthogonality is that unrelated concepts should not be related in a system.
Source: Be Orthogonal – http://www.artima.com/intv/dry3.html
The simpler the design, the fewer exceptions, making learning and reading code easier. Orthogonal features are independent of environment; key parameters are symmetry and consistency.
Source: Orthogonality
Robustness Principle
Be conservative in what you do, be liberal in what you accept from others.
Cooperating services depend on each other's interfaces. Providers should evolve without breaking existing clients.
Why:
To evolve a service, ensure changes support new needs while minimizing impact on existing clients.
How:
Code that sends commands or data must strictly follow the specification, while code that receives should tolerate reasonable deviations.
Related resources:
Robustness Principle – https://en.wikipedia.org/wiki/Robustness_principle
Tolerant Reader – http://martinfowler.com/bliki/TolerantReader.html
Inversion of Control
Also known as the Hollywood Principle: "Don’t call us, we’ll call you." Custom code receives control flow from a generic framework, improving modularity and extensibility.
Why:
Increases module modularity and scalability.
Separates task execution from implementation.
Focuses modules on their design responsibilities.
Prevents modules from being constrained by assumptions about other systems.
Avoids side effects when swapping modules.
How:
Use the Factory pattern.
Use the Service Locator pattern.
Use Dependency Injection.
Use Dependency Lookup.
Use the Template Method pattern.
Use the Strategy pattern.
Related resources:
Inversion of Control – https://en.wikipedia.org/wiki/Inversion_of_control
IoC Containers and Dependency Injection – https://www.martinfowler.com/articles/injection.html
Maximize Cohesion
A module’s cohesion is the degree to which its responsibilities form a meaningful unit; higher cohesion is better.
Why:
Low cohesion makes understanding a module harder.
Changes in one part affect many others, increasing maintenance difficulty.
Unnecessary functionality hampers reuse.
How:
Group related functionality within a single class or component.
Related resources:
Cohesion – (general concept)
Coupling and Cohesion – http://c2.com/cgi/wiki?CouplingAndCohesion
Liskov Substitution Principle
Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
Related resources:
Liskov Substitution Principle – http://en.wikipedia.org/wiki/Liskov_substitution_principle
LSP – http://www.blackwasp.co.uk/lsp.aspx
Open/Closed Principle
Software entities (e.g., classes) should be open for extension but closed for modification, allowing behavior changes without altering source code.
Why:
Improves maintainability and stability by minimizing changes to existing code.
How:
Write classes that can be extended rather than modified.
Expose only the parts that need to change; hide everything else.
Related resources:
Open Closed Principle – http://en.wikipedia.org/wiki/Open/closed_principle
The Open Closed Principle – https://8thlight.com/blog/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html
Single Responsibility Principle
A class should have only one reason to change.
Why:
Improves maintainability: only one module or class needs modification.
How:
Apply Curly’s Law (Do One Thing) – https://mouse0w0.github.io/2018/10/04/Programming-Principles/#%E7%A7%91%E9%87%8C%E5%AE%9A%E5%BE%8B
Related resource:
Single Responsibility Principle – http://en.wikipedia.org/wiki/Single_responsibility_principle
Information Hiding
Software modules expose interfaces while concealing implementation details.
Why:
Clients can remain unchanged when implementations evolve.
How:
Minimize the accessibility of classes and members.
Do not expose member data publicly.
Avoid leaking private implementation details into the class interface.
Reduce coupling to hide more implementation details.
Related resource:
Information Hiding – http://en.wikipedia.org/wiki/Information_hiding
Curly's Law (Rule of One)
Do one thing: each piece of code should have a single, well‑defined purpose.
Related resources:
Curly’s Law – http://blog.codinghorror.com/curlys-law-do-one-thing/
The Rule of One – http://fortyplustwo.com/2008/09/06/the-rule-of-one-or-curlys-law/
Encapsulate Varying Concepts
Identify concepts that are likely to change and encapsulate them behind stable interfaces.
Why:
Minimizes the amount of code that must be altered when a change occurs.
How:
Encapsulate varying concepts behind APIs.
Separate different concepts into their own modules.
Related resources:
Encapsulate the Concept that Varies – http://principles-wiki.net/principles:encapsulate_the_concept_that_varies
Encapsulate What Varies – http://blogs.msdn.com/b/steverowe/archive/2007/12/26/encapsulate-what-varies.aspx
Information Hiding – https://en.wikipedia.org/wiki/Information_hiding
Interface Segregation Principle
Reduce bulky interfaces into multiple smaller, client‑specific ones; interfaces should depend more on callers than on implementations.
Why:
If a class implements unnecessary methods, callers must understand those methods, even if they simply throw exceptions.
How:
Avoid fat interfaces; classes should not implement methods that violate the Single Responsibility Principle.
Related resource:
Interface Segregation Principle – https://en.wikipedia.org/wiki/Interface_segregation_principle
Boy Scout Rule
Leave the code cleaner than you found it, just like a Boy Scout leaves a campsite cleaner.
Why:
Each commit should not increase technical debt; small improvements prevent debt accumulation.
How:
Ensure every commit maintains or improves code quality.
Whenever you see unclear code, fix it immediately.
Related resource:
Opportunistic Refactoring – http://martinfowler.com/bliki/OpportunisticRefactoring.html
Command‑Query Separation
Methods should either perform an action (command) or return data (query), but not both. Queries must not change the answer.
Why:
Separating commands and queries lets programmers use queries confidently without side effects.
How:
Implement each method as either a query or a command.
Use naming conventions to indicate the method type.
Related resources:
Command Query Separation – https://en.wikipedia.org/wiki/Command–query_separation
Command Query Separation by Martin Fowler – http://martinfowler.com/bliki/CommandQuerySeparation.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
