如何提升代码质量,重构并非“万能药”
随着编程技术的不断进步,编程语言变得越来越高级,功能封装也越来越完善。各种技术都在帮助程序员提高编写代码的效率。通过层层封装,程序员似乎不需要了解技术细节,只需逐行翻译需求内容即可。
许多程序员不了解如何组织代码、提升运行效率以及底层基于的原理是什么,但是他们编写的代码通过了编译、测试,并且在上线运行了一个月而没有出现问题,似乎并没有对他们的实际工作产生明显的负面影响。
尽管有“菜鸟”表达了对代码质量潜在问题的担忧,但这些担忧通常会被用“目前项目进展紧迫,等几个月后项目进度宽松后再进行代码重构”这样的说辞来安抚。
虽然我们不能否认,在某些(极其有限的)场景下,重构是解决问题的一种方法。但是,写了大量代码后,我们会发现,重构往往是程序开发过程中最复杂的任务之一。如果我们花了一个月的时间写了一堆糟糕的代码,那么要重构它可能需要更长的时间,也可能面临更高的风险。
过去我们经历了几次无法忍受的大规模重构。每一次重构之前,我们都会集合组内的专家,进行多次分析会议,暂停组内的需求,然后才开始重构。然而,在重构过程中,我们经常会遇到各种困难,几乎每天都会出现许多意想不到的问题。而且,上线时也几乎一定会出现一些问题。
在进行复杂代码重构时,从技术角度来看,需要执行三项任务:理解原有代码、将原有代码分解、构建新代码。然而,待重构的原有代码通常难以理解;模块之间过度耦合,一举一动可能影响整个系统,难以控制影响范围;原有代码不容易进行测试,无法确保新代码的正确性。
重构后会使效率提升多少?风险会降低多少?这个问题很难回答,因为低质量的代码本身并不能简单地标准化。
与写出质量差的代码不同的是,想写出好代码有很多前提:
✔ 理解要开发的功能需求。
✔ 了解程序的运行原理。
✔ 做出合理的抽象。
✔ 组织复杂的逻辑。
✔ 对自己开发效率的正确估算。
✔ 持续不断的练习。
因此随着技术的进步,终究能否实现快速交付和保证代码质量二者的世纪大和解?
以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(慧函数)免费使用,链接https://c.suo.nz/clFAa
- 点赞
- 收藏
- 关注作者
评论(0)