DEV Community

Edwin Torres
Edwin Torres

Posted on

Think Like a Programmer: Stepwise Refinement

I see lots of posts about how to do something in a particular programming language, for example:

  • How to center a <div> element
  • How to use JavaScript promises
  • How to create random numbers in Python

But I rarely see posts about how to develop a program. Any tutorial or online resource can explain programming syntax. That is only part of the battle. Knowing how to choose, combine, and organize programming statements to solve a programming problem is the real challenge.

One way to develop a program is what I call the all or none approach. It is straightforward:

  • Think about a solution
  • Code the entire program: Line 1, 2, 3, ...
  • Execute, test, and revise the program until it there are no more errors

One problem with this approach is that the program may encounter numerous errors, making it difficult to debug and fix. There is a better way.

Stepwise refinement is a programming technique where you start by looking at the problem at a high level. Then you break down the problem into smaller, more manageable components. Next, you develop and refine each component, at each level, step by step. Compile, execute, and test every step of the way. The process continues until all components are developed, with no need to break them down any further. It is an iterative approach where you develop the program a little bit at a time.

Here is an example of stepwise refinement. Consider the following problem:

Convert Fahrenheit temperature to Celsius temperature.

We will write this program in Java. Using stepwise refinement, we break down that problem into subtasks:

  1. Accept Fahrenheit temperature as input.
  2. Calculate Celsius temperature.
  3. Output results.

We break down these subtasks even further. To Accept Fahrenheit temperature as input:

  1. Prompt the user to enter a Fahrenheit temperature.
  2. Accept the temperature value as input.
  3. Store the temperature value in a variable.

At this point, we can write a small program that only prompts the user to enter the Fahrenheit temperature:

public class Temperature { 
  public static void main(String[] args) { 
    System.out.print("Enter a Fahrenheit temperature: ");
  }
}
Enter fullscreen mode Exit fullscreen mode

Now compile and execute the program. Make sure it works. Make sure the output is what you expect. If there are errors, it will be easy to debug, since the program is small.

Once you are certain that the program works properly, continue to the next subtasks. Write code to accept the input Fahrenheit temperature and store the value in a variable:

import java.util.Scanner;  // NEW

public class Temperature { 
  public static void main(String[] args) { 
    System.out.print("Enter a Fahrenheit temperature: ");

    Scanner s = new Scanner(System.in);  // NEW
    double fahr = s.nextDouble();  // NEW
  }
}
Enter fullscreen mode Exit fullscreen mode

Once again, compile, execute, and test. But you only need test the new code, not the code from the previous iteration. Use a debugger or output statement to verify the value of the fahr variable. Make sure the input value is what you expect. This completes the Accept Fahrenheit temperature as input step.

Now write the code for the Calculate Celsius temperature step. With much of the program already written, this step only requires a little research to find the formula and just one new line:

import java.util.Scanner;

public class Temperature { 
  public static void main(String[] args) { 
    System.out.print("Enter a Fahrenheit temperature: ");

    Scanner s = new Scanner(System.in);
    double fahr = s.nextDouble();

    double cels = (fahr - 32) * 5.0/9.0; // NEW
  }
}
Enter fullscreen mode Exit fullscreen mode

Compile, execute, and test. Use a debugger or output statement to verify the value of the cels variable. Make sure the value is correct.

The last step is the Output results subtask:

import java.util.Scanner;

public class Temperature { 
  public static void main(String[] args) { 
    System.out.print("Enter a Fahrenheit temperature: ");

    Scanner s = new Scanner(System.in);
    double fahr = s.nextDouble();

    double cels = (fahr - 32) * 5.0/9.0;

    System.out.println(fahr + "degrees Fahrenheit is " + cels + " degrees Celsius."); // NEW
  }
}
Enter fullscreen mode Exit fullscreen mode

Compile, execute, and test. Verify that the output statement is correct. If it is not, revise and repeat.

This sample problem may be simple enough to solve using the all or none programming approach. But the example demonstrates stepwise refinement, which is useful when solving more complicated programming problems. Break them down into more manageable subtasks and so on. Code a little bit at a time, execute, test, and repeat. Develop the program incrementally. Fix problems along the way. This will make complicated programming problems a lot easier to solve.

Thanks for reading. πŸ˜ƒ

Follow me on Twitter @realEdwinTorres for more programming tips and help.

Top comments (2)

Collapse
 
mccurcio profile image
Matt Curcio

Hi Edwin,
You are absolutely right. I would love to hear your thoughts on engineering approaches.
I participated in a Hackathon some time ago and was really surprised that NOONE had thought to flow-charting their more complex problems. Actually, many were unfamiliar with the concept. Flowcharts can be sooo simple too. To me, Flowcharts are like outlines when you are writing a big paper.

Collapse
 
realedwintorres profile image
Edwin Torres

Hi Matt-

As for engineering approaches, it starts with the type of project. But I have been doing more Agile Software Development lately. I love the flexibility, iterative nature, collaboration, and immediate results. Plus, you learn and adjust as you go. So you end up doing the right thing, early on. I actually teach Agile/DevOps at the college level, so obviously I’m a fan. πŸ‘πŸΌ

I’m also a believer in flowcharting. A picture is worth a thousand words.