阿里巴巴Java开发规范学习——编程规约(1)

2024-04-10 20:36

本文主要是介绍阿里巴巴Java开发规范学习——编程规约(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阿里巴巴Java开发规范

一、编程规约

(一) 命名风格

1.【强制】类名使用UpperCamelCase 风格,但以下情形例外:DO / BO / DTO / VO / AO /

PO / UID 等。
正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

  1. DO (Data Object):用于表示领域模型中的数据对象,通常包含业务相关的属性和行为。例如,CustomerDO, ProductDO
  2. BO (Business Object):用于封装业务逻辑和规则的类,可能包含对多个DO的操作。例如,OrderBO, InvoiceBO
  3. DTO (Data Transfer Object):主要用于在不同层(如表现层与业务层、服务层之间)传递数据的简单对象,只包含数据成员及简单的getter/setter方法。例如,UserDTO, AddressDTO
  4. VO (Value Object):在领域驱动设计(DDD)中,用于表示一个不变的、具有语义概念的对象,其属性值共同定义了对象的完整状态,如 ColorVO, MoneyVO
  5. AO (Application Object):在某些架构中,用于表示应用程序层的实体,负责协调业务逻辑和数据访问。例如,UserAO, RoleAO
  6. PO (Plain Old Object):通常指那些没有继承任何特殊框架或库提供的基类、未实现特定接口、未被注解标记、不含有任何门面方法(如getter/setter以外的方法)的简单对象。例如,CustomerPO, ItemPO
  7. UID (Unique Identifier):用于表示唯一标识符的类或接口,如全局唯一ID生成器 UUIDGenerator 或特定类型ID的类 UserId, OrderId
2. 【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

正例:MAX_FILE_SIZE
反例:maxFileSize

3. 【强制】抽象类命名使用 Abstract 或Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
  1. 抽象类命名使用 AbstractBase 开头
    这个规则建议在命名抽象类时,以 AbstractBase 作为前缀,以明确表示此类是一个抽象类,即不能被实例化,主要用于定义通用行为和接口,供子类继承实现。这样命名有助于开发者一眼识别出这是一个抽象类,了解其设计意图和用途。例如:AbstractAnimalBaseUserService

  2. 异常类命名使用 Exception 结尾
    异常类通常用于表示程序运行过程中遇到的错误情况。遵循这一规则,将 Exception 作为后缀添加到异常类名中,可以清晰地标识出此类是一个异常类,便于理解和管理程序中的错误处理逻辑。例如:InvalidInputExceptionResourceNotFoundException

抽象类中,可以以 Abstract 结尾吗?

虽然在技术层面上,以 Abstract 结尾命名抽象类并不违反任何编程语言的语法规定,但在实践中,以 AbstractBase 作为前缀已经是一种广泛接受且易于理解的抽象类命名约定。将 Abstract 放在类名末尾可能会导致以下问题:

  • 可读性降低:阅读代码时,开发人员习惯于从左到右扫描类名,将表示类性质的关键字放在开头有助于快速识别。将 Abstract 放在末尾可能需要额外的时间和注意力去判断类的性质。
  • 一致性受损:大部分编程社区和项目倾向于遵循将 AbstractBase 放在抽象类名开头的约定。若您的项目中出现以 Abstract 结尾的抽象类,可能会与团队内的其他代码或业界普遍做法产生不一致,增加理解成本。

综上所述,尽管没有严格禁止以 Abstract 结尾命名抽象类,但从可读性、一致性以及遵循最佳实践的角度考虑,建议遵循将 AbstractBase 放在抽象类名开头的命名规则。

4. 【强制】 POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。

反例:定义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

正例: 避免使用 is 前缀命名布尔类型的变量
直接使用描述状态的词汇作为变量名,如 deletedenabledvisible 等。相应的 getter 方法可以保持 JavaBean 规范,即对于布尔类型使用 is 前缀(如 isDeleted()),但对于属性名本身,则不带 is

问题背景:

在 Java 中,布尔类型的变量通常用来表示某种状态或属性的真假值。按照习惯,对于表示“是否具有某特性”的布尔变量,有时会采用 is 前缀来命名,如 isDeletedisEnabledisVisible 等。这种命名方式符合自然语言习惯,能够直观地传达变量的意义。

然而,在涉及序列化和反序列化的场景中,特别是与某些框架(如 RPC 框架、ORM 框架等)交互时,这种命名可能会导致问题。这是因为部分框架在自动处理对象的序列化和反序列化时,依赖于特定的命名约定来正确映射对象属性到外部格式(如 JSON、XML 或数据库字段)。

问题原因:

  1. JavaBean 规范与框架预期的差异
    JavaBean 规范规定,布尔类型的 getter 方法可以使用 is 前缀(如 isDeleted()),而其他类型的属性则使用 get 前缀(如 getName())。当框架尝试根据 getter 方法名反推属性名(去掉 isget 并将首字母小写)时,如果遇到以 is 开头的方法,可能会误以为对应的属性名为 deleted 而不是 isDeleted。这会导致框架在反序列化时找不到实际存在的 isDeleted 属性,从而引发错误。

  2. 外部格式映射规则
    在某些框架中,可能直接基于属性名进行序列化或反序列化。如果外部格式(如 JSON)要求属性名遵循特定的命名约定(如全小写、下划线分隔等),那么带有 is 缀的属性名在转换时可能会与预期不符,导致映射失败或错误。

5. 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。

正例:应用工具类包名为 com.alibaba.ai.util、类名为MessageUtils (此规则参考spring
的框架结构)

6. 【推荐】如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。

说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:

  • public class OrderFactory;
  • public class LoginProxy;
  • public class ResourceObserver;
7. 【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加)

