Incorporating CICS Design Guidelines

To convert what you have learned about the requirements for your business logic component into a detailed design, you need to be familiar with some general design principles for server components.

There are three important things you learned from your estimation of the workload:

The resources you have to use efficiently are:

Let’s examine these individually and develop some guidelines for designing and programming CICS applications from them. Remember, there’s bound to be conflict from time to time when trying to conserve one resource at the cost of another. The appropriate compromises vary from one program to the next.

You can use different techniques for locking (allowing single use of) specific types of resources. These are described in the following paragraphs:

Processor storage

In an online system, storage needs constantly change. Most exist only for the duration of a transaction, and so, in assessing storage needs you have to consider not only how much is used, but for how long. The trade-off between space and time requires the following storage consumers to be considered:

Processor time

In general, you need to conserve processor time. Calls for CICS or operating system services take much longer, relatively speaking, than straight application code. Avoiding unnecessary commands reduces processor time much more than fine tuning your code.

It is undesirable to do long calculations in an online program, because you may be sharing the process with thousands of other users. If such calculations are necessary, you need to use an application design approach that is beyond the scope of this book.

Auxiliary storage

Disk space and transmission capacity is optimized in an online system by minimizing input/output by, for example, creating additional indexes instead of performing sequential searches.

It is undesirable to do complex database queries in an online program. If such queries are needed, special design approaches are needed; these are beyond the scope of this book.

Communication bandwidth

There are two main principles governing community bandwidth:

When a user works on an account, she will bring the account details onto the screen, work with the information, optionally save changes to the database and cease working with the customer account.

There is a potential problem if two users try to do this on the same account at the same time. Both users could be making changes based on the same old copy of the record. Changes made by the first user to complete his work go into the file, but then changes from the second user will overwrite the first user’s updates. You must ensure that, when one user starts to work with a customer account record, subsequent users are prevented from doing so. As discussed in Transactions in Chapter 2, ACID transactions should not wait for user input. Thus, you can’t use the Isolation property of ACID transactions to prevent multiple users working on the same account.

Our solution is to introduce an application-level locking scheme that locks out other users between the initial display of the account details on the screen and ceasing to work with the customer record. Note that you can still exploit the capabilities of ACID transactions during the step that saves the changes.

Use of an application locking scheme is better than using ACID transactions from the perspective of users, too. If you used a long-running ACID transaction to protect against double updating, the second user would be locked out waiting for the first user to complete his work. With an application lock, you can tell the second user to try again later, and you can even pass information as to who owns the lock so that the second user (who may have the actual customer waiting on the telephone) can discuss the problem with the first. Let’s look at one way this locking mechanism could work.

Suppose that as soon as a user asked to update an account number, you make a note in a scratchpad area. (CICS provides scratchpad facilities for keeping track of things between transactions.) You can leave the number there until the update is entirely completed and then erase it. In our example, this means that if you write a scratchpad record in a subsequent transaction, it erases the earlier one. Before starting any update request, you can check to see if the account number is in use. If it is, you can tell the user this and ask him or her to resubmit the request later. Furthermore, you can let the user display the record even if it is in use.

This isn’t quite all, however. Because CICS ensures that transactions are either executed completely or not at all, you have to make sure that all your protected resources get updated in what CICS regards as a single transaction to ensure the consistency of your data. In the conversational case, (see Table 10-1) the program performs all the steps in one transaction. On the other hand locks are held over two terminal output/input operations so the scalability of the system might be adversely affected by a user going to lunch in the middle of a transaction. In the pseudo-conversational case (see Table 4-2), the files are all updated in the third transaction (this is the preferred solution), but the scratchpad is updated in two different transactions (not so good). The real benefit of this design is that no locks are held while waiting for user’s terminal input, so step 2 has disappeared between 1 and 3 and step 6 between 5 and 7.

If the second transaction is completed successfully, but something happens to the third, the scratchpad record is written but not erased. Our data files would be consistent, which is the main concern, but you’d be unable to update the record involved until you could somehow reset the scratchpad.

You can get around this by designing a slightly more sophisticated scratchpad mechanism, for instance, by putting a limit on the time for which a transaction can own an account number. Then an error in the third transaction or thoughtless behavior by a user (going to lunch in the middle of a modification) will not cause an account record to become unusable for more than a short period of time. But all this involves extra coding and complications—is it worth it?

Absolutely. You can program your own mechanism for avoiding concurrent updates. Double updating is one of those problems you can tackle in a variety of ways. We chose a scratchpad. A drawback of a scratchpad, however, is that all future (and, as yet, unknown) transactions that update the account file have to refer to this scratchpad. However you can control this by the design you have chosen to separate the presentation logic from the business logic. Since all updating automatically manages the locking, this should be less of a problem than it may appear at first.

As developers of a reusable component, you must handle errors well. Hence, your component does some or all of the following actions for each error, which correspond to the following table:

The errors that can occur in a CICS transaction can be divided into five categories. For each category, you need to consider which of the error-handling actions are required.

Conditions that aren’t normal from the CICS point of view but are anticipated in the program

For example, when you try to read a record and get a “not found” response.

Errors in this category should be handled by explicit logic in the program. None of the error-handling described above are needed.

Actions needed: 2. (If a record is not found the user should be told.)

Conditions caused by user errors and input data errors

An error of this kind in the sample application would occur if a user tried to add an account number that already existed.

Errors in this category should also be handled by explicit logic in your program. Ideally, no errors of this type should be allowed to stop the program, or do anything else to upset the user.

Actions needed: 2.

Conditions caused by omissions or errors in the application code

These may result in the immediate failure of the transaction (abend) or simply in a condition that you believed “could not happen” according to your program logic. In the sample application, an attempt to add two identical records to the account file would represent this kind of error. You wouldn’t expect it, because you’ve already tested in the frontend transaction that no record with the same key is in the file. One of the main goals of the debugging process should be to get rid of this type of error.

Actions needed: 1, 2, 3, 4.

Errors caused by mismatches between applications and CICS resource definitions, generation parameters and Job Control Language (JCL)

An example is when CICS responds “no such file exists” to your read or write request. When you are first debugging an application, these problems are almost invariably your fault. Perhaps the definition of the file was not installed into the CICS system you are using to test or you spelled a name differently in the program than that used in the definition.

These conditions sometimes occur after the system has been put into production use as well. In this stage, they are usually the result of changes to a CICS resource definition, or a failure to install a resource definition, or JCL, more often than not related to some other application.

This category needs the same treatment as errors in a program that you are debugging. Once the program is in actual use, however, something more is needed when one of these conditions arises. You must give users an intelligible message that they or their supervisors can relay to the operations staff, to help in identifying and correcting the problem. For example, if an administrator has disabled a file for some reason and forgotten to re-enable it, you want a message to the operations staff that says that the problem is caused by a disabled file (and which file, of course). Moreover, you should program for these eventualities from the start, as this part of the program will need debugging just as well as the rest.

Actions needed: 1, 2, 3.

Errors related to hardware or other system conditions beyond the control of an application program

The classic example of this is an “I/O error” while accessing a file. As far as the application programs are concerned, this category needs the same treatment as the one above. Systems or operations personnel still have to analyze the problem and fix it. The only differences are that they probably didn’t cause it directly, and it may take much more effort to put right.

Actions needed: 1, 2, 3.