Я создаю сайт электронной коммерции, используя C #, MVC3, Entity Framework 4, мой первый опыт MVC3 и Entity Framework, поэтому я хочу обеспечить надежную архитектуру. В частности, я подвергаю сомнению мое использование Интерфейсов и Инверсии Зависимостей, поскольку они относятся к уровням Services и Repository. Для краткости и ясности я сосредоточусь на одной области системы, системе Cart.
Вот пример обращения интерфейса, который PluralSite использует для объяснения типичной тенденции создания интерфейсов без учета надлежащих зависимостей.
Допустим, у вас есть интерфейс IKangaroo, от которого зависит класс "BoxingMatch". Когда вы добавляете больше «боксеров», таких как IMikeTyson и IJoeBoxer, у вас теперь есть три разных интерфейса, по одному для каждого боксера, о которых «BoxingMatch» должен знать. IKangaroo, IMikeTyson и IJoeBoxer имеют только одну конкретную реализацию, что означает, что вам даже не нужны эти интерфейсы (вы также можете сделать BoxingMatch зависимым напрямую от конкретных классов Kangaroo, MikeTyson и JoeBoxer). Кроме того, даже не имеет смысла, что будет несколько реализаций IKangaroo или IMikeTyson. Таким образом, интерфейсы не нужны и не приносят никакой пользы архитектуре.
Инверсия зависимостей в этом примере приведет к тому, что «BoxingMatch» определит интерфейс, который будут использовать классы, которые он собирается использовать (Kangaroo, MikeTyson и JoeBoxer). Таким образом, «BoxingMatch» будет зависеть от интерфейса IBoxer, а Kangaroo, MikeTyson и JoeBoxer будут реализовывать IBoxer. Это инверсия, и она имеет смысл.
Теперь моя ситуация ... В конструкторе CartController введены два параметра зависимости: ICartService и IProductService). CartService принимает один введенный аргумент конструктора (ICartRepository). CartController вызывает AddItem () для CartService, а CartService вызывает AddItem () для CartRepository.
ICartRepository имеет две реализации: CartRepository (в основном веб-проекте) и TestCartRepository (в проекте Tests). ICartService имеет только одну реализацию.
Мои вопросы: как моя архитектура складывается с уроком в приведенном выше примере? Я действительно не понимаю, как мой CartController может быть менее связан, чем он уже есть с CartService. Контроллер зависит только от CartService, а не ICartRepository. Так что не похоже, что я могу инвертировать управление здесь, если CartController определит, какой интерфейс CartService и ICartRepository будут использовать, поскольку CartService и CartRepository полностью разные слои. Я прав?
Вниз на один уровень и тот же вопрос. CartService зависит от CartRepository. Применим ли вышеупомянутый принцип инверсии здесь? Или я уже перевернул зависимость, потребовав внедрить параметр ICartRepository в конструкторе CartService?
Итак, мой вопрос на самом деле: я сделал это "правильно"?
Будем благодарны за любые мысли или советы.
Мой код, для справки:
CartController:
//constructor
public CartController(ICartService cartService, IProductService productService)
{
_cartService = cartService;
_productService = productService;
}
public RedirectToRouteResult AddItem(Cart cart, int productId)
{
var product = _productService.GetProduct(productId);
if (product != null)
{
_cartService.AddItem(cart, product, 1);
}
return RedirectToAction("Index");
}
CartService (реализация):
//constructor
public CartService(ICartRepository repository)
{
_repository = repository;
}
public void AddItem(Cart cart, Product product, int quantity)
{
//simplified for brevity
var cartProduct = _repository.CartProducts().SingleOrDefault(cp => cp.CartId == cart.CartId && cp.ProductId == product.ProductId);
_repository.AddCartItem(cartProduct);
}
Хранилище корзины (реализация):
public void AddCartItem(CartProduct cartProduct)
{
_context.CartProducts.Add(cartProduct);
_context.SaveChanges();
}