So I am writing a project using Spring Boot. All of my logic resides in @Service classes. I have separated each service class based on entity. For example - If I have two independent entities A and B, then each has following different classes:
- RestController
- DTOs
- Service
- Repository
- Entity
When I start writing code for a feature, it starts with RestController (an api call basically), which calls a method of service class. This method is public and initially is very small, just input and output. This makes it easy to test (unit tests).
@Service
public AService {
public AResponseDto rootMethod(SomeChunkyDto someChunkyDto) {
return new AResponseDto();
}
}
However, as I add more logic to the method, it becomes bulkier and unreadable.
public AResponseDto rootMethod(SomeChunkyDto someChunkyDto) {
// Logic 1
// Logic 2
// Logic 3
// Logic 4
AResponseDto aResponseDto = // Logic 5
return aResponseDto;
}
So, I refactor:
private String helperMethod1(/* Less chunky, small arguments - preferably primitive data types */) {
// Logic 1
// Logic 2
}
private String helperMethod2(/* Less chunky, small arguments - preferably primitive data types */) {
// Logic 3
// Logic 4
}
public AResponseDto rootMethod(SomeChunkyDto someChunkyDto) {
helperMethod1(...args);
helperMethod2(...args);
AResponseDto aResponseDto = // Logic 5
return aResponseDto;
}
Of course, the actual code is larger and complex. I tried to simplify.
So here is the issue - Those private methods contain logic that should be tested. As they are private, the only way to test them is by testing rootMethod. This makes things complicated, as rootMethod has a bulky input. It is time consuming.
Another thing I have read is that methods with logic shouldn't be private. That way they can be tested very easily. But then they are accessible to other classes which have no use of it.
Helper methods which contain logic that can be reused in other classes, I make them public. But most of the helper methods are specific to a particular entity and their use is limited to that particular service class.
I am not sure what the right approach is here. Should I make the private methods public? Currently I am testing them via rootMethod. But then it is not much of a unit test is it?
Edit: A friend of mine suggested that I should create a separate class for helper methods, like AHelper which will contain helperMethod1 and helperMethod2. That way methods can be public and they can be accessed in @Service class by injecting AHelper as a dependency.
Not sure if this is correct way to do as methods are public and accessible by classes that don't require them. Another thing is that the project is quite small, most probably won't scale in future. So I am trying to keep less files (classes).