0

Consider I have classes as follows:

public class User{
    private String name;
    //other code
    private String getName(){
        return name;
    }
}

public class ShowUserInfo{
    public void show(User user){
        System.out.println(user.getName());
    }
}

I'm quite sure I would not have other variations of User, and doesn't require polymorphism for User. But it is violating the rule of "dependency inversion principle" : ShowUserInfo depends on concrete class User, instead of abstractions. My question is, should I create interface for User:

public interface User{
    String getName();
}

public class UserImp implements User{
    private String name;
    //other code
    @Override
    private String getName(){
        return name;
    }
}

even if I don't need polymorphism and quite sure it would have one type of User only?

4

Yes, but only if you need it.

The Dependency Inversion Principle is not about making something work now. It talks about abstractions and concretions but it's not really about that either.

It's about change.

I can make anything work without DIP. Seriously, there isn't a single program in existence that can't be written completely DIP free.

We don't use DIP to accomplish a requirement. We use DIP so that the inevitable new requirement doesn't force a massive rewrite, recompilation, and redistribution.

So, do you need DIP here?

Well there isn't much code here to go by, other than it's clear that ShowUserInfo knows about User. The question then is if we care.

Think about this: User knows about String. String is as concrete as they come. Yet no one ever throws DIP at String. Why? Because String is stable (unlikely to change). Can you say the same thing about User?

If User is volatile (likely to change) then it's dangerous for ShowUserInfo to know about it directly. A change to User requires a change to ShowUserInfo if there is no DIP. A more stable interface or purely abstract class (doesn't matter which) helps protect against this volatility.

Now that's just about needing a more stable abstraction. DIP can actually do a little more for you.

DIP lets the flow of control go against the source code dependency. That gives you even more options to isolate against change.

Of User and DisplayUserInfo which do you think is more stable?

The usual pattern is to assume the business rule classes are the most stable and the reporting / adapting classes that communicate with the outside world are less so. But, if for some reason you thought User was less stable you could use DIP to reverse the source code dependency so that DisplayUserInfo knows nothing about User and so is protected from its volatility. It's better to know about stable things than unstable things. What you don't know about can't hurt you.

That's the real nifty thing about those open arrows <|-- you see in UML diagrams. Flow of control goes through them backwards. That inversion of direction is where this principle gets its name.

Since DIP lets you replace a uses arrow --> with an implements arrow <|-- pointing the other way, you get to decide what knows about what regardless of what needs to talk to what. That's the real power of DIP.

6

The Dependency Inversion Principle is not a method for using interfaces, nor is it primarily about enabling polymorphism.

DI is about providing dependencies to a class from the outside, rather than having that class create its own dependencies. Doing so allows the class to not be bound to any given implementation. Instead, you can provide the implementation that you wish the class to use, and all the class knows about is the interface.

Think of interfaces as creating a contract, so that an implementation can come along and satisfy that contract:

public interface Dancer
{
    public void dance();
}

public class SalsaDancer implements Dancer
{
    public void dance()
    {
        // Do the salsa.
    }
}

public class ChaChaDancer implements Dancer
{
    public void dance()
    {
        // Do the Cha Cha.
    }
}

public class User implements Dancer
{
    private Dancer _dancer;

    public User(Dancer dancer)
    {
         _dancer = dancer;
    }

    public void dance()
    {
        _dancer.dance();
    }
}

public static void main()
{
    dancer d = new SalsaDancer();
    User u = new User(d);
    u.dance();  // does the salsa.
}

Now, of course, maybe you'll only ever support a SalsaDancer. Polymorphism isn't the only reason you might want to provide DI. You might also want to give the class the capability of being mocked, so that it can be tested independendly of a Dancer implementation.

4
  • 1
    "providing dependencies to a class from the outside" that's Dependency Injection not the Dependency Inversion Principle. Dec 3 '17 at 15:34
  • That's a distinction without a difference. By definition, when you inject dependencies, you're also inverting them. Dec 3 '17 at 15:35
  • 1
    The difference is injection is not the only way to follow DIP. You seem to be defining a principle as merely one of the patterns that follows it. All I'm saying is you're answer could be better. Do what you will. Dec 3 '17 at 15:41
  • Basically, DIP is about nothing, let alone dependency provision as you define it. DIP is non-existent, as it has no precise and consistent definition.
    – ᄂ ᄀ
    Dec 23 '17 at 20:56
2

In your example User looks like a anemic model. An anemic model is purely data and no logic. You don't need to define an interface for these models because:

  • There is only one way to write an anemic data model for a given set of fields, therefore there is no benefit to allowing to swap implementations by defining an interface.
  • In an anemic model design your code makes assumptions based on knowledge that the model is anemic. E.g. if you defined getName() to return a random string each invocation it would break those assumptions.

If your model contains any business logic it is no longer anemic, and you may want to inject an interface. E.g.

public class User{
    private String firstName;
    private String lastName;

    public String getDisplayName(){
        // Business logic!!!!
        return String.format("%s %s", firstName, lastName);
    }
}

You should create an interface here because you can't unit test users of getDisplayName without coupling your test to the implementation of getDisplayName. Further you must test

0

You don't need an interface for User to derive from. User is effectively plain old data. However, you should have an interface for your ShowUserInfo class because it provides a side effect that you will want to test to ensure that it is called at the right time. In other words, some class uses ShowUserInfo and you need to be able to replace that use with a test version.

-3

The Dependency Injection "Principle" is pure cargo cult design. If you need dependency injection, you have a situation that cannot be resolved any other way: third party code needs to be injected into a previously built application, for example. Every other use of dependency injection is simply following a popular fad. There is no such "principle," but if you believe there is, you can join the ranks of many developers who waste their employers funds creating unnecessary complexity..

5
  • 1
    Well, first of all, everyone who writes reasonably sane code uses some form of dependency injection; it makes sense to hand a class (or method) its dependencies from the outside. Newing up dependencies inside a class tightly binds those dependencies to the class, whereas handing those dependencies to the class in a constructor satisfying some interface merely binds that class to the interface definition. Dec 1 '17 at 18:23
  • 3
    Further, decoupling your code in this way is not a fad, it is a feature. If you need that feature (that is, code that is decoupled), DI is one of the best ways to get it. Dec 1 '17 at 18:26
  • The question is about Dependency Inversion, which is invaluable in reducing complexity by defining independent interfaces. Dependency Inversion does not imply Dependency Injection (which I agree is a design concern rather than a 'principle'), though Dependency Inversion is a great way to facilitate Dependency Injection. Dec 2 '17 at 14:33
  • @RobertHarvey decoupling is not a feature, but a change that should be undertaken only when needed. Coupling is exactly the reason we use strongly typed languages. Decoupling has no intrinsic value; it is only useful when encountering coupling that is bad, causing a problem somehow. Dec 5 '17 at 17:43
  • decoupling is ... a change that should be undertaken only when needed -- Of course. Failing to follow that philosophy doesn't make DI cargo cult; it makes its practitioners cargo cult when they use it indiscriminately. Dec 5 '17 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.