前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何提升代码质量,重构并非“万能药”

如何提升代码质量,重构并非“万能药”

原创
作者头像
努力的阿飞
发布2023-09-15 19:44:42
2060
发布2023-09-15 19:44:42
举报

随着编程技术的不断进步,编程语言变得越来越高级,功能封装也越来越完善。各种技术都在帮助程序员提高编写代码的效率。通过层层封装,程序员似乎不需要了解技术细节,只需逐行翻译需求内容即可。

许多程序员不了解如何组织代码、提升运行效率以及底层基于的原理是什么,但是他们编写的代码通过了编译、测试,并且在上线运行了一个月而没有出现问题,似乎并没有对他们的实际工作产生明显的负面影响。

尽管有“菜鸟”表达了对代码质量潜在问题的担忧,但这些担忧通常会被用“目前项目进展紧迫,等几个月后项目进度宽松后再进行代码重构”这样的说辞来安抚。

虽然我们不能否认,在某些(极其有限的)场景下,重构是解决问题的一种方法。但是,写了大量代码后,我们会发现,重构往往是程序开发过程中最复杂的任务之一。如果我们花了一个月的时间写了一堆糟糕的代码,那么要重构它可能需要更长的时间,也可能面临更高的风险。

过去我们经历了几次无法忍受的大规模重构。每一次重构之前,我们都会集合组内的专家,进行多次分析会议,暂停组内的需求,然后才开始重构。然而,在重构过程中,我们经常会遇到各种困难,几乎每天都会出现许多意想不到的问题。而且,上线时也几乎一定会出现一些问题。

在进行复杂代码重构时,从技术角度来看,需要执行三项任务:理解原有代码、将原有代码分解、构建新代码。然而,待重构的原有代码通常难以理解;模块之间过度耦合,一举一动可能影响整个系统,难以控制影响范围;原有代码不容易进行测试,无法确保新代码的正确性。

重构后会使效率提升多少?风险会降低多少?这个问题很难回答,因为低质量的代码本身并不能简单地标准化。

与写出质量差的代码不同的是,想写出好代码有很多前提:

? 理解要开发的功能需求。

? 了解程序的运行原理。

? 做出合理的抽象。

? 组织复杂的逻辑。

? 对自己开发效率的正确估算。

? 持续不断的练习。

因此随着技术的进步,终究能否实现快速交付和保证代码质量二者的世纪大和解?

以SoFlu软件机器人近日推出的专注AI生成Java函数的FuncGPT(慧函数)为代表的AI代码生成工具的出现,或许带来了新的希望。作为飞算SoFlu软件机器人的一个重要组成部分,FuncGPT(慧函数)支持所有类型函数创建。通过自然语言描述Java函数需求,实时生成高质量、高可读性的Java函数代码。生成代码可直接复制到IDEA,或一键导入Java全自动开发工具函数库。同时FuncGPT(慧函数)采用代码编写最佳实践及大规模机器联合训练的方式,致力于通过AIGF(AI-Generated Function)赋能软件开发,为中国软件开发者提供全栈式全流程软件开发的最佳体验,让程序员告别996!

FuncGPT(慧函数)具备以下五大能力:

● 自然语言:通过自然语言即可生成函数,降低软件开发门槛。

● 秒级函数开发:全自动秒级开发函数,秒级完成,效率千倍提升。

● 一站式函数开发应用:函数生成即可直接应用,效率、安全有保障。

● 质量可靠:生成的函数代码符合业界规范、具备良好的可读性,符合最优解。

● 灵活生成:可以根据开发人员的具体需求生成并支持调整和修改。

FuncGPT(慧函数)的代码质量如何?我们以一个Java函数实现BigDecimal的表达式运算需求为例,让FuncGPT与代码屎山一决高下。

代码屎山示例

