-1

I'm trying to start adding some tests to my code. Please take it easy on me cause i'm still new to this stuffs.

As far as i understand dependency inversion, all the dependencies will be place inside a class constructor and they must be an Interface so that we can easily fake it. By following this rule i may end up having a login class like this.

public class Login
{ 
    string _username;
    string _password;
    IUserRepository _userRepository;
    public Login(string username, string password, IUserRepository userRepository)
    {
        this._username=username;
        this._password=password;
        this._userRepository=userRepository;
    }
}

public interface IUserRepository 
{ 

}

This is contrary to how i understand classes will be. I do believe that users of your code need to know nothing about its internal workings. All they need to know is how to instantiate and use the object. In short, provide them a way to get there but hide the details. So to sum it up, having the IUserRepository inside a constructor just made my code more confusing to some users of my class. Please enlighten me on this so that i won't make any more mistakes down the road.

Regards,

  • 1
    Why do you have username and passoword in constructor? – Euphoric Oct 30 '17 at 5:22
  • say i will do a login base on those username and password, i will then use the repository to query the database if the credentials are correct. – Denden Oct 30 '17 at 5:29
  • Why not use them as parameters into separate DoLogin method? – Euphoric Oct 30 '17 at 5:30
  • some other methods may use the username and password, say i have a encryption method as well to encrypt those, i won't be needing to have a parameter for it. – Denden Oct 30 '17 at 5:33
  • Do yourself a favor, and read this book, the first few chapters will completely explain what DI is: amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501 – Eternal21 Oct 30 '17 at 11:52
1

I think one core thing to understand is that in DI'd code, creation of an object and it's use happen in two drastically separated phases or contexts.

In the first phase, right after the start of the program, DI container is used to build an object graph. This means calling constructors of classes and passing in dependencies created the same way. Only known information, that can affect what objects are built, at this point is probably some kind of configuration. So there is no user-supplied data, like name and password in your example.

After this phase is done, some "entry" object is called and the whole thing starts executing code that interacts with user/the world. But this time, majority of calls should be method calls and creation of new objects within initially object graph should be rare-ish.

But it is not impossible to create new class while program is running. To make sure user doesn't need to know about dependencies of class it is trying to create an AbstractFactory is used. For your code, the abstract factory would look like this :

public interface ILoginFactory
{
    Login Create(string name, string password);
}

public class LoginFactory : ILoginFactory
{
    private readonly IUserRepository _userRepo;
    public LoginFactory(IUserRepository userRepo)
    {
        _userRepo = userRepo;
    }

    public Login Create(string name, string password)
    {
        return new Login(name, password, _userRepo);
    }
}

This way, the one who creates new Login class has no need to know of it's transitive dependency on IUserRepository.

  • cool, i will read about the abstract factory. Thanks bud. – Denden Oct 30 '17 at 5:50

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.