2025年9月3日
32 分钟阅读

编程规范

(一) 命名风格 1. [强制] 代码中的 命名均不能以 下划线或美元符号 开始,也不能以 下划线或美元符号 结束。 反例: _name / __name / \$Object / name_ / name$ / Object\$

编程规范

[TOC]

编程规范

(一) 命名风格

  1. [强制] 代码中的 命名均不能以 下划线或美元符号 开始,也不能以 下划线或美元符号 结束。

反例: _name / _name / $Object / name / name$ / Object$

  1. [强制] 代码中的 命名 严禁使用拼音 与英文混合的方式,更不允许直接使用中文的方式(复杂专有名词除外)。

说明: 正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式

也要避免采用。

正例: alibaba / taobao / youku / hangzhou 等国际通用的名称, 可视同英文。

反例: DaZhePromotion [打折 ] / getPingfenByName () [评分 ] / int 某变量 = 3

  1. [强制] 类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外: DO / BO /

DTO / VO / AO

正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion

反例: macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

  1. [强制] 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从

驼峰形式。

正例: localValue / getHttpMessage () / inputUserId

  1. [强制] 常量命名 全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

正例: MAX _STOCK _COUNT

反例: MAX _COUNT

  1. [强制] 抽象类命名使用 Abstract 或 Base 开头 ;异常类命名使用 Exception 结尾 ;测试类命名以它要测试的类的名称开始,以 Test 结尾。

  2. [强制] 文件名统一使用小写

  3. [强制] 杜绝完全不规范的缩写, 避免望文不知义 。

反例: AbstractClass “缩写 ”命名成 AbsClass ;condition “缩写 ”命名成 condi ,此类随

意缩写严重降低了代码的可阅读性。

  1. 【推荐】 为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词

组合来表达其意。

正例: 从远程 仓库 拉取代码的类 命名 为 PullCodeFrom RemoteR epository 。

反例: 变量 const a; 的随意命名 方式。

  1. 【推荐】 如果 模块 、接口 、类、方法使用了设计模式,在 命名时 体现出具体模式。

说明: 将设计模式体现在名字中,有利于阅读者快速理解架构设计 理念 。

正例: public class OrderFactory ;

public class LoginProxy ;
public class ResourceObserver ;

  1. 【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。

说明: 枚举其实就是特殊的常量类,且构造方法被默认强制是私有。

正例: 枚举名字 为 Process StatusEnum 的成员名称 :SUCCESS / UNKOWN _REASON 。

(二) 常量与变量定义

  1. [强制] 不允许 任何魔法值 (即未经定义的常量 )直接出现在代码中。

反例: const key = "Id #taobao _" + tradeId ;

cache.put (key , value );

  1. 【推荐】 不要使用一个常量类维护所有常量, 按常量功能进行归类,分开维护。

说明: 大而全的常量类,非得使用查找功能 才能定位到修改的常量,不利于理解 和维护。

正例:缓存相关常量放在类 CacheConsts下;系统配置相关常量放在类ConfigConsts下。

  1. 【推荐】 如果变量值仅在一个范围内变化 ,且带有名称之外的延伸属性 ,定义为枚举类。下面

正例中的数字就是延伸信息,表示星期几。

正例:

public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}

  1. **【强制】**对所有的变量优先使用const,可变的变量使用let,不允许使用var
    正例:
javascript
const birthDateTime = Date.now(); const condition = foo(); let count = 1; if (condition) { count += 1; }

(三) 代码格式

  1. [强制] 大括号的使用约定。如果是大括号内为空,则简洁地写成 {} 即可,不需要换行 ;如果

是非空代码块则:

1) 左大括号前不换行。

2) 左大括号后换行。

3) 右大括号前换行。

4) 右大括号后还有 else 等代码则不换行 ;表示终止 的右大括号后必须换行。

  1. [强制] 左小括号和字符之间不出现空格 ;同样,右小括号和字符之间也不出现空格。详见

第 5 条下方正例提示。

反例: if (空格 a == b 空格)

  1. [强制] if /for /while /switch /do 等保留字与 括号之间都必须加空格。

  2. [强制] 任何 二目、三目 运算符 的左右 两边 都需要 加一个空格。

说明: 运算符包括赋值运算符 =、逻辑运算符 && 、加 减乘除符号 等。

  1. [强制] 采用4空格缩进,如果使用tab缩进,必须设置1个tab为4个空格.

正例: (涉及 1-5 点)

