[ Overview ]

Design Philosophy #

The preceding sections have outlined the main features of Max2 but as rather separate concepts. This section tries to bind these together by describing the overall design philosophy and how it is applied.

The basic idea incorporated in the design is that, as far as possible, data should only be stored once. This makes any "retrospective" changes easy and ensures consistency - if there's only one copy of the information then there can't be two inconsistent versions.

This is the reason that input data is stored as raw transactions with as little additional information as possible. Of course, in practice, additional information is required. For example, it would not be practical to look back through years of transactions every time a member's account balance is required. The solution to this is to store more static information in the state files as a sort of cached summary of this sort of historical information. This does not negate the basic philosophy as the state files can be rebuilt from the transaction files automatically whenever required.

The practical benefits of this approach include:

The freedom to deal with transactions non-chronologically allows many operations to be carried out easily. For example, it is possible to start entering the flight transactions for a month before the charging rules for that month have been finalized. Flights for one day can be entered even if not all of the information required to enter those for a previous day are available (e.g., due to a lost tug card). Corrections to previous transactions which affect later ones can also be made retrospectively.

There is a limit to how far the non-chronological handling of transactions can be taken, of course. In particular, once data is exported from Max2 (e.g., for use in the club's bookkeeping system) it cannot be automatically rebuilt so it is then necessary to close off those transactions from change (done on a month-by-month basis) to ensure future consistency.

The freedom to change the format of the state file and just do a rebuild makes program development simpler as there is no need to have code to migrate data from older versions or to ensure backward compatibility.

The introduction of new transaction types and the addition of extra fields to the end of existing transaction types also makes for more graceful software evolution. The requirement to ensure that existing transactions are handled in the same manner as before any software change is a significant constraint, though, which sometimes requires some careful thought and design.

For example, the original code was in many places quite lax about the checking done on some transactions. As the checking was tightened up it was found that some existing transactions were actually invalid. Rather than make retrospective changes to the transactions the code was set up to only perform the more rigorous checks on transactions in months after a certain date.