Monday, April 25, 2011

NHibernate Tutorial, Part 3 – Configuration

This is part 3 of my NHibernate tutorial, make sure to start from part 1.

Now that we have a mapped model, it’s time to configure the classes that will actually do the hard work. let’s review them:

The Session

The session (more precisely the ISession interface) is our primary API for using NHibernate. It exposes methods for saving, deleting, updating and querying entities. It’s disposable and cheap to create, although deciding when to create or dispose a session is a subject of it’s own, more on which I’ll elaborate later. What’s important to remember for now is that opening a session isn’t equivalent to opening a database connection – the connections are being pooled for us by the session factory, so when we hold a session open an underlying database connection isn’t necessarily being put on hold for us. Also, a session isn’t thread-safe and should be managed accordingly as needed by your application’s architecture (again, more on that later).

The Transaction

NHibernate has it’s own ITransaction interface that doesn’t comply to System.Transactions namespace, for better or worse. managing the transaction goes hand in hand with managing the session, after all an atomic unit of work should be wrapped in a single transaction and we perform those actions on our session. I’ll explain a little more later about that, but it’s important to remember that opening a transaction (unlike opening a session) IS blocking a database connection – that’s why we need to make them as atomic as possible.

The Session Factory

The session factory is an object that’s configured once per database at the application initialization. It knows which database we use, what our domain looks like, how to handle cache, etc.. The session factory (as it’s name reflects) is responsible for creating sessions throughout our application, while managing the connection pool to the database. It’s thread safe and should be accessible throughout our application. It’s also very expensive to create, for obvious reasons.

Configuring the session Factory

NHibernate supports built it configuration via xml, an example can be found here. Also, stating with NHibernate 3, NHibernate supports configuration via code using the NHibernate.Cfg.Loquacious namespace, more on that can be found here. As I said before, I rather work with FNH with provides mappings and configuration via code, so from here on that’s what we’ll be focusing on.

Yawn. Let’s write some code.

Using the Server Explorer, create a new database (I’m assuming you have SQL Server express 2008 on your machine):db-step-1

db-step-2

Create a new Console Application and use Nuget to add a library package reference to FluentNHibernate. Then add an app.config file and add the following text in it:

<connectionStrings>
    <add name="DbConnection" 
         connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Tutorial;Integrated Security=True;Pooling=False"/>
  </connectionStrings>

Now paste the following code to Program.cs:



   1: using System;
   2: using Entities;
   3: using FluentNHibernate.Cfg;
   4: using FluentNHibernate.Cfg.Db;
   5: using Mapping;
   6: using NHibernate;
   7: using NHibernate.Cfg;
   8: using NHibernate.Tool.hbm2ddl;
   9:  
  10: namespace ConsoleApp
  11: {
  12:     class Program
  13:     {
  14:         private static ISessionFactory _sessionFactory;
  15:  
  16:         static void Main(string[] args)
  17:         {
  18:             Person person;
  19:  
  20:             using (ISession session = OpenSession())
  21:             using (ITransaction tx = session.BeginTransaction())
  22:             {
  23:                 person = new Person { Name = "Matan" };
  24:                 session.Save(person);
  25:                 session.Flush();
  26:                 tx.Commit();
  27:             }
  28:  
  29:             using (ISession session = OpenSession())
  30:             using (ITransaction tx = session.BeginTransaction())
  31:             {
  32:                 var newPerson = session.Get<Person>(person.Id);
  33:                 Console.WriteLine(newPerson.Name);
  34:             }
  35:         }
  36:  
  37:         private static ISession OpenSession()
  38:         {
  39:             if (_sessionFactory == null)
  40:             {
  41:                 _sessionFactory = Fluently.Configure()
  42:                     .Database(MsSqlConfiguration.MsSql2008.ShowSql()
  43:                     .ConnectionString(cfg => cfg.FromConnectionStringWithKey("DbConnection")))
  44:                     .Mappings(cfg => cfg.FluentMappings.AddFromAssemblyOf<StoreMap>())
  45:                     .ExposeConfiguration(AddConfig)
  46:                     .BuildSessionFactory();
  47:             }
  48:  
  49:             return _sessionFactory.OpenSession();
  50:         }
  51:  
  52:         private static void AddConfig(Configuration cfg)
  53:         {
  54:             new SchemaExport(cfg).Create(true, true);
  55:         }
  56:     }
  57: }

