InversionOfControl in the new MVC3 project

I am building an e-commerce site using C #, MVC3, Entity Framework 4, my first hit in MVC3 and Entity Framework, so I want to provide a sound architecture. In particular, I ask a question about my use of interfaces and dependency inversion, as they relate to service and repository tiers. I will focus on one area of ​​the system, the Cart system, for brevity and clarity.

Here, the PluralSite interface inversion example is used to explain a typical trend for creating interfaces without taking into account the corresponding dependencies.

Suppose you have an IKangaroo interface, on which the BoxingMatch class depends. When you add more “boxers,” such as IMikeTyson and IJoeBoxer, you now have three different interfaces, one for each boxer you need to know about “BoxingMatch”. IKangaroo, IMikeTyson, and IJoeBoxer have only one specific implementation, which means you don’t even need these interfaces (you can also make BoxingMatch directly dependent on specific Kangaroo, MikeTyson, and JoeBoxer classes). Also, it doesn't even make sense that there would be more than one implementation of IKangaroo or IMikeTyson. Thus, interfaces are useless and do not add any value to the architecture.

Inverting the dependencies in this example will cause BoxingMatch to define the interface that the classes it intends to use (Kangaroo, MikeTyson, and JoeBoxer). Thus, “BoxingMatch” will depend on the IBoxer interface, and Kangaroo, MikeTyson and JoeBoxer will implement IBoxer. There is an inversion, and that makes sense.

Now my situation ... The CartController constructor has two dependency parameters entered, ICartService and IProductService). CartService takes one argument of the constructor constructor (ICartRepository). CartController calls AddItem () on the CartService, and CartService calls AddItem () on the CartRepository.

ICartRepository has two implementations: CartRepository (in the main web project) and TestCartRepository (in the Tests project). ICartService has only one implementation.

My questions are: how does my architecture stack up before the lesson in the above example? I really don’t see how my CartController may be less connected than it is with CartService. The controller depends only on CartService, and not on ICartRepository. Therefore, it seems to me that I cannot invert the control here if the CartController determines which interfaces CartService and ICartRepository will be used, since CartService and CartRepository are completely different. Am I right?

One level and the same question. CartService is dependent on CartRepository. Does the aforementioned inversion principle apply here? Or have I already inverted the dependency, requiring the parameter ICartRepository entered in the CartService constructor?

So, my question is actually, did I do it “right”?

Any thoughts or advice would be appreciated.

My code is for reference:

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 (implementation):

 //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); } 

Cart repository (implementation):

 public void AddCartItem(CartProduct cartProduct) { _context.CartProducts.Add(cartProduct); _context.SaveChanges(); } 
+4
source share
2 answers

You mistakenly believe that the only reason for using IoC is to provide multiple implementations. In fact, this is one of the least useful reasons for using IoC.

Using the IoC container, you can control the lifetime of the object (for example, by making the objects live during one web request).

The IoC container also handles recursive dependencies. If you create IMikeTyson and IMikeTyson depends on IBoxingShorts, then you do not need to create instances of boxing shorts, they are free.

All of this ignores the big reason for using IoC, and it makes unit testing easier. Using the interfaces, you can provide an IMikeTysons layout for your BoxingMatch unit tests so that you can accumulate known BoxingMatch values ​​and not have to reset your database after each test.

And there are about 100 other benefits that IoC and front-end programming bring to the table.

I think you are thinking too much about your scenario in the basket. You just need to pass the instances you depend on, and don’t worry too much about the academic definition of IoC.

+4
source

This probably does not answer all your questions, but if at some point you intend to separate the process between the levels of the controller and the service, for example. using WCF, your * Services self will become WCF services - this will strengthen the decision to connect layers through interfaces, rather than directly related to classes.

In this case, you can add an additional facade / direction, often called a service agent, through which the "exact" SOA service interfaces are hidden from the controller. This would replace the service level of one of the similar functions, but using various service interfaces.

Your inversion looks great: your layers depend on abstraction (interfaces) and hide the implementation, therefore * The service will not know that the repository uses Entity Framework, NHibernate or DataSets, and will not know that the service level used the repository or directly accessed the database data (injection constructors will not be displayed on the interfaces consumed by clients of the layer, so there is no need to worry here).

+1
source

Source: https://habr.com/ru/post/1384845/


All Articles