What is the purpose of IOC Containers? The combined reasons for it can be simplified to the following:

When using OOP/SOLID Development principles, Dependency Injection gets messy. Either you have the top-level entry points managing dependencies for multiple levels below themselves and passing dependencies recursively through construction, or you have somewhat duplicate code in factory/builder patterns and interfaces that build dependencies as you need them.

There is no OOP/SOLID way to perform this AND have super pretty code.

If that previous statement is true, then how do IOC Containers do it? As far as I know, they aren’t employing some unknown technique that can’t be done with manual D.I. So the only explination is that IOC Containers break OOP/SOLID Principles by using static objects private accessors.

Do IOC Containers break the following principles behind the scenes? This is the real question since I have a good understanding, but have a feeling somebody else has a better understanding:

  1. Scope control. Scope is the reason for nearly every decision I make on my code design. Block, Local, Module, Static/Global. Scope should be very explicit, as much at block-level and as few at Static as possible. You should see declarations, instantiations, and lifecycle endings. I trust the language and GC to manage scope as long as I’m explicit with it. In my research I’ve found that IOC Containers set up most or all dependencies as Static and control them through some AOP implementation behind the scenes. So nothing is transparent.
  2. Encapsulation. What is the purpose of encapsulation? Why should we keep private members so? For practical reasons it is so implementors of our API can’t break the implementation by changing the state (which should be managed by the owner class). But also, for security reasons, it’s so injections can’t occur that overtake our member states and bypass validation and class control. So anything (Mocking frameworks or IOC frameworks) that somehow injects code before compile time to allow external access to private members is pretty huge.
  3. Single Responsibility Principle. On the surface, IOC Containers seem to make things cleaner. But imagine how you would accomplish the same thing without the helper frameworks. You would have constructors with a dozen or so dependencies being passed in. That doesn’t mean cover it up with IOC Containers, it is a good thing! It’s a sign to re-factor your code and follow SRP.
  4. Open/Closed. Just like SRP isn’t Class-Only (I apply SRP down to single-responsibility lines, let alone methods). Open/Closed is not just a high level theory to not alter the code of a class. It’s a practice of understanding the configuration of your program and having control over what gets altered and what gets extended. IOC Containers can change the way your classes work altogether partially because:

    • a. The main code isn’t making the determination of switching out
      dependencies, the framework configuration is.

    • b. The scope could be altered at a time that isn’t controlled by the
      calling members, it is instead determined externally by a static
      framework.

So the configuration of the class isn’t really closed is it, it alters itself based on the configuration of a third party tool.

The reason this is a question is because I am not necessarily a master of all IOC Containers. And while the idea of an IOC Container is nice, they appear to just be a façade that covers up poor implementation. But in order to accomplish external Scope control, Private member access, and Lazy loading, a lot of non-trivial questionable things have to go on. AOP is great, but the way it is accomplished through IOC Containers is also questionable.

I can trust C# and the .NET GC to do what I expect it to. But I can’t put that same trust in a third party tool that is altering my compiled code to perform workarounds to things I wouldn’t be able to do manually.

E.G.: Entity Framework and other ORMs create strongly Typed objects and map them to database entities, as well as provide boiler-plate basic functionality to perform CRUD. Anybody could build their own ORM and continue to follow OOP/SOLID Principles manually. But those frameworks help us so we don’t have to re-invent the wheel every time. Whereas IOC Containers, it seems, help us purposely work around OOP/SOLID Principles and cover it up.

12

I’ll go through your points numerically, but first, there’s something you should be very careful of: don’t conflate how a consumer uses a library with how the library is implemented. Good examples of this are Entity Framework (which you yourself cite as a good library) and ASP.NET’s MVC. Both of these do an awful lot under the hood with, for example, reflection, which would absolutely not be considered good design if you spread it through day-to-day code.

These libraries are absolutely not “transparent” in how they work, or what they’re doing behind-the-scenes. But that’s not a detriment, because they support good programming principles in their consumers. So whenever you talk about a library like this, remember that as a consumer of a library, it’s not your job to worry about its implementation or maintenance. You should only worry about how it helps or hinders the code you write which uses the library. Don’t conflate these concepts!

