Analysis and design
The object-oriented paradigm is a new and
different way of thinking about programming and many folks have trouble at first
knowing how to approach an OOP project. Once you know that everything is
supposed to be an object, and as you learn to think more in an object-oriented
style, you can begin to create “good” designs that take advantage of
all the benefits that OOP has to offer.
A method
(often called a methodology) is a set of processes and heuristics
used to break down the complexity of a programming problem. Many OOP methods
have been formulated since the dawn of object-oriented programming. This section
will give you a feel for what you’re trying to accomplish when using a
method.
Especially in OOP, methodology is a field
of many experiments, so it is important to understand what problem the method is
trying to solve before you consider adopting one. This is particularly true with
C++, in which the programming language is intended to reduce the complexity
(compared to C) involved in expressing a program. This may in fact alleviate the
need for ever-more-complex methodologies. Instead, simpler ones may suffice in
C++ for a much larger class of problems than you could handle using simple
methodologies with procedural languages.
It’s also important to realize that
the term “methodology” is often too grand and promises too much.
Whatever you do now when you design and write a program is a method. It may be
your own method, and you may not be conscious of doing it, but it is a process
you go through as you create. If it is an effective process, it may need only a
small tune-up to work with C++. If you are not satisfied with your productivity
and the way your programs turn out, you may want to consider adopting a formal
method, or choosing pieces from among the many formal methods.
While you’re going through the
development process, the most important issue is this: Don’t get lost.
It’s easy to do. Most of the analysis and design
methods are intended to solve the largest of problems.
Remember that most projects don’t fit into that category, so you can
usually have successful analysis and design with a relatively small subset of
what a method
recommends[9].
But some sort of process, no matter how limited, will generally get you on your
way in a much better fashion than simply beginning to code.
It’s also easy to get stuck, to
fall into “analysis
paralysis,” where you feel like you can’t move forward because you
haven’t nailed down every little detail at the current stage. Remember, no
matter how much analysis you do, there are some things about a system that
won’t reveal themselves until design time, and more things that
won’t reveal themselves until you’re coding, or not even until a
program is up and running. Because of this, it’s crucial to move fairly
quickly through analysis and design, and to implement a test of the proposed
system.
This point is worth emphasizing. Because
of the history we’ve had with procedural languages, it is commendable that
a team will want to proceed carefully and understand every minute detail before
moving to design and implementation. Certainly, when creating a DBMS, it pays to
understand a customer’s needs thoroughly. But a DBMS is in a class of
problems that is very well-posed and well-understood; in many such programs, the
database structure is the problem to be tackled. The class of programming
problem discussed in this chapter is of the “wild-card” (my term)
variety, in which the solution isn’t simply re-forming a well-known
solution, but instead involves one or more
“wild-card factors” – elements for
which there is no well-understood previous solution, and for which research is
necessary[10].
Attempting to thoroughly analyze a wild-card problem before moving into design
and implementation results in analysis paralysis because you don’t have
enough information to solve this kind of problem during the analysis phase.
Solving such a problem requires iteration through the whole cycle, and that
requires risk-taking behavior (which makes sense, because you’re trying to
do something new and the potential rewards are higher). It may seem like the
risk is compounded by “rushing” into a preliminary implementation,
but it can instead reduce the risk in a wild-card project because you’re
finding out early whether a particular approach to the problem is viable.
Product development is risk management.
It’s often proposed that you
“build one to throw away.” With OOP, you may still throw part
of it away, but because code is encapsulated into classes, during the first
iteration you will inevitably produce some useful class designs and develop some
worthwhile ideas about the system design that do not need to be thrown away.
Thus, the first rapid pass at a problem not only produces critical information
for the next analysis, design, and implementation iteration, it also creates a
code foundation for that iteration.
That said, if you’re looking at a
methodology that contains tremendous detail and suggests many steps and
documents, it’s still difficult to know when to stop. Keep in mind what
you’re trying to discover:
- What are the objects? (How
do you partition your project into its component
parts?)
- What are
their interfaces? (What messages do you need to be able to send to each
object?)
If you come up with
nothing more than the objects and their interfaces, then you can write a
program. For various reasons you might need more descriptions and documents than
this, but you can’t get away with any less.
The process can be undertaken in five
phases, and a phase 0 that is just the initial commitment to using some kind of
structure.