Code is the blueprint of any software and making code easier to read should be one of the fundamental principles followed by all developers.
Code formatting is opinionated and individualistic. But looking at code for more than a decade, I found there are codes that just look easier to read. They seem to follow a set of best practices that can be useful for all of us developers.
-
Use fewer comments
Yes, that’s right. While it sounds counter-intuitive, it looks to reduce the fatigue of the reader. The code should be self-explanatory. Example:public Booking createBooking(@RequestBody Booking booking, RestTemplate restTemplate) { // In a "real" environment this would at the very least be a property/environment variable, but ideally something like Service Discovery like Eureka Restaurant restaurant = restTemplate.getForObject("http://localhost:8080/restaurants/" + booking.getRestaurantId(), Restaurant.class); // check if the restaurant actually exists if (restaurant == null) { throw new RestaurantNotFoundException(booking.getRestaurantId()); } // check if the number of diners in the booking is more than the number of seats in the restaurant if (restaurant.capacity() < booking.getNumberOfDiners()) { throw new NoAvailableCapacityException("Number of diners exceeds available restaurant capacity"); } // if we got this far, the booking is valid and we can save it return repository.save(booking); }
This can be reduced to
public Booking createBooking(@RequestBody Booking booking, RestTemplate restTemplate) { Restaurant restaurant = restTemplate.getForObject("http://localhost:8080/restaurants/" + booking.getRestaurantId(), Restaurant.class); checkIfRestaurantExists(restaurant, booking.getRestaurantId()); checkIfCapacityExists(restaurant, booking.getNumberOfDiners()); return repository.save(booking); } private void checkIfRestaurantExists(Booking booking, Restaurant restaurant) { if (restaurant == null) { throw new RestaurantNotFoundException(booking.getRestaurantId()); } }//etc
- Using code formatters in IDE. I prefer to use google java format.
- Using maven formatter plugin to auto format code on build
- Using Intellij IDE inspection and intent actions to refactor code Reference: https://lightrun.com/best-practices/the-quick-and-easy-guide-to-reformatting-code-in-intellij/
- Using static code analysis tools like sonarqube to catch issues like deep nesting.
- Fluent APIs
When using Java’s fluent API to write a functional style of programming, the operator should be in the new line.
Correct.onException(IllegalArgumentException.class) .handled(true) .setHeader(Exchange.CONTENT_TYPE, constant("text/plain")) .setBody().constant("Invalid request data");
Incorrect
.onException(IllegalArgumentException.class). handled(true). setHeader(Exchange.CONTENT_TYPE, constant("text/plain")). setBody().constant("Invalid request data");
- Test names
test should follow the BDD convention: givenX_whenY_thenZ
the _given_ part is optional, but the other two are not
example:whenSendingAPost_thenCorrectStatusCode
The delimiter (underline) should only be used between these sections, and not anywhere else
for example - this isn’t correct:whenSomethingHappens_andSomethingElse_thenSuccessfull
-
tests - structure
always use a new line before the then section of the test for example (notice the new line):public void whenSomething_thenSomethingElse { // some preparation code belonging to the when section assert( ...) }
- code - new lines
here are a few suggestions of where to add (and not add new lines)
- add a new line before the comment: // getters and setters
- add a new line between the given, when and then sections of a test
- code - breaking a new line into multiple lines
example 1 - incorrectpublic Object process(BeanContext context, Object object, String name, Object value) {
example 1 - correct
public Object process( BeanContext context, Object object, String name, Object value) {
example 2 - incorrect
@RequestMapping( value = "/ex/foos", headers = { "key1=val1", "key2=val2" }, method = GET)
example 2 - correct
@RequestMapping( value = "/ex/foos", headers = { "key1=val1", "key2=val2" }, method = GET )
example 3 - incorrect
public void givenDestWithNullReverseMappedToSourceAndLocalConfigForNoNull _whenFailsToMap_thenCorrect() {
example 3 - correct
Either put the entire method on a new line or rename it; definitely don’t break a method name in the middle when breaking a line with an operator, put the operator on the new lineexample 4 - incorrect
CompletableFuture<String> completableFuture = new CompletableFuture<>();
example 4 - correct
CompletableFuture<String> completableFuture = new CompletableFuture<>();
References
- Reference: [do-we-need-comments-in-our-code](https://trishagee.com/2021/05/14/do-we-need-comments-in-our-code/#more-1535)
- Baeldung
Comments