Open Closed JS example (Monster)

Monster Open-Close Principle

ref – https://medium.com/@severinperez/maintainable-code-and-the-open-closed-principle-b088c737262

The chief benefit of the OCP is maintainability. If you adhere to the OCP you can greatly decrease future maintenance costs. The opposite applies as well — when you don’t adhere to the OCP, future maintenance costs will be greater. Consider how the coupling of two entities affects their respective maintainability. The more a given entity knows about how another one is implemented, the more we can say that they are coupled. Therefore, if one of the two entities is changed, then the other must be changed too. Here is a simple example:

We create a MonsterManager that takes in an array of monsters and locations. It then calls rampageAll on it and has all the monsters rampaging through all the locations.

But in order execute the Monster’s abilities, we must first check the monster. Then execute whatever special functionality it has. In order to do this, we check for the prototype of the Monster.

Now we create literal objects in order for instances of the monsters to be created

Create the monsters and locations

Then start rampaging!

In this snippet we use the OLOO pattern to define a MonsterManager prototype object and two types of monster prototypes, Kaiju and GreatOldOne. After initializing some monsters and an array of locations, we then initialize a new MonsterManager called myMonsterManager and call its rampageAll method, unleashing our monsters on those unlucky cities the randomLocation method happens to choose (sorry!) Can you spot any problems in this code related to OCP adherence?

Take a look at the rampageAll method — right now it iterates over each monster and checks whether they are of type Kaiju or GreatOldOne and then logs an appropriate message. What happens when this monster-filled world surfaces some new and terrible type of monster? In order for the program to work we would have to add another branch of conditional logic to the rampageAll method. In other words, we would have to modify the source code and therefore break the OCP. Doing so would not be a big deal with just one more monster type, but what about 10 new types? Or 20? Or 1,000? (Apparently this poor world is filled with monsters!) In order to extend the behavior of our MonsterManager (that is, let it deal with more types of monsters) we are going to have to think about how we deal with individual monster types.

Ultimately, the MonsterManager probably shouldn’t care about how each different monster rampages, so long as it has the ability to rampage in some fashion. Implementing our program this way would allow us to abstract away the rampage functionality to each individual monster. In other words, we can extend the functionality of the rampageAll method without changing the source code of MonsterManager. This use of abstraction is often described as a sort of contract — the objects being used promise to implement some piece of functionality and the object using them promises not to care how they do it. In this case, each monster promises to have a rampage function and MonsterManager promises to let them handle the details.

The correct approach

We connect its prototype to a new Error object
In order to inherit from JS’s Error object

Let’s first create a literal object
it sets the interface for all components to follow
we declare that we have an init property and rampage init
This means that all components who conform to this will need to implement these two functions

Bladmaster is an object that has __proto__ pointing to MonsterInterface
We want this to act as a prototype object

we then conform to our Monster Interface and implement:
init
rampage

Now we have Bladmaster prototype ready. We can create many instances of the Kaiju Monster
Let’s create a small group

we create an instance where the instance’s __proto__ point to to Bladmaster.
this enables us to inherit Bladmaster propeties

But wait a minute, we need to make sure Bladmaster REALLY conforms to MonterInterface. Not just take their word for it.

prototypeObject is our Bladmaster
interfaceObject is MonsterInterface

So we validate our Bladmaster according to MonsterInterface

Now that we have our monsters, we need to create a Monster Manager

We then create our locations and then add in both monsters and locations.
MonsterManager then proceeds to call rampageAll.

MonsterManager’s rampageAll’s implementation will proceed to have each monster execute their abilities upon the city: