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:
- Get your class notebook.
- Write these headings:
Things I need to complete or create |
Tasks | Modules | Data Types | Algorithms | Functions |
- 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:
- 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.
- 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.
- Does this paragraph introduce a new type of data?
If so,
- How will that data be represented?
- Will it be an abstract data type or will
its representation
be exposed in a header file?
- What functions should be packaged with
the data type in the
same module?
- Does it relate to a task?
If so, note it on the sheet for that task.
- 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?
- 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:
- What are my most important data types?
- 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?
- For each data type, are there functions related to it
that should reside in the same module with the data type?
What are they?
- 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?
- 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:
- Do all of the subproblems appear easier to solve (or better specified)
than the original problem?
- Can I solve some of the subproblems with library functions?
- Are some of the subproblems so simple I know how to write functions
for them?
- Can I test the solutions to subproblems independently of the whole
problem? (This testing technique is called unit testing.)
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