问题

如何评价阿里近期发布的Java编码规范?

回答
最近阿里又推出了新的Java编码规范,这次的更新内容不少,看得出来阿里在推动代码质量这块儿是认真的。咱们就掰开揉碎了聊聊,看看这次的规范有哪些亮点,又有哪些地方值得咱们琢磨琢磨。

一、 整体感受:更精细化,更贴近实战

第一眼看下来,这次的规范感觉比以往更“实在”了。不是那种空泛的“要写好代码”的口号,而是深入到了具体的场景和细节。感觉阿里在实际开发过程中遇到的坑,都给总结进去了。

精细化是关键词: 以前的规范可能更侧重于宏观的结构和风格,这次则在很多地方细化到了具体的函数、变量命名、异常处理、并发场景等。这说明他们在实际项目中,因为这些细节导致的问题尝够了“苦头”,所以要通过规范来避免。
贴近实战,解决痛点: 很多规则的出现,都能让人联想到某个实际项目中遇到的棘手问题。比如对并发场景的规范,对复杂逻辑的拆分要求,这都是在大型项目中经常出现的“老大难”问题。阿里把这些写进规范,其实是在分享他们解决问题的经验。
从“不能做什么”到“应该怎么做”: 虽然依旧包含了很多“禁止”的条款,但这次更多的是给出了“推荐”的做法。这种引导性的语言,更容易被开发者接受和采纳,而不是一味地压制。

二、 具体亮点解析:

咱们来挑几个有代表性的,细致分析一下:

1. 对方法长度的严格限制(例如:方法行数):
为什么重要? 方法太长,意味着这个方法可能做了太多事情,违背了“单一职责原则”。代码可读性差,测试困难,复用性低,BUG率也容易升高。
阿里怎么说? 规范里会对方法体行数有一个建议值(具体数值会根据版本有微调,但核心理念不变)。
我的理解: 这不是一个绝对的“红线”,而是个强烈的信号。如果你的方法快到这个长度了,就该想想:是不是可以拆分了?把不同的逻辑放到不同的私有方法里,主方法只负责调用和协调。这样代码看起来清爽多了,也更容易理解和维护。

2. 对参数数量的限制:
为什么重要? 方法参数太多,调用的时候很容易传错顺序,或者忘记某个参数,导致逻辑错误。而且,参数太多也暗示着这个方法可能需要处理的信息过多,可以考虑用对象来封装参数。
阿里怎么说? 同样是有一个建议的参数数量上限。
我的理解: 参数少于3个通常是比较理想的状态。超过3个,就要警惕了。如果确实需要传递多个值,考虑创建一个专门的DTO(Data Transfer Object)或者POJO(Plain Old Java Object)来承载这些数据,这样既清晰又灵活。

3. 异常处理的规范化(例如:checked exception和runtime exception的使用):
为什么重要? 异常处理是Java中一个比较容易被滥用的地方。随便一个`catch(Exception e)`然后啥也不干,或者直接打印堆栈然后继续执行,都可能隐藏着非常严重的bug。
阿里怎么说? 会区分checked exception和runtime exception的使用场景,强调不要随意捕获所有异常,以及如何正确地处理异常(比如记录日志、回滚事务等)。
我的理解: checked exception适合那些程序能够预见并能处理的异常(比如文件不存在),而runtime exception则适合程序本身的错误(比如空指针)。更重要的是,要根据业务场景选择合适的异常处理方式。捕获异常后,至少要记录下来,让使用者知道发生了什么。对于那些真的不应该发生的情况,直接抛出去让调用者去处理,或者让程序终止,也比假装没事更负责任。

4. 并发编程的细节(例如:线程安全、锁的使用):
为什么重要? 并发是Java开发中最容易出错的领域之一,各种竞态条件、死锁问题层出不穷,而且非常难以调试。
阿里怎么说? 针对并发场景,会给出非常具体的建议,比如在并发场景下,尽量使用不可变对象,使用线程安全的集合类(如`ConcurrentHashMap`),避免共享变量的非原子性操作,正确使用锁(比如`synchronized`和`Lock`接口的使用场景和注意事项)。
我的理解: 这部分内容是重中之重。很多时候我们以为自己写的是线程安全的,其实不然。规范里对`synchronized`关键字的使用时机和粒度都会有指导,比如不要在代码块或者方法上滥用`synchronized`,尽量缩小锁的范围,只锁住需要保护的资源。另外,对于共享数据,能用原子类(如`AtomicInteger`)就用原子类,能用并发集合类就用并发集合类,自己再造轮子风险很大。

