How to analyze a programming problem

As a working engineer, you will frequently be faced with an internal or external customer who has an ill-defined problem and needs a solution on a short schedule. During your education, it will rarely be appropriate for your instructors to pose ill-defined problems, but it is both appropriate and helpful for them to pose problems in a way that forces you to analyze them. (The primary meaning of the word ``analyze'' is ``to break into parts,'' primarily for purposes of understanding the whole. It comes from a Greek root meaning ``to dissolve.'') Analysis of a problem requires breaking the problem into parts in order to understand it. Once you understand the structure of the problem, your understanding should lead you to a solution.

When solving a problem by computer, one normally designs a program by breaking the problem into parts, which in turn can be broken into subparts, and so on, until the individual sub-sub-parts are either already to be found in a library or are so easy as to admit of simple, quick solution. Each individual subpart is solved by a function or by a collection of functions in a module. Each solution is written as another function, and so on, all the way up to the main function, which solves the whole problem. In other words, the solution to the main problem is composed of solutions to the individual parts. To design software systems successfully, you must master the techniques of analysis and composition.

You can develop your analytical skills by applying the following systematic technique to any assignment:

  1. Get your class notebook.

  2. Write these headings:
    Things I need to complete or create
    Tasks Modules Data Types Algorithms Functions
  3. On a separate piece of paper, write these headings:
    Things that are provided for me
    Modules Data Types Algorithms Functions Code
Now read the rest of the assignment paragraph by paragraph. For each paragraph, ask yourself these questions:
  1. Does this paragraph describe a task you are to accomplish? If so, list it in your notebook under tasks. For nontrivial tasks, start a fresh sheet of paper for the task, and use it to keep track of modules, data types, algorithms, functions, and advice related to the task.

  2. Does this paragraph describe a module, data type, algorithm, or function that is provided for you? If so, what is it? Does it solve a problem? Does it represent a subtask to be accomplished? Will it help solve a subtask you already know about? In that case, make a note of it on the sheet of paper for that task.

  3. Does this paragraph introduce a new type of data? If so,

  4. Does this paragraph suggest a module, algorithm, or function that you will need to develop? If so, what sub-problem will it solve? What tasks does it relate to? How will it connect with other elements of the system in order to form a harmonious, useful whole? Will it need new data types?

  5. If this paragraph suggests a programming technique or a problem to watch out for, to which tasks, modules, data types, algorithms, or functions is it likely to be relevant?
As you answer these questions, organize the answers in writing using the two sets of headers I've suggested for you, as well as a separate sheet for each major task.

Once you've analyzed the whole assignment, you can start tackling the design. Here are some more questions to ask:

  1. What are my most important data types?
  2. For each data type, should it reside in a module of its own, or should it be grouped in a single module with other data types?
  3. For each data type, are there functions related to it that should reside in the same module with the data type? What are they?
  4. Are there functions that are not necessarily related to any data type but are related to each other, so they should be grouped in the same module?
  5. Which modules should be clients of which other modules?

At this point you are probably ready to design your program. I encourage you to follow Wirth's method of stepwise refinement. This method encourages you to decompose problems into subproblems. About any possible decomposition you can ask:

During the process of refinement, you may invent new modules, data types, algorithms, and functions that you believe you need to help solve your problem. Add them to your lists.

For an example of how to apply this method to a particular programming problem, see the problem of building a lossy image compressor.


Back to the COMP 40 home page