Introduction
I'm using Dagger 2 for a project that's modeled using the principles of DDD.
I'd like to use the Builder Pattern to create complex entities and the way I'd normally get an instance of the builder was by using a static factory method: ComplexEntity.builder().
Aggregate roots will get strongly typed IDs, i.e. ComplexEntityID, that require a value generator for new instances. Right now I have a method for that in my module: #Provides ComplexEntityID provideComplexEntityID(IdValueGenerator generator) { return new ComplexEntityID(generator.nextId(); }.
ComplexEntityBuilder needs an instance (or provider) of ComplexEntityID in order to create a ComplexEntity. But static injection is recommended against by the people from Guice and Dagger (among others) for good reasons.
Question
How to create instances of ComplexEntity using a builder, without using static injection? In other words, how to get an instance of the builder?
Sticking to ComplexEntity.builder() would be nice because it's a common convention, but I'd think that the only way to make an instance available in a static method without using the new () keyword is by using static injection.
Another approach I could think of is to also create ComplexEntityFactory and put the builder() method there. But it seems a bit strange to use a factory and a builder together:
Inject a factory in the class where you need it
complexEntityFactory.builder().value1(...)
.value2(...)
.build();
What would be the recommended approach in this case?
Edit: If it turns out to a dedicated factory after all, tt would be nice if this factory could still be generated using AutoFactory or something similar
I think there is a more elegant solution than the one proposed by jaco0646 in the comment:
Builders are a special kind of service: You use them to realize a specific goal, but they don't have a life cycle or meaning within the domain.
So just inject builders as you would any other service.
This has several advantages:
Builders can use other services and factories by depending on them. In your case this is the dependency on the factory of ComplexEntityID.
Having a dependency on a builder is explicit (which is a good thing). At the moment, your dependency is hidden in a call to a static method.
You can replace the builder in tests.
Overall, this approach improves cohesion and reduces coupling.
One potential pitfall to be aware of is that builders usually have internal state (unlike typical services). So make sure to configure your dependency injection container such that a new builder instance is created for every resolve request.
Related
I have a slight dilemma involving Guice and avoiding non-Guice singletons. Consider a multi-module project where there are 3 modules: shared, frontend and backend. Both the frontend and the backend use an instance of a Profiling class inside of the shared module (which times methods, and is used extensively throughout the project).
Almost every single class requires the use of this Profiling instance (including User objects created dynamically when a user connects).
If every single class requires an instance of the Profiling class, there are drawbacks to different methods of doing it:
Solution 1 (in the constructor, copied to the instance field):
private final Profiling profiling;
#Inject
public User(Profiling profiling, String username)
Drawback: You have to include a Profiling object in every single constructor. This is cumbersome and slightly pointless. You also have to store Guice's Injector statically (or inject it) so that you can create the User objects on-the-fly and not just when the program is first loaded.
Solution 2 (as a instance field only):
#Inject
private Profiling profiling;
public User(String username)
Drawback: Similar as above, you have to use Guice's Injector to instantiate every single object. This means that to create User objects dynamically, you need an instance of the Injector in the class creating the User objects.
Solution 3 (as a static field in one (main) class, created manually by us)
public static final Profiling PROFILING; // Can also use a get method
public Application() {
Application.PROFILING = injector.getInstance(Profiling.class)
}
Drawback: Goes against Guice's/dependency injection recommendations - creating a singleton Profiling object which is accessed statically (by Application.PROFILING.start()) defeats the purpose of Guice?
Solution 4 (as a static field in every single class, injected by Guice)
#Inject
private static Profiling profiling;
// You need to request every single class:
// requestStaticInjection(XXXX.class)
Drawback: Again, this goes against Guice's/dependency injection recommendations because it is statically injecting. I also have to request every single class that Guice needs to inject the Profiler into (which is also cumbersome).
Is there any better way to design my project and avoid falling back to the singleton design patterns I used to use?
TL;DR: I want to be able to access this Profiling instance (one per module) across every single class without falling back to singleton design patterns.
Thanks!
Pragmatically, I would use a normal singleton, maybe through a single-field Enum or a similar pattern.
To see why, you should ask the question: What is the purpose of Guice, and of dependency injection in general? The purpose is to decouple the pieces of your application so they can be independently developed and tested, and centrally configured and rearranged. With that in mind, you need to weigh the cost of coupling against the cost of decoupling. This varies based on the object you're choosing to couple or decouple.
The cost of coupling, here, is that you would be unable to operate any piece of your application without a real working instance of Profiling, including in tests, including for model objects like User. Consequently, if Profiling makes any assumptions about its environment—the availability of high-resolution system timing calls, for instance—you will be unable to use classes like User without allowing Profiling to be disabled. Furthermore, if you want your tests to profile with a new (non-Singleton) Profiling instance for the sake of test isolation, you'll need to implement that separately. However, if your Profiling class is lightweight enough not to pose a huge burden, then you might still choose this way forward.
The cost of decoupling is that it can force every object to become an injectable, as opposed to a newable. You would then be able to substitute new/dummy/fake implementations of Profiling in your classes and tests, and reconfigure to use different Profiling behavior in different containers, though that flexibility may not have immediate benefits if you don't have a reason to subsitute those implementations. For classes like User created later, you would need to pursue factory implementations, such as those provided through Guice assisted injection or AutoFactory code generation. (Remember that you can create an arbitrary number of objects by injecting Provider<T> instead of T for any object you would otherwise inject, and that injecting a Factory instance would be like customizing a Provider to take get parameters you choose.)
Regarding your solutions:
Solutions 1 and 2, per-object injection: This is where a Factory would shine. (I'd favor constructor injection, given the choice, so I'd go with solution 1 between them.) Of course, everything that creates a new User would need to instead inject a User.Factory, so that may turn a tightly-scoped project into a project to convert every class in your codebase to DI—which may be an unacceptable cost for what you're trying to do now.
// Nested interface for your Factory:
public interface Factory { User get(String username); }
// Mark fields that the user provides:
#Inject public User(Profiling profiling, #Assisted String username) { ... }
// Wire up your Factory in a Module's configure:
install(new FactoryModuleBuilder().implement(User.Factory.class));
// Now you can create new Users on the fly:
#Inject User.Factory userFactory;
User myNewUser = userFactory.get("timothy");
Solution 3, requesting static injection of a main holder approximates what I had in mind: For the objects not created through dependency injection, request static injection for a single class, like ProfilingHolder or somesuch. You could even give it no-op behavior for flexibility's sake:
public class ProfilingHolder {
// Populate with requestStaticInjection(ProfilingHolder.class).
#Inject static Profiling profilingInstance;
private ProfilingHolder() { /* static access only */ }
public static Profiling getInstance() {
if (profilingInstance == null) {
// Run without profiling in isolation and tests.
return new NoOpProfilingInstance();
}
return profilingInstance;
}
}
Of course, if you're relying on calls to VM singletons, you're really embracing a normal VM-global static singleton pattern, just with interplay to use Guice where possible. You could easily turn this pattern around and have a Guice module bind(Profiling.class).toInstance(Profiling.INSTANCE); and get the same effect (assuming Profiling can be instantiated without Guice).
Solution 4, requestStaticInjection for every single class is the only one I wouldn't consider. The list of classes is too long, and the likelihood that they'll vary Profiling is too slim. You'd turn a Module into a high-maintenance-cost grocery list rather than any sort of valuable configuration, and you'd force yourself into breaking encapsulation or using Guice for testing.
So, in summary, I'd choose Guice singleton injection for your current injectable objects, normal singleton for your current newable objects, and the option of migrating to Factories if/when any of your newables make the leap to injectables.
There's a nice tutorial that seems to make sense about DI and IoC
Wouldn't it be easier to make the getCustomer methods static in the injector classes? I don't really see any reason to instantiate injector objects in this case.
So instead of:
MessageServiceInjector injector = null;
Consumer app = null;
injector = new EmailServiceInjector();
app = injector.getConsumer();
app.processMessages(msg, email);
We would just do:
Consumer app = null;
app = EmailServiceInjector.getConsumer();
app.processMessages(msg, email);
How to write injector classes properly? At the end of the article it says
We can achieve IoC through Factory Pattern, Template Method Design
Pattern, Strategy Pattern and Service Locator pattern too
but I guess none of the patterns was used in this example (IoC in this case is just simplistic). So how would it be done in a real project (assuming no external frameworks or IoC containers are used), i.e. if I wanted to create all the necessary stuff to let me use DI in my code.
"Easier"? I don't think it makes any difference to your DI engine.
Static would assume one instance. What if you want an instance per request, as you might for each web request? Static won't do then.
I've used Spring for more than ten years. It has a bean factory and DI capability that can deal with singleton or per request instances. Have a look at how it works to see one successful way to do it.
I think Martin Fowler's DI article, now 11 years old, still explains it well.
In real world project, you should use Dependency injection framework like Spring Framework. The are other as well likeGoogle Guice.
I have been personally using spring for couple of years now and it has grow to much larger extent apart from basic DI.
Wouldn't it be easier to make the getCustomer methods static in the injector classes?
It seems to me that what this article is calling an Injector is actually an abstract factory. We use abstract factories when we want a class to create objects at a later point it time.
In general it is not recommended to have static methods. Mainly because the classes that call the static method will have a hard dependency on it, i.e., you cannot at a later point in time consume a different dependency without changing the consuming class code. And this is exactly the problem that DI is trying to solve.
Another reason is that it is hard to mock static methods in a unit test.
So how would it be done in a real project?
In real projects you should construct your objects (e.g. services) in the composition root.
There are two ways to do it. Either use a DI container, or use Pure DI.
In my opinion, Pure DI is a better choice. See this article for a reason why.
What's wrong with following code?
public class DeDoper {
public boolean wackapediaOkToday() {
DnsResolver resolver = ResolverFactory.getInstance().makeResolver();
return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
}
}
Why is this version preferred?
public class DeDoper {
#InjectService
private DnsResolver resolver;
public boolean wackapediaOkToday() {
return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
}
}
I can easily mock ResolverFactory.makeResolver() and this is the same as setting resolver is latest example.
This is what was said in this article from ProQuest.biz:
This [first] version of WackapediaOkToday is, very loosely speaking, "injected" with a DnsResolver (although it's admittedly less like getting a shot, and more like asking a waiter for the check). But it does solve the testing problem, and the "turtles all the way down" problem.
Chained to the Factory
But in this [first version] approach, we are literally "chained" to the Factory classes. (Worse, if the objects created by our Factories have dependencies in turn, we may have to introduce new Factories inside our Factories.) We haven't fully "inverted" our control, we're still calling (controlling) the Factories from inside our classes.
What was needed was a way to get rid of the control in our classes entirely, and have them told what they were getting (for their dependencies).
Let's say you had a service which can have multiple implementations, like "FileLocator". This has a FilesystemFileLocator, which takes as an argument the path to the root of the files and a S3FileLocator, which takes as an argument your S3 credentials. The former would require you to write a service locator to figure out which version you want and then return it. That code, in turn, has to go get your data, build the appropriate type of file locator, etc. You're doing what the IOC container should do for you. On top of that, you've inject a dependency on that specific creation method.
In the second version you've defined (through annotations or XML) what type of file locator you want. The IOC container instantiates and manages that for you. It's less code you have to maintain. It's also less work if you want to introduce a third type of FileLocator. Or maybe you refactor your code so file locators are singletons, or if they were singletons they're now factories for fresh locators, or maybe you want to pool locator instances. In all these cases there will be less breakage if you work with your IOC container.
I've always known Singletons to be "bad", but only now that I've made the move to Java from C++ have I decided to find a way around them. From a bit of reading, I've found that either Factories or Dependency Injection could possibly do the job, but I'd like some confirmation on this.
As an example, I was about to write a AnimationCache singleton that would store a Map<String, Animation>. Different classes should be able to have access to this class (basically) anywhere so that they can easily and efficiently load Animations. A very brief example of what the equivalent code would look like using DI would be great.
Also, is Guice a good framework for DI with non-web apps? I have used Spring for web development, but I'm not so sure that'd work for games.
Spring and Guice will do fine. I personnally prefer Guice for pure dependency injection, but Spring offers much more.
The code would just look like this:
public class AnimationCacheClient {
private AnimationCache cache;
#Autowired // for Spring, or
#Inject // for Guice (but I think Spring also supports it now)
public AnimationCacheClient(AnimationCache cache) {
this.cache = cache;
}
// ...
}
I personnally prefer constructor injection, but you might also use setter injection or field injection.
Note that the purpose of DI is not to have "easy singletons", though. Its main purpose is to make the code (of AnimationCacheClient, here) easily unit-estable, by being able to inject mock dependencies (here, a mock AnimationCache instance).
Using Spring, DI is very simple. Using the #Autowired annotation, you don't even need additional xml to wire things up or a setter method. A member in the class that needs access to the one that has been your singleton before will do.
Here is a good example: http://www.developer.com/java/other/article.php/3756831/Java-Tip-Simplify-Spring-Apps-with-Autowired.htm
I recently 'withnessed' this thread on Singleton and how bad it might be (or not) and what you can do to bypass it. Well worth the read.
My application stores files, and you have the option of storing the files on your own server or using S3.
I defined an interface:
interface FileStorage {
}
Then I have 2 implementations, S3FileStorage and LocalFileStorage.
In the control panel, the administrator chooses which FileStorage method they want, and this value is stored in a SiteConfiguration object.
Since the FileStorage setting can be changed while the application is already running, would you still use spring's DI to do this?
Or would you just do this in your code:
FileStorage fs = null;
switch(siteConfig.FileStorageMethod)
case FileStorageMethod.S3:
fs = new S3FileStorage();
case FileStorageMethod.Local:
fs = new LocalFileStorage();
Which one makes more sense?
I believe you can use DI with spring during runtime, but I haven't read about it much at this point.
I would inject a factory, and let clients request the actual services from it at runtime. This will decouple your clients from the actual factory implementation, so you can have several factory implementations as well, for example, for testing.
You can also use some kind of a proxy object with several strategies behind it instead of the factory, but it can cause problems, if sequence of calls (like open, write, close for file storage) from one client cannot be served by different implementations.
I would still use Dependency Injection here. If it can be changed at runtime, you should inject it using setter injection, rather than constructor injection. The benefit of using any dependency injection is that you can easily add new implementations of the interface without changing the actual code.
DI without question. Or would you prefer to enhance your factory code when you create/update/delete an implementation? IMO, If you're programming to an interface, then you shouldn't bootstrap your implementations, however many layers deep it actually occurs.
Also, DI isn't synonymous to Spring, et al. It's as simple as containing a constructor with the abstracted interface as an argument, i.e. public FileApp(FileStorage fs) { }.
FYI, another possibility is a proxy.