Best Practices in Programming Based on SOLID, KISS and Personal Experience

10 minutes
Best Practices in Programming Based on SOLID, KISS and Personal Experience

The guidelines a programmer should follow on a day to day basis are just as important as they are in any field. Applying these principles may initially seem tedious and time-consuming, but over time, the advantages won’t go unnoticed. Shortcuts, which may save time, can also lead to a variety of problems in the later stages of a project.

Experience shows that cluttered code causes problems as soon as it is extended. This is exactly why Robert Martin (a.k.a. Uncle Bob) collected a set of rules for writing good code, which allow us to create simple, easily modified software. As a complement to this approach, the term KISS, coined by Kelly Johnson, is applied as a basic principle.

In short: KISS (“keep it simple, stupid”) means choosing the simplest design that solves the problem. SOLID is a set of five object-oriented design principles: Single responsibility, Open/closed, Liskov substitution, Interface segregation, and Dependency inversion. Together they keep code easy to read, extend, and test.

What is KISS?

KISS is a term created in the 1960s which was meant to reflect the approach of creating simple, durable aircraft that could be repaired easily in an emergency. This idea has since been adopted by many branches of science and engineering.

KISS is a term also used in developing solutions to programming problems. Literally translated, KISS means “keep it simple, stupid” or “keep it stupid simple”. However, it’s assumed the statement was not supposed to sound negative, but rather to suggest that a simple design makes service and maintenance child’s play.

The use of KISS in programming can be considered in three aspects:

  1. Simplification for current and future cooperative development of your code. From my perspective, this is nothing but the skillful application of SOLID principles.
  2. Writing only enough code to pass a unit test, which relates to TDD and the first SOLID principle, Single Responsibility.
  3. Intuitive approaches to writing software, approachable and simply understood by everyone.

KISS programming alone sets no hard and fast rules regarding the implementation of code, as is the case with most SOLID principles, which are general guidelines for how to create SOLID code.

Let’s take a look at what makes something SOLID

The 5 principles of SOLID were collected and popularised by Robert Martin, as previously mentioned. The acronym itself comes from Michael Feathers, and individual principles build on earlier work, such as Bertrand Meyer’s open/closed principle and Barbara Liskov’s substitution principle.

  • Single responsibility
  • Open / Closed
  • Liskov substitution
  • Interface segregation
  • Dependency inversion
PrincipleIn one sentenceTypical sign of a violation
Single responsibilityA class or method has one reason to changeA class that validates data, stores it, and sends e-mails
Open / ClosedAdd new behaviour by extension, not by editing tested codeEvery new case means another if in an existing method
Liskov substitutionA derived class can replace its base class without breaking behaviourA subclass that throws “not supported” for an inherited method
Interface segregationMany small, client-specific interfaces beat one large oneClasses forced to implement methods they never use
Dependency inversionDepend on abstractions, not on concrete implementationsClasses that create their own dependencies with new

Single responsibility pretty much speaks for itself. Each class or method should be responsible for one separate functionality. An example of breaking this rule can be seen in the code below:

Code example of a Person class that also validates e-mail addresses and postal codes and adds products to a shopping cart, breaking the Single Responsibility principle

In the example above, the rule is being broken by the fact that the Person class “exceeds its competences”. Its only responsibility should be to represent the person’s object and its properties, such as: name, age, address (preferably also as a separate object).

It is definitely not supposed to validate an e-mail address, postal code or add a product to the shopping cart.

Repairing the errors listed above and adapting the code to the single responsibility principle is as follows:

Code refactored to follow the Single Responsibility principle

Applying the KISS principle is closely related to the TDD approach. In order for a correct unit test to occur, one singular responsibility should be envisioned for it.

Open / closed, i.e. open to extension, closed for modification. According to this principle, a class or method should be written in such a way that new behaviour can be added by extending it, without changing the code that already works and is tested.

What this means in practice is presented in the following examples

Let’s start with the rule broken below:

Code example of a Calculator class whose area method has to be modified to support new shapes, breaking the Open/Closed principle

Why is the code above breaking the Open / Closed approach? Because adding code to calculate an area, of e.g. a triangle, would require the direct modification of the area method from the Calculator class.

So how should the calculation of the area of a shape be implemented correctly? An example is shown below:

Code example with a Shape base class and a separate subclass per shape that defines its own area calculation, following the Open/Closed principle

As you can see, to add a shape with the possibility of calculating its area, just create another class that inherits from the Shape class and define the calculation of the area method inside of it.

These first two rules are simple to use in any functionality, even small ones. Applying them, we can write code that will be easy to read and able to be interpreted by other programmers, as well as simple to extend.

At this stage, we’ve applied the first two principles of SOLID: Single responsibility and Open / closed.

The next three rules are used in more complex solutions, or in other words, in extensive logic.

The third rule is Liskov substitution, which states that objects of a derived class must be usable wherever the base class or interface is expected, without breaking the behaviour of the program. In other words, the interface, the abstract class and all methods of the derived class must remain compatible.

What does this mean in practice? Accordingly, with the principles previously described here, this will be presented in two examples: broken and applied.

Typically, I present the incorrect variant first:

Code example of an Animal interface with Dog and Fish classes, where Fish is forced to implement a run method, breaking Liskov substitution

At first glance, everything is fine, there is the Animal class representing the animal and the inheriting Dog and Fish. So what is the problem? In the method enforced by the interface, the dog runs and it makes sense, but nobody has ever heard of a running fish.

This rule therefore is more of a reference to pure logic. The next example shows the correct application of it. It implements the logic of the tool which is most important for a programmer: the coffee machine:

