preface

Recently, I finished the requirements of the Version of December, and there are some codes that do not think deeply enough, so I write a summary. I hope we can think more and summarize more in daily code writing. Come on! At the same time, where there is wrong, also hope to point out.

Making the address

Github.com/whx123/Java…

First, complex logic conditions, whether the order can be adjusted to make the program more efficient.

Suppose the business requirement is this: the member, when logging in for the first time, needs to send a thank you text message. If you don’t think about it, the code is written like this

if(isUserVip && isFirstLogin){
    sendMsg();
}
Copy the code

Suppose there are five requests in total, three for isUserVip and one for isFirstLogin. So the above code, isUserVip is executed 5 times, isFirstLogin is executed 3 times, as follows:

How about adjusting the order of isUserVip and isFirstLogin?

if(isFirstLogin && isUserVip ){
    sendMsg();
}
Copy the code

IsFirstLogin is executed 5 times, isUserVip is executed 1 times, as follows:

Is your program more efficient?

Does your program inadvertently create unnecessary objects?

For example, to determine whether a user’s membership is valid, there is usually a code similar to the following:

Public Boolean specifies whether the user membership is validisUserVIPValid() {
  Date now = new Date();
  Calendar gmtCal = Calendar.getInstance();
  gmtCal.set(2019, Calendar.JANUARY, 1, 0, 0, 0);
  Date beginTime = gmtCal.getTime();
  gmtCal.set(2020, Calendar.JANUARY, 1, 0, 0, 0);
  Date endTime= gmtCal.getTime();
  return now.compareTo(beginTime) >= 0 && now.compareTo(endTime) <= 0;
}

Copy the code

However, each time the isUserVIPValid method is called, Calendar and Date objects are created. New Date = New Date = New Date = New Date = New Date = New Date = New Date

public class Test { private static final Date BEGIN_TIME; private static final Date END_TIME; static { Calendar gmtCal = Calendar.getInstance(); gmtCal.set(2019, Calendar.JANUARY, 1, 0, 0, 0); BEGIN_TIME = gmtCal.getTime(); gmtCal.set(2020, Calendar.JANUARY, 1, 0, 0, 0); END_TIME = gmtCal.getTime(); } // Check whether the user membership is valid public BooleanisUserVIPValid() {
        Date now = new Date();
        returnnow.compareTo(BEGIN_TIME) >= 0 && now.compareTo(END_TIME) <= 0; }}Copy the code

Three, when querying the database, have you checked more data?

As we all know, library search is a time-consuming operation, especially when the data volume is large. So, when querying DB, we take what we need, there is no need to do everything.

Suppose the business scenario is this: Query whether a user is a member. Have seen the implementation code is like this…

List<Long> userIds = sqlMap.queryList("select userId from user where vip=1");
boolean isVip = userIds.contains(userId);
Copy the code

Why check all the data first and then check whether the useId is included to determine whether the useId is a member? If you pass the userId directly into SQL, doesn’t it smell good? As follows:

Long userId = sqlMap.queryObject("select userId from user where userId='userId' and vip='1' ") Boolean isVip = userId! =null;Copy the code

In fact, in addition to passing the query criteria and avoiding the database from retrieving extra data, we can also use select fields instead of SELECT * to make the program more efficient.

Four, added a line of notification class code, can not affect the main process bar.

Imagine a business process like this: You need to add a text message to notify your fans when the user logs in. It is easy to think of the implementation process as follows:

Assuming that the system providing sendMsgNotify hangs or the call to sendMsgNotify fails, then the user fails to log in…

A notification feature made the main log-in process unavailable, obviously missing the point. So is there a way to have it both ways? If yes, send SMS interface to catch exception processing, or another thread asynchronous processing, as follows:

Therefore, when we add non-essential, scalable interfaces such as notification classes, we should take a moment to consider whether it will affect the main process and how best to handle it.

5. Be sensitive to null Pointers. For example, when using Equals, place constant or determinate values to the left.

NullPointException is so common in the Java world that we should think twice before writing code to avoid the low-level NullPointException problem.

For example, in the following business scenarios, the following code is often seen to determine whether the user is a member:

