Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make application layer loosely coupled

I have a Java Spring-boot application which has layers(packages):

  • Controller(controller class)
  • Service (business logic)
  • Domain (database layer)

Inside My Domain I have two database classes

  • MysqlDBManager
  • MongoDBManager

I have many classes in my service package which uses methods of both MysqlDBManager as well as MongoDBManager.

If I use instances of MysqlDBManager' andMongoDBManager` 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' andMongoDBManager` based on the use case internally.

Now service layer, instead of calling MysqlDBManager' andMongoDBManagerdirectly they callDBManager, which internally callsMysqlDBManager' 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?

like image 327
Prakash P Avatar asked Oct 10 '17 07:10

Prakash P


People also ask

What is a loosely coupled application?

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.

Is a loosely coupled application layer architecture?

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.

How do you create a loosely coupled application in Java?

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.


1 Answers

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");
    }
}
like image 145
Bohdan Levchenko Avatar answered Oct 14 '22 10:10

Bohdan Levchenko