Code generation is extremely important to me and thus an integral part of IOTK. As a single developer on a number of products operating in a start up environment, I need to focus my attention on the real challenges of a particular product. Nowadays I find myself spending a lot more time focused on the UI and page integration since I’ve standardized most of how I write my back end code.
I’ve standardized it so much that the IOTK Code Generator can write (by way of rough estimation) half of the code that I would normally do by hand. This gives me the freedom to focus on what’s different or special about a particular product over having to first recreate the basics of what appears in nearly all of the products I have built to date.
In order to accomplish this I had to make the Code Generator entirely active – the code that it produces can be recreated any time (and is with each build of the product), can be generated from both metadata and the Oracle data dictionary, and can be passively extended (using object orientation) so that the generated code is never directly modified.
In the last few hours I’ve read a number of articles discussing the differences between active and passive code generation. I didn’t come across a single article or posting that pointed out really good reasons to build a passive system and, in a small number of cases, the authors were arguing that any code generation at all was a negative. I certainly don’t agree with that but I do agree that a passive code generator is a deficiency.
Essentially the difference between active and passive code generation is that passively generated code is modified by the programmer and thus can never be re-generated. Actively generated code, on the other hand, is never modified by a programmer and can be recreated at will with no impacts to any part of the system that relies on it. My programmer brain says that determining which to build or use is a pretty straightforward decision – giving a framework and a computer the ability to maintain vast amounts of code over the life of a product is a huge benefit. That hasn’t always been the case and for many years I was writing systems that generated “stubs” and large amounts of passively generated code. I took a different course in IOTK and I don’t regret it so I’ve walked away with 2 conclusions:
- Absolutely use a code generator! Let your computer and framework help you enforce its standards by writing as much of your code for you as possible. More importantly, since we’ll spend more time maintaining a system than building it, let your computer maintain as much of the code as possible as well.
- If you want to move fast and have a high quality, consistent product, don’t use passive code generation.
The “base” level entities (classes, functions, PL/SQL packages, unit tests, etc.) are what the Code Generator will create in IOTK. Where a programmer would need to extend the functionality of one these entities, a class is used so the base class can literally be extended. For example, IOTK will create a base level ut_Data_Mapper for the tables you request. One such ut_Data_Mapper might be called ex_Base_Employee. Perhaps you want to create a function that looks up and loads the ut_Data_Mapper by social security number. You would create the following:
//
// +-------------+
// | ex_Employee |
// +-------------+
//
class ex_Employee
extends ex_Base_Employee
{
static function make()
{
return new self();
}
// +----------------+
// | Public Methods |
// +----------------+
final public function lookup_by_social_security_num($ssn)
{
$this->import(ut_Record_Set::make(
__METHOD__,
"select " . $this->get_select_cols() . "
from ex_employee
where social_security_num = :ssn")
->bind(":ssn", $ssn)
->fetch_row_hash()
->one());
return $this;
}
}
In this case I’m adding something to the base level object to accomplish my requirement. I find, though, that often I’m removing things from what the Code Generator has created. In essence it is providing the rule and I’m coding the exceptions – IOTK might create an ut_Data_Mapper object with all 8 columns of a table but my form only requires 4 so I will write code to remove the 4 that aren’t used.
ex_Base_Employee is 70 lines of code (not including the unit tests generated for it, amounting to hundreds of lines of code) and it sits on top of the ut_Data_Mapper class which is hundred or thousands of lines of code. For the entire system to work as I need it to, my effort was 32 lines of code (I’m including blank lines, comments, etc.). Writing 32 lines of code and having the system manage hundreds to thousands clearly illustrates the benefit of the Code Generator.