It has been nearly a year since I graduated and joined my current company. I have fully participated in the development and launch process of the department’s new projects in two phases. As a back-end developer, the most painful thing is before and after the launch. In the bug correction stage after going online, faced with all kinds of sudden and inexplicable bugs, I feel dizzy, confused, and more and more confused as I make changes. This often leads to tragedies such as experimental bug correction, and two bugs appear after correcting one bug. I I can't help but wonder, why are there so many bugs before every launch?
I read a Douban article a few days ago. What is not summarized is not experience, just experience. Programmers can't just write code when business comes, and fix bugs when there are bugs. This makes it difficult to improve technology, so it's no wonder there are so many bugs every time. Some developers have been working for many years, but the number of interfaces is still 500 from time to time. They are busy writing code in the early stage and fixing bugs in the later stage, which makes them tired.
From the first phase, I became familiar with the business and framework, and wrote edge interfaces. In the second phase, I was responsible for a small module and tried to design databases and programs. I stumbled in the middle. Yesterday, it went online smoothly, and I felt it vaguely. So I tried to summarize some experiences. Although it is simple, it may give me and readers some inspiration. (This article only focuses on basic level, simple bugs, and does not involve complex issues such as high concurrency and massive data)
The interface I worked so hard to write worked fine when I tested it, but why did it go wrong when others adjusted it? ? (There should be emoticons here, please make up your own mind.) Of course, it may be a problem with the operating environment, but the program is deployed uniformly on the server. This is generally the responsibility of the architect or operation and maintenance. As for the problem of programming language or operating system, They are all outside the scope of consideration today. Today, we only consider bugs written by ourselves.
In fact, a running program involves nothing more than three things: resources (cpu, memory, etc.) algorithm (program running process) data (user input, database, third-party interface, etc.). Usually we think that resources are reliable, and bugs occur mainly due to unreliable algorithms or data anomalies.
Going one step further, the machine executes instructions strictly according to 0/1. The algorithm executed normally last time. Why did it fail this time? Essentially, it is because the data has changed and the algorithm failed to cover this situation. Therefore, in order to ensure the stability of the interface, we mainly consider two aspects: ensuring the reliability of the data and the robustness of the algorithm, and the robustness of the algorithm is to consider In all situations of data, the two are inseparable.
As analyzed before, data changes are the most common and essential cause of interface bugs. Among them, user input is the main reason for data changes. The program must have user input, otherwise it is meaningless.
There is a famous saying in the programming world: Never trust user input. You never know what the user will type in an input box that expects a name. Don't rest assured just because the front-end has filtered it. On the one hand, users may use crawlers and other means to directly access your interface. On the other hand, the front-end is also your user, and there are also communication errors. The front-end may call you in the wrong way. interface, and this error may be more subtle.
The first suggestion: Strictly verify user input, including format and content.
I know that many people are too lazy to check user input one by one, thinking that as long as the function is normal, it will be ok. However, this often leads to more experience in correcting bugs later. Frequently, bugs are reported during testing. After checking again and again, you find that the front-end passed the wrong parameters or did not reasonably restrict user input. Of course, you can be very rigid and let the front-end make corrections, but this process has already wasted a lot of your time and energy. It is better to check it yourself at the beginning and return appropriate error messages, which will save you a lot of energy later.
This is especially true for dynamic languages such as PHP. For example, if we use the Laravel framework, I will first use $request->validate() at all interface entrances to check the format of all input data. If necessary, Code will also be written to further verify the input content, such as the time range, whether the requested data is valid, etc.
The second suggestion: consider the user's troublesome operations, repeated submissions, delayed submissions
Repeated submissions should be a situation that most backends can think of, and It is the idempotence of the interface. Some resources can only be operated once and must be verified. In fact, it is not only repeated submissions, but also the situation where the same event is processed repeatedly by two people.
As for delayed submission, it was actually a problem pattern that I only realized after the test reported a bug to me. For example, if we return a certain resource to the user through the get interface, the user can return the resource ID through the post interface and submit modifications. Since it is returned by its own get interface, we may want to only verify that the ID is legal, which seems to form a strict closed loop. , but if the user stays on this page and delays submission, the resource may have expired during this period, or the resource has been modified by others, and the user has successfully modified the bug. In fact, if you think about it further, you will find that this is similar to resource failure in high concurrency scenarios.
The third suggestion: Check the return data of the database and third-party interface
In addition to user input, common data sources include databases and third-party interfaces. Relatively speaking, these data interfaces will be much more reliable, and the content format will be more standardized. However, for the stability of the interface, it is best to do some tests. For example, if the data is often empty, program execution must be terminated promptly and appropriate information thrown out.
By the way, for the database, I have also encountered bugs, which are data update problems caused by master-slave delay. Due to my lack of experience, I am not very good at this type of problem, so I won’t write about it anymore.
The fourth suggestion: the program algorithm covers abnormal situations as much as possible
This is actually a supplement to the first three. For some illegal user input, you can directly Abort the program and return an error message, but some situations may require the program to continue running and perform special processing. In these situations, you should try to consider them carefully at the beginning of the program design. Later, there will be many fewer bugs and it will be easier to maintain.
Finally, let’s write a little more thoughts about interface efficiency and code quality.
1. The main factor that affects interface efficiency is database operations
From my limited experience, the long interface time is basically due to unreasonable database operations. Most of our businesses The code does not have performance issues. I have seen a lot of code that queries the database in a for loop. This must be avoided. We can first take out all the data at once and then process it one by one. For example, we will record all database operations at the framework layer. When debugging the interface, we can see all database operations and the corresponding time consumption. The merged queries need to be merged, and the optimized time-consuming queries should be optimized accordingly.
2. Reasonable use of Exception, log
This article is mainly for PHP language. Due to historical reasons, I have seen many codes that rely on return to terminate the program and pass error information. , which makes it extremely difficult to maintain when the code is complex and the call level is deep, and it is far less intuitive and convenient than the Exception mechanism. Also, important information must be written in a log to facilitate later problem discovery and debugging, and it can also be used to prove innocence.
3. The code must be reasonably divided and abstracted
Do not copy and paste the code. Repeated functions must be isolated; demand changes and expansions must be reasonably considered when designing; write small As for focused functions, don’t implement complex functions in one go; the code written in this way is easy to modify, test, and expand. I'm not good at this either. After going online, my code is all messy and difficult to maintain. Next, I need to think more and practice more.
I hope that the code you write will be bug-free!
For more Laravel related technical articles, please visit the Laravel Tutorial column to learn!
The above is the detailed content of Back-end development: how to write reliable interfaces. For more information, please follow other related articles on the PHP Chinese website!