How to quickly improve the readability of the "shit" code in your project with minimal cost (Mom no longer has to worry about deleting the library and running away)

Preface

In this chapter, we mainly learn how to enhance the readability of the code. Someone once said the best model is precisely those who thought he would be laughed at by others mode in the course of my own study design patterns, I often think to learn quickly, but the actual use of it but did not remember which use , I dare not change even if I encounter it, for fear of correcting an online fault. In the end, writing and writing is back to business programming.

Author: vivo with Qi Wei
link: https: //juejin.im/post/6844904047397322759

text

For the simplest example, everyone must have seen Ali’s java coding specifications, and most people may even have installed Ali’s java code detection plug-in. One of them is that you will be prompted when the number of function lines exceeds a certain range. Warning tells you that the function is too long and needs optimization. Many people don't understand why, even the official reason given by Ali is that most people can only see n lines of code on one screen of the computer, so here we need to increase the verification of the number of lines of this function.

In fact, my feeling after working for so many years is that the above reasons are far-fetched. Doesn't a short function need to be optimized? You can look at the following function, this function is also very short, but the readability is not good.

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;
        }

    }

}

The first step of optimization:

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;
    }

The second step:

 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;
    }

Now our add method only has 5 lines of code. Compared with the first edition, the readability is really different.

If your class has very many public methods but very few private methods , then I think there must be room for optimization.

If you want to maintain the simplicity of the system, you must apply the above-mentioned combination method as much as possible to refactor in detail, restructure complex public methods into simple private methods, and finally expose public methods. There are only calls to private methods on business processes .

Let's continue to look at another problem. In many old projects, the biggest feature of Shishan code is that there are too many if else. Many people even know that there is a method called strategy mode that can solve this problem, but they are afraid to start. For example, let’s experience how to target the if else of Shishan code.

Using the PayResult class in this article , now add a method to get the points for the payment result. After all, you always have to get points back when you buy things in e-commerce.

 //获取积分
    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;
    }

Such code projects are certainly not uncommon. Let's now take a look at how to optimize this code in a mature system without any risk. Expand the readability and maintainability. After all, many people know how to reduce if else, but they are often unable to do it in practice. They don't know how to do it, and they dare not do it.

Let's get an integral strategy class first:

//积分策略
public class IntegralStrategy {
    public double getIntegral() {
        return 0;
    }
}

Then put our actual integration algorithm logic into this strategy class

Obviously we still need some parameters, otherwise the variables that need to be referenced in these logics cannot be found. Pass in external references:

//积分策略
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;
    }
}

Then modify our PayResult main class:

  //获取积分
    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();
    }    

At this point, we have completed a preliminary decoupling work, but the overall if else logic has not been completely removed, just moved a place, continue to optimize.

It should be noted here: if your if else logic does not require too many parameters of the main class, then there is no need to pass the main class reference directly, as long as the parameters are passed directly, here for the convenience of demonstration, we directly pass the main class Class as a parameter.

Passing only the parameters without passing the reference of the main class has an advantage: only the minimal coupling between the context class and these strategy classes is involved .

First remove if else

//积分策略
public abstract class IntegralStrategy {
    abstract double getIntegral(PayResult payResult);
}
public class AliPayIntegralStrategy extends IntegralStrategy {
    @Override
    double getIntegral(PayResult payResult) {
        return payResult.getPaymentValue() * 2 + payResult.getLoanValue() * 1;
    }
}
public class UnionPayIntegralStrategy extends IntegralStrategy {
    @Override
    double getIntegral(PayResult payResult) {
        return payResult.getPaymentValue() * 1.5;
    }
}
public class WxPayIntegralStrategy extends IntegralStrategy {
    @Override
    double getIntegral(PayResult payResult) {
        return payResult.getPaymentValue() * 2 - payResult.getCouponValue();
    }
}

Then change the construction method of our PayResult:

 //银联支付 注意看最后一个参数
    public static PayResult createUnionPayResult(Date payDate, Double totalValue, Double paymentValue) {
        return new PayResult(new BankChannel(), payDate, totalValue, paymentValue, 0.0d, 0.0d,new UnionPayIntegralStrategy());
    }

    //微信支付 注意看最后一个参数
    public static PayResult createWxPayResult(Date payDate, Double totalValue, Double paymentValue, Double couponValue) {
        return new PayResult(new WxChannel(), payDate, totalValue, paymentValue, couponValue, 0.0d,new WxPayIntegralStrategy());
    }

    //支付宝支付 注意看最后一个参数
    public static PayResult createAliPayResult(PayChannel payChannel, Date payDate, Double totalValue, Double paymentValue, Double couponValue, Double loanValue) {
        return new PayResult(new AliPayChannel(), payDate, totalValue, paymentValue, couponValue, 0.0d,new AliPayIntegralStrategy());
    }

    //注意看最后一个参数
    private PayResult(PayChannel payChannel, Date payDate, Double totalValue, Double paymentValue, Double couponValue, Double loanValue, IntegralStrategy integralStrategy) {
        this.payChannel = payChannel;
        this.payDate = payDate;
        this.totalValue = totalValue;
        this.paymentValue = paymentValue;
        this.couponValue = couponValue;
        this.loanValue = loanValue;
        this.integralStrategy = integralStrategy;
    }

At this point, we have completely reconstructed the entire integral system.

End of sentence

If you have any insights on the article, or any technical questions, you can leave a message in the comment area to discuss, and you will definitely reply.
Everyone is also welcome to come to my B station to play with me, video explanations of the advanced technical difficulties of various Android architects, Ren Junbai prostitutes ~
B station through train: https://space.bilibili.com/484587989

Friends who like the article, don’t forget to follow, leave a like before leaving~

Guess you like

Origin blog.csdn.net/Androiddddd/article/details/109205440