代码语言:javascript
复制
@MethodDesc(desc="BigDecimal按公式运算,结果四舍五入取N位小数",params= {
            @ParamDesc(name="scaleLen",desc="结果小数位"),
            @ParamDesc(name="middleScaleLen",desc="中间运算除法小数位(传0默认为6位)"),
            @ParamDesc(name="formualText",desc="计算公式(如:A+B/C),如果出现负数请用下划线代替(例:A+B*-1写成A+B*_1"),
            @ParamDesc(name="varArr",desc="变量名和变量值列表(如:A:90,B:89)"),
    })
    public static BigDecimal bigDecimalFormualCalc(int scaleLen, int middleScaleLen, String formualText, Map<String, Object> varArr) {
        int iMiddleScaleLen=6;
        if(middleScaleLen>0){
            iMiddleScaleLen=middleScaleLen;
        }
        Set<String> keySet = varArr.keySet();
        for (String key : keySet) {
            varArr.put(key, varArr.get(key).toString().replace("-", "_"));
        }

        BigDecimal result=null;
        String formualTextStr=formualText;
        String sFormual="";
        String valueTemp="";
        int iLeftBracketIndex=formualTextStr.lastIndexOf(LEFT);
        int iRightBracketIndex=0;
        if(iLeftBracketIndex>=0){
            while (iLeftBracketIndex>=0){
                iRightBracketIndex=formualTextStr.indexOf(RIGHT,iLeftBracketIndex);
                sFormual=formualTextStr.substring(iLeftBracketIndex,iRightBracketIndex+1);
                sFormual=sFormual.replace(LEFT, REPLACEMENT);
                sFormual=sFormual.replace(RIGHT,REPLACEMENT);
                result= FloatUtils.oneBigDecimalFormualCalc(middleScaleLen,iMiddleScaleLen,sFormual,varArr);
                valueTemp=result.toString().replace("-","_");
                formualTextStr=formualTextStr.replace(LEFT.concat(sFormual).concat(RIGHT),valueTemp);
                iLeftBracketIndex=formualTextStr.lastIndexOf(LEFT);
            }
        }

        result=FloatUtils.oneBigDecimalFormualCalc(scaleLen,iMiddleScaleLen,formualTextStr,varArr);
        return  result;
    }
	
	
	public class FloatUtils {
    private FloatUtils(){}
    public static BigDecimal oneBigDecimalFormualCalc(int scaleLen, int middleScaleLen,
                                                      String oneFormualText, Map<String, Object> varArr) {

        BigDecimal result=null;
        String formualTextStr=oneFormualText;
        String linkStr="";

        Set<String> keySet = varArr.keySet();
        for (String key : keySet) {
            formualTextStr = formualTextStr.replace(key, varArr.get(key).toString());
        }
        char c ;
        List<Character> chars = new ArrayList<>();
        List<String> valueList = new ArrayList<>();
        String oneValue="";
        chars.add('+');
        chars.add('-');
        chars.add('*');
        chars.add('/');
        boolean isFindedLink=false;
        while (formualTextStr.length()>0) {
            isFindedLink=false;
            for (int i = 0; i < formualTextStr.length(); i++) {
                c = formualTextStr.charAt(i);
                if (chars.contains(c)) {
                    linkStr = linkStr.concat(String.valueOf(c));
                    oneValue = formualTextStr.substring(0, i);
                    oneValue=oneValue.replace("_","-");
                    formualTextStr = formualTextStr.substring(i+1, formualTextStr.length());
                    valueList.add(oneValue);
                    isFindedLink=true;
                    break;
                }
            }
            if(!isFindedLink){
                formualTextStr=formualTextStr.replace("_","-");
                valueList.add(formualTextStr);
                formualTextStr="";
            }
        }
        BigDecimal[] valueArr=new BigDecimal[valueList.size()];
        for(int i=0;i<valueList.size();i++){
            valueArr[i]=new BigDecimal(valueList.get(i).toString());
        }

        result= FloatFunction.bigDecimalValueCalc2(scaleLen,middleScaleLen,linkStr,valueArr);
        return  result;
    }


}


