First, we sat down in a brainstorm session to get clear what we wanted to change.
This resulted in the following items:
- Improve testability by introducing Dependency Injection.
- Upgrade the Entity Framework to the latest version and dump Self Tracking Entities.
- Remove WCF.
- Create a basic test harness for the common use cases.
I started out with the first one, introducing Dependency Injection. Dependency Injection comes down to ‘asking for what you need instead of constructing it yourself’.
1: public class UnTestable
3: public Person GetById(Guid id)
5: using (IUnitOfWork uow = UnitOfWorkFactory.Create())
7: return uow.PersonRepository.GetById(id);
1: public class Testable
3: private IPersonRepository personRepository;
6: public Testable(IPersonRepository personRepository)
8: this.personRepository = personRepository;
12: public Person GetById(Guid id)
14: return personRepository.GetById(id);
Then I started looking trough our code for all ‘new’ operators or factory calls. After moving these to the constructor I got a lot of compile errors from our ASPX pages. All those direct constructor calls where replaced with Ninject and suddenly, our project was up and running again!
This immediately resulted in better testability. We can now test a class in complete isolation without having any side effects!
Entity Framework & WCF
To upgrade the Entity Framework we switched to using the Nuget package. I removed all existing references, installed the Nuget package and tweaked the T4 template. This gives us the advantage of having compiled queries everywhere and the easier to use DbContext.
After these changes, removing WCF was only a matter of deleting the project. Ninject was configured to construct the in-memory version of the services and WCF wasn’t referenced anywhere directly.
Creating a basic test harness
We have created three separate test projects:
- Scenario Tests
- Functional Tests
- Unit Tests
Some analysis with Visual Studio 2012
So, what have we learned?
We definitely learned something from this project. The key points are:
- Invest in making your application testable from the start. We shouldn’t have settled for running our ‘Unit Tests’ against the database with the idea that otherwise ‘they wouldn’t test anything’.
- Know the difference between Unit Tests and Integration Tests and when to use them.
- Separate construction of objects from business logic. Use Dependency Injection to manage the object construction.
- Build the simplest thing possible. We shouldn’t have used WCF from the start. It hindered our development and cost to much time.
But now, we have our nice architecture back again. We can make changes more easily and the code base is smaller and better to understand. Off course we still have a lot to do. We want to refactor our Anemic Domain model by moving more and more logic to our actual domain entities and we need to move code from our codebehind files back into the presenter where it belongs.
But for now, we have made quite an improvement to our code base. Code should read like it’s poetry!