5 ms·
"Dependency injection is too complicated, look at this one straight-line implementation" is not exactly a fair argument. The whole point of DI is that when you
by danpalmer 1y ago
"Dependency injection is too complicated, look at this one straight-line implementation" is not exactly a fair argument.
The whole point of DI is that when you can't just write that straight-line implementation it becomes easier, not harder. What if I've got 20 different handlers, each of which need 5-10 dependencies out of 30+, and which run in 4 different environments, using 2 different implementations. Now I've got hundreds of conditionals all of which need to line up perfectly across my codebase (and which also don't get compile time checks for branch coverage).
I work with DI at work and it's pretty much a necessity. I work without it on a medium sized hobby project at home and it's probably one of the things I'd most like to add there.
- JyB 1y agoYou are missing the point the post is about Golang specifically.
- jjice 1y agoBut can’t you do your DI by hand? The frameworks can really become absurd in their complexity for a lot of tasks (I’m sure they make sense in many situations). DI is a concept that can be orchestrated with normal code at the top of the execution just fine, eliminating a lot of cruft. To be fair, the numbers you h the row out sound like a framework becomes valuable, but most places I’ve seen DI frameworks, they could be replaced with manual DI and it would be much simpler.
- danpalmer 1y agoWhen you say "do your DI by hand", do you mean wiring up each case, or do you mean writing a DI system that treats the cases generically? The former is what I'm suggesting becomes untenable at some point. The latter is just writing your own DI framework for, which I think would be fine. DI frameworks are complicated, but they're a constant level of complicated, they don't get more complicated as the codebase grows. Not using a DI framework is simple at the beginning, but it grows, possibly exponentially, and at some point crosses the line of constant complexity from a DI framework. Finding where those lines intersect is just good engineering. Ignoring the fact that they do intersect is not.
- tcfhgj 1y ago> Not using a DI framework is simple at the beginning, but it grows, possibly exponentially, and at some point crosses the line of constant complexity from a DI framework. How so?
- danpalmer 1y agoLook at my example numbers, and think through how you would write the setup process for that piece of software. You'd need a ton of conditionals checking all sorts of different things, woven throughout the codebase, in many different classes, etc. With a DI framework of some kind, those conditionals would likely not exist, instead you'd be able to specify all the options, and the DI framework takes over stitching them together and finding the dependencies between them.
- teeray 1y ago> What if I've got 20 different handlers, each of which need 5-10 dependencies out of 30+, and which run in 4 different environments, using 2 different implementations. Listen to your code. If it’s hard to write all that, it probably means you have too many dependencies. Making it easier to jam more dependencies in your modules is just going to make things worse. “But I need all those…” Do you really? They rarely ever are all necessary, in my experience. Usually there’s a better way to untangle the dependency tree.
- danpalmer 1y agoThis was a hypothetical, but I've seen plenty of codebases like this. There's going to be some cruft in there, but even just the baseline for a service capable of releasing, with feature flags, safely, with canaries etc, to XXk-Xm requests per second and <XXms per request, with no downtime, is quite a lot.
- sagarm 1y agoMeh, I've worked on services with in languages with a DI framework (Java+Guice or Spring Boot) and not (C++, Go) and the latter is much nicer. And yeah some had Xm requests. You just dispense with all the frippery that hides the fact that you are depending on global variables if you really want the Guice/Spring Boot experience. The C++ code was much, much easier to trace by hand. It was easier to test. It started much much faster, speeding iteration. Meanwhile the Java service was a PITA to trace, took 30+ seconds to boot, and couldn't be AOT compiled to address that because of all the reflection.
- JyB 1y agoDan, are you referring to handling/implementing DI principle in Golang projects or not. I am curious.
- danpalmer 1y agoI am referring to DI as a general practice. Go does not seem particularly well suited to DI, but I'm not a fan of it as a language in general because I don't think it lets you build the right abstractions. I've done DI in Java (Guice), Python (pytest), Go (internal), and a little in C++ (internal). The best was Pytest, very simple but obviously quite specific. Guice is a bit of a hassle but actually fine when you get the hang of it, I found it very productive. The internal Go framework I've used is ok but limited by Go, and I don't have enough experience to draw conclusions from the C++ framework I've used.