|
||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionThis article focuses on Domain Driven Design, concentrating on using some principles from this area in combination with an 'attribute-flavored' approach. The contents are partially based on an article of mine that was published in the December 2007 issue of the Dutch Microsoft .Net Magazine. BackgroundDomain Driven Design, often abbreviated as DDD, is a topic that can be encountered frequently these days. Some would undoubtedly refer to it as another hype, and as with any new kid on the block it is accompanied by debates as to its merits, as well as flocks of puristic believers. It is not my intention to venture down either road, also due to the fact that my interpretation of Domain Driven Design may be very different from the original intentions as written down by, most notably, Eric Evans and Jimmy Nilsson. I will list some references for further reading at the end of this article. Some principlesIn DDD, the domain is centralized as the planet around which services revolve as if they were satellites or moons. In other words, the services are not themselves part of the business domain, but they use the domain. The domain is explicitly intended as the business domain, or knowledge domain if you will, containing domain classes and business rules. Also, the domain is exposed by one or more repositories for retrieval purposes, and by factories for creational (lifetime) purposes. A domain model should be replaceable by another domain model, ideally leaving the rest of your application intact. This is a principle that is not core to DDD, but one that I would like to adhere to. The principles listed above are actually all examples of the more generic principle of 'separation of concerns'. That is not something new, but in Domain Driven Design, you could call this the mother of all principles. The ubiquitous languageGiven the principles above, you could imply that DDD is more of a 'duh ... that's common sense' approach. And in fact, it is. DDD does not actually add a new technology, nor does it add new language constructs, and as a methodology it is not actually new either. It combines a lot of stuff that is best practice in many minds and places (but, truthfully, not always at the front of our minds, and not always in the right place). It hammers down on the domain-centric mantra : "Business knowledge, my business, your business". That's not probably a mantra you'll find anywhere, as I just made it up, but the essence is keeping business objects, rules, vocabulary and knowledge centralized in one place and disclosable to services and applications that need them. And in doing so, making sure that every actor involved speaks this language. It must be unambiguous, as concise as possible, and fluent on every tongue. This is what Eric Evans refers to as the ubiquitous language. Common base, common groundTo enable compliance with the principles summed up above, a viable option is to have every domain model class inherit from a common base class. In the solution that accompanies this article this is not just a choice between base class and interface, but a fundamental architectural provision that also makes it possible to replace a given model by another (the third principle above). Therefore, more than a base class, we have a complete base assembly that the domain model derives from. This 'basement assembly' contains provisions for properties and property collections, relations, and - as will be evident later on - for the custom attributes and validators that are a second foundation for a domain model such as proposed here.
The code baseThe solution contains three projects:
The basement assembly is a mini framework for domain models. It cannot have references to the model (since the model references the basement assembly), therefore it relies on reflection if necessary to obtain information from the model, and for the most part contains generic constructs that can be used in domain model classes. Now, since code speaks more than words often can, let's look at an example of a domain class that is a derivative of
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Codebasement.DomainDrivenDesign.Basement.Attributes;
using Codebasement.DomainDrivenDesign.Basement.Basement;
using Codebasement.DomainDrivenDesign.Basement.Converters;
using Codebasement.DomainDrivenDesign.Basement.Enums;
using Codebasement.DomainDrivenDesign.Basement.Utilities;
using Codebasement.DomainDrivenDesign.Model.Editors;
using Codebasement.DomainDrivenDesign.Model.Enums;
using Codebasement.DomainDrivenDesign.Model.ModelClasses;
using Codebasement.DomainDrivenDesign.Model.Validators;
namespace Codebasement.DomainDrivenDesign.Model.ModelClasses
{
///
Parameters and PropertiesTo have a generic way of persisting properties and to enable a uniform manner of validation, the properties of domain model instances are represented as parameters, bundled on the AttributesAs you can see, a lot of attributes are used on the domain classes here. Standard attributes such as Besides standard attributes, there are several custom attributes visible in the code above:
Some of these are for validation purposes (and variants can also be found in e.g. the Validation Application Block of the Microsoft Patterns and Practices Enterprise Library). Some are intended to express the characteristics of relations and behavior such as copying, linking, etc. Validation patternThe power of attributes such as illustrated above lies in the very generic way that they can be used, for instance, to apply validation to a domain model such as proposed here. Classes, properties, relations and any other types can be validated uniformly and in a single place. That place being the
///
Serialization and repositoriesThe persistence implementation in the accompanying solution is simple and based on straightforward serialization. The In general, a fire and forget all-in-one serialization pattern will not be sufficient of course, bringing a mapping to a relational model or other storage model into play. An important aspect is to have the persistence governed by one or more repositories, possibly in combination with a provider pattern. Here we have the simple implementation of such a repository for straightforward 'container'-based serialization. This will typically have to be replaced by a more extensive repository that can load and save information to and from the domain model, where the 'containers' are to be replaced by well-chosen aggregate boundaries (e.g. customer with order and order lines as a coherent and transactable 'aggregate').
using Codebasement.DomainDrivenDesign.Basement.Enums;
using Codebasement.DomainDrivenDesign.Basement.Serialization;
using Codebasement.DomainDrivenDesign.Model.ModelClasses;
namespace Codebasement.DomainDrivenDesign.Model.Repository
{
///
FactoriesRepositories for retrieval and persistence, factories for creation. Below is an example basic factory for creating and deleting domain objects. Note here that these two simple methods create or remove any domain object in the model, they are generic in nature. You could also make For a more real-life domain, you would most probably require more specific factory methods that use knowledge about the domain and provide more of a headstart.
///
SampleThe following screenshot show the sample app that uses the domain model. The treeview is populated using the repository, the factory enables creating and removing instances, and the validation results are visible in the list view.
ReferencesCreditsCredits are due for portions of the ConclusionNumerous improvements could and should be made on the code base. However, the point here is the application of some domain driven design principles, making elaborate use of standard and custom attributes, and enabling a domain model that derives from a base assembly that facilitates common ground for any domain model. Essential to Domain Driven Design is to place the business domain back in the spotlight, where it belongs.
|
|||||||||||||||||||||||||||||||||||||||||||||||