项目规范(转载)

目录

  • 第一章、Java中的规范
    • 1.1)类命名采用驼峰命名法
    • 1.2)函数(方法)命名使用驼峰命名
        • 辅助函数命名
        • Controller层/Service层函数命名
        • DAO层函数命名
    • 1.3)变量/枚举/常量命名
    • 1.4)函数参数
    • 1.5)注释
    • 1.6)代码
  • 第二章、MySQL数据库中的规范
    • 2.1)数据库规范
    • 2.2)数据表规范
    • 2.3)字段名规范
    • 2.4)数据库字段类型规范

友情提醒:

先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。注意:大部分内容是摘抄整理的

第一章、Java中的规范

1.1)类命名采用驼峰命名法

属性和类(实体)的命名约定是采用驼峰命名法
1、Controller必须根据业务进行命名,驼峰,Controller结尾
2、Service必须根据业务进行命名,驼峰,Service结尾
3、implement必须根据业务进行命名,驼峰,业务+service+impl结尾
4、辅助类的命名,根据功能进行命名,如果是工具类,utils或者util进行结尾

例如:ChgInfoController
例如:ChgInfoService
例如:ChgInfoServiceImpl
例如:ChgUtil

1.2)函数(方法)命名使用驼峰命名

辅助函数命名

例如构建对象,请用build开头,表示只用于构建对象,并且返回,请使用 private修饰

public class Car {
    private String make;
    private String model;
    private String registration;

    // 构造函数
    public Car(String make, String model, String registration) {
        this.make = make;
        this.model = model;
        this.registration = registration;
    }

    // 辅助函数用于创建Car对象
    private static Car buildCar(String make, String model, String registration) {
        // 在辅助函数中执行对象的创建逻辑
        return new Car(make, model, registration);
    }

    public static void main(String[] args) {
        // 使用辅助函数创建Car对象
        Car car = buildCar("Toyota", "Camry", "ABC123");
        System.out.println("Car make: " + car.make);
        System.out.println("Car model: " + car.model);
        System.out.println("Car registration: " + car.registration);
    }
}
Controller层/Service层函数命名

Controller层方法的命名规约detail/query/count/create/remove/modify 作前缀

Service层方法的命名规约find/query/count/create/remove/modify 作前缀

例如,"getUserById""createNewUser"
DAO层函数命名

Dao层方法的命名规约find/query/count/insert/delete/update作前缀

复数形式使用queryXXs/updateXXs/insertXXs进行命名

DAO所有传参如果是单个参数,请使用@param注解进行注明

所有XXMapper.xml获取参数,请使用@param(“XX”) 命名, #{XX}获取,${XX}会有SQL注入的风险,具体细节请参考Mysql手册`跟’的区别

1.3)变量/枚举/常量命名

变量:使用驼峰
状态类的变量,请使用int类型
boolean类型的变量,请使用has开头,请勿使用is开头,在某些序列化框架下,可能会导致反序列化失败

常量、枚举使用“_”分割,且每个单词全大写

枚举命名请使用业务+Enum进行命名

接口常量命名请使用业务+Constant进行命名(尽量使用枚举来定义常量)

1.4)函数参数

尽量使用对象进行传递,严禁使用MAP进行传参

如果要进行单个参数传递,最好不要操作5个参数,参数太多,看起来太混乱

1.5)注释

类注释

/**
 * 项目名:wang-order-center
 * 创建人: XX
 * 创建时间:2018/8/13 15:45
 * 类名:OrderController
 * 类描述: 订单控制器
 */

函数注释

函数参数,一定要加上 @param 这样,别人在调用的时候,ide会进行提示,如果涉及到枚举 加上注解 @see 可以跳转到枚举

/**
 * 创建人:XXX
 * 创建时间:2018-08-20 20:46:04
 * 描述: 购物车创建订单
 *  @param userId 用户ID
 * @param subUserId 用户ID
 * @param addrId 地址ID
 * @param cartProductIds 购物车ID集合
 * @param fahuoTimeLimitedMode    截单模式 0 立即截单, 1 根据活动时间截单
 */

代码注释

代码注释,进行别使用/**/的形式,注释不需要像写作文那样详细,只需要介绍是做什么的就好

// 构建订单对象

1.6)代码

Controller尽量只做转发,不做具体逻辑实现,所有逻辑实现交由service进行
service的接口函数,尽量功能单一,职责越小,越便于维护跟扩展

如果涉及到写等动作,请在函数上加上@transaction注解/或者自己用事务块包裹

service如果不需要捕获异常,可以往上层抛,订单中心已经在全局做了异常处理

