系列文章说明
阿里巴巴Java开发手册,来自于阿里集团的智慧与经验,用血淋淋的故障换来的总结 阿里经济体全球技术开发准则。
毫不夸张地说,如果完全理解了手册中的条例,你的编程质量,理念,习惯,技巧,和设计能力,将得到一个本质的飞跃。
手册经历了多个版本的迭代,到目前已经相对稳定。其中的规约,标准,建议,给无数的java开发团队提供了指导意见,证明是有效,且实用的。由于原文进行了高度的精炼,对于普通开发者而言,过于简洁,很多地方只有规范,而没有说明具体沉淀出此规范的具体原因,或者不遵守会导致什么问题,也有很多地方没有提供详尽的解决方案,以及进一步该如何做。
针对这点小缺陷,专业人士觉得有必要再把这些规范进行拆解,原因进行分析,后果进行推测,再结合多年的各种业务场景,各种解决方案,来将有些条目进行扩展,提供一些具体可行的处理方式,并将所有这些内容做成一个系列,如果有行业同事,能从从系列文章中获知一二,或者有不同意见,也希望能和专业人士进行探讨。
本系列每篇文章我会做成精读大概需要10-15分钟的阅读量,大概4-5个规约,一般人的注意力集中最大时间,大概能控制再这个范围之类,不要因为学习导致精神力太过耗费。
一、编程规约
(一)命名风格
【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
反例:
_name / __name / $name / name_ / name$ / name__
解释:
有很多开源代码是下划线开头,比如eureka源码中,就有很多这种风格的代码,但我们尽量不要吸收这种风格。
之所有这条规范,是因为其他编程语言,比如python下划线开头是内部变量,$在php中表示变量,__表示内置变量或函数,javascript之前也有将 "_" 作为私有成员的约定成俗的规定,由此看来,此规定是让其他语言转过来的开发者更容易理解。以免不必要的理解负担。
扩展:
- 在合作编程的项目中,理解和沟通是巨大的成本,减少这部分的理解差异,共同建立标准表达,是提升效率的一个重要途径;
- 针对特殊的业务场景,或者应项目里强势架构师要求,可能需要使用特殊符号来重点强调某些变量,在项目开始前,应做好说明文档,统一口径;
【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,纯拼音命名方式更要避免采用。
正例:renminbi / alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。
正例:你们公司奇怪的项目名称,产品名称,无法对应到英文的可以用拼音,大家一致理解就可以。
反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3
解释:
虽然中国在世界上影响力与日俱增,但还是不建议用拼音或中文,中文有同音字,汉字会有编码问题,比如Pingfen:读代码的人可能理解成:评分,平分。
扩展:
- 不要用中文的命名,除开编码问题不表,中文的变量在理解起来不如英文准确直接,举个最简单的列子addressUpdateReqVO一看就知道是干什么的,但是[地址更新请求视图对象]是不是又啰嗦,又不利于理解呢?
【强制】类名使用 UpperCamelCase 风格,但以下情形例外:DO / BO / DTO / VO / AO / PO / UID 等。
正例:JavaServerlessPlatform / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例:javaserverlessplatform / UserDo / XMLService / TCPUDPDeal / TAPromotion
解释:
在读代码时,不管猜词还是拆词都是一件不太好的体验,在c++中通常使用_来分割词组,在特定的情况下,java语言中也不是不能沿用,但是UpperCamelCase 几乎已经是业界标准,建议不要在这方面走个性化路线,留个骂名也不太好。
针对DO / BO / DTO / VO / AO / PO / UID 这些特定场景下使用的后/前缀,很多人习惯只大写第一个字母,一来不符合常规语言语法(英文单词首字母缩写组成的特殊词汇,需要全部大写),二来容易引起理解偏差,比如:DO[Data Object]理解成Do[做/处理]
扩展1:
- DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。一般用在xxxxMapper,xxxxServiceImpl和xxxxManager中;
- DTO( Data Transfer Object):数据传输对象,Service或Manager向外传输的对象;
- BO( Business Object):业务对象。 由Service层输出的封装业务逻辑的对象。和DTO的区别在于BO更贴近上层业务,DTO更贴近底层数据;
- VO( View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。和UI或者API的返回参数有一一对应关系;
- AO (Application Object) :应用对象,在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高;和VO的区别在于AO是针对具体某一个client类型的UI一一对应,VO是通用的返回类型;
- POJO 是 DO / DTO / BO / VO 的统称.
扩展2
通用命名前后缀
- 服务接口定义后缀Service,接口实现定义ServiceImpl;
- 数据访问层定义后缀Mapper或者DAO;
- 控制器层定义后缀Controller;
- 工具类定义后缀Utils;
- DO / BO / DTO / VO / AO / PO之间互相转换的类,定义后缀Converter;
- 请求对象定义ReqVO,返回对象定义RespVO;
- 枚举类型后缀Enum;
- 异常类后缀Exception;
- 配置类后缀Config;
- 静态字段后缀Constants;
- 过程处理后缀Processer;
- 事件处理后缀Handler;
- 需要全局传递的对象[垮多个执行逻辑块]后缀Context;
技巧:
- DO / BO / DTO / VO / AO / PO之间的转换推荐使用MapperStruct来处理,后续作者会出一篇一看就懂的详尽MapperStruct指南。
【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式
正例: localValue / getHttpMessage() / inputUserId
解释:方便理解,统一规范;
扩展1:
- 方法命名统一使用 【动词+名词】 方式,比如getUserInfo,setAddress,updateUserInfo;
- 集合类型的返回值,使用List做后缀,比如getUserList;如果是带分页,使用getUserPageList;如果有查询条件,再加上后缀ByXxx,比如getUserPageListByDepartment,如果有多个查询条件,也可以建议使用queryUserPageList,这种带query前缀的方式;
- 常用的动词前缀do,get,query,delete,update,save,edit,push,pull,load,add,clean,change,make,run,generate,copy,as,to,filter,contain,fire,emit,process,check,validate,has,is,convert;
- 副词放在动词前面,比如:batchDeleteUser,softDeleteAddress
扩展2:
- 常用编程英文发音问题总结https://github.com/shimohq/chinese-programmer-wrong-pronunciation
技巧:
- 针对起止日期,一般我们会使用xxBegin和xxEnd,两个变量来接收前端传过来的参数,专业人士建议使用一个长度为2的Date数组[userCreateDateRange]来存两个日期,分别代表起止,这样做的原因是,大部分的前端框架,选择日期区间的时候,都是返回的一个date数组,这样能减少频繁的转换
【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME 反例:MAX_COUNT / EXPIRED_TIME
解释:
- 针对静态常量,嫌表意不明,不嫌长,这条同样适用于普通变量,类名称,方法名称;
- 有一种代码叫自解释代码,即无需注释的代码,这就要求编程人员对每个类,变量,方法名的命名极其清晰明确,希望大家都以这个标准要求自己,要不了多久就会有人称赞你的代码;
- 很多编程的朋友,由于c++/c带过来的习惯,将变量名称写的很简洁,看起来是好看,但给读代码的人带来很大的负担,遭人唾骂。
技巧:
- 无论在给类名,变量名,方法名,还是数据库表明,字段名,索引名命名时,如果出现可用多个单词命名的情况,一定要选择最简单的那个,意义最少的那个单词,不要选择生僻单词,否则极其容易引发同事的c语言吐槽;
- 针对命名,名词一定放在最后,介词形容词放在前面,比如MAX_STOCK_COUNT而不是STOCK_COUNT_MAX,这样无论是老外还是中国人,都好理解的多;
第一篇暂时就写到这里
如果有什么疑问,意见,或者想法,可以和作者一起探讨