Issue
I am building an application using the Spring MVC framework and there is an architectural issue that I cannot clearly resolve. My problem is that I don't fully understand which part (layer) of the application should be responsible for the control flow (by flow control I mean the display of successive views - pages).
Controllers in Spring MVC are some kind of adapter between the view and the application. Services, on the other hand, are implemented based on business logic.
Suppose we have a controller that supports a certain endpoint:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
// business logic calculates some stuff...
if(fooService.bar()) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
In the above example, the controller decides which view to display based on the result of the fooService, thus managing the flow of control. If there were many conditions, it could lead to ugly code in controller.
Let's consider the next example:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
session.fooBarResult = fooService.bar(); // logic calculates some stuff and saves in session
State newState = stateMachine.sendEvent(PAGE_FINISHED_JOB);
if(newState == State.PAGE_HELLO) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
In this example, the decision which view to display is made in terms of services and business logic. The state machine receives the event and then based on the session and the encoded conditions, it makes a decision to select the next view. Then the controller, based on the new state, prepares the correct view and returns it. The controller knows nothing about the control flow logic.
Which solution for deciding whether to display the next view (page) is better? Are there other more interesting solutions?
Solution
My rule of thumb are :
The service layer should not aware the existence of the UI . It should not have any knowledge about the ui such that service class is decoupled to the ui and can be easily reused in other contexts (e.g exposed it as API , another new ui in the future etc.) So if you find there are service classes that nees to depend on some classes from spring-mvc or servlet etc., something should go wrong.
The logic related to the ui such as what is the next screen to be display should be placed in the controller layer.
The controller layer should keep thin. Try to push as much as the business logic code to a service layer.
So the controller layer should decide the next view to be displayed. It does not make sense to put it in the service layer. Otherwise the service layer will be coupled to the UI (see my point 1)
Answered By - Ken Chan
Answer Checked By - Cary Denson (JavaFixing Admin)