Friday, June 09, 2006

.Net Assemblies and Layered Architecture

How should you physically implement a logically layered application?


My Story


In the book Domain Driven Design Eric Evans encourages the use of Repositories. A repository is an object that is responsible for persistence and retrieval of Model or Business Objects. The intent of the repository is to abstract the object storage mechanism. The interface to a repository should not be specific to a database technology, or any technology being used to permanently store or 'persist' objects. This abstraction allows you to easily change the underlying storage technology. Adding support for a new storage technology (I.e. another relational DBMS), means creating another matching set of repository objects.


Multiple Assemblies


With this in mind, I decided to create 2 assemblies to match the 2 layers. A Domain Model assembly and a Persistence assembly. The idea being that the persistence assembly could be dynamically loaded at runtime and thus chosen from a list of assemblies that support various DBMSes



After running FX Cop on my work, I tried adding the CLS Compliant flag to assembly.info to satisfy the FX Cop audit.


using System;
[assembly:CLSCompliant(true)]

The CLSCompliant attribute caused my Persistence assembly to fail on compilation, due to the fact that it referenced and returned types declared in another assembly. The other assembly was of course my Model assembly. This got me thinking...


Single Assembly


In other projects I have worked on, the persistence layer and model layer were combined in one assembly. The repository classes were included in a seperate namespace (and project sub-folder) and were therefore still distinct from the model objects. So logically the layers were seperate, but the physical implementation was a single assembly. The 2 layers worked very closely together and in many ways really acted like one layer. So this configuration also made sense.

The difficulty with the single assembly comes from the desire to 'swap' between persistence technologies. In the combined model, you can no longer load the repository objects you need at run-time. Supporting multiple database technologies requires the Domain assembly to contain multiple sets of repository objects collected in different namespaces, you would use the Strategy pattern to provide the runtime loading (abstraction from specific types), and some sort of controller to serve up the concrete repositories (based on a config setting perhaps). Each of the architectures has benefits and drawbacks. I like to reduce my assembly count though, and systems don't generally support a huge set of relational database technologies. So I think I will move my seperate assemblies into one. As the XP mantra goes, 'you aren't gonna need it' (Y.A.G.N.I.).

No comments:

Post a Comment