boolean isVip = user.getUserFlag().equals("1");
Copy the code

If let this line of code on the production environment, when you suddenly look back, may be the empty pointer bug, in the lights dim. Obviously, this could result in a null pointer exception, because User.getUserFlag () could be null.

How do you avoid the null pointer problem? Put the constant 1 on the left, as follows:

boolean isVip = "1".equals(user.getUserFlag());
Copy the code

Do your key business codes have logs to protect them?

There should be enough logs to protect business-critical code wherever it is located.

For example: you make a transfer, transfer millions, transfer failed, then the customer complains, then you haven’t printed the log, think of the hot water in the predicament, but there is nothing you can do…

So, what log information do you need for your money transfer business? At least, before the method call, the input parameter needs to print, after the interface call, need to catch the exception, and print the exception related log, as follows:

public void transfer(TransferDTO transferDTO){
    log.info("invoke tranfer begin"); // Prints the entry parameter log.info("invoke tranfer,paramters:{}",transferDTO);
    try {
      res=  transferService.transfer(transferDTO);
    }catch(Exception e){
     log.error("Transfer fail, CIfNO :{}, account :{}", transferTo.getCifNo (), transferTo.getAccount ()) log.error()"transfer fail,exception:{}",e);
    }
    log.info("invoke tranfer end");
    }
Copy the code

In addition to printing enough logs, we also need to pay attention to the log level is not confused, do not print info logs, you should not print error logs, alarm in the middle of the night to urge you to get up to troubleshoot problems.

7. For functions with a large number of lines, can they be divided into smaller functions to optimize?

When we maintain old code, we often see a lump of code, some functions hundreds or even thousands of lines, it is difficult to read.

Suppose you now have the following code

public class Test {
    private String name;
    private Vector<Order> orders = new Vector<Order>();

    public void printOwing() {
        //print banner
        System.out.println("* * * * * * * * * * * * * * * *");
        System.out.println("*****customer Owes *****");
        System.out.println("* * * * * * * * * * * * * * * *");

        //calculate totalAmount
        Enumeration env = orders.elements();
        double totalAmount = 0.0;
        while(env.hasMoreElements()) { Order order = (Order) env.nextElement(); totalAmount += order.getAmout(); } / /print details
        System.out.println("name:" + name);
        System.out.println("amount:"+ totalAmount); }}Copy the code

Divided into small functions with a single function:

public class Test {
    private String name;
    private Vector<Order> orders = new Vector<Order>();

    public void printOwing() {

        //print banner
        printBanner();
        //calculate totalAmount
        double totalAmount = getTotalAmount();
        //print details
        printDetail(totalAmount);
    }

    void printBanner(){
        System.out.println("* * * * * * * * * * * * * * * *");
        System.out.println("*****customer Owes *****");
        System.out.println("* * * * * * * * * * * * * * * *");
    }

    double getTotalAmount(){
        Enumeration env = orders.elements();
        double totalAmount = 0.0;
        while (env.hasMoreElements()) {
            Order order = (Order) env.nextElement();
            totalAmount += order.getAmout();
        }
        return totalAmount;
    }

    void printDetail(double totalAmount){
        System.out.println("name:" + name);
        System.out.println("amount:"+ totalAmount); }}Copy the code

If a function is too long or a piece of code needs comments to understand its purpose, consider breaking it up into functional units and defining short, clear function names. This makes the code more elegant.

Eight, some variable factors, such as red envelope skin and so on, make configuration will be better?

If the product raised a red envelope demand, Christmas, red envelope skin for Christmas, Spring Festival, red envelope skin and so on.

If in code write dead control, there can be code like the following:

if(duringChristmas){
   img = redPacketChristmasSkin;
}else if(duringSpringFestival){ img = redSpringFestivalSkin; }...Copy the code

If by the time of the Lantern Festival, the operation sister suddenly has the idea that the red envelope skin is changed to lantern related, at this time, is it necessary to modify the code and re-release?

From the beginning, implement a red envelope skin configuration table, make red envelope skin configuration? To change the red envelope skin, just modify the table data.

9, redundant import class, local variables, no reference should be deleted

