0

We don't have any frameworj like Spring where we can inject dependencies using annotations or xml file. We have handler classes, service classes and dao classes.

Handler classes access service which perform business logic to get the data to be persisted into the db using dao layer.

Now I have seen that in our project we are adding the dao dependencies in the Service class by declaring them as shown below:

TestService.java

Class ServiceImpl{

    private static final TestAccessor accessor = TestAcceessor.Instance;

}

Here the TestAcceessor is an enum and is made Singleton.

My questions are as follows:

  1. Is implementing the Accessors singleton using enum and then declaring them as shown above(static final) means there is no tight coupling between our project's Service class and DAO class?

    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.

  2. 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.

  • How do you test #1? In other words, what do you for testing services without real DB access? If you can't, then Yes, you are tightly coupled to TestAcceessor.Instance – Laiv Apr 1 at 18:19
  • How do you instanciate Services in #2? – Laiv Apr 1 at 18:23
  • @Laiv thanks for the comment regarding #1. Actually we need our db instance to be running to test the #1 i.e. our service classes. – Yug Singh Apr 1 at 18:46
  • @Laiv our services are stateless. They only implement functions. This is done to avoid multithreading related issues. So we can directly access our services using ServiceName.methodName(). – Yug Singh Apr 1 at 18:47
  • 1
    If you can replace/change the DAO instance without having to change the service (any time), yes. Note that the DI is highly recommended to make the solution more testable. The more testable the better. Solutions should be first testable and then everything else (IMO). – Laiv Apr 1 at 19:09
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.