There are 16 good habits for writing code, which can reduce non-business bugs by 80%

This article is my micro-channel public number, " the Java back-end technology to see the" Author: pick up snail boy. Share if you think it’s pretty good, and respect the originality

Preface

Every good habit is a wealth. This article has compiled 16 good habits for writing code, each of which is very classic. By developing these habits, you can avoid most non-business bugs! I hope it helps everyone, thanks for reading, come on~

1. After modifying the code, remember to test yourself

"After changing the code, self-test" is a basic quality that every programmer must have. Especially don't have this fluke "Psychology: I just changed a variable or I only changed a line of configuration code, no need to self-test." After changing the code, try to ask yourself to test it, you can avoid many unnecessary bugs.

2. Try to check the method input parameters

Entry verification is also a basic quality that every programmer must have. Your method handles "parameters must be verified first". For example, whether the input parameter is allowed to be empty, and whether the input parameter length meets your expected length. Try to get into a habit of this. Many "low-level bugs" are caused by "not checking parameters".
If your database field is set to varchar(16), and the other party sends a 32-bit string, you do not verify the parameters and "insert the database directly is abnormal".

3. When modifying the old interface, consider the compatibility of the interface.

Many bugs are caused by modifying the old external interface, but they are "not compatible". The key problem is mostly serious, which may directly lead to the failure of system release. Novice programmers can easily make this mistake~
So, if your requirement is to modify the original interface, especially if this interface is to provide external services, you must consider interface compatibility. For example, for example, the dubbo interface originally only received A and B parameters. Now you add a parameter C, you can consider this.

//老接口
void oldService(A,B);{
    
    
  //兼容新接口,传个null代替C
  newService(A,B,null);
}
//新接口,暂时不能删掉老接口,需要做兼容。
void newService(A,B,C);

4. For complex code logic, add clear comments

When writing code, there is no need to write too many comments. Good method variable naming is the best comment. However, if it is "code with complex business logic", it is really necessary to write "clear comments". Clear notes are more conducive to subsequent maintenance.

5. After using the IO resource stream, it needs to be closed

Everyone should have had this experience. If the Windows system desktop "opens too many files" or system software, it will feel that the computer is stuck. Of course, our Linux server is also the same. If the IO resource stream is not closed during normal operation of files, or database connections, then this IO resource will be occupied by it, so that others have no way to use it, which causes "resource waste".

So after using the IO stream, you can use finally to close it.

FileInputStream fdIn = null;
try {
    
    
    fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
    
    
    log.error(e);
} catch (IOException e) {
    
    
    log.error(e);
}finally {
    
    
    try {
    
    
        if (fdIn != null) {
    
    
            fdIn.close();
        }
    } catch (IOException e) {
    
    
        log.error(e);
    }
}
JDK 7 之后还有更帅的关闭流写法,「try-with-resource」。
/*
 * 关注公众号,捡田螺的小男孩
 */
try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) {
    
    
    // use resources   
} catch (FileNotFoundException e) {
    
    
    log.error(e);
} catch (IOException e) {
    
    
    log.error(e);
}

6. The code takes measures to avoid runtime errors (such as array boundary overflow, division by zero, etc.)

In daily development, we need to take measures to avoid runtime errors such as "array boundary overflow, divisible by zero, null pointer" and other runtime errors.
Similar codes are more common:

String name = list.get(1).getName(); //list可能越界,因为不一定有2个元素哈
所以,应该「采取措施,预防一下数组边界溢出」,正例:
if(CollectionsUtil.isNotEmpty(list)&& list.size()>1){
    
    
  String name = list.get(1).getName(); 
}

7. Try not to make remote calls or database operations in the loop, and give priority to batches.

Remote operations or database operations are "more network and IO resource-consuming", so try not to call remotely in a loop or operate the database in a loop. You can "check it back in batches at once and try not to check it multiple times." (But, don’t check too much data at one time, but 500 sauces in batches)

正例:
remoteBatchQuery(param);
反例:
for(int i=0;i<n;i++){
    
    
  remoteSingleQuery(param)
}

8. After writing the code, think about how multi-threaded execution will happen, and pay attention to concurrency issues

Some business scenarios we often see are to check whether there is a record first, and then perform the corresponding operation (such as modification). However, the combination of (query + modification) is not an atomic operation. If you have multiple threads in your brain, you will find that there is a problem. The
counterexample is as follows:

