代码规范工具优化实践:一次从“形散神也散”到“有规可循”的工程化探索

Debug到怀疑人生
2025-06-25 08:30
阅读 793

开篇:为什么我决定聊聊这个话题?

开篇:为什么我决定聊聊这个话题?

作为一名有5年开发工具链建设经验的工程师,这几年来我一直跟“代码规范”打交道。说实话,刚入行的时候,我对这块并没有太大感触,觉得不过是一些格式化的配置和强制性的检查工具而已,直到我们团队在推进一个大型项目的重构时,遇到了一系列由代码风格不统一引发的问题。

那时候,项目已经发展到几百个文件、几十万行代码的规模,不同成员各自为政,有的喜欢用 snake_case,有的偏爱 camelCase;有人喜欢把变量命名得天花乱坠,有人甚至直接 var1, var2 这样命名;更有甚者,在同一个函数里缩进方式都不一致,导致整个阅读体验非常差。

我们花了大量时间争论“谁写得更合理”,效率大打折扣。于是,我开始思考一个问题:有没有一种方式,能够让规范自动落地,而不是靠人肉review?

于是就有了这篇实战经验分享文章,我想通过一个真实项目案例,带大家看看我们是怎么一步步建立起一套真正可用、可持续维护的代码规范体系的。


问题描述:那些年我们踩过的坑

问题描述:那些年我们踩过的坑

我们当时的项目是一个中台服务,前端是 React + TypeScript,后端是 Node.js + Express + TypeORM,前后端都有独立的 Git 仓库,但整体上属于同一业务域。整个团队大约有 8 名开发,3 前端,4 后端,还有1名 PM兼架构师。

痛点一:命名混乱,难以维护

举个小例子,我们有一个处理用户身份核验的模块:

  • A同学写的类叫 UserVerify
  • B同学写了 UserValidation
  • C同学搞了个 IdCardCheck

你猜这三个类是不是同一个功能?答案是否定的——但我们花了整整一个下午才搞明白这三个类之间的关系!

痛点二:格式千奇百怪,看别人的代码像读天书

比如这段代码:

function checkAuth(token) {
  if (!token) { return false }
  else {
    const decoded = jwt.verify(token, SECRET)
    return decoded && decoded.userId > 0
  }
}

看起来还算是规矩,那再看看下面这段:

function  checkAuth   (token) {
  if(!token)return false
  else{
    var decoded=jwt.verify(token,SECRET)
    return decoded&&decoded.userId>0
  }
}

虽然功能完全一样,但后者看着就像“鬼画符”。更严重的是,这种格式差异还经常引发不必要的 diff 冲突,浪费评审时间。

痛点三:缺乏统一工具链支持

当时我们的 CI 是 Jenkins 搭建的,但只做了构建成功与否的判断,没有对代码质量有任何限制。即使我们在本地安装了 ESLint、Prettier 这类工具,也没法保证所有人每次都运行这些检查。

更糟的是:每个同学的编辑器配置不一样。有的开了保存自动格式化,有的没开;有的用了 VS Code 的插件,有的用了 WebStorm 的配置……最后还是各写各的。


解决方案:我们是怎么做的?

解决方案:我们是怎么做的?

既然痛点这么明显,那就必须做点改变。我们团队的核心目标很明确:

建立一套自动化、可落地、全链条覆盖的代码规范工具体系。

具体来说,我们要做到:

  1. 标准统一:命名规则、缩进、语句结构等有一套明文规定;
  2. 工具自动化:所有规则可以通过 lint、format 工具自动检测和修复;
  3. 全流程管控:从本地开发、提交代码,到 CI 构建都进行约束;
  4. 可维护性强:规则能灵活配置,并且容易升级迭代。

技术选型:站在巨人肩上的选择

我们并不是从头造轮子,而是基于社区广泛使用的成熟工具来搭建,选型如下:

工具 用途 说明
Prettier 代码格式化 统一风格,自动格式化
ESLint JavaScript/JSX/TS 检查 包括命名、语法错误、最佳实践等
Stylelint CSS/SCSS/Less 检查 对样式也有规范要求
CommitLint Git 提交信息检查 统一 commit message 风格
Husky + Lint-Staged Git Hook 工具 在 git 提交前进行检查
Airbnb ESLint 规则库 基础规则集 减少重复造轮子的工作

