如何用最小代价,迅速提高你项目中“shit”代码的可读性(妈妈再也不用担心我删库跑路啦)

55 阅读1分钟

作者:vivo祁同伟

链接:juejin.im/post/684490…

正文

举个最简单的例子,阿里的java编码规约大家肯定都看过,甚至多数人可能都装了阿里的java代码检测插件,其中有一条就是当你的函数行数超过一定范围的时候就会提示warning告诉你函数太长,需要优化了。很多人不明白为什么,甚至阿里官方给出的理由是 多数人电脑的一屏 只能看到n行的代码,所以这里要增加这个函数行数的校验。

实际上这么多年我自己工作下来的感觉是上述的理由比较牵强,难道一个短函数就不需要优化了么?可以看看看下面的函数,这个函数也很短,但是可读性却并不好。

public class CustomList {

private boolean readOnly;

//默认的数组实际存储的元素个数 为0,

private int size;

//默认数组的长度为5

private Object[] elements = new Object[5];

/**

  • 只读模式下 才可以添加元素,

  • 如果数组长度足够 那么就直接往后面添加一个元素

  • 如果数组长度不够 则将数组的长度增加10

  • 然后再进行赋值

  • @param element

*/

public void add(Object element) {

if (!readOnly) {

int newSize = size + 1;

if (newSize > elements.length) {

Object[] newElements = new Object[elements.length + 10];

for (int i = 0; i < size; i++) {

newElements[i] = elements[i];

}

elements = newElements;

}

elements[size++] = element;

}

}

}

优化的第一步:

public void add(Object element) {

//只读模式就啥也不做

if (readOnly) {

return;

}

if (atCapacity()) {

Object[] newElements = new Object[elements.length + 10];

for (int i = 0; i < size; i++) {

newElements[i] = elements[i];

}

elements = newElements;

}

elements[size++] = element;

}

//是否需要扩容

private boolean atCapacity() {

int newSize = size + 1;

return newSize > elements.length;

}

第二步:

public void add(Object element) {

//只读模式就啥也不做

if (readOnly) {

return;

}

if (atCapacity()) {

grow();

}

addElement(element);

}

//是否需要扩容

private boolean atCapacity() {

int newSize = size + 1;

return newSize > elements.length;

}

//扩容

private void grow() {

Object[] newElements = new Object[elements.length + 10];

for (int i = 0; i < size; i++) {

newElements[i] = elements[i];

}

elements = newElements;

}

//增加一个元素

private void addElement(Object element) {

elements[size++] = element;

}

现在我们的add方法 仅仅就只有5行代码了。而可读性和第一版相比,真是天差地别。

如果你的类里面,public方法特别多,但是private方法特别少,那我觉得就一定还有优化的空间。

如果希望保持系统的简单性,那么就要尽可能的应用上述的组合方法进行细节上的重构,将一个个复杂的public方法,重构成一个个简单的private方法,最终对外暴露的public方法,只存在业务流程上对private方法的调用

下面继续看另外一个问题,在很多老项目中,屎山代码最大的特点就是if else太多,很多人即使知道有个叫策略模式的方法可以解决这个问题,但是却不敢下手,下面介绍一个例子,体会一下如何针对屎山代码的if else 动手。

采用这篇文章里的PayResult类, 现在往里面增加一个方法, 获取这次支付结果的积分。毕竟现在电商里买东西总要返点积分给你的。

//获取积分

public double getIntegral() {

//银联支付 按照1.5实际支付额度 返回积分

if (payChannel instanceof BankChannel) {

return paymentValue * 1.5;

} else if (payChannel instanceof WxChannel) {

//微信支付就按照实际支付额度两倍,然后减去券的金额

return paymentValue * 2 - couponValue;

} else if (payChannel instanceof AliPayChannel) {

//支付宝支付*2 ,然后还可以加上花呗支付的积分 马爸爸牛逼

return paymentValue * 2 + loanValue * 1;

}

return 0;

}

这样的代码项目里肯定不少见,我们现在来看看,怎么在一个成熟的系统里面,有惊无险的将这段代码优化一下。扩大一下可读性和可维护性。 毕竟很多人都知道大概怎么减少if else,但是真正实操起来 就往往做不到,不知道怎么做,也不敢做。

我们先弄一个积分策略类:

//积分策略

public class IntegralStrategy {

public double getIntegral() {

return 0;

}

}

然后把我们实际的积分算法逻辑 放到这个策略类里面

显然我们还需要一些参数,否则这些逻辑中需要引用的变量是找不到的 将外部的引用传进去:

//积分策略

public class IntegralStrategy {

public double getIntegral(PayResult payResult) {

//银联支付 按照1.5实际支付额度 返回积分

if (payResult.getPayChannel() instanceof BankChannel) {

return payResult.getPaymentValue() * 1.5;

} else if (payResult.getPayChannel() instanceof WxChannel) {

//微信支付就按照实际支付额度两倍,然后减去券的金额

return payResult.getPaymentValue() * 2 - payResult.getCouponValue();

} else if (payResult.getPayChannel() instanceof AliPayChannel) {

//支付宝支付*2 ,然后还可以加上花呗支付的积分 马爸爸牛逼

return payResult.getPaymentValue() * 2 + payResult.getLoanValue() * 1;

}

return 0;

}

}

然后修改一下我们的PayResult主类:

//获取积分

public double getIntegral() {

return integralStrategy.getIntegral(this);

}

//注意这个时候我们的全包构造函数 变成了private

private PayResult(PayChannel payChannel, Date payDate, Double totalValue, Double paymentValue, Double couponValue, Double loanValue) {

this.payChannel = payChannel;

this.payDate = payDate;

this.totalValue = totalValue;

this.paymentValue = paymentValue;

this.couponValue = couponValue;

this.loanValue = loanValue;

//也仅仅在这个构造函数 这里增加了一行代码

integralStrategy=new IntegralStrategy();

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。需要的小伙伴可以私信我【进阶】我免费分享给大家,或者直接点击下面链接领取,谢谢大家这么久以来的支持。

Android学习PDF+架构视频+面试文档+源码笔记

如果你有其他需要的话,也可以在GitHub上查看,下面的资料也会陆续上传到Github

330页PDF Android学习核心笔记(内含上面8大板块)

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

    进阶学习资料领取方式:GitHub

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!