<style type="text/css">a[data-mtli~="mtli_filesize6912kB"]:after {content:" (69.12 kB)"}</style>{"id":4948,"date":"2018-11-19T22:24:34","date_gmt":"2018-11-19T21:24:34","guid":{"rendered":"https:\/\/monodes.com\/predaelli\/?p=4948"},"modified":"2018-11-19T13:26:48","modified_gmt":"2018-11-19T12:26:48","slug":"maintainable-code-and-the-open-closed-principle-severin-perez-medium","status":"publish","type":"post","link":"https:\/\/monodes.com\/predaelli\/2018\/11\/19\/maintainable-code-and-the-open-closed-principle-severin-perez-medium\/","title":{"rendered":"Maintainable Code and the Open-Closed Principle \u2013 Severin Perez \u2013 Medium"},"content":{"rendered":"<p><a href=\"https:\/\/medium.com\/@severinperez\/maintainable-code-and-the-open-closed-principle-b088c737262\"><img decoding=\"async\" class=\"alignnone size-full\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1200\/0*qznzIYfkOXCdxTM6\" alt=\"\" \/><\/a><\/p>\n<blockquote><p>A Look at the Open-Closed Principle in JavaScript<\/p><\/blockquote>\n<p><em><a href=\"https:\/\/medium.com\/@severinperez\/maintainable-code-and-the-open-closed-principle-b088c737262\">Maintainable Code and the Open-Closed Principle \u2013 Severin Perez \u2013 Medium<\/a><\/em><\/p>\n<p>Oh, another interesting article that tries to educate the &#8220;unliterate&#8221; JavaScript masses about the basic principle behind Eiffel&#8230;..<\/p>\n<p><!--more--><!--nextpage--><\/p>\n<blockquote>\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h1 id=\"17fe\" class=\"graf graf--h3 graf--leading graf--title\">Maintainable Code and the Open-Closed Principle<\/h1>\n<h2 id=\"e3cf\" class=\"graf graf--h4 graf-after--h3 graf--subtitle\">Abstraction and the Open-Closed Principle in JavaScript<\/h2>\n<\/div>\n<div class=\"section-inner sectionLayout--fullWidth\">\n<figure id=\"a44e\" class=\"graf graf--figure graf--layoutFillWidth graf-after--h4\" data-scroll=\"native\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded\" data-image-id=\"0*qznzIYfkOXCdxTM6\" data-width=\"5163\" data-height=\"2904\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<section class=\"section section--body section--first\">\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--fullWidth\">\n<figure id=\"a44e\" class=\"graf graf--figure graf--layoutFillWidth graf-after--h4\" data-scroll=\"native\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded\" data-image-id=\"0*qznzIYfkOXCdxTM6\" data-width=\"5163\" data-height=\"2904\" data-scroll=\"native\"><img decoding=\"async\" class=\"progressiveMedia-image js-progressiveMedia-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/2000\/0*qznzIYfkOXCdxTM6\" data-src=\"https:\/\/cdn-images-1.medium.com\/max\/2000\/0*qznzIYfkOXCdxTM6\" \/><\/div>\n<\/div><figcaption class=\"imageCaption\">Photo by <a class=\"markup--anchor markup--figure-anchor\" href=\"https:\/\/unsplash.com\/@stairhopper?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"photo-creator noopener nofollow noopener\" data-href=\"https:\/\/unsplash.com\/@stairhopper?utm_source=medium&amp;utm_medium=referral\">Alex Holyoake<\/a> on\u00a0<a class=\"markup--anchor markup--figure-anchor\" href=\"https:\/\/unsplash.com?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"photo-source noopener nofollow noopener\" data-href=\"https:\/\/unsplash.com?utm_source=medium&amp;utm_medium=referral\">Unsplash<\/a><\/figcaption><\/figure>\n<\/div>\n<div class=\"section-inner sectionLayout--insetColumn\">\n<p id=\"1c17\" class=\"graf graf--p graf--hasDropCapModel graf--hasDropCap graf-after--figure\"><span class=\"graf-dropCap\">In<\/span> <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\">part 1<\/a> of the SOLID series, we learned about how to write more flexible code with the Single Responsibility Principle (SRP). By isolating pieces of functionality in individual classes\/modules the SRP helps us guard against unnecessarily coupling responsibilities. If the implementation of one responsibility changes, SRP-adherent design prevents the change from affecting other responsibilities. However, decoupling responsibilities does not necessarily mean a complete decoupling of classes\/modules, functions, objects, etc. In most object-oriented code, different objects must deal with one another in some fashion. What then happens when a particular object needs to be changed? As with responsibility changes, this poses a challenge for the maintenance of downstream objects that could inadvertently be affected by the change. One way to reduce the impact of this challenge is to adhere to the second of the SOLID principles: the <em class=\"markup--em markup--p-em\">Open-Closed Principle (OCP)<\/em>.<\/p>\n<p id=\"086d\" class=\"graf graf--p graf-after--p graf--trailing\">In this post, we\u2019re going to explore the OCP and how to put it into practice. In a slight departure from many discussions on the OCP, we\u2019re going to conduct our exploration in JavaScript\u200a\u2014\u200aa language not often associated with classical OCP tools such as interfaces. However, JavaScript code is as deserving of SOLID adherence as any other code, so let\u2019s give it a shot!<\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h4 id=\"61c4\" class=\"graf graf--h4 graf--leading\"><strong class=\"markup--strong markup--h4-strong\">A Quick Refresher on\u00a0SOLID<\/strong><\/h4>\n<p id=\"f3a5\" class=\"graf graf--p graf-after--h4\">SOLID is an acronym for a set of five software development principles, which if followed, are intended to help developers create flexible and clean code. The five principles are:<\/p>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"97ac\" class=\"graf graf--li graf-after--p\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\">The <strong class=\"markup--strong markup--li-strong\">S<\/strong>ingle Responsibility Principle<\/a>\u200a\u2014\u200aClasses should have a single responsibility and thus only a single reason to change.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"d1aa\" class=\"graf graf--li graf-after--li\">The <strong class=\"markup--strong markup--li-strong\">O<\/strong>pen\/Closed Principle\u200a\u2014\u200aClasses and other entities should be open for extension but closed for modification.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"7cc6\" class=\"graf graf--li graf-after--li\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/medium.com\/@severinperez\/making-the-most-of-polymorphism-with-the-liskov-substitution-principle-e22609866429\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/making-the-most-of-polymorphism-with-the-liskov-substitution-principle-e22609866429\">The <strong class=\"markup--strong markup--li-strong\">L<\/strong>iskov Substitution Principle<\/a>\u200a\u2014\u200aObjects should be replaceable by their subtypes.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"5afd\" class=\"graf graf--li graf-after--li\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/medium.com\/@severinperez\/avoiding-interface-pollution-with-the-interface-segregation-principle-5d3859c21013\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/avoiding-interface-pollution-with-the-interface-segregation-principle-5d3859c21013\">The <strong class=\"markup--strong markup--li-strong\">I<\/strong>nterface Segregation Principle<\/a>\u200a\u2014\u200aInterfaces should be client specific rather than general.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li id=\"f485\" class=\"graf graf--li graf-after--li graf--trailing\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/medium.com\/@severinperez\/effective-program-structuring-with-the-dependency-inversion-principle-2d5adf11f863\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/effective-program-structuring-with-the-dependency-inversion-principle-2d5adf11f863\">The <strong class=\"markup--strong markup--li-strong\">D<\/strong>ependency Inversion Principle<\/a>\u200a\u2014\u200aDepend on abstractions rather than concretions.<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h4 id=\"13e5\" class=\"graf graf--h4 graf--leading\"><strong class=\"markup--strong markup--h4-strong\">The Open Closed Principle<\/strong><\/h4>\n<p id=\"adf2\" class=\"graf graf--p graf-after--h4\">Robert C. Martin, creator and chief evangelist of SOLID, credits Bertrand Meyer as the originator of the OCP. In his 1988 book <em class=\"markup--em markup--p-em\">Object Oriented Software Construction<\/em>, Meyer describes the need to develop flexible systems that can adapt to change without breaking. To do this, Meyer advocates the design of systems where entities (classes, modules, functions, etc) are \u201copen for extension, but closed for modification\u201d. In his development of the SOLID principles, Martin runs with this idea, describing it as a \u201cstraightforward\u201d attack against the threat of \u201cfragile, rigid, unpredictable and un-reusable\u201d code [1]. For his part, Martin breaks down the OCP into its two constituent parts, defining code that is \u201copen for extension\u201d as code to which you can add new behavior, and code that is \u201cclosed for modification\u201d as code that is \u201cinviolate\u201d in that it\u2019s design should never be changed once implemented. In other words, the OCP says that you can always add <em class=\"markup--em markup--p-em\">new code<\/em> to an object, but should never change the design of <em class=\"markup--em markup--p-em\">old code<\/em>.<\/p>\n<p id=\"48af\" class=\"graf graf--p graf-after--p\">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\u200a\u2014\u200awhen you don\u2019t 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:<\/p>\n<figure id=\"3e95\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<\/div>\n<\/section>\n<figure id=\"3e95\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\">\n<div class=\"iframeContainer\"><iframe loading=\"lazy\" class=\"progressiveMedia-iframe js-progressiveMedia-iframe\" src=\"https:\/\/medium.com\/media\/083b85a7d6dfa85f91e3c0e23e8e96b6?postId=b088c737262\" width=\"700\" height=\"250\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-src=\"\/media\/083b85a7d6dfa85f91e3c0e23e8e96b6?postId=b088c737262\" data-media-id=\"083b85a7d6dfa85f91e3c0e23e8e96b6\" data-thumbnail=\"https:\/\/i.embed.ly\/1\/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F23282344%3Fs%3D400%26v%3D4&amp;key=a19fcc184b9711e1b4764040d3dc5c07\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/figure>\n<p id=\"b6ab\" class=\"graf graf--p graf-after--figure\">In this snippet we have a simple function called <code class=\"\" data-line=\"\">announce<\/code> that takes an object as an argument and uses that object\u2019s <code class=\"\" data-line=\"\">items<\/code> and <code class=\"\" data-line=\"\">description<\/code> properties to log a message to the console. When we call this function and pass it the <code class=\"\" data-line=\"\">favoriteCities<\/code> object we get the expected output. But what if we decide that we don\u2019t want the <code class=\"\" data-line=\"\">favoriteCities<\/code> object to store its <code class=\"\" data-line=\"\">items<\/code> in an array and decide it\u2019s better to store them in an object?<\/p>\n<figure id=\"52fc\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<figure id=\"52fc\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\">\n<div class=\"iframeContainer\"><iframe loading=\"lazy\" class=\"progressiveMedia-iframe js-progressiveMedia-iframe\" src=\"https:\/\/medium.com\/media\/efc55d86c9b8e43bb96453f833702898?postId=b088c737262\" width=\"700\" height=\"250\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-src=\"\/media\/efc55d86c9b8e43bb96453f833702898?postId=b088c737262\" data-media-id=\"efc55d86c9b8e43bb96453f833702898\" data-thumbnail=\"https:\/\/i.embed.ly\/1\/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F23282344%3Fs%3D400%26v%3D4&amp;key=a19fcc184b9711e1b4764040d3dc5c07\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/figure>\n<p id=\"8fe6\" class=\"graf graf--p graf-after--figure\">By changing our <code class=\"\" data-line=\"\">favoriteCities.items <\/code>implementation from an array to an object we effectively broke our <code class=\"\" data-line=\"\">announce<\/code> function. The reason is that the <code class=\"\" data-line=\"\">announce<\/code> function knows too much about how <code class=\"\" data-line=\"\">favoriteCities<\/code> was implemented and expects it to have an <code class=\"\" data-line=\"\">items<\/code> property that is an array. Fixing this would be relatively trivial (perhaps we could add a conditional to the <code class=\"\" data-line=\"\">announce<\/code> function to check first whether the <code class=\"\" data-line=\"\">collection.items<\/code> property is an array or an object), but at what long-term cost? What if we didn\u2019t make this change until much later in development and we had lots of functions that used <code class=\"\" data-line=\"\">collection.items<\/code>? We would then have to add conditionals to every place that referenced <code class=\"\" data-line=\"\">items<\/code>.<\/p>\n<p id=\"9dfe\" class=\"graf graf--p graf-after--p\">A better solution is to use polymorphism and to let each <code class=\"\" data-line=\"\">collection<\/code> object decide for itself how its <code class=\"\" data-line=\"\">items<\/code> should be iterated over and logged. In this pattern, the <code class=\"\" data-line=\"\">announce<\/code> function doesn\u2019t care whether the collections it works with use arrays, objects, or some other data structure to hold their <code class=\"\" data-line=\"\">items<\/code>. Here is one approach:<\/p>\n<figure id=\"3376\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<section class=\"section section--body\">\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<figure id=\"3376\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\">\n<div class=\"iframeContainer\"><iframe loading=\"lazy\" class=\"progressiveMedia-iframe js-progressiveMedia-iframe\" src=\"https:\/\/medium.com\/media\/00b4841e7665c34af36d66498089d7e0?postId=b088c737262\" width=\"700\" height=\"250\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-src=\"\/media\/00b4841e7665c34af36d66498089d7e0?postId=b088c737262\" data-media-id=\"00b4841e7665c34af36d66498089d7e0\" data-thumbnail=\"https:\/\/i.embed.ly\/1\/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F23282344%3Fs%3D400%26v%3D4&amp;key=a19fcc184b9711e1b4764040d3dc5c07\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/figure>\n<p id=\"cb57\" class=\"graf graf--p graf-after--figure graf--trailing\">In this final snippet, we provide <code class=\"\" data-line=\"\">favoriteCities<\/code> with a <code class=\"\" data-line=\"\">logItems<\/code> method that implements how to log its items. As far as <code class=\"\" data-line=\"\">announce<\/code> is concerned, it can deal with <em class=\"markup--em markup--p-em\">any<\/em> collection object so long as it has a <code class=\"\" data-line=\"\">description<\/code> property and a <code class=\"\" data-line=\"\">logItems<\/code> method. This is the OCP in action\u200a\u2014\u200athe <code class=\"\" data-line=\"\">announce<\/code> function is <em class=\"markup--em markup--p-em\">extensible<\/em> because it can handle any <code class=\"\" data-line=\"\">collection<\/code> that guarantees these two properties but it is also <em class=\"markup--em markup--p-em\">closed to modification<\/em> because we don\u2019t have to change the source code in <code class=\"\" data-line=\"\">announce<\/code> to change its available behaviors.<\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h4 id=\"fff8\" class=\"graf graf--h4 graf--leading\"><strong class=\"markup--strong markup--h4-strong\">Abstractions as Extensions<\/strong><\/h4>\n<p id=\"f991\" class=\"graf graf--p graf-after--h4\">In a 2014 blog article, Martin discusses the apparent paradox in writing entities that are simultaneously <em class=\"markup--em markup--p-em\">open for extension<\/em> and yet <em class=\"markup--em markup--p-em\">closed to modification<\/em> [2]. How can something be both open and closed at once? Martin uses the example of plugin architecture to describe how new features can be added to software without modifying the original source code. Plugins are useful at the system level, but what about at the entity level when objects are interacting with one another? In this case, the key is <em class=\"markup--em markup--p-em\">abstraction<\/em>. We had a taste of this in the simple examples above when we abstracted out the <code class=\"\" data-line=\"\">logItems<\/code> functionality of our <code class=\"\" data-line=\"\">collection<\/code> objects. Let\u2019s see if we can do the same with a slightly more complex program.<\/p>\n<figure id=\"da9b\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<\/div>\n<\/section>\n<figure id=\"da9b\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\">\n<div class=\"iframeContainer\"><iframe loading=\"lazy\" class=\"progressiveMedia-iframe js-progressiveMedia-iframe\" src=\"https:\/\/medium.com\/media\/945aa06abe3139e84505c05520680caa?postId=b088c737262\" width=\"700\" height=\"250\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-src=\"\/media\/945aa06abe3139e84505c05520680caa?postId=b088c737262\" data-media-id=\"945aa06abe3139e84505c05520680caa\" data-thumbnail=\"https:\/\/i.embed.ly\/1\/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F23282344%3Fs%3D400%26v%3D4&amp;key=a19fcc184b9711e1b4764040d3dc5c07\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/figure>\n<p id=\"c521\" class=\"graf graf--p graf-after--figure\">In this snippet we use the <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/medium.com\/launch-school\/javascript-weekly-fundamental-object-design-patterns-31453f68427f\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/launch-school\/javascript-weekly-fundamental-object-design-patterns-31453f68427f\">OLOO<\/a> pattern to define a <code class=\"\" data-line=\"\">MonsterManager<\/code> prototype object and two types of monster prototypes, <code class=\"\" data-line=\"\">Kaiju<\/code> and <code class=\"\" data-line=\"\">GreatOldOne<\/code>. After initializing some monsters and an array of locations, we then initialize a new <code class=\"\" data-line=\"\">MonsterManager<\/code> called <code class=\"\" data-line=\"\">myMonsterManager<\/code> and call its <code class=\"\" data-line=\"\">rampageAll<\/code> method, unleashing our monsters on those unlucky cities the <code class=\"\" data-line=\"\">randomLocation<\/code> method happens to choose (sorry!) Can you spot any problems in this code related to OCP adherence?<\/p>\n<p id=\"96a5\" class=\"graf graf--p graf-after--p\">Take a look at the <code class=\"\" data-line=\"\">rampageAll<\/code> method\u200a\u2014\u200aright now it iterates over each monster and checks whether they are of type <code class=\"\" data-line=\"\">Kaiju<\/code> or <code class=\"\" data-line=\"\">GreatOldOne<\/code> 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 <code class=\"\" data-line=\"\">rampageAll<\/code> method. In other words, we would have to <em class=\"markup--em markup--p-em\">modify the source code<\/em> 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 <code class=\"\" data-line=\"\">MonsterManager<\/code> (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.<\/p>\n<p id=\"ba9b\" class=\"graf graf--p graf-after--p\">Ultimately, the <code class=\"\" data-line=\"\">MonsterManager<\/code> probably shouldn\u2019t 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 <em class=\"markup--em markup--p-em\">extend<\/em> the functionality of the <code class=\"\" data-line=\"\">rampageAll<\/code> method without changing the source code of <code class=\"\" data-line=\"\">MonsterManager<\/code>. This use of abstraction is often described as a sort of contract\u200a\u2014\u200athe 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 <code class=\"\" data-line=\"\">rampage<\/code> function and <code class=\"\" data-line=\"\">MonsterManager<\/code> promises to let them handle the details.<\/p>\n<p id=\"350c\" class=\"graf graf--p graf-after--p\">As a means of implementing this pattern, languages like C# and Java have an abstraction called an <em class=\"markup--em markup--p-em\">interface<\/em>. An interface can be used to create the kind of contracts described above. Unfortunately, JavaScript does not have interfaces; however, we can roughly approximate some of the behavior of an interface by using prototypal delegation and a custom validation function. Let\u2019s try to do that with our monster program.<\/p>\n<figure id=\"ee71\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\"><\/div>\n<\/div>\n<\/figure>\n<div class=\"postArticle-content js-postField js-notesSource js-trackedPost\" data-post-id=\"b088c737262\" data-source=\"post_page\" data-tracking-context=\"postPage\" data-scroll=\"native\">\n<section class=\"section section--body\">\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<figure id=\"ee71\" class=\"graf graf--figure graf--iframe graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"progressiveMedia js-progressiveMedia is-canvasLoaded is-imageLoaded\" data-scroll=\"native\">\n<div class=\"iframeContainer\"><iframe loading=\"lazy\" class=\"progressiveMedia-iframe js-progressiveMedia-iframe\" src=\"https:\/\/medium.com\/media\/3de1977f61349263cf4ad27c5aa36022?postId=b088c737262\" width=\"700\" height=\"250\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-src=\"\/media\/3de1977f61349263cf4ad27c5aa36022?postId=b088c737262\" data-media-id=\"3de1977f61349263cf4ad27c5aa36022\" data-thumbnail=\"https:\/\/i.embed.ly\/1\/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F23282344%3Fs%3D400%26v%3D4&amp;key=a19fcc184b9711e1b4764040d3dc5c07\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/figure>\n<p id=\"70ea\" class=\"graf graf--p graf-after--figure\">In this snippet, we have a custom <code class=\"\" data-line=\"\">ImplementationError<\/code> as well as a function called <code class=\"\" data-line=\"\">createWithInterfaceValidation<\/code>, which takes <code class=\"\" data-line=\"\">prototypeObject<\/code> and <code class=\"\" data-line=\"\">interfaceObject<\/code> parameters. This function iterates over the <code class=\"\" data-line=\"\">interfaceObject<\/code> parameter to identify which properties should be implemented on the <code class=\"\" data-line=\"\">prototypeObject<\/code> and throws an <code class=\"\" data-line=\"\">ImplementationError<\/code> if they are not implemented. If no errors are thrown then the function returns a new object linked to the passed in <code class=\"\" data-line=\"\">prototypeObject<\/code>. By using this function we can replicate some (though not all) of the functionality of classical interfaces.<\/p>\n<p id=\"f799\" class=\"graf graf--p graf-after--p\">In the rest of the snippet we have new version of our <code class=\"\" data-line=\"\">MonsterManager<\/code> and a few monster types. The difference however is that the <code class=\"\" data-line=\"\">rampageAll<\/code> function no longer has any conditional logic. Rather, it assumes that each monster has implemented a <code class=\"\" data-line=\"\">rampage<\/code> function. When creating our monster types we guarantee exactly this by using a <code class=\"\" data-line=\"\">MonsterInterface<\/code> object as the prototype for each monster type and then using the <code class=\"\" data-line=\"\">createWithInterfaceValidation<\/code> function whenever we instantiate a new monster. In this fashion, we can be sure that every monster has a valid <code class=\"\" data-line=\"\">rampage<\/code> method, otherwise an <code class=\"\" data-line=\"\">ImplementationError<\/code> would be thrown.<\/p>\n<p id=\"95dc\" class=\"graf graf--p graf-after--p graf--trailing\">This snippet still leaves a lot of room for improvement (DRYer code, type checking, signature checking, custom error messages, additional OCP-adherence opportunities, etc.); however, we can already see a number of improvements over the first version. Most importantly, our <code class=\"\" data-line=\"\">MonsterManager<\/code> is extensible in that we can add new behavior but it is also closed to modification in that we don\u2019t need to change the source code when adding that new behavior. We can create as many monster types as we like, so long as they all have a <code class=\"\" data-line=\"\">rampage<\/code> method. This goes to the core of what the OCP is all about.<\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h4 id=\"12fe\" class=\"graf graf--h4 graf--leading\"><strong class=\"markup--strong markup--h4-strong\">TL;DR<\/strong><\/h4>\n<p id=\"79dc\" class=\"graf graf--p graf-after--h4 graf--trailing\">The second of the SOLID principles of software development is the <em class=\"markup--em markup--p-em\">Open-Closed Principle (OCP)<\/em>, which says that software entities (objects, classes, modules, etc.) should be \u201copen for extension\u201d but \u201cclosed to modification\u201d. In this context, extension means adding new behavior and modification means altering existing source code. The OCP is a useful principle for keeping your code maintainable because it ensures that old working code is not changed (causing downstream breakage) while simultaneously allowing for the addition of new behavior. One method for adhering to the OCP is relying on abstractions rather than concretions. When one object interacts with another, it should do so through an abstraction, allowing its partner object to worry about specific implementation. The classic way to do this is with <em class=\"markup--em markup--p-em\">interfaces<\/em> or other abstractions; however, some languages like JavaScript do not provide native interface abstractions. In this case, it is still possible to follow the OCP either through convention or through custom validation methods.<\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<p id=\"b2f5\" class=\"graf graf--p graf--leading\">That\u2019s all for our discussion of the OCP. Stay tuned for articles on the remaining three SOLID principles\u200a\u2014\u200astarting with part 3 on the <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/medium.com\/@severinperez\/making-the-most-of-polymorphism-with-the-liskov-substitution-principle-e22609866429\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/making-the-most-of-polymorphism-with-the-liskov-substitution-principle-e22609866429\">Liskov Substitution Principle<\/a>. And if you want to go back to the beginning of the series, you can find <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/medium.com\/@severinperez\/writing-flexible-code-with-the-single-responsibility-principle-b71c4f3f883f\">part 1 here<\/a>. If you have any comments or questions, leave them below\u200a\u2014\u200aI would love to hear what you think.<\/p>\n<p id=\"a59b\" class=\"graf graf--p graf-after--p graf--trailing\">If you would like alerts when a new article is published you can follow me here on Medium, on <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/twitter.com\/SeverinJPerez\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/twitter.com\/SeverinJPerez\">Twitter<\/a>, or subscribe on my <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/severinperez.com\/blog\/\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/severinperez.com\/blog\/\">personal blog<\/a> where these articles are cross-published. Happy coding!<\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body section--last\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<p id=\"67d9\" class=\"graf graf--p graf--leading\"><strong class=\"markup--strong markup--p-strong\">References<\/strong><\/p>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"d18d\" class=\"graf graf--li graf-after--p\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/web.archive.org\/web\/20060822033314\/http:\/\/www.objectmentor.com\/resources\/articles\/ocp.pdf\" data-mtli=\"mtli_filesize6912kB\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/web.archive.org\/web\/20060822033314\/http:\/\/www.objectmentor.com\/resources\/articles\/ocp.pdf\" data-mtli=\"mtli_filesize6912kB\">Paper: The Open-Closed Principle; Martin, Robert C.; 1996<\/a><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"da82\" class=\"graf graf--li graf-after--li\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/8thlight.com\/blog\/uncle-bob\/2014\/05\/12\/TheOpenClosedPrinciple.html\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/8thlight.com\/blog\/uncle-bob\/2014\/05\/12\/TheOpenClosedPrinciple.html\">Article: The Open Closed Principle; Martin, Robert C.; 2014<\/a><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li style=\"list-style-type: none\">\n<ol class=\"postList\">\n<li id=\"e54a\" class=\"graf graf--li graf-after--li\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/github.com\/ryanmcdermott\/clean-code-javascript#solid\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/github.com\/ryanmcdermott\/clean-code-javascript#solid\">Resource: clean-code-javascript; Mcdermott, Ryan<\/a><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<ol class=\"postList\">\n<li id=\"e28a\" class=\"graf graf--li graf-after--li graf--trailing\"><a class=\"markup--anchor markup--li-anchor\" href=\"https:\/\/en.wikipedia.org\/wiki\/Open%E2%80%93closed_principle\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/en.wikipedia.org\/wiki\/Open%E2%80%93closed_principle\">Wikipedia: Open-closed principle<\/a><\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/section>\n<\/div>\n<footer class=\"u-paddingTop10\">\n<div class=\"container u-maxWidth740\">\n<div class=\"row\">\n<div class=\"col u-size12of12\">\n<div class=\"postMetaInline postMetaInline--acknowledgments u-paddingTop5 u-paddingBottom20 js-postMetaAcknowledgments\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/footer>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p class=\"excerpt\">A Look at the Open-Closed Principle in JavaScript Maintainable Code and the Open-Closed Principle \u2013 Severin Perez \u2013 Medium Oh, another interesting article that tries to educate the &#8220;unliterate&#8221; JavaScript masses about the basic principle behind Eiffel&#8230;..<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"https:\/\/monodes.com\/predaelli\/2018\/11\/19\/maintainable-code-and-the-open-closed-principle-severin-perez-medium\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[72,34],"tags":[],"class_list":["post-4948","post","type-post","status-publish","format-standard","hentry","category-documentations","category-eiffel"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6daft-1hO","jetpack-related-posts":[{"id":4917,"url":"https:\/\/monodes.com\/predaelli\/2018\/11\/14\/single-responsibility-principle\/","url_meta":{"origin":4948,"position":0},"title":"Single Responsibility Principle","author":"Paolo Redaelli","date":"2018-11-14","format":false,"excerpt":"Writing Flexible Code with the Single Responsibility Principle Mhmhmm... where have I heard of that SOLID principle? Ah, Eiffel! Severin Perez Writer | Developer | Information Specialist Sep 7 Writing Flexible Code with the Single Responsibility Principle SOLID Principles and Maintainable Code Photo by NASA on\u00a0Unsplash If you\u2019ve been around\u2026","rel":"","context":"In &quot;Senza categoria&quot;","block_context":{"text":"Senza categoria","link":"https:\/\/monodes.com\/predaelli\/category\/senza-categoria\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":7385,"url":"https:\/\/monodes.com\/predaelli\/2020\/07\/13\/the-s-o-l-i-d-principles-in-pictures\/","url_meta":{"origin":4948,"position":1},"title":"The S.O.L.I.D Principles in Pictures","author":"Paolo Redaelli","date":"2020-07-13","format":"link","excerpt":"If you are familiar with Object-Oriented Programming, then you\u2019ve probably heard about the SOLID principles. Ugonna Thelma explains The S.O.L.I.D Principles in Pictures and she explains them very well. In fact I shall admit that while I've interiorized the S, the O, the L and the I, I always tend\u2026","rel":"","context":"In &quot;Documentations&quot;","block_context":{"text":"Documentations","link":"https:\/\/monodes.com\/predaelli\/category\/documentations\/"},"img":{"alt_text":"Ugonna Thelma","src":"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2020\/07\/2bveoh12R-5thGMYGTkV74A.jpeg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":297,"url":"https:\/\/monodes.com\/predaelli\/2015\/06\/12\/javascript-other-languages\/","url_meta":{"origin":4948,"position":2},"title":"JavaScript + Other Languages","author":"Paolo Redaelli","date":"2015-06-12","format":"link","excerpt":"JavaScript+OtherLanguages Those slides JavaScript + Other Languages are really useful to implement an eventual Eiffel to JavaScript compiler. Well, actually it should be called transcompiler.... We could just feed the C files made by current Liberty compiler but it seems to me that passing throught C which is a procedural\u2026","rel":"","context":"In &quot;Eiffel&quot;","block_context":{"text":"Eiffel","link":"https:\/\/monodes.com\/predaelli\/category\/eiffel\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4677,"url":"https:\/\/monodes.com\/predaelli\/2018\/10\/22\/conditional-javascript-for-experts-hacker-noon\/","url_meta":{"origin":4948,"position":3},"title":"Conditional JavaScript for Experts \u2013 Hacker Noon","author":"Paolo Redaelli","date":"2018-10-22","format":false,"excerpt":"Mastery of conditional expressions for cleaner codes They say in Conditional JavaScript for Experts \u2013 Hacker Noon. What they are suggesting is to use side-effects of\u00a0 \"expression\", as Javascript does not separate commands and queries. Call me dogmatic but this behavior to look like a fundamental ingredient for disaster. In\u2026","rel":"","context":"In &quot;Eiffel&quot;","block_context":{"text":"Eiffel","link":"https:\/\/monodes.com\/predaelli\/category\/eiffel\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1286,"url":"https:\/\/monodes.com\/predaelli\/2016\/04\/17\/eiffel-a-viable-candidate-as-a-language-for-the-gnome-platform\/","url_meta":{"origin":4948,"position":4},"title":"Eiffel: A viable candidate as a language for the Gnome platform ?","author":"Paolo Redaelli","date":"2016-04-17","format":false,"excerpt":"Eiffel: A viable candidate as a language for the Gnome platform ? It was 2004. Linux were labelled as a cancer by Ballmer, Android and iPhone didn't existed. Multi-core CPU were still high-end. It was a different world. From archive.org, before it got lost.... Twelve years ago. And it was\u2026","rel":"","context":"In &quot;Eiffel&quot;","block_context":{"text":"Eiffel","link":"https:\/\/monodes.com\/predaelli\/category\/eiffel\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3971,"url":"https:\/\/monodes.com\/predaelli\/2018\/04\/01\/sheer-pure-evil\/","url_meta":{"origin":4948,"position":5},"title":"Sheer, pure evil","author":"Paolo Redaelli","date":"2018-04-01","format":false,"excerpt":"JavaScript: Can (a==1 && a==2 && a==3) ever evaluate to true?\u00a0Yes, it can. Understand how in this article! That's pure sheer evil, in my humble opinion as it tricks most people. Eiffel forbids this evilness, but I shall explain it better. Recently, an interesting code snippet has been making the\u2026","rel":"","context":"In &quot;Documentations&quot;","block_context":{"text":"Documentations","link":"https:\/\/monodes.com\/predaelli\/category\/documentations\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/4948","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/comments?post=4948"}],"version-history":[{"count":0,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/4948\/revisions"}],"wp:attachment":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/media?parent=4948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/categories?post=4948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/tags?post=4948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}