Quantity

Represent dimensioned values with both their amount and their unit

10 May 2004

This is part of the Further Enterprise Application Architecture development writing that I was doing in the mid 2000’s. Sadly too many other things have claimed my attention since, so I haven’t had time to work on them further, nor do I see much time in the foreseeable future. As such this material is very much in draft form and I won’t be doing any corrections or updates until I’m able to find time to work on it again.

There are many cases where we want computers to represent dimensioned quantities: values such as six feet, or thirty kilograms. Usually these are represented as bare numbers, mainly because that is the best we can do in the limited type systems that languages give us.

But using objects invites us to add new fundamental types whenever they add value, and having a specific type for dimensioned quantities adds quite a lot of value. This is particularly true when the dimensioned value is that of Money. Money is a special case of Quantity, but also one that perhaps the most widely used, as plenty of people are prepared to spend money to watch money.

How it Works

The basic idea of Quantity is a class that combines the amount with the unit. In saying that a quantity is a simple representation. However the real fun with Quantity comes with the behavior that you can apply to it.

The first kind of behavior is arithmetic. You should be able to add two quantities together just as easily as you can add two numbers. Furthermore more the quantities should be intelligent about addition and subtraction: at the least preventing you from adding 6 feet to 180 pounds.

More complicated issues with addition arise where you are trying to add similar units, such as adding 500 meters to 3 kilometers. The simplest approach is to deny that addition, forcing the client to make the conversion. A more sophisticated approach is to see if you can convert one argument to the other, if so you can perform the addition. How well you can do this depends on the sophistication of your convertor.

Multiplication has similar variations in sophistication. The simplest approach is to only permit multiplication and division by scalar numbers. A more sophisticated approach is to allow multiplication by other quantities, but then you have to work out the units of the result. So if you divide 150 miles by 2 hours you get 75 miles/hour.

Comparison operations are needed so you can find out if six feet is more than five feet. The issues here are much the same as those for addition - you have to choose how much conversion you do.

It's useful to provide a simple interface to allow conversion on a quantity directly, although the conversion work is usually best left to a separate convertor object. If you only have a few units, however, it's easier to embed them directly in quantity classes.

One of the most useful behaviors you can give to quantities is to provide printing and parsing methods that allow you easily produce strings and to produce a quantity from a string. This simple pattern can do much to simplify a lot of input and output behavior, either to files or in GUI interfaces.

For simple printing you can have a default, such as first printing the amount and then the unit. That breaks down when in some cases you want to print the unit before the number and other cases afterwards. Usually this kind of variation will depend on the unit, so in these cases you can put the printing and parsing behavior on the unit and delegate to that.

Money

I use Quantity on almost every system I work with, but I rarely use it to represent physical units. Most of the time I use it to represent money. Much of the comments for physical units are the same, but money does have its own spin to bear in mind when you're working with it.

The biggest change surrounds the whole area of conversion. While physical units' forms of conversion don't change over time, exchange rates for money are always changing. Obviously this affects conversion operations, but the effect ripples into the addition, subtraction, and comparison operations as well.

When you convert money, at the least you need to provide some kind of time reference, whose granularity will depend on the application. But in many cases you may have separate conversions in different contexts.

The upshot of all this is that you need to be much more careful about automatic conversion inside arithmetic or comparison operations with money. So often you'll find they are not allowed.

A particularly useful feature with Money in addition to those for Quantity is the handling of rounding. Money is often expressed with a decimal part, yet you should never use real numbers for handling Money. The reason for this is that the rounding behavior of real numbers almost never corresponds to what's needed for money, and ignoring this fact can easily lead to intermittent bugs which are small in denomination and high in frustration.

A money object, however, can encode its own rules for rounding, which means that most of the time you don't have to be aware of the rounding rules while you are working with money.

Connected to this is the knotty matter of division. If you divide $100 by three, what do you get? Usually the answer is not as simple $33.33. The problem is that if you multiply $33.33 you get $99.99 - meaning that a penny goes missing. Accountants don't like pennies to go missing. So you'll have to find out what policy applies to the situation you're looking at. Often the rule is that someone should get extra penny, although it doesn't matter who. So you can put a method in the money object to return a collection of the monies that you need to hand out from the division.

Relational Databases

A common question with Quantity is how to use it for relational databases and other systems without the ability to create new lightweight types. Do you store an amount and a currency code with every monetary value?

The issue here comes when there is a constraint in place that forces all monies to be of the same currency in a certain context. So consider the case where you have an account with many entries. Each entry has a money attribute to show the amount of the entry, yet all the entries on an account have the same currency. Is it reasonable to store the currency once on the account and not duplicate the currency across the entries?

I'm inclined to punt on this question, and leave it to the specifics of your database design. I would still urge you to use money objects in your code: it's up to you whether how you store those in the database. After all the database doesn't give you any behavioral advantages from Quantity. You only get those in the code.

When to Use It

As you've gathered I use Quantity, at least in the money variation, a lot. Indeed with an object-oriented environment there's little reason not use it. Often I've noted that people are scared about using small objects like this mostly due to unfamiliarity. Performance is an oft-cited concern, although I've not seen or heard of Quantity being a really problem for performance.

There's an argument that says that using Quantity isn't worth it when there's only one unit, so you shouldn't use money when you only have one currency. But much of the value of money comes from its behavior, not its multi-unit capabilities, so I would use it even then.

Further Reading

There is a more detailed discussion of the Money variant in P of EAA