Preferences

Another downside of DI is how it breaks code navigation in IDEs. Without DI, I can easily navigate from an instance to where it's constructed, but with DI this becomes detached. This variable implements Foo, but which implementation is it?

Ye debugability and grepability is terrible.

DI seems like some sort of job security by obscurity.

If your IDE starts to decide how you code and what kind of architecture/design you can use, I kind of feel like the IDE is becoming something more than just an IDE and probably you should try to find something else. But I mainly program in vim/nvim so maybe it's just par for the course with IDEs and I don't know what I'm talking about.
Are you not using an LSP with your text editor? If you are then you'll run into the same issue because it's the underlying technology. If you aren't using an LSP then you're probably leaving some workflow efficiency on the table.
I think probably when I write Rust, it does use LSP somehow, but most of the time I use Conjure (by Olical), and I don't think it uses LSP, as far as I know at least, but haven't dug around in the internals much.

> then you're probably leaving some workflow efficiency on the table

Typical HN to assume what the best workflow efficiency is, and that it mostly hinges on a specific technology usage :)

Imagine I'd claim that since you're not using nrepl and a repl connected to your editor, you're leaving some workflow efficiency on the table, even though I know nothing about your environment, context or even what language you program in usually.

> Imagine I'd claim that since you're not using {X}

Usually on the third time someone recommends {X} I would have looked into it and formed my own conclusions with first hand experience.

Ok, don't forget looking into nrepl, so you can be as productive as me and others. That's the second time, now we just wait for the third for you to seriously consider it.
In IntelliJ at least this is a non-issue.
How?
The IDE understands the DI frameworks and can show you which class or classes will be injected.
ctrl shift b = show implementations
This is what I hate most about DI as well and when I told some other devs about this pet peave of mine they were looking at me like I had 2 head or something.
Which language? Android Studio, for example, allows you to navigate to Hilt injection points.
Not an issue in C#
Definitely still an issue in C#. C# devs are just comfortable with the way it is because they don't know better and are held hostage. Everything in C# world after a certain size will involve IOC/DI and the entire ecosystem of frameworks that has co-evolved with it.

The issues are still there. You can't just "go to definition" of the class being injected into yours, even if there is only one. You get the Interface you expect (because hey you have to depend on Interfaces because of something something unit-testing), and then see what implements that interface. And no, it will not just point to your single implementation, it'll find the test implementation too.

But where that "thing" gets instantiated is still a mystery and depends on config-file configured life-cycles, the bootstrapping of your application, whether the dependency gets loaded from a DLL, etc. It's black-box elephants all the way to the start of your application. And all that you see at the start is something vague like: var myApp = MyDIFramework.getInstance(MyAppClass); Your constructors, and where they get called from is in a never-ending abyss of thick and unreadable framework code that is miles away from your actual app. Sacrificed at the alter of job-creation, unit-testing and evangelist's talk-resume padding.

> You can't just "go to definition" of the class being injected into yours, even if there is only one.

Yes, I can? At least Rider can jump to the only implementation, no questions asked.

> And no, it will not just point to your single implementation, it'll find the test implementation too.

It will, but is it a problem to click the correct class from a list of two options?

If you only have one implementation, why do you even have an interface?
So I can mock it out for unit tests.
I'm glad someone knows how I feel.

Yes, the comments about "$25 name for a 5c concept" ring true when you're looking at a toy example with constructor(logger) { .. }.

Then you look at an enterprise app with 10 years of history, with tests requiring 30 mocks, using a custom DI framework that only 2 people understand, with multiple versions of the same service, and it feels like you've entered another world where it's straight up impossible to debug code.

> You can't just "go to definition" of the class being injected into yours, even if there is only one.

This situation isn't unique when using DI (although admittedly DI does make using interfaces more common). However, that's what the "go to implementation" menu option is for.

For a console app, you're right that a DI framework adds a lot of complexity. But for a web app, you've already got all that framework code managing controller construction. If you've got the black box anyways, might as well embrace it.

Make those dependency interfaces dynamic enough to be practically untyped, introduce arbitrary implicit ordering requirements, and we have now invented Middleware.
I haven't really done any c# for 5+ years. What has changed?

I remember trying to effectively reverse-engineer a codebase (code available but nobody knew how it worked) with a lot of DI and it was fairly painful.

Maybe it was possible back then and I just didn't know how ¯\_(ツ)_/¯

If the rules of the dependency injection framework are well understood, the IDE can build a model in the background and make it navigable. I can't speak for C#, but Spring is navigable in IntelliJ. It will tell you which implementation is used, or if one is missing.

In a Spring application there are a lot of (effective) singletons, the "which implementation of the variable that implements Foo is it" becomes also less of a question.

In any case, we use Spring on a daily basis, and what you describe is not a real issue for us.

Is it ctrl+click takes you to the main implementation directly? If not it is reaaaaaallly annoying
I think so.

Also, what I think is also important to differentiate between: dependency injection, and programming against interfaces.

Interfaces are good, and there was a while where infant DI and mocking frameworks didn't work without them, so that folks created an interface for every class and only ever used the interface in the dependent classes. But the need for interfaces has been heavily misunderstood and overstated. Most dependencies can just be classes, and that means you can in fact click right into the implementation, not because the IDE understands DI, but because it understands the language (Java).

Don't hate DI for the gotten-out-of-control "programming against interfaces".

In every language/IDE I've ever used ctrl-click would take you to the interface definition, then you have a second "Show implementations" step that lists the implementations (which is usually really slow) and finally you can have to select the right implementation from the list.

It's technically a flaw of using generic interfaces, rather than DI. But the latter basically always implies the former.

This is the point, you need an IDE with advanced features while a text editor should be all you need to understand what the code is doing..
Why, as a professional, would you not use professional tooling. Not just for DI, but there are many benefits to using an IDE. If you want to hone your skills in your own time by using a text editor, why not. But as a professional, denying the use of an IDE is a disservice to your team. (But hey, everyone's entitled their opinion!)

Edit: upon rereading I realize your point was about reading code, not writing it, so I guess that could be a different use case...

Being able to understand a system under fire with minimal tooling available is a property one must design for. If you get woken up at 3am with a production outage, the last thing you want to do is start digging through some smart-ass framework's idea of what is even running to figure out where the bug is.

There's nothing wrong with using an IDE most of the time, but building dependence on one such that you can't do anything without it is absolute folly.

C# code bases are all about ruining code navigation with autofac and mediatr

This item has no comments currently.