TheFreeSite.com!

Monday, July 28, 2008

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 a project. Now that you
know that everything is supposed to be an object, you can create a “good” design, one that
will take advantage of all the benefits that OOP has to offer.
Books on OOP analysis and design are coming out of the woodwork. Most of these books are
filled with lots of long words, awkward prose and important-sounding pronouncements.9 I
come away thinking the book would be better as a chapter or at the most a very short book
and feeling annoyed that this process couldn’t be described simply and directly. (It disturbs
me that people who purport to specialize in managing complexity have such trouble writing
clear and simple books.) After all, the whole point of OOP is to make the process of software
development easier, and although it would seem to threaten the livelihood of those of us who
consult because things are complex, why not make it simple? So, hoping I’ve built a healthy
skepticism within you, I shall endeavor to give you my own perspective on analysis and
design in as few paragraphs as possible.
Staying on course
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 these methodologies are designed to solve the largest of
problems. (This makes sense; these are the especially difficult projects that justify calling in
that author as consultant, and justify the author’s large fees.) Remember that most projects
don’t fit into that category, so you can usually have a successful analysis and design with a
relatively small subset of what a methodology recommends. 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.
9 The best introduction is still Grady Booch’s Object-Oriented Design with Applications, 2nd edition, Wiley
& Sons 1996. His insights are clear and his prose is straightforward, although his notations are
needlessly complex for most designs. (You can easily get by with a subset.)
Chapter 1: Introduction to Objects 65
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:
1. What are the objects? (How do you partition your project into its component parts?)
2. 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 really get away with any less.
The process can be undertaken in four phases, and a phase 0 which is just the initial
commitment to using some kind of structure.
Phase 0: Let’s make a plan
The first step is to decide what steps you’re going to have in your process. It sounds simple
(in fact, all of this sounds simple) and yet, often, people don’t even get around to phase one
before they start coding. If your plan is “let’s jump in and start coding,” fine. (Sometimes
that’s appropriate when you have a well-understood problem.) At least agree that this is the
plan.
You might also decide at this phase that some additional process structure is necessary but
not the whole nine yards. Understandably enough, some programmers like to work in
“vacation mode” in which no structure is imposed on the process of developing their work:
“It will be done when it’s done.” This can be appealing for awhile, but I’ve found that having
a few milestones along the way helps to focus and galvanize your efforts around those
milestones instead of being stuck with the single goal of “finish the project.” In addition, it
divides the project into more bite-sized pieces and make it seem less threatening.
When I began to study story structure (so that I will someday write a novel) I was initially
resistant to the idea, feeling that when I wrote I simply let it flow onto the page. What I
found was that when I wrote about computers the structure was simple enough so I didn’t
need to think much about it, but I was still structuring my work, albeit only semiconsciously
in my head. So even if you think that your plan is to just start coding, you still
go through the following phases while asking and answering certain questions.
Phase 1: What are we making?
In the previous generation of program design (procedural design), this would be called
“creating the requirements analysis and system specification.” These, of course, were places to
get lost: intimidatingly-named documents that could become big projects in their own right.
Their intention was good, however. The requirements analysis says “Make a list of the
guidelines we will use to know when the job is done and the customer is satisfied.” The
system specification says “Here’s a description of what the program will do (not how) to
satisfy the requirements.” The requirements analysis is really a contract between you and
the customer (even if the customer works within your company or is some other object or
system). The system specification is a top-level exploration into the problem and in some
sense a discovery of whether it can be done and how long it will take. Since both of these
will require consensus among people, I think it’s best to keep them as bare as possible –
ideally, to lists and basic diagrams – to save time. You might have other constraints that
require you to expand them into bigger documents.
66 Thinking in Java www.BruceEckel.com
It’s necessary to stay focused on the heart of what you’re trying to accomplish in this phase:
determine what the system is supposed to do. The most valuable tool for this is a collection
of what are called “use-cases.” These are essentially descriptive answers to questions that
start with “What does the system do if …” For example, “What does the auto-teller do if a
customer has just deposited a check within 24 hours and there’s not enough in the account
without the check to provide the desired withdrawal?” The use-case then describes what the
auto-teller does in that case.
You try to discover a full set of use-cases for your system, and once you’ve done that you’ve
got the core of what the system is supposed to do. The nice thing about focusing on usecases
is that they always bring you back to the essentials and keep you from drifting off into
issues that aren’t critical for getting the job done. That is, if you have a full set of use-cases
you can describe your system and move onto the next phase. You probably won’t get it all
figured out perfectly at this phase, but that’s OK. Everything will reveal itself in the fullness
of time, and if you demand a perfect system specification at this point you’ll get stuck.
It helps to kick-start this phase by describing the system in a few paragraphs and then
looking for nouns and verbs. The nouns become the objects and the verbs become the
methods in the object interfaces. You’ll be surprised at how useful a tool this can be;
sometimes it will accomplish the lion’s share of the work for you.
Although it’s a black art, at this point some kind of scheduling can be quite useful. You now
have an overview of what you’re building so you’ll probably be able to get some idea of how
long it will take. A lot of factors come into play here: if you estimate a long schedule then
the company might not decide to build it, or a manager might have already decided how
long the project should take and will try to influence your estimate. But it’s best to have an
honest schedule from the beginning and deal with the tough decisions early. There have been
a lot of attempts to come up with accurate scheduling techniques (like techniques to predict
the stock market), but probably the best approach is to rely on your experience and
intuition. Get a gut feeling for how long it will really take, then double that and add 10
percent. Your gut feeling is probably correct; you can get something working in that time.
The “doubling” will turn that into something decent, and the 10 percent will deal with final
polishing and details. However you want to explain it, and regardless of the moans and
manipulations that happen when you reveal such a schedule, it just seems to work out that
way.
Phase 2: How will we build it?
In this phase you must come up with a design that describes what the classes look like and
how they will interact. A useful diagramming tool that has evolved over time is the Unified
Modeling Language (UML). You can get the specification for UML at www.rational.com. UML
can also be helpful as a descriptive tool during phase 1, and some of the diagrams you create
there will probably show up unmodified in phase 2. You don’t need to use UML, but it can
be helpful, especially if you want to put a diagram up on the wall for everyone to ponder,
which is a good idea. An alternative to UML is a textual description of the objects and their
interfaces (as I described in Thinking in C++), but this can be limiting.
The most successful consulting experiences I’ve had when coming up with an initial design
involves standing in front of a team, who hadn’t built an OOP project before, and drawing
objects on a whiteboard. We talked about how the objects should communicate with each
other, and erased some of them and replaced them with other objects. The team (who knew
what the project was supposed to do) actually created the design; they “owned” the design
rather than having it given to them. All I was doing was guiding the process by asking the
right questions, trying out the assumptions and taking the feedback from the team to
Chapter 1: Introduction to Objects 67
modify those assumptions. The true beauty of the process was that the team learned how to
do object-oriented design not by reviewing abstract examples, but by working on the one
design that was most interesting to them at that moment: theirs.
You’ll know you’re done with phase 2 when you have described the objects and their
interfaces. Well, most of them – there are usually a few that slip through the cracks and
don’t make themselves known until phase 3. But that’s OK. All you are concerned with is
that you eventually discover all of your objects. It’s nice to discover them early in the
process but OOP provides enough structure so that it’s not so bad if you discover them later.
Phase 3: Let’s build it!
If you’re reading this book you’re probably a programmer, so now we’re at the part you’ve
been trying to get to. By following a plan – no matter how simple and brief – and coming up
with design structure before coding, you’ll discover that things fall together far more easily
than if you dive in and start hacking, and this provides a great deal of satisfaction. Getting
code to run and do what you want is fulfilling, even like some kind of drug if you look at
the obsessive behavior of some programmers. But it’s my experience that coming up with an
elegant solution is deeply satisfying at an entirely different level; it feels closer to art than
technology. And elegance always pays off; it’s not a frivolous pursuit. Not only does it give
you a program that’s easier to build and debug, but it’s also easier to understand and
maintain, and that’s where the financial value lies.
After you build the system and get it running, it’s important to do a reality check, and here’s
where the requirements analysis and system specification comes in. Go through your
program and make sure that all the requirements are checked off, and that all the use-cases
work the way they’re described. Now you’re done. Or are you?
Phase 4: Iteration
This is the point in the development cycle that has traditionally been called “maintenance,” a
catch-all term that can mean everything from “getting it to work the way it was really
supposed to in the first place” to “adding features that the customer forgot to mention
before” to the more traditional “fixing the bugs that show up” and “adding new features as
the need arises.” So many misconceptions have been applied to the term “maintenance” that
it has taken on a slightly deceiving quality, partly because it suggests that you’ve actually
built a pristine program and that all you need to do is change parts, oil it and keep it from
rusting. Perhaps there’s a better term to describe what’s going on.
The term is iteration. That is, “You won’t get it right the first time, so give yourself the
latitude to learn and to go back and make changes.” You might need to make a lot of
changes as you learn and understand the problem more deeply. The elegance you’ll produce
if you iterate until you’ve got it right will pay off, both in the short and the long run.
What it means to “get it right” isn’t just that the program works according to the
requirements and the use-cases. It also means that the internal structure of the code makes
sense to you, and feels like it fits together well, with no awkward syntax, oversized objects
or ungainly exposed bits of code. In addition, you must have some sense that the program
structure will survive the changes that it will inevitably go through during its lifetime, and
that those changes can be made easily and cleanly. This is no small feat. You must not only
understand what you’re building, but also how the program will evolve (what I call the
vector of change). Fortunately, object-oriented programming languages are particularly adept
at supporting this kind of continuing modification – the boundaries created by the objects
68 Thinking in Java www.BruceEckel.com
are what tend to keep the structure from breaking down. They are also what allow you to
make changes that would seem drastic in a procedural program without causing
earthquakes throughout your code. In fact, support for iteration might be the most
important benefit of OOP.
With iteration, you create something that at least approximates what you think you’re
building, and then you kick the tires, compare it to your requirements and see where it falls
short. Then you can go back and fix it by redesigning and re-implementing the portions of
the program that didn’t work right.10 You might actually need to solve the problem, or an
aspect of the problem, several times before you hit on the right solution. (A study of Design
Patterns, described in Chapter 16, is usually helpful here.)
Iteration also occurs when you build a system, see that it matches your requirements and
then discover it wasn’t actually what you wanted. When you see the system, you realize
you want to solve a different problem. If you think this kind of iteration is going to happen,
then you owe it to yourself to build your first version as quickly as possible so you can find
out if it’s what you want.
Iteration is closely tied to incremental development. Incremental development means that you
start with the core of your system and implement it as a framework upon which to build
the rest of the system piece by piece. Then you start adding features one at a time. The trick
to this is in designing a framework that will accommodate all the features you plan to add
to it. (See Chapter 16 for more insight into this issue.) The advantage is that once you get
the core framework working, each feature you add is like a small project in itself rather than
part of a big project. Also, new features that are incorporated later in the development or
maintenance phases can be added more easily. OOP supports incremental development
because if your program is designed well, your increments will turn out to be discreet
objects or groups of objects.
Plans pay off
Of course you wouldn’t build a house without a lot of carefully-drawn plans. If you build a
deck or a dog house, your plans won’t be so elaborate but you’ll still probably start with
some kind of sketches to guide you on your way. Software development has gone to
extremes. For a long time, people didn’t have much structure in their development, but then
big projects began failing. In reaction, we ended up with methodologies that had an
intimidating amount of structure and detail. These were too scary to use – it looked like
you’d spend all your time writing documents and no time programming. (This was often the
case.) I hope that what I’ve shown you here suggests a middle path – a sliding scale. Use an
approach that fits your needs (and your personality). No matter how minimal you choose to
make it, some kind of plan will make a big improvement in your project as opposed to no
plan at all. Remember that, by some estimates, over 50 percent of projects fail.
10 This is something like “rapid prototyping,” where you were supposed to build a quick-and-dirty
version so that you could learn about the system, and then throw away your prototype and build it
right. The trouble with rapid prototyping is that people didn’t throw away the prototype, but instead
built upon it. Combined with the lack of structure in procedural programming, this often leads to
messy systems that are expensive to maintain.

0 comments:

Tell Me Doubts In Java