用于消除 Symfony2 中重复代码的特性、辅助服务或继承
Traits, helper service or inheritance for eliminating repetitive code in Symfony2
我正在尝试清理一个旧的 Symfony2 项目,其中大部分代码都在控制器中。控制器中长而重复的代码块不是最佳选择,它使调试和开发非常乏味且容易出错。
有很多东西我可以轻松清理并转移到服务中,因为这些代码块提供了某种可重用的功能。我知道任何明确定义的任务都应该存在于服务中,而控制器应该只是 "wiring".
但无论我将代码移到哪里,总会有重复的小块把一切搞得一团糟。例如 initialization/transformation/parsing/filtering 模式,在我们的应用程序中广泛使用。
以创建DataTable需要的数据"kneading"为例:
class DefaultController extends Controller {
public function indexAction() {
$data = array(/* some data */);
$encoders = array(new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$datatable = $this->get('datatables.orders');
$datatable->buildDatatableView();
$datatable->setData($serializer->serialize($data, 'json'));
return array('datatable'=>$datatable);
}
}
这是一种非常常见但也非常冗长的模式。我们的开发人员倾向于将数十种此类小模式存储在他们自己计算机上的文本文件中,并且通常 copy/paste 将它们存储到控制器中。
如果我想出使代码更简洁(和 DRY)的解决方案,有多种选择。
- 我可以从所有操作中过滤出重复模式并将它们转储到私有函数中。我在某些地方这样做是为了让事情更清楚一些,但这是一个针对每个控制器本地化的糟糕解决方案。
- 我可以用所有这些代码片段创建一个或多个通用的 "helper" classes,并且
use
当我在服务或控制器中需要它们时,它们包含各种parsing/checking/filtering/building 函数。不过,它可能会变成微小的不相关方法的垃圾收集。
- 我可以创建一个或多个抽象 classes,其中 properties/methods 在许多 services/controllers 中使用,并从中继承。感觉很老套,尤其是当我需要将它夹在用户定义的控制器和 Symfony 框架控制器之间时 class。
- 我可以为这些数据转换函数定义特征,并在适用的地方使用它们。人们经常声称 PHP 特质几乎总是不好的。然而,traits 对我来说似乎是最不滥用和最简洁的选择。
考虑一下:
Bundle/Traits/TableTrait.php
Trait TableTrait {
function serialize($data, $format){
$encoders = array(new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
return $serializer->serialize($data, $format);
}
function buildTable($table, $data){
$datatable = $table;
$datatable->buildDatatableView();
$datatable->setData($this->serialize($data, 'json'));
}
}
Bundle/Controller/SomeController.php
class DefaultController extends Controller {
use \Bundle\Traits\TableTrait;
public function indexAction() {
$data = array(/* some data */);
$datatable = $this->buildTable($this->get('datatables.orders'),$data);
return array('datatable'=>$datatable);
}
}
将 6 行样板文件减少到 1 行。
Traits 是一个不好的解决方案吗?
如果是这样,哪个选项会更好?
您可能会考虑将一些东西转移到服务中。例如:
$serializer = $this->get('json.getset.serializer');
并可能制作数据 table 工厂服务
$dataTable = $this->get('datatable.orders.factory')->create($data);
您甚至可以更进一步,将您的控制器定义为服务,然后注入所需的依赖项。所以你最终会得到:
$dataTable = $this->dataTableFactory->create($data);
我正在尝试清理一个旧的 Symfony2 项目,其中大部分代码都在控制器中。控制器中长而重复的代码块不是最佳选择,它使调试和开发非常乏味且容易出错。
有很多东西我可以轻松清理并转移到服务中,因为这些代码块提供了某种可重用的功能。我知道任何明确定义的任务都应该存在于服务中,而控制器应该只是 "wiring".
但无论我将代码移到哪里,总会有重复的小块把一切搞得一团糟。例如 initialization/transformation/parsing/filtering 模式,在我们的应用程序中广泛使用。
以创建DataTable需要的数据"kneading"为例:
class DefaultController extends Controller {
public function indexAction() {
$data = array(/* some data */);
$encoders = array(new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$datatable = $this->get('datatables.orders');
$datatable->buildDatatableView();
$datatable->setData($serializer->serialize($data, 'json'));
return array('datatable'=>$datatable);
}
}
这是一种非常常见但也非常冗长的模式。我们的开发人员倾向于将数十种此类小模式存储在他们自己计算机上的文本文件中,并且通常 copy/paste 将它们存储到控制器中。
如果我想出使代码更简洁(和 DRY)的解决方案,有多种选择。
- 我可以从所有操作中过滤出重复模式并将它们转储到私有函数中。我在某些地方这样做是为了让事情更清楚一些,但这是一个针对每个控制器本地化的糟糕解决方案。
- 我可以用所有这些代码片段创建一个或多个通用的 "helper" classes,并且
use
当我在服务或控制器中需要它们时,它们包含各种parsing/checking/filtering/building 函数。不过,它可能会变成微小的不相关方法的垃圾收集。 - 我可以创建一个或多个抽象 classes,其中 properties/methods 在许多 services/controllers 中使用,并从中继承。感觉很老套,尤其是当我需要将它夹在用户定义的控制器和 Symfony 框架控制器之间时 class。
- 我可以为这些数据转换函数定义特征,并在适用的地方使用它们。人们经常声称 PHP 特质几乎总是不好的。然而,traits 对我来说似乎是最不滥用和最简洁的选择。
考虑一下:
Bundle/Traits/TableTrait.php
Trait TableTrait {
function serialize($data, $format){
$encoders = array(new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
return $serializer->serialize($data, $format);
}
function buildTable($table, $data){
$datatable = $table;
$datatable->buildDatatableView();
$datatable->setData($this->serialize($data, 'json'));
}
}
Bundle/Controller/SomeController.php
class DefaultController extends Controller {
use \Bundle\Traits\TableTrait;
public function indexAction() {
$data = array(/* some data */);
$datatable = $this->buildTable($this->get('datatables.orders'),$data);
return array('datatable'=>$datatable);
}
}
将 6 行样板文件减少到 1 行。
Traits 是一个不好的解决方案吗? 如果是这样,哪个选项会更好?
您可能会考虑将一些东西转移到服务中。例如:
$serializer = $this->get('json.getset.serializer');
并可能制作数据 table 工厂服务
$dataTable = $this->get('datatable.orders.factory')->create($data);
您甚至可以更进一步,将您的控制器定义为服务,然后注入所需的依赖项。所以你最终会得到:
$dataTable = $this->dataTableFactory->create($data);