4.6 Generating Code
As you've probably noticed,
many Java frameworks require a whole lot
of tedious, redundant syntax. In his book
Refactoring (Addison-Wesley), Martin Fowler
calls such a design a "code smell."
Since Java developers are a lazy and creative lot, they seek ways to
automatically generate repeated bits of code. Further, they think of
ingenious ways to configure their code generation engines. Take an
EJB application, for example. In order to create the persistent model
with a remote interface, you'll need to create at
least seven files: the home object for lifecycle support, a local
that serves as a proxy, the interface, implementation, primary key,
deployment descriptor, and schema. With code generation tools like
XDoclet, you can automatically generate at least five of the seven,
and often six of the seven. You create an XDoclet by instrumenting
your code with simple JavaDoc comments. While this technique
doesn't make your code completely transparent with
respect to persistence, it certainly makes it more
4.6.1 How Code Generation Works
While novice and
Java developers see code generation as black magic,
it's really quite simple. If you've
ever used a mail merge program, you know how it works. You create a
working piece of code. Then you mark the areas of the code that vary
from instance to instance. Together, these form your template. Next,
you provide data to fill in the variables. Like a mail merger, the
code generator takes your template, fills in the blanks, and
generates working code, as in Figure 4-7.
Figure 4-7. Code generation works by combining a template with data
simplifies the problem in several ways. You can generate multiple
targets. You can also generate code with complex structures, such as
repeated or conditional blocks. In general, if you can describe the
patterns in your code and clearly define areas of duplication, you
can probably find or build something to generate it. There are
several types of generation strategies:Wizards
Many an IDE uses wizards to provide data for code generation
templates. Microsoft Studio is famous for these, but others use
wizards prolifically as well.
Some generators, like XDoclet, parse source code to understand what
to generate. The generator may parse the Java application and look
for specialized commands in comments or certain naming conventions.
It may also use reflection to determine generation requirements.
Some code generators work with a general-purpose template engine and
let you generate targets from a variety of prepackaged templates.
Perhaps the most popular is Apache's Velocity.
Alternative model transformations
If you're starting with a non-Java model (most
commonly, XML), you can simply use XML's
transformation stylesheets (XSLT) to generate your targets, or do a
transformation in other ways.
The MiddleGen open source project combines approaches, using
Velocity, XDoclet, Ant, and JDBC to build a database-driven template
approach to generate code for EJB, Struts, and a variety of others.
As you can see, code generation lets you minimize redundant data
through a variety of approaches. The end result is a happier
developer who's not a slave to tedious details.
4.6.2 Code Generation and Transparency
You can use code generation for
much more than saving duplication. From a
configuration file containing classes with properties and their
types, you can generate a database schema, a transparent model, and a
DAO layer. It's an interesting way to code, with
several tangible benefits:You can have a completely transparent model.If you generate your services, your developers will not need to
modify them to support your model.If your requirements of generated services change, you can change a
template in one place and generate them all again.You can create a generalized domain language for your problem domain
without writing a compiler for it. (You can solve problems in a
specialized template language that generates Java, whose compiler you
then take advantage of.)
Whenever you read a list of benefits like this one, keep in mind that
there's always a big
"but." Generated code does have its
downside:When it's used to solve duplication in an
application, code generation treats the symptom (retyping tedious
redundant code) and not the cause (too much duplication). As such, it
can remove your motivation for refactoring problem areas.When it's used with code instrumentation (such as
XDoclet), it can couple your configuration with your code. You may be
combining concerns that should logically be separated, such as your
code and your schema designs.Code generators often create seriously ugly code. Even if you
don't have to write it or maintain it, ugly code is
hard to debug and understand. For example, a wizard may not know
whether a class has been loaded or not, so it's much
more likely to generate code that looks like this:
cls = Class.classForName("java.lang.String");than code that looks like this:
str = c.newInstance( );
String str = new String( );Developers may change generated code, even outside of protected
areas. As a result, changes to the template will not make it into
Code generation is just one of the tools in your tool box and with
each application, you should look at it with fresh skepticism. In
particular, observe these rules:If you can't read it, don't use it.
A wizard may seem to help at first, but it'll spin
out of control quickly if you don't understand every
line that it generates. You want to know that the code will perform
and that you can maintain it when the time comes.Try to refactor duplication before addressing it with code
generation. In other words, put away that sledgehammer, and grab a
flyswatter instead.Change the templates instead of the generated code. If you must
change generated code, make sure that you've got a
protected area to do so, and that you stay within it. To enforce this
rule, don't check in generated code. Build it from
scratch each time.Use respected templates and products. Treat generated code with the
same skepticism that you reserve for human-written code.
As with the other techniques mentioned here, many readers of this
book will never build a code generator. You don't
have to. Instead, you can choose from a number of frameworks or
products that enable code generation or use it under the covers.
While code generation does not always provide transparency by itself,
it can relieve you of many of the details when
you're forced to use a framework that lacks