Finally, we have some entities flying around! If you run the code you can see the SQL (both DDL and DML) in the output window of your application, also the data should appear in your database.


We created a session factory (on the first session request), opened a session and a transaction and used them to persist a new Person entity. Then we created a new session (and transaction) and queried for a person with a given id. We then print out the new entity’s name to make sure it’s indeed our entity.


Let’s go over the interesting parts again:



   1: _sessionFactory = Fluently.Configure()
   2:     .Database(MsSqlConfiguration.MsSql2008.ShowSql()
   3:     .ConnectionString(cfg => cfg.FromConnectionStringWithKey("DbConnection")))
   4:     .Mappings(cfg => cfg.FluentMappings.AddFromAssemblyOf<StoreMap>())
   5:     .ExposeConfiguration(AddConfig)
   6:     .BuildSessionFactory();

We start by FNH’s Fluently.Configure() methods and then use:



  1. The Database method, used to define that we’re using SQL Server 2008, and supply two other settings:

    1. ShowSql() - sets NHibernate to print to the default output every SQL command that’s being executed by a session.
    2. ConnectionString – set to be taken from our app.config under the name “DbConnection”.

  2. Next, the Mappings method where we point our configuration to our ClassMaps. I chose to use all of the ClassMap’s in the mappings assembly, but you can add them one by one if you’d like. Notice that other than FluentMappings we can also add HbmMappings (read more here) or AutoMappings (read more here), I’d rather use FluentMappings.
  3. Next, the ExposeConfiguration allows us to perform extra custom configuration on our underlying IConfiguration object just before it becomes an ISessionFactory. We’ll get there soon, but remember that this is where we can add custom NHibernate configuration, such as listeners and interceptors.
  4. Finally, a call to BuildSessionFactory wraps it all up and gives us an ISessionFactory, ready for work!

Moving on:



   1: private static void AddConfig(Configuration cfg)
   2: {
   3:     new SchemaExport(cfg).Create(true, true);
   4: }

As I said, this is our chance to add our custom configuration to the session factory. I’m using a SchemaExport object to tell the session factory that it should generate and export the SQL’s DDL commands upon initialization. Important Note – Some systems use NHibernate to map an existing database, while others create a brand new one for a new system – while SchemaExport is obviously very useful in the development process, you should still manually export changes to your integration and production environments – be careful not to use SchemaExport on a database you DON’T WANT TO DROP.


Lastly:



   1: using (ISession session = OpenSession())
   2: using (ITransaction tx = session.BeginTransaction())
   3: {
   4:     person = new Person { Name = "Matan" };
   5:     session.Save(person);
   6:     session.Flush();
   7:     tx.Commit();
   8: }

We use the session factory’s OpenSession method to start a new session, we that use the session to explicitly begin a new transaction. If I hadn’t opened a transaction explicitly, the session would have opened one implicitly and committed it when required. Keep in mind that once you open a transaction, unless you commit it yourself it’ll be rolled-back. The session.Flush method isn’t required here since it precedes a commit and that would have triggered a flush automatically, but remember that:



  • The session will try to make the minimum possible database requests to achieve maximum efficiency. When using Session.Save you only add your entity to the session’s list of references (AKA first level cache), the actual insert command will only be executed when a flush is called (either by the user or by the active transaction). UNLESS… we use a database mechanism to generate primary keys (such as SQL Server’s Identity or Oracle’s sequence) which forces our session to go directly to the database on every Save command – not very efficient, is it? There are better ways, read more here. But let’s keep it simple for now.
  • The database understand transactions, and only transactions – even if you only query data. If you won’t open one yourself it’ll be opened implicitly and that may lead to performance issues, running 3 different Get methods without opening a transaction could lead to 3 different transactions. As a best practice, make sure to begin a transaction explicitly and commit it when you’re done with it – even if you only run queries! More on session and transaction management later on.

