post-images/dependency-management/cover.jpg

Dependency Management - Dependency Injection

Hi friend 🙋🏻‍♂️ We often simulate real-life problems in our code. While developing, that is, while creating our classes, we have to use another class call in many classes. This requirement is also called dependency. I have shared an example for you below. It will help you understand better.

Let's say we need a spell checker for a search box. When the user searches for something, we will check the accuracy of the text he wrote or offer a suggestion. We'll look at a dictionary we have while checking out (Lexicon)

// Inappropriate use of static utility - inflexible & untestable!  
public class SpellChecker {
    private static final Lexicon dictionary = ...;

    private SpellChecker() {} // Noninstantiable

    public boolean isValid(String word) { ... }
    public List < String > suggestions(String typo) { ... }
}

We can also create the spell checker we created as a singleton class, as we examined in one of the previous articles. Namely;

// Inappropriate use of singleton - inflexible & untestable!  
public class SpellChecker {
    private static final Lexicon dictionary = ...;

    private SpellChecker(...) {}

    public static SpellChecker INSTANCE = new SpellChecker(...);
    public boolean isValid(String word) { ... }
    public List < String > suggestions(String typo) { ... }
}

Very nice! Our spell checker takes the input that the user has typed and matches it with the information in our dictionary and validates it. But what about when the language changes? So what do we do when we want to enter a dictionary to test it? Can't we test the class we wrote? Shall we write different SpellCheckers for each language and its tests? Of course not!

The best way to resolve our dependencies inside our class would be to include those dependencies from outside, not inside our class. We should include our dependencies inside our class as an injection. This operation is called Dependency Injection.

In the light of all this information, the dependency in our example is Lexicon, our dictionary. When I consider the code again, we do not write the definition of the dictionary in our class as follows, but we need to get it with a constructor from outside.

// Dependency injection provides flexibility and testability 
public class SpellChecker {
    private final Lexicon dictionary;
    public SpellChecker(Lexicon dictionary) {
        this.dictionary = Objects.requireNonNull(dictionary);
    }

    public boolean isValid(String word) { ... }
    public List < String > suggestions(String typo) { ... }
}

As you can see, we can now use and test our spell checker, which we write with the dictionary we want.

Summary

Don't use singletons or static utility classes to implement one or more dependencies whose behavior affects the class, and don't let the class directly generate those resources. Greatly increase the flexibility, reusability, and testability of a class by using Dependency Injection instead.

JavaEffective JavaCreating and Destroying ObjectsDependency InjectionDependency ManagementSingleton Class