Как вы работаете с большим количеством зависимых услуг и внедрением зависимостей? - PullRequest
0 голосов
/ 19 июня 2011

Я использую Dependency Injection с SOA-подобным приложением.

Например, у меня есть служба голосования, которая используется для голосования как за статью, так и за комментарий.

У меня есть 4 зависимости: статья, комментарий, уровень абстракции базы данных и пользователь, необходимые для голосования.

Итак, мой конструктор должен заполнить 4 аргумента, чтобы получить мой объект.

Я всегда слышал, что более 2/3 аргументов являются предупреждением о неправильной разработке кода, и я могу с этим согласиться.

Может быть, тогда моя служба голосования не очень хорошо разработана.

Возможно, мне придется переместить голосование как в Службе статей, так и в комментариях?

Что вы думаете?


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 ]

4 голосов
/ 19 июня 2011

Я всегда слышал, что более 2/3 аргументов являются предупреждением о неправильном дизайне кода

Это не проблема сама по себе.Это просто показатель потенциальных проблем.

И это правило обычно применимо к открытым функциям-членам, а не к конструкторам.

Такие практические правила могут быть опаснымиесли вы применяете их вслепую.У вас могут быть проблемы, и у вас вообще могут быть проблемы.

Некоторые примеры проблем, которые могут (или могут не ) существовать в вашей архитектуре:

  • Ваша служба голосования делает слишком много, и ее следует разделить
  • Ваша "служба голосования" на самом деле не является собственной логической концепцией, а просто аспектом других концепций в вашей системе
  • Вам не хватает абстрактной концепции (в данном случае это голосование, которое содержит статью, комментарий и пользователя)

Но мне действительно нужно было бы увидеть намного больше вашего кодачтобы сказать вам, если какой-либо из них применяется.Из вашего краткого описания кажется, что ваш сервис прост, и что вы слишком обдумываете проблему.

Я использую Dependency Injection с SOA-подобным приложением.

В приложении SOA у вас будут зависимости, о которых пользователи не должны знать.Не выставляйте их пользователям.В этом случае пользователи не должны знать о DAL.

Один из способов решить эту проблему - это взять верхний слой вашего приложения (тот, в который вы вводите зависимости верхнего уровня), добавив шайбу поверхэто, и только выставить прокладку для пользователя.

См. Шаблон фасада .

Редактировать:

Например, у меня есть служба голосования, которая используется для голосования как за статью, так и за комментарий.... Таким образом, мой конструктор должен заполнить 4 аргумента, чтобы получить мой объект.

Внедрение зависимостей - это не только внедрение в конструктор.Вы также можете вводить зависимости через свойства (или функции-установщики) и во время каждого вызова метода.Вы должны использовать то, что имеет смысл для каждой зависимости.

Вы всегда голосуете одновременно за статью и за комментарий?Вы всегда голосуете за одну и ту же статью и / или один и тот же комментарий?Я предполагаю, что нет, поэтому не передавайте их в конструктор.

Передайте только те зависимости, которые не изменятся между использованиями в конструкторе.Передайте те зависимости, которые меняются при каждом использовании, в списке параметров в вашей функции.Передайте необязательные зависимости через свойства / сеттеры.

В вашем конкретном случае вам, вероятно, следует взять $entityManager в конструкторе, взять $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.Возможно, имеет смысл добавить методы vote в классы ArticleService и CommentService, например, или даже в классы Article или Comment, которые вы не описали.

Если выЕсли вы заинтересованы в обратной связи этого типа (видя, как вам следует реорганизовать весь набор классов), тогда вы должны опубликовать еще один вопрос на http://codereview.stackexchange.com

0 голосов
/ 19 июня 2011

всегда слышал, что более 2/3 аргументов является предупреждением о неправильной разработке кода

Совершенно неверно. Особенно в этом случае.
Вы делаете это правильно (DI). Здесь нет необходимости вносить изменения, 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);
...