整洁代码
命名、小函数与可读性。
30 分钟
整洁代码:命名、函数与注释纪律
这一课你将能做到
- 给变量、函数、类起出"读一遍就懂"的名字,不再依赖注释解释
- 把 80 行的"面条函数"拆成一组 10 行以内、单一职责的小函数
- 用判题平台真实代码识别"坏味道":魔法数、布尔参数、嵌套过深、重复代码
为什么要学
代码被阅读的次数远多于被编写的次数。在判题平台里,cf_submission 表对应一次代码提交,cf_practice_record 对应一次刷题记录,这些领域对象会在 Service、Controller、定时任务、消息消费者里被反复读取。如果函数叫 process()、变量叫 data、参数叫 flag,下一个接手的人(也许就是三个月后的你)就要花时间还原上下文。
整洁代码不是洁癖,是降低协作成本。面试官让你手写一段代码,命名和结构是第一印象分。
先建立图像
烂代码 整洁代码
───────────── ─────────────
process(d, f) judgeSubmission(submission, skipCache)
if (s == 1) {...} if (submission.isAccepted()) {...}
// 判断用户是否Vip user.isVip() ← 注释消失
80 行函数 5 个 10 行函数
跟着做
步骤 1:坏味道现场
下面是"提交判题"业务的反面教材,先感受痛:
public void process(long id, String s, boolean f) {
// 查询提交
Submission sub = submissionMapper.selectById(id);
if (sub == null) return;
// 判断状态
if (sub.getStatus() == 0) {
// 调用判题
String r = judgeClient.call(sub.getCode(), sub.getLessonId());
if ("AC".equals(r)) {
sub.setStatus(1);
} else if ("WA".equals(r)) {
sub.setStatus(2);
} else {
sub.setStatus(3);
}
submissionMapper.updateById(sub);
// 是否发通知
if (f) {
notifyService.send(sub.getUserId(), "判题完成");
}
}
}
问题:数字状态码 0/1/2/3、单字母参数、布尔开关、嵌套判断、注释解释代码本应该说清的事。
步骤 2:用枚举替代魔法数
public enum SubmissionStatus {
PENDING, ACCEPTED, WRONG_ANSWER, RUNTIME_ERROR;
public static SubmissionStatus fromJudgeResult(String result) {
return switch (result) {
case "AC" -> ACCEPTED;
case "WA" -> WRONG_ANSWER;
default -> RUNTIME_ERROR;
};
}
}
状态从"需要查表"变成"自解释"。
步骤 3:小函数 + 有意义的命名
public void judgeSubmission(long submissionId) {
Submission submission = submissionMapper.selectById(submissionId);
if (submission == null || !submission.isPending()) {
return;
}
SubmissionStatus result = runJudge(submission);
submission.markAs(result);
submissionMapper.updateById(submission);
}
private SubmissionStatus runJudge(Submission submission) {
String judgeResult = judgeClient.call(submission.getCode(), submission.getLessonId());
return SubmissionStatus.fromJudgeResult(judgeResult);
}