avatarEmanuel Trandafir

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

2316

Abstract

-8Hvx6OuLzCxr0"><figcaption>Photo by <a href="https://unsplash.com/@ryansnaadt?utm_source=medium&amp;utm_medium=referral">Ryan Snaadt</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h2 id="4119">3. Refactor!</h2><p id="514f">Don’t panic! These situations might occur. We cannot be flexible enough to protect against any change whatsoever. In fact, this can even be considered an anti-pattern, known as “<i>over-engineering”</i>.</p><p id="a663">Firstly, we need to refactor the existing code to conform to the <a href="https://javarevisited.blogspot.com/2018/07/10-object-oriented-design-principles.html">Open-Closed principle</a> again.</p><p id="d099">In our case, we can extract an interface from the divider class. This will not apply to dividers only, so we’ll need to choose a different name:</p><div id="12ae"><pre><span class="hljs-keyword">public</span> interface HasPotentialOutput { <span class="hljs-function"><span class="hljs-type">boolean</span> <span class="hljs-title">isApplying</span><span class="hljs-params">(<span class="hljs-type">int</span> number)</span></span>; <span class="hljs-function"><span class="hljs-type">String</span> <span class="hljs-title">getOutput</span><span class="hljs-params">()</span></span>; }</pre></div><p id="d833">After this, we can create another implementation of this interface, specifically for numbers containing one digit.</p><p id="f55c">Though, it can be done even more generically by using <a href="https://javarevisited.blogspot.com/2018/08/top-5-java-8-courses-to-learn-online.html">lambda functions:</a></p> <figure id="b42e"> <div> <div>

            <iframe class="gist-iframe" src="/gist/etrandafir93/b8dbc7e7c75689c26a3daee259740ad7.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="9b50">The predicate is a function that receives a number and it must return a <a href="https://javarevisited.blogspot.com/2018/05/3-ways-to-convert-string-to-boolean-in.html">boolean </a>if the number meets its criteria.</p><h2 id="fb29">4. Polymorhphysm</h2><p id="0466">Consequently, we can easily add new custom el

Options

ements that will print “Barr” if the number contains a 0 or print “Darr” if the number has more than 4 digits.</p> <figure id="ac9d"> <div> <div>

            <iframe class="gist-iframe" src="/gist/etrandafir93/be22bcd44a5541285c5810175194d27b.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="9733">As you can see, in the list we now have various implementations of the <i>HasPotentialOutput </i>interface. Each of them implements the public methods in its own unique way. This pattern is also known as <a href="https://javarevisited.blogspot.com/2020/04/difference-between-inheritance-and-Polymorphism-in-java-oop.html"><i>polymorphism</i></a>.</p><h2 id="5cad">5. Dependency Inversion</h2><p id="538e">Our codebase grows bigger: it is time to add some separation.</p><p id="2231">Let’s keep <i>FizzBuzz </i>and <i>HasPotentialOutput </i>at the core of our application and consider the <i>Dividers</i> and <i>CustomPotterntialElement </i>to be the “details” that can often change (and move them to a separate package).</p><figure id="7e71"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*f8Xg_eoVvBviZnKT_IbOdQ.png"><figcaption></figcaption></figure><p id="52e5">Without even noticing, when we introduced the <i>HasPotentialOutput </i>interface, we actually inverted one of the dependencies.</p><p id="af63">Now, we can clearly see that the <i>Dividers </i>and <i>CustomPotterntialElement </i>depend on the interface from the <i>core </i>package. In other words, the <i>elements </i>package depends on the <i>core </i>package<i>.</i></p><p id="531f">As a result, the <a href="https://javarevisited.blogspot.com/2015/04/fizzbuzz-solution-in-java-8.html"><i>FizzBuzz </i></a>object will function correctly without knowing about the various implementations and regardless of the changes in the elements.</p><h2 id="6966">6. Conclusion</h2><p id="c7f3">In this article, we managed to invert the dependency from our small codebase through polymorphism.</p><p id="562b">We’ve seen how Dependency Inversion works and how it helps us to protect our core domain logic against changes in the peripheric details.</p></article></body>

Dependency Inversion, Polymorphism, and How to Handle Unexpected Changes in Requirements

In this article, we’ll see how to react to unexpected features and changes in requirements.

Photo by Brad Starkey on Unsplash

1. Overview

In our previous article, we implemented a simple FizzBuzz application while focusing on the Open-Closed Principle and testability. Additionally, we used encapsulation and immutable Divider objects to check what needs to be printed for each number.

This led to a flexible design that allowed us easily introduce new dividers (or remove the existing ones), with minimal changes to the existing code.

In this article, we’ll continue working on the same codebase. So make sure to check the current state of the application before continuing reading, if you haven’t done it already.

2. Unexpected Use-Cases

But, what if the new requirement is an unforeseen one? For instance, to print “Bar” if the number contains a “0”? Or to print “Darr” if the number has more than 4 digits?

These requirements have nothing to do with division. We have clearly not prepared for this one — therefore, at this moment, we are actually violating the Open-Closed Principle.

Photo by Ryan Snaadt on Unsplash

3. Refactor!

Don’t panic! These situations might occur. We cannot be flexible enough to protect against any change whatsoever. In fact, this can even be considered an anti-pattern, known as “over-engineering”.

Firstly, we need to refactor the existing code to conform to the Open-Closed principle again.

In our case, we can extract an interface from the divider class. This will not apply to dividers only, so we’ll need to choose a different name:

public interface HasPotentialOutput {
    boolean isApplying(int number);
    String getOutput();
}

After this, we can create another implementation of this interface, specifically for numbers containing one digit.

Though, it can be done even more generically by using lambda functions:

The predicate is a function that receives a number and it must return a boolean if the number meets its criteria.

4. Polymorhphysm

Consequently, we can easily add new custom elements that will print “Barr” if the number contains a 0 or print “Darr” if the number has more than 4 digits.

As you can see, in the list we now have various implementations of the HasPotentialOutput interface. Each of them implements the public methods in its own unique way. This pattern is also known as polymorphism.

5. Dependency Inversion

Our codebase grows bigger: it is time to add some separation.

Let’s keep FizzBuzz and HasPotentialOutput at the core of our application and consider the Dividers and CustomPotterntialElement to be the “details” that can often change (and move them to a separate package).

Without even noticing, when we introduced the HasPotentialOutput interface, we actually inverted one of the dependencies.

Now, we can clearly see that the Dividers and CustomPotterntialElement depend on the interface from the core package. In other words, the elements package depends on the core package.

As a result, the FizzBuzz object will function correctly without knowing about the various implementations and regardless of the changes in the elements.

6. Conclusion

In this article, we managed to invert the dependency from our small codebase through polymorphism.

We’ve seen how Dependency Inversion works and how it helps us to protect our core domain logic against changes in the peripheric details.

Java
Programming
Coding
Software Development
Software Engineering
Recommended from ReadMedium