Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly use dependency injection

Me and two other colleagues are trying to understand how to best design a program. For example, I have an interface ISoda and multiple classes that implement that interface like Coke, Pepsi, DrPepper, etc....

My colleague is saying that it's best to put these items into a database like a key/value pair. For example:

Key       |  Name
--------------------------------------
Coke      |  my.namespace.Coke, MyAssembly
Pepsi     |  my.namespace.Pepsi, MyAssembly
DrPepper  |  my.namespace.DrPepper, MyAssembly

... then have XML configuration files that map the input to the correct key, query the database for the key, then create the object.

I don't have any specific reasons, but I just feel that this is a bad design, but I don't know what to say or how to correctly argue against it.

My second colleague is suggesting that we micro-manage each of these classes. So basically the input would go through a switch statement, something similiar to this:

ISoda soda;

switch (input)
{
   case "Coke":
      soda = new Coke();
      break;       
   case "Pepsi":
      soda = new Pepsi();
      break;
   case "DrPepper":
      soda = new DrPepper();
      break;
}

This seems a little better to me, but I still think there is a better way to do it. I've been reading up on IoC containers the last few days and it seems like a good solution. However, I'm still very new to dependency injection and IoC containers, so I don't know how to correctly argue for it. Or maybe I'm the wrong one and there's a better way to do it? If so, can someone suggest a better method?

What kind of arguments can I bring to the table to convince my colleagues to try another method? What are the pros/cons? Why should we do it one way?

Unfortunately, my colleagues are very resistant to change so I'm trying to figure out how I can convince them.

Edit:

Seems like my question is a little bit hard to understand. What we're trying to figure out is how to best design an application that utilizes multiple interfaces and contains many concrete types that implement those interfaces.

Yes, I know that storing this stuff in the database is a bad idea, but we simply do not know of a better way. This is why I'm asking how do we do it better.

public void DrinkSoda(string input)
{
   ISoda soda = GetSoda(input);
   soda.Drink();
}

How do we correctly implement GetSoda? Should we rethink the entire design? If it's a bad idea to pass around magic strings like this, then how should we do it?

User inputs such as "Diet Coke", "Coke", "Coke Lime", or whatever would instantiate a type of Coke, so multiple keywords map to a single type.

A lot of people have said that the posted code above is bad. I know it's bad. I'm looking for reasons to present to my colleagues and argue why it's bad and why we need to change.

I apologize if this explanation is still difficult to understand. It's hard for me to describe the situation because I don't really understand how to put it in words.

like image 831
Rune Avatar asked Apr 04 '10 02:04

Rune


People also ask

What is the right way to inject dependency?

Constructor injection should be the main way that you do dependency injection. It's simple: A class needs something and thus asks for it before it can even be constructed. By using the guard pattern, you can use the class with confidence, knowing that the field variable storing that dependency will be a valid instance.

What is dependency injection with example?

Dependency injection (DI) is a technique widely used in programming and well suited to Android development. By following the principles of DI, you lay the groundwork for good app architecture. Implementing dependency injection provides you with the following advantages: Reusability of code.

Can you give few examples of dependency injection?

Two popular dependency injection frameworks are Spring and Google Guice. The usage of the Spring framework for dependency injection is described in Dependency Injection with the Spring Framework - Tutorial. Also Eclipse RCP is using dependency injection.


1 Answers

As a general rule, it's more object-oriented to pass around objects that encapsulate concepts than passing around strings. That said, there are many cases (particularly when it comes to UI) when you need to translate sparse data (such as strings) to proper Domain Objects.

As an example, you need to translate user input in form of a string into an ISoda instance.

The standard, loosely coupled way of doing this is by employing an Abstract Factory. Define it like this:

public interface ISodaFactory
{
    ISoda Create(string input);
}

Your consumer can now take a dependency on ISodaFactory and use it, like this:

public class SodaConsumer
{
    private readonly ISodaFactory sodaFactory;

    public SodaConsumer(ISodaFactory sodaFactory)
    {
        if (sodaFactory == null)
        {
            throw new ArgumentNullException(sodaFactory);
        }

        this.sodaFactory = sodaFactory;
    }

    public void DrinkSoda(string input)   
    {   
        ISoda soda = GetSoda(input);   
        soda.Drink();   
    }

    private ISoda GetSoda(input)
    {
        return this.sodaFactory.Create(input);
    }
}

Notice how the combination of the Guard Clause and the readonly keyword guarantees the SodaConsumer class' invariants, which lets you use the dependency without worrying that it might be null.

like image 179
Mark Seemann Avatar answered Sep 30 '22 12:09

Mark Seemann