尽量做到所有的check在入参就应该进行判断

如果遇到需要构建对象,大量 set函数不应该放置主流程,抽离出来一个辅助函数,直接调用辅助函数即可,辅助函数注释写好,主流程调用辅助函数加上功能注释

代码内部尽量不使用多层for循环调用,在不注意的情况,多层for循环嵌套构建对象,很容易写出内存泄漏的代码

尽量不使用匿名内部类,使用lambda,因为现在jdk已经是1.8版本,支持Java8的特性

如果一段代码,超过两个地方调用,说明需要进行抽象,然后对抽象进行实现

函数跳转层级尽量不要过深,因为是业务代码,跳转太深,很容易把人绕晕了

如果一个函数出现特别多的if else 考虑把if else建成枚举,然后枚举内进行判断返回

日志

所有service层可以直接抛出异常,不需要捕获异常处理,已经配置好全局异常处理,只需要抛出错误信息就好

业务错误打印日志,尽量别打印error打印warning级别日志就好,所有抛出异常上面,尽量打印错误日志的参数

日志打印,尽量使用一下示例打印 // 正确打印 LOGGER.info(“订单ID错误,订单ID:{}”,order.getId()); // 错误打印 LOGGER.info(“订单ID错误,订单ID:”+order.getId());

日志是常量,所以请使用以下定义 private static finale Logger LOGGER = LoggerFactory.get(XX.class);

日志引用,禁止引用具体实现,请引用 slf4j接口

请求路径

尽量使用Restful风格

/liveId/productId URL参数,请使用 @PathVariable(“liveId”)String liveId 指定名称绑定

查询尽量使用Get请求方式,如果参数在URL传递过多,可以不使用Get请求,使用POST请求,请把参数写进请求体内

所有写的操作一律使用POST请求,参数放入请求体内,公共参数,以后会让客户端放入请求头内

幂等

所有的核心写接口,例如,创建订单,支付,取消订单等,一定一定要做幂等,幂等可以在所有的check后也可以在函数调用就进行判断,但是一定是在逻辑进行前

幂等接口,一定要跟调用方统一状态,达成共识

往往幂等会伴随着并发同时进行,因为网络传输,机器性能,请求处理,事务提交带有太多的不确定性,所以要加以控制,所以redis尽量只做并发控制跟短时间内的幂等,请勿太依赖redis来进行做幂等,在redis锁后,插入前请进行DB查询操作,查看是否已经写入过,如果已经写入,拒绝请求

单机锁,如果没有竞争资源,不要使用锁

尽量使用 Lock接口作为锁,别使用Synchronize作为锁,后者作为重量级锁,太影响性能

对锁的使用不清楚,严禁私自使用,尽量多请教会的人,避免写出死锁或者活锁

分布式锁,目前只是用了redis的setnx操作作为分布式锁的实现,使用分布式锁,一定一定要设置过期时间或者在锁代码块执行完毕,手动移除锁,否则出现锁不能释放,你就悲剧了………

目前setnx操作,使用的是jedis连接池来实现的,没有使用spring-data提供的redisTemplate是因为,后者的setnx操作并非一个原子操作,运气不好的情况,极有可能出现setnx操作了,setexprie失败,导致锁不过期,但是jedis使用,切勿忘记,使用完毕,归还连接,jedis是不会再你调用完毕主动归还连接的

所有锁,请在check完毕或者check之前进行锁定资源,请勿在最后锁定,进行无用的写

锁定的资源,必须是唯一的,例如,订单ID,订单编号等

第二章、MySQL数据库中的规范

2.1)数据库规范

1、库名必须有意义。因为在linux系统下mysql数据库区分大小写,Windows系统下不区分,为了避免出现问题,全小写

-- 使用小写字母的数据库名称示例
CREATE DATABASE hrdb;

2、一个项目一个数据库,多个项目慎用同一个数据库。
3、数据库和表要使用统一的字符集(如:UTF8),统一字符集可以避免由于字符集转换产生的乱码,MySQL中的UTF8字符集汉字点3个字节,ASCII码占用1个字节。
字符集:utf8mb4、排序规则:utf8mb4_general_ci

2.2)数据表规范

1、表名全小写,多个单词使用下划线分割,使用单数名词,英文全拼,必须有意义做到见名识义。
使用全小写是因为在linux系统下mysql数据库区分大小写,Windows系统下不区分。

 "customer" 而不是 "customers"
 "customer" 而不是 "Customer"
"aliyun_admin"而不是"AliyunAdmin"