javascript
function main() { // 缩进 4个空格 const say = "hello"; // 运算符的左右必须有一个空格 const flag = 0; // 关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格 if (flag == 0) { console.log(say); } // 左大括号前加空格且不换行;左大括号后换行 if (flag == 1) { console.log("world"); // 右大括号前换行,右大括号后有else,不用换行 } else { console.log("ok"); // 在右大括号后直接结束,则必须换行 } }
  1. [强制] 注释的 双斜线与 注释 内容之间 有且仅有 一个空格 。

正例:

javascript
// 注释内容注意在//和注释内容之间有一个空格。
  1. [强制] 单行字符数限制不超过120个,超出需要换行,换行时遵循如下原则:

1) 第二行相对第一行缩进 4个空格,从第三行开始,不再继续缩进,参考示例。

2) 运算符与下文一起换行。

3) 方法调用的点符号与下文一起换行。

4) 方法 调用时,多个参数 ,需要 换行时, 在逗号后 进行 。

5) 在括号前不要换行,见反例。

正例:

javascript
const sb = new StringBuffer(); // 超过 120 个字符的情况下,换行缩进 4 个空格, 点号和方法名称 一起换行 sb.append("zi").append("xin")... .append("huang")... .append("huang")... .append("huang");

反例:

javascript
StringBuffer sb = new StringBuffer(); // 超过120个字符的情况下,不要在括号前换行 sb.append("zi").append("xin")...append ("huang"); // 参数很多的方法调用可能超过120个字符,不要在逗号前换行 method(args1, args2, args3, ... , argsX);
  1. [强制] 方法参数在定义和传入时,多个参数逗号后边必须加空格。

正例: 下例中实参的 "a", 后边必须要有一个空格。

javascript
method("a", "b", "c");
  1. [强制] 去除行末尾的多余空格。
  2. [强制] 必须使用分号";"。

(四) 控制语句

  1. [强制] 在一个switch块内,每个case要么通过break /return等来终止,要么注释说明程

序将继续执行到哪一个case为止 ;在一个switch块内,都必须包含一个default语句并且

放在最后,即使它什么代码也没有。

  1. 【推荐】 表达 异常的分支时, 少用 if -else 方式 ,这种 方式可以改写成:
javascript
if (condition) { ... return obj; } // 接着写 else 的业务逻辑代码 ;

说明:如果非得使用 if()...else if()...else... 方式表达逻辑,
[强制] 避免后续代码维护困难,请勿超过3层。

正例: 超过 3层的if -else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,

其中卫语句示例如下 :

typescript
function today(): void { if (isBusy()) { console.log(“change time.); return; } if (isFree()) { console.log(“go to travel.); return; } console.log(“stay at home to learn Alibaba Java Coding Guideline s.); return; }
  1. 【推荐】 除常用方法(如 getXxx/isXxx )等外,不要在条件判断中执行 其它 复杂的语句,将复

杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

说明:很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么

样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?

正例:

javascript
// 伪代码如下 const existed = (file.open(fileName, "w") != null) && (...) || (...); if (existed) { ... }

反例:

javascript
if ( (file.open(fileName, "w") != null) && (...) || (...) ) { ... }
  1. 【推荐】 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、

获取数据库连接, 进行不必要的try -catch操作(这个try -catch是否可以移至循环体外 )。

  1. 【推荐】 接口入参保护,这种场景常见的是用于做批量操作的接口。

  2. 【参考】下列情形 ,需要进行参数校验 :

1) 调用频次低的方法。

2) 执行时间开销很大的方法 。此情形中, 参数校验时间几乎可以忽略不计,但如果因为参

数错误导致中间执行回退,或者错误,那得不偿失。

3) 需要极高稳定性和可用性的方法。

4) 对外提供的开放接口,不管是RPC /API /HTTP接口。

5) 敏感权限入口 。

  1. 【参考】 下列情形 ,不需要进行参数校验 :

1) 极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查要求 。

2) 底层调用频度比较高的方法 。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底

层才会暴露问题。一般DAO层与Service层都在同一个应用中,部署在同一台服务器中,所

以 DAO的参数校验,可以省略。

(五) 注释规约

  1. [强制] 方法内部单行注释,在被注释语句上方另起一行,使用 // 注释。方法内部多行注释

使用 /* */ 注释,注意与代码对齐。

  1. [强制] 所有的枚举类型字段必须要有注释,说明每个数据项的用途。

  2. 【推荐】 与其 “半吊子 ”英文来注释,不如用中文注释把问题说清楚。专有名词 与关键字 保持

