Thursday, June 25, 2009

db4o POCO Repository using Visual Studio 2010 .Net 4.0 Beta 1 and ASP.Net MVC 1.0

Note: This article applies to beta software and comes with no warranty or support, use at your own discretion. You must have Visual Studio.Net 2010 Beta 1 installed on your machine to make use of the code.

KandaAlpha now hosted on CodePlex, download from http://kandaalpha.codeplex.com/

This is an article which builds on a previous post on domain drive design architecture using asp.net web forms and Entity Framework v4.0. now, we leverage that core architecture to have a db40 object database as the back end and an asp.net mvc web application at the front end.

  • db40 is an object database which means there is no mapping files, attributes or other ‘impedance mismatch’ between your c# classes and the ‘database’ itself. It’s mostly used in embedded scenarios but appears to be getting used in websites. I’ve only just scratched the surface with it here, but i think it’s very cool and i hope it gains more and more traction.
  • asp.net mvc is the latest and greatest presentation architecture for asp.net and includes great separation of concerns between the various layers. In the architecture presented here, the Views and Controllers are within the asp.net mvc web application and the Model is essentially the domain model (e.g. KandaAlpha.Domain.Model)

My previous post discussed the architecture presented here solely within the context of the Entity Framework 4.0. It was also limited to usage of Web Forms on the front end. This release includes that working example but also includes into the solution an asp.net mvc 1.0 application which builds on the architecture and is backed by a db4op powered repository.

The first things i did were:

  • Added an MVC application (KandaAlpha.UI.Mvc) which is the front end side of things, with controllers that dependency inject the services and repositories as before.
  • Implement new repository for db4o (sorry, in the application i misspelt and used a zero, doh!) in KandaAlpha.Infrastructure.Repository.db40.
  • Update the web.config of the mvc application (and associated tests project) to wire the Unity dependency injection so that the db4o repositories are returned for repository interface requests

Changes to Dependency Injection Approach – Service Location vs Constructor Injection

I released this post last night and then got some good feedback from Will Beattie about design smells around my choice of Service Locator pattern approach to the dependency injection within the mvc controllers. One other approach as discussed in this post’s comments is to use constructor injection dynamically on the controllers. So, you can see i’ve added a custom controller factory.

In addition, Will had commented ton the controller’s dependency on the repository layer. I wasn’t too fussed about this given repository is within the domain and simply consists of interfaces but i did break it out for completeness. Notice that this does mean you get duplicate interfaces on the service layer in many cases. In practice, i would be quite happy to expose repository through the service layer but made the change anyway for completeness.

It’s worth noting i do still make of the ServiceLocator pattern within the mvc controller factory itself and also within global.ascx.cs Application_End which is where i ‘clean up’ the Repository Context (e.g. kill to db40 database ‘connection’).

So in general, the trend seems to be to favour constructor injection but there will sill be scenarios where a service locator pattern can prove useful, particular when mocking/testing may not be required.

Unit Test Isolation

If you take a look at the unit test for the controller now you can see how easy it is to mock up the controller without recourse to any dependency injection. In fact, the test is failing because i haven’t gotten round to implement a SaveChanges() for the in simply memory repository i built.

Before the unit test was admittedly an integration test, and it appears cleaner now, although it would be more work to maintain an in memory repository for a larger more complex application, but more advanced mocking tools may help with that.

How the mvc project runs

When you run the mvc project, it simply displays 2 customers on the screen. I’ve also added a little update on one of the customers as you refresh the page, just to show how to save things back to the db40 file.

This all took less than 2 hours and i was very pleased to get things up and running so quickly. It hopefully shows you some of the power and flexibility of dependency injection and the domain drive approach as well as introduction you to how use such an architecture with technologies like asp.net mvc, db4o and entity framework.

Thursday, June 25, 2009 10:51:27 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [3]  |  Trackback
Friday, June 26, 2009 5:45:23 AM (New Zealand Standard Time, UTC+12:00)
This looks interesting, I'm especially interested in db40 so thanks for that.

However I have a few issues with the current approach.

The Controllers aren't Unit Testable (in the strict sense of Testing in Isolation) which kind of defeats the purpose in my opinion. You could have as easily resolved your depedency in the Page_Load or Page_Init under WebForms and achieved the same result.

I think the use of a static dependency resolver should in my opinion be avoided completely or used only in special cases.
If you must resolve your depedencies within the body of a method then why not wrap your static depedency resolver behind an IFactory interface which will still allow you to mock out the dependencies in your Unit Tests.

Giving the Controller knowledge of the Repository seems not quite right, the Controller action should be as dumb as possible e.g. calling a CustomerService.Save(Customer customer).

Interested also to know why you're using Unity?
Friday, June 26, 2009 5:20:13 PM (New Zealand Standard Time, UTC+12:00)
These are all valid points I think.

The static dependency resolver (service locator pattern) shows clearly how DI works, although there are different approachs to doing this sure. the test project can have a mocked version of the services and repositories injected using configuration (swap out with another implementation) so not sure i see too much of a problem here. The static resolver ultimately is a facade over the injection. For sure one could easily remove this explicit injection

It is however a 'relaxed' layered architecture. You could enforce that the controller only knows about the service layer, and the service layer must mask calls to the repository. If you need that level of separation then just hide access to the repository, but i don't mind controllers knowing about a repository as this a domain level construct for getting at the model, although i would push more complex orchestrations or workflows into the service layer. Horses for courses at this level.

I put Unity in because i hadn't used it before and it's part of the MS set of technologies. Castle Windsor etc. works just as well, easy to swap out;) Essentially, the injection is configuration based in my example, even if there is a servicelocator pattern in use

For more on injection: http://martinfowler.com/articles/injection.html
Friday, June 26, 2009 5:32:03 PM (New Zealand Standard Time, UTC+12:00)
This bit is particularly relevant.... although i still see the service locator as 'explicit' dependency injection, rather tha the 'implicit' form Fowler refers to...

The fundamental choice is between Service Locator and Dependency Injection. The first point is that both implementations provide the fundamental decoupling that's missing in the naive example - in both cases application code is independent of the concrete implementation of the service interface. The important difference between the two patterns is about how that implementation is provided to the application class. With service locator the application class asks for it explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.

Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative.

The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem.
Comments are closed.