每当我需要超过 3 个参数时,我总是对函数使用一个数组参数。
示例:考虑这样的函数调用。
processSecondStage($stepTitle, $round, $entryId, $formId, $stepType, $stepAfterApproved, $assigneees, $stageToMove);
我总是更喜欢下面的一个。
processSecondStage(array(
'stepTitle' => $title,
'round' => $round,
'stepAfterApproved' => $stepAfterApproved,
'entryId' => $_entryId,
'assigneees' => (array)$_POST['flow-asignee'],
'stageToMove' => $currentStep,
'formId' => $targetFormId,
'stepType' => 'approval'
));
优势(我可能是错的):
a) 可以添加更多数量的参数
b) 可读性
c) 订单可以轻松更改
d) 默认参数处理更容易
缺点:
a) 代码长度增加,特别是在我们参数少于 3-4 个的情况下。
任何人都可以帮助我了解使用数组参数的更多缺点吗?
每当我更改其他开发人员代码时(就像我现在要做的那样),那么我觉得使用array
作为参数有一些主要缺点,因为如果不是这种情况,那么它应该是一种标准做法。
虽然我已经给出了PHP的例子,但我在我工作的其他语言中也发现了这个。
谢谢。
当您要传递的内容密切相关并且单独没有意义时,数组作为参数很有用。一个经典的例子是由blue
、green
、red
(也许是gamma
)定义的Color
。将这些参数组合成一个数组(或 javascript 中的对象)可以让您轻松将其换出。
始终使用数组作为函数的单个参数会使您在 IDE 可以为您提供的参数列表中松懈。对于阅读代码的人来说,弄清楚需要传递给函数的内容是相当糟糕的。它还为未来的蠕变打开了大门(哦,这个函数只是让我喝咖啡,但如果我添加另一个可选参数,它也可以让我喝茶。哦,也许我可以让它给我做晚餐。为什么不添加功能来订购攻击直升机)。
在常规参数列表中,您可以通过引用(function pushElement(array &$sortableArray, $element)
)传递内容。如果可能的话,这在常规数组中是不应该的。
关于默认值的观点有点有争议。普通参数列表允许类型提示和默认值:
function action(string $action = 'tickle', string $target = 'Polar bear') {
print "I {$action} a {$target}";
}
单个参数作为数组可能只有在传递某种静态配置时才真正闪耀。您将某些内容的配置与使用它的实际代码分开,以便更轻松地修改配置。同时,您可以利用这样一个事实,即您不必以非常特定的顺序发送 20 个参数。
在您的情况下,您给出的参数列表变化很大且很长,这表明您的函数做得太多了。其中一部分可能应该移动到构造函数中,一部分应该移动到某种Form
类中。
这个话题的某些部分是非常固执己见的......
您描述的问题不仅仅是作为列表的参数与参数序列。出现了几个问题(在您的示例中两者都存在)。
- 工具
- 参数排序
- 语义学
工具可能很明显:如果您只有数组作为参数,则没有 IDE 会知道里面应该包含什么。好吧,大多数IDE 不会知道。
参数的排序通常由函数的名称和/或其语义决定。如果drawLine
参数的规范顺序为($from, $to)
。如果没有规范顺序,则代码可能存在其他问题...(见下文)
语义:如果你有3+参数(特别是如果你有更多的参数),那么抽象很可能是错误的。例如,假设你有一个函数createShirt($size="m", int $red, int $blue, int $green, Image $logo, $material="wool")
:属性的顺序是任意的,生成的对象(衬衫)可能不需要所有这些参数,但你绝对可以使用这个抽象。我更喜欢构建器模式,例如:
$shirt = ShirtBuilder::create("m") // verifies m is a size
->setColor(new Color($red,$green,$blue)) // has type-hint color
->setImage($logo) // has type-hint
->setMaterial($material)
->build();
它绝对更详细,但很明显你只需要调用所需的函数,你可以在任何时候验证设置的值(阅读:函数调用)。构建函数可以验证组合是否有效,并且 Shirt 对象本身甚至可以是不可变的。
但是,数组绝对有其位置和用途。但通常它是"提供相同类型事物的列表"。如果您的数组只有来自非常小的域的字符串键,则可能需要一个对象。
使用对象将触发诸如"哪些参数应属于此对象? 如果没有语义原因使真正的参数子集一起出现,则可能需要命令模式(命令对象)。 IDE可能会提供所有奇迹,使使用这些变得容易
tl;博士:
使用数组来保存异构参数列表可能是一种反模式(在某些场景/语言中可能是必要的)。
具有 3 个以上参数的函数/方法表明抽象太少(可能有原因)。使用适当的设计模式。