SRP原则(一种责任原则)是编写支持代码的基本原则之一。在本文中,我将通过PHP语言和Laravel框架示例演示如何应用此原理。通常,在描述MVC开发模型时,会给控制器分配不合理的大任务。获取参数,业务逻辑,授权和响应。当然,在文章和书籍中将其作为示例进行描述,但通常被认为是工作项目中采取行动的呼吁。这样的方法将不可避免地导致类的增长不受控制,并使代码支持大大复杂化。分担责任原则
举个例子,我们将采用比较粗略但经常遇到的“ thick”控制器类型。class OrderController extends Controller
{
public function create(Request $request)
{
$rules = [
'product_id' => 'required|max:10',
'count' => 'required|max:10',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json($validator->errors(), 400);
}
$order = Order::create($request->all());
return response()->json($order, 201);
}
}
在此示例中,很明显,控制员对“下订单”了解得太多,还承担了通知买方和保留货物的任务。我们将努力确保控制器仅需控制整个过程,而无需业务逻辑。首先,我们将在单独的Request类中验证参数。class OrderRequest extends Request
{
public function rules(): array
{
return [
'product_id' => 'required|max:10',
'count' => 'required|max:10',
];
}
}
并将所有业务逻辑移至OrderService类public class OrderService
{
public function create(array $params)
{
$sms = new RuSms($appId);
$sms->send($number, $text);
}
}
使用服务容器,我们将在控制器中实现我们的服务。结果,我们有了一个“瘦”控制器。class OrderController extends Controller
{
protected $service;
public function __construct(OrderService $service)
{
$this->service = $service;
}
public function create(OrderRequest $request)
{
$this->service->create($request->all());
return response()->noContent(201);
}
}
已经更好了。所有业务逻辑都已移交给服务。控制器仅知道OrderRequest和OrderService类 -完成其工作所需的最少信息集。但是现在我们的服务也需要重构。让我们拿出发送短信到一个单独的类的逻辑。class SmsRu
{
protected $appId;
public function __constructor(string $appId)
{
$this->appId = $appId;
}
public function send($number, $text): void
{
}
}
并通过构造函数实现class OrderService
{
private $sms;
public function __construct()
{
$this->sms = new SmsRu($appId);
}
public function create(array $params): void
{
$this->sms->send($nubmer, $text);
}
}
已经更好了,但是OrderService类仍然对发送消息了解得太多。将来我们可能需要替换消息传递提供程序或添加单元测试。我们通过添加SmsSender接口继续重构,并通过SmsServiceProvider提供程序指定SmsRu 。interface SmsSenderInterface
{
public function send($number, $text): void;
}
class SmsServiceProvider implements ServiceProviderInterface
{
public function register(): void
{
$this->app->singleton(SmsSenderInterface::class, function ($app) {
return new SmsRu($params['app_id']);
});
}
}
现在,该服务也摆脱了不必要的细节class OrderService
{
private $sms;
public function __construct(SmsSenderInterface $sms)
{
$this->sms = $sms;
}
public function create(): void
{
$this->sms->send($nubmer, $text);
}
}
事件驱动架构
发送消息不是基本订单创建过程的一部分。不管发送的消息如何,都会创建订单,也有可能在将来添加取消短信通知的选项。为了不使OrderService带有不必要的通知详细信息,可以使用Laravel Observers。一个类,它将跟踪具有我们Order模型的某些行为的事件,并为其分配所有客户通知逻辑。class OrderObserver
{
private $sms;
public function __construct(SmsSenderInterface $sms)
{
$this->sms = $sms;
}
public function created(Order $order)
{
$this->sms->send($nubmer, $text);
}
不要忘记在AppServiceProvider中注册OrderObserver。结论
我知道我在这篇文章中描述的是相当平庸的事情,但是我想展示如何在Laravel框架上实现这一原理。SPR原则是最重要的原则之一,为其余部分铺平了道路。需要使用它,尤其是因为Laravel框架提供了所有必需的工具。