Input validation so far
Earlier, Klaus and Jeremy wrote a program to convert pounds and ounces into kilos.
Much of their code was validating user input:
The code shows error messages like this:
There are two problems with this method.
First, once users click OK, the error message is gone. When they start fixing errors, there's no reminder of what the errors were. No big deal, but at work people get interrupted all the time. Even a one minute interruption will make someone lose track.
The second problem: users might have made more than one mistake. Say a user got both pounds and ounces wrong. S/he gets an error message about the first problem, then the program stops. The user fixes that problem, only to get another error message. It might be more helpful to show both errors at one time.
Better error reporting
Here's what we want to happen when both pounds and ounces have bad input:
Differences from before:
- Both errors are reported.
- The error messages stay on the screen.
We should make other changes, too. A human might have two conversions to make, not just one. Here's a human, to remind you what they are.
Two eyes, one to three noses, you get the idea.
Here's what might happen. The human does the first conversion, without any typing mistakes.
She starts on the second task. She makes a typing mistake in ounces. She meant to type 5, but missed a little, and also hit the R key, just below 5:
The program shows an error, and also erased the output from the previous task – 1.588. Leave it there, and there's a small chance that a human who gets interrupted might think that 1.588 was the right answer. Erase the output cell when the Convert button is pressed, and that won't be an issue.
So that's one change: erase the output each time the program runs.
OK, now the human corrects the mistake and hits Convert:
The program erased the error message. Leave it there, and the human might think she hadn't fixed the mistake.
So, each time the program runs:
- Erase the output.
- Erase error messages.
Initializing
The two erasures are done every time the program runs. Geeks call that initializing, or initing, the program.
The flag pattern
Here's what we want to do. Suppose that Check input 1
is a sub that will show an error.
Check input 1
Check input 2
Check input 3
if nothing went wrong then
process
output
end if
Another way:
Check input 1
Check input 2
Check input 3
if anything went wrong then
end
end if
process
output
The flag pattern helps. A flag is a variable that shows whether something happened. It's usually a Boolean, a data type. Booleans are either True
, or False
, and nothing else. Instead of using booleans for flags, you could use String
s ("yes" or "no"), Integer
s (1 or 0), whatevs. Booleans happen to be convenient for flags, but use what you want.
Validation Sub
Here's the original validation code for pounds and ounces. The differences between validating pounds and validating ounces are marked.
The code is almost identical, so you should think, "Aha! Time for a Sub
." The differences are:
- The cell to check.
- The label to use for the variable in the error messages ("pounds" or "ounces").
Those differences become params for the Sub
. Here's one way to do it.
The first few lines document the Sub
, explaining each param. That's common. Human programmers often work in groups. One human might write checkCellValue
, and the other humans use it. Documenting the params helps those other humans.
Notice the first two params. They're the differences betwixt uses of the sub. To use it to check pounds:
checkCellValue 3, "pounds", poundsOK
To check ounces:
checkCellValue 4, "ounces", ouncesOK
The third param is the result of the check.
Notice the message
variable. Why does it exist? Another way to write the code:
Say the Bad Boss Human wanted errors to look like this:
With this code…
… we need to make the change for every error message. Two error messages, two changes. Eight error messages, eight changes.
With this code…
… we make the change only once, no matter how many error checks we have. Fewer chances of mistakes.
Calling the input validation routine
The weight conversion program is IPO: input, processing, output.
The main program should reflect that:
The main program doesn't call checkCellValue
directly. Instead, the main program calls the sub getInput
, which does all the input validation, and returns a flag showing whether the input was all OK, or if there were any errors. The main program checks that flag to decide whether to continue.
Here's getInput
:
It calls getInput
twice, once for each input cell. If both are OK, then it grabs data from the cells into the variables pounds
and ounces
, and sets the flag dataOK
to True
. Subs
calling Subs
is common.
Some questions for the class.
getInput
? Sub
is to make a chunk. It makes your program easier to understand, easier to test, and easier to change. It also makes it easier to have different people write different parts of the program.
So that's why they created a sub called getInput
.
Why did they create the sub checkCellValue
?
Sub
to do all of the input validation.
Argh! The names!
Here are the calls to checkCellValue
:
checkCellValue 3, "pounds", poundsOK
checkCellValue 4, "ounces", ouncesOK
Here's the sub's signature:
Sub checkCellValue(row As Integer, dataLabel As String, dataOK As Boolean)
The first param. It's 3, or 4, or dataOK
. Which is it?
It's different values at different times.
Params can make a sub behave differently each time it's called. The first time checkCellValue
is called, it messes with row 3. The next time, row 4.
That's one reason to add params. To make a sub do different things at different times.
Also, remember that it's the positions of the parameters that matters, not their names.
Suppose we had this code:
Compare lines 6 and 9. i
and j
are reversed. So here's how the variables in the main program map to the params in the sub:
So you'd see:
Params map to data in the caller.
i
, j
switcheroo, in RL?
It's asking for bugs.
Exercises
Rewrite it, adding error checking and Subs. It should work like this:
Some of the code has been written for you. Download the workbook. You'll see code like this:
Complete the program. Do not change any of the existing code. Remember to use the flag pattern.
Upload your solution.
In the text part of the submission form, please answer the question: What did you learn from this exercise?
(If you were logged in as a student, you could submit an exercise solution, and get some feedback.)