Monday, June 15, 2009

Exploring a WPF Business Application Architecture 2

In my last post I started writing about a pet shop sample I'm putting together to try out a few ideas about structuring business apps using WPF. In this post I'll show the domain model, and I'll show how it's persisted using Castle.ActiveRecord.

The Model
The domain model of the pet shop is shown here:

It's a straight port of the model used in the pet store iBatis.NET sample. I wont go through the model, but just say that it's complicated enough to be interesting as a sample, while simple and small enough to be quick to implement.
For now the domain classes have no behaviour. It's an anemic model. I expect to add behaviour as needed over time.

The Persistence
To exemplify how the model is persisted using Castle.ActiveRecord, I'll show the code of one of the central entities: The category class.











This is a pure POCO, which I think is nice, but ActiveRecord cannot persist instances of category. To make ActiveRecord aware if this a simple attribute is added to the class:





This means that ActiveRecord will be able to create a Category table in the underlying database, but the framework doesn't know which columns the table should have. We tell ActiveRecord what should actually be persisted to the database by adding a few extra attributes:
















All the C# properties that I want to be persisted to the category database table now has an attribute: Simple cases just have a Property attribute and ActiveRecord figures out the rest. The IList is persisted using a HasMany attribute, which means that the product table records will have a foreign key pointing back to the category table. For this to work the product class needs to be an ActiveRecord too.
Lastly notice the Validate* attributes which tells active record to validate certain things before even trying to save the entity to the database.
That's all that is needed to enable the ActiveRecordMediator class to work on my entities. The mediator can now create, read, update, and delete entities/records in the database.

The complete model can be downloaded from here.

Why Use ActiveRecord?
Firstly: It's so easy. There is really not a lot more to it than what I showed above.

Secondly: It's build on the rock solid basis of NHibernate.

Thirdly: The active record pattern is easy to use, easy to understand and actually suits a lot of situation. On the other hand the fact that you follow that one pattern is also the main limitation.

Fourthly: Entities are still almost POCOs. They've just had a few attributes added. This means they are still easily testable, and that I still hjave full control over my inheritance hierarchy. On the other hand the enitities now do two things: They represent a domain concept, and they declare how they are persisted. That's not full-fledged single responsibility. In the cases I have in mind for this exploration though I can live with that.

What's next?
In the next post I'll write about how to read and save ActiveRecord entities through DDD style repositories.