Practical Code Generation
From BriansWiki
[edit] Presenter
[edit] Peter Bell, Systems Forge
[edit] Overview
The workshop was structured to give the attendee a survey of code generation techniques followed by some practical applications, primarily by using the open source CFTemplate that was created by the presenter. The second half of the presentation was a more in depth look at software architecture with an eye towards answering the question: "Now that we know how to generate code, what should it look like?"
[edit] Domain Specific Languages
Another overarching theme of the presentation was to encourage the attendee to look at the process of code generation as a case of using a Domain Specific Language to describes the business objectives of the customer. The point was made that the best programmers throughout history have been effective "language interpreters"; people who can understand the needs of a system-to-person interaction and devise a means of communicating from one to the other.
[edit] Types of Code Generation
[edit] Active
Active models maintain the code created by the generator long term. In the best case there is the ability to round-trip any hand edits and include them in future versions.
[edit] Passive
Passive models create the initial code, and then it is the responsibility of the developer to maintain it. A typical example of a passive code generator is a wizard.
[edit] Approaches to Code Generation
[edit] Templates
Easier to code and maintain since it maintains readability.
[edit] Concatenation
This approach is better for applications with lots of variables and where the required code is small compared to the number of variables.
MetaEdit – a concatenation based code generation tool.
[edit] Anatomy of a Code Generator
[edit] Metadata
A representation of the business objects, their properties and methods. Usually text or database table based.
Antler3(sp?) – metadata generation tool (could not find reference)
[edit] Template
The abstract definition of your application, used to generate code when handed the appropriate metadata.
Velocity is an template engine from the Apache group that can be used to produce any code, the drawback is that it is based of XSLT transformations, which is another language to learn, with poor readability.
[edit] Iterator
Applies "for each <object> do <action>" processing to the templates and metadata.
[edit] Filters
There may also be instance where you need to do conditional iteration such as when a module does not need a DAO component.
[edit] Orchestrator
An orchestrator puts the Metadata, Templates and Interators all together to produce the intended code.
[edit] Cold Fusion as a code generator
One way to look at Coldfusion is as a code generator in that it interprets cftags and generates html from them. Using this same engine to generate cfml code itself is really not that different, The presenter put together a Coldfusion based code generator, CFTemplate that does just that.
The trick to the template is to escape the tag angle brackets just like you would a pound sign in a sql query, by repeating it, like this :">>". For variables, the "#" is replaced with "%" (which are doubled when you need to refer to a real percent symbol. All of this makes for a highly readable template.
[edit] Extending Generated Code
Almost all generated code is going to need to be extended in some manner, here are a number of different ways to accomplish that:
[edit] Protected Blocks
The classic "Don’t touch this code" approach – very brittle – generally not a good idea.
[edit] Inheritance
This is the preferred approach; it allows for flexible extension and can handle the vast majority of cases.
[edit] Events
This approach works by inserting pre and post processing events in your generated code to allow for additional processing or the over-riding of the results of a function.
[edit] Mixins
I got this definition from code dojo:
"A mixin is an interface with implemented methods. When a class includes a mixin, the class implements the interface and includes, not inherits, all the mixin’s attributes and methods. They become part of the class during compilation. Interestingly enough mixins don’t need to implement an interface. The advantage of implementing an interface is obvious so that the class may be passed to methods requiring that interface."
Got it? Well if you do please explain it to me because I still don’t know what this means!
[edit] AOP
Apparently, "Agile Orientated Programming" allows intercepting function calls by using regular expression matching. I am not sure how this works either but it sure sounds cool.
[edit] Summary
According to Peter, you should be able to accomplish everything you need with inheritance, but there are the last 3 approaches to try if this isn’t working for some reason.
[edit] Framework vs. Code Generator
This is not an either/or design decision; practically speaking, there are reasons for both. There are times when you don’t want to expose your framework or there may be proprietary code that you can’t distribute.
There are also performance considerations; most Frameworks will introduce a performance penalty, so a leaner, all-generated site will be faster, but the trade off is that you loose the flexibility of a framework with its multiple layers of abstraction.
[edit] Sources of Meta Data
It really doesn’t matter where the metadata resides, it could be in an XML file, database or delimited text file. The real trick is where does the information come from; you can get started by looking at the dependent database tables, but this is putting the cart before the horse, Object-Design wise. Your business objects should really drive your database design, not the other way around.
Al that being said, you can use a utility called DBX to get table and field definitions, and then refine them with your object model.
You can also generate CFC’s from the Illudium cfc generator, but this is only going to create standalone components. There are also Transfer, Reactor and SQL Alchemy.
The bottom line is that you need a good way to describe your problem domain and your business logic before you can even begin creating templates. Which brings us to the next major section:
[edit] Design Patterns
The most common design pattern in the Model, View, Controller (MVC) pattern.
[edit] Model
This is where the business logic and the major objects are defined
[edit] View
The presentation layer – Forms
[edit] Controller
Handles events and routes them to the model or the view as appropriate.
[edit] Model
[edit] Beans
The Model can be composed of "beans", or "value objects", all classes by other names that represent the core business objects. For instance, the user for a system would be represented by a "user.cfc". This object is responsible for holding all the properties of the user and controlling the access and value of these properties. This is generally controlled through "getters" and "setters". This allows validation and formatting of values as they are either submitted or exposed.
[edit] Service
Access to the user object can be abstracted through a service layer "userService.cfc" that can expose the following common methods:
- getBy Filter (
- getByProperty (getUserByID)
- deleteByProperty (deleteUserByID)
- deleteByFilter
- save (add or update depending on state)
- new
Of course there may be many other custom access methods, or you might not need all of these, the point is, it generally should tell a client what types of actions can be performed on a user object; this is often called an "API".
[edit] Data Access Object
This is the object that implements the Create, Read, Update and Delete methods for the bean. It is primarily used for returning the data associated with a single bean. In the architecture described below, the DAO object creates the bean and hands it back to the Service.
[edit] Gateway
This is functionally similar to a Service, but is geared more to returning a collection of records (or beans depending on how strict your object metaphor is) but is not as abstract as the Service which tends to be the most public interface an object exposes. Here is how all these object interact:
[edit] Iterating Business Object
Instead of the the Gateway object, you could use an Iterating Business Object, or IBO. This is more useful in a strict object orientated approach when everything is an object. In this case the IBO returns a collection of beans rather than a recordset. Gateways are simpler than an IBO and are better for read-only data where there are no custom getters or setters.
Keep in mind that while a gateway may be simpler, your design will need to be refactored if you ever have to add the ability to modify this data. For more info on IBOs, checkout Pete’s site here: http://www.pbell.com/index.cfm/IBO
[edit] Object Factories
This MVC approach can be made more abstract by the use of an "Object Factory" the most popular of which is the Spring framework, the Coldfusion version is know as ColdSpring. Peter developed a lighter weight version that he calls LiteWire,
[edit] Why write code at all?
If you successfully create a micro architecture that allows you to use parameters to define all your created objects and you create enough base business objects to cover all your use-cases, then it is conceivable that you would only have to write code to cover a deficiency in your design, or when the time to extend your base classes is not worth the effort, like when you are handling use-case exceptions.
[edit] Domain Specific Languages
A Domain Specific Language is not a design but a way of consuming MetaData to accomplish the business Objective. Here’s what Wikipedia has to say:
"A Domain Specific Language is a programming language designed for, and intended to be useful for, a specific kind of task. This is in contrast to a general-purpose programming language, such as C."
There are two major categories of DSL’s:
[edit] In-Language
DSL’s can be "in-language" where they use the application's own language (like the way CFTemplate uses ColdFusion). The simplest example of an in-language DSL is when you store data in a delimited string in a text field. The application has to create code that can translate these values into the appropriate business logic (it is generally not a good idea, but you get the idea). In-Language DSL’s allow you to use all the power of a programming language, but they are not accessible to non-technical people, for instance; if the delimited string parsing logic needs to change, only a programmer can access it.
[edit] External
DSL’s can also use an external language like XSLT and to accomplish a given task. A front end can be created to simplify the use of External DSL’s so that they can be user-configured to some extent. In general, External DSL’s are also better at moving from platform to platform.
In this class, the DSL was crucial in the processing of MetaData, either to generate code or to populate a Framework dynamically. A successful project can be described as getting the customer/client to describe their requirements in a DSL as quickly as possible, possibly with them even doing a portion of the data entry.
[edit] Life Cycle Solutions
Peter described the following phases of a software project:
- Quote
- Specify
- Generate
- Manage
- Deploy
- Optimize
[edit] Quoting
Quoting is one of the most difficult business tasks for a developer; even if the customer is an internal one, you will be expected to give them a time estimate which is analogous to a quote (since Time = Money). There are several way to go about quoting:
- Charge per Feature (and then configure for free)
- Charge a discovery fee (lets you develop requirements without risk)
- Charge per Object
[edit] Specify
- Features and Configurators
- Requirements (ideally, outputs from requirements should equal inputs to the generation system)
- Agile Fixed Price (you work with the customer to deliver as many requirements as possible within the given time and money constraints)
- Configuration
[edit] Generate
- Layered SPL iterative approach (Software Product Line - see below)
- Choose Feature Model
- Configure (decision Support)
- Customize (DSL)
- Extend (add custom code)
[edit] Software Product Line
An SPL can be defined as "a collection of applications that do similar things" (like Trackers or Reporting apps). The goal of an SPL is to allow you to create new apps by just tweaking configuration files that set properties, options and custom data types (the trickiest part).
[edit] Tables for Data Definitions:
Pete has recently switched to using XML for data definitions since this allows you to validate your data against a schema to ensure that you have all the required data and that you are using the appropriate values. The major categories of data are:
- Objects
- Properties
- Value Lists
- Custom Properties
- Data Types
[edit] Intent Driven Design
I was glad to see Peter mentioned this, since this is the way I have alway approached application development. To create an application, you need to provide the following information:
- Business Intent
- Roles and Objectives
- Essential Tasks
- Interfaces and Actions (story-board or mockup)
- Inter-Object model (high-level object model)
Do not include Non-Functional Specs, this means you shouldn’t promise things that you can’t control or understand. For instance do not specify a service level agreement that is tied to specific performance metrics (like page or report processing time etc…)
Links (need clarification):
- Open Architecture Ware for modeling and generating XML
- C-Code alchemy (?)
- DSL Refactoring (?)
- API Refactoring (?)
