项目开发守则
project_rule
本项目是南京大学软件学院 2018 级软件工程与计算 III 课程设计项目
1. 总体规约
- 开发工具:Intellij IDEA
- 数据库管理工具:Navicat
- 项目文档和沟通管理:飞书
- 项目版本管理工具:git
- 接口管理工具:Apifox
2. 编程规约
Craftsmanship and the Problem of Productivity: Secrets for Going Fast without Making a Mess
2.1 代码规范
JAVA 代码规范参照 IDEA 插件 Alibaba Java Coding Guidelines,尽量减少 warning,不能存在 error
2.1.1 软工设计原则
单一职责原则
对类来说,一个类应该只负责一项职责。如果一个类负责两个职责,可能存在职责 1 变化,引起职责 2 的变化情况。可以基于抽象逻辑,或者业务逻辑对类进行细化。
接口隔离原则
客户端不应该依赖它不需要的接口,一个类对另外一个类的依赖,应该建立在最小的接口上。
依赖倒置原则
高层模块不应该依赖低层模块,两者应依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;中心思想是面向接口编程。
里氏替换原则
如果将所有类型为 T1 的对象 O1 都替换成类型 T2de 对象 O2,程序的行为不发生改变。那么类型 T2 是类型 T1 的子类型。换句话说说有引用基类的地方必须能透明的使用其子类的对象。
开闭原则
在代码结构的设计设计时,应该考虑对扩展开放,对修改关闭,抽象思维搭建结构,具体实现扩展细节。
迪米特法则
一个类对自己依赖的类知道的越要越好。也就是说,对于依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外开放任何信息
2.2 注释规范
- 代码是用来读的,代码的意图应该由代码自身阐述,优先考虑写更可读的代码
- 代码意图明显的情况下,不要加注释重复说明
- 临时注释标记:TODO, FIXME, OPTIMIZE, REVIEW
- 注释应该随着代码更新
2.2.1 必须要写注释的情况
为什么,而非是什么
- 纲要性的注释:简洁清晰的描述一个文件、类或一个流程
- 复杂的业务逻辑、算法
- 代码的作用不直观时,解释这样做的原因
- 存在多种可选方案时,解释这样选择的原因
- 因为某些限制导致代码不一致、不优雅、存在副作用时,注明原因及后果
- 参考了外部资料时,要注明链接方便查看
- 所有的抽象方法
3. 日志规约
使用 slf4j 框架记录项目运行日志,不要用系统原生 log
4. 测试规约
AIR 原则:单元测试在运行时,要感觉像 AIR 一样并不存在 –Automatic, Independent, Repeatable
5. 安全规约
- 用户请求传入的任何参数必须做有效性验证,忽略参数校验可能导致
- page size 过大导致内存溢出
- 恶意 order 导致数据库安全风险或慢查询
- 用户敏感数据必须要放在数据库中,账号密码等强安全数据需要使用彩虹表等进行加密处理
- 用户传入的 SQL 参数严格使用参数绑定或 metadata 字段限定,防止 SQL 注入,禁止字符串拼接 SQL 访问数据库 (还记得华为的 drop database 吗)
- 隶属于用户个人的页面或者功能必须进行权限控制校验
- 在使用平台资源 (短信、邮件、电话等) 必须实现防重复限制,如数量限制、疲劳度控制、验证码校验等,避免被滥用
6. 数据库规约
6.1 建表规约
- 表达是否概念的字段必须使用 is_xxx 方式命名,数据类型是
unsigned tinyint
(1 表示是,0 表示否) - 如果用字符串来表示有限个状态 (例如 status),必须在后端使用枚举类型传入参数
- 表名、字段名必须使用小写字母或数字,禁止数字开头,禁止两个下划线间只有数字。数据库字段名的修改代价很大,字段名的命名需要慎重考虑。
- Mysql 在 Windows 下不区分大小写,而 Linux 下默认区分,因此不允许出现任何大写字母
- 表名不使用复数名词
- 表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯
- 小数类型为 decimal,禁止使用 float 和 double
- float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储
- 如果存储的字符串长度几乎相等,使用 char 定长字符串类型
- varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效率
- 表必备三字段:id, gmt_create, gmt_modified。
- 其中 id 必为主键,类型为 unsigned bigint、单表时自增、步长为 1。gmt_create, gmt_modified 的类型均为 timestamp 类型,前者现在时表示主动创建,后者过去分词表示被动更新
- 表的命名最好以
业务名称_表的作用
作为开头 - 字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循
- 不是频繁修改的字段。
- 不是 varchar 超长字段,更不能是 text 字段。
- 所有字符的存储与表示都要以
utf-8
编码- 字符统计函数在不同编码有区别,因此统一编码
6.2 SQL 规范
- 不要使用
count(列名)
或count(常量)
来替代count(*)
,count
是统计行数的语法,和数据库无关,和 NULL 非 NULL 无关count(*)
会统计值为 NULL 的行,而count(列名)
不会统计为 NULL 的行
- 使用
ISNULL()
来判断是否为 NULL,因为NULL<>NULL, NULL=NULL, NULL<>1
的结果都是 NULL 而不是 true
7. 版本控制规约
乱动 origin/main 者,狗头打掉!
7.1 Commit 规则
- commit 记录以 commit 类型作为开头:
- feat 新特性
- fix bug 修复
- hotfix 对生产代码的紧急修复
- docs 文档改动
- style 格式化
- refactor 重构代码
- test 项目测试
- commit 的粒度是一个小功能点或一个 bugfix,将恢复的误伤操作降到最低
- commit 记录中,用一句简练的话概括,然后空一行阐述提交增加或修改的地方
- commit 要有独立性,如果是多个功能相同或相近的 commit 可以使用 rebase -i 合并或调整;如果是对上一个 commit 的修正可以用 amend 修复;禁止无意义的 commit
- 如果有临时但暂时不需要提交的改动,可以用 stash 暂存代码
- 在有多个 commit,功能开发到达一个里程碑节点或是完成功能再 push,以整洁 origin/master,尽可能一个 push 就是一个 feat
|
|
7.2 开发规则
我们需要一个干净整洁的 work tree
- 所有的项目开发都会在 dev 分支上进行,生产代码会保留在 master 分支上,非 hotfix 等紧急情况禁止向 master 分支提交
- 所有新 feature 的开发都需要建立一个新的、以该 feature 命名的分支,然后在该分支上进行提交后,将其
merge
到 dev 分支上 - 项目更新一律使用 rebase,即
git pull --rebase
7.3 其余规范
- 谁提交了.idea 或者.vscode 文件夹,谁请喝奶茶