@MethodDesc(desc="BigDecimal按值列表运算(中间除法小数位入参控制),结果四舍五入取N位小数",params= {
            @ParamDesc(name="scaleLen",desc="小数位个数"),
            @ParamDesc(name="middleScaleLen",desc="中间运算除法小数位(传0默认为6位)"),
            @ParamDesc(name="linkArr",desc="运算符列表(如:A+B/C,则传+/)"),
            @ParamDesc(name="valueArr",desc="String值列表(如:A+B/C,则传ABC的3个值)"),})
    public static BigDecimal bigDecimalValueCalc2(int scaleLen, int middleScaleLen,String linkArr,Object[] valueArr) {
        BigDecimal result;
        int iMiddleScaleLen=6;
        if(middleScaleLen>0){
            iMiddleScaleLen=middleScaleLen;
        }
        ArrayList<BigDecimal> valueList=new ArrayList();
        ArrayList linkList=new ArrayList();
        for (int i=0;i<valueArr.length;i++){
            if (valueArr[i] instanceof BigDecimal){
                valueList.add((BigDecimal)valueArr[i]);
            }else if (valueArr[i] instanceof Double){
                valueList.add(BigDecimal.valueOf((double)valueArr[i]));
            }else if (valueArr[i] instanceof Integer){
                valueList.add(BigDecimal.valueOf((int)valueArr[i]));
            }else {
                valueList.add(new BigDecimal(valueArr[i].toString()));
            }
        }
        for (int i=0;i<linkArr.length();i++){
            linkList.add(linkArr.charAt(i));
        }
        String linkStr="";
        BigDecimal valueOne=null;
        BigDecimal valueTwo=null;
        int iIndex=0;
        int multiplyDivideIndex=-1;
        BigDecimal tempValue= BigDecimal.ZERO;
        while (linkList.size()>0){
            multiplyDivideIndex=-1;
            for (int i=0;i<linkList.size();i++) {
                linkStr=linkList.get(i).toString();
                if ("*".equals(linkStr)|| "/".equals(linkStr)) {
                    multiplyDivideIndex = i;
                    break;
                }
            }
            if(multiplyDivideIndex<0) {
                iIndex=0;
            }
            else {
                iIndex=multiplyDivideIndex;
            }
            linkStr=linkList.get(iIndex).toString();
            valueOne=valueList.get(iIndex);
            valueTwo=valueList.get(iIndex+1);
            switch (linkStr) {
                case "+":
                    tempValue=valueOne.add(valueTwo);
                    break;
                case "-":
                    tempValue=valueOne.subtract(valueTwo);
                    break;
                case "*":
                    tempValue=valueOne.multiply(valueTwo);
                    break;
                case "/":
                    tempValue=valueOne.divide(valueTwo,iMiddleScaleLen,BigDecimal.ROUND_HALF_UP);
                    break;
                default:
                    break;
            }
            valueList.remove(iIndex);
            valueList.remove(iIndex);
            valueList.add(iIndex,tempValue);
            linkList.remove(iIndex);
        }
        if (scaleLen<0){
            result=valueList.get(0);
        } else {
            result=valueList.get(0).setScale(scaleLen,BigDecimal.ROUND_HALF_UP);
        }
        return  result;
    }

FuncGPT(慧函数)

代码语言:javascript
复制
// 类名:BigDecimalCalculator
// 函数名:calculateExpression
// 函数功能:使用BigDecimal计算表达式的结果
// POM依赖包:
// <dependency>
//     <groupId>org.apache.commons</groupId>
//     <artifactId>commons-lang3</artifactId>
//     <version>3.12.0</version>
// </dependency>

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Stack;