if(isAvailable(ticketId){
    
     
    1、给现金增加操作 
    2deleteTicketById(ticketId) 
}else{
    
     
    return "没有可用现金券";
}

In order to understand it more easily, look at this flowchart:
Insert picture description here

1. Thread A plus cash
2. Thread B plus cash
3. Thread A deletes the ticket flag
4. Thread B deletes the ticket flag
Obviously there is a "concurrency problem", the positive example should "use the atomicity of the database delete operation", as follows:

if(deleteAvailableTicketById(ticketId) == 1){
    
     
    1、给现金增加操作 
}else{
    
     
    return “没有可用现金券” 
}

Therefore, this habit is also necessary, "After writing the code, if you want to execute it in multiple threads, will there be concurrency consistency problems."

9. Get the properties of the object, first determine whether the object is empty

This point originally belonged to "taking measures to avoid runtime exceptions", but I still took it out as a key point to write, because usually the empty pointer exception is too common, and a hand shake is not noticed, which causes the null pointer to report to production. The environment is gone.
Therefore, when you want to obtain the attributes of an object, try not to believe that "theoretical is not empty". We easily develop a habit to determine whether it is empty, and then obtain the attributes of the object. Positive example:


if(object!=null){
    
    
   String name = object.getName();
}

10. Multi-threaded asynchronous priority considers the appropriate thread pool instead of new thread, and considers whether the thread pool is isolated

Why use thread pool first? There are several advantages of using thread pool.
It helps us manage threads and avoid increasing resource consumption of creating and destroying threads.
Improve response speed.
Reuse.
At the same time, try not to share a thread pool for all businesses, you need to consider "thread pool isolation". It is different key business, allocate different thread pools, and then the thread pool parameters should be considered appropriately.

11. After manually writing the SQL of the code business, first take it to the database and run it, and also explain to see the execution plan.

After manually writing the SQL of the business code, you can take it to the database and run it to see if there are any syntax errors. The bad habit of some small partners is to package the code and test the server after writing. In fact, putting SQL in the database for execution can avoid many errors.
At the same time, also use "explain to see your Sql execution plan", especially if you can't go to the index.

explain select * from user where userid =10086 or age =18;

12. When calling a third-party interface, you need to consider exception handling, security, and timeout retry.

If you call a third-party service or distributed remote service, you need to consider
exception handling (for example, if you adjust someone else’s interface, if there is an exception, how to deal with it, retry or as a failure)
timeout (can’t predict how long the other’s interface will generally take Return, generally set a timeout disconnection time to protect your interface)
Number of retries (your interface failed, you need to retry, you need to think about this issue from a business perspective) A
simple example, you make an http request For other people's services, you need to consider setting connect-time and retry times.

If it is an important third-party service such as money transfer, you also need to consider "signature verification" and "encryption".

13. Interface needs to consider idempotence

Interfaces need to be considered idempotent, especially important interfaces such as grab red envelopes and transfer funds. The most intuitive business scenario is "the user clicks twice in a row". Does your interface hold?
Idempotent (idempotent, idempotence) is a mathematical and computer science concept commonly found in abstract algebra.
In programming, the characteristic of an idempotent operation is that the effect of any number of executions is the same as the effect of one execution. Idempotent functions, or idempotent methods, are functions that can be executed repeatedly with the same parameters and obtain the same results.
Generally, there are several kinds of "idempotent technical solutions":
query operations,
unique index
token mechanism, to prevent repeated submission of
database delete operations,
optimistic locks,
pessimistic locks,
Redis, zookeeper distributed locks (previously used Redis distributed locks to grab red envelopes)
State machine idempotence

14. In the case of multithreading, consider linear safety issues

In the case of "high concurrency", HashMap may have an infinite loop. Because it is non-linearly safe, you can consider using ConcurrentHashMap. Therefore, try to develop a habit as far as possible. Don’t come up with a new HashMap();
Hashmap, Arraylist, LinkedList, TreeMap, etc. are all linearly unsafe;
Vector, Hashtable, ConcurrentHashMap, etc. are all linearly safe

15. Consider the master-slave delay problem

Insert first, then go to query, this kind of code logic is more common, this "may" be problematic. Generally, the database has a master database and a slave database. Writing is writing to the main library, and reading is generally reading from the library. If there is a master-slave delay, it is very likely that your insert is successful, but you cannot find it.

If it is an important business, you need to consider whether to compulsorily read the main library or modify the design plan.
However, some business scenarios can accept a slight delay between the master and the slave, but this habit is still necessary.
After writing the code for operating the database, think about whether there is a master-slave delay problem.

16. When using the cache, consider the consistency between the cache and the DB, as well as (cache penetration, cache avalanche and cache breakdown)

In layman's terms, we use caching for "quick checking and less time-consuming interface". However, when caching is used, it is necessary to "pay attention to the consistency of the cache and the database". At the same time, it is also necessary to avoid the three major problems of cache penetration, cache avalanche and cache breakdown.
Cache avalanche: refers to the large amount of data in the cache until the expiration time, and the huge amount of query data causes excessive pressure on the database or even downtime.
Cache penetration: refers to querying a certain non-existent data. When the cache is missed, it needs to be queried from the database. If the data is not found, it will not be written to the cache. This will cause the non-existent data to go to the database every time a request is made Query, and then put pressure on the database.
Cache breakdown: Refers to when the hot key expires at a certain point in time, and a large number of concurrent requests for this key happen to come at this point in time, and a large number of requests hit the db.

Guess you like

Origin blog.csdn.net/qq_41936224/article/details/111469753