preface

We’ve talked about naming and commenting, and code styles in Java programming. Today we’re going to talk about some practical Java programming techniques that can actually improve your code readability. This part of the skills are trivial, and it is difficult to list comprehensively. I just summarized some key skills that I think need you to gradually summarize and accumulate in practice.

1. Break up your code into smaller chunks

Most people have a habit of reading code, looking at the whole first and then the details. Therefore, we need to be modular and abstract thinking, good at refining large chunks of complex logic into classes or functions, shielding details, so that readers do not get lost in the details, which can greatly improve the readability of the code. However, we really only recommend refining classes or functions if the code logic is complex. After all, if the extracted function contains only two or three lines of code, you have to skip over it to read the code, which increases the reading cost.

Here’s an example to further explain. The code details are shown below. Before refactoring, was the initial section of the invest () function about time processing hard to understand? After refactoring, we abstracted this logic into a function named isLastDayOfMonth, which gives us a clear idea of what it does and whether today is the last day of the month. Here, we have greatly improved the readability of complex logical code by distilling it into functions.

// The code before refactoring

public void invest(long userId, long financialProductId) {

  Calendar calendar = Calendar.getInstance();

  calendar.setTime(date);

  calendar.set(Calendar.DATE, (calendar.get(Calendar.DATE) + 1));

  if (calendar.get(Calendar.DAY_OF_MONTH) == 1) {

​    return;

  }

  / /...

}

// Refactored code: the logic is clearer after refining the function

public void invest(long userId, long financialProductId) {

  if (isLastDayOfMonth(new Date())) {

​    return;

  }

  / /...

}

public boolean isLastDayOfMonth(Date date) {

  Calendar calendar = Calendar.getInstance();

  calendar.setTime(date);

  calendar.set(Calendar.DATE, (calendar.get(Calendar.DATE) + 1));

  if (calendar.get(Calendar.DAY_OF_MONTH) == 1) {

   return true;

  }

  return false;

}
Copy the code

2. Avoid excessive function parameters

In my opinion, a function with 3 or 4 parameters is acceptable, but a function with 5 or more parameters is considered too many, which affects the readability of the code and makes it difficult to use. There are two ways to deal with too many parameters.

Consider whether a function has a single responsibility and whether it can be split into multiple functions to reduce the number of arguments. The sample code looks like this:

public void getUser(String username, String telephone, String email);

// Split into multiple functions

public void getUserByUsername(String username);

public void getUserByTelephone(String telephone);

public void getUserByEmail(String email);
Copy the code

Encapsulate the parameters of a function as objects. The sample code looks like this:


// Encapsulate parameters as objects

public class Blog {

title: 33- Improve code quality20Bar programming specificationprivate String summary;

  private String keywords;

  private Strint content;

  private String category;

  private long authorId;

}

public void postBlog(Blog blog);
Copy the code

In addition, if the function is an exposed remote interface, encapsulating parameters as objects can also improve interface compatibility. When new parameters are added to the interface, the old remote interface caller may not need to modify the code to accommodate the new interface.

3. Do not use function arguments to control logic

Do not use Boolean identifiers in functions to control internal logic. If true, use one piece of logic and if false, use another. This clearly violates the single responsibility principle and interface isolation principle. I suggest splitting it into two functions for better readability. Let me give you an example.

public void buyCourse(long userId, long courseId, boolean isVip);

// Split it into two functions

public void buyCourse(long userId, long courseId);

public void buyCourseForVip(long userId, long courseId); But if the function is thetaprivateIf a function is private and has limited influence, or if the split function is often called at the same time, we can consider preserving the identity argument. The sample code looks like this:// Split the call into two functions

boolean isVip = false;

/ /... Omit other logic...

if (isVip) {

  buyCourseForVip(userId, courseId);

} else {

  buyCourse(userId, courseId);

}

// The invocation of the reserved identity argument is more succinct

boolean isVip = false;

/ /... Omit other logic...

buyCourse(userId, courseId, isVip);
Copy the code

In addition to the case where logic is controlled by a Boolean type as an identity parameter, there is also the case where logic is controlled by whether the parameter is null. In this case, we should also break it up into multiple functions. The split functions have clearer responsibilities and are hard to mistake. Specific code examples are as follows:

public List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {

  if(startDate ! =null&& endDate ! =null) {

​    // Query transactions between two time ranges

  }

  if(startDate ! =null && endDate == null) {

​    // Query all transactions after startDate

  }

  if (startDate == null&& endDate ! =null) {

​    // Query all transactions before endDate

  }

  if (startDate == null && endDate == null) {

​    // Query all transactions}}// Split into multiple public functions, more clear and easy to use

public List<Transaction> selectTransactionsBetween(Long userId, Date startDate, Date endDate) {

  return selectTransactions(userId, startDate, endDate);

}

public List<Transaction> selectTransactionsStartWith(Long userId, Date startDate) {

  return selectTransactions(userId, startDate, null);

}

public List<Transaction> selectTransactionsEndWith(Long userId, Date endDate) {

  return selectTransactions(userId, null, endDate);

}

public List<Transaction> selectAllTransactions(Long userId) {

  return selectTransactions(userId, null.null);

}

private List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {

  // ...

}
Copy the code

More original reading:javawu.com