So, to go through by point:

  1. Immediately we reach what I can only assume is an example of the above. You say that IOC containers set up most dependencies as static. Well, perhaps some implementation detail of how they work includes static storage (though given that they tend to have an instance of an object like Ninject’s IKernel as their core storage, I doubt even that). But this is not your concern!

    Actually, an IoC container is just as explicit with scope as poor man’s dependency injection. (I’m going to keep comparing IoC containers to poor man’s DI because comparing them to no DI at all would be unfair and confusing. And, to be clear, I’m not using “poor man’s DI” as a pejorative.)

    In poor man’s DI, you’d instantiate a dependency manually, then inject it into the class that needs it. At the point where you construct the dependency, you’d choose what to do with it- store it in a locally scoped variable, a class variable, a static variable, don’t store it at all, whatever. You could pass the same instance into lots of classes, or you could create a new one for each class. Whatever. The point is, to see which is happening, you look to the point- probably near the application root- where the dependency is created.

    Now what about an IoC container? Well, you do exactly the same! Again, going by Ninject terminology, you look at where the binding is set up, and find whether it says something like InTransientScope, InSingletonScope, or whatever. If anything this is potentially clearer, because you have code right there declaring its scope, rather than having to look through a method to track what happens to some object (an object may be scoped to a block, but is it used multiple times in that block or just once, for example). So maybe you’re repelled by the idea of having to use a feature on the IoC container rather than a raw language feature to dictate scope, but as long as you trust your IoC library- which you should!- there’s no real disadvantage to it.

  2. I still don’t really know what you’re talking about here. Do IoC containers look at private properties as part of their internal implementation? I don’t know why they would, but again, if they do, it’s not your concern how a library you’re using is implemented.

    Or, maybe, they expose a capability like injecting into private setters? Honestly I’ve never encountered this, and I’m dubious about whether this really is a common feature. But even if it’s there, it’s a simple case of a tool that can be misused. Remember, even without an IoC container, it’s but a few lines of Reflection code to access and modify a private property. It’s something you should almost never do, but that doesn’t mean .NET is bad for exposing the capability. If somebody so obviously and wildly misuses a tool, it’s the person’s fault, not the tool’s.

  3. The ultimate point here is similar to 2. The vast majority of the time, IoC containers DO use the constructor! Setter injection is offered for very specific circumstances where, for particular reasons, constructor injection can’t be used. Anybody who uses setter injection all the time to cover up how many dependencies are being passed in is massively absuing the tool. That’s NOT the tool’s fault, it’s theirs.

    Now, if this was a really easy mistake to innocently make, and one that IoC containers encourage, then okay, maybe you’d have a point. It’d be like making every member of my class public then blaming other people when they modify things they shouldn’t, right? But anybody who uses setter injection to cover up violations of SRP is either willfully ignoring or completely ignorant of basic design principles. It’s unreasonable to lay the blame for this at the IoC container.

    That’s especially true because it’s also something you can do just as easily with poor man’s DI:

    var myObject 
       = new MyTerriblyLargeObject { DependencyA = new Thing(), DependencyB = new Widget(), Dependency C = new Repository(), ... };
    

    So really, this worry seems completely orthogonal to whether or not an IoC container is used.

  4. Changing how your classes work together is not a violation of OCP. If it was, then all dependency inversion would be encouraging a violation of OCP. If this was the case, they wouldn’t both be in the same SOLID acronym!

    Furthermore, neither points a) nor b) come close to having anything to do with OCP. I don’t even know how to answer these with respect to OCP.

    The only thing I can guess is that you think OCP is something to do with behaviour not being altered at runtime, or about where in the code the lifecycle of dependencies is controlled from. It’s not. OCP is about not having to modify existing code when requirements are added or change. It’s all about writing code, not about how code you’ve already written is glued together (though, of course, loose coupling is an important part of achieving OCP).

And one final thing you say:

But I can’t put that same trust in a third party tool that is altering my compiled code to perform workarounds to things I wouldn’t be able to do manually.

Yes, you can. There is absolutely no reason for you to think that these tools- relied on by vast numbers of projects- are any more buggy or prone to unexpected behaviour than any other third-party library.

Addendum

I just noticed your intro paragraphs could use some addressing too. You sardonically say that IoC containers “aren’t employing some secret technique we’ve never heard of” to avoid messy, duplication-prone code to build a dependency graph. And you’re quite right, what they’re doing is actually addressing these things with the same basic techniques as we programmers always do.

Let me talk you through a hypothetical scenario. You, as a programmer, put together a large application, and at the entry point, where you’re constructing your object graph, you notice you have quite messy code. There are quite a few classes that are used again and again, and every time you build one of those you have to build the whole chain of dependencies under them again. Plus you find you don’t have any expressive way of declaring or controlling the lifecycle of dependencies, except with custom code for each one. Your code is unstructured and full of repetition. This is the messiness you talk about in your intro paragraph.

So first, you start to refactor a bit- where some repeated code is structured enough you pull it out into helper methods, and so on. But then you start to think- is this a problem that I could perhaps tackle in a general sense, one that isn’t specific to this particular project but could help you in all your future projects?

So you sit down, and think about it, and decide that there should be a class that can resolve dependencies. And you sketch out what public methods it would need:

void Bind(Type interfaceType, Type concreteType, bool singleton);
T Resolve<T>();

Bind says “where you see a constructor argument of type interfaceType, pass in an instance of concreteType“. The additional singleton parameter says whether to use the same instance of concreteType each time, or always make a new one.

Resolve will simply try to construct T with any constructor it can find whose arguments are all of types which have previously been bound. It can also call itself recursively to resolve the dependencies all the way down. If it can’t resolve an instance because not everything has been bound, it throws an exception.

You can try implementing this yourself, and you’ll find you need a bit of reflection, and some caching for the bindings where singleton is true, but certainly nothing drastic or horrifying. And once you’re done- voila, you have the core of your very own IoC container! Is it really that scary? The only real difference between this and Ninject or StructureMap or Castle Windsor or whatever one you prefer is that those have a lot more functionality to cover the (many!) use cases where this basic version wouldn’t be sufficient. But at its heart, what you have there is the essence of an IoC container.

5

Don’t IOC containers break a lot of these principles?

In theory? No. IoC containers are just a tool. You can have objects that have a single responsibility, well separated interfaces, can’t have their behavior modified once written, etc.

In practice? Absolutely.

I mean, I’ve heard not a few programmers say that they use IoC containers specifically to allow you to use some configuration to change the behavior of the system – violating the Open/Closed Principle. There used to be jokes made about coding in XML because 90% of their job was fixing Spring configuration. And you’re certainly correct that hiding the dependencies (that admittedly, not all IoC containers do) is a quick and easy way to make highly coupled and very fragile code.

Let’s look at it a different way. Let’s consider a very basic class that has a single, basic dependency. It depends on an Action, a delegate or functor that takes no parameters and returns void. What is this class’ responsibility? You can’t tell. I could name that dependency something clear like CleanUpAction which makes you think it does what you want it do. As soon as IoC comes into play it becomes anything. Anyone can go into the configuration and modify your software to do pretty much arbitrary things.

“How is that different from passing in an Action to the constructor?” you ask. It’s different because you can’t change what’s being passed into the constructor once the software is deployed (or at runtime!). It’s different because your unit tests (or your consumers’ unit tests) have covered the scenarios where the delegate is passed into the constructor.

“But that’s a bogus example! My stuff doesn’t allow changing behavior!” you exclaim. Sorry to tell you, but it does. Unless the interface you’re injecting is just data. And your interface isn’t just data, because if it were just data you’d be building a simple object and using that. As soon as you have a virtual method in your injection point, the contract of your class using IoC is “I can do anything“.

“How is that any different from using scripting to drive things? That’s perfectly fine to do.” some of you ask. It isn’t different. From a program design perspective, there’s no difference. You’re calling out of your program to run arbitrary code. And sure, that’s been done in games for ages. It’s done in tons of systems administration tools. Is it OOP? Not really.

There’s no excuse for their current ubiquity. IoC containers have one solid purpose – to glue together your dependencies when you have so many combinations of them, or they shift so rapidly that it is impractical to make those dependencies explicit. So very few businesses actually fit that scenario though.

18

