Programming Principles

Here’s the list of Programming Principles which every software developer should know to be able to efficiently design a good application.

KISS

KISS, Acronym for Keep it Simple, Stupid – states that Most systems work best if they are kept simple rather than made complex.

Why

  • Less code takes less time to write, has less bugs, and is easier to modify.
  • Simplicity is the ultimate sophistication.
  • It seems that perfection is reached not when there is nothing left to add, but when there is nothing left to take away.

YAGNI

YAGNI stands for “you aren’t gonna need it“: don’t implement something until it is necessary.

Why

  • Any work that’s only used for a feature that’s needed tomorrow, means losing effort from features that need to be done for the current iteration.
  • It leads to code bloat; the software becomes larger and more complicated.

How

  • Always implement things when you actually need them, never when you just foresee that you need them.

DRY

DRY stands for Don’t Repeat Yourself. Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts.

Why

  • Duplication (inadvertent or purposeful duplication) can lead to maintenance nightmares, poor factoring, and logical contradictions.
  • A modification of any single element of a system does not require a change in other logically unrelated elements.
  • Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.

How

  • Put business rules, long expressions, if statements, math formulas, metadata, etc. in only one place.
  • Identify the single, definitive source of every piece of knowledge used in your system, and then use that source to generate applicable instances of that knowledge (code, documentation, tests, etc).
  • Apply the Rule of three.

CQRS

The Command Query Separation principle states that each method should be either a command that performs an action or a query that returns data to the caller but not both. Asking a question should not modify the answer.

With this principle applied the programmer can code with much more confidence. The query methods can be used anywhere and in any order since they do not mutate the state. With commands one has to be more careful.

Why

  • By clearly separating methods into queries and commands the programmer can code with additional confidence without knowing each method’s implementation details.

How

  • Implement each method as either a query or a command
  • Apply naming convention to method names that implies whether the method is a query or a command

Composition Over Inheritance

Why

  • Less coupling between classes.
  • Using inheritance, subclasses easily make assumptions, and break LSP.

How

  • Test for LSP (substitutability) to decide when to inherit.
  • Compose when there is a “has a” (or “uses a”) relationship, inherit when “is a”.

Encapsulate that changes

A good design identifies the hotspots that are most likely to change and encapsulates them behind an API. When an anticipated change then occurs, the modifications are kept local.

Why

  • To minimize required modifications when a change occurs

How

  • Encapsulate the concept that varies behind an API
  • Possibly separate the varying concept into its own module

Hide Implementation Details

A software module hides information (i.e. implementation details) by providing an interface, and not leak any unnecessary information.

Why

  • When the implementation changes, the interface clients are using does not have to change.

How

  • Minimize accessibility of classes and members.
  • Don’t expose member data in public.
  • Avoid putting private implementation details into a class’s interface.
  • Decrease coupling to hide more implementation details.

Minimize Coupling

Coupling between modules/components is their degree of mutual interdependence; lower coupling is better. In other words, coupling is the probability that code unit “B” will “break” after an unknown change to code unit “A”.

Why

  • A change in one module usually forces a ripple effect of changes in other modules.
  • Assembly of modules might require more effort and/or time due to the increased inter-module dependency.
  • A particular module might be harder to reuse and/or test because dependent modules must be included.
  • Developers might be afraid to change code because they aren’t sure what might be affected.

How

  • Eliminate, minimise, and reduce complexity of necessary relationships.
  • By hiding implementation details, coupling is reduced.
  • Apply the Law of Demeter.

Maximize Cohesion

Cohesion of a single module/component is the degree to which its responsibilities form a meaningful unit; higher cohesion is better.

Why

  • Increased difficulty in understanding modules.
  • Increased difficulty in maintaining a system, because logical changes in the domain affect multiple modules, and because changes in one module require changes in related modules.
  • Increased difficulty in reusing a module because most applications won’t need the random set of operations provided by a module.

How

  • Group related functionalities sharing a single responsibility (e.g. in a class).

Robustness Principle

Be conservative in what you do, be liberal in what you accept from others

Collaborating services depend on each others interfaces. Often the interfaces need to evolve causing the other end to receive unspecified data. A naive implementation refuses to collaborate if the received data does not strictly follow the specification. A more sophisticated implementation will still work ignoring the data it does not recognize.

Why

  • In order to be able to evolve services you need to ensure that a provider can make changes to support new demands while causing minimal breakage to their existing clients.

How

  • Code that sends commands or data to other machines (or to other programs on the same machine) should conform completely to the specifications, but code that receives input should accept non-conformant input as long as the meaning is clear.

Inversion of Control

Inversion of Control is also known as the Hollywood Principle, “Don’t call us, we’ll call you“. It is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. Inversion of control carries the strong connotation that the reusable code and the problem-specific code are developed independently even though they operate together in an application.

