4 ms·
Why do or don't people like IoC?
by chris_wot 9y ago
Why do or don't people like IoC?
- Cyclone_ 9y agoA reason to like it is that in a system with DI and IoC you spend less time trying to build up objects and pass them to where they need to go, since it's simple to just inject them into the class you want using an annotation. Spring takes care of the object creation under the hood for you. A reason not to like IoC is that since it's so easy to use it can lead to sloppiness since you're not thinking about the overall structure of the application as much.
- makmanalp 9y agoThis explanation always messes with me... Why are you trying to build up objects and pass them into places? (er, sorry, I don't mean you of course, I just mean in general) When / why is that ever a thing that someone needs to do so often that it becomes a concern? How come I rarely if ever see this in the e.g. python or C++ world? I get the idea of decoupling component implementations from their host objects but I just can't see most use cases needing that level of generality. Especially when it comes at the price of smearing a big and complicated IoC framework all over your code. Past a threshold of codebase size and complexity, I see the value of course, but IoC frameworks get pitched too often as a thing that everyone should be using IMHO. Even for testing we already have mocking tools that handle replacing component objects with mocked versions just fine, and we don't need IoC tools for that.
- _xgw 9y ago> Why are you trying to build up objects and pass them into places? Well, that place needs those objects to do its job. > When / why is that ever a thing that someone needs to do so often that it becomes a concern? In web applications, at least, you find yourself with a few controllers, which all need a few services which all need a few repositories to access the database... I guess you can see where this is going. Declaring in your class' constructor that instances need an object of `Type` is the less repetitive way of saying that an instance of a class needs something. Writing the code that builds objects and passes them to your constructors would be quite repetitive.
- chris_wot 9y agoIf you ever see someone implement the command pattern, you'll see passing objects.
- tytytytytytytyt 9y ago> Why are you trying to build up objects and pass them into places? Maybe something like the mediator pattern? There's definitely use cases for it, but I think a lot of the time the cure isn't any better than the disease.
- usrusr 9y agoWith DI, that one big messy application root object that every codebase seems to naturally gravitate to becomes a generic, clean, reusable mechanism you did not write yourself. (Unless you put another big messy application root object on top of your DI, which I suppose is a learning experience I am not alone with)
- jmspring 9y agoPersonally, when I build something, I prefer to know exactly what will happen prior to compile/build, not hope some configuration will handle things. I can deal with both, but just a preference. In general, dynamic integrations like IoC, etc make things harder to troubleshoot/debug as well.
- exabrial 9y agoExactly, right? That's what DI/IOC allows you to do. You can test a component where the variables always return simple deterministic results for one unit of code, or/[preferably] and you can also have a set of tests where you integrate all components.
- chris_wot 9y agoI think he's talking about autowiring.
- dullgiulio 9y agoExactly, and a lot of Spring discussions conflate the things and blurry the image a lot. Inversion of Control is really good and there are no reasons not to use it. When you have something that can be done in multiple ways, make a small interface and several implementations for it. The trick now is how to decide what to use. The simplest way is just to parse your configuration file or application flags/arguments in main and instantiate the concrete implementation of your classes there, then pass them down all the way until you need them. This is explicit, simple and clean. Spring makes you (at least) do two things wrong: 1. Configure the concrete implementations the wrong way. You don't want your users to decide which class implements a certain interface. You want them to decide something higher level, like for example "get crash data via e-mail" or "get crash data in logs". The rest is implementation details. 2. Annotations for autowiring: my feeling is that those are just to go around Java verboseness. Instead of typing "VeryLongName veryLongName = new VeryLongName()", "@autowire" it easier to type. I have always seen it misused (used for stuff that is not Inverted/Configurable) and it makes code more magic. Even worse, you are back at having classes pick their dependencies, even if they are interface implementations. If your classes take their dependencies as constructor parameters, everything is much more explicit.
- Chickenosaurus 9y agoThe major advantage IoC provides is decoupling of components. Components do not instantiate their dependencies and therefore are not coupled to specific dependency implementations. Any dependency that satisfies the interface the component expects can be injected. This is especially useful when implementing tests because it is easy to inject mock implementations of dependencies.
- barrkel 9y agoYou have it a bit backward IMO. Java (specifically) unit tests normally require that you indirect your dependent code through an object reference in order to mock the implementation, thus creating a composition problem. Unit testing in Java turns a control flow problem into a data flow problem. You then need help in getting all the data to the right places, a problem that unit testing created. IoC containers are a solution to this problem; they then move part of the implementation of your program into your config, or embed it implicitly in constraints in how things are composed. This is usually not an improvement in ease of understanding or navigating a project, since it optimizes for changing it. Personally I'm deeply suspicious of mocking as an approach to testing code. I much prefer a functional approach with explicit data flow between parts of the system, rather than indirecting control flow through vtables using complex ad-hoc protocols that become part of your specification by getting baked into mocks in tests. IoC and mocking promotes dataless Verber, Doer and Handler classes that have no real place in an OO model of a system. We shouldn't forget that decoupling isn't good for its own sake. Things that change together are already coupled; decoupling them at the implementation level is usually an obstacle in every way, whether to understanding, effort, performance, whatever. Abstraction use vs programmer experience generally follows a hump shaped curve; beginners know nothing, intermediates abstract everything, while experts use fewer more powerful, more composable abstractions and code more directly elsewhere. Mocking IMO optimizes for the middle case of too many non-reusable abstractions.
- cztomsik 9y agoPart of the problem is Java environment itself, other platforms allows exporting single instances (import an actual singleton), so there is not so much need for DI Also, you don't need to swap everything, your application (in fact) has hard dependencies. And mocking everything is not always the best way to test system (sometimes it's totally okay to mock the whole db)
- TheAceOfHearts 9y agoInjecting your own dependencies makes lots of sense for some use-cases. For example, you'd probably wanna make it such that your network adapter can be swapped out in order to support different transports. By allowing it to get swapped out you also make it easier to test your code, since you can then use a fake network adapter to replicate any kind of scenario you wish to test. The problem with the cult of DI fanatics is that they can sometimes take it too far. Sometimes code is tightly coupled to the implementation by necessity, and it doesn't add any value to have additional layers of misdirection. Although I'll admit that this is a bit of a strawman, since IoC can be summed up as "give things what they need", which is generally a sensible approach.
- vbezhenar 9y agoApplication consists of components. One component need to talk to another. You either use some kind of global repository or IoC. Repository is easier to use without framework, but with framework support IoC is as easy to use and provides better incapsulation, easier testing.
- EdSharkey 9y agoWhen all your modules' dependencies are injected as constructor parameters, it's straightforward to mock those dependencies when TDD'ing the module. Constructor parameter injection is really vital to isolate the SUT (system under test) when writing your tests. Any other type of injection is magical, and should be avoided. At test-runtime, one will pass mock objects to the SUT's constructor using the new keyword. These mock objects are used to rig up specific preconditions that drive the scenario to be tested. Mocks can also be used to assert that the SUT called the dependency as expected with parameters. At runtime, the IoC container handles instantiation of the module and injects the dependencies as appropriate constructor params. I assume you asked this because Spring Framework is the poster child of dependency injection and IoC in the Java world. With all the Aspect-Oriented Programming and proxification and scope twizzling that occasionally blooms in the Spring ecosystem that is all wired-up using Spring DI, I think Spring sometimes gets a bad rep. Only abusers of those features get bad reps with me. Spring as a whole is a trove of nicely built systems with lots of classy 3rd party integrations. I personally prefer using Google Guice for DI because it is a standalone system, it eschews doing classpath scanning to identify injectable classes which I think makes it faster especially at startup, and it has decent integrations with 3rd party libraries.
- jacques_chester 9y agoFWIW, the Spring team fairly emphatically advise against anything but constructor injection[0], to the point that a major feature of Spring Framework 5 was to rework the code to be exclusively constructor injected[1]. [0] http://olivergierke.de/2013/11/why-field-injection-is-evil/ http://olivergierke.de/2013/11/why-field-injection-is-evil/ [1] https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x#general-core-revision https://github.com/spring-projects/spring-framework/wiki/Wha...
- sbov 9y agoPeople like it because it lets you unit test in Java. Most of the time IoC involves an interface with a single implementation and there will never be a 2nd. Note that DI is just a form of IoC and both are separate from Spring. You can "manually" do DI by passing objects to constructors yourself. Some people have a complex web of dependencies and Spring can help make this manageable. Other people don't but have a hatred for passing arguments to constructors.
- cztomsik 9y agoSimple - sometimes you don't need IoC. Also, Java is statically-typed language and DIC are a way to do more dynamic stuff (@Transactional proxies) - such things are possible without DI in some other languages.
- commandlinefan 9y agoIf you do it right, it makes writing automated unit tests (like JUnit) if not easy, at least possible. If you have a Java class whose constructor instantiates a JDBC connection to a database, you can't write a unit test for that class without having a live database instance for it to connect to. If you have a method call that includes a HTTP invocation to an external REST endpoint, you can't unit test that unless the REST endpoint is up, running and accessible. If you have a function that deletes rows from a database, you can't test it unless the database is not only available, but has the rows that the function is expecting to delete. IoC, if practiced correctly and usefully, "inverts" those parts so that they can be stubbed/mocked out by the unit testing framework. You can also make the case that, practiced correctly, IoC makes it more likely that the code you wrote can be applied to a different, but similar problems (although in my experience this is more theoretical than practical, since "the business" usually asks for things that don't fit into such nice, neat little boxes). The _problem_ with IoC is when it becomes a religion rather than a testability practice. If you're spending extra time doing something, it should at least be worth the time spent on it.