16不要:当JavaScript代码评论感觉就像看惊悚片
#javascript #网络开发人员 #编程 #codereview

悬念

[当动作放慢时,不确定性和张力会增长]
The 3 Essential Elements of Suspense Explained — How Fincher, Carpenter and Refn Create Suspense - YouTube

代码作者可以通过多种方式增加读者的不确定性并减慢审核过程,例如:

1)使用不必要的条件

const roles = {
  student: "s",
  teacher: "t"
};

// bad
const role = currentRole === roles.student ? roles.student : roles.teacher;

// good
const role = roles[currentRole];

2)包装内部条件也很常见(静态)零件

// bad
if (firstName === '') {
  getFullName(placeholderName, lastName);
} else {
  getFullName(firstName, lastName);
// Hmm, looks like the only difference is the first argument?
}

// good
const userFirstName = firstName === '' ? placeholderName : firstName;
getFullName(userFirstName, lastName);

3)过度使用optional chaining operator

// let's assume that all of 'userData' fields always exist
const userData = {
  id: '123',
  personal: {
    age: 33,
  },
};

// bad
const userAge = userData?.personal?.age; 
// Are those really optional? Should we update TypeScript interfaces?

// good
const userAge = userData.personal.age;

4)过度使用logical OR operator

// bad
const filterTruthful = (array) => {
  const a = array || []; // Why not as default function parameter?
  return a.filter(Boolean);
};

const canBeAlsoUndefinedOrNull = 'ABC';
const copyWithFallback = canBeAlsoUndefinedOrNull || ''; 
// Do we need fallback for 0? Is that a possible value?

// good
const filterTruthful = (array = []) => {
  return array.filter(Boolean);
};

const canBeAlsoUndefinedOrNull = 'ABC';
const copyWithFallback = canBeAlsoUndefinedOrNull ?? '';

5)用动词命名数据

// bad
const verifyUser = {
  id: '123',
  verify: true,
};

validateUser(verifyUser); // Is "validateUser" a higher-order function?

// good
const verifiedUser = {
  id: '123',
  verified: true,
};

validateUser(verifiedUser);

6)无原因选择太简洁的名字

// bad
const p = [
  {
    id: 0,
    c: [[1, 2]],
  },
];

const pc = p.map((i) => i.c.flatMap((c) => c));

// good
const positions = [
  {
    id: 0,
    coordinates: [[1, 2]],
  },
];

const coordinates = positions.map((position) =>
  position.coordinates.flatMap((c) => c)
);
// 'c' is clear enough thanks to pretty obvious context

7)以不同的方式执行类型的胁迫并使其易于忽略

// bad
const asNumber = +Infinity;
const asBoolean = !!Infinity;
const asString = `${Infinity}`;
const asStringList = [1, 0, ''].map((i) => i.toString());

// good
const asNumber = Number(Infinity); 
// Infinity is a number so this is redundant 
const asBoolean = Boolean(Infinity);
const asString =  String(Infinity);
const asStringList = [1, 0, ''].map(String);

8)使用无助的(新)公约

// bad
const THEME_NAMES = {
  dark: 'dark',
  light: 'light',
};
// Why not camelCase?
// If it: 'is more global const' - do we need const sub-types?
// Do we want changing the name on each scope change?

const Config = {
  themeName: THEME_NAMES.dark,
  simplifiedUI: true,
};
// It's named like a class / constructor.
// Do we really need that capital letter here?

// good
const themeNames = {
  dark: 'dark',
  light: 'light',
};

const config = {
  themeName: themeNames.dark,
  simplifiedUI: true,
};

9)不使用评论会有所帮助(因为评论不好!11)

/* bad */
.slider {
  transform: translateZ(0);
}

/* good */
.slider {
  transform: translateZ(0); /* Fixes flickering in Safari 14, see: https://github.com/nolimits4web/swiper/issues/3527 */
}

但是,对于某些程序员而言,这还不够,他们决定将审稿人的不确定性留在最后。

悬崖衣架

[当情节在关键或悬疑时刻突然结束时,让读者或听众陷入悬念或不确定性的结果]

Screenshot from LOST series which was famous from overusing cliff hangers

Screenshot of LOST series - credits

10)将死更简单操作包裹在多个嵌套功能中

// bad
function validateInput(userInput) {
  return validateText(userInput);
}

function validateText(text) {
  return checkIfString(text);
}

function checkIfString(str) {
  return typeof str === 'string';
}

// good
function validateTextInput(text) {
  return typeof text === 'string';
}

11)在测试文件断言中使用广泛的逻辑 /外部LIB助手

// bad
describe("createDate", () => {
  it("returns date in correct format", () => {
    expect(createDate()).toBe(_.trim(moment().format("ll")));
  });
});

// good
// assuming date is properly fixed in test env
// to not fail the day after / in different timezones
describe("createDate", () => {
  it("returns date in format: [three-letter month], [dayNumber], [year]", () => {
    expect(createDate()).toBe("Apr 1, 2023");
  });
});

12)忽略错误处理

// bad
const getFirstPost = async () => {
  return fetch('https://jsonplaceholder.typicode.com/posts/1');
};

// good
const getFirstPost = async () => {
  let response;
  let parsedResponse;

  try {
    response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  } catch (e) {
    throw new Error(e); // ConnectionError, e.g. Network connection, CORS
  }

  try {
    parsedResponse = await response.json();
  } catch (e) {
    throw new Error(e); // ParsingError, e.g. SyntaxError
  }

  if (response.ok) {
    return parsedResponse;
  }

  throw new Error(parsedResponse); // ResponseError, e.g. Error from Back-end validation
};

有时代码作者不仅使读者对代码中发生的事情感到不确定,而且还为审阅者提供了更直接的虚假线索。

红鲱鱼

[当我们出现错误的线索]
What is a Red Herring — 5 Techniques to Mislead & Distract an Audience - YouTube

该术语在1807年普及英国辩论家威廉·科贝特(William Cobett),他讲述了一个故事,他用一种强烈的烟熏鱼来转移和分散猎犬的兔子。

[Wikipedia]

13)定义不使用定义形式的const

const data = {
  items: {
    posts: [],
  },
};

// bad
const { items } = data;
// ...
return items.posts.map((post) => <div>{post}</div>);

// good
const { items: { posts } } = data;
// ...
return posts.map((post) => <div>{post}</div>);

14)用当前特征需要的名称(过早别名)定义简单条件

const roles = {
  student: "s",
  teacher: "t"
};

// bad
const hasAccessToMTS = currentRole === roles.teacher;

// good
const isTeacher = currentRole === roles.teacher

15)以多种方式命名一件事

const roles = {
  student: "s",
  teacher: "t"
};

// bad
const userPosition = roles.student;

// good
const userRole = roles.student;

16)在代码中留下误导性评论

// bad
const performMultipleRequests = async () => {
  const promise1 = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const promise2 = await fetch('https://jsonplaceholder.typicode.com/posts/2');

  return Promise.all([promise1, promise2]); // performs requests parallely
};

// good
const performMultipleRequests = async () => {
  const promise1 = fetch('https://jsonplaceholder.typicode.com/posts/1');
  const promise2 = fetch('https://jsonplaceholder.typicode.com/posts/2');

  return Promise.all([promise1, promise2]);
};

您可以看到代码审查过程可能类似于看一部惊悚片,但我不确定这是否总是一件坏事 - 我的意思是,它比像恐怖,喜剧一样好得多或灾难场景:

我们试图通过进行评论来避免。

如果您喜欢您阅读的内容,那么我鼓励您查看我以前的文章:
Similarities between programming & screenwriting - DEV Community