#004 – How do we develop programs? Part 1

Now, I’m sure you’re itching to develop your first programs. However, before writing your first C++ programs, it is worth understanding the workflow behind programming.

A program exists for a reason. It is a solution to a problem. If the problem is unclear, the code will be unclear. If the solution is poorly designed, the bugs will usually appear later when the program becomes harder to change.

Three things to take away:

  • Programming starts with understanding the problem, not writing code.
  • A better design usually produces simpler code.
  • The development workflow gives you a repeatable way to move from idea to executable program.

The development workflow

Here is the complete flowchart. Let’s analyze it step by step

Step 1 – Scrutinize the problem

What problem are you intending to solve?

The first question is not:

What code should I write?

The first question is:

What problem am I solving?

This matters because vague problems produce vague programs.

Compare these two goals:

I want to make a calculator.

and:

I want to write a program that asks the user for two numbers and an operator,
then prints the result of applying that operator.

The second version is much better. It tells us what inputs the program needs, what operation it performs, and what output it should produce.

Here are two more examples:

I want to write a program that lets the user enter several numbers,
then calculates and prints the average.
I want to write a program that generates a 2D maze, lets the user move through it, and reports success when the user reaches the exit.

A useful habit is to identify:

  • The required input
  • The required output
  • The rules of the problem
  • The invalid cases
  • The point at which the program is finished

For the average calculator, this might look like:

Input: numbers entered by the user
Output: average of those numbers
Rules: average = total / count
Invalid cases: no numbers entered
Finished when: the user chooses to stop entering numbers

We haven’t coded yet however the foundations are taking shape.

Step 2 – Design a solution

Design is the how.

There are usually multiple ways to solve the same problem. Some are simple and maintainable. Others technically work but become difficult to extend, test, or debug.

Do not rush this step. That results in bugs.

The majority of a software developer’s time isn’t actually spent writing the program. It’s spent on maintenance, which is caused by a lack of planning. Thus, it pays to invest in planning now to avoid headaches in the future.

For example, for the average calculator, a simple design could be:

1. Set total to 0.
2. Set count to 0.
3. Repeatedly ask the user for a number.
4. Add each number to total.
5. Increment count for each valid number.
6. When input is finished, calculate total / count.
7. Print the result.

This is not C++ yet. It is an algorithm: a sequence of steps that solves the problem.

Good solutions tend to have a few qualities:

  • Straightforward: the logic is easy to follow.
  • Modular: the program is broken into smaller pieces.
  • Documented where necessary: the important reasoning is explained.
  • Robust: invalid input and edge cases are considered.
  • Changeable: small requirement changes do not require rewriting everything.

A weak design often hides complexity.

Step 3 – Program the solution

Aahh. The fun part.

Once the problem is understood and the solution is designed, we can write the code.

For the average calculator, the first version might be deliberately simple:

#include <iostream>

int main(){
    double total { 0.0 };
    int count { 0 };

    std::cout << "How many numbers will you enter? ";
    std::cin >> count;

    for (int i { 0 }; i < count; ++i) {
        std::cout << "Enter number " << i + 1 << ": ";

        double value {};
        std::cin >> value;

        total += value;
    }

    if (count > 0) {
        std::cout << "Average: " << total / count << '\\n';
    } else {
        std::cout << "No numbers entered.\\n";
    }
}

This program is not perfect. It does not properly validate bad input, and it assumes the user enters the number of values upfront.

That is acceptable for a first implementation.

The purpose of the first version is to convert the design into working code. Once it works, we can iterate on it.

In Summary

Programming becomes less chaotic when you follow a repeatable process.

Do not begin with code. Begin with the problem. Then design the solution. Then write the program. Then compile it.

We’ll resume Step 4 – Compile the program in the next Nibble. See you then!