Software Design Principles DRY, KISS, YAGNI

I’ll give you a quick summary of some software development principles and software design related terms with a brief description.

What is good software?

Good software must meet the following conditions:

  • Operational
  • Transitional
  • Maintenance

Why Software Design Principles

To handle the frequent change in user requirements, we need the software design principles. These principles reduce dependencies so that developers can change one area of software without affecting others. They are also intended to make designs easier to understand, maintain, and extend.

SOLID Principles

This is an abbreviation for five Object-Oriented design principles.

  1. Single Responsibility Principle.
  2. Open/Closed principle.
  3. Liskov Substitution principle.
  4. Interface Segregation Principle.
  5. Dependency Inversion principle.

Tight Coupling

Tight coupling (in general) occurs when two things rely on one another, i.e., changing one may have an effect on the other.

Loose Coupling

Loose coupling occurs when two things are dependent on one another, implying that changing one may have little or no effect on the other. The goal of a loose coupling architecture is to reduce the risk that a change made in one element will cause unanticipated changes in other elements.

Dependency Injection

In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service).

Mock

Mock objects are simulated objects in object-oriented programming that mimic the behaviour of real objects in controlled ways, most often as part of a software testing initiative. A mock object is typically created by a programmer to test the behaviour of another object.

Spy

Mock and Spy are both used to fake or mimic the behaviour of an object, but in spy, there is a real object and you are simply spying or stubbing specific methods of it.

DRY(Don’t Repeat Yourself)

Don’t Repeat Yourself is an abbreviation. It entails refactoring code that is reused several times. DRY code is simple to modify since all changes must be made in one place.

Have a glance at the following code fragment. I’m checking for the even or odd number in the specified array. But for if(array[i] percent 2!==0), the rest of the code is duplicated. This is obviously against the DRY principle.

const printOdd=(array)=>{
  for(let i=0;i<array.length;i++){
    if(array[i]%2!==0){
      console.log(array[i]);
    }
  }
}


const printEven=(array)=>{
  for(let i=0;i<array.length;i++){
    if(array[i]%2===0){
    console.log(array[i]);
    }
  }
}


printOdd([1,2,3,4,5]);
printEven([1,2,3,4,5]);


Let’s refactor the code and apply the DRY principle.

DRY Code

const printNumbers=(array,cb)=>{
   for(let i=0;i<array.length;i++){
    if(cb(array[i])){
      console.log(array[i]);
    }
  }
}


printNumbers([1,2,3,4],(x)=>x%2!==0); // odd numbers

printNumbers([1,2,3,4],(x)=>x%2===0); // even numbers


KISS- Keep it Simple, Stupid

This principle states that your code should be as simple as possible. You should avoid overcomplicating things. A simple code is easier to understand and maintain.

Let’s look at some real-world examples to better understand this principle.

Example 1

I’m merging the two arrays into a single array in the following code snippet. This code is fine, but we can simplify it by using the new javascript operator spread.

const even = [2,4,6]
const nums = [10,12,16].concat(even); // 10,12,16,2,4,5


After applying the KISS principle

const even = [2,4,6]
const nums = [10,12,16,...even]


We could use the spread operator in any situation (beginning, end, middle)

Example 2

The example below is self-explanatory. Here, I’m checking to see if the variable is defined and then making a decision. This code is quite verbose, and we can simplify it by utilising the “short circuit” technique.

Short-**Circuit Code-**n some programming languages, the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression.

function checkName(name) {
  if (name === null || name === undefined || name === "") {
    console.log("name not defined!");
  } else {
    console.log(name);
  }
}
checkName();


The code above is fairly common, so let’s put it to good use.

function checkName(name) {
  console.log(name || "name not defined!");
}
checkName();


Example 3

Consider the following scenario. In the code below, I’m making an ajax request and using a “Promise”-based API. Things can get nasty when we use multiple nested promises.

const getData = (url) => {
  return $.getJSON(url)
    .then((data) => {
      console.log(data);
    })
    .catch((err) => {
      console.log(err);

    });
};

getData("https://jsonplaceholder.typicode.com/todos/1");


This promise-based code will be transformed into an async/await code block as shown below. Which is very clear and simple to understand.

const getData = async (url) => {
  try {
    const data = await $.getJSON(url);
    console.log(data);
  } catch (err) {
    console.log(err);
  }
};
getData("https://jsonplaceholder.typicode.com/todos/1");


YAGNI

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

You may like

Please do not post any spam link in the comment box😊

Post a Comment (0)
Previous Post Next Post