If you see unused import classes, unused local variables, etc., delete them:

These unreferenced local variables, if they are not used, delete them, they are not old women’s red, it will be more mellow. It will still compile together, which means it will still consume resources.

SQL > select * from ‘SQL’ where index = ‘index’;

When querying a table with a large amount of data, we need to confirm three things:

  • Whether your table is indexed
  • Whether your query SQL matches the index
  • Is there room for optimization in your SQL

In general, if the size of the table exceeds 100,000, you should consider adding an index to the table. In what cases does an index fail? The index is invalid due to the like wildcard and index column operation. Interested friends can have a look at my article. Essential for backend programmers: Ten miscellaneous diseases of index failure

Should your method return an empty collection or null?

If null is returned, the caller may throw a null-pointer exception if it forgets to check. If you return an empty collection, you can eliminate the problem.

Mybatis will return a null set if the result is null.

Is case

public static List<UserResult> getUserResultList() {return Collections.EMPTY_LIST;
}
Copy the code

Try to specify the size of the collection when initializing it

The Ali development manual recommends this

Assuming your map stores about 15 elements, the best way to write it is as follows

//initialCapacity = 15/0.75+1=21 Map Map = new HashMap(21); And becausehashHashMap = new HashMap(32);Copy the code

When querying a database, if too much data is returned, consider batching.

Suppose your order table has 100,000 data to update status. Do not query all unupdated orders at once, but in batches.

Example:

List<Order> list = sqlMap.queryList("select * from Order where status='0'");
for(Order order:list){
  order.setStatus(1);
  sqlMap.update(order);  
}
Copy the code

Is:

Integer count = sqlMap.queryCount(select count(1) from Order where status ='0');
while(true){
    int size=sqlMap.batchUpdate(params);
    if(the size < 500) {break; }}Copy the code

14. Does your interface take idempotence, concurrency into account?

What is idempotence? One and more requests for a resource should have the same result for the resource itself. That is, any number of executions have the same impact on the resource itself as a single execution.

Why idempotent?

  • Users can’t generate multiple orders after clicking on the APP for several times
  • Users because the network is stuck, repeatedly click to send a message, the recipient can not receive the same message repeatedly.

Assume a business scenario:

Click the download button, and the system starts to download the file. Click download again, and a message is displayed indicating that the file is being downloaded.

Some people do this:

Integer count = sqlMap.selectCount("select count(1) from excel where state=1");
if(count<=0){
    Excel.setStatus(1);
    updateExcelStatus();
    downLoadExcel();
}else{
    "File downloading in progress"
}
Copy the code

Let’s see, what might be the problem with two requests coming in?

Execution process:

  • In the first step, A queries for files that are not being downloaded.
  • Step 2, B queries for files that are not being downloaded.
  • Step 3, A starts downloading the file
  • Section four, B starts downloading files

Obviously, there is a problem with both files being downloaded at the same time. The right way to do it?

if(updateExcelStatus(1){
    downLoadExcel(); 
}else{
    "File downloading in progress"
}
Copy the code

Isn’t it beautiful to augment your utility class with a private constructor?

The methods of utility classes are static and can be called directly from the class. However, some callers may instantiate first and then call with objects, which is not good. How can you avoid this and get your utility classes into a controlled state by adding private constructors

public class StringUtis{
       private StringUtisPublic static bool validataString(String STR){}}Copy the code

Sixteen, the basic unchanged user data, caching, whether the performance has been improved

If your interface needs to query the database many times, retrieve various data, and then perform various kinds of operations based on the data, then the performance of the interface is not good. Typical application scenarios include: live broadcast list.

So, how do you optimize? Analyze the parts of the data that you sort, the data that is changing in real time, continue to look up the DB, the data that is not changing, such as the age of the user and so on, do a timed task, pull it from the DB into the cache, directly out of the cache.

So, the thinking at this point is to use caching appropriately at the right time.

To complement…

Personal public account

  • If you are a good boy who loves learning, you can follow my public account and study and discuss with me.
  • If you feel that this article is not correct, you can comment, you can also follow my public account, private chat me, we learn and progress together.
  • Github address: github.com/whx123/Java…