保持代码的简洁性,并加上有效的Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。
正例:

  • 接口方法签名 void commit();
  • 接口基础常量 String COMPANY = “alibaba”;
8. 接口和实现类命名的两套规则:

1)【强制】对于 Service 和DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部
的实现类用Impl 的后缀与接口区别。
正例:CacheServiceImpl 实现CacheService 接口。
2) 【推荐】 如果是形容能力的接口名称,取对应的形容词为接口名 (通常是–able 的形式)。
正例:AbstractTranslator 实现 Translatable 接口。

9. 【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。

说明:枚举其实就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。
正例:枚举名字为ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

10 .【参考】各层命名规约:

A) Service/DAO 层方法命名规约

1) 获取单个对象的方法用 get 做前缀。
2) 获取多个对象的方法用 list 做前缀,复数形式结尾如:listObjects。
3) 获取统计值的方法用 count 做前缀。
4) 插入的方法用save/insert 做前缀。
5) 删除的方法用remove/delete 做前缀。
6) 修改的方法用update 做前缀。
B) 领域模型命名规约
1) 数据对象:xxxDO,xxx 即为数据表名。
2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
3) 展示对象:xxxVO,xxx 一般为网页名称。
4) POJO 是DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

(二) 常量定义

1. 【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。

反例:

String key ="Id#taobao_" + tradeId;
cache.put(key, value);
2. 【强制】在long 或者Long 赋值时,数值后使用大写的L,不能是小写的 l,小写容易跟数字1 混淆,造成误解。

说明:Long a = 2l; 写的是数字的21,还是 Long 型的2?

3. 【推荐】不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。

说明: 大而全的常量类, 杂乱无章, 使用查找功能才能定位到修改的常量,不利于理解和维护。
正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下

4. 【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。

1) 跨应用共享常量:放置在二方库中,通常是 client.jar 中的constant 目录下。
2) 应用内共享常量:放置在一方库中,通常是子模块中的constant 目录下。
反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义了表示“是”的变量:
类A 中:public static final String YES = “yes”
类B 中:public static final String YES = “y”;
A.YES.equals(B.YES),预期是true,但实际返回为false,导致线上问题。
3) 子工程内部共享常量:即在当前子工程的 constant 目录下。
4) 包内共享常量:即在当前包下单独的 constant 目录下。
5) 类内共享常量:直接在类内部 private static final 定义。

5. 【推荐】如果变量值仅在一个固定范围内变化用 enum 类型来定义。

枚举(Enum)类型的概念与特性:

enum(枚举)是一种特殊的类型,它允许定义一组命名的常量,这些常量通常是相互独立且互斥的。枚举类型在很多编程语言中都有支持,如 Java、C#、Python(通过枚举模块实现)等。枚举类型的优点包括:

  • 类型安全:枚举类型的变量只能被赋予其定义范围内预设的值,不允许赋值为其他未定义的值,增强了代码的健壮性和安全性。
  • 可读性强:枚举成员以具名常量的形式存在,使用有意义的名称代替原始值(如整数或字符串),提高了代码的可读性和自文档化能力。
  • 易于维护:当枚举成员有所增减或值发生变化时,只需修改枚举定义一处,所有引用该枚举的地方都会自动更新,降低了维护成本。

何时使用枚举来定义变量值范围:

当变量的取值仅在一个固定的、有限的范围内变化,并且这些值具有特定的语义时,非常适合使用枚举类型来定义。以下是一些典型的应用场景:

  1. 状态标识
    例如,订单的状态可能只有几个固定选项:PENDING(待处理)、PROCESSING(处理中)、COMPLETED(已完成)、CANCELLED(已取消)等。使用枚举可以清晰地表示这些状态,并确保状态值不会被错误地设置为无效值。
public enum OrderStatus {PENDING,PROCESSING,COMPLETED,CANCELLED
}
  1. 星期、月份等预定义集合
    例如,表示一周中的星期或一年中的月份,这类值都是固定的且具有明确语义。使用枚举可以使代码更具可读性,并防止拼写错误或使用非法值。
public enum DayOfWeek {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}public enum Month {JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER
}
  1. 方向、颜色、角色类型等具有固定选项的分类
    例如,表示二维平面上的方向(NORTH, SOUTH, EAST, WEST),用户角色类型(ADMIN, MODERATOR, USER),或者颜色(RED, GREEN, BLUE 等)。这些情况都可以使用枚举来限制变量的取值范围。
public enum Direction {NORTH,SOUTH,EAST,WEST
}public enum UserRole {ADMIN,MODERATOR,USER
}public enum Color {RED,GREEN,BLUE,// ...
}

总结来说,当变量的取值范围固定且具有明确语义时,使用枚举类型来定义不仅可以提高代码的可读性和安全性,还能简化维护工作。遵循“如果变量值仅在一个固定范围内变化,用 enum 类型来定义”这一规范,有助于提升代码质量,符合良好的编程实践。

这篇关于阿里巴巴Java开发规范学习——编程规约(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/892080

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.