I am currently trying to learn the benefits of using an IoC container and familiarize myself with the DI. I started using StructureMap as it seems quite simplistic and yet powerful.
I want to check if I understand these concepts correctly. Let us assume the following rudimentary classes in the application (details for brevity):
public class OrderService : IOrderService { private IOrderRepository _repository; private ITaxCalculator _taxCalculator; private IShippingCalculator _shippingCalculator; public OrderService(IOrderRepository repository, ITaxCalculator taxCalculator, IShippingCalculator shippingCalculator) { this._repository = repository; this._shippingCalculator = shippingCalculator; this._taxCalculator = taxCalculator; } public IOrder Find(int id) { return this._repository.Find(id); } } public class OrderRepository : IOrderRepository { public IOrder Find(int id) {
First of all, the principle of dependency inversion states that since the OrderService is a “high-level” module, it will not depend on the details of the implementation of anything of a lower level, it should just have references to these classes and be able to ask them to do their job without knowing what it does, and the consumer code must be responsible for creating and passing these pre-configured modules. It is right? Therefore, the DI keeps these classes loosely coupled, so they don’t need to know exactly how the method is called for this dependency, just so that it is called and does whatever it needs, the OrderService does not care if it requests the Repository XML or uses NHibernate or EF or even raw DataSets; he just knows that he can call the repository, tell him to find the order with identifier 42, and the repository will know what to do.
I also understand that the IoC container, StructureMap in this case provides benefits, without forcing us to make sure that we create all these dependencies manually and pass them. For example, the main method of a trivial application using the above code may have:
static void Main(string[] args) { IOrderService service = new OrderService( new OrderRepository(), new StandardShippingService(), new StandardTaxService(new StandardTaxSpecification())); IOrder order = service.Find(42);
which is disgustingly ugly with all the news to set it up; even if I created the variables, they are still ugly. Using an IoC container allows me to avoid all of this, and in the case of StructureMap, this will be as follows:
static void Main(string[] args) { ObjectFactory.Initialize(x => { x.For<IOrderRepository>().Use<OrderRepository>(); x.For<IOrderService>().Use<OrderService>(); x.For<IOrder>().Use<Order>(); x.For<IShippingCalculator>() .Use<StandardShippingCalculator>(); x.For<ITaxCalculator>().Use<StandardTaxCalculator>(); x.For<ITaxSpecification>() .Use<StandardTaxSpecification>(); }); IOrderService service = ObjectFactory.GetInstance<IOrderService>(); IOrder order = service.Find(42);
Which is much cleaner, easier to maintain, and allows me to simply exclude a specific class, say for Mock, if I wrote unit test. In short, the advantage is that it further separates everything that I don’t even need (in the call code, that is), on which particular class it depends, I can simply create it using the container and let it do this and provide so that the consumer code knows only what it needs - for example, in a real application, if the controller calls the service, it does not need to know about repositories or calculators or specifications, all it needs to know is to use OrderService to do something with The Order.
It is right? There are a few things in this post that I'm not sure about yet:
If you decide to use an IoC container, is it intended to be used throughout the application, only if you have many inverted dependencies for the solution, or only the consumer? For example, in OrderRepository, if I use a specific implementation and create an order; Will this class use StructureMap to receive an order? This may be a bit of a dumb question, but all the DI / IoC examples I've seen focus only on using it in a consumer client (like a web page) and never relate to using it elsewhere. This seems to be an all-or-nothing approach: if you intend to use an IoC container, it will be used everywhere; you essentially replace any call with new SomeObject(); , in this case ObjectFactory.GetInstance<ISomeObject>();
It is considered good or bad that every class (where possible, of course) flow from the interface, do I need to use DI / IoC or something like taunts? I have seen many code examples in which each individual class that does not have an embedded interface has an interface behind it, and although I see the benefits and possible future verification of this, and I believe that the following TDD or BDD may be a factor here, like using these methodologies will usually tell you if you need an interface for a class, but I have seen and talked with many people who, TDD or not, think that you should never define an object type as a concrete class; it should always be an interface or an abstract class as a base type. This is similar to the case of the "Needless Complexity" code smell, not to mention a violation of YAGNI.