Mvc pattern – splitting model into data-access and business logic layers

mvc

I've had a chance to try it out and I like it very much. I'm thinking of using it in all of my future projects. I'd like to hear some critique and opinions about it. I've done a little research on the subject and I'm not sure I've seen this approach around, but I'm pretty sure that it must have been tried by some more experienced people and I'd like to avoid any pitfalls that come with it

The idea is that model is split into:
1. db access layer (dal)
2. business logic layer (bll)

  1. so db access layer contains (ideally) no logic at all other then db access logic – prepared queries that are supplied with parameters, when called, and which return results from db, if needed (in case of SELECT queries). these classes are not tested (if no logic is inserted into them), since they don't contain any if/for/while/throw… commands

  2. business logic layer which contains actual logic of the app. controllers do not see dal and only call bll which in turn calls dal when needed. bll needs to be tested (i use unit testing) and since it is kept separate from the db access, when read-only functionality is being tested, db access can be mocked using dependency injection (create mock class alternative for every dal class with all the same methods, load them via the factory method when requested from bll and depending on whether the call came from testing environment or not load either mock or 'real' class. of course in case of write functionality (DELETE, INSERT), testing would have to include db calls, so in that case 'real' class would be called, rather then mock, but this can still be very useful if system has more read then write db calls

Benefits of this approach:

  1. code separation – it keeps your business logic clean of db access code which improves readability, especially in big methods that need to make several calls to db. it makes it easier to maintain code and also allows you to encapsulate db access logic, which can be called from a numer of blls which also makes it easier to maintain
  2. it makes it easier to switch databases at any point, which is not something that happens often, but if it does happen, it's not an easy thing to do, everybody who had to do it at some point know what i'm talking about
  3. when testing bll with mock classes, it makes tests run faster since no calls to db are made. this is not too significant, but can help when you are tweaking some functionality intensively and testing it along the way. at the same time it makes it much easier to test performance of 'pure logic' detached from db calls

drawbacks:

  1. more cluttering because of adding whole new layer of classes to the system
  2. slightly lower performance due to the added dependancy injection which takes time to resolve
  3. while mock classes do nice work, they do have to be created and maintained so there is added bureaucracy to the whole system

Am I missing anything? Do you prefer system that I described or good ol' fashion 3 layer mvc and why? I'm no guru, I'm still exploring various architectures, but I like this one very much and would love to hear what my more experienced colleagues have to say about it

Best Answer

MVC means model-view-controller separation for the client-side, in this case, your site. It has nothing to do with the backend layering.

Concerning backend layering; I personally like the onion approach as described here and applied here. The business layer is independent on the data layer implementation or any other technical aspect, as it only knows interfaces.

So in your controller you use the backend services (note that I'm not saying WCF services - it can be WCF, but doesn't have to be). You get data back in a specific format (the model) and you then could transform this data into viewmodels which are designed specifically for a view.

The backend services would then have the various layers that you need to implement the chosen architecture (business layer, data layer etc), but this is independent of your ASP.NET MVC site.

And don't avoid using dependency injection for the wrong reasons. It should be the default programming style.

Related Topic