Does using an IoC container necessarily violate OOP/SOLID principles? No.

Can you use IoC containers in such a way that they violate OOP/SOLID principles? Yes.

IoC containers are just frameworks for managing dependencies in your application.

You stated Lazy injections, property setters, and a few other features I haven’t yet felt the need to use, which I agree with can give you a less than optimal design. However, the usages of these specific features are due to limitations in the technology you’re implementing IoC containers in.

For example, ASP.NET WebForms, you are required to use property injection as it’s not possible to instantiate a Page. This is understandable because WebForms was never designed with strict OOP paradigms in mind.

ASP.NET MVC on the other hand, it’s entirely possible to use an IoC container using the very OOP/SOLID friendly constructor injection.

In this scenario (using constructor injection), I believe it promotes SOLID principles for the following reasons:

  • Single Responsibility Principle – Having many smaller classes allows these classes to be very specific and have one reason for existing. Using an IoC container makes organizing them much easier.

  • Open/Closed – This is where using an IoC container really shines, you can extend the functionality of a class by way of injecting different dependencies. Having dependencies that you inject lets you modify the behavior of that class. A good example is changing the class that you’re injecting by writing a decorator to say add caching or logging. You can completely change implementations of your dependencies if written in an appropriate level of abstraction.

  • Liskov Substitution Principle – Not really relevant

  • Interface Segregation Principle – You can assign multiple interfaces to a single concrete time if you want, any IoC container worth a grain of salt will easily do this.

  • Dependency Inversion – IoC containers let you do dependency inversion easily.

You define a bunch of dependencies and declare the relationships and scopes, and bing bang boom: you magically have some addon that alters your code or I.L. at some point and makes things work. That isn’t explicit or transparent.

It is both explicit and transparent, you need to tell your IoC container how to wire up dependencies and how to manage object lifetimes. This can be either by convention, by configuration files, or by code written in your system’s main applications.

I agree that when I write or read code using IOC containers, it gets rid of some slightly inelegant code.

This is the whole reason for OOP/SOLID, to make systems manageable. Using an IoC container is inline with that goal.

The writer of that class says, “If we didn’t use an IOC Container, the Constructor would have a dozen parameters!!! That’s horrible!”

A class with 12 dependencies is probably an SRP violation no matter what context you’re using it in.

5

Don’t IOC containers both break, and allow coders to break, a lot of OOP/SOLID principles?

The static keyword in C# allows developers to break a lot of OOP/SOLID principles but it’s still a valid tool in the right circumstances.

IoC containers allow for well structured code and reduce the cognitive burden on developers. An IoC container can be used to make following SOLID principles much easier. It can be misused, sure, but if we excluded the use of any tool that can be misused we would have to give up programming altogether.

So while this rant raises some valid points about poorly written code, it is not exactly a question and it is not exactly useful.

5

I see multiple mistakes and misunderstandings in your question. The first major one is that you are missing distinction between property/field injection, constructor injection and service locator. There has been lots of discussion (eg. flamewars) about which is the right way to do things. In your question, you seem to assume only property injection and ignore constructor injection.

Second thing is that you assume that IoC containers somehow affect design of your code. They don’t, or at least, it should not be necessary to change the design of your code if you use IoC. Your problems with classes with many constructors is case of IoC hiding real problems with your code (most possibly a class that has breaks SRP) and hidden dependencies are one of the reasons why people discourage use of property injection and service locator.

I don’t understand where the problem with open-closed principle comes into this, so I won’t comment on it. But you are missing one part of SOLID, that has major influence on this : Dependency Inversion principle. If you follow DIP, you will find out, that inverting a dependency introduces an abstraction, whose implementation needs to be resolved when an instance of class is created. With this approach, you will end up with lots of classes, that require multiple interfaces to be realized and provided at construction to function properly. If you were to then provide those dependencies by hand, you would have to do lots of additional work. IoC containers make it easier to do this work and even allow you to change it without having to recompile the program. You are probably confusion Open/Closed principle with Dependency Inversion principle in your question.

So, the answer to your question is no. IoC containers don’t break OOP design principles. Quite contrary, they solve problems caused by following SOLID principles (especially Dependency-Inversion principle).

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật