4 ms·
Do use DI, it's great. It helps with structuring into entity/model/service/controller and treats DI providers as a global resource. But don't require configurat
by nurettin 6y ago
Do use DI, it's great. It helps with structuring into entity/model/service/controller and treats DI providers as a global resource. But don't require configuration and instantiate lazily as a class member like a sane framework instead of having to pass it to constructors.
- jolux 6y agoConstructor injection is the preferred way to do DI because construction is a strong guarantee that an object’s state is properly initialized.
- mumblemumble 6y agoIn .NET, the usual convention is that you make required things constructor arguments, so that there's no room for confusion. Personally, I quite like that quite a bit compared to platforms and frameworks where the convention seems instead to be, "RTFM or die (at run time)."
- mwcampbell 6y ago> In .NET, the usual convention is that you make required things constructor arguments, so that there's no room for confusion. Except in Windows Forms, where the norm is a zero-argument constructor and setting everything via properties, because that approach works with component-based design-time tools. Come to think of it, I think WPF and its descendants do the same.
- ygra 6y agoYou can tell the designer how a particular type has to be created if it doesn't have a parameterless ctor, but yeah, it's generally easier to do it that way.
- mumblemumble 6y agoIt's been a while since I touched either WinForms or WPF, but, if I recall correctly how things worked, I don't think this is actually an exception to the convention. Don't they also make everything optional? In which case, the correct way to follow the pattern would be to also leave the constructor parameterless and configure everything via properties.
- KallDrexx 6y agoConstructor DI is extremely important though, because time and time again lazily injected dependencies via properties results in circular dependencies and sometimes missing dependencies that fail at runtime. I'm not talking about simple cycles either, every time I have seen lazy dependency injection done has ended up in an A -> B -> C -> D -> A scenario. Passing required dependencies by constructors makes this extremely apparent, not just to the DI framework but to the developers themselves. With constructor injection I can immediately grasp exactly what dependencies an object depends on without even going into the full code flow to look at all the code to find all the IOC container calls. Edit: Also constructor injection is critical for testing dependency injection. IT allows you to have automated tests that construct every relevant object using the same DI setup as your live application and you can verify that the DI framework can resolve dependencies for everything. If your DI is lazily done this cannot happen unless you explicitly call all code flows, opening yourself up to runtime errors that may be missed. Unit tests won't catch this because the dependencies of your production site will be different than the dependencies of your test scenarios.
- mumblemumble 6y agoI'd go a step further and say that if calls to the IoC container are scattered all around your code, you're not actually doing DI. You're following the service locator antipattern. (https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Patt...)
- gpderetta 6y agoVery much so. We are currently on a long term process of migrating a large C++ codebase from a service locator model to just passing dependencies through constructors. New code is significantly simpler to both use, understand and test.
- legulere 6y agoDependency injection is just using passing your dependencies as interfaces, especially in the constructor. Nothing more. Dependency injection frameworks are DI combined with a service locator. Dependency Injection Frameworks have the same issues: - understanding what is going on is harder than injecting objects by hand. - you have limited control over object lifetimes (when objects are created and disposed). Permanent, scoped and transient might be enough most of the time for a web service, but as soon as you fire off tasks that can outlive the requests or when you use it in different circumstances like UI it’s getting a problem.