Domain Objects: The Importance of State


When I stoked up Windows Live Writer, my intent was to write an entry about testing. Specifically, I was going to aim at testing the domain. Then I realized I had never written an entry on domain objects and thought it was a necessary place to start.

As a disclaimer, this article is not the be all, end all of explanations of domain modeling. If you want a full treatise, you would be best reading Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans. If you want to stick in the .NET world, Applying Domain Driven Design and Patterns by Jimmy Nilsson is also a good read.

What is a Domain?

Now this is the thousand dollar question. What is a domain? Rather than answer the question straight out, let’s look at a scenario. Picture a company that takes orders via phone (or Internet, if phone orders seem antiquated). There is an application to take an order, another to box the items in the warehouse and a third to ship the items to the customer.

If we look at this scenario from the database, we might see a schema much like the one below.

image|
Above taken from Adventure Works, SQL Server 2008 R2

Now, if we take the schema above, we can build each of the applications by mirroring the schema as objects in the applications. This is acceptable, but not optimal. In addition, we are potentially exposing sensitive customer data, like payment information, to employees who have no need to see the information.

Let’s talk about a customer for a second. In the ordering application, all of the customer information is important. We need to know the customer’s name, address or addresses (if there are different home, credit card and shipping addresses, for example), at least one telephone, and at least one form of payment information. This application may be served well by simply mirroring the database schema. In other words, in the order “domain”, we need all types of information about a customer.

When we move to the shipping domain, however, we only need a name, phone number and shipping address. The customer object may be better set up like the following C# code:

public class Customer
{
    public string Name { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    public string PhoneNumber { get; set; }
}

In the warehouse domain, we don’t really need to have a customer object at all, as we simply need to pick some items and put them in a box. To aid the application in the shipping domain, we can print out a order label that can be scanned.

In the above example, there is one application per domain, but we can have multiple applications in a single domain. We can, theoretically, have applications that cross multiple domains, but that is a concept beyond this post.

Now we can return to the question: What is a Domain? A domain is a specific area of influence for an application. In my examples, I use the idea of an order domain, a warehouse domain and a shipping domain. Perhaps a weak example, but it shows that an object can radically change from the expected object in a relational database. And that is worth the price of admission (currently free).

Creating Domain Objects

In general, a domain object is an object that holds state. While there are patterns, like Active Record, that have “smart” objects that contain behavior, the norm for the domain are containers that hold current information about an object, or its current state. The repository pattern, which separates behavior and state, is much more common today.

To put it in a way that jogs memory, just think of BS. Domain objects deal with the S (state) in BS (behavior and state) and not about the B (behavior).

Since we are only dealing with state, it is extremely easy to make our domain objects, as we can use the simple property format:

public class ObjectType
{
    public Type PropertyName { get; set; }
}

When I start a new project, the first folder I create is the domain folder. I then set up two projects, one for domain objects and another for domain specific exceptions. I will then determine whether or not to test the domain objects, which is the subject of the next post. The Visual Studio project will look something like this:

image

I will cover more of the project setup I use in future posts.

Important Points

  1. A domain is an area of influence. When we develop an application, we need to find the Subject Matter Expert (SME) in that domain and have them help us determine the domain objects.
  2. Domain objects handle state and do not deal with behavior.
  3. Domain objects should be a primary or “first” concern when developing an application.

See you at the next post, which covers the question “should I set up tests on domain objects?”

Peace and Grace,
Greg

Twitter: @gbworld

Advertisements

When “using” obfuscates (C#)


I was working on some code today for a intermediate service (internal WCF service that gets answers from another service and simplifies the output data model). Essentially, a public API service calls my service, which calls a BEA service, etc.

In order to understand the paging logic quickly, I examined some code from a previous developer. I found the following code to handle paging:

var reqPage = new MultiplePagingData {pageKey = count};
req.pagingData = reqPage;

Fairly simple. I create a MultiplePagingData object and add the pageKey and attach to the request object. Since much of the previous work was over simplified, I decided to take a look at MultiplePagingData and ensure I was not missing anything. Right click the line and it goes to the PagingData class. WTF? Due to my insanity, I tried this a few times, just to be sure (insanity being trying the same thing over and over and expecting different results).

Try from the other end? Okay, let’s find usings. And then the problem hit me. It was in the “using” statements. The developer was aliasing a class called PagingData.

using MultiplePagingData = Company.Project.Proxy.ServiceName.PagingData;

Ouch! Looks like something else to write up the code review.

Using is a wonderful keyword. It allows you to avoid fully qualifying all of your objects in your code, which greatly speeds up development. You see it at the top of every C# file:

using System;
using System.Collections.Specialized;
using System.Configuration;

It also serves to alias, with the intent being on creating short, easy to type keywords for namespaces. The primary reason for using the alias is when you have two libraries that contain classes with the same name. For example, suppose I have a customer object in two namespaces:

using customer1 = SomeCompany.Project.Subproject.Domain.Models;
using customer2 = SomeCompany.Project.Subproject.Domain.Models;

I then save a lot of typing, by specifying the customer like so:

customer1.Customer c = new customer1.Customer();

My searching now tells me it is perfectly legal to actually alias the class and call it whatever you want. In my brief testing in .NET 4.0, I have been unable to recreate this nightmare, however. If I had more time, I would play a bit and figure it out.

Now, perhaps someone has a good reason for aliasing an actual class. If so, I would love to hear it, as the code I am looking at merely obfuscates the code.

Peace and Grace,
Greg

Twitter: @gbworld