Recommendation of Project/Code Structure with Spring

Hi i am looking for an improvement of how i could improve the code structure to decouple frontend from other logic. Would be MVC or MVP an option or are there more proofed recommendations of how to get a clean structure? In my old app i tried to have kind of MVC but in becomes a mix (because i am the only dev on this project an no one cares :P) But i want to improve this (and myself) for the next project

Example:
DashboardView.java has a Grid
DashboardController.java which inject Database-Services, external API-Services do some calculations or what ever and and creates the Model like
Person.java

Currently i use the Service Classes directly in the view which works good as well. Isnt it already decoupled because the Service is responsible to get the data from database, manipulating it etc? For example:

Dummycode example:

PersonService personService;
//Inject PersonService from Spring via Constructor

Grid<Person> grid = new Grid()

grid.setItems(personService.findPersonsLeftTheCompany());

Looking forward to pratically tipps :slight_smile:

2 Likes

Hi Nico

Your dummycode looks perfect to me. Injecting all the @Service classes that are needed in each view is a good approach.

The Service class has methods that are tailored to the actual needs (findPersonsLeftTheCompany). Any businesslogic behind said method can be “hidden” from the ui. The @Repository layer can also be handled/injected by the service itself.

The Models (e.g. Person.class) can also be in a different package/module, or even added to the project via dependency.

The View classes can now focus on actual view things, and are not bloated with business-logic code. To me, that looks like a good MVC-like structure.


Now, I also want to give a tip to keep the view classes (the ones with @Route annotation) as clean as possible:

Whenever a component needs specific adjustments/configurations, I try to make my own class that extends said component. Instead of this in the view class:

Grid<Person> grid = new Grid(Person.class, false);
grid.addColumn(p -> p.getFirstAndLastName());
grid.addColumn(p -> p.getJobTitle());
grid.addColumn(p -> p.getLeaveCompanyDate());
grid.setSelectionModel(SelectionMode.MULTI);
grid.setItems(personService.findPersonsLeftTheCompany());
//etc
add(grid);

I will instead my own class PersonsLeftCompanyGrid:

public class PersonsLeftCompanyGrid extends Grid<Person> {
    public PersonsLeftCompanyGrid(PersonService personService) {
        super(Person.class, false);
        addColumn(p -> p.getFirstAndLastName());
        addColumn(p -> p.getJobTitle());
        addColumn(p -> p.getLeaveCompanyDate());
        setSelectionModel(SelectionMode.MULTI);
        setItems(personService.findPersonsLeftTheCompany());
        //etc
    }
}

This way the View class stays as compact as possible. Another side effect is that we now have a reusable component that could be used in multiple places.

// view
PersonsLeftCompanyGrid grid = new PersonsLeftCompanyGrid(personService);
add(grid);
3 Likes

Thanks a million! Your tio with extracting to own components makes a lot of sence! Thank you!

Did you already look at The Vaadin Way documentation? Application Layer | Building Apps | Vaadin Docs

1 Like

Bloody Edge recommendation by Olli! Might be good to promote it more (in a Blog Post)? :)

Edit: back to main topic, only thing I would like to add to Kaspar’s comment: Make sure you apply your “architecture” / style consistent. It makes big application so much easier to maintain, when e.g. all packages follow the same style of naming and class splitting.

1 Like

That’s a new section in the documentation that we have started to gradually build out. I’m sure we will blog about it once we reach some kind of 1.0 level of completeness.

2 Likes