I believe this questions has been asked in some or the other way but i'm not getting it yet.
We do a GWT project and my project leader disallowed to use GIN/Guice as an DI framework (new programmers are not going to understand it, he argued) so I try to do the DI manually.
Now I have a problem with deep object graphs. The object hierarchy from the UI looks like this:
AppPresenter->DashboardPresenter->GadgetPresenter->GadgetConfigPresenter
The GadgetConfigPresenter way down the object hierarchy tree has a few dependencies like CustomerRepository, ProjectRepository, MandatorRepository, etc.
So the GadgetPresenter which creates the GadgetConfigPresenter also has these dependencies and so on, up to the entry point of the app which creates the AppPresenter.
Dependency Injection (DI) is a programming technique that makes a class independent of its dependencies. “In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A 'dependency' is an object that can be used, for example as a service.
Dependency injection is basically the process of providing the objects that an object needs (its dependencies) instead of having it construct them itself. It's a very useful technique for testing. You don't need any framework to have dependency injection.
There are three types of dependency injection — constructor injection, method injection, and property injection.
In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.
You write that
the GadgetPresenter which creates the GadgetConfigPresenter[.]
Instead of directly creating GadgetConfigPresenter
instances, GadgetPresenter
should take a dependency on an Abstract Factory that can create GadgetConfigPresenter
instances for it. This pushes the inner dependencies of GadgetConfigPresenter
to the factory.
Using Constructor Injection all the way, your Poor Man's DI wiring should look something like this (apologies for the C# syntax):
var customerRepository = new CustomerRepository(/*...*/);
var projectRepository = new ProjectRepository(/*...*/);
var mandatorRepository = new MandatorRepository(/*...*/);
var gadgetConfigPresenterFactory =
new GadgetConfigPresenterFactory(
customerRepository,
projectRepository,
mandatorRepository);
var gadgetPresenter = new GadgetPresenter(gadgetConfigPresenterFactory);
var dashboardPresenter = new DashboardPresenter(gadgetPresenter);
var appPresenter = new AppPresenter(dashboardPresenter);
Notice how we break the dependency chain often, ensuring that the number of dependencies for each consumer never becomes too big.
In principle, this means that you must create all the dependencies at boot time, unless you implement a lazy loading strategy.
Such things as managing lifetimes are exactly the sort of thing where a DI Container can be enormously helpful, but it's entirely possible to write an entire application by just following DI patterns and principles.
All in all, though, I would still recommend a DI Container if at all possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With