Почему бы не объединить все классы обслуживания в метод Factory (вместо введения интерфейсов)? - PullRequest
11 голосов
/ 25 марта 2010

Мы создаем проект ASP.NET и инкапсулируем всю нашу бизнес-логику в классы обслуживания. Некоторые из них находятся в доменных объектах, но обычно они довольно анемичны (из-за того, что мы используем ORM, это не изменится). Чтобы лучше включить модульное тестирование, мы определяем интерфейсы для каждого сервиса и используем D.I .. Например. вот пара интерфейсов:

IEmployeeService
IDepartmentService
IOrderService
...

Все методы в этих сервисах - это, в основном, группы задач, и классы не содержат закрытых переменных-членов (кроме ссылок на зависимые сервисы). Прежде чем беспокоиться о модульном тестировании, мы просто объявили бы все эти классы как статические и попросили бы их вызывать друг друга напрямую. Теперь мы настроим класс следующим образом, если сервис зависит от других сервисов:

public EmployeeService : IEmployeeService
{
   private readonly IOrderService _orderSvc;
   private readonly IDepartmentService _deptSvc;
   private readonly IEmployeeRepository _empRep;

   public EmployeeService(IOrderService orderSvc
                        , IDepartmentService deptSvc
                        , IEmployeeRepository empRep)
   {
      _orderSvc = orderSvc;
      _deptSvc = deptSvc;
      _empRep = empRep;
   }
   //methods down here
}

Это обычно не проблема, но мне интересно, почему бы не создать фабричный класс, который мы вместо этого раздаем?

т.е.

public ServiceFactory
{
   virtual IEmployeeService GetEmployeeService();
   virtual IDepartmentService GetDepartmentService();
   virtual IOrderService GetOrderService();
}

Тогда вместо звонка:

_orderSvc.CalcOrderTotal(orderId) 

мы бы позвонили

_svcFactory.GetOrderService.CalcOrderTotal(orderid)

В чем недостаток этого метода? Это все еще проверяемое, оно все еще позволяет нам использовать D.I. (и обрабатывать внешние зависимости, такие как контексты базы данных и отправители электронной почты через D.I. внутри и за пределами фабрики), и это устраняет большую часть D.I. настроить и консолидировать зависимости подробнее.

Спасибо за ваши мысли!

Ответы [ 3 ]

4 голосов
/ 25 марта 2010

Один аргумент против этого заключается в том, что это не проясняет ваши зависимости. Это показывает, что вы зависите от «некоторых вещей на фабрике сервисов», но не от каких сервисов. Для целей рефакторинга может быть полезно точно знать, что и от чего зависит.

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

3 голосов
/ 25 марта 2010

Такая фабрика, по сути, Service Locator , и Я считаю это анти-паттерном , потому что он скрывает ваши зависимости и позволяет очень легко нарушить Single Responsibility Принцип (SRP).

Одно из многих замечательных преимуществ, которые мы получаем от Инъекции конструктора , заключается в том, что делает нарушения SRP настолько очевидными .

2 голосов
/ 25 марта 2010

Если большинство ваших классов зависят от этих трех интерфейсов, вы можете передать объект, который их объединяет, НО: если большинство классов зависят только от одного или двух из них, то это не очень хорошая идея, поскольку эти классы будут иметь доступ к объектам, в которых они не нуждаются, и с которыми у них нет бизнеса, и некоторые программисты всегда будут вызывать код, который они не должны вызывать только потому, что он доступен.

Кстати, это не фабрика, если вы всегда не создаете новый объект в методах Get [...] Service (), а делать это просто для передачи нескольких методов плохо. Я бы просто назвал его ServiceWrapper и превратил их в свойства EmployeeService, DepartmentService и OrderService.

...