你如何使用很多依赖服务和依赖注入?

时间:2011-06-19 00:06:39

标签: php dependency-injection soa

我正在将依赖注入与类似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
}

2 个答案:

答案 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。例如,在voteArticleService类上添加CommentService方法,或者甚至在您没有的ArticleComment类上添加{{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);