Code example of a coffee machine that follows Liskov substitution: every machine type brews coffee

Coffee is always brewed in the coffee machine, regardless of its type.

The next principle is Interface segregation.

A very good description of it is the following sentence: “many client-specific interfaces are better than one general-purpose interface”.

In practice, this means that the interfaces created should be dedicated to only one functionality.

An example of breaking this rule is as follows:

Code example of a report printing interface with PDF and Excel methods, breaking Interface segregation

In the example above, the print logic of various reports has been implemented. An interface was created with two methods declared: to print PDF and Excel spreadsheets. However, for the results of the school exam, you do not need an Excel spreadsheet.

In this case, this method is redundant, but since it’s forced by the interface, it must be implemented. According to the principle of Interface segregation, a better solution is the declaration of several specialized interfaces.

To rectify the problem, we could create two separate interfaces: PrintablePdfInterface and PrintableExcelInterface.

The last principle SOLID provides is Dependency inversion. It says that high-level modules should not depend on low-level modules, and both should depend on abstractions rather than on concrete types. It sounds complicated, but it is a simple way to declare functionality so that it works with any implementation of an interface. This makes the code easier to test and to change.

The following examples illustrate this well. Breaking the rule:

Code example breaking the Dependency inversion principle

Application of the rule:

Code example applying the Dependency inversion principle

The above principles should be treated as a set of tools for writing good, sound code. However, it is not necessary to apply all these elements in every project. We have tried to include best practices for programming.

Programmers should adapt this tool to the individual needs of the application. Intuitively, in a small project we may not need the last three principles in a formal way, although Liskov substitution applies whenever you use inheritance, but the first two are definitely worth sticking to, even when building smaller functionalities.

From my own experience, I know that code written with best practices from the beginning is much easier to develop.

How do SOLID and KISS apply to WordPress and WooCommerce development?

The same ideas work in WordPress code. Actions and filters let you extend behaviour without editing WordPress core or a plugin’s files, which is the open/closed principle in practice, and child themes follow the same logic. Keeping each plugin class focused on one job, and depending on interfaces rather than concrete classes, makes custom code easier to test and to hand over to another team. For examples, see how to develop a custom theme in WordPress and what WooCommerce endpoints are.

We see the opposite pattern in stores that have changed hands: cluttered code that nobody dares to touch. A technical audit shows how deep the problem goes, and a rescue mission stabilises the code before any rebuild. For new work, see our WordPress development and WooCommerce development.

Key takeaways

  • Keep it simple: choose the simplest design that solves the problem (KISS)
  • Give each class or method one responsibility
  • Extend behaviour by adding code, not by changing tested code
  • Make sure derived classes can replace their base classes without surprises
  • Prefer small, specific interfaces and depend on abstractions

Frequently asked questions about SOLID and KISS

What does SOLID stand for?

SOLID stands for Single responsibility, Open/closed, Liskov substitution, Interface segregation, and Dependency inversion. They are five object-oriented design principles that make code easier to read, extend, and test.

What does KISS mean in programming?

KISS means “keep it simple, stupid”. It tells developers to choose the simplest design that solves the problem, so the code is easier to understand, maintain, and repair later.

What is the difference between KISS and SOLID?

KISS is a general rule to avoid unnecessary complexity. SOLID is a specific set of five design principles for object-oriented code. Applying SOLID well usually supports KISS, because it keeps classes small and focused.

Who created the SOLID principles?

Robert C. Martin (Uncle Bob) collected and popularised the principles in the early 2000s. The acronym was coined by Michael Feathers, and individual principles come from earlier work, such as Bertrand Meyer’s open/closed principle and Barbara Liskov’s substitution principle.

Do I need all five SOLID principles in a small project?

Not always in a formal way. Single responsibility and open/closed pay off even in small functions. Liskov substitution matters whenever you use inheritance, and interface segregation and dependency inversion matter more as the code base grows.

How do SOLID principles apply to WordPress and WooCommerce development?

WordPress hooks let you extend behaviour without editing core or plugin files, which is the open/closed idea in practice. Keeping each plugin class focused, and depending on interfaces rather than concrete classes, makes custom code easier to test and maintain.

Pwel Zmyslowski

Paweł Zmysłowski

CEO WLC.team

At White Label Coders responsible for the sales process and sales team, still involved in the analytical and advisory roles in case of more complex projects.

Author page

Is your WordPress “working, but slow”?

MORE ARTICLES

Read also

  • Why do my comparison tables cause layout shift?
    11 minutes

    Why do my comparison tables cause layout shift?

    Comparison tables often cause layout shift because parts of them load without reserved space, so content jumps around as the page renders. This happens when images lack dimensions, dynamic data loads without placeholders, or custom fonts reflow text after the first paint. Layout shift hurts user experience and your Core Web Vitals, which feed into…

    Read

  • How do you implement multiple payment gateways in iGaming platforms?
    11 minutes

    How do you implement multiple payment gateways in iGaming platforms?

    Implementing multiple payment gateways in iGaming platforms involves integrating several payment processors to offer diverse payment options, ensure regulatory compliance, and maximise transaction success rates. This approach requires careful technical planning, strong security measures, and intelligent routing systems. The process typically involves API integrations, database management, and thorough testing to create smooth payment experiences for…

    Read

  • 1 minute

    Development of export activity on new foreign markets

    White Label Coders sp. z o.o. has received EU co-funding for the project “Development of export activity on new foreign markets”. The support, in the form of an export voucher, comes from the project “InterGlobal – internationalisation of SMEs from the Silesian Voivodeship”, implemented by Fundusz Górnośląski S.A. under the European Funds for Silesia 2021–2027…

    Read