Domain Specific Language and POCOs

I was thinking about POCOs last night and how they relate to the Ubiquitous Language Principle*.  To illustrate my thoughts, I created a simple 3-tier solution ins Visual Studio.  The User Layer is a Console Application that references the Business Layer.  The Business Layer then references the Data Layer.  The Data Layer uses Entity Framework to handle all of the CRUD with the actual database. 

 

image

 

Following good design, I know that my POCOs need to represent the domain objects that the application is acting on.  I also know that these domain objects need to be defined only once.  Also, because of the dependencies, the EF created classes should not be visible to the User Layer – if the UI references the data layer, then the simplicity of design and the chance of circular relationships and twisted logic increases significantly. 

Following that path, I created a POCO in my data layer.  I started with a Category Class:

image

Note the naming difference among properties between the Business Layer Category Class and the Data Layer Category Class.  I then wired up a CategoryFactory class that provides new Categories and acts on changes to altered categories – sort of a mish-mash between the GOF Factory and Builder pattern and the more-recent Repository pattern.

The first method I wrote was a select by id method:

public Category GetCategory(int id)
{
    NorthwindEntities entities = new NorthwindEntities();
    entities.Categories.Where(c => c.CategoryID == id).FirstOrDefault();
    return null;
}

The problem is immediately apparent.  I am selecting a Northwind.Data.Category from the data layer but I am returning a Northwind.Business.Category from the business layer.  I need some kind of translation method to handle the 2 classes.

public Category GetCategory(int id)
{
    NorthwindEntities entities = new NorthwindEntities();
    Northwind.Data.Category dataCategory = entities.Categories.Where(c => c.CategoryID == id).FirstOrDefault();
    return ConvertCategory(dataCategory);
}

private Category ConvertCategory(Northwind.Data.Category dataCategory)
{
    Category category = new Category()
    {
        Id = dataCategory.CategoryID,
        Description = dataCategory.Description,
        Name = dataCategory.CategoryName
        //TODO: Convert byte[] to picture 
    };
    return category;
}

This kind of solution introduces lots of code, which can be fixed using a POCO generator.  I still have a problem though – does having a Category in each layer violate the Ubiquitous Language Principle?  If you read Even’s description, the answer is “maybe” – he introduces the ULP so that business people can be specific in their requirements and talk in terms of the domain model.  Should the business experts even know about the data layer – probably not.  But what about 2 different sets of developers on the team – the business layer developers and the data layer developers?  When they talk about a Category in a meeting, which one?  Should they namespace it?  How about if we add the dbas to the meeting?  Their category is the actual representation on the database, which may or may not directly correspond to the data layer category which may not correspond to the business layer category.  Finally, what happens when the business expert talks to the dbas (a common occurrence when the reporting module is being developed separately).  The business expert might be talking Northwind.Business.Category and the dba is talking a Category table record. 

I don’t have a good solution, or even a good set of possible options:

1) Give every object a name that reflects not only their business meaning but their layer with the Cannon being the business layer.

CategoryDataTable

CategoryDataObject

Category

Yuck. And do you want to tell the DBA/Data Modeler that they have to rename their tables?  Good luck.

2) Always talk in namespaces in meetings.  For example. “Hey Joe, I noticed that the Data.Category object has a Description field.  Is it read-only?”  The Business.Category is not.  Less yucky, but requires a more specific lexicon that might drive your business experts nuts.  Also, note the variable name that I used in the transform method (dataCategory) – it is not really Hungarian notation because I am not using the type in the prefix, but I am using the namespace.  Yuck.

3) I don’t have an option #3.

As it stands, I option for #2 – I would rather be specific with my business experts and use some kind of Hungarian-notation bastardization. But I am not happy….

 

*   The Ubiquitous Language Principle is something I coined after reading chapter 2 of  Eric Evan’s Domain Driven Design

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: