As I'm just getting into ASP.NET Core, I'm also continuing to slowly learn about Dependency Injection and still trying to identify some value in it for our practical purposes. The point I've reached leaves me asking, if all of the dependencies for a given operation must be injected into the controller, what limits developers from misusing those dependencies in inappropriate spots? For example, if a controller must have an Entity Framework database context and an IMemoryCache
injected into its constructor so that it can pass them all the way down to your data access layer, what now prevents Dudley the dull developer from accessing the cache or executing a database query directly from the controller? The controller and every layer actor in between having to act as a broker for dependencies they should know nothing about is making me uncomfortable with it, but I'm sure this must be addressed. How is this handled?
-
3What prevents a developer from simply instantiating those classes directly and using them in the controller if they want to? Why is that any different than using injected dependencies? Also, you don't have to inject a dependency into a controller "so that it can pass them all the way down to your data access layer". The "passing down" part isn't necessary; it's handled by the framework. If the controller doesn't need a dependency itself, don't inject it into the controller. Only inject it into the component that needs it.– Eric KingCommented Jul 6, 2020 at 20:44
-
For built-in framework classes, nothing, but one way typically is through layering and assembly references (or lack thereof). The latter part of your comment sounds like how I would prefer it to work but I haven't seen how that's possible in this framework yet - only "passing down".– xr280xrCommented Jul 6, 2020 at 22:20
2 Answers
what limits developers from misusing those dependencies in inappropriate spots?
Nothing.
But nothing stops developers from misusing anything else in your code. DI isn't a tool to protect you from bad developers, it's a tool to make things easier to manage and to test. If you have developers who can't write well structured code, then you have bigger problems than whether you're using DI or not.
-
There are always bad devs especially in the small business world. There are also Jr. devs/ new team members who need to get to work on small tasks before understanding an overall complex architecture. Structuring code to encourage appropriate usage is certainly not my invention. The question isn't how to use DI to enforce it but how to stop DI from bastardizing it. Nothing stops a developer from misusing anything but you can cause them to have to go to great lengths to do so to prevent accidents. Dangling instances of classes that should not be used out in plain sight is asking for trouble.– xr280xrCommented Jul 6, 2020 at 22:17
-
PRs and code reviews are there to stop the bad code getting into the trunk, not frameworks. Commented Jul 6, 2020 at 22:32
-
I appreciate that point. But those don't stop the bad code from being written and having to be re-written and that leads to more time spent on code reviews, both of which slow down development and cost money. Code can be structured to help avoid this.– xr280xrCommented Jul 6, 2020 at 22:44
-
1You shouldn't have to say the same thing in multiple code reviews; if you are, that's an issue that your staff aren't learning. Commented Jul 7, 2020 at 7:58
-
That's not what I was saying. Regardless, your answer "Nothing" is true, but Eric King more directly addressed what I was asking in his comment above. In a moment of confusion, I had forgotten between reading and implementing is that it's a dependency graph - you would not be injecting non-dependencies into a controller constructor just so it can pass them down - those should be injected as well by registering them in the service container. So there is no "dangling instances of classes that should not be used out in plain sight" to tempt misuse.– xr280xrCommented Jul 7, 2020 at 19:01
identify some value in it for our practical purposes.
Consider a class that knows just where to find what it needs to work. It needs 5 different things and reaches out into the rest of the code base to find them.
Consider a class that knows it needs 5 things and doesn't care where they come from.
Now, make a random change to your code base. Which class do you think it's more likely you broke?
That difference has some value to me.