Avoid anemic domain models by empowering your objects

Ka Wai Cheung on January 16, 2017

One of the common anti-patterns I see in a lot of object-oriented code today (including my own) is what Martin Fowler refe... [Read Full]
This is a single comment view full discussion

Your article illustrates a problem that is hard to model nicely in classic OO, requiring a bunch of nuanced code to overcome these shortcomings. I'd argue that inter-mixing data and "process" is a consequence of these shortcomings.

Since you're using C#, I'll illustrate how this problem would be more appropriately modeled in F#. We'll start by modeling a type that encodes the activity date:

type ActivityDate = 
    | ArbitraryDate of DateTime
    | Today

Here we've declared a sum type (aka discriminated union) that encodes all the information necessary to determine if the activity date is EITHER an arbitrary date, OR a value that indicates that the user is filtering on today's activity. Now we'll define the actual domain model:

type ActivityFilter = { activityDate : ActivityDate; /* Hiding the other properties */ }

As you can see, we require one fewer properties than the C# example in order to convey the same amount of information.

Take a moment to consider how much code was required in the C# examples to determine the actual date we need to filter on. Here's how that would look in F#:

let getFilterDate activityDate = 
    match activityDate with
    | ArbitraryDate date -> date
    | Today -> DateTime.Now.Date

In a grand total of 8 lines of code, we've modeled the same problem in a much cleaner, more straightforward way. Debating where the methods that operate on our domain models should live is largely an exercise in bike shedding. Instead, we should be asking if the languages and paradigms we use are anemic.

code of conduct - report abuse