small medium large xlarge

Never Build an Application

We say ``Never build an application."

“But,” you may reply, “isn’t that what application programming is all
about?”

“Yes.” We smile irritatingly. “But it shouldn’t be.”

What do we mean by this?

The first problem lies in building an application slavishly to
fixed, rigid requirements.

Given the fluid nature of the user’s requirements and the rapidly changing
face of business requirements in today’s market, it is foolish to
try to build the application that you originally set out to build! By
the time the project is complete, the needs will have changed.
You will have built a legacy application right from the start, that needs to
be ripped up and re-engineered to reflect not only the changes to the
business world, but also to reflect the wisdom garnered by the staff
during code development.

Now some folks will say, “ah, but we use an iterative
development

process so we can track the changing requirements as they happen!”.
Well, not really. The team is still focused on building an application,
perhaps one with a slightly shifting set of features, but any larger
changes to work flow or capabilities is as likely as not to run aground.

A short digression:
Some people misinterpret iterative development to mean the same
thing as a waterfall-style development (analysis → design → code → test)
but with a much shorter cycle time. They miss an important point;
the activities involved are peer functions, and you may freely
bop between coding, analysis, design, test, etc. in any order in a
non-linear fashion.
These folks will often insist on a finalized design document before coding
begins, ignoring the valuable feedback path from coding that influences
design (and even analysis).

But even with a proper iterative development environment,
the focus is mainly on developing
an application, and I maintain that this is the wrong goal.
So if you shouldn’t build an application, what should you build?

Language Design

Rather than designing an application to serve a limited, fixed set of needs,
look at a broader picture of the solution domain you are working in.

There’s an old Bell Labs proverb (cited in [C++]),
that says:


Library design is language design.

That is to say, if you are designing a library of reusable functions
to be called in varying circumstances, what you are really designing
is a small, consistent “language” specific to the problem domain at hand.
With a small library of functions, and a knowledge of the semantics of
calling and combining the functions provided, the programmer can tackle
any number of application-specific tasks that the library writer would
never have been aware of.

This is a fine idea for well-defined, specialized tasks like matrix operations,
statistics, 3D graphics, etc., but how does this idea of a rich function
library translate into the guts of an object oriented application?

A true object oriented program is designed without a “top”
([OOSC2]), that is, without a well-defined single
high level “here’s how the whole thing works”.
What the user
sees as an application program is but one particular entry point that
invokes the objects necessary for the application. This now implies that
what the user perceives as the application could be dramatically altered
by augmenting and combining the available objects in a different way.

So ideally then, what the designer of a project should bear in mind
is the following goal:


Design a domain specific “language” that can be used to
talk about applications in this domain.

Note that applications is plural!

This “language” may take shape in the form of:

  • Services that classes of objects can provide.
  • Interactions between objects to fulfill promised services.
  • Definition of meta-data to describe the data that the system will operate on.

and all the other usual tricks that make up an implementation.

Hasn’t this been said before?

Sort of.

As an aside: nothing really is new;
Plato and Aristotle spoke of classes of objects, taxonomies and such.
The ancient Greeks named the atom long before we had nuclear subs.
Even the Bible described communications using
a binary notation ([MATT])!
Nothing really NEW has been invented for several thousand years,
actually. Improved a great deal, but not quite as new as we’d like to
think.

So how do these ideas relate to the current hot topics and
buzzwords in our industry?

The current rage with the UML focuses a great deal on class
modeling
.
A fine notion, but beware of the fine print. Modeling the actual classes
that will be implemented (via code generation/round trip engineering)
is obviously an implementation level activity. By this time, the horse
is out of the barn and halfway down the road. Conceptually,
what you want to model is this domain-specific “language” space, and
keep that in sync with the users. This may of course have multiple valid
implementations (which kills the notion of reversibility, but that’s
a separate matter). I think this is different from those involved in
domain modeling per se, as we intend to model a sufficiently
rich solution space, not the problem domain itself.

Reusability is one of the more popular buzzwords of the day,
and is a fine goal if you need the code base to span multiple projects,
or across an entire enterprise. But first things first:
usability
must happen before re-usability. Some validation and testing might be a rare
thrill as well. Reusability is a two-edged sword; do not waste time
adding flexibility that isn’t needed, neither limit yourself from adding
such flexibility in the future. It’s a fine line, and quite a tricky
thing to get right. But it can help to NOT think in terms of reusability,
but rather flexibility and expandability to achieve the same goal.

Componentware, Beans, etc.: As usually pitched, this again is
an implementation level thing. But it doesn’t need to stop there. If
you can drag buttons and data-aware controls around, why not drag around
business rules and services, points of workflow, and other higher-order
concepts? The real value of componentware, Java beans, and so on is being
able to use a very high level scripting language (like Perl, JavaScript, etc.)
to combine components to make novel applications without writing
any new component-level code. That’s the idea; we aren’t quite there yet,
but it is more than a few steps in the right direction.

References

[C++]
Stroustrup, Bjarne. “The C++Programming Language”
Addison-Wesley, 1991.

[OOSC2]
Meyer, B. “Object-Oriented Software Construction, Second
Edition”

Prentice Hall, 1997.

[MATT]
King James Bible, Matthew 5:37:
“But let your communication be, Yea, yea; Nay, nay: for whatsoever
is more than these cometh of evil.”