首页 > 代码库 > 重构笔记——移除对参数的赋值
重构笔记——移除对参数的赋值
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42497857
在上一篇文章中介绍了“分解临时变值“。本文将介绍“移除对参数的赋值”这种重构手法。
下面让我们来学习这种重构手法吧。
开门见山
发现:代码对一个参数进行赋值。
解决:以一个临时变量取代该参数的位置。
//重构前 int dicount(int inputVal, int quantity, int yearToDate){ if(inputVal > 50) inputVal-=10; }
//重构后 int dicount(final int inputVal, int quantity, int yearToDate){ int result = inputVal; if(result > 50) result-=10; }
动机
我想你很清楚“对参数赋值”这个说话的意思。如果把一个名称为fool的对象作为参数传递给某个函数,那么“对参数赋值”意味改变fool,使它引用另一个对象。但是,如果在“被传入对象”身上进行什么操作,那没问题,我们经常会这么做。这里只针对“fool被改变而指向另一个对象”这种情况来讨论:
void test(Object fool){ fool.changedBySomeWay(); //that's ok fool=anotherObject; //trouble will appear }我们之所不这样做,是因为它降低了代码的清晰度,而且混用了按值传递和按引用传递这两种参数传递方式。JAVA只采用按值进行传递。
在按值传递的情况下,对参数的任何修改,都不会对调用端造成任何影响。如果你只以参数表示“被传递进来的东西”,那么代码会清晰的多,因为这种用法在所有语言中都表现出相同的语义。
在JAVA中,一般不要对参数赋值:如果你看到手上的代码已经这么做了,就应该使用本文的方法。
做法
示例
int dicount(int inputVal, int quantity, int yearToDate){ if(inputVal > 50) inputVal-=5; if(quantity > 100) quantity-=10; if(yearToDate > 1000) yearToDate-=100; return inputVal; }以临时变量取代对参数的赋值动作,得到下列代码:
int dicount(int inputVal, int quantity, int yearToDate){ int result = inputVal; if(result > 50) result-=5; if(quantity > 100) quantity-=10; if(yearToDate > 1000) yearToDate-=100; return result; }可以为参数加上final关键词,强制其遵循“不对参数赋值”这一惯例:
int dicount(final int inputVal, final int quantity, final int yearToDate){ int result = inputVal; if(result > 50) result-=5; if(quantity > 100) quantity-=10; if(yearToDate > 1000) yearToDate-=100; return result; }
JAVA的按值传递
我们应该都知道,JAVA使用按值传递的函数调用方式,这常常也会使大家迷惑。在所有地点,JAVA都会遵循严格按值传递:
//JAVA按值的传递 class Params{ public static void main(String[] args) { int x = 10; triple(x); System.err.println("x after triple:" + x); } private static void triple(int arg){ arg = arg * 3; System.err.println("arg in triple:" +arg ); } } //输出 //arg in triple:30 //x after triple:10
//以对象为参数 class Params{ public static void main(String[] args) { Date d1 = new Date(2015,1,1); nextDateUpdate(d1); System.err.println("d1 after nextday:" + d1); Date d2 = new Date(2015,1,1); nextDateReplace(d2); System.err.println("d2 after nextday:" + d2);//61380864000000 } private static void nextDateUpdate(Date d) { d.setDate(d.getDate()+1); System.err.println("arg in nextday d1 : "+d); } private static void nextDateReplace(Date d) { d = new Date(d.getYear(),d.getMonth(),d.getDate()+1); d=null; System.err.println("arg in nextday d2: "+d); } } //输出 /* arg in nextday d1 : Tue Feb 02 00:00:00 CST 3915 d1 after nextday: Tue Feb 02 00:00:00 CST 3915 arg in nextday d2: Tue Feb 02 00:00:00 CST 3915 d2 after nextday: Mon Feb 01 00:00:00 CST 3915 */从本质上说,对象的引用是按值传递的。因为可以修改参数对象的内部状态,但对参数对象重新赋值是没有意义的。
本文主要介绍了重构手法——移除对参数的赋值。我觉得这个重构手法使用的情况并不常见,一般情况下,我们都觉得没有必要把参数的值重新定义。但是为了让代码显得比较清晰,在某些情况下还是值得做的。
最后,希望本文对你有所帮助。有问题可以留言,谢谢。(PS:下一篇将介绍重构笔记——以函数对象取代函数)
重构笔记文章如下
重构笔记——入门篇
重构笔记——代码的坏味道(上)
重构笔记——代码的坏味道(下)
重构笔记——构筑测试体
重构笔记——提炼函数
重构笔记——内联函数
重构笔记——内联临时变量
重构笔记——以查询取代临时变量
重构笔记——引入解释性变量
重构笔记——分解临时变量
重构笔记——移除对参数的赋值