5. 命名规范的细化:
为什么重要? 好的命名能够直接提升代码的可读性,让其他开发者甚至未来的自己更容易理解代码的意图。
阿里怎么说? 不仅仅是变量名、方法名,连类名、接口名、包名都会有更具体的建议,比如使用名词表示类,使用动词表示方法,避免使用缩写,以及使用有意义的、能够表达其含义的词语。
我的理解: 这一点其实是贯穿始终的。比如,一个变量叫`a`,你能知道它是什么吗?但如果叫`userCount`,瞬间就明白了。规范里会强调避免使用过于笼统或单字的命名。对于一些枚举值或者常量,也会有明确的命名风格要求。

6. 关于设计模式的使用建议:
为什么重要? 设计模式是前人总结出来的解决常见问题的经验,合理使用可以提高代码的可维护性、扩展性和复用性。
阿里怎么说? 可能会推荐在特定场景下使用某些设计模式,并给出一些使用上的注意点,避免“过度设计”。
我的理解: 这是一个比较微妙的点。设计模式不是越多越好,也不是越复杂越好。关键在于“合适”。规范会引导开发者在需要的时候使用,而不是为了用而用。比如,在需要策略选择的时候,可以用策略模式;在需要创建复杂对象的时候,可以用建造者模式。

三、 怎么看待这些规范?

1. 这不是“圣经”,是“指南”: 任何规范都不能百分之百适用于所有场景。阿里发布的规范是他们在大量项目实践中总结出来的经验,是优秀的实践案例,但遇到特殊情况,我们仍然需要结合具体业务来判断。不能为了迎合规范而牺牲代码的可读性和实际效果。
2. 提升团队整体水平的利器: 规范的最大价值在于统一团队的代码风格和思维方式。当团队成员都遵循一套规范时,代码的风格会更加一致,沟通成本降低,新人上手也更快。
3. 持续学习和改进的过程: 技术是不断发展的,编程规范也一样。阿里也在不断更新他们的规范,这说明他们也在持续地学习和改进。我们开发者也应该保持学习的态度,关注最新的规范,并反思自己的代码实践。
4. 工具辅助是关键: 好的规范还需要好的工具来支撑。比如IDE的代码检查插件,静态代码分析工具(如SonarQube),这些工具可以帮助我们在提交代码前就发现不符合规范的地方,大大提高效率。

四、 总结:

总的来说,阿里这次发布的Java编码规范是一份非常有价值的参考。它比以往更加精细化,更加贴近实战,解决了很多开发者在日常开发中会遇到的痛点。

如果你是新人: 认真学习这些规范,会让你少走很多弯路,并且从一开始就养成良好的编程习惯。
如果你是有经验的开发者: 也可以从中发现一些自己可能忽略的细节,或者对一些问题的理解更加深入。把它作为一面镜子,反思自己的代码,不断提升。
如果你是团队管理者: 这是推动团队代码质量提升的绝佳工具。将其引入团队,并配合相应的培训和工具支持,能够显著提升团队的开发效率和代码质量。

当然,规范的落地还需要团队的共同努力和持续的实践。但至少,有一份清晰、有指导意义的规范摆在面前,就已经成功了一半。值得点赞!

网友意见

user avatar

很好的东西,98%以上内容可以直接使用。有一些地方个人觉得可以提高一下:

1. 应该写明这个文档是什么许可协议的。比如说在其基础上稍作改动然后分发是否许可?如果没任何许可协议,那有人把其中大括号必须不换行改成必须换行然后用原来的名字免费分发你也拿他没办法吧。

2 “变量"跟“常量”的用法有点混淆

12.【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁 性,并加上有效的 javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量

初看时一头雾水,根本就不可能在接口里定义变量呀,看后面的描述,似乎说的是常量。类似的地方好像还有几处,感觉就是对象域,类静态域(不管是否final),方法的局部变量,都统称变量。当然,这是小节,习惯了就好。只不过一开始看时感觉有点混乱。

3. 作为本质上是“开发规范”的“开发手册”,个人认为一些根本过不了编译的“知识点”就不需要列出来了,有点干扰重点。比如说:

6. 【强制】泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用 add 方法。 说明:苹果装箱后返回一个<? extends Fruit>对象,此对象就不能往里加任何水果,包括苹 果。

这种写法根本过不了编译,个人感觉没必要专门写出来。何况提到了<? extends T>不能.add,为何不提<? super T>不能.get。

4. 关于包名的规则我觉得不能涵盖所有场景