Well, we now have a session factory that persists our entities using our mappings, but what else can we do with a session? Find out in the next part – Session and Transaction.

Sunday, April 24, 2011

NHibernate Tutorial, Part 2 – Modeling Our Domain

This is part 2 of my NHibernate tutorial, make sure to start from part 1.

It’s time to use NHibernate to model our entities.

What are the different ways to model an entity?

NHibernate originally supported two means of entity modeling (both of which are not ideal):

  • Xml – using hbm.xml files to define mappings via the nhibernate-mapping-2.0.xsd schema. Xml files on the other hand, are, well, Xml files – they don’t compile and the intellisense is poor. (AND I JUST HATE XML FILES! there, I’ve said it! Meta programming is great in theory but frustrating in practice).
  • Attributes – using .Net Attributes from NHibernate.Mapping.Attributes. the attributes create clutter in classes and they couple our entities to NHibernate since unlike Java’s JPA, .Net doesn’t have a common persistence API meaning we have to use NHibernates attributes directly.

Luckily, we now have better alternatives. I’m going to use FluentNHibernate since I really like the simple and elegant API. An alternative is ConfORM, which is integrated in the NHibernate 3.2 release.

Using Fluent NHibernate

Let’s rebuild our domain from scratch, this time even simpler:

Create a new class library named “Entities”, add the following classes:

public class Store
{
    public Store()
    {
        Branches = new HashSet<Branch>();
    }
 
    public virtual int Id { get; protected set; }
    public virtual string Name { get; set; }
    public virtual Person Contact { get; set; }
    public virtual ICollection<Branch> Branches { get; set; }
}
 
public class Branch
{
    public virtual int Id { get; set; }
    public virtual Store Store { get; set; }
    public virtual Person Manager { get; set; }
}
 
public class Person
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}


It’s important to notice that all of our classes’ properties and methods must be virtual, that’s because of NHibernates use of proxies for lazy loading, but more on that later. For now, you can just use my vprop snippet to save time.



FluentNHibernate (from now on, FNH) maps entities using ClassMaps, which on initialization generate xml that’s similar to NHibernates classic hbm files.



Create a new class library named “Mapping”, since this is where we first use NHibernate we’ll use Nuget to get the dependencies (install SP1 if you haven’t already, it’s in there):





  • Right click your project –> “Add Library Package Reference”nuget-step-1

  • Search online for FluentNHibernate and install it. notice it depends on NHibernate, which itself depends on other packages: nuget-step-2

  • Follow this post to make sure Nuget keeps your dependencies up to date without having to check them into you source control.


Let’s start with mapping our Person class, since it’s the simplest of the three. Add a new class to the mapping project named it PersonMap, it should look something like this:




 

   1: using Entities;
   2: using FluentNHibernate.Mapping;
   3:  
   4: namespace Mapping
   5: {
   6:     public class PersonMap : ClassMap<Person>
   7:     {
   8:         public PersonMap()
   9:         {
  10:             Id(p => p.Id).Column("id").GeneratedBy.Identity();
  11:             Map(p => p.Name).Column("name").Not.Nullable().Length(25);
  12:         }
  13:     }
  14: }


Let’s see what we have here:





  • On line 6 you can see we inherit from FNH’s ClassMap<> which makes this class a fluent mapper for Person.

  • On line 10 we define the class’s primary key using a lambda expression, making it refactor friendly. We also define SqlServer identity as the generator for the primary key and “id” as the database column name (later, we’ll use a convention for that, but let’s keep it simple for now). If we don’t define a column name it’ll be the property name by default, and if we don’t define a generator it’s native by default. Read some more here (keep in mind that I use Identity for simplicity, it’s probably NOT the best generator since it has to use the database to generate a new PK).

  • On line 11, again using a lambda expression, we define the Name property as a not nullable, 25 chars long column.


