参考此评论,
当一个类有很长的参数列表时,它可以是一个“代码 闻到“你的班级试图做太多而且可能不做 遵循单一责任原则。如果你的班级正在尝试 要做太多,请考虑将您的代码重构为多个 彼此消耗的小班。
我应该怎么做下面这个控制器类 - 它是“试图做太多”?
class Controller
{
public $template;
public $translation;
public $auth;
public $article;
public $nav;
public function __construct(Database $connection, $template)
{
$this->template = $template;
$this->translation = new Translator($connection);
$this->nav = new Nav($connection);
$this->article = new Article($connection);
$this->auth = new Auth($connection);
}
public function getHtml()
{
if(isset($_REQUEST['url']))
{
$item = $this->article->getRow(['url' => 'home','is_admin' => $this->auth->is_admin]);
include $this->template->path;
}
}
}
如何将它分解为更小的类 - 如果它是一个控制器,它包含我需要输出页面的这些基本类?
我该怎么做才能遵循dependency injection的原则?
答案 0 :(得分:1)
注意:这将是简短版本,因为我正在工作。我将在晚上详细说明
所以...你的代码有以下违规行为:
SRP (以及扩展名 - SoC):您的控制器负责验证输入,授权,数据收集,使用数据填充模板以及渲染所述模板。此外,您的Article
似乎对数据库抽象和域逻辑负责。
LoD :您只传递$connection
,因为您需要将其传递给其他结构。
封装:您的所有类属性都具有公开可见性,并且可以随时更改。
依赖注入:当你的"控制器"有几个直接的依赖关系,你只是传递模板(实际上不应该由适当的MVC中的控制器管理)。
全局状态:您的代码取决于$_REQUEST
超全局。
松散耦合:您的代码直接绑定到类的名称和这些类的构造函数的足迹,您在构造函数中初始化。
答案 1 :(得分:0)
TL; DR:我在这里看不到违反SRP的情况,但是对象构成有点破坏
从我看到的(这是完整的类列表?),$connection
不会直接在类中使用,因此不应该注入它。
我在任何地方都看不到$this->translation
和$this->nav
的使用情况。这是一个复制粘贴工件吗?
而是注入$connection
,我会在这个类之外构造Article
和Auth
,然后只注入这些,因为你的控制器只直接使用这些,而不是控制器。
所以整个班级都是这样的:
class Controller
{
private $article;
private $auth;
private $template;
public function __construct(Article $article, Auth $auth, $template)
{
$this->article = $article;
$this->auth = $auth;
$this->template = $template;
}
public function getHtml()
{
if(isset($_REQUEST['url']))
{
$item = $this->article->getRow(['url' => 'home','is_admin' => $this->auth->is_admin]);
include $this->template->path;
}
}
}
除非你的Article
是具有ActiveRecord模式的域对象,否则在这种情况下我仍会注入$connection
并将其存储在本地变量中。并且仅在您确实需要时创建新的Article
对象,即在getHtml
方法中。
这样你在构造函数中不做太多工作,只分配局部变量。对象组合在其他地方处理。如果需要,您可以替换Auth
的实施。
此外,当您在构造函数中没有做太多工作时,您的对象图创建非常便宜。如果你使用某种DI容器,这很重要,因为必须同时创建很多对象。