• No results found

T HE PARTIAL - CLASS GENERATOR MODEL

In document Code Generation in action (Page 116-119)

Building simple generators

4.4 T HE PARTIAL - CLASS GENERATOR MODEL

The partial-class generation model is the first of the code generators to build code from an abstract model. The previous generators used executable code (e.g., C, Java, C++, SQL) as input. This is the first generator to use an abstract definition of the code to be created as input. Instead of filtering or replacing code fragments, the partial-class generation model takes a description of the code to be created and builds a full set of implementation code.

The difference between this model and tier generation is that the output of a partial-class generator should be used in conjunction with some derived partial-classes that will aug-ment and override the output. Both the base class and the derived class are required to create the fully functioning production form. Tier generation requires no such derived classes because it takes responsibility for building and maintaining all of the code for the tier.

Partial-class generation is a good starting point for tier generation. The advantage of building only part of a class is that you have the ability to override the logic in the generated classes if your business logic has custom requirements that are not covered by the generator. Then, as you add more functionality to the generator, you can migrate the custom code from the user-derived classes back into the generated classes.

4.4.1 Uses and examples

Here are some common uses for partial-class generation:

• Building data access classes that you can override to add business logic

• Developing basic data marshalling for user interfaces

• Creating RPC layers that can be overridden to alter behavior

Figure 4.18 shows the I/O flow using a definition file as the source of the base class structure information.

Definition File

Partial-Class Generator

Output Base Class Source Code

Compiler

Executable Templates

Derived Class Custom Source Code

Figure 4.18 A partial-class generator using a definition file for input.

Note that the output of the generator relates to the handwritten code.

In a partial-class generation model, your application code should never create instances of the base classes directly—you should always instantiate the derived classes.

This will allow the partial-class generator to transition to a full-tier generator by generating the derived classes directly and removing the original base classes from the project.

Let’s look an example. This partial-class generator is closely related to code munger 6. Both generators are building classes for structured storage based on a defined set of the required fields. The output of the generator is a set of classes based on the contents of a simple text definition file, shown here:

Person:first,middle,last

This small test file specifies one class, Person, which has fields named first, middle, and last. We could have specified more classes by adding extra lines, but just having one class keeps the example simple.

The output class, Person, is shown here:

public class PersonBase { protected String _first;

protected String _middle;

protected String _last;

public PersonBase() {

_first = new String();

_middle = new String();

_last = new String();

}

public String getFirst() { return _first; }

public void setFirst( String value ) { _first = value; } public String getMiddle() { return _middle; }

public void setMiddle( String value ) { _middle = value; } public String getLast() { return _last; }

public void setLast( String value ) { _last = value; } }

THEPARTIAL-CLASSGENERATORMODEL 89 Listing 4.14 shows the code for the generator.

require "erb/erb"

File.open( "fields.txt" ).each_line { |line|

( class_name, field_text ) = line.split( ":" ) fields = field_text.strip.split( "," ) erb = ERb.new( File.open( "field_class.template.java" ).read ) new_code = erb.result( binding ) print "Creating #{class_name}Base.java\n"

File.open( "#{class_name}Base.java", "w" ).write( new_code ) }

q

The split method splits a string into an array on the specified delineator. In this case, we use the : character as a delineator. The two elements of the string are then put into the class_name and field_text variables.

w

After you have the field_text, you want to break it up into an array of fields.

Use the split method again to break up the string, using the comma character as a delineator.

e

Here you create an ERb object with the contents of the text template. Then, invoke the template using the result method. Pass in the variables from the current scope using the binding method.

The t1.rb generator uses one template, field_class.template.java:

public class <%= class_name %>Base {

public String get<%= field.capitalize %>() { return _<%= field %>; } public void set<%= field.capitalize %>( String value ) { _<%= field %> = value; }

<% } %>

}

q

Here you iterate through each field and create a String instance variable for the field.

w

In the constructor, this code replaces the class name and then creates calls to new for each field.

Listing 4.14 Partial-class generator: building structure classes from a CSV file

Creates the new file Splits the fields into an array

w

Reads the class name and fields

q

e

Reads each line of the input file

Runs the ERb template

Creates the get and set methods

e

e

Finally, this code iterates through each field to create get and set routines with the right field name.

4.4.2 Developing the generator

The example process flow shown in figure 4.19 could be used to develop a partial-class generator.

Let’s examine these steps in detail:

• Build the base class test code—First, design and build the base class you want the generator to create.

• Build the derived class test code—Next, build the derived class that will use the base class as a test case. You should also build the definition file that specifies the base class. The generator will take this file as input.

• Design the generator—After building the input, output, and definition files, you need to spend some time creating a simple design for the generator.

• Develop the input parser—Your first implementation step is to develop the parser that will read the definition file and store any elements that are required by the generator.

• Develop the templates from the test code—The next step is to take your original base class code and to turn it into an ERb template for use by the generator.

• Develop the output code builder—The final step is to merge the input parser with the template invocation code and to write the code that will create the out-put files.

In document Code Generation in action (Page 116-119)