Moving on to the Store map:




 

   1: using Entities;
   2: using FluentNHibernate.Mapping;
   3:  
   4: namespace Mapping
   5: {
   6:     public class StoreMap : ClassMap<Store>
   7:     {
   8:         public StoreMap()
   9:         {
  10:             Id(s => s.Id).Column("id").GeneratedBy.Identity();
  11:             Map(s => s.Name).Column("name").Not.Nullable().Length(25);
  12:  
  13:             References(s => s.Contact);
  14:  
  15:             HasMany(s => s.Branches)
  16:                 .AsSet()
  17:                 .Inverse()
  18:                 .Cascade.SaveUpdate();
  19:         }   
  20:     }
  21: }
Let’s see what we have that’s new:



  • Using the References method on line 13 we define Contact as a reference, this will result in a Person foreign key in the Store’s table. I can specify the foreign key’s column name, but the default will be something like Contact_id.

  • Using the HasMany method we define that we have many branches, this will result in a foreign key of Store in the Branches table. We also define:



    • AsSet – the default behavior is AsBag, while a One-To-Many relation is actually more similar to a Set. Read more here.

    • Inverse – When defining a one-to-many relation, an update to the database can result in duplicate update statements, since both the “Many” entity and the “One” entity take responsibility for the relation and execute update. Declaring “Inverse” on the relation means “I’m not responsible for updating it”. Usualy the “Many” side is responsible since it holds the foreign key, in our case the Branch will have a reference to Store and that part of the relation will be responsible for updating it.

    • Cascade – defining the cascade as SaveUpdate means that when saving a new Store or updating an existing one will result in an attempt to save or update the branches in it’s branches collection. Read more here.


Lastly, let’s map our Branch entity:




 

   1: using Entities;
   2: using FluentNHibernate.Mapping;
   3:  
   4: namespace Mapping
   5: {
   6:     public class BranchMap : ClassMap<Branch>
   7:     {
   8:         public BranchMap()
   9:         {
  10:             Id(b => b.Id).Column("id").GeneratedBy.Identity();
  11:  
  12:             References(b => b.Manager);
  13:             References(b => b.Store);
  14:         }
  15:     }
  16: }


Finally, nothing new here. Smile



The previous map will comply to the following database schema:



erd



But for you guys to see it for yourselves, you’ll have to configure a SessionFactory, more on that in the next part – Configuration.

Creating a virtual property code snippet

Hi,

For those of you who use NHibernate, you must know by now that NHibernate forces us to declare our entity’s methods and properties as virtual since it uses proxies to implement lazy load of relations.

I created a small code snippet called vprop – same as prop only virtual.

It looks likes this:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>vprop</Title>
            <Shortcut>vprop</Shortcut>
            <Description>Code snippet for an automatically virtual implemented property
