转载请注明原创出处,谢谢!
缘由
阿里JAVA开发手册已经发表有很长时间了,值得认真研究思考推广
阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的哲学,值得好好阅读。
可谓包罗万象,几乎日常Java开发中方方面面都有所涉及。
每一条都是前人踩过的坑,通过血的教训总结出来的。
能公布出来真是造福全部Java开发者。
开发手册详细列举如何开发更加高效,更加容错,更加有协作性,力求知其然,更知其不然,结合正反例,提高代码质量。比如,异常日志处理时的各种不规范行为;集合转换的各种坑;创建线程池出现的等待队列OOM等。
的确阿里JAVA开发手册值得我们好好阅读和思考,每一条都是前人踩过的坑,通过血的教训总结出来的。所以今天就其中一点自己的思考理解进行分享。
看完这条,个人觉得主要是圈复杂度,由于代码是人写的,并且需要人来进行维护,如果足够的复杂的话,那么编写出现错误的可能性都很大,并且维护理解起来难度也非常高,以及后期如果需要扩展本来就很复杂再加一个很简单的功能都变得很困难(相信大家一定都有这样的经历)。
圈复杂度
圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准。
在软件测试的概念里,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为独立线性路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。
看看上面阿里JAVA开发手册里面提到的,如果非得使用if()...else if()...else...方式表达逻辑,【强制】避免后续代码维护困难,请匆超过3层。如果超过3层的if-else的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现。
其实在我看来,使用卫语句、策略模式、状态模式就是来降低圈复杂度,让代码更加简单,这样不管是编写代码人员以及维护人员都可以非常方便了解到本质意思。
虽然阿里JAVA开发手册提到的是if()...else if()...else...方式表达逻辑,延伸下,关于多次嵌套循环等道理也一样,需要考虑优化的。
思路分析
如上图,其实看起来就是一颗树结构,相对来说其实比较复杂了,优化的思路其实就是把树结构变成顺序结构即可,那样条理就清晰了,总体思路是这样的,下面看看使用卫语句、策略模式、状态模式怎么达到的。
卫语句
卫语句?卫语句就是把复杂的条件表达式拆分成多个条件表达式,比如一个很复杂的表达式,嵌套了好几层的if - then-else语句,转换为多个if语句,实现它的逻辑,这多条的if语句就是卫语句。
其中卫语句示例如下:
public void today() {
if (isBusy()) {
System.out.println("change time.");
return;
}
if (isFree()) {
System.out.println("go to travel.");
return;
}
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
return;
}
其实这个比较简单,每一个if对应叶子节点的一条路径(每个if基本就return了)。
策略模式
概述:使用这个模式来将一组算法封装成一系列对象。通过传递这些对象可以灵活的改变程序的功能。
策略模式比较有名的就是诸葛亮的三个锦囊妙计说起,如图:
诸葛亮为什么要这么麻烦,做三个锦囊?他完全可以只做一个锦囊,将这三个妙计都写在它上面。可他没有这么做,而是正确的运用了策略模式做了三个锦囊。这样做的好处十分明显:诸葛亮一个锦囊写一个妙计,他的思路十分清晰,不会三个计策相互混乱。而赵云看妙计的时候也十分方便,什么时候看哪个妙计,使用十分方便,如果三个妙计混在一起,他就没这么方便了。
在JDK中java.util.Comparator#compare()就是使用的策略模式,比如我们经常对商品进行排序,条件有很多啊,按照商品浏览量、价格、更新时间、【价格、时间】、【浏览量、更新时间】(进行升序、降序操作)其实这个也是上面那颗树,需要做的就是每次取其中一条叶子节点。很多时候这些判断都是写在一个公用的方法里面,进行大量的判断之后写排序,而JDK怎么做的呢?把变化的比较判断拿出来,其实判断树中每个叶子结点就是一种策略,想象我们平时怎么做的呢? 都是把Comparator#compare()写好(可能有很多实现Comparator接口的排序算法)每次我们调用的时候选择其中一种即可。
与卫语句不同的是,卫语句把每一个if对应叶子节点的一条路径。而策略模式是所以叶子都在实现Comparator接口了,具体开始用那个是调用的直接用(所以不会像卫语句那样看见很多if了)
状态模式
概述:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。主要解决的是对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
- 封装了转换规则。
- 枚举可能的状态,在枚举状态之前需要确定状态种类。
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
由于状态模式是封装了转换规则,所以一般树的深度最少需要2层以及上,个人理解的感觉就是一个流程了,比如*水低于0度是冰的状态--> 大于0度又变成液态--> 100度又变成沸腾的状态
状态模式与策略模式很像,策略模式是外驱动,而状态模式是内驱动。本质也是把判断树里面只取其中一条叶子的路径。
状态模式有一个明显的缺点:状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
程序员笑话
老婆给当程序员的老公打电话:下班顺路买十个包子,如果看到卖西瓜的,买一个。当晚老公手捧一个包子进了家门…老婆怒道:你怎么只买一个包子?!老公甚恐,喃喃道:因为我真看到卖西瓜的了。”
如果使用策略模式就简单了,2条信息,1:买十个包子。2:买一个西瓜,没有就算了。
虽然是个笑话,但是顺序的就是比判断的要简单。
总结
- 圈复杂度概念
- 卫语句
- 策略模式
- 状态模式
汇总:本质就是把较深的判断树,使用的时候,就是把判断树结构变成顺序结构即可,就是给出每个叶子的路径而不需要看起来是一颗复杂的树结构。
思考
这是阿里JAVA开发手册其中一条明细,为什么呢,结果是啥,怎么出乎意料啦??期待你的留言和分析!!!
上面的一些分析都是个人自己的理解和思考,如果发现有不对的希望留言指出,谢谢!!!
如果读完觉得有收获的话,欢迎点赞加关注。
个人公众号
阿里JAVA开发手册零度的思考理解(一)的更多相关文章
-
阿里JAVA开发手册零度的思考理解(二)
转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...
-
阅读阿里Java开发手册记录
概述 在阅读完阿里Java开发手册(嵩山版)后,发现自己在开发过程中有一些没有按照规范开发的情况,这里将容易忘记的规范记录下来,并且添加自己的理解,一方面方便自己巩固记忆,另一方面希望对其他同学能够提 ...
-
品阿里 Java 开发手册有感
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图, ...
-
JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法
前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学 ...
-
阿里java开发手册中命名规约解读之DO/BO/DTO/VO/AO
前言 在阅读<阿里巴巴Java开发手册>时,看到命名规则中有这样一条 虽然知道这些是根据Java对象的角色所分配名称的后缀,但是没有弄清楚分别是什么意思,日常开发中也没有使用到. 网上查找 ...
-
读《阿里Java开发手册》总结(1)
一·命名约定 类名使用大驼峰式命名(领域模式相关命名除外:如DAO\VO\DO等). 常量必须全部大写,单词中间用“_”隔开(如MAX_COUNT). 抽象类命名使用Abstract或Base开头.异 ...
-
从阿里Java开发手册学习线程池的正确创建方法
前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更 ...
-
【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法
jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口 |–Execut ...
-
阿里Java开发手册1.3.0 文字版
版本: 1.3.0 update: 2017.9.25 一.编程规约 (一) 命名风格 1. [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:_name _na ...
随机推荐
-
鼠标划过用户名时在鼠标右下角显示div展示用户资料
最近做一个网站论坛,为了方便会员之间相互了解,又不想再做一个页面展示用户资料,就想到了鼠标划过用户名时在鼠标右下角显示div展示用户资料这个效果, 这里要注意的该方法不是给每个用户名的旁边都绑定一个d ...
-
checkbox check all or ancheck all
<script type="text/javascript" src="js/jQuery.1.8.3.min.js"></script> ...
-
SVG简介
最近遇到SVG这个名词,于是查阅资料,做个笔记. 前言 图片的数字化.将图片存储为数据有两种方案. 位图.也被称为光栅图.即是以自然的光学的眼光将图片看成在平面上密集排布的点的集合.每个点发出的光有独 ...
-
input实时监听(input oninput propertychange onpropertychange)
本文实例讲述了js与jquery实时监听输入框值的oninput与onpropertychange方法.分享给大家供大家参考.具体如下: 最近做过一个项目,需求是下拉框里自动匹配关键字,具体细节是实时 ...
-
查看源码利器之sublime text 3 配置 Ctags 插件
最近在看源码的时候发现sublime text 3是很给力的一款软件,小巧精致,这里着重讲解一下Ctags协助编译和跟踪函数 一.安装Package Control (如果Preferences &g ...
-
J.U.C并发框架
转载:http://itindex.net/detail/48869-j.u.c-%E6%A1%86%E6%9E%B6 J.U.C并发框架 作者:Doug Lea SUNY Oswego Oswego ...
-
[cloud][sdn] network namespace
man 手册关于IP netns的介绍: http://man7.org/linux/man-pages/man8/ip-netns.8.html 一个非常好的介绍,有概念,有操作: http://c ...
-
从网易云音乐网页版无登陆下载MP3的办法
用chrome浏览器就能办到 现在,你还为下载不到满意的音乐而苦恼吗?
-
iOS开发中的压缩以及解压
事实上,在iOS开发中,压缩与解压,我都是采用第三方框架SSZipArchive实现的 gitHub地址: https://github.com/ZipArchive/ZipArchive 上面有 ...
-
关于RSA、公钥、私钥、加密、签名的那些概念
前言 作为一名程序员,经常会听到加密解密之类的词.而非对称加密技术,应用的非常广泛.本文不写加密技术的原理,只是希望以一个简单的类比,让大家了解非对称加密中常见词的概念,以及它的作用. 介绍 在RSA ...