The Paddle-boat Rental System

       We begin the discussion of JSD with an example of bad system development followed by system development using JSD.

An entrepreneur runs a paddle-boat rental business on a picturesque pond. When a client comes, the operator of the business makes a boat available, helps the client into the boat, and keys a message onto the console of the PC that the was just purchased for the business. The message consists of a session identifier, a start-of-trip code,'S'; and the system clock time. When the session is finished, the client retuns the boat, and the operator keys in another message consisting of the session identifier, an end-of-trip code, 'E', and the system clock-time. The operator then computes the session time and charges and receives payment from the client. (Eventually the operator plans to automate the computation of charges, but keeps this secret for now.)

The owner wishes to produce management information in the form of a daily report at the end of the day's business and invites a developper to produce the information. The report has just two lines:

    Number of sessions = nnnn
    Average session time = mm

The developper immediately ascertains that the report can be produced by a single function that consists of two parts. The first component processes the day's data and the second component prints the report. Moreover, the processing component consists of first counting the total number of sessions, and dividing this by the total time of all sessions. Counting the sessions is easy enough--simply count the number of messages with an 'S' code. Computing the total time isn't much harder:

totaltime = (endtime of session 1 - starttime of session 1) + (endtime of session 2 - starttime of session 2) +

                    ....... (endtime of session n - starttime of session n)

or more conveniently,

totaltime = (endtime of session 1 + endtime of session 2 + ... + endtime of session n) -
                (starttime of session 1 + starttime of session 2 + ... + starttime of session n)

The resulting solution, functionally designed and implemented in structured code, is:

begin open message stream;
    get message
    number := 0; totaltime := 0;
    dowhile <not end-of-stream>
        if code = 'S'
        then
            number := number + 1;
            totaltime := totaltime - starttime
        else totaltime := totaltime - endtime
        endif
        get message
    endwhile
    print 'NUMBER OF SESSIONS = ', number;
    if number <> 0
    then print 'AVERAGE SESSION TIME = ', totaltime / number;
    endif
    close message stream;
end

The system goes into production and everyone is happy. Soon, however, the owner approaches the developper with a small enhancement to the report. The enhancement consists of just one additonal line to the report:

LONGEST SESSION TIME = ppp

Careful examination convinces the developper that the enhancement cannot be made except by throwing away the existing code and starting anew. The reader should be persauded that indeed this is the case. The developper convinces the owner that there are technical reasons why the modification cannot be made, and the owner, dazzled by the developper's brilliance, agrees that the change isn't crucial anyway.

However, the owner returns a little later with another request, to produce two reports instead of one, with the same format as the original report. The first report should deal with sessions starting before noon, while the second would summarize those starting during the afternoon. Because the change is so small, the owner is convinced that the developper will be able to satisy the request without difficulty. Again, the developper (and, I hope, the reader), realizing that the system could not be modified, gives the owner an explanation, something to do with the capacity of the hard disk. The owner is less dazzled and definitely disatisfied with the service being given.

Soon, the owner returns with a critical request: the telecommunications line has been dropping some of the 'S' and 'E' messages, and sessions involving these dropped messages must not be included in the report. Once again the developper realizes that the change cannot be made without totally scrapping the existing system. The developper's attempts at explanation fall upon deaf ears. Neither the time nor the budget is available to create a new system, and the developper is soon walking the streets in search of a new job.

        Why did the system fail? It failed because it was based on a functional design instead of being based on a model of the real-world situation. In the situation under consideration, the real world consists of paddle-boat sessions. The client rents a paddle-boat for a session. The first line of the requested report consists of the total number of sessions, while the second line consists of the average length of a session. The system should have been based on the structure of a session. However, in the program text, there is no component that correpsonds to a session. There is no variable we can point to and say 'there is one of these for each session'.

The structure text for the system should have been the following:

begin
    open session stream;
    get session;
    number := 0; totaltime := 0;
    do while <not end-of-stream>
        number := number + 1;
        totaltime := totaltime + (endtime - startime)
        get session
    enddo;
print 'NUMBER OF SESSIONS = ', number;
if number <> 0
then print 'AVERAGE SESSION TIME = ', totaltime / number;
endif
close session stream;
end.
In the program text above, the variable number refers to sessions. Each record on the session stream represents a session, and contains the start time, end time, and session-id for a session.

The three system changes asked for by the manager of the paddle-boat system aren't hard to make. They are given below:

(i) Add a line, LONGEST SESSION TIME = ppp, to original report

A modified or new text line is indicated by an arrow in front of the line.

begin
    open session stream;
    get session;
    --> number := 0; totaltime := 0; maxtime := 0
    do while <not end-of-stream>
        number := number + 1;
        -->sessiontime := endtime - startime;
        --> totaltime := totaltime + sessiontime;
        --> if sessiontime > maxtime
        --> then maxtime := sessiontime;
             endif
               get session
        enddo;
    print 'NUMBER OF SESSIONS = ', number;
    if number <> 0
    then print 'AVERAGE SESSION TIME = ', totaltime / number;
    endif
    --> print 'LONGEST SESSION TIME = ', totaltime / number;
    close session stream;
end.
(ii)Modify original report to contain the same information for both morning and afternoon sessions begin
    open session stream;
    get session;
    morning := 0; morningtime := 0;
    afternoon := 0; afternoontime := 0;
    do while <not end-of-stream>
        if startime < 1200
        then begin
            morning := morning + 1;
            morningtime := morningtime + (endtime - startime)
         end
         else begin
            afternoon := afternoon + 1;
            afternoontime := afternoontime + (endtime - startime)
          end
          endif
            get session
     enddo;
    print 'NUMBER OF MORNING SESSIONS = ', morning;
    if morning <> 0
    then print 'AVERAGE MORNING SESSION TIME = ',
        morningtime / morning;
    endif
    print 'NUMBER OF AFTERNOON SESSIONS = ', afternoon;
    if afternoon <> 0
    then print 'AVERAGE AFTERNOON SESSION TIME = ',
        afternoontime / afternoon;
    endif
    close session stream;
end.
(iii) Omit sessions with a missing starttime or endtime message

A modified or new text line is indicated by an arrow in front of the line.

begin
    open session stream;
    get session;
    number := 0; totaltime := 0;
    do while <not end-of-stream>
    -->if (startime <> nil and endtime <> nil)
         then begin
            number := number + 1;
            totaltime := totaltime + (endtime - startime)
        end
        endif
    get session
    endwhile;
    print 'NUMBER OF SESSIONS = ', number;
    if number <> 0
    then print 'AVERAGE SESSION TIME = ', totaltime / number;]
    endif
    close session stream;
end.
The moral of this example is twofold: First, system maintenance becomes difficult if not impossible when program text does not correspond to the structure of the problem. Second, if the program text corresponds to the structure of the problem, functional modifications usually can be accommodated.