I have a Java Spring-boot application which has layers(packages):
Inside My Domain
I have two database classes
I have many classes in my service package
which uses methods of both MysqlDBManager
as well as MongoDBManager
.
If I use instances of MysqlDBManager' and
MongoDBManager` on my service class directly then service layer will get tightly coupled with domain layer.
To solve this problem I have created a class named **DBManager**
in my domain package which behaves as a proxy class which calls MysqlDBManager' and
MongoDBManager` based on the use case internally.
Now service layer, instead of calling MysqlDBManager' and
MongoDBManagerdirectly they call
DBManager, which internally calls
MysqlDBManager' and MongoDBManager
.
Hence now my service class is not tightly coupled with domain layer.
Below are my classes which resembles my use-case.
MongoDBManager class:
Class MongoDBManager {
public saveUserDocs(String docs) {
//.....
}
}
MysqlDBManager class:
Class MysqlDBManager {
public saveUserData(List<String> rows) {
//.....
}
}
DBManager class:
Class DBManager {
@Autowired
private MysqlDBManager mysqlDBManager;
@Autowired
private MongoDBManager mongoDBManager;
public saveUserData(List<String> rows) {
mysqlDBManager.saveUserData(rows);
}
public saveUserDocs(String docs) {
mongoDBManager.saveUserDocs(docs);
}
}
Service class:
class Service {
@Autowired
private DBManager dBManager;
//....... code here
dBManager.saveUserData(rows);
dBManager.saveUserDocs(docs);
}
My Question is:
Is this (as explained above) a good way to make my application layers loosely coupled or their exist better ways to do this?
Loosely-coupled software means routines (modules, programs) are called by an application and executed as needed. For example, Web services employ loose coupling. When a function is required, the appropriate Web service module is executed.
In computer science, the term loosely coupled refers to different systems that can interoperate with minimal dependencies on each other. For example, if a client application communicates to the server application using only a well-defined web service, the two layers can be said to be loosely coupled.
To achieve loose coupling, one should use abstract classes or interface while performing inheritance. The following examples will make the concept clearer. Output: Inside the foo method of derived class.
You approach is fine, it is look like some sort of Facade design pattern, but I would recommend more traditional way.
You already have spring as IoC container, so all you have to do is to extract interfaces from your *DBManager
-classes and tell spring about your implementations. Then you will be able to inject an actual implementation using an interface, which in turn might resides in a totally different package. Therefore coupling will cease to exist.
Here is an example.
DataStorage contract:
package root;
import java.util.List;
public interface UserDataStorage {
void saveUserData(List<String> rows);
}
DocumentStorage contract:
package root;
public interface UserDocumentStorage {
void saveUserDocs(String docs);
}
DataStorage implementation:
package root.domain;
import org.springframework.stereotype.Service;
import root.UserDataStorage;
import java.util.List;
@Service
public class MysqlDBManager implements UserDataStorage {
@Override
public void saveUserData(List<String> rows) {
System.out.println("Saving data....");
}
}
DocumentStorage implementation:
package root.domain;
import org.springframework.stereotype.Service;
import root.UserDocumentStorage;
@Service
public class MongoDBManager implements UserDocumentStorage {
@Override
public void saveUserDocs(String docs) {
System.out.println("Saving docs....");
}
}
Then your service classes might look like this (please pay attention there is no reference to domain
package:
package root.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import root.UserDataStorage;
import root.UserDocumentStorage;
import java.util.Collections;
@Service
public class MyService {
private final UserDataStorage dataStorage;
private final UserDocumentStorage documentStorage;
@Autowired
public MyService(UserDataStorage dataStorage, UserDocumentStorage documentStorage) {
this.dataStorage = dataStorage;
this.documentStorage = documentStorage;
}
public void callMe() {
this.dataStorage.saveUserData(Collections.emptyList());
this.documentStorage.saveUserDocs("Document1");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With