2、明细表的名称为:主表的名称+字符dtl(detail缩写)

采购定单的名称为:po_order,则采购定单的明细表为:po_orderdtl

3、临时库/表必须以tmp为前缀并以日期为后缀。备份库/表必须以bak为前缀并以日期为后缀。通用表要加前缀all

临时表:temp_orders_20220101, temp_data_20220101
临时库:temp_db_20220101, temp_workspace_20220101

备份表:bak_data_20220101
备份库:bak_workspace_20220101

通用表:all_user。

4、数据库表要用自增id,一定是主键且为自动增长,建议主键是整型,最好是unsigned bigint类型

5、禁止在表中建立预留字段

6、外键、触发器不要有。 数据的完整性靠程序来保证。
触发器和存储过程容易将业务逻辑和DB耦合在一起。

7、创建时间create_time、修改时间update_time、创建人create_by、修改人update_by字段,每个表都必须有!
注意:create_time和update_time一定要用数据的时间戳,自动生成。不要通过代码去操作这两个字段。

2.3)字段名规范

1、列名使用全大写或者全小写,多个单词使用下划线’_'分隔,因为Linux系统上,对于列名和列别名,不区分大小写。

"order_date""customer_name""ORDER_DATE""CUSTOMER_NAME"
反例:userID、houseID。
反例:username、userid、isgood。

2、列名使用有意义的名称:用英文单词的全拼尽量避免使用缩写,除非是广泛认可的缩写,以确保字段名的清晰和易懂。

例如 "customer_id" 代表顾客ID。
"user_id"代表用户ID
反例:cus_id、uid、pid。

3、列名中避免使用保留字:确保字段名不是MySQL的保留字,以避免潜在的冲突和错误。

如name、desc、range、match、delayed等。参考MySQL官方保留字。

4、列名中包含表名,但命名字段时不要重复表的名称,而是使用有意义的缩写

在名employe的表中应该为"emp_name"
反例:"employee_name"

5、列名表达是与否概念必须使用is_xxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)。坚持is_xxx的命名方式是为了明确其取值含义与取值范围

正例:表达逻辑删除的字段名is_deleted,1表示删除,0表示未删除。

说明1:如果一个字段存储的是数值,并且是非负数,要设置为unsigned(无符号的)。注意:POJO类中的任何布尔类型的变量,都不要加is前缀,而是设置从is_xxx字段到布尔类型变量xxx的映射关系。
说明2:系统设定取值范围很小且固定的场景,例如表示是与否的值,使用tinyint类型。

2.4)数据库字段类型规范

1、字段必须填写描述信息。

2、如果存储的字符串长度几乎相等,则使用char定长字符串类型。
例如,11位手机号,邮编(postcode)。

这种固定长度的纯数字,也不要用int类型或long类型,因为只有数字参与了运算,才用数值型。

3、小数类型为decimal,禁止使用float和double类型。
在存储时,float和double类型存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过decimal的范围,那么建议将数据拆成整数和小数并分开存储。

4、整型int定义中不添加长度
比如使用INT,而不是INT(4)。

5、varchar是可变长字符串,不预先分配存储空间,长度不要超过5000个字符
禁止使用varchar类型作为主键。

6、长度超过5000个字符定义字段类型为text,独立出来一张表,用主键来对应,避免影响其他字段的索引效率。

7、禁止使用blob、text类型保留大文本、文件、图片
建议使用其他方式存储,MySQL只保存指针信息。

8、一列需要占很大空间的字段,一定要单独拎出来,不要和常用信息放一张表。
举个例子: 文章的信息和文章的内容,这一定要分成两个表。否则会给你的文章性能带来极大的挑战。因为很多情况下,查看文章列表,根本不需要查看到文章的内容。

9、所有字段在设计时,必须有默认值,避免使用NULL字段
NULL字段很难查询优化、NULL字段的索引需要额外空间、NULL字段的复合索引无效
字符型的默认值为一个空字符值串‘’,数值型的默认值为数值0,逻辑型的默认值为数值0。

10、系统中所有逻辑型中数值0表示为“假”,数值1表示为“真”,datetime、smalldatetime类型的字段没有默认值,必须为NULL。

除以下数据类型timestamp、image、datetime、smalldatetime、uniqueidentifier、binary、sql_variant、varbinary外

11、多表中的相同列,必须保证列定义一致。

12、不建议使用ENUM类型,使用TINYINT来代替。

转载自:大佬
https://www.cnblogs.com/wangxiayun/category/1398529.html

你可能感兴趣的:(其他知识,Java基础知识汇总,开发语言)