想象一家刚开张的餐厅,后厨挤满了从各地请来的厨师:有人习惯把菜板摆在右手边,有人炒菜爱放三勺盐,有人切土豆非要切出花来。单看每个人都是好手,可一到饭点就乱了套——找锅的、找料的、踩脚的,端出去的菜今天一个样、明天又一个样。老板终于意识到:后厨缺的不是更厉害的厨师,而是一套所有人都认的规矩。 代码团队的故事几乎一模一样。三个工程师写同一个订单模块,一个用双引号,一个用单引号,一个缩进两格、一个缩进四格;同一个变量今天叫 orderTotal,明天叫 total_price。每个人单独看都没问题,合在一起,阅读成本就像雪球一样越滚越大。这篇文章就是一份“后厨规整指南”:从为什么要规范、规范定什么(命名、格式、结构),到怎么让规范真正落地(ESLint、Prettier 等自动化工具配合评审机制),再到老项目如何渐进式治理。你会看到,制定规范的本质不是限制自由,而是把团队从无穷无尽的风格争论中解放出来,让每个人把精力花在真正重要的事——写出好代码上。

岗位关联

理解代码规范的定义与落地方法,是 AI 工程师参与团队协作的必修课:它决定了你在代码评审、开源贡献乃至与 AI 编码助手协作时,能否少踩风格坑、多出好设计。

目录
  1. 可视化演示
  2. 1. 规范的价值
  3. 2. 命名规范
  4. 3. 格式规范
  5. 4. 结构规范
  6. 5. 自动化工具
  7. 6. 规范落地
  8. 7. 老项目治理
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示代码规范三层体系:命名意图表达、格式自动化工具链、CI门禁检查,可视化从混乱到统一的规范治理过程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

命名规范层级 变量名应表达意图而非技术实现细节 命名是代码规范中最易被忽视的部分 name = intent + type

1. 规范的价值

一家餐厅的后厨,挤满了来自五湖四海的厨师。川菜师傅的案板永远摆右手边,粤菜师傅的酱料从不写标签,法餐出身的厨师习惯把所有刀具按长短排好。单看每个人都是好手,可一到饭点就乱套:帮厨找不到料、配菜切得七扭八歪、同一道回锅肉今天辣明天甜。老板终于明白:后厨缺的不是更厉害的厨师,而是所有厨师都认的一套规矩。

代码团队几乎复刻了这个场景。有人坚持双引号,有人钟爱单引号;有人缩进两格,有人缩进四格;同一个订单总价,昨天叫 orderTotal,今天叫 total_price。单独看每个人的代码都没毛病,一旦协作,互相读代码的时间比写代码还长。代码规范,就是团队约定好的“后厨规矩”。

规范的本质是降低协作中的认知负担。一段代码写一次,却被读无数次,读代码的成本才是大头。规范的价值公式一目了然:

后厨的规矩不是用来限制厨师的,而是让任何新来的厨师都能迅速上手:哪怕明天换一批人,菜的味道还是那个味道。规范沉淀的是团队对“什么是好代码”的共识,把一次性的写作成本,摊薄进无数次阅读中——这正是代码规范作为“团队协作基础设施”的意义。

Ctotal=Cwrite+Nreaders×Cread\displaystyle C_{total} = C_{write} + N_{readers} \times C_{read}
一段代码的总成本 = 写作成本 + 读者数量 × 每人阅读成本。规范每降低一点阅读成本,收益就会被“读者数量”放大很多倍。
  1. 阅读成本乘数每个读者都要付出理解成本,读者越多,总成本被放大得越厉害。
    Nreaders×CreadN_{readers} \times C_{read}
  2. 写作成本写代码的人一次性付出,一次写、多次读,写作成本在总成本中占比其实很小。
    CwriteC_{write}
  3. 总成本公式总成本等于两者之和,规范的作用就是压低乘数 C_read。
    Ctotal=Cwrite+Nreaders×CreadC_{total} = C_{write} + N_{readers} \times C_{read}

2. 命名规范

