1

How often do you use IoC for controllers/DAL in real projects?

IoC allows to abstract application from concrete implementation with additional layer of interfaces that should be implemented. But how often concrete implementation changes? Should we really have to do job twice adding method to interface then the implementation if implementation hardly will ever be changed? I took part in about 10 asp.net projects and DAL (ORM-like and not) was never rewritten completely.

Watching lots of videos I clearly understand that IoC "is cool" and the really nice way to program, but does it really needed?

Added a bit later: Yes, IoC allows prepare better testing environment, but we also have nice way to test DAL without IoC. We wrap DAL calls to database into uncommited transactions without risk to make data unstable.

4
  • No, a IoC doesn't make you application easier to test, you never use your IoC in tests. Contract based programming (programming to interfaces instead of implementations) do, however, make your application more testable. Commented May 5, 2010 at 7:09
  • Yes, I agree, it's easy. But I have strong feeling, that I do the extra-job with such too-interface-centric-programming that is too "academic", nice shiny feature that is not very helpfull (though not harmfull). Commented May 5, 2010 at 7:21
  • 1
    In the beginning it might be "extra work", but when you have learned how to use your IoC and contract based programming you will see that it will be a lot less work in pretty much every case. When done right, you can set up a lot of conventions and you will have to write a lot less code in your applications and the code you write will be a lot more readable and maintainable. My advice is to read up on how to use your IoC and test it for a while. You will not regret it. Commented May 5, 2010 at 7:26
  • Can someone please use the full name of IOC once so I don't have to look it up? Thanks! Commented May 6, 2010 at 4:10

4 Answers 4

2

IoC isn't a pattern only for writing modular programs; it also allows for easier testing, by being able to swap in mock objects that implement the same interface as the components they stand in for.

Plus, it actually makes code much easier to maintain down the road.

Sign up to request clarification or add additional context in comments.

6 Comments

Yes, but for example, I can test DAL without IoC. Usually I wrap tests in transaction (that is uncomitted) and work with development database data without mocking & risk to make data unstable.
Then you're actually doing integration testing, since you're touching databases.
Why not? May be testing with mocking, then without mocking it too much?
I disagree it makes code easier to maintain because every time method signature changes (& it's too often situation when project starts) I have to do changes twice (interface + implementation).
@Andrew Florko, That is something that the IDE will do for you and you will not have to worry about that. You just change the interface and you have tools that change the implementations for you.
|
1

It's not IOC that allows you to abstract application from concrete implementation with additional layer of interfaces, this is how you should design your application in order to be more modular and reusable. Another important benefit is that once you've designed your application this way it will be much easier to test the different parts in isolation without depending on concrete database access for example.

12 Comments

> to be more modular and reusable. I suspect DAL library is reusable itself, because > isolation without depending on concrete database access for example Seems (for me) to be unpractical and hardly ever used feature. > benefit is that once you've designed your application this way it will be much easier to test the different parts Seems to be minor, because (if we talk about DAL) i can test DAL with uncomitted transaction calls.
@Andrew Florko, Then how do you test you BLL without using your DAL if you have a dependency on your DAL? Your question seem to be more about contract based programming then the use of IoC containers. Those are two different things.
Yes, my BLL depends on DAL implementation. And I have never faced the problem with this dependence (because DAL implementation never changed completely). Unit tests cover DAL "singular functions" with uncomitted transaction calls as well as BLL "complex functions".
@Andrew Florko, Then you can't unit test your BLL, because it will test your DAL as well. Writing tests will then be a lot harder then if you could simply muck your DAL (and all other dependencies).
Yes, I can't. But is it really a problem? Have you ever faced the situation, where such approach leads toward unpredictable results (not theoretically but in practice)? And each time I add method to contract interface, I have to create real-DAL implementation, and mock-DAL implementation as well. May be, world goes crazy on unit testing? Creating a DAL mock is not really pleasent job. It can contains hundreds of functions with in "memory database" with lists/dictionaries. Why not to test the real DAL functions on real data in place?
|
1

There's much more about IoC except ability to change implementation:

  • testing
  • explicit dependencies - not hidden inside private DataContext
  • automatic instantiation - you declare in constructor that you need something, and you get it - with all deep nested dependencies resolved
  • separation of assemblies - take a look at S#arp Architecture to see how IoC allows to avoid referencing NHibernate and other specific assemblies, which otherwise you'll have to reference
  • management of lifetime - ability to specify per request / singleton / transitive lifetime of objects and change it in one place, instead of in dozens of controllers
  • ability to do dynamic stuff, like, getting correct data context in model binders, because with IoC you now have metadata about your dependencies; and this shows that maybe IoC does to your object dependencies what reflection does to C# programming - a lot of new possibilities, that you never even thought about

And so on, I'm sure I missed a lot of positive stuff. While the only "bad" thing that I can think about (and that you mentioned) is duplication of interface, which is non-issue with modern IDEs support for refactoring.

Well, if your data interfaces change every day, and you have hundreds of them - you may want to avoid IoC.

But, do you avoid good design practices just because it's harder to follow them? Do you copy and paste code instead of extracting a method/class, just because it takes more time and more code to do so? Do you place business logic in views just because it's harder to create view models and sync them with domain models? If yes, then you can avoid IoC, no problem.

Comments

0

You're arguing that using IOC takes MORE code than not using it. I disagree.

Here is the entire DAL IOC configuration for one of my projects using LinqToSql. The ContextProvider class is simply a thread safe LinqToSql context factory.

container.Register(Component.For<IContextProvider<LSDataContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<LSDataContext>>();
container.Register(Component.For<IContextProvider<WorkSheetDataContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<WorkSheetDataContext>>();
container.Register(Component.For<IContextProvider<OffersReadContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<OffersReadContext>>();

Here is the entire DAL configuration for one of my projects using NHibernate and the repository pattern:

container.Register(Component.For<NHSessionBuilder>().LifeStyle.Singleton);
container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(NHRepositoryBase<>)));

Here is how I consume the DAL in my BLL (w/ dependency injection):

public class ClientService
{
    private readonly IRepository<Client> _Clients;

public ClientService(IRepository&lt;Client&gt; clients)
{
    _Clients = clients;
}

public IEnumerable&lt;Client&gt; GetClientsWithGoodCredit()
{
    return _Clients.Where(c => c.HasGoodCredit);
}

}

Note that my IRepository<> interface inherits IQueryable<> so this code is very trivial!

Here's how I can test my BLL without connecting to a DB:

public void GetClientsWithGoodCredit_ReturnsClientWithGoodCredit()
{
    var clientWithGoodCredit = new Client() {HasGoodCredit = true};
    var clientWithBadCredit = new Client() {HasGoodCredit = false};
    var clients = new List<Client>() { clientWithGoodCredit, clientWithBadCredit }.ToTestRepository();
    var service = new ClientService(clients);

var clientsWithGoodCredit = service.GetClientsWithGoodCredit();

Assert(clientsWithGoodCredit.Count() == 1);
Assert(clientsWithGoodCredit.First() == clientWithGoodCredit);

}

ToTestRepository() is an extension method that returns a fake IRepository<> that uses an in-memory list.

There is no possible way you can argue that this is more complicated than newing up your DAL all over your BLL.

The only way you could have ever written the above test is by connecting to a DB, saving some test clients, and then querying. I guarantee that takes 100+ times longer to execute than this did. (Times that by 1000 tests and you can go get some coffee while you're waiting.)

Also, by using uncommitted transactions for testing you introduce debugging nightmares resulting from ORMs that don't query over uncommitted entities.

1 Comment

I should add that one of those projects I referenced has over 100 db tables!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.