Modeling MoneyA Money abstraction consists of a numerical value and a currency. It is therefore like a quantity measured in a specific unit.The RequirementsThe numeric part has to support high-precision and a well-defined rounding behaviour. Floating point variables clearly do not suffice. Two other common approaches are also unsatisfactory: storing the value as an integer number of currency's subdivision (eg. storing USD1.73 as 173 cents) - this fails to support fractional currency subdivisions (and a quick look at your neighbourhood gas station's prices will convince you that such fractions are surprisingly common). The second common approach is to store the value in an infinite precision number. This is unsatisfactory, because accounting principles actually call for a specific rounding behaviour - during the calculation, not just at the end. (Specific information on this point is not easy to come by and may vary from country to country, and from business to business.) The currency part has essentially no behaviour. It just bundles various information on the currency (such as name, ISO-4217 three-letter and numeric code, etc). Note that currencies do appear and disappear: Sometimes in an organized fashion, such as the recent transition to the Euro (as other countries join the European Union, their currencies, too, may disappear). Sometimes new currencies are created ad-hoc, for instance in the face of a severe currency crisis (primarily in developing markets). Often there exists a "canonical" format do display amounts in a given currency. Such information might be encapsulated in the currency abstraction as a default format. It will nevertheless be necessary to provide a way to override this setting to provide arbitrary formatting. A monetary value has to support multiplication and division by a scalar, as well as addition and subtraction between money instances of the same currency, subject to the rounding and precision rules mentioned above. (Curiously, these properties fulfill the requirements of a one-dimensional vector space - it is not clear, however, how this knowledge helps the modeling process.) The real problem, of course, is how to treat calculations (ie. addition and subtraction) involving multiple currencies. The following business domain behaviour is conceivable:
Even fixing a time leaves the applicable conversion rate undetermined, since the latter is also dependent on the business and even the specific transaction (each money exchange has different rates for buy and sell transactions) - but this is leaving the modeling domain: For the purpose of modeling it is sufficient to assume that conversion rates are either specified or unspecified. Where the values are coming from and how they enter the system is not part of the overall modeling effort. Modeling ApproachesSeveral modeling approaches are possible. The simplest one is to generate a run-time error (exception), whenever a multiple-currency operation is attempted. As a very simple approach this works reasonably well, however it introduces another sort of error which is not detected until run-time. In particular for problems where the number of currencies the system has to handle is small and fixed, this seems unnecessary. One can make money objects in general inconvertible, in such a way that attempting a cross-currency operation will generate a compile-time error. (It is currently not clear whether existing programming languages would support this model in a practical way.) One can require the full matrix of conversion rates to exist at all times for all supported currencies. This is unnecessarily unflexible, since only a small fraction of all possible conversion is likely to ever be executed. The execution of the calculation may be delayed and the sequence of operations be recorded instead. At some later point, this stack may be projected onto a single value by supplying all necessary conversion rates. Several hybrid schemes are possible, of course. One may also want to introduce different conversion zones, such that instances belonging to the same conversion zone are freely convertible, but instances belonging to different zones are not. This might be useful to keep different sets of conversion rates around (say, today's and yesterday's). ConclusionSurprisingly, finding a satisfatory way to model something as simple and familar as money turns out to be not so easy. Some of the above approaches may work well enough for any given application, but a really compelling design does not emerge.Resources
|