Why

  • Inversion of control is used to increase modularity of the program and make it extensible.
  • To decouple the execution of a task from implementation.
  • To focus a module on the task it is designed for.
  • To free modules from assumptions about how other systems do what they do and instead rely on contracts.
  • To prevent side effects when replacing a module.

How

  • Using Factory pattern
  • Using Service Locator pattern
  • Using Dependency Injection
  • Using contextualized lookup
  • Using Template Method pattern
  • Using Strategy pattern

Curly’s Law

Curly's Law is a concept in software engineering that states "Do one thing and do it well." It means that software components should have a single, well-defined responsibility or function, and that they should not try to do too much or be overly complex.

This law was named after Douglas McIlroy, a computer scientist who coined the term “Unix philosophy,” which emphasizes simplicity, composability, and modularity in software design.

Code For The Maintainer

Why

  • Maintenance is by far the most expensive phase of any project.

How

  • Be the maintainer.
  • Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.
  • Always code and comment in such a way that if someone a few notches junior picks up the code, they will take pleasure in reading and learning from it.
  • Use the Principle of Least Astonishment.

Law of Demeter

Don’t talk to strangers.

Why

  • It usually tightens coupling
  • It might reveal too much implementation details

How

A method of an object may only call methods of:

  1. The object itself.
  2. An argument of the method.
  3. Any object created within the method.
  4. Any direct properties/fields of the object.

Brooks’s Law

Brooks’s Law is a concept in software engineering that states “adding manpower to a late software project makes it later.” It means that adding more developers to a project that is already behind schedule will actually cause the project to take even longer to complete.

This law was named after Fred Brooks, a software engineer and author of the book “The Mythical Man-Month,” which explores the challenges of managing large software projects.

The new developers need time to get up to speed on the project, which involves learning about the existing codebase, the project requirements, and the development process. In addition, communication and coordination between team members becomes more challenging as the team grows larger, which can cause additional delays and misunderstandings.

Linus’ Law

This law was named after Linus Torvalds, the creator of the Linux operating system, who famously said, “Given enough eyeballs, all bugs are shallow.

Linus’ Law is a concept in software engineering which states that if enough people are looking at a piece of code, then any bugs or issues in that code will be quickly identified and resolved.

Boy-Scout Rule

The Boy-Scout Rule is a concept in software development that states “Always leave the code cleaner than you found it.” It means that when you modify existing code, you should take the opportunity to improve its quality, clarity, and maintainability, rather than just making the minimum necessary changes.

This rule was named after the Boy Scouts, who are taught to leave campsites in better condition than they found them, by cleaning up litter, repairing any damage, and leaving the site in a better state for the next visitors.

By applying the Boy-Scout Rule, we would take the time to make these improvements, even though they’re not strictly necessary to achieve the desired functionality. By doing so, we leave the code in better condition than we found it, making it easier to understand, maintain, and extend in the future

Murphy’s Law

Murphy’s Law is a common saying in engineering and other fields that states “Anything that can go wrong, will go wrong.” It is a reminder to always be prepared for the unexpected and to anticipate possible problems or failures.

Even if everything seems to be working correctly, there’s always the possibility that something unexpected could happen. To prepare for this, it’s important to add error checking and handling to our code, so that we can catch and address any issues that arise.

SOLID Principles

Single Responsibility Principle(SRP)

A class should never have more than one reason to change.

Long version: Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Responsibility can be defined as a reason to change, so a class or module should have one, and only one, reason to change.

Why

  • Maintainability: changes should be necessary only in one module or class.

How

  • Apply Curly’s Law.

Open-Closed Principle(OCP)

Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. In other words, you should be able to add new functionality without modifying existing code.

Liskov Substitution Principle (LSP)

Subtypes must be substitutable for their base types. In other words, if you have a base class and a subclass, you should be able to use the subclass wherever you can use the base class, without introducing any bugs or unexpected behaviour.

Interface Segregation Principle (ISP)

Clients should not be forced to depend on interfaces they do not use. In other words, a class should not be required to implement methods it does not need.

Reduce fat interfaces into multiple smaller and more specific client specific interfaces. An interface should be more dependent on the code that calls it than the code that implements it.

Why

  • If a class implements methods that are not needed the caller needs to know about the method implementation of that class. For example if a class implements a method but simply throws then the caller will need to know that this method shouldn’t actually be called.

How

  • Avoid fat interfaces. Classes should never have to implement methods that violate the Single Responsibility Principle.

Dependency Inversion Principle (DIP)

High-level modules should not depend on low-level modules. Both should depend on abstractions. In other words, you should depend on abstractions, not on concrete implementations.

Wiki: https://en.wikipedia.org/wiki/Category:Programming_principles

Comments

Leave a Reply