你的代码应该讲述一个故事:编写供他人阅读的代码的技巧
当我们编写代码时,我们也在为其他开发人员编写一个故事。
以下是一些关于如何为我们未来的自己和其他开发人员(我们的读者)编写代码的提示。
1. 使用函数和变量来表达你的意图,而不是注释
依赖注释可能会导致代码阅读和理解时间更长。你应该考虑你的代码将如何延续下去。这是一个其他人可能会在未来几年内阅读的故事。
坏的:
const sendResult = (dbConfig, query) => {
// get connection to database
const db = getConnection(dbConfig);
/* The function calculates exame results for all students */
const users = db.sendQuery(query);
const results = users.map(user => ({ id: user.id, result: result }));
/* Generate Email with results */
const html = generateHTML(results);
sendEmail(html);
}
好:
创建额外的函数来解释你的代码。需要添加注释的地方应该能引导用户创建新变量或函数。函数越短,测试起来就越容易,代码也就越简洁。
const getStudentResults = (dbConfig, query) => {
const dbConnection = getConnection(dbConfig);
const users = dbConnection.sendQuery(dbConfig, query);
return users.map(user => ({ id: user.id, result: result }));
}
const emailResults = () => {
const html = generateHTML(results);
sendEmail(html);
}
const sendResult = (dbConfig, query) => {
const resuls = getStudentResults(dbConfig, query);
emailResultse(resuls);
}
优点:
使用 JSDoc 之类的工具记录高级功能是评论的理想用例。
/**
* Get student results from the Database
* @param {object} dbConfig - Config for connecting to the db
* @param {string} query - Query for the database
*/
const getStudentResults = (dbConfig, query) => { }
免责声明:注释有其适用的场合和时间。我并不反对注释本身,只是在代码简洁的情况下,过度使用注释是更好的选择。
2. 使用变量解释控制语句
当别人阅读你的代码时,你应该让他们读起来尽可能轻松。我可不想因为脑子里不停地做些小计算而毁掉一个好故事。
坏的:
const user = getStudentResults(4309394);
// I need to compute this in my brain to figure out what is happening in this if statement
if (user.result < 40 || user.attendance < 50) {
sendEmail(user, false);
} else {
sendPassMail(user, true)
}
好的:
分配新变量来存储语句的结果,可以让代码的读者更好地理解故事。代码的读者会尝试找到他们关心的部分。帮助他们跟上故事的节奏,以便他们修复错误或添加相应的功能。这个故事会有共同作者。
const user = getStduentResults(4309394);
const userPassedCourse = user.result > 40 && user.attendance > 50;
if (userPassedCourse) {
sendEmail(user, false);
} else {
sendEmail(user, true)
}
3. 避免模棱两可的论点
myFunction(null, undefined, 1)
这不是任何故事的最佳开头。不要让读者深入研究函数,只需看看参数的作用即可。
坏的:
const user = getStudentResults(4309394);
if (user.result > 40 && user.attendance > 5) {
// what does false mean here, I can guess but it should be explicit
sendEmail(user, false);
} else {
sendEmail(user, true)
}
好的:
传递一个对象在这里可能是一个很好的解决方案。
const sendEmail = ({ user, passedCourse }) => { }
const user = getStudentResults(4309394);
const userPassedCourse = user.result > 40 && user.attendance > 50;
if (userPassedCourse) {
sendEmail({ user, passedCourse: true });
} else {
sendEmail({ user, passedCourse: false });
}
也很好:
您可以通过创建一些新功能让您的故事更具表现力。
const sendEmail = ({ user, passedCourse }) => { }
const sendPassEmail = (user) => {
sendEmail({ user, passedCourse: true });
}
const sendFailEmail = (user) => {
sendEmail({ user, passedCourse: false });
}
const user = getStudentResults(4309394);
const userPassedCourse = user.result > 40 && user.attendance > 50;
if (userPassedCourse) {
sendPassedEmail(user);
} else {
sendFailEmail(user)
}
4. 魔法在某些故事里是好的,但在我们的故事里不是
避免使用魔法数字。与上述模棱两可的论点类似,魔法数字也会带来我们不希望在故事中出现的那种阴谋。
坏的:
const getStudents = (courseId, fieldOfStudy) => {}
const students = getStudents('323424', 4);
好的:
const getStudents = (courseId, studentType) => {}
const courseId = '323424';
const fieldsOfStudy = {
ENGINEERING: 4,
BUSINESS: 5
};
const students = getStudents(courseId, fieldsOfStudy.ENGINEERING);
5. 使用枚举。避免使用字符串作为标识符。
与魔法数字一样,使用字符串作为标识符可能会导致故事混乱。字符串中包含 ID 可能会导致歧义。重构这些字符串将更加困难。
坏的:
getResults({ entity: 'undergrad', courseId: 'SCIENCE_101'});
// Elsewhere in the code
getResults({ entity: 'undergrad', courseId: 'SCIENCE_101'});
getResults({ entity: 'undergrad', courseId: 'SCIENCE_100'});
好的:
const entity = {
UNDERGRAD: 'underGrad',
POSTGRAD: 'postGrad',
}
getResultsFromDB({ entity: entity.UNDERGRAD, courseId: 'SCIENCE_101'})
更好的是,使用 typescript 来强制类型安全。
6. 冗长胜于简洁
不要让读者感到困惑。我们的代码应该简洁、干净,但我们的函数名不需要受长度限制。
坏的:
const results = getResults();
好的:
const examResults = getStudentExamResults();
你有什么建议?
我很想在评论区看到一些代码片段。