JavaScript – S.O.L.I.D – The Five Principles of Object Oriented Design – Part 2

In this article, we will learn about the Javascript 5 SOLID Principles. We will discuss about the second SOLID principle Open Closed Principle” . This is Part 2 for Javascript Object oriented design SOLID principles.
solid.png

So Let’s begin.

2. Open-Closed Principle


“Objects or entities should be open for extension, but closed for modification.”

“Open for extension means that we should be able to add new features or components to the application without breaking existing code.

Closed for modification means that we should not introduce breaking changes to existing functionality, because that would force you to refactor a lot of existing code — Eric Elliott”

In simpler words, means that a class or factory function in our case, should be easily extendable without modifying the class or function itself. Let’s look at the areaCalculator factory function, especially it’s sum method.

sum () {
 
 const area = []
 
 for (shape of this.shapes) {
  
  if (shape.type === 'Square') {
     area.push(Math.pow(shape.length, 2)
   } else if (shape.type === 'Circle') {
     area.push(Math.PI * Math.pow(shape.length, 2)
   }
 }
 return area.reduce((v, c) => c += v, 0)
}

If we wanted the sum method to be able to sum the areas of more shapes, we would have to add more if/else blocks and that goes against the open-closed principle.

A way we can make this sum method better is to remove the logic to calculate the area of each shape out of the sum method and attach it to the shape’s factory functions.

const square = (length) => {
  const proto = {
    type: 'Square',
    area () {
      return Math.pow(this.length, 2)
    }
  }
  return Object.assign(Object.create(proto), {length})
}

The same thing should be done for the circle factory function, an area method should be added. Now, to calculate the sum of any shape provided should be as simple as:

sum() {
 const area = []
 for (shape of this.shapes) {
   area.push(shape.area())
 }
 return area.reduce((v, c) => c += v, 0)
}

Now we can create another shape class and pass it in when calculating the sum without breaking our code. However, now another problem arises, how do we know that the object passed into the areaCalculator is actually a shape or if the shape has a method named area ?

Coding to an interface is an integral part of S.O.L.I.D., a quick example is we create an interface, that every shape implements.

Since JavaScript doesn’t have interfaces, So how can we achieved this, in the lack of interfaces ?

Function Composition to the rescue !


First we create shapeInterface factory function, as we are talking about interfaces, our shapeInterface will be as abstracted as an interface, using function composition.

const shapeInterface = (state) => ({
  type: 'shapeInterface',
  area: () => state.area(state)
})


Then we implement it to our square factory function.

const square = (length) => {
  const proto = {
    length,
    type : 'Square',
    area : (args) => Math.pow(args.length, 2)
  }
  const basics = shapeInterface(proto)
  const composite = Object.assign({}, basics)
  return Object.assign(Object.create(composite), {length})
}


And the result of calling the square factory function will be the next one:

const s = square(5)
console.log('OBJ\n', s)
console.log('PROTO\n', Object.getPrototypeOf(s))
s.area()
// output
OBJ
 { length: 5 }
PROTO
 { type: 'shapeInterface', area: [Function: area] }
25


In our areaCalculator sum method we can check if the shapes provieded are actually types of shapeInterface, otherwise we throw an exception:

sum() {
  const area = []
  for (shape of this.shapes) {
    if (Object.getPrototypeOf(shape).type === 'shapeInterface') {
       area.push(shape.area())
     } else {
       throw new Error('this is not a shapeInterface object')
     }
   }
   return area.reduce((v, c) => c += v, 0)
}


and again, since JavaScript doesn’t have support for interfaces like typed languages the example above demonstrates how we can simulate it, but more than simulating interfaces, what we are doing is using closures and function composition.


Conclusion

In this article (Part-2), We have discussed about the second SOLID principle Open closed principle.

In previous article (part-1), We have also discussed  about the first SOLID principle Single responsibility principle

In next articles (Part-3), We will learn about the other SOLID principles  Liskov substitution principle, Interface segregation principle,  Dependency inversion principle.

Thanks for reading ! I hope you enjoyed and learned about Javascript Object oriented design SOLID principles concepts. Reading is one thing, but the only way to master it is to do it yourself.
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!😊😊😊

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s