今天的分享来源于工作中的点点滴滴……
01. 习惯性自嘲
代码写久了,伴随肩疼头痛眼近视,于是乎也就成了名副其实的 code farmer(码农),作为如牛吃草挤奶般的码农,吃草(撸)挤奶(码)便是日常要事,接下来就聊聊身边同事的一些关于撸码的问题,顺道穿(掰)插(扯)一下我独到的见解(想想我这脸皮会有多厚)。
02. 撸码的艾尔莎
假想一下,你投资的产品到期了,但是你却没有收到平台给你的转账,面对此种场景,估计你会二话不说,先去看看投资平台的官网还在不在,确认是不是平台跑路啦;然后去找客服投诉......
做过理财相关项目的应该都清楚,赎回是用户最关心的功能,但是赎回过程中往往涉及到很多的状态,例如初始状态、赎回中、赎回结果不明、赎回失败、赎回成功等等,但是不同的状态,所做的业务处理逻辑也不同。
敢问,赎回的这段代码该怎么撸呢?同事艾尔莎撸码实现过程中,可谓是吐槽又吐槽,于是就出现了下面的代码段。
不要小看上面代码段中每一个状态下的输出打印,在真实场景下,每个状态对应少则有 10 行,多则有上百行代码,所以用“一坨”这个词来形容真实的那段代码,再合适不过啦。
不过,是否可以调整调整代码呢?
答案是必须的,同事艾尔莎遂拿出《阿里巴巴Java开发手册 v666.pdf》,借用鲁迅先生提倡的“拿来主义”的思想开始调整。
调整一:采用阿里开发手册“注释规约”章节中提到的原则,先调整注释。
【强制】 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释,使用/* */注释,注意与代码对齐。
在每行末尾进行注释,不只是艾尔莎习惯性的问题,也是很多同事习惯性的一个问题,那采取规约调整后的效果如何呢?的确是明朗了不少么?!
调整二:采用阿里开发手册“编程规约——常量定义”章节中提到的原则,调整常量。
【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
艾尔莎按照“编程规约”提炼魔法值,进行常量定义,调整之后的效果如下,档次感觉有点上升。
到这,大多数码农重构代码可能就止步了,因为在业务支撑没有任何问题,在代码阅读上也没啥大问题了,但是艾尔莎重构代码绝不至于当前,于是又搬出《重构:改善既有代码的设计》宝典,开始了更进一步的重构。
艾尔莎掌握了书中“Replace Conditional with Polymorphism(以多态取代条件式)”的精髓,并且开始一步步尝试。
首先回顾上段代码段,从高度上去看,无论每个状态条件下做什么事情,都是进行相关处理而已,所以把每个状态条件下要做的事情,抽象出一个接口,只定义一个要处理的操作规范就可以啦。
然后把每个状态条件下要处理的事情,各自去实现接口,完成各自的事情处理就好了。
例如,赎回状态为初始的业务逻辑处理实现如下。
例如,赎回状态为赎回中的业务逻辑处理实现如下。
其它状态就不一一列举啦,主要是思想、主要是思想、主要是思想。
最后是奇迹发生的地方,直接抛码。
可以看出原有的“一坨”代码,变成了两句。简单解释一下变化后的两句代码,主要是根据赎回状态获取对应的业务逻辑处理实现,其中 SpringContextHolder 网上一搜一大片,其本质还是从 ApplicationContext 获取 Bean 的实例。如果在非 Spring 环境实现起来也简单,维护一个 Service 实现的配置文件,然后用反射创造出每个赎回状态对应的实例(这个实现准备在“爱情 36 技”系列中开篇去讲,本次不多说)。
艾尔莎这么重构,会有什么效果?个人愚见。
1. 直观上代码量陡增(要是按照代码行数,发工资该多好啊),代码易阅读(不过喜欢较真的同学,肯定认为这没有 if/eslse 看着爽,影响了阅读,哈哈);
2. 状态条件要是继续增多,直接自定义状态对应的实现处理就好了,对原有状态分支不影响;
3. 紧急需求来临时,无需关注每个状态的处理,只需关注对应的状态的实现,进行处理即可;
艾尔莎这么重构,会有什么效果?官方定论。
1. 在面向对象术语中,听上去最高贵的词非“多态”莫属。多态最更根本的好处就是:如果你需要根据对象的不同型别而采取不同的行为,多态使你不必编写明显的条件式;
2. 针对 type code(型别码)而写的大量 switch 语句以及针对 type string(型别名称字符串)而写的 if-then-else 语句在程序中就会很少出现;
3. 如果想增加一种新型别,只需要建立一个新的 subclass,并提供适当的函数实现就行了,这么一来就大大降低各部分之间的相依程度,使系统升级更加容易。
官方说的就是漂(生)亮(硬),暂不管个人愚见还是官方定论,不过经过艾尔莎的重构,确实改变了既有代码的设计,代码逼格确实陡然上升。
如果感觉有意思,那么在实际开发中,如果你也遇到大批量的 switch/case、if/else 不妨采取此方案尝试进行重构一下。
03. 撸码的艾米丽
同事艾米丽是 Android 开发人员(没错,上次文章提到删库的就是她),她近期在自研一个社交的项目,从前端到后台,不知不觉她就成了全栈开发。
不过,作为一个跨界全栈码农,总是有很多我们看似简单的小问题,却阻挡她前进,下面简单扯一扯她遇到的一个“Java 截取文本中超链接”的问题。
背景。有一个类似头条“Hi,#艾米丽#这大概就是冰雪美人吧#杰瑞#这是一只没有苦恼的老鼠”这样的一段文本,她在后端存储格式是下面这种富文本格式。
Hi,#艾米丽#\"艾米丽\" target=\"_blank\" href=\"http://v.xxx.com/xxxx1\">这大概就是冰雪美人吧#杰瑞#\"杰瑞\" target=\"_blank\" href=\"http://v.xxx.com/xxxx2\">这是一只没有苦恼的老鼠
但是 App 端不像 H5 那样直接能渲染链接,App 端需要拿到里面的链接才能做后续的事情,但是如何进行拆分拿到里面的链接,隔行如隔山,这可难倒了她!
寻找 idea。隔行如隔山,但隔行不隔理,一猿小将来支招,直接用最土、最 low 的方法进行正则匹配来拆分字符串就好了,艾米丽抱着编码思想去尝试解决去啦。
一天过去了,艾米丽的问题仍然没有解决,小窗口找我帮她搞定一下。
帮人帮到底。于是花了 2 分钟的功夫,先用最土的方法正则匹配,解析出艾米丽想要的链接;然后又找谷哥、度娘搜罗一番,解决方案可谓是应有尽有,于是把解决方案整理成
(1)最土、最 low 方法,正则匹配拆分;
(2)采用一款 Java 的 HTML 解析器 jsoup;
(3)采用 android.util 工具包
......
艾米丽最后采用最适合自己的一款 android.util 工具包得意解决。
一个看似很小的问题,静下来想一想,却把编程十余年的撸码套路说清楚啦。
面对需求实现或者疑难杂症,无论问题大小,首先花点功夫琢磨一下、在脑海中搜索一下实现思路;然后找谷哥度娘搜罗一番,看看是否有现成的方案;接着冷静思考,大胆去实现;如果仍然无解,最后求助同事/好友求 idea,也就是寻找高人指点迷津!
04. 完美的总结
身边以 Coding 为生的 farmer,一板砖拍下去确实能拍伤好几个,不过他们的日常工作,无不透漏着一点,那就是 Coding 是个技术活,撸码也有套路,需要掌握方式方法,闲暇之余多看看轮子,多积累技术栈,多寻找寻找灵感。
好了,一猿小讲一家之言,就掰扯就到这儿,如果再有人问“编码规范”不妨拿本文去扯扯淡。
最后,希望今天的分享能够对你们有一丁点帮助,当然也希望你们能够喜欢。