此外,我们还结合 GitHub Action 来完善 CI 端的检查逻辑。


代码实践:如何将这些工具串联起来

代码实践:如何将这些工具串联起来

下面我会详细介绍一些关键实现步骤,并贴出核心配置片段,让你能真正 copy-paste 回去就能用。

Step 1: 安装依赖(以前端为例)

首先在 package.json 中添加必要的 devDependencies:

"devDependencies": {
  "eslint": "^8.46.0",
  "prettier": "^3.2.4",
  "eslint-config-airbnb": "^19.0.4",
  "eslint-plugin-import": "^2.28.1",
  "eslint-plugin-react": "^7.33.2",
  "eslint-plugin-jsx-a11y": "^6.7.1",
  "stylelint": "^14.21.0",
  "stylelint-config-standard-scss": "^4.1.0",
  "husky": "^8.0.3",
  "lint-staged": "^13.2.3",
  "@commitlint/cli": "^17.8.0",
  "@commitlint/config-conventional": "^17.8.0"
}

Step 2: 创建 .eslintrc.js

// .eslintrc.js
module.exports = {
  extends: ['airbnb', 'prettier'],
  parserOptions: {
    ecmaVersion: 2022,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  env: {
    browser: true,
    es2021: true,
  },
  rules: {
    // 自定义规则
    'no-console': ['warn'],
    'react/prop-types': 0,
    'react/react-in-jsx-scope': 0,
    'react/jsx-uses-react': 0,
  },
};

Step 3: 创建 .prettierrc

{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "bracketSpacing": true,
  "arrowParens": "always"
}

Step 4: 设置 Git Hook(Husky)

安装 husky:

npm install husky --save-dev
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"

然后配置 lint-staged

// package.json
"lint-staged": {
  "*.js": ["eslint --fix", "prettier --write"],
  "*.jsx": ["eslint --fix", "prettier --write"],
  "*.ts": ["eslint --fix", "prettier --write"],
  "*.tsx": ["eslint --fix", "prettier --write"],
  "*.scss": ["stylelint --fix"]
}

Step 5: 加入 CommitLint 检查

创建 .commitlintrc.js

module.exports = {
  extends: ['@commitlint/config-conventional'],
};

并在 .husky/commit-msg 中加入:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit $1

这样就能确保 commit message 必须符合规范啦。


踩坑经验:那些只有自己踩过才知道的坑

这套体系搭建过程中,我们也遇到不少问题,有些甚至让我一度怀疑人生 😂,以下是我印象最深的几个:

坑点一:ESLint 和 Prettier 冲突了怎么办?

这几乎是个必踩的坑。一开始我们发现 Prettier 格式化之后,ESLint 又报错,说某些规则不匹配。后来才发现,是因为两者默认的规则并不完全一致。

解决方案是安装 eslint-config-prettier 插件:

npm install eslint-config-prettier --save-dev

并修改 .eslintrc.js 中的 extends:

extends: ['airbnb', 'prettier'],

这个顺序也很重要,要确保 prettier 放在最后,这样它的规则才会优先级最高。

坑点二:团队协作下的个性化配置怎么处理?

每个程序员多少都会有一些个人喜好,比如有些人喜欢用双引号,有些人就是不喜欢。但是我们必须在团队层面达成统一,否则就没法谈规范。

我们的做法是:不允许本地私自更改 prettier/eslint 的配置文件。如果确实有个别特殊需求,可以提交 issue 到公共仓库,由技术负责人评估是否纳入全局规则。

为了防止误改,我们还在 CI 中加入了配置校验脚本,确保 .eslintrc.js.prettierrc 文件的内容与约定的一致。

坑点三:旧项目迁移太痛苦怎么办?

我们那个项目已经有几十万个历史代码,不可能一夜之间全部 fix 掉。

所以初期我们设定了比较宽松的规则,先启用基本的格式化工具,如自动换行、缩进、空格等基础格式化。

随着习惯养成,逐步引入更严格的命名规范、语义规则等。每一步都配合一次全员培训或者会议讲解新规则的意义。

这样做既能减轻阻力,也能让团队慢慢适应,最终接受整套体系。


效果总结:规范带来的收益远超预期

当我们把这个系统全面落地后,效果非常明显,以下是几个关键指标的改善:

指标 实施前 实施后
Pull Request review 时间 平均 4h 降到 1.5h
无效 Diff 冲突数 每次 PR 5~10 处 几乎为零
新同学上手速度 一周左右才能写出合规代码 3天内完成标准提交
重大风格争议次数 每周至少 1 次 几乎不再发生
代码搜索效率提升 关键词命中率较低 明显提高

最重要的是,大家都习惯了“规范即底线”,再也不用花时间争论“这个应该怎样写”的问题了。


经验分享:给开发者的建议

经过这次实践,我也积累了不少经验和教训,总结成几点建议,供大家参考:

✅ 1. 不要一开始就追求完美

很多同学在引入规范工具时总想一次性配齐所有规则,结果往往适得其反。正确的做法是:先跑通流程,再逐步丰富规则。

建议分阶段实施:

  • 第一阶段:配置格式化工具(Prettier)
  • 第二阶段:接入基础 Lint 检查(ESLint + 默认规则)
  • 第三阶段:根据团队特点定制规则
  • 第四阶段:增加 CI 构建检查环节

✅ 2. 让规范“落地”比“存在”更重要

工具再好,没人用等于白搭。所以一定要:

  • 所有人都安装好对应的编辑器插件(VSCode / WebStorm / etc.)
  • 设置好保存自动格式化
  • 做一次团队内部培训,解释规则背景和意义
  • 在 README 或 Wiki 中放一份 quick start 文档

✅ 3. 给新人准备一份标准化模板

我们后来为每个新入职的同学提供了一个 .config-template 目录,里面包含了一份完整的 .eslintrc, .prettierrc, .stylelintrc 文件,并附带安装命令和使用说明。避免每次都要手动设置,省时省力又不容易出错。

✅ 4. CI 检查不能遗漏

不要以为本地检查就够了。CI 端还是要加一层兜底机制,防止有人绕过了 hook 或者本地工具失效。我们是通过 GitHub Actions 实现的:

name: Linter Check

on:
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18.x
      - run: npm ci
      - run: npx eslint .
      - run: npx stylelint "**/*.scss"

这样,哪怕本地没跑 lint,在 CI 上也会被拒绝合并。


小插曲:那次“因为格式冲突差点打架”的经历

记得有一次上线紧急 bug 修复,A 同学提了一个 PR,B 同学在 review 的时候突然跳出来:“你这个变量命名太烂了吧,能不能起个有意义的名字?”

结果 A 很不服气地说:“我这是按照之前的代码风格写的啊!你们平时都是这么写的。”

眼看就要吵起来了,幸好我及时出面,翻出了我们最新制定的命名规范文档,一条条对照着来看。结果发现两人都错了,变量名不符合命名规范中的动宾结构要求。我们临时在 Slack 上开了个会议,现场更新了命名规范,并同步到 everyone。

事后复盘,大家都觉得:有了统一的规则,反而更容易达成共识。 吵架少了,效率高了,这就是规范的价值。


结语:让工具成为团队文化的一部分

开发环境配置界面-1

写到这里,其实这篇文章更像是我在回顾过去几年在工程化体系建设方面的一些心得体会。代码规范工具不是冷冰冰的程序,它是团队文化的外在体现。当我们能够用技术手段“固化”开发行为时,就是在打造一个更高效率、更低摩擦的研发环境。

希望这篇文章对你有所启发,如果你正在考虑或正在实施类似的工具体系,不妨动手试试上面提到的方法,也许你的团队会因此变得更“清爽”一些。

记住一句话:代码是写给人看的,偶尔给机器跑一下。而好的规范,正是让“人”更能读懂这段代码的关键。

如有需要,欢迎留言交流实践经验 👇

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