PHP: 使用数组键来标识函数参数

PHP: Using array keys to identify function arguments

我用户定义了很多函数,其中一些有六个、十个甚至更多的参数。当我忘记函数的参数是什么,或者它们的顺序时,阅读我的代码会变得困难。我设计了一种方法来处理这个问题,用一个数组替换所有参数,并使用数组键作为标签每个参数。因此,例如,而不是

function MyFunction(string $sSayThis, int $nRepeatTimes, bool $bLoud = $false) {...}

我现在有

function MyFunction(array $args)
   {$sSayThis = $args['sSayThis']); CheckType($sSayThis, 'string');
    $nRepeatTimes = $args['nRepeatTimes']); CheckType($nRepeatTimes, 'int');
    $bLoud = (IsSet($args['bLoud']) ? $args['bLoud'] : false); CheckType($bLoud, 'bool');
    ...
    }

调用此函数,而不是

MyFunction('Hello', 3, true);

现在看起来像

MyFunction(array('sSayThis' => 'Hello', 'nRepeatTimes' => 3, 'bLoud' => true));

当只有三个参数时,这几乎没有必要,如本例所示,但在阅读具有六个或十个参数的函数的代码时,这可能会非常有帮助!另外,如果我只需要为第十个参数传递一个值并在这之前为所有可选参数使用默认值,我可以从调用中省略那些其他参数,而不是为它们传递一系列 , '' .

这是一个 hack,看起来有点丑。但它确实有助于使我的代码自我记录并更易于阅读。

我知道有些 IDE 会给我参数提示,但我使用的是 Notepad++,它不会那样做。

这个想法在去年提出的类似问题 PHP Function Arguments - Use an array or not? 中进行了讨论,但该问题没有显示函数调用的样子,这是问题中最重要的部分。一些人在回答这个问题时说,一个函数永远不需要十个参数,那么多表明设计不佳。我理解这种担忧,但有时算法只需要大量信息。

这种方法有什么问题吗,或者是否有更好的方法来自我记录这些函数调用?

我会解雇你。只是在开玩笑。但说真的,这是一个 svengali。您不应该尝试为已经解决的问题发明一些全新的东西。你会让任何试图阅读你的代码的人感到困惑,并且你会让自己在未来变得毫无用处。这不是基于意见的,因为有标准的方法来处理这个问题。

学习 OOP,尤其是接口。接口定义了对象期望接收的内容的"contract"。 [那些是你一直忘记的输入]。如果您有一个接受 10 个参数的函数,您应该减少逻辑,以便该函数接受具有 10 个属性的 OBJECT。然后从其他对象构建对象。您将剩下 5 个左右 [我假设这些属性以某种方式相关,所以它不会是 10 个对象],只需几行代码即可处理,使其具有很高的可读性。

恕我直言,在代码可读性方面几乎没有任何区别。然而,第二种方法增加了一些新的缺点:

  • 它不再受益于 PHP 类型提示
  • 您的 IDE 无法再使用从代码和注释中解析的信息来提供有用的提示或自动完成

具有大量参数的函数通常表明遗留代码已经超出其设计限制。我认为这需要一些重构,例如:

class Speaker
{
    /**
     * @var string
     */
    private $sayThis;

    /**
     * @var int
     */
    private $repeatTimes;

    /**
     * @var bool
     */
    private $loud;

    /**
     * @param string $sayThis
     */
    public function __construct(string $sayThis)
    {
        $this->sayThis = $sayThis;
    }

    public function times(int $repeatTimes)
    {
        $this->repeatTimes = $repeatTimes;
        return $this;
    }

    public function loud(bool $loud = false)
    {
        $this->loud = $loud;
        return $this;
    }

    public function say()
    {
        $output = str_repeat($this->sayThis, $this->repeatTimes);
        echo $this->loud
            ? mb_strtoupper($output)
            : $output;
    }
}

(new Speaker('Foo'))
    ->times(4)
    ->loud(true)
    ->say();

如你所见,我也去掉了匈牙利符号。