Search code examples
c#dependency-injectiondomain-driven-designdependency-inversion

Data Layer call and implementing DI


I'm learning how to implement DI in a 3 layers architecture, but I'm not quite sure if what I have implemented is actually a DI or some sort of mud abomination. The code works in the sense that obviously the DBWriter gets reached but I'm wondering if what I did is breaking the entire DDD design or that's just how it works.

The presentation Layer depends on the data layer for the sole purpose of DI. Is that a wrong approach?

Dependencies diagram (I'm really sorry for the mspaint job): Diagram

I want my logic layer to handle everything and I do this through an interface.

UI code:

   private void createUsrBtn_Click(object sender, EventArgs e)
    {
        dbWriter.WriteUserToDB(new User(..user stuff..));
    }

Is it correct to call here the datalayer, from the UI? As far as I've understood (and I'm not quite sure if I did), I can call the data layer from the presentation Layer as long as I'm going through an abstraction in the logic layer, is that correct?

Logic layer UserManager class:

public interface IUserManager {
    void WriteUserToDB(User user);
   
}
public class UserManager : IUserManager 
{
   public void WriteUserToDB(User user)
    {
    }
  
}

Here am I actually supposed to write the method and that's it?

DataLayer DBWriter class:

 public class DBWriter : IUserManager
{ 
    public void WriteUserToDB(User user)
    {... sql stuff ...
    }
}

I'm sorry for the confusion, I have to refactor my entire application to include DI (I have used a presentation -> logic layer -> data layer up until now with DTO's) and I'm finding it quite hard to wrap my head around these concepts.

I'm sorry if the question has already been asked or if it is redundant.

Thanks in advance


Solution

  • In general, the UI layer should not communicate directly with the data layer. The idea is to keep the UI as thin as possible(*), and have all the work done by the logic layer. That gives a few benefits, most notably including...

    • You have all the important code in the logic layer, where it can be tested easily (assuming you set up your dependencies correctly of course). Testing UI code is hard and often fragile

    • You can change the UI without needing to change any of the logic code.

    Yes, this sometimes means that the code in the logic layer does nothing more than pass the execution directly through to the data layer, but that's a small price to pay for the benefits of keeping the layers separate.

    (*) In practice, it's often impossible to avoid some code in the UI, but as long as the code is only responsible for manipulating the UI, not doing any business logic or modifying any data, then it's OK.