6 ms·
The inverse of IoC is Control
- galaktor 14y agoYounger IoC frameworks aim for configuration in code, allowing for a much more dynamic usage. Examples (c#) * Autofac * Ninject
- jakubholynet 14y agoWe use Guice which also allows that. But that doesn't address some of the key points he makes, such as - runtime x compile time wiring - wiring is based on types so injecting differently set up instances is difficult (we have a hell of Providers and different annotations to pick the right kind of instance injected) - non-transparency of the wiring process (sice it is performed by the magical IoC container) I agree with a lot of what he writes. At the same time I believe there are cases where I would appreciate some kind of automation for wiring (f.ex. if I want a fresh instance for each session or request). And there are certainly cases when runtime wiring - as in the mentioned case of plugins - is useful.
- steverb 14y agoNinject actually does allow you to wire up with criteria beyond type based on the context into which the object is being injected.
- galaktor 14y agoI'm mostly familiar with Autofac, and there are many other ways to wire your app other than by type * by interface * by enum * by parametrized constructor (Func<..>) * by (arbitrary) string * per process / per thread / per whatnot
- unwind 14y agoI'm pretty sure IoC here refers to "inversion of control" (http://en.wikipedia.org/wiki/Inversion_of_control http://en.wikipedia.org/wiki/Inversion_of_control). I had to look it up though, I find it a bit silly that even the original article doesn't spell this out in the first sentence. I guess it's super-obvious from context (and the claim of the title) so I guess I'm just not very smart, today. Oops.
- roam 14y agoDon't use IoC if you don't need it, but I'll explain why we need it in our case: some customers require different implementations. That's where the DI part comes from -- to enable us to load a different dependency based on the customer. Now, you could provide a different bootstrapper class per customer or start building a mega class with a lot of ifs-and-buts(elses), or you specify this kind of stuff in a configuration file. We opt for configuration files. We opt for IDEs that can interpret Spring configuration files which means typos or incorrect dependencies do show up. This allows us to swap out implementations in case shit goes down without having to recompile, connect over a VPN to a remote desktop and hop through a few more hoops to get our class file on the other side. If you're not running your own apps on infrastructure you control (we should be so lucky), you have to take this sort of stuff into account. I'd love to be able to say "This is how stuff's set up. Deal with it." (And when shit goes down, it is usually not at the place you were expecting it to happen, which means all kinds of configuration options for your bootstrapper would probably still fall short.)
- zupatol 14y agoI agree with using IoC for different implementations, but I'm puzzled by those who want to use it everywhere, because it supposedly makes the code easier to test. Guice is a nice IoC framework, but look at what they say on their website: "Think of Guice's @Inject as the new new." http://code.google.com/p/google-guice/ http://code.google.com/p/google-guice/
- nkohari 14y agoTesting is kind of a side effect. When you design your code with IoC in mind, you naturally will create more logical separations and avoid tight coupling -- which in turn will make your code easier to test. (Source: I wrote Ninject. :)
- edwinnathaniel 14y agoIf your code has a hard-static dependencies to web-service call, you can't test it easily (and repeatedly). Especially when the actual service is down. If your code has a hard-static dependencies to DB call, you now have excuses not to write test against it because "it's hard to prepare the environment to do such things." Not all projects are as small as a Todo-List written using Rails. Medium-to-Large size projects with large DB schemas exist in which it will take hours to run your Rails tests: "testing-my-active-record-models-as-unit-tests"
- _pmf_ 14y agoI found that a sweet spot between wiring-by-code and wiring-by-container-and-configuration-dsl is using a dynamic language for wiring (say, Rhino, which is very lightweigth): you have the flexibility of wiring-by-code and can easily change the configuration purely by deployment (without recompiling anything)
- RyanZAG 14y agoJust curious, but what's wrong with recompiling? If you make a typo in your Rhino file on production, your whole app is now failing. Surely it makes more sense to just take the 5 minutes to recompile (or hopefully 30 minutes and test it out in dev first)? I don't really understand what problem using the dynamic language is trying to solve there, and you've just added in a whole new branch of different code that won't work with static analysis, and will need to be maintained in addition to your normal code.
- _pmf_ 14y agoIn my case, I have an Eclipse-based product (toolchain for embedded development) that must be reconfigured per client or even per project (on site); i.e. it is more about dynamically creating very specific variants of a product. Using client/project-specific plugins would be the alternative for me, but this has much more overhead.
- RyanZAG 14y agoAre you not packaging un-used code into your embedded binaries then? You'd also have to manually test the reconfigured client before deploying it, I think. Seems better to make an automated build system off a database of configurations - a simple sql table with the different settings that could automatically build versions for all clients. You'd get static compile time checking of each build, and it would allow for easily running automated tests against each client's version. So you'd end up with no un-used code, a database of client configuations, and static compile time checking. Seems win-win. Sorry for 'assuming your problems', feel free to ignore. Interesting situation though.
- jt2190 14y agoAccording to Martin Fowler [1], Inversion of Control is an alternative to using a Service Locator: > In the Java community there's been a rush of lightweight > containers that help to assemble components from > different projects into a cohesive application. > Underlying these containers is a common pattern to how > they perform the wiring, a concept they refer under the > very generic name of "Inversion of Control". In this > article I dig into how this pattern works... and > contrast it with the Service Locator alternative. The > choice between them is less important than the principle > of separating configuration from use. [1] http://martinfowler.com/articles/injection.html http://martinfowler.com/articles/injection.html (edit: Also, the Spring Framework has had alternatives to XML configuration for years: http://www.ibm.com/developerworks/webservices/library/ws-springjava/index.html http://www.ibm.com/developerworks/webservices/library/ws-spr...)
- gertgoeman 14y agoI think the title's a bit misleading though... This guy is obviously talking about dependency injection. Things like callbacks, observers, events, ... are also types of IoC.
- FreshCode 14y agoDo I understand correctly that the writer's main concern is that DI configuration is done in XML files, or that configuration takes place at run-time, instead of compile-time?
- pretoriusB 14y agoHis main concern is that you lose static checks by the compiler, you lose clarity in the code, you lose dynamic configuration of objects AND you have to use yet another DLL (and a horrible one at that: XML).
- filpen 14y agoI also don't get what the author's issues are. Half of the article seems to be against XML configuration, and I don't come from a Java background but it seems that there are containers for Java that do not necessarily require an XML configuration, or is it not the case?
- twistedpair 14y agoHmm... guess the author is not familiar with @Autowired, @Resource, @Component... etc. You don't need XML fun. And, he complains about 2 of the same type... behold @Autowired(name="bar"), @Autowired(name="bah"). Miracle? No, just DI.
- bborud 14y agoMost places I have seen DI frameworks being used, they solve a problem the programmer shouldn't be having in the first place.
- filpen 14y agoInteresting. Do you mind expanding on this? What problems were they trying to solve?
- bborud 14y agoI don't buy that wiring up code explicitly in plain old java without the help of an injection framework is as painful as some people seem to think -- and if it really is: I suspect the reason is bad design or that they just haven't given the problem much thought. That happens. If people need the assistance of a framework to wire up their application, it is probably because the API design sucks ass and there are too many moving parts the programmer is forced to pay attention to. (And when I say API design: all code design is about APIs -- every time you create a class or an interface you are creating an API of some sort). Good APIs hide and abstract. And good implementations take care of things you don't need to see or know. And I say if, because most of the time, applications are not so complicated that you need help to manage wiring them up. Most of the projects I have worked on the past 15 years can usually be wired up in less than 40-50 lines in a Main.java. I have worked on some projects that needed considerably more, but interestingly, managing that code was never a problem. Explicit wiring you can read from start to finish beats vague declarative shit that you may be able to figure out if you pay close attention.
- filpen 14y agoThank you for clearing that up, much appreciated. I also noticed that most of the time the container tends to be used as a Service Locator indiscriminately around the code base, which tends to create more problems than it solves. On the other hand, I think it is a good refactoring step if your plan is to eventually move all the composition logic at the entry point of the application. Coming from .NET, I tend to do the wiring as close as possible to the entry point as well, but I still use a container because it makes object lifecycle management much easier, and with convention over configuration it is trivial to associate interfaces to implementations: this not only reduces wiring up code for complex applications to a few lines, it also makes the rest of the application container-agnostic, which is quite cool.
- martinced 14y agoIoC is an usual technique and buzzword from the C#/Java + XML + ORM + SQL hell. There are many programmers working in the Real-World [TM], powering great apps and webapps, using saner technologies who have never heard of the term. I wrote my own IoC container (a clone of picocontainer IIRC) to see what the fuss was about when the term started to become fashionable. No big deal. It can help reproduce various states (for examples in testing environments) to more easily test your app. Sure people will say: "You need an IoC container to do DI, what you're talking about is DI, not IoC". But, fundamentally, it is once again related to "state" and the difficulty to recreate a state in {dev,pre-prod,prod,whatever}. So it's once again a "solution" missing the bigger picture. Sure, people stuck in the "stateful OO" mindset will love IoC and, honestly, if you're stuck in such an hell IoC can be useful. With the caveat that IoC makes it much harder to reason about what's going on when some shit hits the fan. "Every problem can be solved with another layer of abstraction, except the problem of too many layers of abstraction" But there's light at the end of the tunnel. There are other ways to design great apps. And to make you feel even better: being "smart" as nothing to do with knowing every technology out there ; )
- SideburnsOfDoom 14y agoAre you saying that IoC implies that you also must use XML and an ORM? That really isn't so.
- wcoenen 14y agoIt turns out that there is a problem with instantiating everything manually in main if you have a lot of components: it becomes non-trivial to figure out the order of instantiation. This problem will typically surface whenever you add a dependency between existing components. If the dependency is currently instantiated after the changed component, it will have to be moved up so it is instantiated earlier. But then it turns out the dependencies of that component also need to be moved up etc. To deal with this you then have to calculate a "dependency rank" for each component (i.e. 0 for components without dependencies, and x+1 for components where the max rank among the dependencies is x) just to figure out a new order that works. This problem doesn't exist if you use a dependency injection container with configuration in code, because the order of component registration is not important.
- mercurial 14y agoYeah, what you'd end up recreating is a directed graph of dependencies, and make it needlessly fragile. You don't need the big machinery for smaller projects, though. What I end up doing in Python is having builder methods in __init__.py which can instantiate objects from the package (possibly instantiating objects from sub-packages in the process), with any dependency not in the package or sub-packages being a parameter. You get some granularity in your dependency injection, you avoid magic and you don't need to use the builder methods if you don't want to. It may not scale to large class hierarchies, but for mid-size projects it's fine.
- michaelochurch 14y agoJava culture (IDE-dependence, AbstractFactoryVisitorFactory patterns, Maven and XML monstrosities) is hideous. It's based on the idea that reading code is a lost cause. You can no longer trust code, so you need all these wonky tool configurations to compensate for the fact that you're trying to make an army of inept programmers build something that is (unless it fails) going to become the next generation's legacy bloatbomb.
- factorialboy 14y agoIn our defense, have you tried reading Java code?
- michaelochurch 14y agoWait, people actually read Java code? I thought that's what IDEs were for. For a serious response, I've seen tons of Java code of varying quality. Most was worse than horrible, but I have seen well-written Java. The Java code for Clojure is excellent, for one example. Most corporate Java code is indistinguishable from profanity.
- edwinnathaniel 14y agoDitto with any other language (especially JavaScript...)
- twistedpair 14y agoI grant you that. I try to abide by everything in "Effective Java 2" but some of the code I come across in my daily work makes me ill. I wish I could say such code was uncommon, but someone will always try to use a hammer as a screwdriver if it still compiles.
- twistedpair 14y agoAlways love all the Java hate on ycomb. I'm not sure how a dynamically code hotswapping Ruby app with 10k classes and 1k domain objects works, but I suspect many of the same patterns emerge as have been solved in Java.
- deleted 14y ago[deleted]
- tkellogg 14y agoMaybe you should be using C#. As a community we fight hard to reject xml configuration, favoring type safe lambda expressions instead. Anything that ignores the type safe guarantees that C# offers quickly does. There was briefly a spring.net but it quickly died for this reason.
- SideburnsOfDoom 14y agoAgreed. Is the author's problem with IoC or with XML config? hard to tell, but they're really not the same thing. IoC containers in C# have rejected config in XML, in favour of config in code, using either generics and lambdas (e.g. register Component.For<IFoo>.ImplementedBy<Bar> ) or via scanning (e.g. AllTypes.FromAssembly(x).BasedOn<Foo>().WithService.FirstInterface() ). Spring.net was an exception and in comparison it really sucked. IoC Config in code is much better. But can't this be done in java too?
- mercurial 14y agoThat's what Guice does, and newer versions of Spring too (though I'm not sure if you can go full Java and drop the XML entirely).
- VexXtreme 14y agoI have found that in a lot of cases IoC ends up being completely misused and abused in really horrible ways. One of the more common antipatterns I encounter is creating an interface for every single thing in the application ("because hey, the implementation might change and it'll be easy to swap out"). No, if you're building a webshop or a task management application, abstracting and injecting your business logic or domain objects is as stupid as it gets. I always keep hearing this argument "but something will change". No, it won't. Is it really worth introducing all this boilerplate nonsense into the application just for the off chance of something changing at some point? And even if that happens, don't you think you're better off just doing whatever modifications are necessary vs. putting all this crap into your application? The only scenario where I've found IoC to make sense is when an application depends on a module and that module REALLY needs to be swapped out with another one. I once had that with a stock market analysis application that depended on X service for data feeds, but X service suddenly stopped working and I could just inject Y service instead without having to change anything else. But even in that case IoC container would've been redundant as plain old DI does the job just fine. That was the only thing in the application that I wrote that way because I didn't want to hard code an external dependency (that I have no control over) into my application. But what I keep encountering is the cargo cult approach to programming where IoC is done for the sake of IoC and everything is injected for the sake of being injected, with no rational explanation as to why. It's quite terrible really.
- specialist 14y ago> creating an interface for every single thing in the application Ditto turning everything into a "service" a la WSDL and now SOA. CORBA lives!
- nahname 14y agoIoC is automating the code required to wire up objects that are properly decomposed. When you spend a long time learning how to effectively work with static languages, a few things come out. Dependency inversion and composition. Where does this leave us? It often means we have classes that need one or more other objects when they are instantiated. This often results in chains of objects. For example, new Repository(new SessionFactory(new Configuration())) Writing that code is pretty painful. Rather than dealing with long chains of dependencies, manually wiring everything up. You define mappings and let an IoC container do it for you. Why not just wire everything up manually in static functions and be done with it? It is really hard to change static code and often impossible to test it in a language like Java/C#. There is almost nothing you can do to test a piece of code that calls out to User.find(1) in one of it's methods. Why are there no IoC practices in ruby? Primarily because the second point is no longer true (you can test everything easily). I still think there is merit in knowing the dependency chain rather than just calling User.find(1) and hoping that something somewhere conjures up a database connection and configures everything correctly, at the correct time. IoC is control and automation. Those are both powerful tools to any programmer.
- bborud 14y ago> new Repository(new SessionFactory(new Configuration())) > Writing that code is pretty painful. If you think you are making things less painful by obfuscating the code snippet above I would challenge you to think about what you are doing. The above is incredibly clear. There is no doubt what is happening and if you screw up the compiler will yell at you. If you obfuscate it through annotations and force readers of your code to try to reason about how the system will behave runtime, you have added exactly zero value. You have only degraded the readability and understandability of the system. A little extra typing never killed anyone.
- nahname 14y agoYou don't annotate anything. It simply becomes the following, ... public Repository(ISessionFactory factory) ... The repository never knows about IoC or where things come from. Nor should it.
- jhartmann 14y agoSure you have to use it where it makes sense, but IoC containers and frameworks like Spring can really make things easier. If you have to talk to anything complex (pick your messaging poison), need to keep transactions across these items, need to run under multiple different web containers and swap out configuration you are going to have some messy code to handle all of this sort of stuff. For enterprise integration problems I will pick Spring any day. For instance I can write a complex messaging bridge between two different messaging systems using nothing but some xml configuration. The mess of doing all the JNDI lookups, getting all my XA transactions right, handling firing messages after certain things happen all can be done without explicitly putting things all over the code. The beauty of IoC containers and AOP programming is that you can mix in a well tested piece of code across all your application with minimal effort. You can mixin authentication, transaction management, request cleanup, caching, etc. without making major changes to your app. I know there are many people here that might crucify me for the opinion but I call bullshit. They just have never had to work on something sufficiently complex where IoC and frameworks like Spring can become a huge time savings. Obviously with any tool you have to make sure you don't chainsaw off your leg, and its really stupid to do certain things with any tool. The black magick of aop and IoC can make reasoning about things a little harder, but the shear power of the tool makes solving hard problems in complex applications tractable. Try auditing transaction management in an application with 10 thousand tables written by hundreds of people of various experience levels. Or just use spring transactions and inject the well tested behavior across the entire application.
- InvisibleCities 14y agoFirst of all, the author doesn't hate IoC and Containers, he hates XML registration (with good reason). I can't say anything about Java, but in C#, when you use modern IoC frameworks like StructureMap and AutoFac, all registration of components takes place in code, using generics and lambdas. This allows you to easily wrap your services in interfaces, de-coupling code and making things much more testable, especially if you use a good mocking framework like Rhino. When you combine DI/IoC with ideas like the Onion Archtecture (http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ http://jeffreypalermo.com/blog/the-onion-architecture-part-1...), writing readable, testable, flexible, maintainable applications becomes supremely easy.
- skrebbel 14y agoA lot of people in this thread point out that modern IoC containers are good because they can automatically wire up your component tree for you, which is such a hassle to figure out and code manually in a place like main(). This component tree is the core of your application architecture. If the classes are well named, a big part of the application structure should become clear to someone reading your hand-coded main(). Also, if this is such a pain to figure out, why are you using components at all? I find the idea of splitting functionality into classes but having no clue how these classes relate to one another a tad scary, really. I usually have a picture of the entire component tree on the wall near our team. It's great for pointing at when discussing design, and it's trivial to draw. Writing a main() really shouldn't be more work than copying that picture into code. A tad tedious, but never more than an hour of work. Why add all that IoC complexity for saving 60 minutes. ? Why replace an excellent starting point for new team members to dive into code by a library that does magic? Deployment variability doesn't cut it for me. Nearly always, you can foresee which things may need to be variable, and which aren't. Explicitly make those configurable, instead of all classes and their arguments like you'd do in Spring. In your main(), just if or switch over these config settings to instantiate the right class. Again, very readable, and you strongly convey intent to code readers.