后厨里最让人抓狂的,是冰箱上贴的标签:一个盒子写着“东西”,另一个写着“周二剩的”。没人知道里面是什么,掀开盖子才发现是土豆和昨天炖的肉。好厨房的标签一定清清楚楚:“土豆-2024-10-01”。命名,就是代码世界里的食材标签。

变量名是写给未来的读者看的,包括三天后的自己。一个叫 data 的变量就像一盒“东西”,而 orderTotal 则直接告诉你盒子里装的是什么。命名规范的首要原则是“见名知意”,其次是遵循语言社区的约定俗成:别让读者在“命名方言”上花费额外的翻译时间。

JS 生态常用 camelCase 命名变量和函数,Python 社区更爱 snake_case;类名几乎统一用 PascalCase,常量则用 UPPER_SNAKE_CASE。函数名建议以动词开头(fetchUser、calculateTotal),布尔变量用 is/has/can 前缀(isValid、hasPermission)——读到名字就知道它回答什么问题。文件名与导出的内容保持一致,让“找文件”变成“猜得到”。命名是否优秀,可以用一个评分公式来理解:

回到后厨,标签的本质是“让找东西的人不打开盖子就猜中内容”。命名规范不是审美洁癖,而是把每个人心里那本私人词典,换成团队共用的一本词典。翻词典的人越多,词典的价值就越大——这就是命名值得写进规范第一章的原因。

Score(name)=Desc(name)−λ×Len(name)\displaystyle Score(name) = Desc(name) - \lambda \times Len(name)
命名评分 = 描述度 − 长度惩罚系数 × 名称长度。好名字在“信息量”与“简洁度”之间取平衡。
  1. 描述度名字承载的业务语义量,衡量读者能否瞬间联想其含义。
    Desc(name)Desc(name)
  2. 长度惩罚名字每多一个字符都会增加噪音,用系数 λ 衡量惩罚力度。
    λ×Len(name)\lambda \times Len(name)
  3. 命名评分评分越高越见名知意,即描述充分且长度克制。
    Score(name)=Desc(name)−λ×Len(name)Score(name) = Desc(name) - \lambda \times Len(name)

3. 格式规范

中餐后厨里,学徒最先练的就是刀工。同样一颗土豆,有人切丝、有人切块、有人切片,炒出来的口感完全不同。但统一的刀工不只是为了好看:同一锅菜要均匀受热,就得保证菜形一致。格式规范解决的不是美观问题,而是“同一锅菜能不能均匀受热”的协作问题。

缩进两格还是四格、字符串用单引号还是双引号、行尾加不加分号——这些争论在技术上都没有对错,因为它们只是不同的约定。格式规范的核心价值是一致性本身:只要全团队统一,阅读时就不需要不断切换“方言模式”。格式问题的本质,是让读者的视觉习惯保持稳定。

格式问题的终极解法不是人肉遵守,而是交给格式化工具。Prettier 接管缩进、引号、换行、分号、空行等一切“机械决定”,把争论从代码评审中彻底移除。人只负责表达逻辑,机器负责统一外貌——这比任何规范文档都更有执行力。格式混乱程度可以量化:

后厨里最稳定的刀工,不是靠师傅每天吆喝“切细一点”,而是靠一把定好尺寸的标准案板。Prettier 就是那把“定好尺寸的机器”:刀工规矩、不费力、还零争吵——这正是格式问题最适合自动化的原因。

D=NviolationNline\displaystyle D = \frac{N_{violation}}{N_{line}}
混乱密度 = 违规行数 ÷ 总行数。目标不是追求某个具体风格,而是让这个密度无限趋近于零。
  1. 违规行数不符合格式规则的代码行数,由工具自动统计。
    NviolationN_{violation}
  2. 总行数代码库规模,用来把违规数归一化成比例。
    NlineN_{line}
  3. 混乱密度全库每行代码中混入的不合规比例,被工具压得越低越好。
    D=NviolationNlineD = \frac{N_{violation}}{N_{line}}

4. 结构规范

后厨讲究分区:热菜区、冷菜区、备料区、洗碗区。如果凉菜师傅跑到热菜灶台上切三文鱼,热菜师傅又在凉菜间炒辣椒,整间厨房必然乱成一锅粥。结构规范解决的是“东西该放哪、谁归谁管”的更大粒度秩序——比命名和格式高一个层次。

代码结构规范包括:模块划分,一个文件只做一件事,即单一职责;目录组织,按业务域或功能分层,入口、组件、工具各归其位;依赖方向,上层可以依赖下层,但下层不反向依赖上层。这些规则让“新文件该放哪”变成不用问人的常识,而不是每次开会讨论的话题。

衡量模块质量有两个经典指标:内聚度,即模块内部元素围绕同一目标协作的紧密程度;耦合度,即模块之间相互依赖的强度。好结构就是高内聚加低耦合:高内聚让改动局部化,低耦合让重构不牵连一片。用一个比值来概括:

好的后厨,新来的帮厨不用问就知道面粉放哪、刀具归哪。结构规范的价值,就是让团队的“新帮厨”——无论是新人还是三个月后的你自己——都能凭常识到达正确的位置,不必在迷宫一样的目录里迷路。

Module Quality=CohesionCoupling\displaystyle \text{Module Quality} = \frac{\text{Cohesion}}{\text{Coupling}}
模块质量 = 内聚度 ÷ 耦合度。内聚越高、耦合越低,模块越独立,改动越安全。
  1. 内聚度模块内部元素围绕同一职责协作的紧密程度。
    Cohesion\text{Cohesion}
  2. 耦合度模块之间依赖的强度,耦合越高,一处改动牵连面越大。
    Coupling\text{Coupling}
  3. 模块质量这个比值越大的模块,越容易理解、测试和替换。
    CohesionCoupling\frac{\text{Cohesion}}{\text{Coupling}}

5. 自动化工具

后厨规矩定得再好,靠人记总会漏。出餐口站着一位“大师傅”,每道菜出锅前都要过他的眼:摆盘正不正、佐料齐不齐、咸淡对不对。但人肉把关有极限——高峰时段,大师傅一着急就放水了。自动化工具,就是那位永不疲倦、每次一视同仁的“机器大师傅”。

前端生态里有一位分工明确的“大师傅组合”:ESLint 管规则检查,擅长抓语义层面的问题——未使用的变量、危险的全局赋值、违反命名约定的函数名;Prettier 管格式统一,负责缩进、引号、分号、换行等机械外观。简单说,一个管“对不对”,一个管“齐不齐”。

光有工具还不够,还要把工具挂到流程上:Git hooks 在 commit 前自动跑检查,不过关不许提交;CI 门禁在 merge request 时再次校验,漏网之鱼进不了主干。规范从“文档上的文字”变成了“流程中的硬约束”。机器如何判定一段代码合规?本质是一个逻辑与运算:

机器大师傅从不讲情面,也从不缺席。它不会因为赶时间就漏看一道菜,也不会因为某位厨师资历老就手下留情。正因如此,团队里关于格式和低阶问题的争吵被机器彻底接管,人的注意力才能留给真正需要判断力的评审工作。

StyleOK(code)=⋀r∈Rulespass(r,code)\displaystyle StyleOK(code) = \bigwedge_{r \in Rules} pass(r, code)
代码合规 = 所有规则同时通过。只要有一条规则不满足,整体判定就是不合规——像出餐检查,一道菜不合格就整盘退回。
  1. 规则集合团队定义的全部规范条目,构成机器检查的输入。
    Rules={r1,r2,…,rn}Rules = \{r_1, r_2, \dots, r_n\}
  2. 单条规则判定每条规则对代码做布尔判断,结果只有通过或违规两种。
    pass(r,code)∈{0,1}pass(r, code) \in \{0, 1\}
  3. 全部合取所有规则同时通过才算规范,用逻辑与运算符连接。
    ⋀r∈Rulespass(r,code)\bigwedge_{r \in Rules} pass(r, code)

6. 规范落地

后厨老板拿到一本五星级餐厅的菜谱,复印二十份发给厨师,要求第二天照做——结果毫无悬念:大家照旧各炒各的。为什么?因为规矩是“砸”下来的,不是“长”出来的。规范落地难的不是定规则,而是让人心甘情愿地改变习惯。

落地心法第一条是共同制定:规范文档不该由领导一个人拍板,而应由团队核心成员一起起草,逐条讨论“这条规则解决什么问题”。第二条是工具先行:先上 ESLint 和 Prettier,让机器承担执行和反馈,人的抵触会小得多。第三条是评审配套:代码评审中传递规范背后的“为什么”,新人才能内化而非死记硬背。

落地不是开关切换,而是一个扩散过程。刚开始只有少数人遵守,随着工具配置到位、评审模式固定、文档逐步沉淀,遵守率会以指数速度上升:

菜谱要变成后厨的习惯,靠的是师傅带徒弟、一道菜一道菜地练,再加上每次出品时的统一检查。规范落地也是同一件事:不是发文件,而是建机制——让每个人参与定义、让工具负责执行、让评审传递理由,规范才能从纸面“长”进日常。

A(t)=1−e−kt\displaystyle A(t) = 1 - e^{-kt}
采纳率随时间指数上升趋近 100%。k 越大,扩散越快——工具与评审机制就是加速 k 的杠杆。
  1. 采纳率时间 t 时刻,团队中已按新规范行事的比例。
    A(t)A(t)
  2. 未采纳残余尚未转变的比例随时间指数衰减,衰减速度由 k 决定。
    e−kte^{-kt}
  3. 饱和趋势时间足够长时采纳率趋近于 1,规范成为默认习惯。
    A(t)=1−e−kt,lim⁡t→∞A(t)=1A(t) = 1 - e^{-kt}, \quad \lim_{t\to\infty} A(t) = 1

7. 老项目治理

新菜谱好推行,老菜谱难。一家开了十年的餐厅,几十道招牌菜全是老做法的产物,如果某天全部换成新标准,老顾客立刻发现“味儿变了”,后厨也因手忙脚乱而出错。老项目治理,就是一场不能急火的“老菜改良”。

核心原则是“存量容忍、增量收紧”。老代码的历史风格先不翻烧饼:大规模重写风险极高,还容易把 git 历史和并行分支搅乱。新代码必须遵守新规范,新增文件的检查直接在 CI 里强制执行。先控制增量,再寻机消化存量,这是最稳妥的节奏。

存量消化要用工具分批进行:把项目按模块切成一块块“旧菜”,用 codemod 脚本或批量格式化逐块改写,每改一块发一个独立 PR,由原模块负责人评审;灰度发布,先在小流量模块试点,确认无误再推广到全量,防止“改完发现变味了”。这个治理过程可以建模:

老菜改良的智慧,是既承认老菜的价值,又对新菜立规矩。老项目治理同理:不否定历史、不一次性推倒,而是用增量的耐心和工具的确定性,让代码库在一次次小步快走中自然过渡到新的秩序。

D(t)=D0×e−λt+Dnew(t)\displaystyle D(t) = D_0 \times e^{-\lambda t} + D_{new}(t)
总违规量 = 存量违规指数衰减 + 新增违规量。存量被持续消化,新增被门禁压低,整体逐步归零。
  1. 存量债务衰减历史遗留的不合规代码量,随治理推进指数下降。
    D0×e−λtD_0 \times e^{-\lambda t}
  2. 新增债务新代码违反规范的量,通过 CI 门禁保持在低水平。
    Dnew(t)D_{new}(t)
  3. 总债务模型存量持续消化、增量始终受控,总量逐步逼近零。
    D(t)=D0×e−λt+Dnew(t)D(t) = D_0 \times e^{-\lambda t} + D_{new}(t)

AI 应用场景

场景 1:AI 编码助手与团队规范对齐

阶段:代码生成与辅助编码

解决的问题:Copilot、Codex 等 AI 助手生成的代码风格五花八门,如果不加约束,AI 反而会成为规范破坏者。传统做法是人工逐行修改 AI 输出,效率极低且容易遗漏。

具体案例:团队将 ESLint 配置、.editorconfig 与“编码规范.md”放入仓库根目录,并在 AI 助手的自定义指令中写明“所有生成代码必须通过仓库 ESLint 检查,变量统一 camelCase”。AI 生成的代码在 IDE 中实时收到规范检查反馈,违规片段被高亮,工程师一键修复后合入。这就像给机器大厨也发了一本后厨手册。

场景 2:CI 流水线中的规范门禁

阶段:持续集成与质量门禁

解决的问题:人工评审盯格式既低效又伤感情,风格争论消耗评审人大量精力。传统做法靠评审人口头提醒,效果随人数增加而衰减。

具体案例:在 GitLab CI / GitHub Actions 中增加 lint 与 format-check 阶段,任何 MR 只要 ESLint 报错或 Prettier 检查不过,流水线直接标红、禁止合并。规则由全体开发者投票选定,门禁由机器人执行,评审人的精力留给逻辑与架构。这就是把“出餐口大师傅”换成了永不疲倦的机器。

场景 3:AI 辅助老项目批量迁移

阶段:代码重构与存量治理

解决的问题:老项目数千个文件风格混乱,手动重命名和格式化不现实;一次性全量替换又会淹没 git 历史、冲垮并行分支。传统做法是“眼不见为净”或“冒险重写”。

具体案例:团队按模块分批迁移,先运行 Prettier 统一格式,再用 codemod 脚本加 AI 辅助批量重命名——让 AI 生成“旧名 → 新名”映射表,工程师评审后执行,每批独立 PR、由原模块负责人审查,合并后监控回归。这正对应“老菜改良”的分批灰度思路。

Python 演示

python65 行
import re  class MiniStyleLinter:    """A tiny style linter that simulates team rule automation."""     def __init__(self, max_line_len=80):        self.max_line_len = max_line_len        self.reports = []     def check_line(self, lineno, line):        # 检查行长度, 行尾空格与缩进是否合规        body = line.rstrip("\n")        if len(body) > self.max_line_len:            self.reports.append((lineno, "line too long", body.strip()[:24]))        if body.endswith(" "):            self.reports.append((lineno, "trailing space", body.strip()[:24]))        indent = len(body) - len(body.lstrip(" "))        if indent % 4 != 0:            self.reports.append((lineno, "bad indent", body.strip()[:24]))     def check_name(self, lineno, kind, name):        # 函数用 snake_case, 类名用 PascalCase        if kind == "def" and not re.match(r"^[a-z][a-z0-9_]*$", name):            self.reports.append((lineno, "not snake_case", name))        if kind == "class" and not re.match(r"^[A-Z][A-Za-z0-9]*$", name):            self.reports.append((lineno, "not PascalCase", name))     def scan(self, source):        # 逐行扫描并返回问题列表, 模拟 ESLint 的规则检查        self.reports = []        for lineno, raw in enumerate(source.splitlines(), 1):            self.check_line(lineno, raw)            m = re.match(r"^\s*(def|class)\s+([A-Za-z0-9_]+)", raw)            if m:                self.check_name(lineno, m.group(1), m.group(2))        return self.reports     def fix(self, source):        # 自动修复: 去掉行尾空格, 模拟 Prettier 的格式化        return "".join(line.rstrip() + "\n" for line in source.splitlines())  def main():    sample = (        "class orderService:\n"        "    def CalculateTotal(items): \n"        "      total = 0\n"        "        for item in items:\n"        "            total += item.price\n"        "        return total\n"    )    linter = MiniStyleLinter()    problems = linter.scan(sample)    print("=== style report ===")    if not problems:        print("all clean, style ok")    for lineno, kind, detail in problems:        print(f"line {lineno}: [{kind}] {detail}")    print("=== auto fixed ===")    print(linter.fix(sample))  if __name__ == "__main__":    main()
目的:实现一个迷你版“机器大师傅”——用几十行 Python 模拟 ESLint(规则检查)和 Prettier(格式化)的核心逻辑,扫描一段代码并输出违规报告,再自动修复行尾空格。
  1. self.reports.append((lineno, "line too long", body.strip()[:24]))记录违规三元组:行号、违规类型、内容摘要,模仿 ESLint 的报错输出格式。
  2. indent = len(body) - len(body.lstrip(" "))数出行首空格数,再判断缩进是否为 4 的倍数,对应格式规范里的缩进规则。
  3. re.match(r"^\s*(def|class)\s+([A-Za-z0-9_]+)", raw)用正则提取函数名和类名,交给命名规则判定,对应命名规范的自动化。
  4. "".join(line.rstrip() + "\n" for line in source.splitlines())经典格式化技巧:去掉行尾空格再补回换行,模拟 Prettier 的幂等修复。
  5. if __name__ == "__main__":提供可执行入口,让检查器既能当模块导入,也能命令行直接运行。

常见误区

误区很多团队以为把代码格式化整齐就算有规范了,配上 Prettier 后就万事大吉,命名乱、结构乱的问题依然存在,却没人管。

正解格式只是规范最表浅的一层。就像后厨规矩不仅是刀工,还包括食材标签(命名)、灶台分区(结构)和出餐顺序(流程)。命名和结构对可维护性的影响远大于缩进和引号,而这些恰恰是 Prettier 管不了的,需要规范文档 + ESLint + 代码评审共同约束。

为何常见:格式问题最显眼也最好自动化,工具一跑立竿见影,容易让人误以为规范问题已被全部解决。

误区有些人觉得规范越厚越专业,于是把 Airbnb、Google 的规范全抄过来,规则上百条,新同事一写代码满屏报错,怨声载道。

正解规范的目的是消除争论而不是制造争论。每一条规则都应能回答“它解决什么痛点”,并且尽量用工具自动执行。规则过载会增加学习成本和抵触情绪,最终形同虚设。后厨规矩再多,帮厨记不住,就等于没有规矩。

为何常见:抄大厂规范给人一种“我们也很专业”的安全感,却忽略了规范必须适配团队自身的规模和真实痛点。

误区面对存量代码,有人喜欢“一次性解决”:Prettier --write 全库跑一遍,ESLint --fix 全库修一遍,看似干净,实则灾难。

正解全局格式化会产生巨大的 diff,淹没真正的逻辑变更,让 code review 失去意义;同时所有并行分支的合并冲突会集中爆发。正确做法是“存量容忍、增量收紧、分批改写”,像老菜改良一样一块一块来,每批独立 PR 评审后再合。

为何常见:“一步到位”在直觉上很有吸引力,但工程世界是增量世界,一次性革命的代价往往被严重低估。

误区很多团队定完规范后,写一份 Markdown 发到群里就宣布“规范落地”,结果两周后没人再看那份文档,代码风格依旧各自为政。

正解没有工具强制和评审反馈的规范是“纸面规范”。菜谱印得再精美,厨师不照着做就是废纸。落地的关键是机制:让工具在提交前拦截、让评审在合并前把关、让文档在需要时被查阅而不是被背诵。规范要“活”在流程里,而不是“躺”在 wiki 里。

为何常见:文字发布成本最低,容易给人“已经完成”的错觉,而真正的落地是机制建设,比写文档费劲得多。

面试题

Q1. 代码规范对团队最核心的价值是什么?

单选题 · easy

  • A.让代码文件体积更小
  • B.让代码风格统一易读← 正确答案
  • C.让程序运行速度变快
  • D.让老板更容易查考勤

答案:B。规范的核心价值是降低协作中的认知负担:风格统一后,每个成员读别人的代码都像读自己的。它不改变文件大小、不影响运行速度,更与考勤无关。就像后厨规矩不是让菜变得更好吃,而是让所有人都能稳定地做出同一个味道。

Q2. 以下哪种命名方式最符合“见名知意”?

单选题 · easy

  • A.用单个字母作为变量
  • B.变量名尽量简短即可
  • C.用业务含义命名变量← 正确答案
  • D.用数字编号命名变量

答案:C。见名知意指读者不读注释就能猜出变量用途,例如 orderTotal 比 x 或 data 清晰得多。单个字母和数字编号会增加解码成本;“尽量简短”若牺牲含义就背离了目标。好命名像后厨的食材标签,不用掀盖子就知道里面是什么。

Q3. 下列哪些属于代码格式规范范畴?

多选题 · mid

  • A.缩进统一为四个空格← 正确答案
  • B.字符串统一用单引号← 正确答案
  • C.订单模块放在哪级目录
  • D.行尾是否保留分号← 正确答案

答案:ABD。格式规范管的是代码“外貌”:缩进、引号、分号、换行、空行。目录归属属于结构规范,模块划分也是结构规范的内容。格式问题没有对错只有一致,最适合交给 Prettier 这类工具自动处理,就像标准案板让刀工整齐划一。

Q4. 关于 ESLint 和 Prettier 的分工,正确的是?

单选题 · mid

  • A.ESLint 管格式而 Prettier 管规则
  • B.ESLint 管规则而 Prettier 管格式← 正确答案
  • C.两者功能完全相同可以互换
  • D.两者都只适用于 CSS 文件

答案:B。ESLint 负责规则检查,能发现未使用变量、危险写法、命名违规等语义问题;Prettier 负责格式统一,处理缩进、引号、换行等外观问题。二者像后厨的大师傅和标准案板:一个管“对不对”,一个管“齐不齐”。

Q5. 关于内聚和耦合,正确的说法是?

单选题 · mid

  • A.内聚越低模块越加独立
  • B.耦合越高模块越加稳定
  • C.高内聚低耦合是理想结构← 正确答案
  • D.内聚和耦合互不相关

答案:C。内聚指模块内部围绕同一职责协作的紧密程度,耦合指模块间的依赖强度。理想结构是高内聚、低耦合:改动集中在内部、不牵连外部。像后厨热菜区只做热菜、不依赖冷菜区,各区域独立又高效。

Q6. 老项目渐进式规范化中,合理的做法有哪些?

多选题 · hard

  • A.对所有存量代码立即重写
  • B.新代码先严格执行新规范← 正确答案
  • C.按模块分批自动转换格式← 正确答案
  • D.一次性格式化全部历史提交

答案:BC。“存量容忍、增量收紧”是老项目治理的核心:存量不翻烧饼,避免巨大 diff 和合并冲突;新增代码必须在门禁内守规矩;存量靠分批迁移消化。立即全量重写和改写历史提交风险极高,如同把十年老菜一天全换,客人必然流失。

Q7. 减少团队对规范抵触情绪,最有效的做法是?

单选题 · hard

  • A.让工具自动执行少靠人盯← 正确答案
  • B.用绩效考核强制惩罚
  • C.提前保密减少无谓讨论
  • D.一次性引入全部规则

答案:A。抵触多来自“被要求改变”和“规则讲不清理由”。工具自动执行把规范从“人盯人”变成“机器反馈”,不带情绪、行为一致;共同制定规则让成员理解理由,抵触自然消解。高压惩罚和保密推行只会让规范变成对抗工具。

Q8. 为什么格式问题最适合交给 Prettier 这类工具?

单选题 · mid

  • A.因为工具能发现业务逻辑错误
  • B.格式问题没有对错只有一致← 正确答案
  • C.工具运行比代码评审更慢
  • D.格式问题比命名问题重要

答案:B。缩进用两格还是四格、引号用单还是双,本质没有对错,核心是团队保持一致。机器执行零争议、零遗漏、永不疲倦。若靠人肉约定,就像每天靠师傅唠叨刀工,既低效又伤感情,而业务逻辑检查是 ESLint 和评审的职责。

Q9. 代码评审在规范落地中承担的作用有哪些?

多选题 · hard

  • A.传递规范背后的设计理由← 正确答案
  • B.发现工具查不出的语义问题← 正确答案
  • C.完全替代自动化工具检查
  • D.促进团队形成规范共识← 正确答案

答案:ABD。评审是规范内化的关键场景:新人通过评审理解“为什么这么定”而非死记条文;工具只管机械规则,评审则能发现命名是否真的贴切、模块拆分是否合理等语义问题。但评审无法替代自动化工具——人眼会累,机器不会。

Q10. 一份规范要真正被团队执行,最关键的前提是什么?

单选题 · easy

  • A.文档写得越长越详细
  • B.规范与工具流程结合← 正确答案
  • C.用英文撰写显得专业
  • D.由技术总监签字生效

答案:B。规范的价值在于落地:配置 ESLint/Prettier、接入 Git hooks 和 CI 门禁,让机器在提交和合并前把关,规范才从“文档”变为“流程”。文档再长、签名再正式,没有机制执行就是纸面后厨规矩,最终无人照做。