| Section II: Functional Decomposition of 'main' | Section I: User Interface Analysis - Giving Olympia Choices | Section III: C++ Code | Section IV : Putting It All Together |
|
Table of Contents
Learning C++:
An Index of Entry Points
2. The A reference document on the basic elements of C++.
3. The Patterns
|
A. Discovering a Set of Functions
The Interface analysis does help us here. The tasks referred to there included:
We do not yet know whether users will be asked all of the questions in 'main' or elsewhere. Should we have 'main' request both which contract to work with and which operation to perform on that contract, or should we only have 'main' ask which operation the user wants to perform and have the functions 'DisplayInfo' or 'ChangeInfo' ask which contract? Let's explore the first way in this example.
Now, do any of these functions need further decomposition? The 'intro' and 'closing' functions as well as the 'Get...' functions are probably simple enough - we have already worked with these kinds of functions and found them to not be difficult. How about the other functions? The function 'DisplayInfo' will send messages to the instance of contract under consideration seeking the information it needs to display. In this sense it uses or calls other functions. However, these are functions already designed and implemented as part of the class design we did in chapter 5 so we have no further design work to do.
'ChangeInfo' will likewise use member functions of the class 'contract' but it has some added tasks. First, it needs to find out which property(ies) the user wants to change. Therefore, we need a function to ask the user which property(ies) he or she wishes to change. Of course, we already have such a function. What we are discovering here is that 'GetProperty' is used by 'ChangeInfo'.
'ChangeInfo' also needs to ask the user for the new value of the property being changed before it calls the member function to make the change. Again, we have such functions in 'GetSquareFootage', 'GetNumDesks, and GetNumDays' . Our conclusion is that these too are subtasks of 'ChangeInfo'.
Here is a structure chart of this program as designed. There are two points to note: First, the member functions used in the program are not included in the chart. Second, since structure charts are a general tool, not designed specifically for C++ or any programming language, we use a more English like naming scheme for the modules.
B. Functional Design
Now, what do these functions need from the function(s) that call
them and what will they return? Consider 'DisplayInfo' first. From our earlier discussions
of functions that output values, we know that this function needs
to receive the values to be output. In the case of 'DisplayInfo'
there are four such values - the square footage, the number of
desks, the number of days, and the per week charge. We could then
say that this function has four receives but another way to answer
this is to say that the function simply needs a contract since each
contract 'contains' these four pieces of information. The advantage
of this new approach is that it allows new properties to be added
to the contract design or old properties removed without changes
to the parameter list. If eventually contracts acquire more properties,
the values for those new properties will still be provided to
'DisplayInfo' as long as the contract itself is provided.
In terms of 'returns', we know that functions that output values
usually do not return anything and 'DisplayInfo' is no exception.
Here then is the design for this function.
DisplayInfo
Receives: A contract
The 'receives' for 'ChangeContract' are the same. This function
cannot change a contract unless it has one to change. However,
the situation is a bit more complex in the case of 'returns'.
Whichever function calls this function would, presumably, like
to get back the changed contract. As a general rule, whenever
a function changes values, it probably should return what got changed.
So, 'ChangeContract' both receives and returns a contract. The
design looks as follows:
ChangeInfo
Receives: A contract
C. An Improved Decomposition
The purpose of 'main' is now very simple:
The algorithm then looks as follows:
D. Top Down or Bottom Up Design
Our task then is to design the algorithm for' ProcessUserChoices'
- the first function not yet designed starting from the top of
the structure chart. It's purpose, as we started to describe above,
is to:
Goal: The user's requests have all been handled
As for receives and returns, ' ProcessUserChoices' does not need
anything from 'main' nor does it return anything to 'main'. This
is clear when you look at the algorithm for 'main'. It simply
handles the introductory and closing screens and passes off the
real work to ' ProcessUserChoices'.
E. Boolean Variables and Another Pattern
Notice where 'done' is set to TRUE. Inside the loop we have a
new option - when 'Q' has been entered for 'choice'. When this
happens, we ask the user if he or she is sure they want to exit.
If they say 'yes', 'done' is set to TRUE and the loop will stop
executing. If the person says 'no' (or anything else for that
matter), 'done' is not changed, that is, nothing happens, and
the loop continues.
So far so good, but there is a problem. Before proceeding, see
if you can find it, first by simply reviewing the algorithm and
then, if the problem is not obvious, by tracing it.
What do you think the problem is? If you said that users are forced to enter a contract number even if they have entered 'Q' to signal that they are finished, you are correct. If you said something else, be sure you see the problem now- perhaps by tracing the algorithm again.
To fix this we need to move the call to Get Contract Number inside
the two 'if' statement branches that need a contract number -
when the person types a 'D' or a 'C'. |