Skip to main content

Section 5.13 Incremental Development of Functions

We have seen multiple case studies that used incremental development to build their way to the final version of a program. We can use the same process to develop functions incrementally. Our first attempt at a function doesn’t have to always (or even ever) produce the correct return value. Instead, we can return some partial version of the answer (or a made up answer) while using print statements or a debugger to check what we have done so far.
As an example, suppose you want to find the distance between two points, given by the coordinates \((x_1, y_1)\) and \((x_2, y_2)\text{.}\) By the usual definition:
\begin{equation*} distance = \sqrt{(x_2 - x_1)^2 +(y_2 - y_1)^2} \end{equation*}
A distance function will need four parameters (the 2 x values and 2 y values) and will return a single value (the distance). So it’s prototype will look like this:
double distance(double x1, double y1, double x2, double y2)
Given this, we can write an outline for the function, which is sometimes called a stub. The stub includes the function declaration and a return statement:
double distance(double x1, double y1, double x2, double y2) {
    return 0;  // Fixme!!!
}
The function clearly is not returning the correct result, but the return statement allows it to compile. Which means that we can test the function without worrying about syntax errors. This program has some tests that will call the function and check its answer for various inputs:
Listing 5.13.1.
Running the program will result in failed tests. But the code itself should build and run. Now, we can start adding code and testing it. Even if those β€œtests” aren’t the final tests we will use.
Say we want to find the difference between the two x values and the two y values first. We might write code to do this, and then print out the values:
Listing 5.13.2.
By running that code, we can check the values being calculated and confirm they look correct. We will remove the print statements when the function is finished. Code like that is called scaffolding, because it is helpful for building the program but is not part of the final product. (We could use a debugger to check the values instead of printing them.)

Checkpoint 5.13.1.

The next step is to square dx and dy. We could use the Math.pow function, but it is simpler to multiply each term by itself. Then we add the squares and print the result so far. This is what the new version might look like with the new scaffolding added and the old removed:
double distance(double x1, double y1, double x2, double y2) {
    cout << "distance(" << x1 << ", " << y1 << ", " << x2 << ", " << y2 << ")" << endl;
    double dx = x2 - x1;
    double dy = y2 - y1;
    cout << "dx is " << dx << endl;
    cout << "dy is " << dy << endl;
    double dsquared = dx * dx + dy * dy;
    cout << "dsquared is " << dsquared << endl;
    return 0;  // Fixme!!!
}
Once we tested that version, we could try to finish the function be returning the square root of dsquared. That last line would hopefully pass the final tests for the function itself. Once we were sure it did, we could remove the debugging scaffolding to leave something like:
double distance(double x1, double y1, double x2, double y2) {
    double dx = x2 - x1;
    double dy = y2 - y1;
    double dsquared = dx * dx + dy * dy;
    return sqrt(dsquared);
}
As you gain more experience programming, you might write and debug more than one or two lines at a time. But if you find yourself spending a lot of time debugging, consider taking smaller steps.
You have attempted of activities on this page.