With some of the external factors out
of the way, it's
time to form a plan to find the best possible foundation, from a
technical perspective. You'll be tempted to get a
standard middleware stack and build from there. In fact, just by
starting with the gargantuan J2EE platform, you're
probably making far too many assumptions.After you've taken stock of external influences,
start with the most basic question: what are you building? Without
gathering a full set of requirements, you can still probably answer
some basic questions. You don't have to have all of
the answers from the beginning. In fact, you'll find
that you create additional questions as you spiral inward, as in
Figure 5-4. That's perfectly
normal. The important thing is to consider the questions that will
have the biggest overall impact on your designs. The outer-most
questions tend to disrupt designs more. Inner questions tend to
affect fewer systems.
Figure 5-4. As you explore foundational decisions, the process tends to spiral from the outside in
Your goal is to avoid over-designing out of the gate. (In fact,
you'd prefer to under-design out of the gate.) You
just want to avoid questions like, "So,
isn't passing SQL input directly from the user
interface going to murder security?" 10 minutes
before you're supposed to be in production.
Higher-level questionsthe outer questionsprompt more
detailed questions. This is natural, and helpful.
5.3.1 Outer Questions
Outer questions are the higher-level issues
that shape your foundation quickly.
You may be able to make a rough cut at your overall design without
writing any code, but it's not necessary. Just nail
down enough details to get some code rolling. Early code then helps
to shape your requirements and thus your design. Here are some outer
What are your external interfaces?
External interfaces make an
excellent starting point
when you're trying to iron out early decisions. An
external interface is one that you don't fully
control. Interfaces that cross major boundaries (such as programming
languages, networks, firewalls, or JVMs) may need special
consideration. You need a strategy for dealing with each before
Who is your user?
In the early design stages, look
at your user interface as
one more external interface. A professional data entry clerk has more
demanding requirements than an occasional departmental user.
Supporting external clients over the Internet also dictates
What are your physical deployment restrictions?
Firewalls and existing deployment hard
ware or software shape your solution. You
want to sanity-check compatibility at every turn. For example, if you
deploy a new message board discussing products with your existing
e-commerce application, make sure to use a compatible JVM, servlet
engine, and other software.
What are your database requirements?
Depending on your application,
you may or may not decide
to treat a database as just another distributed interface. Since
databases form the core of many applications, I prefer to treat them
separately. You'll need to decide on a persistence
strategy fairly quickly. Is JDBC enough? Will you need a persistence
framework? Do you expect to cache? Who owns the schema? These
questions can make or break a project.
What components must/might you reuse?
You may have inherited some business components that you think might
be useful. They'll come with some baggage, including
programming languages and styles, an interface, and an overall
philosophy. If developers err in this area, they often work too hard
to reuse a component that doesn't fit.
It's far better to steal some of the best ideas of
the inherited components and start from scratch. However, if one of
the components is a tax rules engine with an investment of 30 million
lines of code, you'll have to use it. Your most
critical task in that case is to wrap it in a way
that's consistent with your architecture.
What's your security policy?
Most developers treat
security as an add-on
service. Unfortunately, that technique extends to most operating
systems and programming environments. Fortunately, the news about
Java and .NET is slightly better. If you decide on a consistent
security policy before you start coding, you'll
avoid some common problems. In this area, you can't
guess; you need to know. If you've never heard of a
SQL injection attack, call an expert. Then form a cohesive policy and
follow it for all of your applications.
How fast does it need to be?
I can't think of many applications
designed correctly for performance out of the gate. Most were either
over-designed or under-designed. It's likely that
yours will be, too. The critical point is to make decisions that will
not paint you into a corner later. If you may need to cluster,
don't build in dependencies that make clustering
more difficult. You don't need to (and
shouldn't) optimize prematurely, but understand the
possible design implications of your expected load.
You can draw some rough lines in the sand by looking for the core
requirements of your project. That's the purpose of
the outer questions. You'll find that
you've only got partial answers, but you may have
enough information to understand your security model, the potential
software layers, and potential deployment scenarios.
5.3.2 Inner Questions
After you've asked the outer
questions and done some further
development, you're going to need to fine-tune your
architecture. That's the purpose of inner questions.
Inner questions drill down into specialized problems; their goal is
to refine your design, middleware requirements, and the interfaces
between layers. Think of an inner decision as a major fork in the
road. It's a detail that will definitely force a
foundational architectural decision. Answering an inner question
permits you to refine your design. Here are some examples of inner
questions. As you can see, they depend almost entirely on your
application:Will we support stored procedures? And which persistence frameworks
support stored procedures?Does my façade layer need to be distributed? If not, do we
still need to use session beans in the façade layer? If
not, can we replace the J2EE application server with a simple servlet
container and a web server?Would a persistence framework simplify things? Am I spending too much
time coding and debugging JDBC and raw SQL?
It's best to ask and answer these questions after
you've had some experience with the problem.
It's also best to put time and energy into answering
the questions and then live with your first answer until something
Sometimes, you'll find that
you need to write code to
answer an inner question. That's expected and
healthy. For example, you wouldn't want to use a
persistence framework without trying it first. And you
wouldn't want to use a persistence framework until
you've established a need. (I tell my customers to
push a POJO solution until it breaks, and only then get a persistence
framework.) When you do decide to prototype, write just enough code
to make your decision. Try to use production-coding techniques so
you'll have a firm grasp of the shape of the
solution. It's best to carve out a small but
technically demanding scenario, one that proves a representative
business requirement. If you're going to be paying
for a product, consider getting a vendor's
assistance.Regardless of the technique that you use to answer the inner
questions, make sure the team understands that once the decision is
made, there's no going back. Technical decisions can
fragment vulnerable teams. It's been my experience
that in order to keep everyone pulling together,
it's usually easier to get the entire team to agree
to abide by a decision once it's made.
When you think about it, what I've described
classical iterative development. Each iteration lets you know more
about the system and solve more of your target problem. The primary
way that processes differ in this area is the style and weight of
documentation. You need to collect just enough documentation to do
your job. Minimally, you've got to update your
requirements to reflect any new, needed functionality, based in a
foundational decision. The rest is entirely up to you. I prefer to
keep it light. Frequently, I'll handle outer
questions in meeting notes. For inner questions, if I need to get
teammates to agree to a decision in a meeting or after a prototype,
I'll try to follow the meeting or prototype exercise
with a simple email that covers:What we were trying to learnWhat we decidedWhat contributed to the decision
Then I'll copy everyone who needs to sign off and
say, "Does everybody agree?" This
informal process has served me well as a developer.
It's fast, to the point, and has just enough process
to get the job done. In fact, as a consultant, most of my major
agreements are not formal contracts. I also follow up with my
clients, describing what I learned and letting the customer sign off.
I find email organization services like listservs to be invaluable in
this respect. You can create a distribution list for
"architecture and design," for
instance. Then, for all decision-making emails, simply copy the
"architecture and design" listserv,
making a threaded repository of all decisions publicly available to
the whole team.