DekGenius.com
Previous Section  < Day Day Up >  Next Section

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 transparent.

4.6.1 How Code Generation Works

While novice and intermediate 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
figs/bflJ_0407.gif


Figure 4-7 shows the general concept, although it 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.


Code inspection

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.


Template engines

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.


Combined approaches

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");
    str = c.newInstance( );

  • than code that looks like this:

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 production code.

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 transparency.

    Previous Section  < Day Day Up >  Next Section