Bug Prevention with Code Generation: A J2EE Case Study
Pages: 1, 2
Bug Analysis: "They're Not Poisonous."
departuretime, followed by
arrivaltime. The fetched values get assigned to the volatile strings
departureTime in the wrong order. And this is the first bug. Then these strings are passed on to the
Transportation constructor as
departureTime, but the constructor expects
arrivalTime. This is the second bug. Of course, as they are both strings, the compiler can't detect the error. Later on in the code, exactly the same bugs are replicated. That makes four bugs. But the application behaves wonderfully. How can it be?
Wait. Sure. I got it. One bug neutralizes the other. The departure time from the DB gets assigned to
arrivalTime, but then
arrivalTime is passed as a parameter where
departureTime is expected. So the constructor receives the fetched departure time where it expects it, and the application works fine.
Figure 3 shows the two method execution flows. Seen from the outside, the two flows appear identical. Inside, things are different:
Figure 3. Hidden bugs contribute to method execution
Hand-Coding J2EE Applications Is Hard. Even Where the Sun Shines.
The sample code for the DAO code generator comes from the best possible J2EE 1.4 source. It is part of the J2EE 1.4 Developer Release published by Sun Microsystems on java.sun.com on November 24, 2003. The DAO samples are taken from the new blueprint application called "Java[tm] Adventure Builder Demo 1.0 Early Access 4" (JABD). More specifically, the source file containing the dormant bugs is PointbaseCatalogDAO.java.
The purpose of the new DAO code generator is to enable automatic generation of all Java files from the JABD application that contain database access statements. The rationale for this is that the code in these files is conceptually simple, although structurally complex. In other words, mapping database data to Java properties and vice versa is not rocket science, but it does require constant attention, due to the number of software layers involved. In many cases, the code scans the list of database columns or the list of class properties, and applies some very simple micropattern of code to each item in those lists.
There are two ways to provide this constant attention on repetitive code fragments: one way is to have J2EE developers focus on these tedious details and write that code by hand. As this case study demonstrates, it is difficult to avoid bugs when hand-writing this type of code, although good testing can verify the proper behavior of the application. The other way is to have powerful and flexible automatic tools to build the plumbing parts of J2EE applications, and free developers to perform more challenging development tasks. There are plenty of challenging tasks when developing J2EE applications. The help provided by these tools becomes particularly relevant when you extend, restructure, or maintain your applications; for instance, when you add a new property to your class model. Then you have to add that property in a number of code spots. Modern code generation tools can reliably do that job in seconds.
The JABD application is a comparatively simple application, at least from a size perspective. It clearly demonstrates and documents how to use J2EE 1.4 technologies. In particular, it contains three Pointabase*DAO.java files. The DAO code generator currently produces 95% of this Java code (including comments and blank lines) starting from a concise declarative textual input. The remaining 5% is one business method with real logic that the code generator cannot invent. That code must be written by hand, and the DAO code generator provides the means to insulate and preserve hand-written code across successive re-generation runs.
Where Can I Get that J2EE Generator?
The prototype DAO code generator that helped discover the bugs is the first in a set of J2EE generators modeled on the JABD application. Somusar's approach with respect to code generation is to derive each new generator from existing code samples, and reproduce those samples with the new code generator starting from a concise declarative description of the desired code. Users of the code generator can then provide their specific concise input and have the generator produce and re-produce that particular type of code for their new software entities. This is true not only for Java code, but for any type of code that provides a significant degree of redundancy, and for documentation, as well.
As an example, a multi-tier code generator can produce SQL
create table scripts, XML metadata descriptors, JSP files, multi-class Java implementations of application components, HTML documentation, and more. In particular, Somusar's code generators for large applications can produce all of these files for each software entity starting from one compact multi-tier entity description file. If your application model contains more than 15 or 20 entities, you might want to do the math and consider how many files you could generate for your J2EE implementation of that model.
The JADB application provides a complete set of samples, so expect a number of J2EE code generators to be announced in the near future. In a way, you can think of these specialized code generators as if they were passionate plumbing code writers, or maniacal web designers or pedantic technical writers. They love repetitive work.
To view the code generated by the DAO generator prototype and to try that generator on your computer please refer to Code Generation Somusar Style, (Chapter 3, "J2EE Generators"). By the way, while you are there, you can also view the POJO and database schema SQL files produced automatically by corresponding generators.
This article discussed how repetitive work can lead to sneaky coding errors, even in the best J2EE lab in the world. This is true for a carefully hand-written sample application, and is far more true for real-world large applications. Smart code generators can help avoid those coding errors, and greatly increase development teams' productivity by automating repetitive work and thus freeing valuable developers' time for more complex tasks.
The larger the application where you apply these code generators, the higher the amount of benefit and relief that you can derive from them. Think of a J2EE application with a few hundred entities; let's say 300 entities, with an average of five properties per entity, an average of four Java classes per entity, plus one database table, and maybe three user-interface dialogs. Do the math: 300 * (4 + 1 + 3) * 5 = 12,000 code fragments that manipulate those data items. Actually, many more than that, as each class will manipulate them more than once. In most cases, those fragments will move data across application tiers. That's roughly comparable to drilling holes when you build a house. If your task consisted of drilling 12,000 holes, would you prefer a manual drill, or would you rather use its automated equivalent?
Francesco Aliverti-Piuri has more than 20 years of varied software experience on several platforms, technologies, and architectures.
Return to ONJava.com.