Hi Alan, some thoughts inline below.
On Mon, Nov 11, 2013 at 10:03 AM, Alan Darkworld <[email protected]>wrote: > Hello everyone, > > I've been working with Java for several years now and I'm always open for > new ideas to improve code quality. But I do have some serious doubts about > dependency injection (more on that later). However, as large frameworks > such as Eclipse 4 and Xtext employ it successfully, I'm trying to get used > to this new idiom. When walking through some tutorials, several questions > appeared: > > > *1)* The Injector becomes a sort of "main static factory" for the entire > application. However, Guice does not instance-control the injector - in > other words, Injector#getInstance is not static. How do you share your > injector across all classes in your application such that it's easy to > access? The easiest thing I can think of is to create it once at the start > of the program and then make it available through a static field, but that > just doesn't feel "right" to me. > This isn't really the right angle. This line of thought is more akin to non-DI programming -- where you have a single static "service locator", and other pieces of code call out to that locator and ask for objects. That isn't what DI is about. DI is about ensuring that your objects only care about exactly what they need and nothing more. No dependencies on this big "whale" objects. You construct your injector and get the "entry point" of your application (e.g, something like MyApp.class), and MyApp has its dependencies injected, its dependencies have theirs injected, etc... recursively all the way down. No class ever needs to look back at the Injector, because the Injector has already figured out each specific dependency and knows how to create the class properly. (There are, of course, some advanced use-cases where you may need the Injector... but those are typically for extension-like circumstances, and not in common usages. In those cases, you simply list the Injector as another dependency and it will inject itself. No statics required.) > > *2)* I can see that DI is handy if all objects have no-argument default > constructors. But most of the time, this is not the case, especially with > immutable objects that need to check their invariants in their constructor. > Consider for example an immutable "DateRange" class with the invariant > "start date < end date". The only valid constructor for this class has two > parameters (the dates), yielding a client code like: > > long start = calculateStart(); // calculates the start time based on > user input (result is dynamic) > long end = calculateEnd(); // calculates end time based on user input > (result is dynamic) > DateRange period = new DateRange(start, end); // throws > IllegalArgumentException if start > end), need to replace this line by > Depencency Injection > > How would something like this translate into the Dependency Injection > idiom? I can clearly see DI working for the Java Beans pattern, but what > about the immutable case? I've had a look at the Guice Documentation, but I > couldn't spot an answer to this. > Simple bean-like classes like DateRange aren't things that should be injected. Those are just simple data classes. There's no need to get fancy and do anything with dependency injection there. DI is more useful when there's actual dependencies -- "start"/"end" and other user-supplied parameters aren't things that are injected. If the entire class is made up of user-supplied values, then it isn't something DI should handle. I'm not sure where you found that DI is useful for no-args constructs. DI isn't very useful there. DI is useful when you have constructors that take system-supplied arguments (e.g, ExperimentManager depends on ActiveExperiments and RpcSystem). (And again, there are cases where you may have an object that depends on some mix of user-supplied & system-supplied values. For those cases, there's an extension called AssistedInject<https://code.google.com/p/google-guice/wiki/AssistedInject>... but that's more advanced usage.) > > > *3)* For many years, several books (including the excellent "*Effective > Java*") have gone to great lenghts explaining how to keep our class > invariants safe from both malicious access and careless programmers > (including client use and subclassing). By applying DI, we forfeit the > control over our fields, we give up on encapsulation. From my point of > view, with DI the focus has shifted from "*This class will work, no > matter how much you mistreat it*" to "*It works if you treat it right, > otherwise it's your own fault*". What implications does that have for > software quality? We sure gain a lot in terms of configurability (create a > new subclass, introduce it in the module and you're all set), but what do > we lose with respect to safety and contracts? This is actually my main > concern about DI and the very reason why I can't yet wrap my head around > it. Can somebody provide a reason why my concerns are without cause? Please > do! > I'm not sure what leads you to that conclusion. You can still easily check invariants with DI. In fact, it's easier to check with DI because, by injecting your dependencies, your class is stating upfront: I care about <this>, and <that>. With a service locator pattern, it instead either says nothing or says: I care about <something that may be inside that that>. So your tests don't know exactly how to construct it, and casual readers of the code have to analyze the entire class for usage instead of just looking at the constructor. > > I do have some more concerns about DI, but the three stated above are the > ones which really prevent me from getting into it. I'd be grateful if > someone could explain how to do it the right way (for 1 and 2), or why I'm > wrong (for 3). > Have you watched the video <https://www.youtube.com/watch?v=hBVJbzAagfs>on the Guice front page? Bob & Dhanji do a very good job of explaining how it works. sam > > > Thanks, > > > Alan > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/google-guice. > For more options, visit https://groups.google.com/groups/opt_out. > -- You received this message because you are subscribed to the Google Groups "google-guice" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/google-guice. For more options, visit https://groups.google.com/groups/opt_out.
