Account
Collect together related accounting entries and provide summarizing behavior
22 January 2005
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.
Accounts have been around for a long time. Whether they are personal bank accounts, project cost accounts, or a corporate chart of accounts; they crop up in most problems involving accounting.
There are various ways to think about what an accoount is. A good way is to think of them as a container of entries Accounting Entry). Whenever you create an entry, you put it into an account. The account is more than a container, however, it also has behavior provide summary information, such as a balance.
You can also think of an account as an Audit Log of some value, something you use for an amount where you don't just want to know what the current value is, you also want to be able to know it's value at any point in the past, and you want to know each discrete change that happened to that value.
A third way of thinking about an account is a way of tying together all the elements of an entry that describe the kind of entry it is. In this it provides a step of indirection between the entry and its descriptors. Using this allows you more easily pull together all the entries that have similar characteristics.
Figure 1: Accounts can act as a leve of indirection between an entry and its descriptors
When people think about accounts, they usually think about monetary accounts. However accounts can be used for more than money. If I have twenty four bottles of Black Butte in my refridgerator, I can think about that as an account. When I take a couple of bottles out for Cindy and me to have with our Rogan Josh, I can think of that as an withdrawel of two bottles. I'm not inclined to use an accounting system for my fridge, but if you have a network of warehouses then such a model can make a lot of sense.
How it Works
There are two essential qualities to the account pattern: keeping a collection of entries and providing summarizing information over those entries.
Since you usually get a large amount of entries you often need to optimize the way you calculate balances. The optimization technique will depend on what kind of information you need from the account. For instance if you often need the current balance, you can cache the current value in a field and use the entries to calcualte backwards to get earlier balances.
Entries typically go back all the way to the opening of the account. However if there are too many, and you no longer need details about them, you can replace a clump of entries with just a single consolidating entry whose value is the balance of the removed entries. This will maintain the balance for dates after the consolidation, but means you won't be able to get information that cuts into the summary entry. However this entry can be used as a proxy for the detailed entries.
You usually expect that all the entries in an account will be of the same currency. So usually you see accounts created with a particular currency in mind. It is possible to create accounts that dynamically choose their currency when they are given their first entry, but the fiddly behavior of how to treat empty accounts means that it's hardly worth the effort.
If you allow accounts to hold entries from different currencies, you'll need to use a Money Bag for the summary calculations.
The typical summarizing behavior you see is to get the balance, withdrawels and deposits on some date or over a time period.
When to Use It
I tend to feel the urge to use Account in couple of different situations.
The first is where there is some value where I need current value, historical values, and to be able to keep a history of changes to that value. If I only need the current value I can just use a field. If I only need current and historic values I can use Temporal Property - although I'm not sure that Account is any more complicated than Temporal Property.
The second case is where I'm already using Accounting Entry (15) but I want to pull together all the entries for a common set of descriptions. This makes it easier to compare like entries with like.
Often you find yourself wondering whether to use Account or to use Accounting Entry on its own. Some of the event based patterns, such as Posting Rule Network (52) and Difference Adjustment (59) are much easier to use if you use Account. Another factor is how the domain experts see the domain. If they use think of the world in terms of accounts, then it makes sense to use Account, if not don't.
It's not difficult to see the anlaogy between Account and the idea of version control systems. Indeed you can think of Account as applying the idea of verison control to money. However I don't think that means that you can use Account for non quantitative situations. While I guess you can think of a code version control as balances, withdrawels, and deposits to text files; for me that's stretching the analogy a little too far.
Example: Simple Example (Java)
The basic behavior for accounts is actually very straightforward, consisting of collecting together entries (Accounting Entry) and providing summary information. Collecting entries is very simple.
class Account ... private Collection entries = new HashSet(); private Currency currency; void addEntry(Money amount, MfDate date){ Assert.equals(currency, amount.currency()); entries.add(new Entry(amount, date)); }
The summary information is not that much more complicated.
class Account... Money balance(DateRange period) { Money result = new Money (0, currency); Iterator it = entries.iterator(); while (it.hasNext()) { Entry each = (Entry) it.next(); if (period.includes(each.date())) result = result.add(each.amount()); } return result; } Money balance(MfDate date) { return balance(DateRange.upTo(date)); } Money balance() { return balance(MfDate.today()); }
Often it's useful to provide separate behavior to determine totals added or removed from the account over time.