跳转至

代码规范

开发规范

一、命名要求

  • 变量、函数和类的命名需要有具体的含义,对于非常长的变量,我们推荐用缩写的方式进行简化,进而提升可读性

  • 变量、类一般以名词或动名词的单词组成;函数一般以动词或行为的词组组成

  • 对于普通变量、函数需要以小驼峰风格命名;对于常量而言,需要以全大写、下划线风格命名;对于类而言,需要以大驼峰风格命名

二、注释要求

  • 精简、清晰的注释对于代码维护有很大的帮助,我们推荐写有效的注释,但冗余、无效的注释并非我们期望的,它们提高代码的理解成本,因此注释精简也是非常重要的环节

  • 错误、过时的注释是绝对不可取的,我们在提交代码的过程中,注释需要实时更新,即便是删除错位的注释而不是修改它们,也会比留下它们好

  • 好的注释一般分为三部分内容:做什么、为什么、怎么做;我们也可以通过代码来相互解释,但精简、清晰是我们写注释的基本原则

三、函数要求

1.拒绝超大函数

不同的代码规范都会对超大函数(或者叫大函数)进行定义,而 Hango 给出的定义是:超过 50 行的函数我们称之为超大函数。超大函数一般是各种逻辑的堆叠,超大函数对于代码阅读有非常大地影响,对于此类函数后期的维护成本则是会更高,因此我们建议将大于 50 行的函数进行拆分,让函数内的逻辑更富有语义化。

2.优化圈复杂度

圈复杂度是一种代码复杂度的衡量标准,可以理解为函数用例所有的分支总数,如下运算符都会引入圈复杂度

  • if 语句
  • while 语句
  • for 语句
  • case 语句
  • catch 语句
  • and 和 or 布尔操作
  • ? : 三元运算符

我们可以通过各类工具,例如 Sonar 、MetricsReload 等工具对函数进行圈复杂度的计算,圈复杂度影响函数的理解难度,我们对圈复杂度的要求: 15 <= 圈复杂度

圈复杂度 代码理解难度 测试难度 维护成本
1 ~ 10 清晰
10 ~ 20 复杂
20 ~ 30 非常复杂
> 30 不可读 不可测 非常高

3.减少函数入参

函数入参的个数我们要求小于等于 5 个,过长参数列是典型的坏味道,因为数量越多的函数入参将会有更多松散的变量需要维护,函数的可用性需要依赖来自各处的变量,对于函数维护是不小的挑战

4.提炼重复代码

重复的代码在后期变更中将是噩梦,相同的代码散落各处,一个问题的修复将很难实现,我们需要把各处的相同代码进行同步修复,而这也并不能保证万无一失;因此我们需要尽可能地提炼函数和重复代码,降低后续代码修改难度

5.合理处理异常

对于可以预知的异常我们希望在代码中进行预处理,而非直接通过 try\catch 进行捕获处理,因为异常发生后程序将进行异常栈的采集和处理,这个过程是非常消耗性能的,举个典型的案例来说

Null Point Exception (NPE) 是开发过程中最常见的异常,我们需要通过判空来避免它,而不是通过 try\catch 来捕获他

四、代码格式

  • 采用 4 个空格缩进,禁止使用 tab 字符

  • 一行代码我们建议在 120 个字符以下,否则需要进行合理地换行

  • if/for/while/switch/do 等保留字与括号之间都必须加空格

  • 任何二目、三目运算符的左右两边都需要加一个空格

  • 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格;而左大括号前需要空格

  • if/for/while 语句需要以 {} 包裹,即使只有 1 行内容

五、业务规约

1.数据bean相互转换

代码开发过程中,经常会遇到数据 bean A 需要转换为数据 bean B,该类操作,应放在对应 service 层实现,避免后续扩展时因需调用其他 service 函数填充某个字段时导致的扩展困难等问题。

2.业务远程短连接调用命名规范

对于业务模块中需要远程调用其他服务的场景,应在该业务的 package 中创建 remote package,并创建 XXXRemoteClient 类(xxx为业务名)用以实现远程调用相关代码


OpenAPI 规范

一、请求API规范

1.API 使用请求参数 Action 风格案例如下

GET /hango/v1/service/?Action=DescribeServices

2.查询统一用 GET 类型接口;修改接口(增、删、改)统一用 POST 类型接口

3.接口统一用动词风格

4.API 的请求 path 进行类型划分,以版本号作为的根 path,二级 path 以资源标识;版本序号:v1\v2\v3\v4 ...

以 Hango 最大概念拆分,例如当前查询服务的请求 path 为:GET /v1/service/?Action=DescribeServices&ServiceId=1

服务:/service
路由:/route
插件:/plugin
物理网关:/physicalGateway
虚拟网关:/virtualGateway

6.复数和单数查询接口归一,以过滤参数区分,用于精简各类命名的接口;案例如下

查询服务:/v1/service?Action=DescribeSerices&Offset=0&Limit=20

查询 serviceId 为 1 的服务:/v1/service?Action=DescribeSerices&ServiceId=1

二、请求参数规范

列表查询接口都需要提供分页和模糊功能,以请求参数 Pattern、 Offset 和 Limit 区分; Offset 默认值 0 , Limit 默认值 20

三、响应body

1.单一对象查询响应格式

{
  "Code": "Success",
  "Message": "处理成功",
  "RequestId": "7e78958a-0d74-4a7b-be36-c303b2909580",
  "Result": {
      ...
  }
}

2.分页查询统一用如下格式进行返回(Total 代表总数、 Data 代表对象列表)

{
  "Code": "Success",
  "Message": "处理成功",
  "RequestId": "7e78958a-0d74-4a7b-be36-c303b2909580",
  "Total": 1,
  "Result": [
    {
      ...
    }
  ]
}

3.修改接口,可以考虑传回数据

{
  "Code": "Success",
  "Message": "处理成功",
  "RequestId": "7e78958a-0d74-4a7b-be36-c303b2909580",
  ...
}
Back to top