Abstract
I just entered the company and developed two pieces of code. I met the boss who was in charge of it. I started standard PR and Codereview and learned some things.
Naming conventions and presentation issues
This should be modified more of the problem, to cite a few more typical chestnut:
1. Express questions
In fact, I did not find something in the database
throw new Error('Did not find the package whose ID is 2.')
Copy the code
D: Garbage: L
- D: Did your PE teacher teach you English? Where did you write that…
- L: wow! My English was taught by my PE teacher, so I translated it on the Internet.
- D: I’m afraid it’s a fake translation app.
- L: Google Translate has pictures and truth!
- D: You are not learning Chinese well.
No matter I am not good at English or Chinese, I do not think much about it and I do not have the craftsman spirit to keep improving. I’m sure no one can say that I’m wrong, but the truth is that it’s not good.
2. API design specification
// bad
get('/package/package_with_app_version? appid=xxx&version=xxx');
// good
get('/package? appid=xxx&version=xxx');
Copy the code
After checking the API design specifications, all of them prefer RESTful API style.
Actions are described using HTTP Method
Method | Corresponding database behavior | describe |
---|---|---|
GET | SELECT | Fetching resources from the server |
POST | CREATE | Create a new resource on the server |
PUT | UPDATE | Update the resource on the server (the client provides the full resource after the change) |
PATCH | UPDATE | Update resources on the server (client provides changed properties) |
DELETE | DELETE | Deletes resources from the server |
Example:
// Get the package list
get('/package');
// Get the package with ID 12
get('/package/12');
// Strictly RESTFUL, the return list should be filtered by these two parameters
// But I think it is not suitable in the business, so I change it according to the business, directly return the corresponding package
get('/package? appid=xxx&version=xxx');
// If you want to be strict with the specification, you should write it like this
get('/app/:appid/package/:version')
// Specify the page number and the number of records per page.
get('/package? page=2&per_page=100');
// Update package, the client provides all information about the package, similar to replacement
put('/package/:id');
// Update package. The client provides information that needs to be updated
patch('/package/:id');
/ / delete the package
delete('/package/:id');
/ / create a package
post('/package');
Copy the code
More formal design API, you can see at a glance what the API will do.
Code error
1. Problems occurred when reading the file splicing buffer
The following is the wrong way to write, the big guy looked at the wrong, let change. I was so frustrated that it took me a long time to experiment and finally it turned out that my notation really does get garbled when I parse it. Post code
const fs = require('fs');
let rs = fs.createReadStream('./Zn-utf8.txt');
let body = ' ';
rs.on("data", (chunk) => {
body += chunk;
});
rs.on("end", () = > {console.log(body);
});
Copy the code
It’s really garbled!
Error: Here really appear garbled code, the following analysis of the reason.
An English character takes up one byte, while a Chinese character takes up three bytes. When the file is large and needs to be cut.
Assumption: every 17 characters are cut once in reading
'when a three bytes of Chinese characters' = = >' a (1, 2, 3) (4 and 6) han (7,8,9) words (10) of the final three three (13,14,15) (16) as word (verse 19,20,21) (22,23,24) '= = > chunk1:' a three Chinese characters? ? '+ chunk2:'? Byte 'Copy the code
However, in the above code, the implicit toString() appears when the string is spliced, which converts the incomplete chunk into a string, resulting in the incorrect parsing of incomplete Chinese characters and garbled characters.
That’s why you get those three garbled characters, right
Solutions:
let body = [];
rs.on('data', (chunk) => {
body.push(chunk);
});
rs.on('end', () => {
body = Buffer.concat(body).toString();
console.log(body);
});
Copy the code
2. Use the timer to check the status
let status = await checkStatus();
if (status === 'success' || status === 'faild') {
if (status === 'success') {
console.log('success! I'm gonna do whatever I have to do. ')}else if (status === 'faild') {
console.error('failure! I can't do anything I want. '); }}else {
this.statusTimer = setInterval(async () => {
status = await checkStatus();
if (status === 'success' || status === 'faild') {
clearInterval(this.statusTimer);
if (status === 'success') {
console.log('success! I'm gonna do whatever I have to do. ')}else if (status === 'faild') {
console.error('failure! I can't do anything I want. '); }}},200);
}
Copy the code
CheckStatus (); faild; pending; checkStatus(); If the state is pending, a setInterval is turned on and checked every 200 milliseconds until the result is generated.
It sounds like there is no problem, AND I also thought so at first, but the result is really beyond my expectation, because in the local debugging, the request time is too short to find this problem, the big guy can see it at a glance, put a piece of code and run the result, we can see at a glance.
// The concept version of the above logic
var timer = setInterval(async() = > {console.log('What to do before sending the request')
await new Promise(resolve= > setTimeout(resolve, 5000));
console.log('Something to do after receiving a request');
}, 1000)
Copy the code
To execute a function every second, await will block the content after the function for 5 seconds, clear the timer with clearInterval, meaning that the desired result has been received and the function will not be executed again. However, there were five other ‘things to do after receiving a request’ outputs.
That is to say, when the network situation is not good, my previous code will cause, after checking the status is successful, after clearing the timer, it is likely that there are still several functions not completed, will check the status is successful, trigger the successful thing to do, resulting in serious consequences.
Optimization scheme, solve the problem by recursion +sleep function:
Sleep is also used to reduce invalid requests, and the main problem is recursion.
async function checkStatus() {
const status = await checkStatus();
if (status === 'success' || status === 'faild') {
if (status === 'success') {
console.log('success! I'm gonna do whatever I have to do. ')}else if (status === 'faild') {
console.error('failure! I can't do anything I want. '); }}else {
console.log('pending... ');
await new Promise(resolve= > setTimeout(resolve, 500));
awaitcheckStatus(); }}Copy the code
Perfect problem solving
Exception handling
I was checked twice by the boss about exception catching:
- Your requests are not tried… How do you catch the wrong one?
- I changed after >>>>>> you how everywhere try… Catch says, was it fun?
So I silently researched where to catch exceptions, when not to catch exceptions, where to catch exceptions, and whether every request should be tried… catch?
I know that there are many better capture modes. For example, I particularly like the exception handling of egg. Errors in the Service layer controller layer are wrapped, thrown out, and processed uniformly through middleware.
- Q: When was it not captured?
- A: In JS, trycatch is useless for asynchronous callback functions. If you can’t catch it, then the native uncaughtException catches all uncaught errors, at which point you can’t do proper error handling.
- Q: How should asynchronous functions be captured?
- A: Basically, as long as you don’t jump out of the asynchronous call chain, you can catch it. There are many solutions, such as using promise to catch asynchronous errors, reject. Or with async await, you can catch exceptions easily.
- Q: Should exceptions be caught everywhere?
- A: Of course not. Exceptions thrown in the inner layer will be caught in the process of rising, so there is no need to write everywhere. Throwing exceptions, printing errors when you feel you should, and catching errors when you need to handle them is a scale THAT I probably need more experience with.
I have learned something about this, but it is definitely far from enough. Let’s accumulate experience of this piece slowly. But now you can at least use the minimum try… Catch, take care of all the mistakes.
Learn to put yourself in the user’s shoes
It’s not about code, it’s not about programs, it’s not about logic, it’s about perspective.
The following is the design of CLI commands during development
The first edition
# build locally
seeder-package [packageName] -o ./dist/package.tgz
# Deploy test environment (go live automatically)
seeder-package [packageName] -d ./dist/package.tgz
# Deploy the production environment (manual online)
seeder-package [packageName] -d ./dist/package.tgz -e production
# Update version number
seeder-package [packageName] --pv major
seeder-package [packageName] --pv minor
seeder-package [packageName] --pv patch
seeder-package [packageName] --pv 3.2.5
Check the current version number
seeder-package [packageName] --pv current
Copy the code
The second edition
# build locally
seeder [packageName] -o ./dist/package.tgz
Deploy the package at the specified path to the test environment
seeder [packageName] -d ./dist/package.tgz
Package and deploy to the test environment
seeder [packageName] -d -o
Pull the latest version of the package from the test environment to the production environment
seeder [packageName] -d --prod
# Update package deployment test live
seeder [packageName] -o -d --pv [xxx]
Short for update package Deployment Test go live
seeder [packageName]
Copy the code
The third edition
Seeder [packageName] # Package and update patch version seeder [packageName] # Package and update patch version seeder [packageName] --pv [XXX] # Sync to production seeder [packageName] -pCopy the code
The three versions are a huge change
First edition ==> second edition
This change was something I wanted to do on my own, as I felt during development that the usability was so poor that I had to input too much at a time. In general, this change is designed to reduce the amount of content that users type.
- Shorten the Seeder-package directive to seeder
- The deployment environment will need to be actively declared. The default value of the -e environment is the test environment and only needs to be set for production environment.
- Merge the package deployment two commands without passing long parameters.
- Instructions like -o-d –pv [XXX] can do several jobs at once.
- I made the shorthand
Second edition ==> Third edition
Both the conflict and the gain occurred at this time.
-o output local files -d deployment — PROd describes the environment — PV version related operations, one command one action, very clear. Do what you want to do with the instructions, should not be simplified, the logic is very clear. I’ve eliminated all the input items that I could have left out.
Big guy’s point of view: Simplify again, simplify to the extreme (so that I think the command action description is not clear), big guy thinks I said my clear logic is for developers, not from a technical point of view, think it can be implemented logically. I’ve been lying to myself about being logical when IT turns out I’m doing it myself. (Take a tumble)
A third overhaul simplified the order to the point where it was indispensable. These two changes to the code are the biggest, but they are also the biggest gains I made this time. I learned what is humanization and what is thinking from the perspective of users, forgetting that I am a developer.
Thank you
In the past, I always felt that CodereView was useless, but this time I gained a lot. There were still many business problems that were not easy to summarize, and many problems without characteristics were not listed. In this development, I also learned to write test cases.
Sometimes you don’t need to code to fulfill a requirement. It’s more like polishing a craft, and in the spirit of craftsman, your attitude determines the quality of your code. Thanks to the big guy to teach their own, I believe that the future will also learn a lot, their code quality will be dawdling to improve.
From a child who has been on the job for two weeks
I want to share this with you and I want to progress with you and this code is very comfortable to tap