White Label Coders  /  Blog  /  Best Practices in Programming Based on SOLID, KISS and Personal Experience

Category: Software Engineering

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

solid and kiss in programming
17.01.2019
5 min read

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.

Empirical evidence shows there is no situation in which cluttered code won’t cause problems when it’s further extended.  This is exactly why Robert Martin (a.k.a. Uncle Bob) created a set of rules for writing good code, which allow us to create simple, easily modified software. As a compliment to this approach, the term KISS, coined by Kelly Johnson, is applied as a basic principle.

What is KISS?

KISS is a term created in the 1960’s which was meant to reflect the approach of creating simple durable aircrafts 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, rather to suggest

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.
  1. Writing only enough code to pass a unit test, which relates to TDD and the first SOLID principle – Single Responsibility.
  2. 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

Robert Martin, as previously mentioned, is responsible for establishing the 5 rules of SOLID:

  • Single responsibility
  • Open / Close
  • Liskov substitution
  • Interface segregation
  • Dependency inversion

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:

An example of breaking this rule can be seen in the code below

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 liability principle is as follows:

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

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

Open / closed, i.e. open to extension, closed for modification.
According to this principle, each method should be written in such a way that it can be easily expanded upon or overwritten, yet impossible to be directly modified.

What this means in practice is presented in the following examples

Let’s start with the rule broken below:

Let’s start with the rule broken below:

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:

So how should the calculation of the area of a shape be implemented correctly?

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 fully met the first principle of SOLID.

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 the interface, the abstract class and all methods of the derived class must remain 100% 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:

Typically, I present the incorrect variant first:

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:

 It implements the logic of the tool which is most important for a programmer - the coffee machine

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:

An example of breaking this rule is as follows:

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 executed. 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: Printable PdfInterface and Printable ExcelInterface.

The last principle SOLID provides is Dependency inversion. It says that all dependencies should depend as much as possible on abstraction, not on a particular type. It sounds complicated, but it really is a very simple principle for declaring functionalities in a way that operates on the most common types of data.  This essentially makes the code universal.

The following examples illustrate this well.
Breaking the rule:

Breaking the rule:

Application of the rule:

Application of the rule:

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 practicies for programming.

Programmers should adapt this tool to the individual needs of the application. Intuitively, in a small project, we will not apply the last three principles, 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.

Good luck!

Chadynka-WLC

Upper-mid PHP Developer / Frontend & Backend

Professional in full-stack web development. His experience covers building websites, online shops, APIs and maintaining them. Driven by solution design and user’s satisfaction, supported by solid interpersonal and management skills make a robust, all-round developer who can take on the impossible. Strongly focused on quality and best practices, fan of SOLID and KISS approach, experienced with automated testing.

Related Articles
SEE OUR BLOG
Check related articles
alter table
"Alter table" Applied to a Large Table

Do you have a large table and want to alter it? Only for InnoDB? It can be done!

Read more
Teamwork
Code Reviews - Putting the “Team” in Teamwork

The quality of the code defines the final effect of the completed project for the client. Regardless of the complexity of the project, software development can be divided into specific pieces of functionality, which ultimately make up the whole - business effect recommended by the client: online store, website, order management platform, game creation system, application ...

Read more
automating testing
Automatic Testing

Creating automated tests is a very important element of the software development process. This approach to creating tests utilizes TDD and BDD methodologies

Read more
Testing before Deployment
Testing of a website, our best practicies for testing before deployment

Testing a website or an app before it’s launch is like a rehearsal before the show. This is like the last wardrobe fitting before the gala.

Read more
VERSA WP Versatile WordPress Starter Template
Open-source, versatile WordPress Starter Template – Versa WP

Choosing a starter theme for a WordPress-based website is the most important decision that affects every stage of the project implementation. A starter theme should be like a well-tailored suit..

Read more
delighted programmer with glasses using computer
Let’s talk about your WordPress project!

Do you have an exciting strategic project coming up that you would like to talk about?

wp
woo
php
node
nest
js
angular-2