-3

I am trying to decouple a dependency from Book Class to BookStorage, but got confused how to do this right. Can someone tell me how to decouple this correctly? Here is my code:

    public interface IBook
    {
        string Execute(Guid bookId);
    }

    public class Book : IBook
    {
        public string Execute(Guid bookId)
        {
            var Id = 2;
            var storage = new BookStorage(Id);// Decouple this dependency? 

            // Get data
            var response = storage.GetBookData("GOF");
            return response;
        }
    }


    public interface IBookStorage
    {
        string GetBookData(string name);
    }


    public class BookStorage : IBookStorage
    {
        public BookStorage(int id)
        {

        }
        public string GetBookData(string bookName)
        {
            throw new NotImplementedException();
        }
    }
1
  • Perhaps a book does not store itself. An entity (book) typically does not implement an interface either. Ideally an entity should not have any dependencies, if it must consider using double dispatch (pass in a IBookStorage on your Exceute method). In this case why not turn it around, pass the Book instance to a Bookstorage? Book.Execute is semantically very poor... What does it mean to execute a book? Can one execute a book?
    – Joppe
    Jan 27, 2017 at 1:44

1 Answer 1

6

The point of dependency-injection is to not create the dependencies within your class, but to delegate that task to the calling code. So instead of creating a new instance of BookStorage within your Execute-method pass it as parameter, using the IBookStorage interface.

public string Execute(Guid bookId, IBookStorage bookStorage)
{
    var Id = 2;

    // Get data
    var response = bookStorage.GetBookData("GOF");
    return response;
}

This would change the interface also. If you don´t want to do this you can also pass the dependency via constructor-injection:

var book = new Book(new BookStorage("GOF"));

which will need this constructor

class Book
{
    private readonly IBookStorage storage;
    public Book(IBookStorage storage)
    {
        this.storage = storage;
    }
}

EDIT: To improve this desing further you could resolve this dependency using a dependency-injection-container like NInject or similar. But this goes to far for a question here on SO.

4
  • 1
    This doesn't break the dependency on a concrete instance of BookStorage, it just moves the coupling into another class. Personally I would abstract BookStorage to an interface and inject an IBookStorage interface into Book via a container like Unity or Ninject. I will say your example illustrates DI without all the plumbing involved in setting up a container though.
    – dparsons
    Jan 26, 2017 at 9:49
  • @dparsons Sure, this is true. For the sake of simplicity I omitted DI-container. However if BookStorage is just a DTO this won´t make so much sence though.
    – HimBromBeere
    Jan 26, 2017 at 9:50
  • The usage of an interface is essential for breaking the dependency, so I took the freedom and made some minor changes to your answer to correct that. Note this has nothing to do with using a DI container.
    – Doc Brown
    Jan 26, 2017 at 14:35
  • What should I do if my methods are not abstracted properly? (E.g I have tons of classes with no interfaces). Do I implement poor man's DI? Dec 19, 2017 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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