毫无疑问,in-out 参数会导致代码困惑,因为它们可能会增加意外/不可预测的副作用。
所以,许多优秀的程序员说:
Avoid in-out parameters for changing mutable method parameters. Prefer to keep parameters unchanged.
对于希望自己的代码最简洁易懂的完美主义程序员来说,这条“规则”是否必须适用于所有情况?
例如,假设一个将元素添加到一个简单列表的基本方法,有两种方法:
第一种方式(带in-out参数):
private void addElementsToExistingList(List<String> myList){
myList.add("Foo");
myList.add("Bar");
}
来电者是:
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
addElementsToExistingList(myList);
第二种没有out参数的方式:
private List<String> addElementsToExistingList(List<String> originalList){
List<String> filledList = new ArrayList<String>(originalList); //add existing elements
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
来电者是:
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(addElementsToExistingList(myList));
第二种方式的优点:
参数未修改 => 没有对新读码器产生意外副作用的风险。
第二种方式的缺点:
非常冗长且可读性非常差......
当然,你会告诉我,这么简单的代码,第一种方式确实更方便。
但是,如果我们不考虑任何概念/代码的难度,我认为第二种方式对任何读者(无论初学者与否)都更合乎逻辑且更明显。
但是,它违反了 CQS 原则,即认为“命令”方法具有潜在的(但允许的,因为它是约定)副作用和具有返回类型但没有副作用的“查询”方法。
那么,激励程序员应该采用什么?根据代码案例混合两个?或者保持期望总是避免 in-out 参数的“法则”...
(当然,添加元素的方法的命名是为了显式示例,在实际代码中是一个糟糕的名称选择)。
最佳答案
我认为法律应该是:
Use what is more straight-forward, but always, always document the behavior of your methods extensively.
你的第二个例子是一个很好的例子,如果没有文档,你肯定会遇到错误:方法的名称是 addElementsToExistingList
,但是方法不会将元素添加到现有列表- 它创造了一个新的。至少可以说,这是一个违反直觉和误导性的名称......
关于java - 始终避免在 Java 中输入输出参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9673729/