英文原文即可。

反例: “TCP连接超时 ”解释成 “传输控制协议连接超时 ”,理解反而费脑筋。

  1. 【推荐】 代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑

等的修改。

说明: 代码与注释更新不同步, 就像路网与导航软件更新不同步一样, 如果导航软件严重滞后,

就失去了导航的意义。

  1. 【参考】 谨慎注释掉代码 。在上方详细说明,而不是简单地注释掉。 如果无用,则删除。

说明: 代码被注释掉有两种可能性: 1)后续会恢复此段代码逻辑。 2)永久不用。前者如果没

有备注信息,难以知晓注释动机。后者建议直接删掉 (代码仓库保存了历史代码 )。

  1. 【参考】对于注释的要求:第一、能够准确反应设计思想和代码逻辑 ;第二、能够描述业务含

义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同

天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路 ;注释也是给继任者看

的,使其能够快速接替自己的工作。

  1. 【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的

一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。

反例:

// put elephant into fridge
put(elephant, fridge);

方法名put,加上两个有意义的变量名 elephant 和 fridge ,已经说明了这是在干什么,语

义清晰的代码不需要额外的注释。

  1. 【参考】 特殊注释标记, 请注明标记人与标记时间。 注意及时处理这些标记, 通过标记扫描,

经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。

1) 待办事宜

// TODO:( 标记人,标记时间, [预计处理时间 ])

表示需要实现, 但目前还未实现的功能。 这实际上是一个 Javadoc 的标签, 目前的 Javadoc

还没有实现, 但已经被广泛使用。 只能应用于类, 接口和方法 (因为它是一个 Javadoc 标签 )。

(六) 其它

  1. [强制] 在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。

  2. [强制] 注意 Math .random () 注意取值 的范围 0≤ x<1 (能够

取到 零值,注意除零异常 ),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后

取整。

  1. [强制] 获取当前毫秒数 Date.now(); 而不是 new Date () .getTime ();

  2. 【推荐】 及时清理不再使用的代码段或配置信息。

说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。
5. [推荐] 字符串使用单引号 '',生成字符串时,使用模板字符串代替字符串连接
正例:

javascript
function sayHi(name) { return `How are you, ${name}?`; }

反例:

javascript
function sayHi(name) { return 'How are you, ' + name + '?'; }
  1. [推荐] 复制数组推荐拓展运算符
javascript
const arrCopy = [...arr];
  1. [推荐] 使用解构存取和使用多属性对象
javascript
const [a, b] = array; const [a = aDefault, b] = array; const [a, b, ...rest] = array; const { a: a1, b: b1 } = obj; const { a: a1 = aDefault, b = bDefault } = obj;
  1. [推荐] 尽可能使用箭头函数
    正例:
javascript
const foo = ()=> { ... }

推荐tsconfig 和 eslint 配置

tsconfig

json
{ // 用来配置编译选项 "compilerOptions": { "target": "esnext",// 生成js 的版本,下一版本 "module": "esnext", // 生成的module的形式,esm,cmd,amd啥的 "strict": false, // 是否严格模式 "jsx": "preserve", // jsx用于的开发环境,preserve/react/RN "importHelpers": true, // 指定是否引入tslib里的复制工具函数 "moduleResolution": "node", // 用于选择模块解析策略 node/classic "experimentalDecorators": true, // 用于指定是否启用实验性的装饰器特性 "declaration": true, // 是否生成类型声明 "incremental": true, // 是否启用增量编译 "esModuleInterop": true, // 通过导入内容创建命名空间,实现CommonJS和ES模块之间的互操作性 "allowSyntheticDefaultImports": true, // 用于允许从没有默认导出的模块中默认导入 "sourceMap": true, // 编译时是否生成.map文件 "baseUrl": ".",// 用于设置解析非相对模块名称的基本目录,相对模块不会受到baseUrl的影响 // 用于设置模块名到基于baseUrl的路径映射 "paths": { "@/*": [ "src/*" ] }, // 指定要包含在编译中的库文件 "lib": [ "esnext", ] }, // 指定编译的文件,没有include和exclude时候用 "file": [], // 指定待编译的文件 "include": [ // ** : 任意目录 , * : 任意文件 "src/**/*.ts", ], // 指定排除的文件 "exclude": [ "node_modules" ] }

eslint

json
{ ... rules: { // 代码风格规则 'semi': [2, 'always'], // 使用分号 'indent': [ 2, 4, ], 'no-multi-spaces': 2, // 不允许多个连续的空格 'space-unary-ops': [2, { words: true, nonwords: false }], // 一元运算符后必须有空格 'space-infix-ops': 2, // 中缀操作符周围必须有空格 'space-before-blocks': [2, 'always'], // 代码块前必须有空格 'no-mixed-spaces-and-tabs': 2, // 不允许混合使用空格和制表符 'no-multiple-empty-lines': [2, { max: 1 }], // 连续空行不超过 1 行 'no-trailing-spaces': 2, // 行尾不允许有空格 'no-whitespace-before-property': 2, // 属性名和点运算符之间不能有空格 'no-irregular-whitespace': 2, // 不允许出现不规则的空白字符 'space-in-parens': [2, 'never'], // 圆括号内不能有空格 'comma-dangle': [2, 'never'], // 逗号不允许有拖尾 'array-bracket-spacing': [2, 'never'], // 数组括号内不允许有空格 'object-curly-spacing': [2, 'never'], // 对象括号内不允许有空格 'max-len': ['error', { code: 120 }], // 行宽最大为 120 字符 'operator-linebreak': [2, 'before'], // 运算符换行时,运算符在行首 'comma-style': [2, 'last'], // 逗号风格:换行时在行尾 'no-extra-semi': 2, // 不允许出现多余的分号 'curly': [2, 'all'], // 使用大括号包裹所有控制结构 'key-spacing': [2, { beforeColon: false, afterColon: true }], // 属性名与冒号之间不能有空格,冒号后必须有空格 'comma-spacing': [2, { before: false, after: true }], // 逗号后必须有空格 'semi-spacing': [2, { before: false, after: true }], // 分号后必须有空格 'camelcase': [1, { properties: 'always' }], // 强制使用驼峰命名法 'new-cap': ['error', { newIsCap: true, capIsNew: false }], // 构造函数首字母必须大写 'spaced-comment': [2, 'always'], // 注释后必须有空格 'no-inline-comments': 2, // 不允许行内注释 'eqeqeq': [2, 'always', { null: 'ignore' }], // 强制使用全等 (===) 运算符 'no-else-return': [1, { allowElseIf: false }], // 禁止 else 语句,如果 if 语句中已返回值 'no-loop-func': 2, // 禁止在循环中定义函数 'no-restricted-syntax': [ 1, { selector: 'BinaryExpression[operator=\'instanceof\']', message: 'Use \'instanceof\' for object type detection.' // 不建议使用 instanceof 来检测对象类型 }, { selector: 'BinaryExpression[operator=\'typeof\']', message: 'Use \'typeof\' for type detection.' // 不建议使用 typeof 来检测类型 }, { selector: 'CallExpression[callee.name=\'parseInt\']', message: 'Use Math.floor, Math.round, or Math.ceil instead of parseInt to remove decimal points.' // 不建议使用 parseInt 来移除小数点 } ], 'no-implicit-coercion': [1, { allow: ['!!'] }], // 禁止隐式类型转换 'radix': [2, 'always'], // parseInt 函数必须指定进制 'quotes': [2, 'single'], // 强制使用单引号 'no-array-constructor': 2, // 不允许使用 Array 构造函数 'max-lines-per-function': [ 1, { max: 50, // 函数最大行数为 50 行 skipComments: true, // 跳过注释行 skipBlankLines: true, // 跳过空行 IIFEs: true // 对立即调用的函数表达式 (IIFE) 应用规则 } ], 'max-params': [1, 6], // 函数参数最大数量为 6 'no-eval': 2, // 禁止使用 eval 'prefer-const': 1, // 建议使用 const 声明不变的变量 'no-var': 1, // 建议使用 let/const 替代 var 'prefer-destructuring': [ 1, { object: true, array: false } // 建议使用解构赋值 ], 'prefer-template': 1, // 建议使用模板字符串 'template-curly-spacing': [2, 'never'], // 模板字符串中的花括号内不允许有空格 'no-duplicate-imports': 2, // 禁止重复导入 // TypeScript 特定规则 '@typescript-eslint/no-unused-vars': 'error', // 禁止未使用的变量 '@typescript-eslint/explicit-module-boundary-types': 'off' // 允许省略函数的返回类型 }, }
评论区 (0)
你的临时ID:
暂无评论,来发表第一条评论吧!