Lets say we have typical trivial CRUD app:
- user sends data
- controller catch the request and map it
- controller sends data to service for processing
structure:
- api
- request
- TestProjectRequest.java
TestProjectController.java
- service
- testProject
- TestProjectService.java
In code:
@RestController("testProject")
@AllArgsConstructor
public class TestProjectController {
private final TestProjectService service;
@PostMapping("/")
public void createTestRequest(TestProjectRequest testRequest, HttpServletRequest request) {
service.process(...);
}
}
@Getter
@Setter
public class TestProjectRequest {
....
}
Now, the request that came to controller may or may not contain all neccessary informations for the service and we may need to enrich the data.
What is actually good practice for mapping data like this? In scenario where we wanted to enrich TestProjectRequest
for example of some data present in HttpServletRequest
we can create another class for it:
@Getter
@Setter
public class EnrichedTestProjectRequest {
// data from TestProjectRequest
// enriched data
}
and in controller create mapper:
@RestController("testProject")
@AllArgsConstructor
public class TestProjectController {
private final TestProjectService service;
@PostMapping("/")
public void createTestRequest(TestProjectRequest testRequest, HttpServletRequest request) {
EnrichedTestProjectRequest enrichedRequest = enrichRequest(testRequest, request);
service.process(enrichedRequest);
}
}
Now we have TestProjectService
as:
public interface TestProjectService {
void process(EnrichedTestProjectRequest request);
}
Since the TestProjectService
method process
now consumes EnrichedTestProjectRequest
, the definition of EnrichedTestProjectRequest
should be in in service.testProject
package, as it expose API and we should follow lose coupling/high cohesion. However by following this logic, even if we did not enrich the request we should map the TestProjectRequest
to some class that is exposed by module of TestProjectService
. And this seems like it makes sense but also is a lot of work to follow some good practices.
What is the correct view on this? Does it make or make not sense to map data like this? Some good practices suggests every module should be stand alone, so if they expose some API, they should also expose the data structures that API consumes.