Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling one DAO from another DAOFactory

Currently, my application architecture flows like this:

View → Presenter → Some asynchronous executor → DAOFactory → DAO (interface) → DAO (Impl)

For the time being, this kind of architecture works; mainly because I've only been needing one kind of DAO at the moment. But as the requirement grows, I'd need to expand to multiple DAOs, each with their own implementation on how to get the data.

Here's an illustration to my case:

enter image description here

The main headache comes from FooCloudDao which loads data from an API. This API needs some kind of authentication method - a string token that was stored during login (say, a Session object - yes, this too has its own DAO).

It's tempting to just pass a Session instance through FooDaoFactory, just in case there's no connection, but it seems hackish and counter-intuitive. The next thing I could imagine is to access SessionDAOFactory from within FooDaoFactory to gain instance of a Session (and then pass that when I need a FooCloudDAO instance).

But as I said, I'm not sure whether or not I could do a thing like this - well, may be I could, but is it this really the correct way of doing it?

like image 721
Hadi Satrio Avatar asked Nov 09 '22 10:11

Hadi Satrio


1 Answers

I presume your problem is actually that FooCloudDao has different "dependencies" than other components, and you want to avoid passing the dependencies through every class on the way.

Altough there are quite some design patterns which would kind of solve your problem, I would suggesting taking a look on Dependency Injection / Inversion of Control principles and frameworks. What you would do with this is:

  1. You would create an interface for what your FooCloudDao needs, for example:
interface ApiTokenProvider {
     string GetToken();
 }
  1. You would create and implementation of that interface which would get it from the session or wherever that thing comes from:
class SessionBasedApiTokenPrivider implements ApiTokenProvider {
    public string GetToken() {
        // get it from the session here
    }
}
  1. The defined class above would need to be registered with IoC container of your choice as the implementation of ApiTokenProvider interface (so that whoever asks for ApiTokenProvider will be decoupled from the actual implementation -> the container would give him the proper implementation).

  2. You would have something called constructor injection on your FooCloudDao class (this is later used by the container to "inject" your dependency):

public FooCloudDao(ApiTokenProvider tokenProvider) {
    // store the provider so that the class can use it later where needed
}
  1. Your FooDaoFactory would use the IoC container to resolve the FooCloudDao with all its dependencies (so you would not instantiate the FooCloudDao with new)

When following these steps you will make sure that:

  • FooDaoFactory remains clean of passing dependecies through
  • you make your code much more testable because you could test your FooCloudDao without the real session (you could only give in the fake interface implementation)
  • and all other benefits which come with Inversion of Control...

Note on the session: if you encounter the problem of getting the session in the SessionBasedApiTokenProvider, most of the time the session itself is also registered with the IoC controller, and injected where needed.

like image 163
Denis Biondic Avatar answered Nov 15 '22 11:11

Denis Biondic