Creating an immutable value object in C# – Part IV – A class with a special value

Other posts:

  • Part I – Using a class
  • Part II – Making the class better
  • Part III – Using a struct
  • In the last post we looked at structs as ways to implement immutable value objects and we discovered that they have several issues.

    A good thing about the struct implementation was the introduction of an explicit ‘special value’ instead of ‘null’. I personally like doing that because it forces me to think about what are the special values in my domain instead of blindly rely on null and its semantics. Plus, it also works where null breaks down, when there are multiple special values.

    Having explicit special values is obviously not related to structs in any way. You can use the same pattern with classes as well, but you have to manage ‘null’ values that can enter your API. Here is how I did it for the DateSpan class.

    First I defined an utility function to manage null values:

        public static void CheckNull<T>(T t) {
    
            if (t == null)
                throw new ArgumentNullException();
        }

    Then I had to check my null precondition for each parameter of my API. I.E.

        public DateSpan Intersect(DateSpan other) {
    
            Utils.CheckNull(other);
            ...
        }

    Most importantly I now have to check for null in ‘Equals’ and ‘==’:

        public override bool Equals(object obj) {
    
            // Interesting choice, null is not valid in this domain
            Utils.CheckNull(obj);
    
            if (this.GetType() != obj.GetType()) return false;
    
            DateSpan other = obj as DateSpan;
    
            return other.End == End && other.Start == Start;
        }
        public static Boolean operator ==(DateSpan v1, DateSpan v2) {
    
            Utils.CheckNull(v1);
            Utils.CheckNull(v2);
    
            return (v1.Equals(v2));
        }

    So now we have an immutable value object, represented as a class, with checks for nulls and a special value (not shown above because it is essentially the same as for structs). So, does this work?

    It does, but it is cumbersome to write. And if it is too cumbersome, I already know that I’m not going to use it. I might start doing it, but I would soon give up. Are there ways to ease the pain?

    One way would be to use snippets to help in writing the code. Snippets in this case have a couple of problems:

    • It is not easy to ‘snippify’ the logic inside ‘Equals’, ‘GetHashcode’ and such
    • It makes easy to write the code, but still it is hard to read it and maintain it

    In the next post we’ll look at a better solution.

    Advertisements

    Creating an immutable value object in C# – Part III – Using a struct

    Other posts:


    In Part II I talked about the asymmetry created by using ‘null’ as the special value for our little DateSpan domain. We also noticed the boredom of having to implement Equals, GetHashCode, ‘==’ and ‘!=’ for our value objects. Let’s see if structs solve our problem.


    Well, to the untrained eye they do. Structs cannot be null and they implement Equals and GetHashCode by checking the state of the object, not its pointer in memory.


    So, have we found the perfect tool to implement our value object?


    Unfortunately, no. Here is why a struct is a less than optimal way to implement a value object:



    1. Convenience issues – it is not as convenient as it looks

      1. You still have to implement ‘==’ and ‘!=’.
      2. You still want to implement Equals() and GetHashCode(), if you want to avoid boxing/unboxing.

    2. Performance issues – it is not as fast as it looks

      1. Structs are allocated on the stack. Every time you pass them as arguments, the state is copied. If your struct has more than a few fields, performance might suffer

    3. Usability issues – it is not as useful as it looks.

      1. Structs always have a public default constructor that ‘zeros’ all the fields
      2. Structs cannot be abstract
      3. Structs cannot extend another structs

    Don’t get me wrong, structs are extremely useful as a way to represent small bundles of data. But if you use value objects extensively, their limitations start to show.


    A case could be made that you should use struct to implement value objects if the issues exposed above don’t apply to your case. When they do apply, you should use classes. I’m a forgetful and lazy programmer, I don’t want to remember all these cases. I just want a pattern that I can use whenever I need a value object. It seems to me that structs don’t fit the bill.


    For the sake of completeness, here is the code for DateSpan using a struct. Note that I explicitly introduced a ‘special value’ instead of using null (which is not available for structs).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public struct DateSpan {

    public static DateSpan NoValueDateSpan { get { return noValueDateSpan; } }

    public DateSpan(DateTime pstart, DateTime pend) {

    if (pend < pstart)
    throw new ArgumentException(pstart.ToString() + ” doesn’t come before “ + pend.ToString());
    start = pstart;
    end = pend;
    hasValue = true;
    }

    public DateSpan Union(DateSpan other) {

    if (!HasValue)
    return other;

    if (!other.HasValue)
    return this;

    if (IsOutside(other))
    return DateSpan.NoValueDateSpan;

    DateTime newStart = other.Start < Start ? other.Start : Start;
    DateTime newEnd = other.End > End ? other.End : End;

    return new DateSpan(newStart, newEnd);
    }

    public DateSpan Intersect(DateSpan other) {

    if (!HasValue)
    return DateSpan.NoValueDateSpan;

    if (!other.HasValue)
    return DateSpan.NoValueDateSpan;

    if (IsOutside(other))
    return DateSpan.NoValueDateSpan;

    DateTime newStart = other.Start > Start ? other.Start : Start;
    DateTime newEnd = other.End < End ? other.End : End;

    return new DateSpan(newStart, newEnd);
    }

    public DateTime Start { get { return start; } }
    public DateTime End { get { return end; } }
    public bool HasValue { get { return hasValue; } }

    // Making field explicitely readonly (but cannot use autoproperties)
    // BTW: If you want to use autoproperties, given that it is a struct,
    // you need to add :this() to the constructor
    private readonly DateTime start;
    private readonly DateTime end;
    private readonly bool hasValue;

    private bool IsOutside(DateSpan other) {

    return other.start > end || other.end < start;
    }

    // Changing the internal machinery so that hasValue default is false
    // This way the automatically generated empty constructor returns the right thing
    private static DateSpan noValueDateSpan = new DateSpan();

    #region Boilerplate Equals, ToString Implementation

    public override string ToString() {
    return string.Format(“Start:{0} End:{1}”, start, end);
    }

    public static Boolean operator ==(DateSpan v1, DateSpan v2) {

    return (v1.Equals(v2));
    }
    public static Boolean operator !=(DateSpan v1, DateSpan v2) {

    return !(v1 == v2);
    }

    //public override bool Equals(object obj) {

    // if (this.GetType() != obj.GetType()) return false;

    // DateSpan other = (DateSpan) obj;

    // return other.end == end && other.start == start;
    //}

    //public override int GetHashCode() {

    // return start.GetHashCode() | end.GetHashCode();
    //}

    #endregion
    }

    TimeLineAsStruct.zip

    Bisection-based XIRR implementation in C#

    Here is a quick implementation of XIRR (using Excel nomenclature) written in C#.


    Disclaimer: this is a super simple Bisection-based implementation. People tend to prefer the Newton method, but this is simpler and works for the app I’m writing. I decided to post it because I couldn’t find one on the net when I looked for it. I attached testcases to show the extent of my testing.


    It is called CalculateXIRR and it is invoked by passing a list of cash flows, a tolerance and a max number of iterations.

    using System;
    using System.Linq;
    using Money = System.Decimal;
    using Rate = System.Double;
    using System.Collections.Generic;

    public struct Pair<T, Z> {

    public Pair(T first, Z second) { First = first; Second = second; }

    public readonly T First;

    public readonly Z Second;

    }


    public class CashFlow {

    public CashFlow(Money amount, DateTime date) { Amount = amount; Date = date; }

    public readonly Money Amount;
    public readonly DateTime Date;
    }

    public struct AlgorithmResult<TKindOfResult, TValue> {

    public AlgorithmResult(TKindOfResult kind, TValue value) {

    Kind = kind;
    Value = value;
    }

    public readonly TKindOfResult Kind;
    public readonly TValue Value;
    }

    public enum ApproximateResultKind {
    ApproximateSolution,
    ExactSolution,
    NoSolutionWithinTolerance
    }

    public static class Algorithms {

    internal static Money CalculateXNPV(IEnumerable<CashFlow> cfs, Rate r) {

    if (r <= -1)
    r= -0.99999999; // Very funky … Better check what an IRR <= -100% means

    return (from cf in cfs
    let startDate = cfs.OrderBy(cf1 => cf1.Date).First().Date
    select cf.Amount / (decimal) Math.Pow(1 + r, (cf.Date – startDate).Days / 365.0)).Sum();
    }

    internal static Pair<Rate, Rate> FindBrackets(Func<IEnumerable<CashFlow>, Rate, Money> func, IEnumerable<CashFlow> cfs) {

    // Abracadabra magic numbers …
    const int maxIter = 100;
    const Rate bracketStep = 0.5;
    const Rate guess = 0.1;

    Rate leftBracket = guess – bracketStep;
    Rate rightBracket = guess + bracketStep;
    var iter = 0;

    while (func(cfs, leftBracket) * func(cfs, rightBracket) > 0 && iter++ < maxIter) {

    leftBracket -= bracketStep;
    rightBracket += bracketStep;
    }

    if (iter >= maxIter)
    return new Pair<double, double>(0, 0);

    return new Pair<Rate, Rate>(leftBracket, rightBracket);
    }

    // From “Applied Numerical Analyis” by Gerald
    internal static AlgorithmResult<ApproximateResultKind, Rate> Bisection(Func<Rate, Money> func, Pair<Rate, Rate> brackets, Rate tol, int maxIters) {

    int iter = 1;

    Money f3 = 0;
    Rate x3 = 0;
    Rate x1 = brackets.First;
    Rate x2 = brackets.Second;

    do {
    var f1 = func(x1);
    var f2 = func(x2);

    if (f1 == 0 && f2 == 0)
    return new AlgorithmResult<ApproximateResultKind, Rate>(ApproximateResultKind.NoSolutionWithinTolerance, x1);

    if (f1 * f2 > 0)
    throw new ArgumentException(“x1 x2 values don’t bracket a root”);

    x3 = (x1 + x2) / 2;
    f3 = func(x3);

    if (f3 * f1 < 0)
    x2 = x3;
    else
    x1 = x3;

    iter++;

    } while (Math.Abs(x1 – x2)/2 > tol && f3 != 0 && iter < maxIters);

    if (f3 == 0)
    return new AlgorithmResult<ApproximateResultKind, Rate>(ApproximateResultKind.ExactSolution, x3);

    if (Math.Abs(x1 – x2) / 2 < tol)
    return new AlgorithmResult<ApproximateResultKind, Rate>(ApproximateResultKind.ApproximateSolution, x3);

    if (iter > maxIters)
    return new AlgorithmResult<ApproximateResultKind, Rate>(ApproximateResultKind.NoSolutionWithinTolerance, x3);

    throw new Exception(“It should never get here”);
    }

    public static AlgorithmResult<ApproximateResultKind, Rate> CalculateXIRR(IEnumerable<CashFlow> cfs, Rate tolerance, int maxIters) {

    var brackets = FindBrackets(CalculateXNPV, cfs);

    if (brackets.First == brackets.Second)
    return new AlgorithmResult<ApproximateResultKind, double>(ApproximateResultKind.NoSolutionWithinTolerance, brackets.First);

    return Bisection(r => CalculateXNPV(cfs,r), brackets, tolerance, maxIters);
    }
    }

    // TESTS
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Collections.Generic;
    using System;
    using Rate = System.Double;

    namespace TimeLineTest
    {
    [TestClass()]
    public class AlgorithmsTest {

    IEnumerable<CashFlow> cfs = new CashFlow[] {
    new CashFlow(-10000, new DateTime(2008,1,1)),
    new CashFlow(2750, new DateTime(2008,3,1)),
    new CashFlow(4250, new DateTime(2008,10,30)),
    new CashFlow(3250, new DateTime(2009,2,15)),
    new CashFlow(2750, new DateTime(2009,4,1))
    };

    IEnumerable<CashFlow> bigcfs = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(10, new DateTime(2002,1,2)),
    new CashFlow(20, new DateTime(2003,1,3))
    };

    IEnumerable<CashFlow> negcfs = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(-1, new DateTime(2002,1,2)),
    new CashFlow(1, new DateTime(2003,1,3))
    };

    IEnumerable<CashFlow> samedaysamecfs = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(10, new DateTime(2000,1,1)),
    };

    IEnumerable<CashFlow> samedaydifferentcfs = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(100, new DateTime(2000,1,1)),
    };

    IEnumerable<CashFlow> bigratecfs = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(20, new DateTime(2000,5,30)),
    };

    IEnumerable<CashFlow> zeroRate = new CashFlow[] {
    new CashFlow(-10, new DateTime(2000,1,1)),
    new CashFlow(10, new DateTime(2003,1,1)),
    };

    IEnumerable<CashFlow> doubleNegative = new CashFlow[] {
    new CashFlow(-10000, new DateTime(2008,1,1)),
    new CashFlow(2750, new DateTime(2008,3,1)),
    new CashFlow(-4250, new DateTime(2008,10,30)),
    new CashFlow(3250, new DateTime(2009,2,15)),
    new CashFlow(2750, new DateTime(2009,4,1))
    };

    IEnumerable<CashFlow> badDoubleNegative = new CashFlow[] {
    new CashFlow(-10000, new DateTime(2008,1,1)),
    new CashFlow(2750, new DateTime(2008,3,1)),
    new CashFlow(-4250, new DateTime(2008,10,30)),
    new CashFlow(3250, new DateTime(2009,2,15)),
    new CashFlow(-2750, new DateTime(2009,4,1))
    };

    double r = 0.09;
    double tolerance = 0.0001;
    int maxIters = 100;

    private TestContext testContextInstance;

    public TestContext TestContext {
    get {
    return testContextInstance;
    }
    set {
    testContextInstance = value;
    }
    }

    [TestMethod()]
    public void CalculateXNPV() {

    Assert.AreEqual(2086.6476020315416570634272814M, Algorithms.CalculateXNPV(cfs, r));
    Assert.AreEqual(-10.148147600710372651326920258M, Algorithms.CalculateXNPV(negcfs, 0.5));
    Assert.AreEqual(4.9923725815954514810351876895M, Algorithms.CalculateXNPV(bigcfs, 0.3));
    }

    [TestMethod]
    public void FindBrackets() {

    var brackets = Algorithms.FindBrackets(Algorithms.CalculateXNPV, cfs);
    Assert.IsTrue(brackets.First < 0.3733 && brackets.Second > 0.3733);

    brackets = Algorithms.FindBrackets(Algorithms.CalculateXNPV, bigcfs);
    Assert.IsTrue(brackets.First < 0.5196 && brackets.Second > 0.5196);

    brackets = Algorithms.FindBrackets(Algorithms.CalculateXNPV, negcfs);
    Assert.IsTrue(brackets.First < -0.6059 && brackets.Second > -0.6059);
    }

    [TestMethod]
    public void XIRRTest() {

    var irr = Algorithms.CalculateXIRR(cfs, tolerance, maxIters);
    Assert.AreEqual(0.3733, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(bigcfs, tolerance, maxIters);
    Assert.AreEqual(0.5196, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(negcfs, tolerance, maxIters);
    Assert.AreEqual(-0.6059, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(samedaysamecfs, tolerance, maxIters);
    Assert.AreEqual(ApproximateResultKind.NoSolutionWithinTolerance, irr.Kind);

    irr = Algorithms.CalculateXIRR(samedaydifferentcfs, tolerance, maxIters);
    Assert.AreEqual(ApproximateResultKind.NoSolutionWithinTolerance, irr.Kind);

    irr = Algorithms.CalculateXIRR(bigratecfs, tolerance, maxIters);
    Assert.AreEqual(4.40140, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(zeroRate, tolerance, maxIters);
    Assert.AreEqual(0, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(doubleNegative, tolerance, maxIters);
    Assert.AreEqual(-0.537055, irr.Value, 0.001);
    Assert.AreEqual(ApproximateResultKind.ApproximateSolution, irr.Kind);

    irr = Algorithms.CalculateXIRR(badDoubleNegative, tolerance, maxIters);
    Assert.AreEqual(ApproximateResultKind.NoSolutionWithinTolerance, irr.Kind);
    }
    }
    }

    Creating an immutable value object in C# – Part II – Making the class better

    Other posts:



    In the previous post I showed how to trivially implement a value object. The code works but it has several issues. Some are very simple, others are more interesting.


    Let’s take a look at them:



    • State not explicitly read-only

    • Asymmetry in the usage of Union and Intersection

    • Small perf issue in the Union method

    The first problem is that my use of automatic properties doesn’t assure that the status of the object is immutable; I can still modify it from inside the class. The simple solution is to make the fields readonly and write the getters as in:

        private readonly DateTime start;
    private readonly DateTime end;

    public DateTime Start { get { return start; } }
    public DateTime End { get { return end; } }


    The second issue is more subtle. Consider this code

            DateSpan d1 = new DateSpan(new DateTime(1, 1, 2000), new DateTime(1, 1, 2002));
    DateSpan d2 = null;

    DateSpan r1 = d1.Intersect(d2);
    DateSpan r2 = d2.Intersect(d1);


    I would like things in my little ‘algebra’ to be symmetric. In this case I’d like: r1 == r2 == null. But this code throws in the last line as I’m trying to invoke a method on a null object.


    The traditional solution to this problem is to make Union and Intersect to be static methods, but then you loose the magic of calling them as instance methods (i.e. it becomes hard to chain them together as in d1.Intersect(d2).Union(d3).Intersect(d4)).


    Extension methods come to the rescue here as they allow you to create static methods, but to call them as if the were instance methods. The new code for Intersect looks like the following:

        public static DateSpan Intersect(this DateSpan one, DateSpan other) {

    if (one == null)
    return null;

    if (other == null)
    return null;

    if (one.IsOutside(other))
    return null;

    DateTime start = other.Start > one.Start ? other.Start : one.Start;
    DateTime end = other.End < one.End ? other.End : one.End;

    return new DateSpan(start, end);
    }


    This workaround would not work if the extension method needs to access private state of the class. In that case you would need to create a static method on the DataSpan class and invoke it from the extension method. Slightly more convoluted, but still doable.


    At a more philosophical level, the asymmetry issue happens here because I’m using something outside my domain of interest (the null value) to represent a special value inside my domain of interest. More on this as we talk about structs in upcoming posts.


    The last point is a very small one. In the Union method I am creating a new object unnecessarily in the following line:

            if (other == null)
    return new DateSpan(Start, End);

    I can obviously avoid it by just returning “this“.


    This post hints to several possible issues. Is it a good idea to use null to represent special values in my domain? What if I have more than one of them (i.e. positive/negative infinite)? Would using structs solve these problems?


    We’ll take a look at these options in upcoming posts. Attached is the modified code.

    Creating an immutable value object in C# – Part I – Using a class

    Other posts:



    Value objects are objects for which the identity is based on their state instead of their pointer in memory. For example, a numeric Complex class is, most of the time, a value object because you can treat two instances as the same if their state (real and img fields in this case) is the same. An immutable value object is a value object that cannot be changed. You cannot modify its state, you have to create new ones.


    I’m using these guys more and more in my code for a number of reasons, both practical and philosophical. The practical ones revolve around the greater robustness of programming without side effects and the greater simplicity of parallelizing your code. The philosophical ones are more interesting (and subjective). When in my design process I spend the time to aggressively looking for these kinds of objects, the resulting design ends up cleaner. I especially like when I can define some sort of “close algebra” for these guys (i.e. a set of functions that operate over them and produces new ones, not unlike ‘+’ and ‘-‘ for numbers).


    This series describes how to create immutable value objects in C# and the design decisions involved. This is a summary of an email thread I had with Mads and Luke.


    The concept I will use for this series is a DateSpan. As I define it, a DateSpan has a Start and an End date. You can ask for the DataSpan that represents the Union and Intersection of two DateSpans. The tests in the attached code better define the behavior of these operations.


    Given that I never use structs in my code (I’m a minimalist language user), I’ll start by using a class to represent it. We’ll make this class better in part II and use a struct in part III. A first stab at it is as follows:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public class DateSpan {

    public DateSpan(DateTime start, DateTime end) {

    if (end < start)
    throw new ArgumentException(start.ToString() + ” doesn’t come before “ + end.ToString());
    Start = start;
    End = end;
    }

    public DateSpan Union(DateSpan other) {

    if (other == null)
    return new DateSpan(Start, End);

    if (IsOutside(other))
    return null;

    DateTime start = other.Start < Start ? other.Start : Start;
    DateTime end = other.End > End ? other.End : End;

    return new DateSpan(start, end);
    }

    public DateSpan Intersect(DateSpan other) {

    if (other == null)
    return null;

    if (IsOutside(other))
    return null;

    DateTime start = other.Start > Start ? other.Start : Start;
    DateTime end = other.End < End ? other.End : End;

    return new DateSpan(start, end);
    }

    private bool IsOutside(DateSpan other) {

    return other.Start > End || other.End < Start;
    }

    public DateTime Start { get; private set; }
    public DateTime End { get; private set; }

    #region Boilerplate Equals, ToString Implementation

    public override string ToString() {
    return string.Format(“Start:{0} End:{1}”, Start, End);
    }
    public override bool Equals(object obj) {

    if (obj == null) return false;
    if (this.GetType() != obj.GetType()) return false;

    DateSpan other = obj as DateSpan;

    return other.End == End && other.Start == Start;
    }

    public override int GetHashCode() {

    return Start.GetHashCode() | End.GetHashCode();
    }

    public static Boolean operator ==(DateSpan v1, DateSpan v2) {

    if ((object)v1 == null)
    if ((object)v2 == null)
    return true;
    else
    return false;

    return (v1.Equals(v2));
    }

    public static Boolean operator !=(DateSpan v1, DateSpan v2) {

    return !(v1 == v2);
    }

    #endregion
    }

    public static class TimeLineExtensions {

    public static bool IsSuperSet(this DateSpan span, DateSpan other) {

    if (span.Intersect(other) == other)
    return true;

    return false;
    }
    }


    Some things to notice in this code:



    1. Defining a value object with a C# class involves overriding Equals, Hashcode, “==” and “!=”. It is tricky, but usually boilerplate stuff, well described in Wagner (2004). I don’t have Bill’s book in my office, so I kind of made it up on the fly. It could be very wrong (the ‘==’ one looks very suspicious). Don’t copy it, read Bill’s book instead
    2. Defining an immutable object with a C# class involves discipline in not changing the private state (we’ll see in Part II that we can do better than ‘discipline’)
    3. Notice the extension method IsSuperSet. This is something I picked up from an old Coplien book, probably this one. The concept is to keep methods that don’t use internal state of an object external to the object itself for the sake of future maintainability. The syntax for doing that was awkward before, but extension methods make it easier

    This works (it passes all the tests), but it has a number of problems. We’ll talk about these in Part II.

    TimeLineAsClass – 1.zip