简体   繁体   中英

IoC/DI for a small .NET projects

The separation of concerns provided by IoC/DI frameworks cannot be overestimated for a large projects, but is there a place for such techniques in a small project?

Can you share some real-life uses of IoC/DI frameworks you found to be useful when you were coding another small/average project.

For the sake of definition:

A "small project" contains 100-1000 lines of code (balpark, just to give an idea), it takes a 1-3 days to code and the lifetime of the resulting application before it gets thrown away or decomissioned is within 1 week - 5 years after the initial release (this is there it gets hard to draw a line between small/average/large project).

Thanks.

For a small project, I'd be tempted to still use dependency injection, but not use a framework. Just craft all the dependencies in your entry point. You still get all the benefits of testability, and you can move on to use a fully-fledged container later on - but you don't need to worry about setting up the container until it's actually going to be useful.

I've used this approach on a couple of small projects, and it's worked very well. Of course, it depends on how complicated your dependencies are - whether they need to be factories, have different scoping etc - but if it's just "I have these three things which all depend on an authentication service" then that's pretty straightforward.

but is there a place for such techniques in a small project?

Even in small projects you should use the IoC pattern in order to weaken the coupling between the layers and make it unit testable. Always work with abstractions. Whether you use a DI framework or not doesn't really matter. In small projects you could simply do the plumbing of the dependencies manually, don't really need an object container to do the dependency injection, but when you give it a second thought why not?

Depends on what you deem to be important in your implementation. If testability is important and if you tend to follow single responsibility principle (in small or big projects), you generally end up with a bit more classes than you probably would otherwise. This can result in an invocation like

var svc = new ShippingService(new ProductLocator(), 
                              new PricingService(), 
                              new InventoryService(), 
                              new TrackingRepository(new ConfigProvider()), 
                              new Logger(new EmailLogger(new ConfigProvider())));

If you can live with this and personally I would too, in a throw away app, then by all means you dont really need a DI Container. Go with whatever makes you happy. Cheers.

Edit :

Over the years I've found TinyIoC to be a good compromise for smaller projects.

I wouldn't relate IoC to project size as much as to:

  • number of classes in the project
  • complexity of their dependency
  • expected amount of maintenance and extending
  • expected switch of developers during extensions and maintenance

Especially the last two will make it much easier if you test your code for which you do need (well it can be avoided with proper tools but...) IoC.

Don't over-engineer your code

Hence I would suggest not to use DI containers for starters but definitely use IoC in terms of interfaces and double constructors like:

public class Example : IExample // for others that might depend on it
{
    private IDependant service;

    // default constructor used in your application
    public Example() : this(new DependentService())
    {
        // does nothing else
    }

    // constructor for testing purposes
    public Example(IDependant service)
    {
        this.service = service;
    }

    // IExample implementation
}

Simple two level dependencies are easily manageable manually without the use of DI containers. And most likely faster to use as well. This will make your code easily testable and especially think of this if you'll provide bugs as test cases that would automate future-proof bug avoidance.

Small project tend to grow

Small projects with added value in business environment tend to be extended quite frequently since it pushes user imagination how things could be enhanced even further. So don't underestimate your small project. It may soon grow.

I write a lot of similar sized projects, 30-40 per year.

I use DI but create my own factory class with a Resolve method.

public T Resolve<T>()
    where T:class {
        if (typeof(T).IsAssignableFrom(typeof(Something)))
            return new Something(Resolve<ISomethingElse>()) as T;
        ...
}

One shortcut I take is that I make most members virtual instead of creating a separate interface.

Generally speaking, why not use a DI container for small projects? The simpler your code base, the simpler it is to use a container, my advice is use on that provides a simple fluid interface for dependency registration, or just use linq, then you pretty much end up with a really small footprint that wires up your entire app:

public void OnStartup(args){
    var container = new IoCContainerOfChoice();

    Types.FromThisAssembly()
        .ForEach(type => container.Register(type, type.DefaultInterface());

    container.Resolve<ShellView>();
}

That's as simple as it needs to be for a lot of small projects. The idea is a one liner that registers all types in your project with a default interface (I usually write an extension method on "System.Type" to pick either a named interface, the first interface, or just return itself). NOTE: Most modern IoC containers have their own Fluent Interface for providing this functionality, this is simply an example.

And hey look, you are now setup for the future of unexpected growth, you can save urself a bunch of "new-ing", and decouple your application big or small.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM