【问题标题】:PHP Return strategy. One single type or more?PHP 返回策略。一种或多种?
【发布时间】:2018-12-04 09:33:20
【问题描述】:

我已经构建了大型 php 应用程序,但我知道问自己一个问题:函数是否应该只返回一种数据类型和 null 或者是否可以返回更多数据类型。因为它现在不知何故开始觉得重新调整一个以上的数据类型(除了 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。我这样做了。但由于我返回多个空值,我无法获得具体信息,为什么它在我调用该函数的地方返回空值。或者这可能表明该功能违反了诸如关注点分离原则之类的东西?我还有其他类似的情况,所以请不要太具体地解决这个特定的功能。

【问题讨论】:

    标签: php design-patterns architecture return-type


    【解决方案1】:

    在 PHP 中函数返回多个类型是正常的。 strpos 就是一个例子。它返回一个整数或布尔值。您必须准备好区分整数零或布尔假。

    【讨论】:

      【解决方案2】:

      只返回一种类型并在某些情况下无法返回该类型时抛出异常是很有意义的。在其他情况下,返回 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;
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-03
        • 1970-01-01
        • 2014-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多