Domain Engineering
Domain Engineering is a process for creating
a family of programs so that programs in the family
can be created efficiently.
Most often the motivation for doing domain engineering
is to achieve a significant increase
in software productivity within the chosen domain.
Domain engineering is the fundamental process that
has been used to create application generators (or
program generators),
tools for creating user interfaces, database systems,
application frameworks, and wizards of all kinds.
Each such successful program family typically results
in productivity increases on the order of 10 to 100 times.
Domain Engineering is often divided into two parts:
- Domain Analysis: a process for determining the terminology,
boundaries, commonalities and variabilities of a domain.
- Domain Implementation: the creation of a process and tools
for efficiently generating a customized program in the domain.
In the remainder of this page, I provide a short
description of some of the key concepts and
principles of domain engineering.
Decisions
Any development process is a series of decisions.
Decisions are made during requirements, software architecture,
interface development, software design (algorithms, data structures,
data representation), software coding and testing, and application use.
According to Fred Brooks, the hard thing about software is
making the decisions, not coding them.
The hard thing about domain engineering is figuring out
what the important decisions are and who and when
they should be made.
In the domain engineering process we distinguish between
different times, in particular we note the following major
times:
- Domain Engineering time: domain engineers make decisions about
a family of programs within some domain
- Application Development time: application developers make decisions for a
particular application
- Application Use: the end user makes decisions about a particular
use of the application
Commonalities
A commonality is a decision during domain engineering.
It represents something that is common across all programs
in the family of programs.
Because commonalities represent the common parts of such
programs, they represent the potential savings of this approach.
The set of commonalities represent the portion of
the software that will be reused in each member of the program family.
However, at the same time, commonalities also represent the
limitations or boundaries of the program family because
they represent the set of assumptions that must be made
by each application created in the program family.
Variabilities
Variabilities are decisions that are explicitly deferred
during domain engineering time to either application
development or application use.
Variabilities represent the extent that individual members
of the program family vary from each other.
Tradeoffs between Commonalities and Variabilities
The hard thing about domain engineering is deciding who and when
a decision should be made.
Which decisions should become commonalities?
Which decisions should be variabilities?
A commonality represents increased productivity at
the possible expense of a smaller program family.
A certain balance between commonalities and variabilities
is usually found. A situation in which almost
everything is a commonality typically results in
a small program family and is almost equivalent to
a single application.
The opposite situation in which there are virtually
no commonalities results in very little software reuse
and consequently is also little different from building
applications one at a time.
Another way of thinking about whether to make
a decision a commonality or a variability is to ask
whether
the decision should be standardized or
parameterized.
Standardizing creates commonalities.
In many efforts standards are often used to effectively
and easily create program families.
Standardization processes are examples of
domain engineering.
Standization may be an external or internal process.
Internationally recognized standards are often used
in combination with an organization's internal standardization
process.
For example, an organization may decide to adopt the XML standard
in combination with standardizing on a platform independent
internal standard to create an XML tool set based on Java.
Domain engineering is typically an iterative process
that will typically change commonalities and variabilities
over time.
Some commonalities may become variabilities when it is
discovered that the program family is too small.
Alternatively, a variability may evolve to a commonality
(for example as a result of an organization's standardization
process).
Separation of Concerns
Once the domain analysis is performed, the next major step
is domain implementation.
After domain analysis is completed we know what decisions must be made by whom
and at what time, but we don't yet know how we are going
to let this happen without a lot of chaos.
Without domain engineering techniques, software systems are
often produced that mixes all these decisions together making
it difficult for people to make decisions independently of others.
Separation of concerns is a concept that structures
systems so that decisions can be made independently of each other.
There are many techniques for doing this and good software
engineers have been doing these things for a long time.
A classic example is the separation of machine dependent code
from the machine independent code. For example, in C, one
often finds separate files that deal with all the machine
dependencies. This makes it much easier to port
the application to a new platform.
Although domain engineering might be a new term to many people,
its basic concepts have long been embodied in good
software engineering practices.
Parameterization of
programs, functions, and objects,
putting build-time attributes in header files,
and replacing mystery constants with named constants are
examples that lend themselves to a "poor man's" approach
to domain implementation.
Software architecture is intimately linked to domain
engineering, particularly in the area of abstractions
and application frameworks.
A more sophisticated technique are program generators.
These tools separate what you want from how
you do it. Program generators typically accept a specification
that represents the set variabilities -- the set of decisions
made by an application developer, and the program generator
combines these decisions with the set of commonalities to
create a customzied program.
Specification-Driven Tools and Program Generators
Tools and techniques for creating program generators, application
generators, and other specification-driven tools typically
begin with a specification.
A specification is an expression of the information
for a particular program in a program family.
Typically a specification is written in some textual language
and program generators (or other
similar tools) are used to read the specification and generate a
program and perhaps other related outputs such as documentation
and test cases.
Such tools are difficult to build from scratch.
Fortunately, there are a variety of tools that can
be used to efficiently build such systems.
MetaTool is one such tool
that I created while at Bell Labs that has been widely used
for building a wide variety of program generators.
MetaTool can be licensed from Harmony
Software.
The design of a textual language requires both technical
skill and knowledge about arcane parsing techniques as well
as an art where the feel of the language is easily understood
and used by its users.
I began designing languages since my undergraduate days at UCLA
and have literally designed hundreds of languages, from full blown
programming languages to small languages for narrow domains.
Non-textual Specifications
A specification does not have to be expressed in a textual language.
Finite state diagrams, entity-relationship diagrams, wysiwyg tools,
and many diagrams and graphics are often a superior way of visualizing
and editing a specification. Diagrams combined
with property sheets (as used in most popular visual programming
tools) is an excellent alternative to textual languages.
Other alternatives include the use of databases to store
specifications as relations or the use of XML to represent
specifications as an information structure.
System Modeling
One of the more powerful techniques of a domain engineering
approach is to use the set of tools to create a system modeling
environment.
This means supplementing the program generator with other features
to allow the complete or partial simulation of the system.
This simulation could be used to see the system behavior
and performance.
This permits a rapid iterative development of a system.