public class BigDecimalCalculator {
    /**
     * 使用BigDecimal计算表达式的结果
     * @param expression 要计算的表达式
     * @return 计算结果
     */
    public static BigDecimal calculateExpression(String expression) {
        if (StringUtils.isBlank(expression)) {
            throw new IllegalArgumentException("Expression cannot be blank");
        }

        Stack<BigDecimal> numberStack = new Stack<>();
        Stack<Character> operatorStack = new Stack<>();

        for (int i = 0; i < expression.length(); i++) {
            char ch = expression.charAt(i);
            if (Character.isDigit(ch)) {
                StringBuilder sb = new StringBuilder();
                while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
                    sb.append(expression.charAt(i));
                    i++;
                }
                i--;

                BigDecimal number = new BigDecimal(sb.toString());
                numberStack.push(number);
            } else if (ch == '(') {
                operatorStack.push(ch);
            } else if (ch == ')') {
                while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
                    BigDecimal result = performOperation(numberStack, operatorStack);
                    numberStack.push(result);
                }
                if (!operatorStack.isEmpty() && operatorStack.peek() == '(') {
                    operatorStack.pop();
                }
            } else if (isOperator(ch)) {
                while (!operatorStack.isEmpty() && hasHigherPrecedence(ch, operatorStack.peek())) {
                    BigDecimal result = performOperation(numberStack, operatorStack);
                    numberStack.push(result);
                }
                operatorStack.push(ch);
            }
        }

        while (!operatorStack.isEmpty()) {
            BigDecimal result = performOperation(numberStack, operatorStack);
            numberStack.push(result);
        }

        return numberStack.pop();
    }

    private static boolean isOperator(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }

    private static boolean hasHigherPrecedence(char op1, char op2) {
        if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) {
            return true;
        }
        return false;
    }

    private static BigDecimal performOperation(Stack<BigDecimal> numberStack, Stack<Character> operatorStack) {
        BigDecimal num2 = numberStack.pop();
        BigDecimal num1 = numberStack.pop();
        char operator = operatorStack.pop();

        BigDecimal result;
        switch (operator) {
            case '+':
                result = num1.add(num2);
                break;
            case '-':
                result = num1.subtract(num2);
                break;
            case '*':
                result = num1.multiply(num2);
                break;
            case '/':
                result = num1.divide(num2, 2, RoundingMode.HALF_UP);
                break;
            default:
                throw new IllegalArgumentException("Invalid operator");
        }

        return result;
    }
}

// 函数示例
// 使用BigDecimal计算表达式的结果示例
// 入参:expression,要计算的表达式
// 出参:result,计算结果
// 调用示例:
// String expression = "2.5 + 3 * (4 - 1)";
// BigDecimal result = BigDecimalCalculator.calculateExpression(expression);
// System.out.println(result);
// 输出结果:例如,计算表达式"2.5 + 3 * (4 - 1)"的结果为:11.5
// 则输出结果为:11.5

经过对比分析,不难发现:

可读性上:

人工代码命名存在截断和不规范,注释不够简洁清晰,代码可读性差;

FuncGPT使用了合理的命名和注释,函数和变量的命名清晰明了,注释对函数的功能和参数进行了说明,提高了代码的可读性。

可维护性上:

人工代码代码层层嵌套,方法繁琐,不利于后期维护修改;

FuncGPT使用了合适的数据结构和算法。它使用两个栈来处理运算符和操作数,通过遍历表达式字符并根据优先级进行计算,避免了复杂的嵌套逻辑和多重判断。

安全性上:

人工代码没有判断空值,存在漏洞,健壮性差;

FuncGPT引入了Apache Commons Lang库,利用StringUtils类的isBlank方法判断表达式是否为空,提高了代码的健壮性和可靠性。

综上,FuncGPT(慧函数)生成的代码具有更好的可读性、可维护性和异常处理,并且使用了逆波兰表达式计算和第三方库来提供更强大的功能。

FuncGPT(慧函数)免费使用,链接https://c.suo.nz/74U0Y

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com