Best practice for transferring data to the service layer

I am working on a web application in spring following the MVC pattern and was wondering what is considered the "best practice" for creating a robust service layer. The reason for this question is the following situation:

The page for editing user information is loaded. After submitting this form, I collect all my data in my controller method in a specific Command class containing only the data needed for the subsequent action (user update).

Now I can think of several situations to pass this information to my service layer:

  • Passing the command itself: userService.save (command);
  • Passing the model class selected in the controller: userService.save (user);
  • Passing both the model class and the command: userService.save (user, command);
  • Passing all parameters individually: userService.save (command.getName (), ...)

In my opinion, passing the command class itself looks like the most elegant solution, since I can first fully validate all the values ​​with the framework and then pass them to my service. I'm worried that when I call a method from another class (not through my form / controller), I might populate that command object with invalid data, leading to possible errors in the service level.

What would you recommend and why?

+3


source to share


4 answers


Seeing that I have the following ideas Passing the command itself: userService.save (command);

This may not be a good idea as your service level is unreasonable depending on the Command object

Passing a model class, fetched in the controller: userService.save(user);

      

I will vote for this. Service level is just what he really should have known

Passing both a model class and the command: userService.save(user, command);

      



Not. Same as the first option

Passing all of the parameters individually: userService.save(command.getName(), ...)

      

Hmmmm ... not sure ... Perhaps in the future this will be the main task.

I think if you want to do the validation, Use validation util classes to do the validation 
    which can be used for both Service and UI layer. Here a lot validation can be centralized.

      

+1


source


In his MVC book, Dino Esposito recommends creating a "worker" class that takes and returns a viewmodel. The controller calls the worker using the viewmodel and then worker delegates as needed. I haven't used it in practice, but in theory it seems like a good solution.



0


source


Any option using the Command object will cause problems. It breaks the clutch. Now your service level is closely related to the service level. Please don't do this.

(EDIT: In my answer below, when I say Model for the View Layer I'm talking about the View Model, and for the Service Layer it's the Domain Model) Sending a Model Object looks like a good option. But that depends on how the model was created. In some cases the presentation layer will need a different model structure and the service layer will need a moderatley / completely different structure.

If both levels have different needs, you need to create 2 models. Thus, the structure of the service layer structure should not change when the presentation layer changes. This is important because a service can have multiple consumers and it might not change when the presentation layer changes.

If they don't have a different structure, I would still create them in terms of the service layer, since the service is a real reusable component here.

0


source


A good template for working with commands in multi-tier systems is to have a CommandBus service that routes your commands to their specific handlers. This way you disconnect your controller from its services (when it connects to the common routing system).

commandBus.handle(command);

You have to do the extra work of configuring the command bus handlers, but it will pay off in the long run when you can reuse this routing information:

commandBus.register(commandType, handlerService);

and then you should be able to postpone command checking in the service commandBus

(although that would mean some confusion of problems for commandBus)

commandBus.registerValidator(commandType, validatorsCollection);

0


source







All Articles