7.2 Transaction Requirement Pattern


7.2 Transaction Requirement Pattern

Basic Details

Related patterns:

Data type, data structure

Anticipated frequency:

Usually fewer than 10 requirements; more if one or more fundamental transaction type has subtypes that have their own requirements

Pattern classifications:

Affects database: Yes

Applicability

Use the transaction requirement pattern to define a type of event in the life of a living entity, and/or a function for entering such a transaction.

Discussion

Transactions are the lifeblood of any commercial system: they're usually where the money comes from. So handling them well is critical to a system's success. A system might have only a small number of types of transaction, and it might take surprisingly few requirements to specify them; even so, it's important to get these few right. Examples of transactions: a purchase from a Web retail site, renewing a magazine subscription, making a successful bid at an auction.

A transaction is a representation of something that happens at a point in time. For most kinds of transactions, this is clear and straightforward. A bank customer requests a cash withdrawal, which is deemed to take place the moment the cash is handed over. The transaction's details are fixed at the moment it is deemed to happen. This is an important rule: systems that break it are asking for trouble sooner or later. After the bank customer has walked off with their cash, the bank can't play around with the amount withdrawn or pretend it was paid from someone else's account: changing any of the transaction's details would be incorrect. If a genuine mistake was made (such as the wrong customer's account being debited), the only way to fix it is by means of one or more further transactions. Who'd trust a bank that did otherwise? (The purpose of the first pervasive requirement in the "Extra Requirements" section is to enforce this rule.)

A simple after-the-fact record that some event occurred (for example, an entry in a log or in a change history of a living entity) is not a transaction for the purposes of this requirement pattern; it is categorized as chronicle information (as defined in the introduction to this chapter).

image from book
Complex Transactions

Transactions can be complex. First, the time at which a transaction happens might not be clear-cut, and second, a transaction can comprise subtransactions.

A customer places an order with a Web shop. When exactly does this transaction happen? The obvious answer is as soon as the customer placed it-but that's not necessarily the right answer or the best answer. The shop takes a while to verify availability of the products. Can the customer change the order before it does? They'd find it very convenient! The shop discovers a couple of products are unavailable and is forced to remove them from the order; the rest of the order is confirmed. Does the order happen now? The shop dispatches those products that are ready for shipping and sends the rest later. What effect does this have?

In fact, a complex transaction (like this Web shop purchase) involves subtransactions (of more than one type), each of which happens at a particular moment, after which it can't be changed. It's well worth building a solid understanding of the different types of subtransaction involved in a complex transaction. A key matter is deciding when each subtransaction is deemed to happen, because this has a major bearing on who can do what, up till when. Paying attention to when each subtransaction happens can unearth subtleties you might otherwise miss. In the case of our Web shop, we might find ways to give the customer greater flexibility to change an order. Conversely, we might discover situations where it's not obvious to the user what state the transaction is in. How many times have you made a purchase from a Web site and not known the order status, how much it's going to cost you (especially mailing charges), and whether you can change your order? These are flaws in their system.

Sometimes it's useful for information to devolve (that is, to pass or appear to pass) from a transaction to its subtransactions-and to permit changes to that information in any subtransaction until that subtransaction happens. For example, consider the delivery address in a Web shop order. When our system creates one suborder for the part to be delivered now and another for the part that can't, the original delivery address can devolve on to the two suborders. We can then let the customer change the delivery address of the second suborder-because that subtransaction hasn't happened yet. But notice that the original order never changes after it is placed. Devolving information like this can add to the attractiveness of the system, as directly perceived by the users-in this case, the customers. So it's not simply a design issue; it affects requirements. Conversely, if the devolving of information is ignored, situations such as this might never come to light-until customers moan about the inflexibility of your system.

If a complex transaction becomes too complex, simplify it-artificially if necessary. Options include applying an extra restriction on when it or a subtransaction can be changed, or omitting or limiting some function. For example, our Web shop might decide not to allow a customer to change anything about an order after submitting it. A transaction becomes too complex when you don't properly understand it, you can't model it to your satisfaction, or you're unsure whether it could result in an unpleasant combination of circumstances (such as an order being changed after commitments have been made). Whenever you simplify a complex transaction, state it clearly in the requirement and explain the reason for it. You don't want a developer to remove the simplification (just because they're smart enough to), because it might still lead to the unpleasant combination of circumstances or be hard to test thoroughly enough.

Viewed one way, a complex transaction can itself appear to have events during its life-which makes it look a bit like a living entity. The easiest way to distinguish the two is that a transaction comes to the end of life naturally (such as when an order is fulfilled), whereas a living entity stays alive until explicitly terminated (for example, when a customer closes their account).

image from book

Now for another subtlety to worry about! If a transaction doesn't happen immediately, and its processing uses one or more configuration values, consider what to do if one of those values changes after the transaction was entered but before it happened. For example, if our Web shop's mailing charges change after receiving an order but before shipping it, should we levy the old charge (which is what we told the customer) or the new one (which is what it'll actually cost us-if we're merely passing this on)? Neither way is ideal. We could do better if the mailing charge changes were entered in advance, but even then we probably won't know beforehand whether shipping will occur before or after the change. A simple solution usually suffices once a situation like this has been spotted, but it's still worth recognizing it in the requirement. A picky, intricate answer is rarely necessary and is a sign that your solution is too complicated-which means potentially fragile and unsatisfactory software.

Content

A requirement for a transaction needs to define at least the following:

  1. Transaction name State what it's called.

  2. An explanation of the transaction Describe what it is and what it's for.

  3. The information the transaction contains Give this in the form of a data structure. This can include details about how particular values are entered, validated, and displayed. (See this part of the living entity requirement pattern, earlier in this chapter, for a little further explanation.)

  4. How a transaction is uniquely identified This enables us to distinguish two transactions whose details might otherwise be identical (or at least hard to tell apart). Computer systems are sufficiently fast that to differentiate on the basis of time, you need to get down to very small gradations of time-certainly much less than a second, and possibly finer than the accuracy of the machine's clock). The safest way is to allocate a transaction ID to each transaction-even if people rarely need to refer to them.

  5. Owner living entity details This identifies the entity on whose behalf the transaction is being performed: the customer making a purchase, the bank account from which cash is being debited. (Assume every type of transaction belongs to a living entity, because you're unlikely to encounter one that doesn't.) A type of transaction could conceivably have more than one owner-but they're rare.

  6. When the transaction is deemed to happen State this in terms of steps in the life of the transaction. It could be when the transaction's entered, when it's accepted (in a sense meaningful to the system-such as when a shop has checked that it has in stock all the products in an order), or when it's approved (say, manually by a person). This is the moment from which no changes are allowed. If the "happen time" isn't stated in the requirement, the transaction can be assumed to happen immediately when it is entered. Even if a transaction has separate steps for acceptance, approval, or other actions, its entry time could still be regarded as the time it happened.

  7. Transaction longevity (Optional.) How long should transactions of this sort hang around? That is, after how long does it become eligible for deletion? This effectively incorporates the intent of a longevity requirement (as per the data longevity requirement pattern in Chapter 6), which is good practice to consider for each type of transaction, even if you decide not to state it in the requirement explicitly.

Template(s)

Open table as spreadsheet

Summary

Definition

«Transaction name»

There shall be a function to create a «Transaction name» transaction for a «Owner living entity name». Each «Transaction name» shall contain the following information:

  • «Data item 1 description».

A «Transaction name» is «Transaction explanation». Each «Transaction name» is uniquely identified by «Transaction identifier(s)».

A «Transaction name» is deemed to have happened «Transaction happen time description». [«Transaction longevity statement».]

Example(s)

Open table as spreadsheet

Summary

Definition

Account adjustment

It shall be possible to post an adjustment (debit or credit) to the account of a selected customer. An adjustment shall contain the following information:

  • Customer ID

  • Adjustment amount

  • Adjustment reason-free-form text intended to explain why the adjustment was raised

A unique ID shall automatically be allocated to each account adjustment.

It is expected that authority to use this will be restricted to very few employees.

Extra Requirements

See also the "Extra Requirements" in the introduction to this chapter.

If you're going to specify performance requirements for anything in your system, it's most likely to be for the processing of transactions-because they're usually the highest volume, most visible, most financially significant part of a commercial system. It's illuminating to try calculating daily or monthly volumes for each type of transaction-even if only in a cursory manner, and even if it only serves to point out that you have little idea how busy your system's likely to be. Refer to all the requirement patterns in Chapter 9, "Performance Requirement Patterns," for types of performance for which you could consider specifying requirements.

Here's a pervasive requirement to enforce the rule stated previously:

Open table as spreadsheet

Summary

Definition

Do not modify transactions

No database row that acts as a transaction with actual or potential financial consequences shall ever be modified after the transaction was originally recorded such that its financial effect is or might be altered. In particular, errors in financial transactions shall never be rectified by modifying the transactions themselves. Instead, additional transactions shall be the only way to make the necessary adjustments.

For the purposes of this requirement, a financial transaction is any row in any database table that causes some financial value (such as a customer's account balance) to change.

The motivation for this requirement is to force a clear history of financial-related activity to be maintained. This is impossible if values in transactions are overwritten, because it results in both an inability to see what happened and quite possibly in errors that are hard to make sense of and to rectify.

Considerations for Development

Always adhere to the rule of never modifying any transaction after the fact. And take care processing transactions, because they're important.

Considerations for Testing

Testing that transactions are handled well is perhaps the most important testing of all, because the functions to process transactions tend to be the most heavily used and are highly visible. So testers should prepare a large number of test cases that cover all eventualities. Identify all the relevant permutations that a complex transaction can have, including states, transitions between states, and error conditions. Then build test cases for them all.

Pay special attention to the statement in a transaction requirement about when a transaction is deemed to happen. Test that a transaction cannot be changed after this point. When testing a complex transaction, ask yourself at each stage whether it's clear where you stand: is it obvious whether the transaction has been accepted? Can you tell what you're allowed to change? Are the financial implications spelled out? For example, is it clear to a customer how much they must pay? And are the actual computed consequences what you expected?




Microsoft Press - Software Requirement Patterns
Software Requirement Patterns (Best Practices)
ISBN: 0735623988
EAN: 2147483647
Year: 2007
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net