Language Version: C# 3.0 or higher</Description>
            <Author>matang</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[public virtual $type$ $property$ { get; set; }$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Just make sure to save this xml to:


…\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets\vprop.snippet


And typing “vprop” followed by two Tabs will generate a virtual property.


Enjoy!

NHibernate Tutorial, Part 1 – Introduction

Hi everyone,

I’ve been working with NHibernate for almost two years now, and it’s been a pretty fun ride. Since I’ve learned a lot along the way I thought I should provide an NHibernate tutorial, specifically working with spatial entities since I don’t think there’s enough material out there on that topic.

Now, there’s a LOT of knowledge and good NHibernate tutorials there so I’ll try to give a link to another article where I see fit, starting with:

  1. A screencast tutorial from summer of NHibernate, for a more visual tutorial. I can’t say I’ve seen it since I’m more of a reading kind of guy, but I got the impression it’s good.
  2. NHibernate 3 Cookbook – a great book that that introduces real life NHibernate usages and tools.
  3. Oren Eini’s (AKA Ayende Rahien) blog – One of NHibernates contributors and the writer of a great software design blog.

I’ll also combine Domain Driven Design principles along with this tutorial, as we develop our own application. Let’s go.

Some History…

Let’s look at a simple example:

domain

Ignore the base class IntEntity for now, we’ll get to it later – just keep in mind that each of the above entities also has an Id property and a version property, both of type int.

Now, a single Store has many Branches, and a branch has a reference to it’s parent store. Also, each store has a reference to a Person who’s it’s contact, and each Branch has a person who’s it’s manager. A simple model in OO, but a bit more complex in a relational database:

erd

A property becomes a foreign key and we have a One-to-Many relationships – it’s up to us to make the conversion back and forth to objects. Now, we want our application to persist these entities while keeping the entities oblivious of the underlying mechanism.

If you’ve ever worked with ADO.Net or any other DAO framework, you know it means a lot of implementation (even if we auto-generate some code) – each entity has it’s own SQL queries for CRUD operations that requires manual implementation and maintenance, not to talk about inheritance modeling. Also, it doesn’t’ support refactoring since it’s based on pure SQL strings.

Oh, and did I mention we want the same entities to be persisted on Oracle10 and Sql Server 2008, and tested against Sqlite?

NHibernate to the rescue!

NHibernate is a mature, open source OR/M framework, which basically means it allows us to model our entities naturally as objects, and define how they should be be to the underlying RDBMS in a more declarative way. It was originally ported from Java’s Hibernate thought it has a life of it’s own for some time now.

Microsoft also provides an OR/M framework called Entity Framework, it’s not as mature but it’s growing fast and it has a great designer support, if that’s your cup of tea. Still, NHibernate is more mature and supports more features.

To start working with NHibernate, we need to map our model, configure our database connection and settings and actually use them in our application.

We’ll continue on the next part - Modeling Our Domain.

Friday, April 22, 2011

Entities vs. Value Objects

As I mentioned in a previous post,  our application would consist of multiple layers, one of which is the model layer – services, factories, entities and repositories (*cough* session? *cough*).

But what do we mean when we say entity? or more precisely, how do we identify our entities, and what’s the best way to manage them and express the rest of the data? Let’s start be defining entities and value objects:

Entities

An Entity is an object that’s defined uniquely by an identity, we’ll usually persist those objects and they’ll contain both data and behaviors. They are the core of our domain, and require careful and well-thought out design – what one application may refer to as a User is probably not what another system will. Entities will probably contain references to other entities and value objects, but more on that when we talk about aggregates.

As a best practice, entities should focus on their domain’s business logic and be ignorant to their infrastructural concerns, such as database persistence. That’s where OR/M frameworks come in handy, helping us keep our entity a POCO (or POJO in the Java world), unlike other approaches such as Active Records which delegates the entity with the persistence responsibility.

Value Objects

On the other hand, Value Objects are not being tracked and are not uniquely identified. The most common example is the address object – It has a few properties that together represents a conceptual whole but it has no identity. Keep in mind that your domain may use addresses as entities if they need to be tracked uniquely – a billing address of a customer is probably a value object while in the real-estate domain it could be a uniquely identified estate. Value objects van contain references to other entities and value objects, though probably not as frequently as entities.

As a best practice, value objects should be immutable and cheap to create. Immutable objects are by definition objects that don’t change their value after creation, such as String or DateTime. For more on that, go here.

Often, value objects will contain either data only (also referred to as a Data Transfer Object, DTO) or behavior only.

Summary

Entities are objects that have an identity by which they can be tracked, they are the core of our domain and should be designed as precisely as possible with help from our domain expert. Value objects are objects that help us express a conceptual whole in a reusable way, they should be cheap to create and immutable.

Tuesday, February 8, 2011

UX is everywhere!

I overheard a conversation today about gas stations and it made me think about why I keep filling gas at same company for the last couple of years. As a bike owner I don't really feel the rising prices of gas so my main consideration isn't money - what then makes me come back?

Oddly enough, the reason is User Experience. You see, I don't like to move my fat buttocks more than I have to, that's why I prefer using a credit card – I don't even need to get off of the bike thanks to the gas station's self-service user terminal. Yey.

The only thing I do need to do is enter my ID number and license plate number. While my ID number is obviously critical when paying with a credit card, the license plate should be optional since it's up to me to limit my card to specific vehicles, right? Well, most gas station companies don't think so since it's a required field! I bet it means nothing for most users… (either that, or I'm the proud owner of a vehicle licensed 11-111-11 for some time now).

