有很多参数的函数是不好的形式吗?有啥选择?

Posted

技术标签:

【中文标题】有很多参数的函数是不好的形式吗?有啥选择?【英文标题】:Is it bad form to have functions with a lot of parameters? What's the alternative?有很多参数的函数是不好的形式吗?有什么选择? 【发布时间】:2011-02-08 13:17:55 【问题描述】:

我有一个查询数据库的搜索功能,并且有大约 15 个可选参数。显然这并不漂亮,称它为有点乱。 php 不允许重载方法,所以我一直在创建巨大的函数签名。

我在其他地方看到了诸如创建参数类之类的建议:Disadvantages of using a lot of parameters

但这似乎太重了。我可以传入一个关联数组,但是虽然这减少了参数的数量,但我认为这不太容易理解,因为没有内置文档说明数组中应该存在哪些键。

还有其他方法可以优雅地处理这个问题吗?通常在其他语言中,我会有一个非常丑陋的 private 方法,它最多需要十几个参数,然后创建同名的 public 方法,这些方法接受这些参数的子集并在内部调用私有方法。

【问题讨论】:

【参考方案1】:

在PHP中,可以使用关联数组:

someFunction(array(
    "a" => 3243,
    "b" => 2354,
    "c" => 33453,
    "d" => 324353,
    "e" => 321243,
    "f" => 321243,
    "g" => 312243,
    "h" => 321243,
))

或正在调用该函数的对象的属性(如果有意义的话)。 PHPMailer 发送这样的邮件:

// instantiate the class
$mailer = new PHPMailer();

// Set the subject
$mailer->Subject = 'This is a test';

// Body
$mailer->Body = 'This is a test of my mail system!';

// Add an address to send to.
$mailer->AddAddress('foo@host.com', 'Eric Rosebrock');

if(!$mailer->Send())

    echo 'There was a problem sending this mail!';

它还有更多的可选参数。它也可以使用具有数百个参数的方法,但这更具可读性。

编辑:这些解决方案还更好地支持可选参数。在属性的情况下很简单,在关联数组的情况下,您可以将数组与默认值数组合并。

【讨论】:

使用数组作为参数还有一个好处是不会强迫你创建参数的层次结构。在你的函数开始时,你仍然可以检查是否给出了所需的参数。 是的,但是函数签名中没有有意义的文档——除非我单独记录并保持最新,否则有人怎么知道允许哪些参数? 执行此操作的好地方是 Doxygen/PHPDoc 评论(如果您不了解这些,请在 Google 上搜索)。然后,高级 IDE 将能够在输入代码时向您显示此类文档。【参考方案2】:

通常,长参数列表是代码中所谓的不良气味,可以通过称为 Introduce 参数对象的重构来删除。参考this。

干杯

【讨论】:

【参考方案3】:

是的,好的经验法则是不超过 3-4 个参数。如果您需要更多,那么通常您应该使用数组或对象作为参数之一。但在某些情况下,如果你认为你真的需要更多参数,那么当然,为什么不呢。如果它使您的代码易于理解和使用,那为什么不呢。

【讨论】:

【参考方案4】:

您可以创建一个将参数存储为属性的类,允许您根据需要设置每个属性,然后有一个使用这些属性来查询数据库的方法。构造函数可以为这些属性设置默认值。这只是让调用更容易一些。

$function = ClassFunction();
$function->arg1 = 'Some value.';
$function->arg2 = true;
$function->arg3 = 5;

$result = $function->call_method();    // This uses default values for any property not set.

【讨论】:

【参考方案5】:

在我看来,“参数过多”的问题只是一个更深层次的问题的表现:糟糕的架构。如果一个函数真的需要所有这些参数值,那么很有可能它做得比它应该做的要多得多。

这应该是一个提醒“哦,嘿,让我们重新考虑不要使用过程 X 来做所有的事情,而是想想 X 应该真正做什么以及 Y 和 Z 应该做什么。

【讨论】:

【参考方案6】:

将您的函数转换为类会很好。有两个主要优点:

函数参数转换为属性并可以注释

我认为比较大的函数代码可以拆分成一组更小的私有方法

【讨论】:

以上是关于有很多参数的函数是不好的形式吗?有啥选择?的主要内容,如果未能解决你的问题,请参考以下文章

Matlab中的高斯函数有啥区别吗?

具有大量局部最小值的多参数优化

有啥方法可以选择函数是不是使用默认参数?

Paypal 中定期付款的 IPN 与普通发票付款有啥不同的参数吗?

实际参数、格式参数、虚拟参数以及实际参数和形式参数之间有啥区别? [复制]

向过程传递参数有啥传递和啥传递两种方法,其中啥是VB默认的参数传递方式?