9. 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用 单数形式,但是类名如果有复数含义,类名可以使用复数形式。 正例: 应用工具类包名为 com.alibaba.mpp.util、类名为 MessageUtils(此规则参考 spring 的框架结构)

如果包名的一部分是个词组怎么办?比如说Unit of work。难道写成 com.alibaba.unit.of.work ? 如果刚好又有个叫 com.alibaba.unit的包,那 com.alibaba.unit.of.work就会在com.alibaba.unit下面,虽然它们之间毫无逻辑关系。我记得行业标准是包名用小写加下划线的分割方式,例如 com.alibaba.unit_of_work 。

5. 有一些原因解释没触及痛点(也就是规则我是认同的,但由于原因解释没触及痛点,反而会被一些“独立思考能力强”的同学驳回来)。

比如说:

18.【推荐】final 可提高程序响应效率,声明成 final 的情况: 1) 不需要重新赋值的变量,包括类属性、局部变量。 2) 对象参数前加 final,表示不允许修改引用的指向。 3) 类方法确定不允许被重写。

在现代主流javac和JVM下“final可提高程序响应效率”并不成立。加final更多的是从可读性方面去考虑的。主要的关键在于,如果开发时如果习惯使用IDE的“抽取局部变量”功能来声明局部变量,那么加final根本没有额外工作量,属于“何乐而不为”。而如果程序员的习惯是手打变量声明,那在变量声明处打final就太烦人了,根本不可能推得动。

再比如说:

1. 【强制】不要捕获 Java 类库中定义的继承自 RuntimeException 的运行时异常类,如: IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保 证程序健壮性。 正例:if(obj != null) {...} 反例:try { obj.method() } catch(NullPointerException e){…}

这点实在不能同意更多,问题是痛点不是“健壮性”(这种提法又落入“防御式编程” vs “契约式编程” 的争吵中,谁说try...catch...不健壮的。)事实上对RuntimeException不做规避的最大问题是:

第一,会干扰使用“异常断点”来排错。

第二,导致维护时难以判断开发时的原始意图。比如说,这样一段代码:

       public void setEmployeeBirthday(Long id, Date birthday) {     final Employee employee = loadEmployee(id);     employee.setBirthday(birthday); }      

在setBirthday那行抛了NPE,那么其实有以下几种可能:

1. loadEmployee返回null是一种正常情况,写上面这个方法的程序员忘了处理这种正常情况。

2. loadEmployee在任何时候都不应该返回null。

3. loadEmployee返回null是一种正常情况,但在当前特定的场景下,传入的id不应该令它返回null。

如果写这个方法时,在loadEmployee之前检查了id,我维护时立马就可以判定这是第三种情况。如果在loadEmployee之后使用之前就检查了employee是否null而没有在之前检查id,我立马就可以判定这是第二种或第三种情况。如果所有程序员都严格遵守这个“尽可能检查” 的规则,我发现根本没有检查代码,基本就可以判定写这段程序的程序员完全没想到employee可能是null这种场景(也就是很可能是第一种情况)。

6. 还有一些我能明白作者要传达的意思,但措辞上似乎有点混乱的。比如说

9. 【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使 用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘 撑爆,并记得及时删除这些观察日志说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。纪录日志时请 思考:这些日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?

这是从运维的角度来说的吧?从编程角度来说,打日志还真是越多越好,只要level不乱就行。我在日常工作中是直接把TDD里测试代码的步骤拿过来做trace日志的,在生产环境排错时不知救过多少次命。其实关键问题是,trace log本来就是用来排一些debug都查不出的错的,如果我能在开发时预判这里可能有问题,我就应该打debug level的log了。如果要求程序员在“记录日志时”预判某条日志能不能给排错带来好处,那trace level的log就基本不用打了(明知能给排错带来好处的log当然得打debug level)。

总体来说,这个文档是对初学者非常有用的参考资料,至少有一些平时两种方案摇摆不定的地方(嗯,大括号,说的就是你),你现在可以明确知道其中一种是经过实践验证绝无问题的(不代表另一种会有问题),也能避免不少运行时的坑。以上几点只是结合个人经验的一点点补充意见。

user avatar

本人前阿里员工,这确实就是阿里日常的编码规范,每一条都是前人踩过的坑,通过血的教训总结出来的。

能公布出来真是造福全部Java开发者。

如果你在经历Java项目,尽管拿去用,会少踩很多坑。

如果你开始新项目,请不要使用一种需要32页编码规范才能少踩坑的语言。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有