4
votes

Does Dependency Injection violate the Separation of Concerns as it pertains to an n-tier architecture?

Suppose you have the following projects:

MyApp.Data
MyApp.Business
MyApp.Web

If I were to use DI to tell the Business Layer which Data Context to use, wouldn't this violate SoC? This would mean the UI (MyApp.Web) would have to have knowledge of the Data Access Layer (MyApp.Data) to tell the Business Layer (MyApp.Business) which context to use, right?

public class WebForm {
    public void Save(Object dto) {
        BusinessObject bo = new BusinessObject(Data.MyDataContext);
        bo.ValidateAndSave(dto);
    }
}

I always thought, in an n-tier architecture, each tier should only have knowledge of the next tier (UI to Business, Business to Data). Is this not really a big deal?

2

2 Answers

4
votes

In general, you're correct. However, Dependency Injection tends to be thought of as "configuration" rather than part of the Presentation Layer (even though it often typically does live there). If your UI components are designed to not know about the data layer, then this is what really matters.

If you are designing a testable system, then the business and data layers should be independent of the UI, but something has to configure them. You could create yet another layer, called MyApp.Configuration that does all this, but most people find this to be over-engineering.

The important thing is whether your components are well designed, not whether the UI has some configuration knowledge of the other layers.

It's really no different from having app settings in your Web.Config. After all, unless your using a service oriented architecture, everything is running on the same computer in the same process anyways. And if you are using an SoA, then you would configure the individual parts on their respective servers.

4
votes

No, it does not violate the SoC, in fact it encourages it.

The problem is that in your example you are not using DI, at least in the UI. You are letting the WebForm explicitly build the objects it needs, instead of getting those dependencies injected.

The main idea is to have a central bootstrapper in an app that creates the root object, which gets it dependencies which in turn are constructed from other dependencies and so on. Given that is such a pain to do manually, you rely on DI containers that do that automatically using conventions or via configuration, or both.

So in your example, you would have the WebForm be constructed using a DI container and you would specify dependencies to, say, an IBusinessObject that would in turn depend on the DataContext to do things with those entities and create them from dto's. Then in that Save method you would use that by using the instance that was injected from outside, either manually or via a container, but always in some root point in the app lifecycle