Мы разрабатываем проект 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. и консолидирует зависимости больше.
Спасибо за Ваши мысли!
Если большинство ваших классов в зависимости от этих трех интерфейсов вы можете передать объект, который объединяет их вместе, НО: если большинство классов просто зависят от одного или двух из них, то это не лучшая идея, поскольку эти классы будут иметь доступ к объектам, которые им не нужны и у них нет дела, и некоторые программисты всегда будут вызывать код, который они не должны вызывать, только потому, что он доступен.
Кстати, это не фабрика, если только вы не всегда создаете новый объект в методах Get [...] Service (), а делать это просто для передачи нескольких методов - плохо. Я бы просто назвал его ServiceWrapper и превратил бы их в свойства EmployeeService, DepartmentService и OrderService.
Один из аргументов против этого состоит в том, что это не проясняет ваши зависимости. Это показывает, что вы зависите от «некоторых вещей в сервисной фабрике», но не от того, какие услуги. В целях рефакторинга может быть полезно точно знать, что от чего зависит.
Внедрение зависимостей должно упростить такие вещи, если вы используете соответствующую структуру - это должно быть просто вопросом создания правильного конструктора, определения того, что реализует какой интерфейс, и разрешения сортировки все вышло.
Такая фабрика по сути является локатором служб , и я считаю ее анти-шаблоном , потому что она скрывает ваши зависимости и упрощает нарушение единственной ответственности Принцип (SRP).
Одно из многих замечательных преимуществ, которые мы получаем от Constructor Injection , заключается в том, что он делает нарушения SRP настолько очевидными .