"Good code doesn't need comments"
"Good code doesn’t need comments" is a phrase often uttered by overconfident developers. They firmly believe their code is so logically clear that anyone could understand it at a glance even ten years later. However, the reality is often this: three months later, you’re cursing at the screen, while your colleagues silently leave "WTF" comments in the code review.
How to Create Confusion with "Self-Documenting Code"
"Self-documenting code" is the perfect excuse to avoid comments. For example, a function named processData
seems clear enough, but no one knows what data it processes, how it processes it, or why it’s processed. Even better, use a bunch of abbreviated variable names inside the function, like:
function processData(d) {
const fD = d.filter(x => x.s);
const mD = fD.map(x => ({ ...x, v: x.v * 2 }));
return mD.sort((a, b) => b.v - a.v);
}
The "self-documenting" nature of this code is evident in:
d
might be data, but no one knows its structure.- What is
x.s
?status
?selected
? Orsecret
? - What does
v
stand for?value
?velocity
?vampireCount
? - The sorting logic is "descending," but why? Business requirements? Or was the developer in a bad mood?
Adding comments might ruin the "artistry" of this code—after all, comments would spoil the fun of this "guessing game."
Using Magic Numbers and Hardcoding to Enhance "Unmaintainability"
Another enemy of comments is magic numbers. For example:
function calculateDiscount(price) {
return price * 0.7;
}
Here, 0.7
means a 30% discount, but why not add a comment? Because:
- Future maintainers might think it’s some mysterious coefficient, like "70% of users love this discount."
- If the business changes to a 20% discount, future developers might directly change it to
0.8
, unaware that the original number meant "30% off."
A more advanced approach is to combine multiple magic numbers, turning the logic into a complete black box:
function calculatePrice(quantity) {
return quantity * 42 + 3.14 * Math.log(quantity);
}
No one knows what 42
and 3.14
represent, but comments would ruin this "mathematical beauty."
Using Nested Conditionals to Create a "Logic Maze"
Another trick to avoid comments is to make the code logic so complex that no one dares to touch it. For example:
function getUserAccessLevel(user) {
if (user.role === 'admin') {
if (user.department === 'IT') {
return 'full';
} else if (user.department === 'HR') {
return user.isTemporary ? 'restricted' : 'full';
}
} else if (user.role === 'editor') {
return user.hasApproval ? 'partial' : 'none';
} else {
return 'none';
}
}
The "elegance" of this code lies in:
- No one knows what
'full'
,'restricted'
,'partial'
, or'none'
actually mean in terms of permissions. - The impact of
isTemporary
andhasApproval
is hidden in nested logic. - If a new role needs to be added in the future, maintainers must tread carefully to avoid breaking the existing cryptic logic.
Adding comments might make this code "too easy to understand," stripping it of its "defensive programming" value.
Using "Future-Proof Parameters" to Enhance Code Flexibility
To make code more "future-friendly," you can add seemingly useless parameters that "might be useful someday." For example:
function formatDate(date, options = {}) {
// options currently does nothing, but it might support timezone, format, etc., in the future
return date.toISOString();
}
The advantages of this approach are:
- Future developers calling this function will wonder what
options
actually does. - If they try passing parameters, like
formatDate(new Date(), { timezone: 'UTC' })
, they’ll find it has no effect, leading to deep self-doubt. - If future expansion is truly needed, they might just rewrite the function instead of deciphering the original "fake extensibility."
Using "Self-Optimizing" Code to Make Logic Untraceable
"Self-optimizing" refers to code written for "performance" or "conciseness" that actually makes the logic harder to understand. For example:
const result = data.reduce((acc, curr) =>
(acc[curr.id] = { ...curr, processed: true }, acc), {});
The "brilliance" of this code lies in:
- It uses the comma operator (
,
) to "elegantly" omitreturn
. - It directly modifies
acc
insidereduce
while returning it, leaving uncertainty about side effects. - It uses destructuring (
...curr
) to "optimize" object merging, but no one knows whatprocessed: true
is for.
Adding comments would strip this code of its "hacker vibe."
Using "Dynamic Property Names" to Make Code Inscrutable
Dynamic property names are a powerful feature of JavaScript, but they can also be used to create confusion. For example:
const config = {
[`${process.env.NODE_ENV}_API_URL`]: 'https://api.example.com',
[`${process.env.NODE_ENV}_TIMEOUT`]: 5000,
};
The "advantages" of this code are:
- No one can directly infer the structure of
config
—it’s only known at runtime. - If
NODE_ENV
isundefined
, the property name becomesundefined_API_URL
, but no one will catch this issue beforehand. - Future maintainers wanting to add a new environment must carefully ensure
NODE_ENV
is set correctly.
Comments? That would only strip this code of its "dynamic charm."
Using "Implicit Type Coercion" to Create Surprises
JavaScript’s implicit type coercion is a fantastic tool for creating "surprises." For example:
function addToCart(item, quantity) {
if (quantity) {
cart.push({ ...item, quantity });
}
}
The "subtlety" of this code lies in:
- If
quantity
is0
,if (quantity)
evaluates tofalse
, preventing users from purchasing "zero" items. - Future developers might spend an hour debugging before realizing the issue lies in "implicit coercion."
- Adding a comment like
if (quantity !== undefined)
would ruin the "fun" of this code.
Using "Long Method Chaining" to Turn Debugging into a Nightmare
Method chaining looks cool, but it can also make debugging extremely difficult. For example:
const result = data
.filter(x => x.active)
.map(x => ({ ...x, score: calculateScore(x) }))
.sort((a, b) => b.score - a.score)
.slice(0, 10)
.reduce((acc, curr) => ({ ...acc, [curr.id]: curr }), {});
The "artistry" of this code lies in:
- If
calculateScore
throws an error, the stack trace will only point to.map
, without revealing which specific data caused the issue. - If
data
isundefined
, the error occurs at.filter
, but you might initially thinkdata
wasn’t fetched. - If future developers want to add logging, they must break down the entire chain, ruining the code’s "fluidity."
Comments? That would only make this code "too easy to debug."
Using "Global State" to Make Code Behavior Unpredictable
Global state is the ultimate weapon for creating "unmaintainability." For example:
let currentTheme = 'light';
function toggleTheme() {
currentTheme = currentTheme === 'light' ? 'dark' : 'light';
}
function renderButton() {
button.style.backgroundColor = currentTheme === 'light' ? '#fff' : '#000';
}
The "advantages" of this code are:
- Any part of the code can modify
currentTheme
without considering who depends on it. - If a component doesn’t call
renderButton
aftertoggleTheme
, the UI will fall out of sync, but no one will know why. - If future developers want to add a new theme, they must ensure all logic depending on
currentTheme
is updated.
Comments? That would only constrain the "free spirit" of global state.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn