阿里云主机折上折
  • 微信号
Current Site:Index > "Good code doesn't need comments"

"Good code doesn't need comments"

Author:Chuan Chen 阅读数:64084人阅读 分类: 前端综合

"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? Or secret?
  • 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:

  1. Future maintainers might think it’s some mysterious coefficient, like "70% of users love this discount."
  2. 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 and hasApproval 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:

  1. Future developers calling this function will wonder what options actually does.
  2. If they try passing parameters, like formatDate(new Date(), { timezone: 'UTC' }), they’ll find it has no effect, leading to deep self-doubt.
  3. 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" omit return.
  • It directly modifies acc inside reduce while returning it, leaving uncertainty about side effects.
  • It uses destructuring (...curr) to "optimize" object merging, but no one knows what processed: 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:

  1. No one can directly infer the structure of config—it’s only known at runtime.
  2. If NODE_ENV is undefined, the property name becomes undefined_API_URL, but no one will catch this issue beforehand.
  3. 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 is 0, if (quantity) evaluates to false, 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:

  1. If calculateScore throws an error, the stack trace will only point to .map, without revealing which specific data caused the issue.
  2. If data is undefined, the error occurs at .filter, but you might initially think data wasn’t fetched.
  3. 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:

  1. Any part of the code can modify currentTheme without considering who depends on it.
  2. If a component doesn’t call renderButton after toggleTheme, the UI will fall out of sync, but no one will know why.
  3. 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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.