我是否在 Laravel 控制器中使用静态方法将自己设置为失败?
Am I setting myself up for failure using a static method in a Laravel Controller?
我对 OOP 很陌生,所以这确实是一个基本的 OOP 问题,在 Laravel 控制器的上下文中。
我正在尝试创建一个通知系统系统,当某些其他对象被创建、编辑、删除等时,它会创建 Notification
对象。因此,例如,如果 User
被编辑,然后我想生成关于此编辑的 Notification
。按照这个例子,我创建了 UserObserver
,它在保存 User
时调用 NotificationController::store()
。
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
NotificationController::store($data);
}
}
为了完成这项工作,我必须将 NotificationController::store()
设为静态。
class NotificationController extends \BaseController {
public static function store($data)
{
// validation omitted from example
$notification = Notification::create($data);
}
我对 static
的含义只是模糊地了解,所以我在这里所做的事情很可能存在内在错误,但这似乎或多或少地完成了工作。但是,我读过的所有内容都表明静态函数 通常 不好的做法。我在这里做的是 "wrong," 吗?我怎样才能做得更好?
我将有几个其他观察者 类 需要调用相同的 NotificationController::store()
,并且我希望 NotificationController::store()
处理 $data
的任何验证。
我刚刚开始学习单元测试。我在这里所做的会不会对测试造成任何困难?
我在这里广泛地写了关于静力学的文章:How Not To Kill Your Testability Using Statics。适用于您的情况的要点如下:
静态函数调用 couple 代码。无论出于何种原因,都不可能 用其他任何东西替换 静态函数调用或 跳过 这些调用。 NotificationController::store()
本质上与 substr()
属于相同的 class 事物。现在,您可能不想用其他任何东西替换对 substr
的调用;但是有很多原因让您现在或以后可能想要替换 NotificationController
。
单元测试只是一个非常明显的用例,其中非常需要替换。如果你想单独测试 UserObserver::saved
函数,因为它包含一个复杂的算法,你需要用所有可能的输入来测试它以确保它正常工作,你不能将该算法与对 [=12= 的调用分离].而该函数可能会依次调用一些 Model::save()
方法,该方法又想与数据库对话。您需要设置所有其他不相关代码所需的整个环境(并且可能包含也可能不包含其自身的错误),基本上不可能单独测试这个功能。
如果您的代码看起来更像这样:
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
$this->NotificationController->store($data);
}
}
好吧,$this->NotificationController
显然是一个可以在某些时候被替换的变量。大多数情况下,该对象会在您实例化 class:
时注入
new UserObserver($notificationController)
您可以简单地注入一个允许调用任何方法的模拟对象,但它什么也不做。然后您可以单独测试 UserObserver::saved()
并确保它实际上没有错误。
一般来说,使用依赖注入代码可以使您的应用程序更加灵活,并允许您将其拆分。这对于单元测试是必要的,但在以后你现在甚至无法想象的场景中也会派上用场,但是从现在开始半年后你会被难住,因为你需要为你想要的一些新功能重构你的应用程序实施。
警告:我从未写过一行 Laravel 代码,但据我所知,它 确实 支持某种形式的依赖注入。如果确实如此,您绝对应该使用该功能。否则,请非常清楚您的代码的哪些部分与其他部分耦合,以及这将如何影响您以后将其拆分和重构的能力。
我对 OOP 很陌生,所以这确实是一个基本的 OOP 问题,在 Laravel 控制器的上下文中。
我正在尝试创建一个通知系统系统,当某些其他对象被创建、编辑、删除等时,它会创建 Notification
对象。因此,例如,如果 User
被编辑,然后我想生成关于此编辑的 Notification
。按照这个例子,我创建了 UserObserver
,它在保存 User
时调用 NotificationController::store()
。
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
NotificationController::store($data);
}
}
为了完成这项工作,我必须将 NotificationController::store()
设为静态。
class NotificationController extends \BaseController {
public static function store($data)
{
// validation omitted from example
$notification = Notification::create($data);
}
我对 static
的含义只是模糊地了解,所以我在这里所做的事情很可能存在内在错误,但这似乎或多或少地完成了工作。但是,我读过的所有内容都表明静态函数 通常 不好的做法。我在这里做的是 "wrong," 吗?我怎样才能做得更好?
我将有几个其他观察者 类 需要调用相同的 NotificationController::store()
,并且我希望 NotificationController::store()
处理 $data
的任何验证。
我刚刚开始学习单元测试。我在这里所做的会不会对测试造成任何困难?
我在这里广泛地写了关于静力学的文章:How Not To Kill Your Testability Using Statics。适用于您的情况的要点如下:
静态函数调用 couple 代码。无论出于何种原因,都不可能 用其他任何东西替换 静态函数调用或 跳过 这些调用。 NotificationController::store()
本质上与 substr()
属于相同的 class 事物。现在,您可能不想用其他任何东西替换对 substr
的调用;但是有很多原因让您现在或以后可能想要替换 NotificationController
。
单元测试只是一个非常明显的用例,其中非常需要替换。如果你想单独测试 UserObserver::saved
函数,因为它包含一个复杂的算法,你需要用所有可能的输入来测试它以确保它正常工作,你不能将该算法与对 [=12= 的调用分离].而该函数可能会依次调用一些 Model::save()
方法,该方法又想与数据库对话。您需要设置所有其他不相关代码所需的整个环境(并且可能包含也可能不包含其自身的错误),基本上不可能单独测试这个功能。
如果您的代码看起来更像这样:
class UserObserver extends BaseObserver
{
public function saved($user)
{
$data = [
// omitted from example
];
$this->NotificationController->store($data);
}
}
好吧,$this->NotificationController
显然是一个可以在某些时候被替换的变量。大多数情况下,该对象会在您实例化 class:
new UserObserver($notificationController)
您可以简单地注入一个允许调用任何方法的模拟对象,但它什么也不做。然后您可以单独测试 UserObserver::saved()
并确保它实际上没有错误。
一般来说,使用依赖注入代码可以使您的应用程序更加灵活,并允许您将其拆分。这对于单元测试是必要的,但在以后你现在甚至无法想象的场景中也会派上用场,但是从现在开始半年后你会被难住,因为你需要为你想要的一些新功能重构你的应用程序实施。
警告:我从未写过一行 Laravel 代码,但据我所知,它 确实 支持某种形式的依赖注入。如果确实如此,您绝对应该使用该功能。否则,请非常清楚您的代码的哪些部分与其他部分耦合,以及这将如何影响您以后将其拆分和重构的能力。