Specifying the Function Input Conditions
PreConditions
You have previously worked your way through creating a simple program that used simple functions to draw pictures. In essence, each function was a stand-alone command and you typed the number of functions you needed in the correct sequence needed to create the asterisk box. It was important for you to get through that process because the sequencing and application of functions in your programs is what programming is about. However, there are ways to make the functions more powerful and effective so that your program development is both easier and more efficient. Consider the following.
Preconditions. The first thing you need to know or decide is what the preconditions for your function design will be. If someone has told you what the preconditions will be, you can just follow her rules and design your function as needed. However, many times you will be the one designing the whole program, so as you design your functions you need to know what your function can, or might be required to, handle.
Say for example that you are writing a function to divide two numbers. A precondition should be that the divisor will never be zero when this function is used. If there is a chance that the divisor will be zero, your function must be able to adapt to that condition.
Another example would be a function that calculates factorials. Since the highest normal integer can only reach to about 264 (on most computers), your function may crash the program or return bad data if the answer is greater than this limit allows. This means that if a number that is too large is entered to be factorialized, there will be a problem.
Other example preconditions:
- function will be passed a c-string containing a user prompt (meaning it will not be passed an integer or a double value)
- function will never be passed a negative number
- function will only be passed an integer value
- etc
The key to preconditions is that you will design your function with the expectation that the input or starting conditions will be correct within certain constraints, or you will design your function to respond to the inappropriate conditions. More about this later.
So, how do you decide what the preconditions should (and maybe shouldn't) be?
Go back to the previous division function example. If you have a function that is supposed to divide one number by the other, what will the function need to know? It will be assumed that the function itself will know how to divide numbers, but it won't automatically know which numbers to divide. Therefore, you will decide to send it a divisor and a dividend, shown in the following prototype.
public double divideTwoNumbers( double divisor, double dividend );
Your factorial function will know how to implement the factorial action, but that will only require the number to be factorialized and it doesn't need anything else. The “What’s the same?” and “What’s different?” questions are asked and you find that this function only needs to accept one value, as shown in the following prototype.
public double calcFactorial( double value );
One more example. Consider a situation where your function calculates and adds a sales tax to a sales subtotal. The function will need to know the subtotal and the tax rate. However, most commonly the tax rate is a global constant, and these constants do not need to be passed to functions because they are in scope (i.e., available) everywhere in the source code. Therefore the function preconditions will be that the subtotal is passed to the function, and that the tax rate will be available as a class or global constant, yielding the following function prototype. The “What’s the same?” question is that the tax, which is always the same in the program, will always be multiplied by the subtotal. The “What’s different?” question is that the subtotal will be different with each call of the function.
public double calcTotal( double subtotal );
Once you have figured out the preconditions for a function, you can decide what you need for input to the function. Deciding, and then specifying (i.e., creating a specification for) the input for each function will be required for all functions you write.
Watch this video to see more examples of the Pre-Condition assessment leading to function inputs.