Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Business Primitives (2/2)

Ok, so now that we have talked about the Business Primitive concept lets go through some of the actual examples. Let’s take an example of a ‘Loan’ class.

public class Loan
{
    public int Id { get; set; }
    public int InterestRate { get; set; }
    public DateTime TradedOn { get; set; }
    public DateTime SettledOn { get; set; }
    public decimal Principal { get; set; } 
}

After some small tweaks.

public class Loan
{
    public int Id { get; set; }
    public Rate Interest { get; set; }
    public DateTime TradedOn { get; set; }
    public DateTime SettledOn { get; set; }
    public Money Principal { get; set; }
}

Already the code feels more robust to me. The dates aren’t that interesting to the business other than they are dates so they haven’t yet been uplifted into ‘business primitives’ but Interest has been converted to ‘Rate’, which immediately helps with math and providing meaningful math like methods, as well as Principal which is now ‘Money’ which also helps with math and the more pernicious rounding issues.

So how was ‘Rate’ implemented? What does it look like?

[DebuggerDisplay("{_rate}%")]
public class Rate
{
    int _rate;
    private Rate() { }
    
    //factory methods
    public static Rate FromWholePercent(int rate) { new Rate(){_rate = rate};}

    //equality overrides here
    //operator overrides here
} 

First, we have the ‘DebuggerDisplay’ attribute which is my new best friend, it allows you to customize how the debugger displays your object in the debug view, very helpful. I have wrapped the previous rate value in a very simple fashion, and now we have a nicely centralized place to put math based functions (myRate = baseRate+riskRate). I have also added a factory method that help explain how this Rate object is being made. From whole percents such as 78% or 22%. Because we have hidden the way we actually store the value, we could also add support for 22.2% by adding a new factory method and changing the internal storage with out changing any other part of the code base. Very cool.

Ok, so what about saving these value objects and now I need to bind them to the UI how do I get at that hidden variable? I have taken quite a few paths when trying to implement this and the way that I do things now is a combination interface + base class. If you are anything like me you are thinking ‘base class, yuck’ and well I still do but this is the best way that I have come up with and I am open for suggestions. :)

So my ‘business primitives’ inherit from an abstract class called ‘Primitive<T>’ this class helps to streamline the creation of my business primitives. It also EXPLICITLY implements an interface called ValueObject<T> that exposes the underlying value, that can be used by UI controls and persistance frameworks with out mucking up my public API. I love that I don’t see ‘SetValue’ and ‘GetValue’ unless I want to (yes, this could have been a property, not sure why I choose this). Here is the interface:

public interface ValueObject<T>
{
    void SetValue(T input);
    T GetValue();
}

and the base class

[DebuggerDisploy("{_primitiveValue}")]
public class Primitive<T> :
    ValueObject<T>
{
    T _primitiveValue;

    public Primitive()
    {
    }

    public Primitive(V primitiveValue)
    {
        _primitiveValue = primitiveValue;
    }

    void ValueObject<T>.SetValue(T input)
    {
       _primitiveValue = input;
    }

    T ValueObject.GetValue()
    {
        return _primitiveValue;
    }
        
    //equality stuff
}

I really wanted to do some tricky generics to try and implement the operator overloads in the base class as well, but the compiler wasn’t to happy about that so those still have to be implemented in the ‘Rate’ class. Now my ‘Rate’ object looks like this:

public class Rate :
    Primitive<int>
{
    private Rate() { }
    private Rate(int value) : base(value){}

    //factory methods
    public static Rate FromWholePercent(int rate) { new Rate(rate);}

    //operator overloads should be implemented here

    public bool Equals(Rate other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return base.Equals(other);
    }
} 

For saving these buggers? Well, using NHibernate we can persist this as an ‘int’ using an IUserType, which makes things very simple and still manages to keep NH out of our domain.
Some links on implementing IUserTypes

Otherwise, with the interface you now have the means to get access to the value, so customize for your needs!

Now that we have addressed the saving aspect, what’s a good way to present these ‘business primitives’? Because

inputLoanPrincipal.Text = loan.Principal.ToUiString();

sucks. I would suggest some extension methods on your UI controls that take Primitive<T> as the type and can then cast to the ValueObject and get access to the value. Or extending the UI binding much in the way FubuMVC has, seems like a really solid way to approach things too.

I hope this helps :)

-d

About Dru Sellers

Sr. Software Engineer at Dovetail Software.
This entry was posted in Small Ideas. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://odalet.wordpress.com Olivier

    Suggestion to get rid of the Primitive base class:
    because, it seems to only contain boilerplate code, it could be generated by a T4 macro as a partial class containing roughly the interface implementation + constructors code

    By the way I think generating complex code is a bad habit: generated code should be easily readable and should be such it could have been written by hand… complexity should be in framework & support classes. In your case, the Primitive base class seems be a perfect candidate for generation.

  • http://simon-says-architecture.com/ Szymon Pobiega

    I created a base type for my DDD value objects when implemening .NET version of DDDSample application. My approach was to move all (in)equality checks to base class so that they don’t have to be tested for each value object class. I created an abstract method GetAtomicValues()-> IEnumerable which must be implemented in derived class to allow Equals and GetHashCode to work correctly. I have also methods for operator overloads but, as you said, operators themselves must be placed in leaf classes. Source is available here:

    http://dddsamplenet.codeplex.com/SourceControl/changeset/view/40819#519316

  • Markus Zywitza

    @Ollie

    A primitive is to me, well a primitive type. Anything more complex, like the combination of Amount and Currence, is a type, a value type, a struct or whatever, but not a primitive.

  • Jeff Sternal

    I really enjoyed the first article and parts of this one, but I really don’t understand what value the Primitive class provides or what problems it solves.

    Is it really just saving you the trouble of writing getters, setters, and a constructor for your business primitives?

    That hardly seems worth the sacrifice of picking up a dependency on a base class. What’s the drawback of using a POCO here?

  • http://www.josheinstein.com Josh Einstein

    Very cool. I am a little bit disappointed that you already set an upper bound on the article parts. I really think you could go on and on with this topic and I’m working on a follow-up piece myself.

    A couple things… 1) The use of DebuggerDisplay is very cool. I have not been doing that in my business primitives but I’m going to start. 2) I don’t really agree with the use of a base class here because things like Rate/Money seem like they should be structs, not classes. Typically I’ll choose a class when the business primitive wraps a string or other reference type and I’ll use a struct when it wraps a value type.

    As for participating in UI bindings, depending on whether you’re using Silverlight or WPF it really helps to create a corresponding TypeConverter or IValueConverter implementation to go back and forth from string so that you can easily bind it to existing controls.

    Have you looked at Paul Stovell’s post about “Enforced Strings”? I like the term “Business Primitive” better personally but he’s effectively talking about the same thing.

  • http://www.josheinstein.com Josh Einstein

    Very cool. I am a little bit disappointed that you already set an upper bound on the article parts. I really think you could go on and on with this topic and I’m working on a follow-up piece myself.

    A couple things… 1) The use of DebuggerDisplay is very cool. I have not been doing that in my business primitives but I’m going to start. 2) I don’t really agree with the use of a base class here because things like Rate/Money seem like they should be structs, not classes. Typically I’ll choose a class when the business primitive wraps a string or other reference type and I’ll use a struct when it wraps a value type.

    As for participating in UI bindings, depending on whether you’re using Silverlight or WPF it really helps to create a corresponding TypeConverter or IValueConverter implementation to go back and forth from string so that you can easily bind it to existing controls.

    Have you looked at Paul Stovell’s post about “Enforced Strings”? I like the term “Business Primitive” better personally but he’s effectively talking about the same thing.

  • Ollie Riches

    @Markus

    ‘Depending on what you need for money, sometimes even three or four pieces of data are required (transaction date and exchange rate in addition to amount and currency). ‘

    Aren’t you mixing the usage of the primitive with the structure of the primitive?

    Agreed that Currency would have to be primitive of money.

  • Markus Zywitza

    Well, interesting, but what do you do with Money?

    Is it just a masked System.Decimal? If you are taking the approach seriously, you will need
    ValueObject
    Primitive

    Depending on what you need for money, sometimes even three or four pieces of data are required (transaction date and exchange rate in addition to amount and currency). After all, value objects don’t stay primitives for long. You are admitting this when you write that the rate could be combined from a base rate and a risk rate, so even rate is transforming into a complex object.

    I predict this transformation for all kind of value objects which is why we shouldn’t use primitives but types for them. Classifying those types as business primitives doesn’t remove the notion that they are primitives, thus making them harder to develop away from the primitive start.

    I’d rather take another way: If you need a primitve access to a complicated value object, create an interface for that primitive and implement it in the value object:

    public class Rate : IPrimitive {…}
    public class Money : IPrimitive, IPrimitive {…}

    allows users to handle part of the value object handling with defaults for the rest: When using IPrimitive for Money, USD can be used for Currency by default. A base class, however, restricts such a system too much as there isn’t enough orthogonal behaviour in value objects.

  • Ollie Riches

    So we can’t have interest rates that aren’t whole numbers?