2023-02-26 14:18:22 +08:00
## 开发规范
目录
- 规范说明
- 规范建议
- 命名规范
- 编码规范
- 框架规范
- 插件规范
- 数据库规范
- 包功能规范
### 规范说明
- 开发规范意义是是让大家尽可能写出风格统一的代码,让团队代码有更好的可读性与可维护性。
- 在实际业务开发中,除了要提高业务开发效率,保证线上业务高性能外,好的编程习惯也是一个开发人员基本素养之一。
### 规范建议
- 在我们实际开发中,有很多开发人可能是由某一语言转到另外一个语言领域,在转到另外一门语言后, 我们都会保留着对旧语言的编程习惯,在这里,我建议的是,虽然不同语言之前的某些规范可能是相通的, 但是我们最好能够按照官方的一些demo来熟悉是渐渐适应当前语言的编程规范, 而不是直接将原来语言的编程规范也随之迁移过来。
### 命名规范
#### 命名准则
* 当变量名称在定义和最后一次使用之间的距离很短时,简短的名称看起来会更好
* 变量命名应尽量描述其内容,而不是类型
* 常量命名应尽量描述其值,而不是如何使用这个值
* 在遇到for, if等循环或分支时, 推荐单个字母命名来标识参数和返回值
* package名称也是命名的一部分, 推荐全部使用小写, 请尽量将其利用起来
* 使用一致的命名风格
#### 文件命名规范
* 全部小写
* 除unit test外避免下划线(_)
* 文件名称不宜过长,但不必为了简短而忽略含义
#### 变量命名规范参考
* 驼峰命名
* 见名知义,避免拼音替代英文
* 不建议包含下划线(_)
* 不建议包含数字
#### 函数、常量命名规范
* 驼峰式命名
* 可导出的必须首字母大写
* 不可导出的必须首字母小写
* 避免全部大写与下划线(_)组合
#### 参考文档
* [Practical Go: Real world advice for writing maintainable Go programs ](https://dave.cheney.net/practical-go/presentations/gophercon-singapore-2019.html#_simplicity )
### 编码规范
#### import
* 单行import不建议用圆括号包裹
* 按照`官方包`, NEW LINE, `当前工程包`, NEW LINE, `第三方依赖包`顺序引入
```go
import (
"context"
"string"
"greet/user/internal/config"
"google.golang.org/grpc"
)
```
#### 函数返回
* 对象避免非指针返回
* 遵循有正常值返回则一定无error, 有error则一定无正常值返回的原则
#### 错误处理
* 有error必须处理, 如果不能处理就必须抛出。
* 避免下划线(_)接收error
#### 函数体编码
* 建议一个block结束空一行, 如if、for等
```go
func main (){
if x==1{
// do something
}
fmt.println("xxx")
}
```
* return前尽可能空一行
```go
func getUser(id string)(string,error){
....
return "xx",nil
}
```
### 框架规范
- 项目启动初始化方法都放在`server/internal/global/init.go`,插件放在:`server/addons/xxx插件/global/init.go`
- Api 对外接口层 都放在`server/api`,根据实际应用和应用具体功能划分子目录,插件放在:`server/addons/xxx插件/api`
- Router 路由注册方式应尽可能按gf2.0版本风格定义, 参考: https://goframe.org/pages/viewpage.action?pageId=30736904
- Controller 控制器层 都放在`server/internal/controller`,根据应用和具体功能拆分子目录,插件放在:`server/addons/xxx插件/controller`
- Input 对内接口层 都放在`server/internal/model/input`,根据应用和具体功能拆分子目录并以`in`结尾,插件放在:`server/addons/xxx插件/model/input`
- Logic 业务逻辑层 统一放在`server/internal/logic` 根据实际业务需求按logic/xxx/*.go拆分, 插件放在: `server/addons/xxx插件/logic`
- Orm 模型实体层 统一放在`server/internal/model/entity`
- Dao 数据访问层 统一放在`server/internal/dao`
- 自定义工具函数都放在 `server/utility` ,且应根据不同类型的方法做分包,相同类型的方法放在同一个包内
- 状态枚举统一调用`server/internal/consts`中的常量和属性
### 插件规范
- 插件命名统一全部小写
- 资源文件在 `addons/xxx插件/resource` 或`server/resource`
- 每个插件之前应该是完全独立的,尽可能避免插件于插件之间的调用依赖
- 插件和主模块之前的调用应尽可能通过 Service 接口来调用
- 插件业务初始化顺序下应在主模块之后, 应尽可能避免使用init方法隐式初始化
### 数据库规范
#### 命名规范
- 数据表名小写,多关键字使用下划线分割(关键字尽量全称)
- 字段名小写,多关键字使用下划线分割(关键字尽量全称)
- 禁止使用保留字并且尽量少用含有关键词来命名
- 临时表必须以tmp_开头、以日期结尾, 备份表必须以bak_开头、以日期结尾
2023-03-16 15:35:02 +08:00
- 同数据库表名设置统一前缀,默认是`hg_`
2023-02-26 14:18:22 +08:00
- 插件模块表名建议以`hg_addon_`开头,如:`hg_addon_hgexample_table`,含义:`插件_案例_表格`。在生成代码时可自动识别实体命名为:`Table`
#### 基础规范
- 所有的字段必须添加注释
- 尽可能地使用InnoDB作为表的存储引擎
- 所有的表和字段必须添加注释
- 尽量控制表行数在500万以内
- 尽可能采用冷热数据分离策略
- 禁止以图片、文件等二进制数据
#### 表设计规范
- 尽可能每张表的索引数量控制在5个以内
- 每一张InnoDB表都必须含有一个主键, 自增主键必须是`bigint`类型
- 尽可能避免使用外键约束
- 设置数据表架构应考虑后期扩展型
- 遵循范式与冗余平衡原则
#### 字段设计规范
- 尽可能将所有的数据列定义为 `NOT NULL` 类型
- 避免 ENUM 数据类型
- json 存储的数据用 `json` 字段代替 `text`
- 表与表关联的键名保持一致或以关联表名的缩写为前缀
- 固定长度的字符串字段务必使用 `char`
- 使用 `UNSIGNEG` 存储非负整数
- 禁止敏感数据以明文形式存储
- 金额相关的数据必须使用 `DECIMAL` 数据类型
- 尽量所有表有 `status` 字段来标注数据状态(1:启用,2:禁用,3:已删除),业务状态请使用其他字段;`status`字段类型 为带符号的 `tinyint(1)` 。如果还需要其他的数据状态 请先判断该状态的数据是有用的数据还是无意义的数据,有用的数据状态 > 0,无意义的数据状态 < -1
- 所有的删除(除开清空回收站操作) 请标记 `status` 为 3
- 创建时间字段为`created_at`,修改时间字段为`updated_at`,删除时间字段为`deleted_at`,类型`datetime`
- 用户关联 id 字段为 `member_id` 或 `created_by`
- 排序字段为 `sort`
- 区分应用字段为 `app_id`
- 区分插件来源需要增加字段为 `addon_name` 和 `is_addon`
- 关系树表中必须包含字段:`id`(主键)、`pid`(上级ID)、`level`(树等级)、`tree`(关系树)
- 多选、多图、多文件字段类型应尽量使用类型`json`
### 包功能规范
##### Input(对内接口 - 过滤验证)
- 接收Api 对外接口数据和参数过滤
- 对提交的复杂数据参数进行验证处理返回
##### View(视图)
- 数据处理显示
- 页面渲染
##### Controller(控制器)
- 数据接收
- 服务调用
- 简单CURD入库
- 简单业务逻辑
##### Logic(业务逻辑 - 服务接口功能)
- 数据逻辑处理
- 数据入库
- 数据查询