Showing posts with label DDD. Show all posts
Showing posts with label DDD. Show all posts

Using Syntax to Model the Domain

I'm fascinated by the small syntactic decisions that bring code closer to representing the business domain. Never mind the class inheritance examples from text books ("Dog IS-A Pet," which has nearly never been relevant), I mean using properties, methods, and constructors to let the compiler ensure your objects stay in a valid state. Linguistically, I think this is neat.

Not everything deserves a setter


Consider my Bacon class with an IsCooked property:

public class Bacon
{
  public bool IsCooked { get; set; }
}

To cook some bacon, I set IsCooked to true. Sure. But what if I set it to false? I just defied physics and the space-time continuum. Shucks.

IsCooked should be read-only, and I need a different way to change it in a one-way transition: I need a method. Bacon comes into my domain uncooked, so I'll set that property in its constructor.

public class Bacon
{
  public bool IsCooked { get; private set; }

  public Bacon()
  {
    IsCooked = false;
  }

  public void Cook()
  {
    IsCooked = true;
  }
}

The sanctity of thermodynamics is preserved. When the transitions get more interesting than a simple Boolean, you're looking at a state machine.

Polywhatism?


I encountered this example in the wild, but I've changed the domain to protect the innocent.

We're exploring a dungeon, and in our inventory we have items that affect our health:
  • amulets add a small amount to our health each day;
  • granola bars give us a lump-sum boost to our health the moment we eat them; and
  • cursed rings sap away our health each day until the curse runs out. (Why keep a cursed ring? How else would you command your army of winged monkeys?)

Here's a display of our inventory:

ItemDaily BoostTotal Remaining
Obsidian amulet150
Luck ring(25)375
Jasper amulet253
Granola of righteousness400


This was implemented as a collection of IHealthItem objects. Here's what I found:

public class Amulet : IHealthItem
{
  public int? DailyBoost { get; set; }

  public int? Total
  {
    get
    {
      return null;
    }
    set
    {
      throw new NotSupportedException(
           "Amulets do not have a total");
    }
  }
}

As if the cursed rings weren't bad enough, now there are properties we're not allowed to call, lurking, waiting to pounce on us with a run-time exception. The calling code, when working with an IHealthItem instance, is forced to make an "Is" check to determine the type, in order to know which properties are safe to use. Half the properties aren't relevant half the time. The DailyBoost property on CursedRing has an additional problem: Should you set it to a negative number, or assume it should be stored as an absolute value and multiplied by -1 when being used and displayed? The IHealthItem interface does not provide any abstraction.

In fact, these are not three variations of the same thing. The only quality they have in common is the user's desire to see them displayed in a table. (Further proof that they weren't related, in the real application, that table was labeled "Amulets/Granola Bars/Cursed Rings.") These concepts should have been modeled as three independent entities, keeping it unambiguous in the business layer how to use them to increment and decrement the adventurer's health. Only at the presentation (UI) layer, they could be projected into a display-only DTO (Data Transfer Object) or view model, using strings for all three properties.

Don't let me be uninitialized


If a property must be set for an object to be in a valid state, the class's constructor should require that value as an argument instead. That way, it's impossible to construct the object without also putting it into a valid state.

If a method, MethodB(), uses a private field and relies on another method, MethodA(), to be called first to set it, MethodB should take that value as a parameter instead. That way, MethodB can be called only after the result of MethodA has been determined; the correct order in which to call them is unambiguous.

These types of temporal coupling are illustrated nicely with examples and remedies on Mark Seemann's blog in "Design Smell: Temporal Coupling." (He has a whole series on encapsulation.)

Too, meaning drives syntax


When I find myself compelled to explain in comments, to write instructions ("make sure you set this before you call that") in the xml summary, to incorporate usage notes into method names, I pounce on that as a candidate for refactoring. Finicky methods and classes that require secret knowledge to use correctly are invitations for bugs. It's like when I'm editing the rules for one of Jon's games: every instance of the word "except" must justify its existence. Every special-case exception immediately draws my attention as a spot where the rules could be improved and streamlined. Similarly, when coding, certain behaviors draw my attention as opportunities for improvement. Hyper-explainy documentation is a big one.

Semantics is the study of meaning, and syntax is the study of structure. That distinction makes them sound like separate domains, but the two interpretations of "foreign car mechanic" stem from syntactic ambiguity. Each word still carries the same meaning, but in one case "foreign" modifies "car," and in the other, "foreign" modifies "mechanic." Syntax in natural languages certainly influences meaning, so why not in code, as well?

Inconvenient Accessibility Makes Self-Documenting Code

Intentional use of access modifiers (public, private, etc.) is like a clear memo to your team. This came up during Steve Bohlen's Virtual Alt.Net talk on domain-driven design.

Steve explained the distinction between Entity objects, which have a unique identity independent of their properties (Even when I change my name, I'm still me.), and Value objects, which are defined by their properties (If you change the house number in an address, you have a new address.). When dealing with Entities, code should not be able to change the unique id—that would be like someone claiming your social security number and thereby becoming you. Therefore, Entity classes should have private setters for their unique identifiers.

A meeting attendee asked why, since this gets inconvenient when you're creating an object based on a record fetched from the persistence repository. It's a big pain; why bother? The analogy I would offer is this. When you're defining a class to represent an Entity in your business domain, you know it's an Entity. You intend for it to behave and be treated like an Entity. You don't want any of your teammates setting its unique id in their code. So you send them an email: "Don't set Person.UniqueId, okay?" Uh hunh. How well is that going to work over time?

Instead, if you simply don't provide a public accessor to the UniqueId property, your teammates will get the message loud and clear. Granted, someone could edit the code and change the accessibility, but the fact that he or she needs to is a flashing neon sign saying "Stop. Think. Are you barking up the wrong tree?" You've made your code communicative. Its structure conveys your intent. No need for comments; this is an example of self-documenting code.