Code Generation for Fun and Profit
I am an unapologetic code generator. Best is that generated at compile time (or before), but runtime will do in a pinch for languages that allow it. (Here's a good article on code generation focused on Java.)
Here's an example of how much fun I have with this. Each one of our domain objects is represented by an INI file. (Don't laugh! I think INI files are the perfect balance between editing ease and expressiveness, plus they force you to keep your configuration fairly simple, avoiding the inevitable complications as you pile more smarts in there.)
Anyway, in that INI file we define the basics (name of the object, name of the table), some relationships and some queries. Some queries involve relationships.
So here's a (cleaned-up and simplified) snippet from one of them:
[bean]
bean = Customer
table = Customer
[relate Order]
type = many
field_map = custCustno >> ordrCustno
[query lastName]
return = self
where = {custLast} LIKE ?
param_type = String
param_name = lastName
order = {custLast}, {custFirst}
[query activeOrders]
return = Order
relate = Order
where = {ordrStatus} = 'A'
order = {ordrOrderDate} DESC
This will create the main object, any data transfer objects, session facades, interfaces and delegates. It will also methods like fetchByLastName() in the facade (returning multiple Customer objects in a List) as well as object methods like getOrders() (from the 'relate' entry) and getActiveOrders() (from the 'query activeOrders' entry), each of which will return a List of Order objects.
In the 'query' entry We don't need to tell the system how to relate a Customer to an Order since it already knows. You can extend this as deep as you like, such as this:
[query activeOrderLineItems]
return = OrderLineItem
relate = Order
relate = OrderLineItem
where = {ordrStatus} = 'A'
order = {orliAmount}
Even though the Customer isn't directly related to an OrderLineItem, it is related to an Order which is related to a OrderLineItem. Cool!
How is it implemented? Who cares? Seriously, the point is that you've now decoupled these. The code generator guru can tweak that all she likes while the business logic or the front-end folks can develop to the interface.
One of the useful things about this: you can easily keep your queries in one place. If they're too complicated to represent in configuration, it gets put in code. But complicated stuff is more fun to write as opposed to this sort of drudgery.
But the main thing is that this opens up all sorts of possibilities for automation. For instance, I've been working on a testing framework that uses a fast object database (currently db4o as I mentioned here and here) as opposed to a live database. Since most of our business processes are coded as POJOs we can test them outside the container, and we don't have any nightmare database syncronization issues replete with referential integrity issues.
Code generation to the rescue. Coding to the same interfaces as already generated, there is a parallel tree of objects that will read and write to the db4o database rather than the actual database. And since the queries and relationships are in the configuration, we can take that same information to implement it in a different fashion -- in this case, using a Query object that matches against all objects in the database, since there won't be very many.
So: We can use normal unit testing tools! We can run on alternative operating systems that might not support a particular database! We don't have to be database administrators!
And finally, one of the best things about code generation: you can do it in any language! This may lead to maintainability problems if you're a 100% pure language X shop, but it also allows you to use the tool best suited to the job. (In this case: Perl, of course!)
(I also wrote briefly about this a little while ago in a TSS thread.)
Sure, but you have to have some understanding also. (#11942)







