I’ve been writing a small time tracker web application to teach myself ASP.Net MVC, and am using NHibernate as the ORM. I’m trying to use best practises while building this app, and one issue I was trying to deal with was whether to build a layer over the top of NHibernate. My first set of controller actions used NHibernate directly, with a dependency injected ISessionFactory. This was fine for simple queries (like get Task with id 1) but it meant more and more of my model concerns were leaking into my Controllers. I had thought that NHibernate provided enough of an abstraction over my model for this to not matter, but I was quite wrong.
Remembering I had seen some argument over whether using a generic repository was a good idea or not, I started searching around and found quite a few blogs saying it was a bad idea. They made sense, and one blog had a great solution: Create a Repository<T, U> abstract class for common CRUD style operations, inherit your specific Repository from that, and only expose meaningful methods in your interface to client code. The benefits of this approach are many - your client code can only see methods that are applicable to each model class, you don’t have to duplicate your common CRUD operations for each model class, and it is easy as pie to unit test.
This last point is the one worth mentioning in my books. The great thing about separation of concerns is it should make things easier to pull apart for unit testing. Because my Repository methods have meaningful names, and are pretty fine grained, my mocking setup looks almost readable. It is immediately obvious from reading my tests that TaskController.List(5) should call ITaskRepository.GetLatestTasks(5). Not only that, but most of the Controller actions have been reduced to “Get this from Repository, return to View” or “Save this thing to the Repository”. They are small, obvious methods, and that makes them easier to test, and easier to maintain.