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

简介: 随着编程技术的不断进步,编程语言变得越来越高级,功能封装也越来越完善。各种技术都在帮助程序员提高编写代码的效率。通过层层封装,程序员似乎不需要了解技术细节,只需逐行翻译需求内容即可。许多程序员不了解如何组织代码、提升运行效率以及底层基于的原理是什么,但是他们编写的代码通过了编译、测试,并且在上线运行了一个月而没有出现问题,似乎并没有对他们的实际工作产生明显的负面影响。

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


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


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


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


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

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


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


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

理解要开发的功能需求。

了解程序的运行原理。

做出合理的抽象。

组织复杂的逻辑。

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

持续不断的练习。

 

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

以SoFlu软件机器人近日推出的专注AI生成Java函数的FuncGPT(慧函数)为代表的AI代码生成工具的出现,或许带来了新的希望。

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

 

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

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

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

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

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

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

 

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

 

代码屎山示例

@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(慧函数)

// 类名: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(慧函数)免费使用,链接链接

相关文章
|
10月前
|
程序员 编译器 C语言
如何更高效的写出更健全的代码,一篇文章教会你如何拥有一个良好的代码风格
如何更高效的写出更健全的代码,一篇文章教会你如何拥有一个良好的代码风格
41 0
|
Web App开发 编解码 监控
防御性设计和开发
“防御性编程(Defensive programming)是防御式设计的一种具体体现,它是为了保证,对程序的不可预见的使用,不会造成程序功能上的损坏。它可以被看作是为了减少或消除墨菲定律效力的想法。”
779 0
防御性设计和开发
|
29天前
|
设计模式 程序员
代码可读性问题之培养和提高团队对代码可读性的重视,如何解决
代码可读性问题之培养和提高团队对代码可读性的重视,如何解决
|
3月前
|
测试技术
深入白盒测试:静态分析与动态分析的融合之道
【4月更文挑战第9天】 在软件开发过程中,确保代码质量和功能正确性是至关重要的。白盒测试作为一种软件测试方法,能够深入到程序内部逻辑结构,对软件的内部运作进行透彻的检查。本文将探讨白盒测试中静态分析与动态分析的结合使用,揭示如何通过这两种技术手段提高测试覆盖率和发现潜在缺陷。文章首先介绍白盒测试的基本概念,然后详细阐述静态分析和动态分析的原理及应用,最后提出一个结合两者的测试策略,旨在帮助测试工程师更有效地开展工作。
|
3月前
|
算法 测试技术 持续交付
代码重构:提升软件质量的艺术与实践
代码重构:提升软件质量的艺术与实践
130 0
|
设计模式
重构·改善既有代码的设计.03之重构手法(上)
之前的重构系列中,介绍了书中提到的重构基础,以及识别代码的坏味道。今天继续第三更,讲述那些重构手法(上)。看看哪些手法对你的项目能有所帮助......
19233 1
重构·改善既有代码的设计.03之重构手法(上)
|
设计模式
重构·改善既有代码的设计.04之重构手法(下)完结
重构改善既有代码的设计完结篇,汇总了全部的重构手法。看看哪些手法对你的项目能有所帮助…
7383 2
重构·改善既有代码的设计.04之重构手法(下)完结
|
测试技术 程序员
代码重构的力量:如何衡量重构成功
许多工程团队都在努力衡量他们重构工作的有效性。让我们看一下可以帮助您衡量重构成功的 5 个指标。 代码重构为开发人员提供了急需的精神休息,我认为许多开发人员都可以与此相关。整天编写代码要求很高,尤其是在您每天创建新功能的情况下。这是一项繁重的工作,开发人员通常需要一些空间来思考代码库的整体组织并回顾可以改进的地方
149 0
|
安全 大数据 程序员
软件开发困难、软件开发困难原因、软件开发困难的根本原因
  软件开发困难   软件开发困难最典型的事件是12360火车票订票,高并发量让初期的12360版本经常崩溃,根本不能用。不能用的软件或平台网站,这样的软件开发困难,难于上青天。   微软在开始组织团队编写Windows操作系统时,也经常遇到软件开发困难,进度迟迟不能更新,产品上线遥遥无期,导致微软领导一个头两个大。
649 0
|
测试技术