我正在将依赖注入与类似SOA的应用程序一起使用。
例如,我有一个VoteService,用于为Article和Comment投票。
然后我有4个依赖项,文章,评论,数据库抽象层和投票所需的用户。
所以我的构造函数有4个参数来填充以获取我的对象。
我总是听说超过2/3的论点是对错误代码设计的警告,我可能同意这一点。
也许我的VoteService设计得不好。
我可能不得不在文章和文章中移动投票。评论服务?
您怎么看?
class ArticleService {
public function createArticle(); // and other crud methods
}
class VoteService {
public function __construct($entityManager, $articleService, $commentService, $configurationService);
// here is the constructor with much arguments
public function addArticleVote()
{
$vote = new ArticleVote();
$vote->setType(ArticleVote::TYPE_UP)
$vote->setArticle($article);
$this->entityManager->persist($vote);
$this->entityManager->flush();
}
// the same method applies for comment
}
答案 0 :(得分:4)
我总是听说超过2/3的参数是对错误代码设计的警告
这本身并不是问题。它只是潜在问题的一个指标。
此规则通常适用于公共成员函数,而不适用于构造函数。
如果你盲目地应用它们,这样的经验法则会很危险。您可能遇到问题,根本没问题。
您的架构中可能存在(或可能不)的一些问题示例:
但我真的必须看到更多的代码告诉你它们是否适用。从您的简短说明来看,听起来您的服务很简单,并且您过度思考问题。
我正在将依赖注入与类似SOA的应用程序一起使用。
在SOA应用程序中,您将拥有用户不应该了解的依赖项。不要将它们暴露给用户。在这种情况下,用户不应该知道DAL。
解决此问题的一种方法是获取应用程序的顶层(注入顶级依赖项的层),在其上添加垫片,并仅将垫片暴露给用户。
请参阅Facade Pattern。
修改强>
例如,我有一个VoteService,用于为Article和Comment投票。 ...所以我的构造函数有4个参数可以填充以获取我的对象。
依赖注入不仅仅是 构造函数注入。您还可以通过属性(或setter函数)以及每个方法调用期间注入依赖项。你应该使用每个依赖关系中的任何一个。
您是否总是同时对文章和评论进行投票?您是否总是对同一篇文章和/或同一评论进行投票?我的猜测是否定的,所以不要在构造函数中传递它们。
仅传递构造函数中使用之间不会更改的依赖项。在函数的参数列表中传递每次使用时更改的依赖项。通过properties / setters传递可选的依赖项。
在您的特定情况下,您应该在构造函数中使用$entityManager
,在构造函数或setter中取$configurationService
(取决于它是否可以在没有依赖项的情况下生存),取$articleService
方法中的addArticleVote
,并使用$commentService
方法中的addCommentVote
。
class VoteService {
public function __construct($entityManager);
// Adding this in case you have sensible logic if it isn't present.
// If it isn't optional (you don't have defaults that make sense to put in this class),
// then put it back in the ctor
public function setConfigurationService($configurationService)
{
// ...
}
public function addArticleVote($articleService) // or $article
{
// ...
}
public function addCommentVote($commentService) // or $comment
{
// ...
}
}
也许我的VoteService设计得不好。
我会评估你是否应该VoteService
。例如,在vote
和ArticleService
类上添加CommentService
方法,或者甚至在您没有的Article
或Comment
类上添加{{1}}方法可能是有意义的描述
如果您对此类型的反馈感兴趣(了解您应该如何重构整套课程),那么您应该在http://codereview.stackexchange.com上发布另一个问题
答案 1 :(得分:0)
总是听说超过2/3的参数是对错误代码设计的警告
完全错误。特别是在这种情况下 你正在以正确的方式(DI)。这里不需要改变imo。
我可能不得不在文章和文章中移动投票。评论服务?
这可能是另一种解决方案。但你可以自由地留在这个imo
如果要实现此解决方案,可以使用方法IVotable
创建接口addVote
。
此时,您可以在Articles/Comments
课程中实现此界面,以便您可以:
$a = new Article;
$b = new Comment;
$a->addVote($currentLoggedUser,10); //> Inject only loggedUser (and maybe your DAL)
$b->addVote($currentLoggedUser,10);