悬念
[当动作放慢时,不确定性和张力会增长]
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 */
}
但是,对于某些程序员而言,这还不够,他们决定将审稿人的不确定性留在最后。
悬崖衣架
[当情节在关键或悬疑时刻突然结束时,让读者或听众陷入悬念或不确定性的结果]
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