Introduction: why code review is not about "finding bugs"
\nCode review is not just a formality or a way to find typos. In modern JavaScript and Node.js development, it is the main tool for maintaining code quality, sharing knowledge within the team, and preventing technical debt. However, many developers reduce review to syntax checking, overlooking architectural issues, performance, and readability.
\nIn this article, we will break down exactly what to check in JavaScript code (using Node.js as an example), and how to give feedback so as not to offend a colleague, but to help them grow. Practical code examples will help solidify the material.
\n\n1. What to check in JavaScript code: a practical checklist
\nLet's start with specific checkpoints. Let's divide them into three levels: syntax/style, logic/security, and architecture.
\n\n1.1. Code style and formatting
\nIt's simple here: use a linter (ESLint) and a formatter (Prettier). There should be no arguments about spaces during review. Configure the configs in the project once. Check that:
\n- \n
- The code follows the
eslint-config-airbnbrules or your custom settings. \n - There are no unnecessary
console.logstatements (if not in dev mode). \n - Variable names are meaningful:
const userData, notconst x. \n
1.2. Asynchronous logic (Promise, async/await)
\nThis is a common area for errors in Node.js. Check:
\n- \n
- Error handling in async functions. Missing
try/catchcan cause the process to crash. \n - Correct use of
awaitinside loops. If tasks are independent, usePromise.all. \n
Bad:
\n// Sequential execution, although parallel is possible\nconst results = [];\nfor (const id of ids) {\n const data = await fetchData(id); // Wait for each request\n results.push(data);\n}\n\nGood:
\n// Parallel execution\nconst promises = ids.map(id => fetchData(id));\nconst results = await Promise.all(promises);\n\n\n1.3. Security and memory leaks
\nCritical for Node.js:
\n- \n
- No injections: do not use
evalornew Functionunless absolutely necessary. \n - Closing streams, database connections, and file descriptors. \n
- Input validation. Never trust the request body (
req.body). \n
2. How to give feedback: psychology and tactics
\nEven a perfect checklist won't work if the feedback makes the code author want to close the PR and quit. Here are a few rules.
\n\n2.1. The "sandwich" rule (optional, but effective)
\nStart with a positive comment, then point out the problem, and end with support. For example:
\n- \n
- "Great solution using
Mapfor caching!" \n - "However, there is a potential issue here with mutating the original array. Let's use
.map()instead of.forEach()with push." \n - "Otherwise the code is clean, thanks for the quick fix!" \n
2.2. Comment on the code, not the person
\nInstead of "You wrote a terrible loop," say "This loop can be replaced with Array.reduce to improve readability." Avoid the pronoun "you" in a negative context.
2.3. Provide context and alternatives
\nSimply writing "This is wrong" is bad. Explain why and suggest an alternative. Example of a bad comment:
\n"Don't use var."\n
A good comment:
\n"Herevarcreates a variable in the global scope, which can lead to bugs. Let's replace it withconst, since the value is not reassigned."