PHP返回策略。一种或多种?

时间:2018-06-25 18:22:04

标签: php design-patterns architecture return-type

我已经建立了大型的php应用程序,但是我知道要问自己一个问题:一个函数是否应该只返回一种数据类型,并且返回null还是可以返回更多数据类型?因为某种原因现在它开始变得不想要重新调整一个以上的数据类型(空值除外),因为它邀请您在函数调用后编写如下代码:

if(is_array($returnVariable)) { 
    // do something
} else if(is_int($returnVarable)) { 
    // do something else
}

从逻辑上讲,仅从函数返回一件事或什么都不返回似乎是更合逻辑的,因为您不必到处乱写if和else的代码。但是我可能会完全离开。以这个功能为例:

public function update(array $data, Model $user)
{
    if(!is_a($user, User::class)) return null;

    //Update the user
    $user->fill($data);

    //Send the user an activated notification if it was activated and it was not earlier.
    if($user->getOriginal('activated') == 0 && $user->activated == 1) {
        $user->activated_at = Carbon::now()->toDateTimeString();
        $user->notify(new ActivatedUserNotification($user));
    }

    $saved = $user->save();

    //User was not updated because of an error
    if(!$saved) return null;

    //User was successfully updated. Return the user
    return $user;
}

我实际上想返回一件事或为空。而我这样做。但是由于我返回多个null,所以我无法获得特定信息,为什么它在我调用该函数的地方返回null。还是这表明功能违反了关注分离原则?我还遇到其他类似情况,因此在解决此特定功能时请不要太具体。

2 个答案:

答案 0 :(得分:1)

在PHP中,函数返回多个类型是正常的。 strpos是一个示例。它返回一个整数或布尔值。您必须准备知道整数零或布尔假之间的区别。

答案 1 :(得分:1)

仅返回一种类型并在某些情况下无法返回该类型时抛出异常是很有意义的。在其他情况下,返回null或该类型更有意义。

如果您使用的是PHP 7,则可以declare a return type像这样...

function sum($a, $b): float {
    return $a + $b;
}

这可以帮助您确保函数没有做太多事情,并且可以更轻松地使用类的API。

虽然确实有限制。 PHP中还没有co/contra variance,所以在某些情况下(如接口),类型提示实际上会阻碍API的简化。此外,在某些情况下,您可能想使用generic作为返回类型。这些也不是PHP的一部分,因此,如果您想使用泛型作为类型提示,则现在必须没有该类型提示。

您似乎已经注意到使用返回类型的某些好处以及使用参数类型的好处。

键入参数的使用非常明显:它降低了函数的复杂性,并使它倾向于做一件简洁的事情。

在我看来,使用返回类型具有相同的作用...但是,它并没有降低方法内部的复杂性,而是降低了执行该方法的代码的复杂性...这可能更重要,因为复杂调用该方法的代码将需要处理整个地方的变量返回类型。

简单的例子...

function add($a, $b) {
  if (is_string($a) && is_string($b)) {
    return $a . $b;
  } else if (is_int($a) && is_int($b)) {
    return $a + $b;
  }
}

此函数不键入其参数,因此我们需要考虑其常见用例并处理函数中的不同参数类型。这使我们的功能失去了重点,我们将永远不会发现所有可能的情况,这意味着该功能可能会破裂然后扩大范围。

我们也不知道返回类型是什么,所以在函数被使用的任何地方,我们都需要考虑一下...

$result = add($a, $b);
if (is_string($result)) {
  // Do something
} else if (is_int($result)) {
  // Do something else
}

我们可以解决此问题:

function add(Int $a, Int $b) : Int {
    return $a + $b;
}
function concatStrings(String $a, String $b) : String {
    return $a . $b;
}

现在无论在哪里使用这些功能,类型检查逻辑都将消失。我们的功能更短,更简单,每个人都知道如何使用它们以及应该做什么。测试它们也变得更加容易。