4 ms·
Heh, not the op but I'll bite. I just had to go through an open source project that uses guice, in order to try to trace a particular code path, since the user
by thisone 8y ago
Heh, not the op but I'll bite.
I just had to go through an open source project that uses guice, in order to try to trace a particular code path, since the user group was less than helpful.
Trying to figure what was running was an absolute nightmare of nested magic spread out through a score of files. Meaning as soon as I had a clue, I'd lose it as I had to retrace back through all those files.
I'm sure it's clear as crystal to the people who wrote it, but DI can be obtuse as hell if you have to figure what's actually running on your own.
- spatulon 8y agoI understand dependency injection to mean 'pass dependencies as arguments', which seems pretty simple and reasonable. e.g. instead of void foo() { SingletonLogger::logError("no cheese"); } you'd write void foo(ILogger logger) { logger.logError("no cheese"); } Now it's much easier to unit test `foo` with a mock logger object. Is there more to it than that? Why are there big, complicated frameworks for it?
- thisone 8y agoDI/IoC gets complicated, fast. hand rolling DI, yep brilliant, generally quite easy to work your way through because it's easy to see where classes are being used. Hand rolling can get complicated when your applications get BIG and you want to do fancy things like having modular code (whether you ever use the module somewhere else or not) or lazy loading or multiple scopes. Then you use a framework and you find your dependencies take dependencies, your wireup code is auto-magical, you inject dependencies into private properties, you want multiple implementations of particular interfaces but want to ensure only the right one gets used in each circumstance. Then multiple people start getting their fingers into the pie and the DI/IoC explodes into config files throughout the application, and the only way to understand what's being wired up without a map, is to "find usages", pin files, and cry (I'm not bitter or anything ;) DI/IoC can work wonders for handling complexity, it can also increase your complexity if you aren't very careful)
- vbsteven 8y agoThat last sentence is the important part: "if you aren't very careful". I work in multiple large java/spring codebases and the rule we use is "Keep all configuration related to the same base type/interface in the same file". That way if you want to find out which logger is injected you only have to check 1 file. Another easy way to find out what is injected at runtime is to attach a debugger and set a breakpoint.
- thisone 8y ago:( with the particular project I've been looking through, trying to debug via running the entry point was a non-starter. The part of the system I needed to trace would only be able to run if I had 4 other services running (all started seperately from the same main file) and a full dataset loaded. Once I finally discovered a hint about which files governed the behaviour I was investigating I was finally able to isolate the tests to begin the debug cycle. Sometimes it's just complicated.
- logicchains 8y agoImagine you want to simplify the code, and you hate passing values around, so you write a framework that allows you to write something like: @GetMeALogger(andCallIt=loggy) void foo() { loggy.logError("no cheese"); } Where @GetMeALogger does some magic at compile time to pipe in some kind of logger class based on various config options. Then to unit test it, you use different config than production.
- kamarg 8y agoMainly because once you get more than a few arguments, it gets tedious to start newing them all up and all of their dependencies and on down the stack. So some people built frameworks to do it for you but each of these frameworks requires their own configuration/documentation and suddenly instead of 50 lines of news, you have annotations in twenty different files that effect the way your code runs without actually being code. Each step to get from A to Z seems perfectly logical but the end result is a difficult place to start.
- vbsteven 8y agoIt's only a problem if you let it become a problem. Just like with code style, naming and formatting, the DI configuration should be enforced during code review. Spaghetti code would not pass code review, so why would you allow spaghetti configuration. In the code bases I work in I know if I need to know what Logger is injected I need to look at the LoggerConfiguration class to see which Logger implementations are used in production, staging and dev. And even if I don't know the name of the LoggerConfiguration file, I have an IDE that can get me from injected property to configuration in one click.
- sharemywin 8y agoBut, your experienced in your teams code. Now, let's say you and your team get fired except maybe some person on another continent they hired to keep it up. OK, 20 years from now. Your reincarnated and you just got hired to dig through the code and you've hard of java, but nobody uses that relic anymore.. Good luck. That would be a fun text adventure....
- vbsteven 8y agoDeclaring "I need an ILogger" is the easy part. The complicated part is the configuration related to which ILogger implementation will be injected at runtime. This can depend on several things like configuration properties, environment variables, libraries loaded, feature flags enabled, etc edit: also, you don't always want to manually pass the argument to every function. At application startup you typically want to build a full graph of objects with all the dependencies "wired up". The big complicated frameworks (Spring for example) read in a bunch of configuration, resolve all dependencies, and then construct the graph for you.
- EADGBE 8y ago> I'm sure it's clear as crystal to the people who wrote it This - in general - is the problem with programming.