I don't understand this code:
Class ServiceImpl{
private static final TestAccessor accessor = TestAcceessor.Instance;
}
ServiceImple knows it's being tested? It always gets a TestAccessor
?
The pure dependency injection version of this code looks like this:
public static void main(String[] args) {
TestAccessor testAccessor = new TestAccessor();
ServiceImple service = new ServiceImple(testAccessor);
service.start();
}
Class ServiceImpl{
ServiceImpl(Accessor accessor){
this.accessor = accessor;
}
Accessor accessor;
...
}
Here serviceImple
has no idea what kind of Accessor it's using or where to find it. You can feed it anything it knows how to talk to. You don't have to change any globally located anything to do that.
Now you don't have to do it this way. But, using the locating method:
Show me how you do polymorphism.
The fact that your classes have no state means nothing to me. I make stateless instances all the time. Doesn't hurt a thing. Instance state isn't the only reason to have an instance. The ability to polymorphically deploy messages (events and commands) is also important. Tell me how you do that.
Injecting doesn't mean locating. You are not using dependency injection. You are using a service locator. Yours is just distributed as static method getters.
IMO there is no tight coupling as we are just accessing the enum constant and any change to DAO enum doesn't make us change the service class.
That still means you're stuck with one service class. That's the coupling. The coupling is in the form that things KNOW where to find their dependencies. Done this way you can't achieve polymorphism by simply handing them different things. You have to change whats where they expect to find their dependencies. That makes achieving polymorphism difficult because if you change the dependency that where your class expects to find it you've changed that dependency for everything that uses it. That's called a global. Reasoning about the impact of messing with them is hard.
People often trot out testability as the argument against this kind of coupling but that misses the real point. There are many frameworks that use reflection tricks unshoot yourself in the foot when you work this way. These bandaids aren't going to heal the bullet wound of global dependencies.
Not knowing where your dependencies come from is nice because now finding them is not your problem. It means you can focus on using the dependencies. It means you know what you're using was meant for you because they were given specifically to you.
Doesn't that just move the problem somewhere else? Yes it does. You can create everything in main()
and inject from there. You can a simple factory method that locates the dependencies and then injects them. What? Yes I said locates. Locating isn't evil. It's just best done by construction code in classes/moduals/main that doesn't have to know how to use anything. This is the separate use from construction principle. It's important enough that if you do use static methods to build instances they shouldn't hang off the same class name that instantiate unless you know some damn good default dependencies.
You shouldn't make it unimaginable to write a different static factory method that builds the instance with different dependencies. This should be no more difficult then giving the new factory a good name.
Show me how you have the ability to separate use and construction decisions like this I'll forget about pure dependency injection. Show me how you do polymorphism.
Since we are accessing Service classes from Handler classes, how can we inject DAO dependencies if required into service(We don't use Spring) class?
IMO we don't want to do that from Handler as that would expose our DAO classes to Handler and thus make them insecure.
Unless you have a SecurityManager
Hanging DAO's off static finals wont secure them either thanks to reflection. Just because you want to control access to something doesn't mean it has to exist in only one place or only have one form.
Look into GuardedObject to control access to an object. Then you can pass it to whatever.
TestAcceessor.Instance
ServiceName.methodName()
.