On Orthogonal Frameworks

time to read 4 min | 613 words

One of the interesting aspects of open source projects is that there are quite a bit of directions that the developers and the community would like to go to, all at once. Even in healthy communities, people sometimes would like to do Really Wierd Stuff, for a specific scenario or use case, they would like to do something that goes against the grain of the project. Or is something that really should be outside the scope of the project, etc.

The usual response to this is to allow a user to supply its own implementation of a framework component. NHibernate is a great example of that, where you can almost always override the default NHibernate behavior with your own. This means that in terms of flexibility, it is possible to go in at almost all levels and decide that you would like this behavior to work differently for you. For a tool like NHibernate, it is a very important feature, because people have some very interesting ideas about how a database schema should look like.

Why am I talking to you about this? Because I find, with the exception of WCF, that most commercial frameworks do not give nearly as much leeway, and they have "certain ideas" about what you have to do in order to use them. Right now, I would like to talk about the Entity Framework requirements for a base class / interface implementations.

Again, a base class / optional interfaces are great way to extend the way you are using a given framework, but the heavy weight approach is flawed from the start. It makes a lot of assumptions about the way you use it, and uses tooling to hide ugliness. There shouldn't be ugliness in the first place, but I digress.

Let us take change tracking as a simple example, the Entity Framework requires that the object will manage its own changed state. Personally, I feel that this is a violation of the Single Responsability Principal. NHibernate handles this by comparing the old/new values of the object, and decide accordingly if it should save it. This has some performance implications in limited scenarios*. Having the object track its state is preferable, because then you can just do if(entity.Changed) Save(entity).

I decided to spike what it would take to build an orthogonal implementation of this with NHibernate. ~120 lines of code later, I had NHibernate inject change tracking behavior into the object, which would flag it as changed if a set property was called.

Let me repeat that, 120 lines of code, zero change to the model (still Plain Old C# Classes), new behavior. For kicks, I have added support for INotifyPropertyChanged behavior, which was an additional of 10 lines of code.  

This is also an approach that is taken by guys that doesn't have a designer team just waiting to generate a ton of code just to get things started. This is based on clever code and flexible architecture. The problem with the code gen approach is that it lets you cover holes in the tool you are using, but those holes will come back to bite you when you need to amke something that the author of the tool didn't think about.

* Loading large number of objects and updating a few, then persisting. That is partly why Evict() is for.

** The new behavior is not part of NHibernate, if there is interest, I can post the patch.