0

After reading some of "Clean Architecture" I got the idea that perhaps I should reconsider the way I have architected a chart of accounts/accounts object in an accounting program.

I have accounts which live in a tree structure like this:

Budget account (root) 
   Sections (0..n)
     Accounts (0..n)
       Subaccounts (0.n)
          LineItems(0..n)`

Only line items have an actual concrete 'total' value, which is entered by a user and stored as a number field. Each level of the hierarchy derives the total from the sum of its children's total, so the Budget Account total is ultimately equal to the sum of all the line items.

My question is this -- Should the 'total' property above 'lineitem' of each account be implemented as a function equal to something like

get total() :number {
  return (sumOf(children.total())
} 

, or should it be designed as a number field on each account which is updated in response to user lineitem changes by responding to an observable which announces changes in the values of any of accounts children?

In the former case, accuracy and maintainability, simplicity, concurrence are all probably increased if there is only one set of actual data to be maintained at the line item level, but it just seems like a heck of a lot of processing that has to happen each time a page with accounts has to show its total. For example if a page header {{budgetAccount.total}} that in turn would provke a process where every single account is recursed through a loop to calculate the total -- on every page referesh! And if you print the entire chart of accounts, the same numbers are added over and over and over each time an account.total is requested. However, with the speed of and capacity of todays machines and browser and I don't have akeen sense if the burden of all this processing is actually meaningful or not and worth persisting some of these imemdiate totals within the accoutn object, so they don't need recalculation everytime some uses the getter.

For context, might be 20K-30K lineitems in my actual budget, split over maybe 1,000 accounts at various levels. But of course, an exceptionally large budget may come along with as many as 100,000 or 500,000 line items. In my application, the entire budget structure is kept in memory once retrieved from the back end..

What the factors that should be considered in this decision?

1 Answer 1

1

Auditors

Love them or hate them, they will get there hands into any system of account.

Presuming that this is such an accounting system, which is easier to explain?

  1. Here is the exact value as displayed on the customers invoice. It may be incorrect, but that was what was displayed, and as such our contractual obligation.

  2. Here is a bunch of code, and this is how you understand what was done, and ignore that commit its not on the main line, and yes if the customer were to come back and look at their invoice today, it would not match the invoice they were given then.

Personally auditors do not take well to having to learn a programming language. Your auditors may be different.

Trade Off

Which is more important to you - Clock cycles or Memory?

If Clock cycles are costly, then a single computation and sacrificing some memory works.

If Memory is more costly, then on demand calculations is the cost of having that space available.

If they are mixed, perhaps a memoised map? If the value exists return it, otherwise calculate it and insert it before returning it. Not enough space? pick one of the older results and replace it/just empty the entire cache.

Assumptions

What precisely do you mean by todays computers?

  • A Cray? it might be overkill.
  • My watch? You are surely joking.

Pick your actual baseline, and test using a machine built to that baseline. Collect your results and experiment on different ways until you come up with something working/or give up and upgrade the baseline.

Also remember that the baseline machine is probably running other software, like anti-virus, web browser, a back ground file cleaner, etc.. Not all of those resources are uniquely available to your program.

4
  • Your list of tradeoffs and assumptiosn are well taken. Nevertheless, this is only a single question of many that I need to think about in architecting my system. I have to start somewhere, and since I clocked my machine doing 50K additions in about 4 millis (a Macbook pro) and my users will be on similarish PCs, it seems like the best place to start is storing only the concrete numbers (the ones entered by the user), and calculating all the intermediate totals until it starts to slow down the user experience. Is that your basic advice?
    – GGizmos
    Commented Jul 10, 2020 at 2:01
  • Broadly yes. Pick a place, and make your judgements about what can/cannot happen, what is acceptable/unacceptable from the position. You'll soon find the shortcomings, and places you can move to. However I think you didn't get the point about auditors. Its not enough to have something that works within the resource budget, if it isn't also providing guarantees that other humans will bank on. What those guarantees are you need to be clear on before entertaining candidate implementations. eg: quicksort is often faster then logsort, but quicksort is not a stable sort, logsort is.
    – Kain0_0
    Commented Jul 10, 2020 at 3:33
  • I actually do get the point about auditors. Mine application is a program for budgeting not bookkeeping. Budgets generally do not find their way (at least not directly) into the company's books. I udnerstand that if I were recording actual transactions, I would have to have a complete history to support an audit trail.
    – GGizmos
    Commented Jul 10, 2020 at 20:40
  • Fair enough. Then yes, think up some solutions. Pick one that isn't obviously broken. Implement it, measure, improve as needed.
    – Kain0_0
    Commented Jul 12, 2020 at 23:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.