Formal Design Process
The formal design process generally occurs
after a functional specification is written and you know
what you are building. While it's possible and often
useful to play with designs and prototypes before
everything is known, the devil is in the details and it's
important to have an entire picture before carrying out
hard core design.
The actual design process can vary
greatly, depending on the structure and purpose of the
system; for instance, building J2EE web applications can
be quite different than assembler kernel modules.
A Group Project
Good design is a group project, especially
at the system and architecture level. This group
includes QA and sometimes other groups who have a
significant stake in how things get developed. Most
companies forget to include QA or Support and end up with
designs that lack basic features needed to support the
efforts of those groups. This is especially true of
QA's role, as many designs are very difficult to test;
modest changes at the design stage can vastly improve the
quality of the system.
Basic Architecture & Technologies
Next, decide on the basic structure of the
system and the general technologies to be employed.
For instance, is this a web-based system using J2EE on
application servers, or is it a COBOL middle-ware system
to run on Windows NT. These choices, which should
not be made lightly, go a long way in determining the
design approaches used throughout the process.
Architecture & Logical Modules
Now, look at how the system might be put
together (everything is still at the trial stage at this
point), including some listings of obvious system modules
and how they might fit together. Pay attention to
how data and events will flow in and out of the system,
and between modules. Good design generally dictates
a modular (and probably object-oriented) architecture, so
figure out how this relates to your system.
Once you make a single pass at
modularization, you should begin to have some sense of the
scope and structure of the system. Next, dive down
another level or two in discussing various aspects of the
system, including basic data objects (customer, account,
article, etc.), how things are stored, memory management,
database interaction, session management, error handling,
Then, the next level architecture - What are the
components of the system, including major classes?
How do they interact; who calls who, what's the exact
flow, what are the alternate flows - this needs a full
system flow and diagram set that can be carefully managed
later. How flexible is everything. How encapsulated
is everything? How is memory handled, in detail, for
network, parsing, read/write, flow-through, etc., who
releases it, when? What are high/low water marks for
things, when/how do we shed load?
Third level design - What do the classes look like in
detail, how do we interact with subsystems and memory. How
are logging, diagnostics and stats done. How is parsing
done (hand or lex parsers). What functions are needed in
what classes, do an interaction diagram.
Code layout - Layout the source code files in a way
that makes sense, working hard to reduce the possibilities
of collisions. This includes using directories for major
subsystems and lots of files, plus a good include system
that makes sense. Deal with any multi-platform
issues right up front, including how these will be
organized and made, including platform QA issues.
At this point, people will know how the system is put
together and generally how it will work. The next
step is to create a functional list of things for people
to work on. This will include which modules go to
which person, what the initial areas of responsibility
are, etc. From this point, the process moves to the
Just keep peeling away the onion to
determine data structures, detailed information flow,
error recovery, etc. In general, developers tend to
resist getting too deep on this, but experience has shown
that group design even at low levels ends up with superior
results and fewer missed challenges.
Services & Abstractions
Once you have a handle on the structure of
things, begin thinking about common services and
abstractions. Services include configuration,
logging, diagnostics/debugging, security, communications,
user tracking and statistics, database management and
similar functions. These should all be pushed into
dedicated modules or objects, allowing for abstract
interfaces and minimal repetition in the main system.
Abstractions are also important in
combining common characteristics. Commonly
implemented as base classes in OO systems, these are just
ways of sharing common functions, data structures, etc.
Re-factoring, discussed later, is a key method of
continual abstraction and combinatorial design.
Use of UML in design
If at all possible, consider using UML in the design
process. The Unified Modeling Language is a very
useful set of tools and methodologies that both builds and
documents the knowledge base in and around the design.
Some people sell UML as being able to write code for you,
but this is not its primary utility - having good, easy to
update, documentation and a process for working out the
design are the key benefits.
If the system involves performance requirements or
complex processing, consider the use of mathematical
modeling of key issues. This allows for additional
thought on potentially problematic areas and provides for
some guidelines to measure against once the system is