My favorite gas station company is different because the terminal's user interface instructs me to enter my license plate number or press 'Enter' to continue. Silly as it may be, they get my money – others don't.

When designing a good UI don't make the user think – make him experience. Try to make that extra step forward in figuring out what he may want at any point, without clutter and noise. Definitely not an easy task, but if you won't take it somebody else will – and that might be a good enough reason to choose a competing product.

Wednesday, February 2, 2011

Introduction to Domain Driven Design

I’ll try to explain what DDD is all about in a nutshell as explained more broadly in this great free online pdf (a must read for every system architect IMHO), which in itself is a nutshell of this (so I‘ve heard) great book about DDD. It also includes other topics I figured I should add. If you find yourself dozing off while reading, feel free to jump straight to the Summary for a quick reference. Put yo’ helmets on.

What, Why and How?

Let’s start with a confusing diagram that sums it all up, yet means nothing at this point:

ddd

Confused? Let’s try and put some sense into it.

Developing a business application is all about increasing that business’ productivity by solving a real-world problem or automating a real-world business process, either way we’re dealing with a real-world Domain of entities, data and processes.

Domain Driven Design is in it’s core an approach to software design, which emphasizes the need to focus on the business domain in which the software operates, and model our software as a reflection of the real world. Why? because software is eventually made up of code, and the bigger the problem you’re trying to solve the more complex and messy it can get. Staying true to the “real world” keeps our software understandable, cohesive, easy to change in respect to the target domain and most importantly – do what we expect it to do, as it imitates reality. OO languages are best for this design method since they allow us to define entities and processes in an intuitive, language natural way.

Now, while the development team consists of experts in many technical areas, they are usually not experts in the business domain. Since you can’t produce a good solution to a problem you don’t fully understand we can conclude that In order to produce good quality software you must involve an expert of the business domain in the development process. (On a side note, agile mythologies also advocate for client involvement and frequent feedback, another aspect where agile and software design come together naturally).

Let’s take for example a simple domain, that of a restaurant’s shifts management – the manager plans the following month’s shifts and publishes them as drafts to his employees which fill out their preferences and constraints. The manager then assigns employees to shifts according considering their input and republishes the final schedule. Our mission – take that process online and automate whatever is possible.

While the team speaks in terms of classes, database and builds, the manager speaks in terms of waiters, bartenders and schedules. The first step then is to create a common domain language between the domain expert and the team, a language that will be used throughout the development process.

To start modeling your domain, ask the expert some guiding questions. Identify your entities with verbs being their behaviors (/ methods) and nouns being their attributes (/ properties). For example, we’ll ask the manager of the restaurant to describe his process from end to end, which may be something like:

“A manager publishes an empty schedule with shifts in it so that employees can fill our their constraints and preferences until a given deadline. After the deadline, the manager assigns employees to shifts with respect to those preferences, and publishes the following weeks’ schedule.”

From that sentence alone we can probably understand that we have an entity called manager and a process that includes that manager assigning employees to shifts according to their constraints and preferences. We’ll name that process “Planning”. We also have an entity called schedule, with a one-to-many relation to an entity called shift, which itself has a many-to-many relation with an entity called employee. The employee has a one-to-many relation to constraint and preference. The employee also fills out his constraints and preferences in a process we can name “Submitting”.  We can also infer that a schedule is attributed with a start date, an end date and a deadline. All that from a single sentence – its objects, nouns and verbs.

Manager, Employee, Planning, Submitting and the rest of the underlined words are now added to our domain language. By keeping the conversation active, we can find out more and refine our model and our language - maybe constraints and preferences are the same entity with a different attribute? Maybe the schedule’s start and end date shouldn’t exist and are only defined by the first and last shift in that schedule? and so on…

