代码重构:过长参数列表
【摘要】 代码重构:过长参数列表
什么是过长参数列表(Long Parameter List)
-
定义:方法的入参过多,或存在不必要的参数
-
影响:方法不易被理解、使用,方法签名容易不稳定,不易维护
-
改进目标:去除多余参数,合并部分参数,提升方法签名稳定性
-
方法:
-
以查询取代参数
-
保持对象完整
-
引入参数对象
-
函数组合成类
-
移除标记参数
-
-
注:有时候你明显不希望造成“被调用对象”与“较大对象”间的某种依赖关系。这时候将数据从对象中拆解出来单独作为参数,也很合情合理。但是请注意其所引发的代价。如果参数列太长或变化太频繁,你就需要重新考虑自己的依赖结构了。
代码案例
public class TicketInfo {
private final double baseDiscount;
public TicketInfo(double baseDiscount) {
this.baseDiscount = baseDiscount;
}
/**
* 获取票据信息
*
* @param name 姓名
* @param age 年龄
* @param isChild 是否儿童
* @param isStudent 是否学生
* @param ageFloor 年龄上限
* @param ageCeiling 年龄下限
* @param performance 演出信息
* @param basicPrice 基本票价
* @return 票据信息
*/
public String getTicketInfo(String name, int age, boolean isChild, boolean isStudent, int ageFloor, int ageCeiling,
Performance performance, double basicPrice) {
if ((age < ageFloor || age > ageCeiling)) {
throw new IllegalArgumentException("age is out of valid range, cannot buy ticket!");
}
return getPerformanceInfo(performance)
+ getConsumerInfo(name, age, isStudent, isChild)
+ getPriceInfo(isChild, isStudent, basicPrice);
}
private String getPriceInfo(boolean isChild, boolean isStudent, double basicPrice) {
final double discount = getDiscount(isStudent, isChild);
final double ticketPrice = getTicketPrice(discount, basicPrice);
return "priceInfo" + Constant.LINE_SEPARATOR
+ "\tprice: " + ticketPrice + Constant.LINE_SEPARATOR
+ "\tdiscount: " + discount + Constant.LINE_SEPARATOR;
}
private double getDiscount(boolean isStudent, boolean isChild) {
double childDiscount = calculateDiscount("Child", isChild, isStudent);
double studentDiscount = calculateDiscount("Student", isChild, isStudent);
return BigDecimal.valueOf(Math.min(childDiscount, studentDiscount))
.setScale(2, BigDecimal.ROUND_HALF_UP)
.doubleValue();
}
private double calculateDiscount(String discountType, boolean isChild, boolean isStudent) {
if ("Child".equals(discountType) && isChild) {
return 0.5;
}
if ("Student".equals(discountType) && isStudent) {
return 0.9 * baseDiscount;
}
return baseDiscount;
}
private double getTicketPrice(double discount, double basicPrice) {
return BigDecimal.valueOf(discount * basicPrice).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
private String getConsumerInfo(String name, int age, boolean isStudent, boolean isChild) {
return "consumerInfo" + Constant.LINE_SEPARATOR
+ "\tname: " + name + Constant.LINE_SEPARATOR
+ "\tage: " + age + Constant.LINE_SEPARATOR
+ "\tisStudent: " + isStudent + Constant.LINE_SEPARATOR
+ "\tisChild: " + isChild + Constant.LINE_SEPARATOR;
}
private String getPerformanceInfo(Performance performance) {
return "playInfo" + Constant.LINE_SEPARATOR
+ "\tplayName: " + performance.getPlayName() + Constant.LINE_SEPARATOR
+ "\tplayType: " + performance.getPlayType() + Constant.LINE_SEPARATOR
+ "\tdate: " + performance.getPlayDate() + Constant.LINE_SEPARATOR;
}
}
代码背景
-
计算某表演项目的票价;
-
只有符合年龄要求才可以购买,;
-
儿童票5折, 学生可以打9折, 二者取最小;
症状/问题:方法入参过多,该问题的具体情况有:
-
某几个入参有关联性
-
某几个入参是一个对象的部分字段
-
某些入参可通过其他入参计算得到
代码背景
-
计算某表演项目的票价;
-
只有符合年龄要求才可以购买,;
-
儿童票5折, 学生可以打9折, 二者取最小;
症状/问题
-
函数逻辑都是针对某个入参对象属性的加工
-
某些入参属于标记,用于控制代码逻辑
-
查询取代参数、保持对象完整、引入参数对象
-
移动函数至适合的类、移除标记参数
相关技巧
华为编程规范
可运行CodeCheck来辅助排查是否存在过长参数列表的坏味道:
总结
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)