Money Pattern: An introduction to Value Objects
There is a saying that you can get away with just about any crime as long as you only commit it once. This is probably a hard-learned lesson for the Cobol developer employed by a major Norwegian bank back in the early nineties. He added a small “feature” which transferred subunits lost in rounding to his own account to a program running in the bank’s back office system. To cover his devious scheme, he only skimmed one transaction in ten. With the huge amount of money flowing through a banking system every day, this should be more than enough to give him a substantial “raise”. If he had stuck to one in ten, he might have gotten away with his crime, but as most crooks, he got greedy and started to skim even more transactions. By the time he was caught, he had stolen a whooping 500,000 Norwegian kroner (~$77,500).
Some years later, an insurance company was on the verge of bankruptcy after a claim for coverage of medical expenses made on a travel insurance policy. The amount of loss was ~100,000 Danish kroner (~$17.400) – a significant amount, but well within the risk reserve of any insurance company. Since the loss happened in Italy the amount of loss was specified in Italian Lire (Lire was the currency in Italy before the Euro was introduced). The payment solution made the assumption that every payment would be made in Danish Kroner and the 25,968,600 Italian Lire suddenly became 25,968,600 Danish Kroner.
These stories are urban legends circulating amongst developers about how monetary values have been misunderstood or exploited in enterprise applications. Like most urban legends, they’re probably exaggerated but there is probably some truth to them.
The common advice when handling monetary amounts in our applications is to use a high precision decimal type. In the Java world, authorities such as Martin Fowler and Joshua Block have for long recommended using java.math.BigDecimal for monetary operations. Others recommend using both a long and a short to express a monetary amount. There is little guidance on which type is the most appropriate in the .NET-space – but choosing a type only solves part of the problem.
As we saw in the insurance story, money is more than a number, currencies must be taken into account as well. Most developers understand this and do so when designing solutions. A common transaction system might have a transaction table with a corresponding business object, like the ones shown below.
The obvious design problem with the Transaction business object is the lack of cohesion between the amount and currency of the monetary value. When a domain specialist describes a transaction, she would probably talk about an amount, but not mention its currency unless it was central to the business problem being discussed. From the domain specialist’s point of view, the currency is intrinsic to the amount, so in the business domain the double and string is one cohesive unit.
The design decisions made when modeling the Transaction class seem to be driven by technical, rather than business considerations. The developer needed to map the individual rows in the Transactions table to a business object and mirrored the database schema in his class. In the database it makes sense to denormalize the currency and amount to allow queries like the one below.
SELECT SUM(amount) FROM Transactions WHERE currency=’USD’
Unless your RDBMS supports composite types, you would have to express the currency as a single alphanumerical column or a similar domain type. This would however be very inefficient with queries like the one above.
In your domain model you would benefit from expressing the amount and currency as a cohesive unit, rather than two separate properties. This would encapsulate the business logic for manipulating a monetary value, rather than having it scattered throughout the code. This will increase testability and reusability, reduce code duplication and reduce the risk of defects occurring in the code.
The amount and currency should be expressed as a Money value object. As opposed to an Entity, a value object does not have a conceptual identity – it just describes a characteristic of another object.
If we apply the notion of Entities and Value Objects to the Transaction domain, a Transaction is an Entity which must be uniquely identified. The identifier should be a business identifier, but it can also be a surrogate value if the Entity has no natural business identifier. If a Transaction moving $200 from account A to account B is canceled, we want to make sure that we cancel the specific transaction, rather than any transaction moving $200 between the accounts.
Even though a dollar bill has a serial number printed on it, we don’t really care which $200 we transfer. Unless you are the Federal Reserve Bank, the identity of a dollar bill does not matter. Hence in the Transaction domain the Money is a Value Object rather than an Entity.
Since we don’t care which instance we have of a Value Object, this pattern gives us huge freedom designing the type. Value Objects can be shared between different instances of a class, however we want to ensure that if one Transaction changes it’s amount, this should not change the amounts of other Transactions. To ensure that this does not happen, we need to make the Value Object immutable . With this in mind we can refactor the Amount and Currency properties of the Transaction to a Money structure.
Now we’ve got a cohesive Money type where the logic related to money can be contained.
The currency is usually expressed with a currency code such as USD or JPY. ISO 4217 is the standard describing these three letter codes. There is quite a few rules associated with a currency. We commonly associate currencies with the currencies used in different countries around the world. For instance the euro zone uses the Euro currency, Britons have their pounds and Americans their US Dollars. Naturally ISO 4217 standardize all of these currencies, but it also standardizes other entities such as precious metals like gold and silver, and Special Drawing Rights which are potential claims on the freely usable currencies of International Monetary Fund members.
For currencies the standard defines the relationship between the major currency unit and subunits of the currency. The subunit of the Norwegian Krone (NOK) is Øre, for US Dollars (USD) it is Cent. The subunit is often 1/100 of the major unit, but 1/10 or 1/1000 is also common. The Japanese Yen has the sub unit Sen, but this unit is not used. Some other currencies like the Mauritanian Ouguiya (MRO) does not use decimal division of units, but rather has a fixed relationship between units and sub units. One Ouguiya equals 5 Khoums.
The System.Globalization.RegionInfo class in the .NET framework can provide some information about currencies. The class does not support the entire ISO 4217 list, but the currencies supported should be sufficient for most scenarios. The documentation for the class lists all of these currencies and a list of ISO 3166 two and three letter ISO codes you can retrieve RegionInfo for. To programmatically list which currencies .NET supports we can iterate through the supported cultures and create RegionInfo objects for these. An example of this is shown below. Please note that since some countries use the same currencies, the list will include some duplicates.
public static void Main()
{
CultureInfo[] specificCultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
foreach (CultureInfo currentCulture in specificCultures)
{
RegionInfo currentRegion = new RegionInfo(currentCulture.Name);
Console.WriteLine(string.Format("{0} ({1})",
currentRegion.CurrencyEnglishName,
currentRegion.ISOCurrencySymbol));
}
}
With this in mind, we should use a specific type rather than a string to represent a currency.
Just like the Money class, the Currency class is a Value Object. Except for the Precision property, it’s property values are retrieved from RegionInfo objects using the technique described earlier. The Currency class maintains a private dictionary mapping the ISO currency symbols to instances of the Currency type. Rather than using a public constructor, you use the static factory method to retrieve a specific Currency. This is an example of one of the optimizations you can do with Value Objects. Since the Currency is an immutable type, different Money instances do not need their own private Currency instance. Instead they share Currency objects. If you have a thousand Money instances representing Russian Rubles, you only need one Currency instance to represent the Ruble currency. This optimization option is important because Value Objects tend to be numerous. Having a sole instance of a Value Object which is referenced by any number of other types is an example of the Flyweight pattern.
You should carefully consider how you optimize Value Objects. Having to create new copies of an object might take up a lot of memory, while distributed systems can take a severe performance hit from shared instances. In our Currency example it is safe to use a shared instance because the Currency type is strictly immutable.
The Currency type holds meta data about a currency. This meta data is important to the Money type, because it dictates the behavior of many monetary operations. Monetary calculations are not ordinary calculations. Let’s imagine that your team has been awarded a $1000 bonus which you need to split evenly between the three team members. Conventional math would tell you that each person should have $333 ⅓. The problem here is that there is no such thing as 33.33 cents. Cents can only be a whole number. You have two choices when splitting $1000 between three people; one of you can get lucky and get $333.34 while the others get a cent less – or you all get $333.33 and you throw away the last cent.
Lost cents was what the Cobol developer in the banking story took advantage of. On a small scale, lost cents might be acceptable, but judging from the amounts the Cobol programmer managed to skim, losing cents is not acceptable.
We therefore need to extend our Money type to cater for common monetary operations.
Above is a class diagram depicting the model for our Money type.
For convenience the Money type has a number of overloaded constructors, in addition the Currency type has an implicit cast operator allowing a string to be casted to a Currency. This gives a lot of flexibility when creating instances of the type.
public void DifferentWaysOfGettingMoney()
{
Money money;
// You can be very specific...
Currency usd = Currency.Create("USD");
money = new Money(usd, 42);
// ..or you can be implicit with less code.
money=new Money("USD",123.22);
}
Having a friendly interface for your model is important because it will be easier for people to use it. Enabling a string to be casted to a Currency will also increase the readability of the code and make it easier to refactor away from currencies being expressed as conventional strings.
To increase usability, you should also make Value Object behave like built-in types like System.Double. To achieve this you should provide implementations of the applicable operators for the type. For a simple value such as the Currency, you should overload the equality and inequality operators. For types representing quantities you should also overload arithmetic and comparison operators allowing quantities to be added, subtracted, divided or multiplied, and compared with other quantities.
[Test]
public void MoneyWithDifferentCurrenciesAreNotEqual()
{
Money m1 = new Money("USD", 42.4);
Money m2 = new Money("NOK", 42.4);
Assert.IsTrue(m1 != m2);
}
[Test]
public void LesserAmountWithSameCurrencyIsLessThanGreater()
{
Money lesser = new Money("USD", 10d);
Money greater = new Money("USD", 20d);
Assert.IsTrue(lesser < greater);
}
You can also give the Money type an ICurrencyConverter which in turn can be used to easily convert one currency to another. The currency converter could for instance use a Web Service to retrieve the conversion rate for two currencies.
[Test]
public void CanConvertCurrency()
{
// Please note that this test uses a fake to perform the
// conversion.
Money.CurrencyConverter = new FakeCurrencyConverter();
Money usd = new Money("USD", 123d);
Money nok = usd.ToCurrency("NOK");
Assert.AreEqual(Currency.Create("NOK"), nok.Currency);
Assert.AreEqual(usd.Amount*FakeCurrencyConverter.Ratio,
nok.Amount);
}
Solving the bonus allocation problem described earlier would require complex logic in the client code. Allocations are common when working with monetary values, so the Money type also supports operations like this.
[Test]
public void CanSolveFoemmelsConundrum()
{
Money[] allocations=new Money("USD", 0.05d).Allocate(3);
Assert.AreEqual(3, allocations.Length);
Assert.AreEqual(
new Money("USD", 0.05d), Money.Sum(allocations));
Assert.AreEqual(new Money("USD", 0.02d), allocations[0]);
Assert.AreEqual(new Money("USD", 0.02d), allocations[1]);
Assert.AreEqual(new Money("USD", 0.01d), allocations[2]);
}
The entire source code for the Money model can be downloaded here.
This articles has shown how you can use Domain-Driven Design techniques to write explicit code which helps encapsulate business rules, make the programming interface intention revealing, and increase the usability of an API. The Money pattern was first described by Martin Fowler in his Analysis Patterns book
and later revisited in Patterns of Enterprise Applications Architecture
. For the Java platform, there are quite a few libraries which implement this pattern. Most of these make use of the java.Math.BigDecimal class. This class is quite different from the System.Decimal structure in .NET. BigDecimal consist of an arbitrary precision integer unscaled value and a scale. The BigDecimal class gives users complete control over rounding, which makes it perfect for monetary operations. There are no types with similar fine-grained control in .NET, but you have the ability to control rounding of floating point numbers with the System.Math class.
I’ve seen some attempts to implement Fowler’s Money pattern on the .NET platform, but most of these have fell short of the usability of their Java counterparts.
Much of the data we process in our applications can be expressed as Value Objects. Whenever you only care about what, and not who a thing is, a Value Object is probably the appropriate choice. The Money pattern is a variation of the Quantity pattern. Other amounts that should be modeled as quantities are weight, dimensions and similar. Value Objects are not limited to dimensioned quantities. The Currency type represents a value we usually think of as a string. As we’ve learned through designing a Money model, this value represents more than the string which identifies it. There are numerous examples of other values of this kind. An International Bank Account Number (IBAN) is one example of such a value. An IBAN can be validated, you can derive the country the bank is located in from an IBAN and much more. Even if an IBAN can be used to uniquely identify a bank account, we should represent IBANs as Value Objects. The bank account should however be thought of as an Entity.
Value Objects are not restricted to only contain other values, they can reference Entities as well. In Domain-Driven Design, Eric Evans has a great example of this:
“VALUE OBJECTS can even reference ENTITIES. For example, if I ask an online map service for a scenic driving route from San Francisco to Los Angeles, it might derive a route object linking L.A. and San Francisco via the Pacific Coast Highway. That route object would be a VALUE, even though the three objects it references (two cities and a highway) are all ENTITIES.”
Together with Entities, Value Objects are the core types in a domain model and central in Domain-Driven Design. Domain-Driven Design is a way of thinking for developing software that deals with complicated domains. If you are unfamiliar with Domain-Driven Design, I recommend reading “Domain Driven Design – Tackling Complexity in the Heart of Software” by Eric Evans
and “Applying-Domain Driven Design and Patterns with Examples in C# and .NET”
by Jimmy Nilsson.