In these sessions with the domain expert, be as creative as you’d like and use whatever makes you communicate the best – diagrams, white boards and drawings. Make sure to sum it all up and keep an updated domain language reference.

Since I’d like to keep this post at a “readable” size, I’ll divide it into a series of posts (soon to be actual links):

  • Entities vs. Value Objects
  • Architecture – Separation and Interaction
  • Services, Aggregates, Factories and Repositories
  • Refactoring - Constraints, Processes and Specifications
  • Distillation and Generic Subdomains

Summary

When implementing DDD, make sure to:

  1. Identify your domain expert, involve him in the process and create a common domain language (The “Ubiquitous Language”).
  2. Model you domain into Entities and Value Objects according to the target domain, using:
    1. Aggregates to concentrate groups of entities and value objects under a single root entity.
    2. Services to implement stateless operations on multiple entities.
      1. Not to be confused with Web \ Wcf Services, we’re talking about Domain Services.
    3. Factories to separate creation of complex entities and their dependencies.
    4. Repositories to abstract the access to the data layer and stay loosely coupled from your implementation.
      1. Personally, I’m not sure that abstracting your data access framework is always a right decision, for example I do think that Service classes should include a property of ISession when using NHibernate, since the abstraction hides important features and it’s a price to pay, while OR/M isn’t something that you replace that quickly and may not need an abstraction.
  3. Separate a big project into smaller modules, each with it’s own domain model, and try not to overlap. Where you can’t avoid overlapping, communicating between teams is the key, along with automatic integration tests and a CI server.
    1. Define the relationship between you different models (Shared Kernel \ Customer-Supplier \ Anticorruption Layer \ Open Host Service) and make sure your teams act accordingly.
    2. An updated and publicly displayed context map helps to see the big picture and keep in mind the connections between the different modules’ contexts.
  4. Try to extract your core domain out of the entire domain and put you best people on it, that is what separates your application from the rest and that’s where your specialty should shine. for the other generic subdomains use one of the following:
    1. Off the shelf solution
    2. Existing model with an appropriate wrapping
    3. Outsourcing
    4. An in house implementation with lesser focus
  5. Avoid common pitfalls:
    1. Modelers should also code – keeping your hands dirty keeps you in tune.
    2. Don’t over-abstract, talk in real life scenarios – implement the next step ONLY while keeping in mind the following ten steps.
    3. Apply DDD only when it fits – it’s perfectly Ok to use DDD on one module and not on another, all in the same global domain, as long as the communication between you domains

 

Few technical tips

  1. Use an IoC framework, such as Castle WIndsor, Autofac or Spring.Net, after a small learning curve it’ll enhance your code’s maintenance.
  2. Inject dependencies as high as you can in the application, to make you code suitable for as many contexts as possible (NH Session management is a good example for why dependencies should be injected and not created).
  3. Use an OR/M framework and make sure that only the required project reference it and only the required classes use it.
  4. Separate your code into projects, make sure to stay on “need to reference” bases only, to make sure you’re classes aren’t being abused.
  5. Refactor, and then refactor again – if you’re afraid to refactor legacy code, write tests to cover it’s specs and then try again – it’ll even help you to better understand the requirements you’re implementing.
  6. Use TDD to think before you code, starting is hard but it’s addicting.
  7. Prototype anything you’re not sure of – performances, solution structure, etc..
  8. Define a set of contracts and DTO’s as a single point of interface between two modules, don’t reference the other module’s core – it’s not yours!
  9. COMUUNICATE – talk to you team, talk to you client, talk to your mother, just talk.

Want to know more?

Read this or this, or visit the DDD group at: http://groups.yahoo.com/group/domaindrivendesign

Phshewwww, that was long, but now that we’ve armed ourselves and laid down our design principles let’s get practical – in the next couple of posts we’ll be applying those tools and principles on our own application, using frameworks and tools like WCF, FubuMVC, NHibernate, Automapper and more.

For now, happy modeling.