跳到主要内容

自解释代码

· 阅读需 2 分钟

summary

  1. 使用命名常量而非晦涩的错误代码 | Using named constants instead of cryptic error codes
  2. 将复杂逻辑抽离成独立函数 | Extracting complex logic and putting it in its own function
  3. 运用短路求值使代码流程线性化 | Using short-circuit evaluation to make the code flow linear
  4. 引入类型注解辅助静态检查与实时编码反馈 | Introducing type annotations to help with static type checking and real-time coding feedback

original code

async function createUser(user) {
if (!validateUserInput(user)) {
throw new Error('u105');
}

const rules = [/[a-z]{1,}/, /[A-Z]{1,}/, /[0-9]{1,}/, /\W{1,}/];
if (user.password.length >= 8 && rules.every((rule) => rule.test(user.password))) {
if (await userService.getUserByEmail(user.email)) {
throw new Error('u212');
}
} else {
throw new Error('u201');
}

user.password = await hashPassword(user.password);
return userService.create(user);
}

命名常量与单一职责原则

const err = {
userValidationFailed: 'u105',
userExists: 'u212',
invalidPassword: 'u201',
};

function isPasswordValid(password) {
const rules = [/[a-z]{1,}/, /[A-Z]{1,}/, /[0-9]{1,}/, /\W{1,}/];
return password.length >= 8 && rules.every((rule) => rule.test(password));
}

async function createUser(user) {
if (!validateUserInput(user)) {
throw new Error(err.userValidationFailed);
}

if (isPasswordValid(user.password)) {
if (await userService.getUserByEmail(user.email)) {
throw new Error(err.userExists);
}
} else {
throw new Error(err.invalidPassword);
}

user.password = await hashPassword(user.password);
return userService.create(user);
}

短路求值

function throwError(error) {
throw new Error(error);
}

async function createUser(user) {
validateUserInput(user) || throwError(err.userValidationFailed);
isPasswordValid(user.password) || throwError(err.invalidPassword);
!(await userService.getUserByEmail(user.email)) || throwError(err.userExists);

user.password = await hashPassword(user.password);
return userService.create(user);
}