admin管理员组

文章数量:1574540

文章目录

    • 前言
      • 最近更新时间
      • 参考
      • 规范说明
      • IDE插件
    • 编程规范
      • 命名规范
        • 【强制】命名不能以下划线或美元符号开头或者结尾。
        • 【强制】命名不允许使用拼音与英文混合的方式。
        • 【强制】类目使用UpperCamelCase风格。
        • 【强制】方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格。
        • 【强制】常量命名应该全部大写,单词间使用下划线隔开。
        • 【强制】抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类目开始,以Test结尾。
        • 【强制】定义数组时,类型和[]紧挨。
        • 【强制】POJO类中的任何布尔类型的成员变量,不要加is前缀。
        • 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英文单词。
        • 【强制】包名统一使用单数形式;类目可以使用复数形式。
        • 【强制】避免子类父类使用同名的成员变量;同一方法的不同代码块内使用同名的局部变量;非get/set方法的参数和成员变量同名;
        • 【强制】枚举中不能定义NAME的枚举值或name的域变量。
        • 【推荐】命名可以做到代码自解释。
        • 【推荐】如果使用了设计模式,在命名时要体现出具体模式。
        • 【推荐】接口中的方法不用加任何修饰符,并尽量避免定义变量。
        • 【强制】对于Service和DAO类,实现类使用接口类名+Impl命名。
        • 【参考】枚举类名加上Enum后缀,枚举成员名称需要全大写并下划线分割。
      • 注释规范
        • 【强制】类、类属性、类方法的注释必须使用javadoc注释方式,不能使用//方式。
        • 【强制】所有的抽象方法(包括接口中的方法)必须要用javadoc注释。
        • 【强制】所有的类都必须添加创建者信息和创建日期。
        • 【强制】方法内部单行注释,使用//注释,在被注释语句上方另起一行。
        • 【强制】方法内部多行注释,使用/* */注释,注意与代码对齐。
        • 【强制】else、else if的区块注释,使用//注释,在区块的第一句执行语句上方另起一行。
        • 【强制】所有的枚举字段必须要有注释。
        • 【推荐】使用中文注释。
        • 【推荐】代码修改的同时,注释也要进行相应的修改。
        • 【推荐】在类中,删除未使用的任何字段和方法;在方法中,删除未使用的任何参数声明与内部变量。
        • 【参考】谨慎注释掉代码。如果以后可能恢复,在上方添加详细注释说明;如果无用,则删除。
        • 【参考】对于注释的要求:第一,能够准确反映设计思想和代码逻辑;第二,能够描述代码背后的业务含义。
        • 【参考】注释应该精简准确、表达到位,避免出现一个极端:过多过滥的注释,造成维护负担。
        • 【参考】特殊注释标记如TODO、FIXME,请注明标记人与标记时间。
      • 格式规范
        • 【强制】大括号内为空写为{};非空则Java式大括号风格。
        • 【强制】小括号外侧前后都加空格,内侧前后都不加空格。
        • 【强制】类型强制转换时,右括号之后不加空格。
        • 【强制】任何二目、三目运算符的左右两侧都加空格。
        • 【强制】采用4个空格缩进,禁止使用tab字符。
        • 【强制】双斜线注释符后面有且仅有一个空格。
        • 【强制】单行字符数不超过120个。
        • 【强制】换行后的所有行都缩进4个空格;运算符、方法调用的点符号之前换行;逗号(例如多个参数)之后换行;
        • 【强制】定义或使用时,多个参数的逗号之后加空格。
        • 【强制】IDE的text file encoding设置为UTF-8,换行符使用Unix格式。
        • 【推荐】没有必要增加若干空格使得多个变量赋值时按照等号来对齐。
        • 【推荐】单个方法的总行数不超过80行。
        • 【推荐】不同逻辑/语义/业务的代码之间插入一个且仅一个空行分割来提高可读性。
      • 常量定义
        • 【强制】不允许任何魔法值。
        • 【强制】在long/Long赋值,使用大写L。
        • 【推荐】不用使用一个常量类维护所有常量,而是按照业务/功能进行归类。
        • 【推荐】如果变量值仅在一个固定范围内变化用enum类型来定义。
        • 【推荐】常量的复用有5个层次,分别对应不同位置:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。
      • 控制语句
        • 【强制】在一个switch块内,每个case要么通过 break / continue / return 等来终止,要么注释说明程序将继续执行到哪一个case为止。
        • 【强制】每个switch块都必须包含一个default语句并放在最后,即使它为空。
        • 【强制】当switch括号内的变量类型为String,必须先进行null判断。
        • 【强制】在 if / else / for / while / do 语句中必须使用大括号,即使只有一行代码。
        • 【强制】三目运算符 ``condition ? exp1 : exp2`` 中,高度注意 exp1 和 exp2 在涉及算术计算或数据类型转换时,可能抛出因自动拆箱导致的NPE异常。
        • 【强制】在高并发场景中,避免使用“等于”判断作为中断或退出的条件。
        • 【推荐】表达异常分支时,少用if-else方式,而是用哨兵语句。
        • 【强制】超过3层的if-else的逻辑判断代码,需要使用哨兵语句、策略模式、状态模式等来实现。
        • 【推荐】当某个方法的代码总行数超过10行时,return / throw 等中断逻辑的右大括号后需要加一个空行。
        • 【推荐】不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个命名有意义的布尔变量,以提高可读性。
        • 【推荐】不要在其他表达式(尤其是条件表达式)中,插入赋值语句。
        • 【推荐】避免采用取反逻辑运算符。
        • 【推荐】循环体内的语句要考量性能,定义对象/变量、获取数据库连接、不必要的try-catch都尽量移至循环体外处理。
        • 【参考】推荐进行参数校验的场景如下:
        • 【参考】推荐不必进行参数校验的场景如下:
      • 异常处理
        • 【强制】可以通过预检查方式规避的RuntimeException异常不应该通过catch的方式来处理,例如:NPE。
        • 【强制】使用enum的valueOf获取枚举值时,不存在对应枚举值则会抛出IllegalArgumentException异常,而不是返回null。
        • 【强制】异常捕获不要用来做流程控制、条件控制。
        • 【强制】稳定代码不要加catch;非稳定代码尽可能区分异常类型,再做对应的异常处理。
        • 【强制】捕获异常后应该进行处理或者将异常抛给它的调用者;最外层业务使用者必须处理异常,将其转化为用户可以理解的内容。
        • 【强制】事务场景中,catch到异常后,如果需要回滚,则需要手动回滚事务。
        • 【强制】finally块必须对资源对象、流对象进行关闭,并内部进行try-catch处理关闭异常。
        • 【强制】不要在finally块中使用return。
        • 【强制】捕获异常类型与抛异常的类型匹配或者是其父类。
        • 【强制】在调用RPC、三方包或动态生成类的相关方法时,捕捉异常必须使用Throwable类来进行拦截。
        • 【推荐】方法的返回值可以为null,不强制返回空集合/空对象时,必须添加注释充分说明什么情况下会返回null值。
        • 【推荐】NPE产生的常见场景如下:
        • 【推荐】对公司外开放的接口必须使用错误码;内部跨应用RPC调用优先使用Result方式:封装isSuccess()方法、错误码、错误信息;应用内部推荐抛出异常。
        • 【推荐】定义时要区分unchecked/checked异常,避免直接使用RuntimeException异常,而是使用有业务含义的自定义异常。
      • 日期时间
        • 【强制】日期格式化时,传入pattern中表示年份统一使用小写的yyyy。
        • 【强制】日期格式化时,分清楚大小写的M和H。
        • 【强制】获取当前毫秒数:System.currentTimeMillis();而不是new Date().getTime();
        • 【强制】不允许在程序任何地方使用 java.sql.Date/Time/Timestamp
        • 【强制】禁止在程序中写死一年为365天;应该使用动态获取。
        • 【推荐】避免闰年2月问题。2月29日的一年后是3月1日。
        • 【推荐】使用枚举值来指代月份。如果使用数字,注意Date、Calendar等日期相关类的month取值为0-11。
      • OOP规范
        • 【强制】避免通过对象来引用静态变量或静态方法。
        • 【强制】所有的覆写方法,必须加 @Override 注解。
        • 【强制】相同参数类型(避免使用Object类型),相同业务含义,才可以使用Java的可变参数。
        • 【强制】外部调用的接口,不允许修改方法签名。
        • 【强制】接口过时必须加 @Deprecated 注解,并在接口文档注释中清晰地说明采用的新接口是什么。
        • 【强制】不能使用过时的类或方法。
        • 【强制】应使用常量或确定非null的对象来调用equals。
        • 【强制】避免使用float/Float类型,而是使用double/Double类型进行替代。
        • 【强制】所有整型包装类的对象之间的值比较,使用equals方法。
        • 【强制】浮点数之间的等值比较,不能使用 == 或者 equals 来判断。
        • 【强制】BigDecimal的值的比较使用compareTo()方法,而不是equals()方法。
        • 【强制】禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。
        • 【强制】任何货币金额,均以最小货币单位且整型类型来存储。
        • 【强制】定义数据对象DO类时,属性类型要与数据库字段类型相匹配。
        • 【强制】POJO类的属性、RPC方法的参数和返回值,必须使用包装数据类型。
        • 【推荐】局部变量推荐使用基本数据类型。
        • 【强制】定义POJO类时,不要定义任何属性的默认值。
        • 【强制】序列化类新增属性时,不能修改serialVersionUID值;完全不兼容升级,需要修改serialVersionUID值。
        • 【强制】构造方法中禁止加入任何业务逻辑;初始化逻辑应该添加到init方法中。
        • 【强制】POJO类必须覆写toString()方法;子类注意添加super.toString()。
        • 【强制】禁止在POJO类中,同时存在对应属性xxx的isXxx()和getXxx()方法。
        • 【推荐】使用索引访问String的split方法得到的数组时,注意长度检查。
        • 【推荐】一个类的多个构造方法或同名方法应该顺序放置在一起。
        • 【推荐】类内方法的推荐按照信息价值来顺序放置:公有方法 > 保护方法 > 私有方法 > getter/setter方法。
        • 【推荐】构造函数/setter方法的参数名称与成员变量名称一致;getter/setter方法中不含业务逻辑。
        • 【推荐】循环体内,字符串的联接方式,使用StringBuilder的append方法。
        • 【推荐】不允许被继承的类和不允许被覆写的方法,都使用final来修饰。
        • 【推荐】慎用Object的clone方法来拷贝对象,默认是浅拷贝。
        • 【推荐】类成员与方法访问控制从严,方便维护重构。
      • 集合处理
        • 【强制】只要覆写equals,就必须覆写hashCode。
        • 【强制】Set存储的对象、Map的key对象,必须覆写equals和hashCode。
        • 【强制】使用Map的方法 keySet() / values() / entrySet() 返回集合对象时,不可以对其进行添加元素操作。
        • 【强制】在使用 java.util.stream.Collectors 的toMap()方法时,选择带 BinaryOperator mergeFunction 参数的方法来处理重复key。
        • 【强制】在使用 java.util.stream.Collectors 的toMap()方法时,注意当value为null会抛NPE异常。
        • 【强制】判断集合内部元素是否为空,使用isEmpty()方法,而不是size() == 0的方式。
        • 【强制】返回值不能使用Collections类返回的对象
        • 【强制】ArrayList的subList结果不可强制转换成ArrayList,否则会抛异常。
        • 【强制】在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生异常。
        • 【强制】使用集合转数组的方法,必须使用集合的带参toArray(T[] array)方法,传入的是类型完全一致、长度为0的空数组。
        • 【强制】在使用Collection接口任何实现类的addAll()方法时,都要对输入的集合参数进行NPE判断。
        • 【强制】使用Arrays.asList()把数组转换成集合时,不能对其进行修改,否则会抛异常。
        • 【强制】泛型通配符<? extends T>来接收返回的数据,此泛型集合不能使用add方法;而<? super T>不能使用get方法。
        • 【强制】在无泛型限制的集合赋值给泛型限制的集合时,在使用集合元素时,需要进行instanceof判断,避免抛出类型转换异常。
        • 【强制】不要在foreach循环里进行元素的添加/删除操作;删除操作应该使用Iterator方式,如果并发操作,需要对Iterator迭代器对象加锁。
        • 【强制】实现Comparator时必须单独处理相等情况。
        • 【强制】泛型集合使用时,在JDK7及以上,使用diamond语法或全省略。
        • 【推荐】集合初始化时,指定集合初始值大小。
        • 【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。
        • 【推荐】高度注意Map类集合的K/V能不能存储null值的情况。
        • 【参考】避免集合的无序性和不稳定性带来的负面影响。
        • 【参考】利用Set元素唯一的特性,可以快速对另一个集合进行去重操作。
      • 并发处理
        • 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
        • 【强制】创建线程或线程池时指定有意义的线程名称,以方便追查问题。
        • 【强制】线程资源必须通过线程池提供,不允许显式创建线程。
        • 【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式。
        • 【强制】SimpleDateFormat是线程不安全的类,一般不要定义为static;如果定义为static,必须加锁,或者使用DateUtils工具类。
        • 【强制】必须回收自定义的ThreadLocal变量。
        • 【强制】高并发时,同步调用应该去考量锁的性能损耗。
        • 【强制】对多个资源、数据库表、对象同时加锁,需要保持一致的加锁顺序,否则可能会造成死锁。
        • 【强制】在使用阻塞等待获取锁的方式中,在加锁方法后紧跟try代码块,并在finally中解锁。
        • 【强制】在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。解锁方式同阻塞等待方式。
        • 【强制】并发修改同一记录时,为避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据
        • 【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中一个任务没有捕获抛出的异常,其他任务便会自动终止运行。推荐改为使用 ScheduledExecutorService 方式。
        • 【推荐】资金相关的金融敏感信息,使用悲观锁策略。
        • 【推荐】使用CountDownLatch后,子线程退出前必须调用countDown方法。
        • 【推荐】避免Random实例被多线程使用,JDK7之后可以使用ThreadLocalRandom。
        • 【推荐】通过双重检查锁实现延迟初始化,存在优化问题隐患。
        • 【参考】volatile解决多线程内存不可见问题。可用于一写多读来解决变量同步问题,不可用于多写。
        • 【参考】HashMap是线程不安全的;在容量不够进行resize时可能出现读写死循环,导致CPU飙升。
        • 【参考】ThreadLocal对象使用static修饰,它无法解决共享对象的更新问题。
      • 前后端规范
        • 【强制】前后端交互的API,需要明确:协议、域名、路径、请求方法、请求内容、状态码、响应体。
        • 【强制】前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。
        • 【强制】服务端发生错误时,返回给前端的响应信息必须包含:HTTP状态码、errorCode、errorMessage、用户提示信息。
        • 【强制】在前后端交互的JSON格式数据中,key必须为lowerCamelCase风格。
        • 【强制】errorMessage用于错误定位,可以在前端输出在type="hidden"的文本类控件中,或者用户端的日志中;注意不要包含敏感信息。
        • 【强制】对于需要使用超大整数的场景,服务端一律使用String字符串类型返回,禁止使用Long类型。
        • 【强制】HTTP请求通过URL传递参数时,不能超过2KB。
        • 【强制】HTTP请求通过body传递内容时,必须控制长度,否则超长会导致后端解析出错。
        • 【强制】在翻页场景中,用户没有输入参数或输入小于1的参数,则前端发送第一页参数给后端;后端发现用户输入的参数大于最后一页,则直接返回最后一页。
        • 【强制】服务器内部重定向必须使用forward;外部重定向地址必须使用redirect方式。
        • 【推荐】服务器返回信息必须被标记是否可以缓存。
        • 【推荐】服务端返回的数据,使用JSON格式而非XML。
        • 【推荐】前后端的时间格式统一为"yyyy-MM-dd HH:mm:ss",统一为GMT。
        • 【参考】在接口路径中不要加入版本号,版本控制在HTTP头信息中体现,有利于向前兼容。
      • 其他
        • 【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
        • 【强制】避免用Apache BeanUtils进行属性的copy,而是用Spring BeanUtils等。
        • 【强制】velocity调用POJO类的属性时,直接使用属性名取值即可,模板引擎会自动按照规范调用其对应的getter/setter方法。
        • 【强制】后端输送给页面的变量必须加 $!{var} 中间的感叹号。
        • 【强制】注意 Math.random() 返回的是0<=x<1的double类型,可能有除零异常。
        • 【强制】如果需要整数类型的随机数,不要使用 Math.random() 去乘以10的次数,而是直接使用Random对象的 nextInt() 或者 nextLong() 。
        • 【推荐】不要在视图模板中加入任何复杂的逻辑运算。
        • 【推荐】及时清理不再使用的代码段或配置信息。
        • 【参考】避免出现重复的代码,即DRY(Don't Repeat Yourself)原则。
    • 日志规范
      • 错误码
        • 【强制】错误码的制定原则:快速溯源、沟通标准化。
        • 【强制】错误码不应体现版本号和错误等级信息。
        • 【强制】全部正常,但不得不填充错误码时返回5个0:00000。
        • 【强制】错误码为字符串类型,共5位,分为2个部分:1位标识错误产生来源 + 4位数字编号标识详细分类原因。
        • 【强制】错误码不能直接输出给用户作为提示信息使用。
        • 【推荐】错误码之外的业务独特信息由错误信息errorMessage来承载;错误码本身不涵盖具体业务信息。
        • 【推荐】在获取第三方服务错误码时,向上抛出时应该做转义,例如C0300转B0200,且在错误信息中带上原有的第三方错误码。
      • 日志
        • 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架(SLF4J、JCL)中的API。
        • 【强制】日志文件推荐至少保存15天;对于当天日志,以 {logname}.log 保存,过往日志以 {logname}.log.{yyyy-MM-dd} 保存。
        • 【强制】根据国家法律,网络运行状态、网络安全事件、个人敏感信息操作等相关记录,留存的日志不少于6个月,并且进行网络多机备份。
        • 【强制】应用日志命名推荐 {应用名}\_{类型}\_{日志描述}.log 的格式。
        • 【强制】在日志输出时,字符串变量之间的拼接使用{}占位符方式。
        • 【强制】对于 trace / debug / info 级别的日志输出,必须进行日志级别的开关判断。
        • 【强制】配置logback的AsyncAppender的时候,\<appender>标签的name属性值和\<appender-ref>标签的ref属性值不能相同。否则会触发循环引用和日志任务队列堵塞。
        • 【强制】避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中为\<logger>标签设置additivity=false。
        • 【强制】生产环境禁止使用 System.out/err 输出日志,禁止使用 e.printStackTrace() 打印异常堆栈。
        • 【强制】异常信息应该包括2类信息:案发现场信息和异常堆栈信息。
        • 【强制】日志打印时禁止直接用JSON工具将对象转换成String。
        • 【推荐】可以使用warn日志级别来记录用户输入参数错误的情况,便于追溯。
        • 【推荐】生产环境禁止输出debug日志;有选择地输出info日志。
        • 【强制】海外部署的服务器由于字符集问题,需要使用全英文的日志。
    • 单元测试
        • 【强制】好的单元测试必须遵守AIR原则。
        • 【强制】自动化:单元测试应该使用assert来验证,而非交互式的打印信息来人肉验证。
        • 【强制】独立性:单元测试用例之间不能相互调用或者依赖执行的先后次序。
        • 【强制】可重复:可以重复执行,不能受到外界环境的影响。
        • 【强制】要保证测试粒度足够小,一般是方法级别,有助于精确定位问题。
        • 【强制】核心业务、核心应用、核心模块的增量代码确保单元测试通过。
        • 【强制】单元测试代码必须写在测试代码目录:src/test/java,不允许写在业务代码目录下。
        • 【推荐】单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%。
        • 【推荐】编写单元测试遵守BCDE原则,以保证交付质量。
        • 【推荐】和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。
        • 【推荐】对于不可测的代码在适当时机做必要的重构,使代码变得可测。
        • 【推荐】在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例。
        • 【推荐】单元测试作为一种质量保证手段,建议在项目提测前完成,不建议项目发布后再来补充。
        • 【参考】单元测试常见误解:
    • 安全规范
        • 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。
        • 【强制】用户敏感数据禁止直接展示,需要进行脱敏。
        • 【强制】用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定,以防止SQL注入;禁止字符串拼接SQL访问数据库。
        • 【强制】用户请求传入的任何参数必须做有效性验证。
        • 【强制】禁止向HTML页面输出未经安全过滤或未正确转义的用户原始数据。
        • 【强制】表单、AJAX提交必须执行CSRF安全验证。
        • 【强制】外部重定向传入的目标地址必须执行白名单过滤。
        • 【强制】Web应用必须正确配置Robots文件,非SEO URL必须配置为禁止爬虫访问。
        • 【强制】在使用平台资源,如短信、邮件、电话、下单、支付,必须实现正确的防重放的机制,如数量限制、疲劳度限制、验证码校验,从而避免被滥刷而导致资损。
        • 【推荐】发帖、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过滤等风控策略。
    • MySQL规范
      • 建表规范
        • 【强制】表名、字段名必须使用小写字母或数字,并使用下划线分割;禁止数字开头,禁止2个下划线中间只有数字。
        • 【强制】表名不使用复数名词。
        • 【强制】禁用保留字来命名表名、字段名,如desc、range、match、delayed等。
        • 【强制】表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)。
        • 【强制】唯一索引名为uk\_字段名1\_字段名2;普通索引名则为idx\_字段名1\_字段名2。
        • 【强制】小数类型为decimal,禁止使用float和double。
        • 【强制】如果存储的字符串长度几乎相等,则使用char定长字符串类型。
        • 【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过5000;如果长度超过5000,则定义字段类型为text,独立出来一张表,用主键来对应,避免影响其他字段索引效率。
        • 【强制】表必备三字段:id,create_time,update_time。
        • 【推荐】表的命名最好遵循“业务名称_表的作用”.
        • 【推荐】库名与应用名尽量一致。
        • 【推荐】如果修改字段含义或者对字段的状态值进行追加时,需要即时更新注释。
        • 【推荐】字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况。
        • 【推荐】单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。
        • 【推荐】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
      • 索引规范
        • 【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
        • 【强制】超过3个表禁止join;需要join的字段,数据类型保持绝对一致;多表关联查询时,保证被关联的字段有索引。
        • 【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,而是要根据实际文本区分度来决定索引长度。
        • 【强制】页面搜索禁止左模糊或者全模糊,如果需要则要使用搜索引擎来解决。
        • 【推荐】如果有order by的场景,注意利用索引的有序性。
        • 【推荐】利用覆盖索引来进行查询操作,来避免回表操作。
        • 【推荐】利用延迟关联或者子查询优化超多分页场景。
        • 【推荐】SQL性能优化目标:至少要达到range级别,要求是ref级别,如果可以是const最好。
        • 【推荐】建组合索引的时候,区分度最高的在最左边。
        • 【推荐】存在非等号和等号混合判断条件时,在建组合索引时,要把等号条件的列前置。
        • 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。
      • SQL规范
        • 【强制】不要使用count(列名)或count(常量)来替代count(*)。
        • 【强制】count(distinct col)计算该列除NULL之外的不重复数量。注意count(distinct col1,col2)如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
        • 【强制】当某一列的值全是NULL时,count(col)的返回结果为0;但sum(col)的返回结果为NULL,需要注意NPE问题。
        • 【强制】使用ISNULL()来判断是否为NULL值。
        • 【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名或表名进行限定。
        • 【强制】在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
        • 【强制】不得使用外键与级联更新,一切外键概念必须在应用层解决。
        • 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
        • 【强制】在线上执行数据更新前,要先select,确认无误才能执行数据更新。
        • 【推荐】SQL语句中表的别名前加as,并以t1、t2、t3...的顺序依次命名。
        • 【推荐】in操作能避免就避免;否则,需要评估in的集合数量,控制在1000个以内。
        • 【参考】存储采用utf8字符集,字符计数方法要注意length()得到的是存储长度不是汉字个数。
        • 【参考】在MySQL5.0及以上版本,varchar(20)表示可以存20个字符/汉字。
        • 【参考】需要存储表情,选择utf8mb4进行存储。
        • 【参考】不建议使用truncate语句。
      • ORM规范
        • 【强制】在表查询中,禁止使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
        • 【强制】POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。
        • 【强制】不要在上层也使用DO,即使字段完全一样,也要重新定义DTO、VO等。
        • 【强制】sql.xml配置中参数注意:#{},#param#;但不要使用${},可以出现SQL注入。
        • 【强制】iBatis自带的queryForList(String statementName, int start, int size)不推荐使用。
        • 【强制】不允许直接拿HashMap与HashTable作为查询结果集的输出。
        • 【强制】更新数据表记录时,必须同时更新记录的update_time为当前时间。
        • 【推荐】更新接口不要更新无改动的字段。
        • 【参考】@Transactional事务不要滥用,会影响性能。
    • 工程规范
      • 应用分层
        • 【推荐】从上至下建议的层级如下:
        • 【推荐】分层异常处理规范如下:
        • 【推荐】分层领域模型规范如下:
      • 二方库规范
        • 【强制】GAV的规则:
        • 【强制】二方库版本号命名方式:主版本号.次版本号.修订号;起始版本号为1.0.0。
        • 【强制】定制包命名方式:主版本号.次版本号.修订号-英文说明[序号]
        • 【强制】线上应用不允许依赖SNAPSHOT版本包。
        • 【强制】正式发布的二方库不允许版本号覆盖升级。
        • 【强制】二方库的新增或升级,保持除功能点之外的其他Jar包版本仲裁结果不变。
        • 【强制】二方库里可以定义枚举类型,参数可以使用枚举类型;但是接口返回值不允许使用枚举类型或者包含枚举类型的POJO对象。
        • 【强制】依赖于一个二方库群/三方库群时,必须定义一个统一的版本变量,避免版本号不一致。
        • 【强制】禁止在多个子项目的pom依赖中对同一个 GroupId/ArtifactId 出现不同Version。
        • 【推荐】工具类在二方库/三方库已经提供的,不要在本应用中编程实现。
        • 【推荐】pom文件中的所有依赖声明放在dependencies语句块中,所有版本仲裁放在dependencyManagement语句块中。
        • 【推荐】二方库不要有配置项。
        • 【参考】二方库发布遵循的原则如下:
      • 中间件规范
        • 【强制】任何操作,都是先保存数据库成功后,再进行缓存的新增、更新、删除操作。
        • 【强制】RPC调用必须有超时设置。
        • 【推荐】webx配置中的.do写法表示ajax异步接口,默认使用该写法即可。
        • 【推荐】了解每个服务大致的平均耗时,通过独立线程池配置,将较慢的服务与主线程池隔离开,防止各个服务线程同归于尽。
      • 服务器规范
        • 【推荐】高并发服务器调小TCP协议的time_wait超时时间。
        • 【推荐】调大服务器所支持的最大文件句柄数。
        • 【推荐】给JVM环境参数设置 -XX:+HeapDumpOnOutOfMemoryError 参数,让JVM碰到OOM场景时可以输出dump信息。
        • 【推荐】在线上生产环境,JVM的Xms和Xmx设置一样大小的内存容量,避免在GC后调整堆大小带来的压力。
    • 研发规范
        • 【强制】任何CodeReview(下称CR)至少需要2人参与并通过(不包括自己)。
        • 【强制】CR提交者确保静态代码扫描已经成功地执行,且单元测试用例全部通过后才进行CR。
        • 【强制】在CR过程中,依照评审意见的任何一次改动都必须重新Review。
        • 【强制】一个CR的大小要求:涉及的变更文件数<=10;单个文件的最大变更行数<=300行;不允许超过总行数1000行的变更。
        • 【推荐】千行CR的评论个数超过2个。
        • 【参考】CR关注的点需要聚焦,技术、业务、数据库等在不同场景中倾向性有所区别。
        • 【参考】以CR的方式形成团队代码文化,拉齐业务认知,一起验证设计方案。
        • 【参考】需求交付时长控制在21天以内,即需求分析8天以内,开发交付13天以内。
    • 设计规范
        • 【强制】采用面向失败架构设计来规避任何未知风险。
        • 【强制】存储方案和底层数据结构的设计也需要在设计评审中通过,并沉淀为文档。
        • 【强制】在需求分析阶段,如果与系统交互的User超过一类并且相关的 Use Case 超过5个,使用用例图来表达更加清晰的结构化需求。
        • 【强制】如果某个业务对象的状态超过3个,使用状态图来表达并且明确状态变化的各个触发条件。
        • 【强制】如果系统中某个功能的调用链路上的涉及对象超过3个,使用时序图来表达并且明确各调用环节的输入与输出。
        • 【强制】如果系统中模型类超过5个,并且存在复杂的依赖关系,使用类图来表达并且明确类之间的关系。
        • 【强制】如果系统中超过2个对象之间存在协作关系,并且需要表示复杂的处理流程,使用活动图来表示。
        • 【强制】系统设计时要准确识别出弱依赖,并针对性地设计降级和应急预案,务必保证核心系统正常可用。
        • 【推荐】核心系统发布上线时,确保“三可”:可灰度、可回滚、可监控。
        • 【推荐】系统架构设计时明确以下目标:
        • 【推荐】需求分析与系统设计在考虑主干功能的同时,需要充分评估异常流程和业务边界。
        • 【推荐】类在设计与实现时要符合单一原则。
        • 【推荐】谨慎使用继承的方式来进行扩展,优先使用聚合/组合的方式来进行实现。
        • 【推荐】系统设计阶段,根据依赖倒置原则,尽量依赖抽象类与接口,有利于扩展与维护。
        • 【推荐】系统设计阶段,注意对扩展开放,对修改闭合。
        • 【推荐】系统设计阶段,将共性业务或公共行为抽取出来公共模块/配置/类/方法等,避免重复代码情况。
        • 【参考】设计文档的作用是明确需求、理顺逻辑、后期维护、次要目的用于指导编码。
        • 【参考】设计的本质是识别和表达系统难点。
        • 【参考】可扩展性的本质是找到系统的变化点,并隔离变化点。
        • 【参考】敏捷开发不等于没有设计和文档沉淀。
        • 【参考】代码即文档的观点是错误的,清晰的代码只是文档的某个片断,而不是全部。
        • 【参考】在做无障碍产品设计时,需要考虑到:
    • 附录
      • 一、名词参考
      • 二、一级和二级错误码

前言

最近更新时间

2022.09

参考

部分未尽详情参考《阿里巴巴Java开发手册V1.6(泰山版)》:https://download.csdn/download/zhiyuan411/12602917

另有著书《阿里巴巴Java开发手册》,《码出高效:Java开发手册》,可自行百度电子版。

规范说明

编程规范的存在意义:

  • 标准统一,提升沟通效率和研发效能。
  • 防患未然,提升质量意识和系统可维护性,降低故障率。
  • 工匠精神,追求极致的卓越精神,打磨精品代码。

规范分为三个级别:

  • 【强制】必须遵守。是不得不遵守的规定,违反本规定或将引起严重的后果。
  • 【推荐】尽量遵守。长期遵守这样的规定,有助于系统稳定性和合作效率的提升。
  • 【参考】充分理解。技术意识的引导,是个人学习、团队沟通、项目合作的方向。

IDE插件

本文标签: Java