Four columns of object-oriented programming

JavaScript is a multi-paradigm language and can be written following different programming paradigms. A programming paradigm is basically a set of rules that you follow when writing code to help you solve a particular problem.

In this article, we introduce four pillars that are software design principles to help you write object-oriented clean code.

The four pillars of object-oriented programming are:





Let's take a closer look at each of them.

Abstraction in object-oriented programming

Abstract means to hide implementation details within something; Sometimes a prototype, sometimes a function. So when you call a function you do not need to know exactly what it is doing.

You never have to code anything if you have to figure out what each function does in a large base code. It takes months to finish reading them.

With specific abstracting details you can create a reusable, understandable, and easily modifiable base code. Let us give you an example:

  1. function hitAPI(type){  
  2.     if (type instanceof InitialLoad) {  
  3.         // Implementation example  
  4.     } else if (type instanceof NavBar) {  
  5.         // Implementation example  
  6.     } else {  
  7.         // Implementation example  
  8.     }  
  9. }  

Can you see in this example how to implement exactly what you need for your custom use?

Every new API you need to reach requires a new block, and this has its own custom code. This is not an abstract because you have to worry about implementing any new ones you add. It is not reusable and keeping it is a nightmare.  

What about something like the code below?

  1. hitApi('', HTTPMethod.Get)  

Now you can just send a URL and which HTTP method you want to use to your function and you're done.

You do not need to worry about how the function works. This deals with it. This greatly helps to reuse the code! And it makes your code very maintainable.

This is what is called abstraction. Find items that are similar in your code and provide a generic function or object to use in different locations with different items.

Here is a good final example of Abstraction: Imagine you are creating a coffee machine for your users. There are two approaches:

How to make it with Abstraction

Have a "Make Coffee" button

How to make it without Abstraction

Have a button titled "Boil water"

Have a button titled "Add cold water to the kettle"

Have a button titled "Add a spoonful of coffee powder to a clean cup"

Have a button titled "Clean every dirty cup"

And all the other buttons

This is a very simple example. But the first approach summarizes logic in the machine. But the second approach forces the user to figure out how to make coffee and basically make his own coffee.

The next column shows us how we can achieve Abstraction using Encapsulation.

Encapsulation in object-oriented programming

The definition of encapsulation is the act of enclosing something. Losing access to parts of your code and privatizing items is exactly what Encapsulation does (often referred to as data hiding).

Encapsulation means that every object in your code must control its status. The current "Snapshot" status of your object. Keys, methods on objects, Boolean properties, and more. If you want to reset a boolean or remove a key from the object, they are all changes in your status.

Restrict the parts of the code that can be accessed. Make them inaccessible if they are not needed.

Private properties are obtained using closures in JavaScript. An example is given below:

  1. var Dog = (function () {  
  3.     // Private  
  4.     var play = function () {  
  5.         // play implementation  
  6.     };  
  8.     // Private  
  9.     var breed = "Dalmatian"  
  11.     // Public  
  12.     var name = "Rex";  
  14.     // Public  
  15.     var makeNoise = function () {  
  16.         return 'Bark bark!';  
  17.     };  
  19.     return {  
  20.         makeNoise: makeNoise,  
  21.         name: name  
  22.     };  
  23. })();  

The first thing we did was build a function that would call immediately (or so-called IIFE). This creates an object that anyone can access but hides some details. You can not call play and do not have access to breed because we did not display it in the final object with return.

This particular pattern is called the Revealing Module Pattern above, but this is just an example of how to achieve Encapsulation.

We want to focus more on the idea of ‚Äč‚ÄčEncapsulation (because this is more important than learning a pattern and counting Encapsulation).

Think about it, and think more about how you can hide and separate your data and code. Modulation and having a clear responsibility for objectivism is key.

Why should we prefer privacy? Why shouldn't everything be universal?

Many unrelated parts of the code are interconnected through a global variable.

If you use the name again, you are likely to override the variables, which can lead to bugs or unpredictable behavior.

Argument becomes difficult in code, and you follow what is being read and written for variables and mood swings.

Encapsulation can be applied to separate smaller functions by separating long lines of code. Separate these functions in the modules. We hide the data in a place where nothing else needs to be accessed, and make it clear what is needed.

This is a summary of Encapsulation. Attach (bind) your data to something, be it a class, object, module, or function, and do your best to keep it as private as possible.

Inheritance in programming

Inheritance allows one object to obtain the properties and methods of another object. In JavaScript, this is done by Prototypal Inheritance.

Reuse is the main benefit here. Sometimes we may want to do the same thing in several places and they have to do all the same things except one small part. This is a problem that inheritance can solve.

Whenever we use inheritance, we try to adjust it so that the parent and child are highly correlated. Correlation depends on how relevant your code is. For example, does the Bird type develop from the DieselEngine type?

Keep your inheritance simple and predictable. Do not inherit from something that is completely irrelevant just because it has a method or property that you need. Inheritance does not solve this particular problem well.

When using inheritance, you should have the most functionality required (you do not always need everything completely).

The main developers are called Liskov replacement principle. This principle says that if you can use the parent class (let's call it ParentType) wherever you can use the child (let's call it ChildType), and ChildType inherits from ParentType, then you have passed the test.

The main reason this test failed is because ChildType removes items from the parent. If ChildType deletes methods it inherited from its parent, this will result in a TypeError in which there are undefined items that you expect it to be.

Inheritance chain is a term used to describe the inheritance flow from the prototype of the base object (the same thing that inherits from everything else) to the end of the inheritance chain (the last type inherited, Dog in the example above). Do your best to keep your inheritance chain clean and reasonable.

Polymorphism in object-oriented programming

Polymorphism means "conditions occurring in several different forms." This is exactly what the fourth and final pillars of object-oriented programming do. Types in the inheritance chain are able to do different things.

If you have used inheritance correctly, you can trust your parents as well as their children. When two types use the same inheritance chain, they can be used interchangeably without any errors or declarations in the code.

In the last diagram, we may have a prototype called Animal, which defines makeNoise. Then any extensions of the prototype can be overridden to do their custom work. Something like this:

  1. // Let's set up an Animal and Dog example  
  2. function Animal(){}  
  3. function Dog(){}  
  5. Animal.prototype.makeNoise = function(){  
  6.     console.log("Base noise");  
  7. };  
  9. // Most animals we code up have 4. This can be overridden if needed  
  10. Animal.prototype.legs = 4;  
  12. Dog.prototype = new Animal();  
  14. Dog.prototype.makeNoise = function(){  
  15.     console.log("Woof woof");    
  16. };  
  18. var animal = new Animal();  
  19. var dog = new Dog();  
  21. animal.makeNoise(); // Base noise  
  22. dog.makeNoise();    // Woof woof- this was overridden  
  23. dog.legs;           // 4! This was inherited  

Dog inherits from Animal and can use the default legs property. But it can also do its implementation.

The real power of polymorphism is sharing behaviors and allowing custom overrides.


We hope we have been able to explain to you the four main pillars of object-oriented programming and how it leads to cleaner and more powerful code.

Java Script

Principles of object-orientation main cases of object-orientation object-orientation in JavaScript advantages of object-oriented programming program improvement with object-orientation key cases of object-orientation
You must be logged in to post a comment