
This document used images from MyGeneration version 088b
Philosophy
If the author of this article was running for President of the software
development world his slogan would be “It’s the Data Stupid”. The
requirement process has one purpose and that is to define the data for an
application. To look at a data model is to look at an application where the
user interface exists to let humans modify and use the data contained therein.
It is in this world where “data” reigns supreme that MyGeneration flourishes.
Consider, for instance, all of the valuable and untapped information already
stored in a typical database just waiting to be reused. Tables make great
business objects with each column in the table forming a property of the
business object. Each column in a table has a certain data type such as a char,
varchar, int or a date field. The meta-data in the database can provide
information such as whether a column is required and if there is an index on
it, its length, and much more. In addition to creating business objects why not
use that same meta-data lying around in the database to generate stored
procedures as well? As well as certain types of user interface components?
MyGeneration performs these tasks quite well, and it can also later be used to
regenerate them when the database is modified, again and again.
The Common Enemy
Whether you are a software engineer or a project manager the primary measure of
success for a software project is delivering a defect free, maintainable
application in a timely manner within an allotted budget. And, more
importantly, you should be able to obtain success by repeating that process
over and over again. However, there are many things that can prevent a software
development team from reaching this level of success, including;
-
Lack of a consistent architectural approach across the application code-base
-
An ever changing data model requiring the application code to be reworked to
reflect those changes
-
Discoveries made during development that cause the code to need modification
(non data related)
-
Defects introduced into the application code by software developers
The items listed above, even given a rigorous detailed design phase, are
actually quite common to most software development projects. MyGeneration is
product that directly addresses these common problems and in large part
eliminates them as risk factors, thereby dramatically improving your chances of “delivering
a defect free, maintainable applications in a timely manner within an allotted
budget.” Let’s begin with a quick example to provide us with some
context. A Quick Example
Below is an example of a business object property (get and set accessor). The
language is C# and “currentRow” represents a DataRow in an ADO.NET DataTable.
The code is pretty simple.
public virtual string LastName
{
get
{
return (string)currentRow["LastName"];
}
set
{
currentRow["LastName"] = value;
}
}
Once an architect or a developer determines what his business object properties
will look like, s/he would typically hand code the properties for every column
in every table. This is usually done while staring at a hard copy of the data
model or while staring at a database enterprise tool. This is not only a very
unrewarding task for a developer it is also the exact type of tedious activity
that introduces hard to find copy/paste propagation errors and other not so
easily detected errors. Besides, all of the data necessary to produce the code
above for every property is already stored in the database. Why pay (force)
developers and or contractors to sit around and do such tedious work? Whether
you’re doing fixed bid projects or not it makes since to save this time and
spend it on the more risky aspects of your project.
If we take the property above and replace the portions that would change, from
property to property, with tags this is what it would look like.
public virtual <column-type><column-name>
{
get
{
return (<column-type>)currentRow[ "<column-name>"];
}
set
{
currentRow["<column-name>"] = value;
}
}
Now that we’ve identified what portions we need to replace dynamically from the
meta-data stored in the database we are ready to open MyGeneration and create a
VBScript or JScript template to do just that. We do this by iterating through
the columns of a table and generating all of the properties for us. Below is a
VBScript example that will do just that. We’ve even made our script smart
enough to determine if the property should be read-only by checking the
Column.IsComputed
or
Column.IsAutoKey flags. There is an intrinsic object available
to all scripts named “MyMeta”. MyMeta is an object which acts as the root of
your database meta-data. The script below uses MyMeta to generate properties
for the Employees table of the Northwind database, however, this is done only
for demonstration purposes. This code snippet is taken from one of our sample
scripts that generates a fully functional business object.
<%
Set objTable = MyMeta.Databases.Item(“Northwind”).Tables.Item(“Employees”)
For Each objColumn in objTable.Columns
%>
public virtual <%= objColumn.LanguageType %> <%= objColumn.Name %>
{
get
{
return (<%= objColumn.LanguageType %>)currentRow["<%= objColumn.Name%>"];
}
<% If Not objColumn.IsComputed And Not objColumn.IsAutoKey Then %>
set
{
currentRow["<%= objColumn.Name %>"] = value;
}
<% End If %>
}
<% Next %>
Now, using MyGeneration you can generate all of the properties for all of your
business objects using the meta-data that already exists in your database. When
the database is modified simply regenerate these properties. So, how much time
did we spend doing that? Not much. And we can regenerate it at any time in the
future.
This is but a tiny slice of what MyGeneration can accomplish. However, this
should be enough for the reader to recognize where the places are in their
application that could benefit from MyGeneration. In fact, the author of this
article uses this technique to generate all of the stored procedures and the
entire collection of business objects for his applications.
Default Settings

Upon launching MyGeneration the first thing to do is make a connection to a
database using the above ‘Default Settings’ dialog. Choose the database driver
in the “Driver” combobox and then use the “…” button. This will bring up the
standard Windows ‘Data Link Properties’ dialog. Be sure to check the ‘Allow
Saving Password’ before choosing the OK button. The Language and DbTarget
Mappings will be discussed later in this document. MyGeneration requires an
OLEDB driver to gather the database meta-data. For help with connection strings
see MyGeneration
Online Documentation.
The Database Browser and Properties Windows
Once you successfully connect to your database there are two dockable windows
that work in unison. The “Database Browser” shown below docked on the left will
allow you to walk your database in a tree-like fashion. And the “Database
Browser Properties” window docked on the right will display the individual
properties of the object you have selected in the tree control.

In the above image we have connected to the Northwind database via Microsoft SQL
Server and have selected the LastName column in the Employees
database. And, since we have the properties window open all of the properties
and their values for the LastName column are listed. The
Properties window can be very useful when writing scripts or templates because
the ‘Property’ is the name of the actual property you will access in your
script, for instance, column.IsInPrimaryKey is how you would
determine whether or not a column is part of a tables primary key. The
Properties window is the ultimate source of help concerning database meta-data.
Language and DbTarget Mappings
There are two key properties shown in the above image (Properties) available
specifically for Column objects, ‘LanguageType’ and ‘DbTargetType’. These
properties are available to you in your script or template files and are
determined dynamically at run time. If you refer back to the Default Settings
dialog you can see that C# was chosen as the ‘Language Type’ and SqlClient was
chosen as the ‘DbTarget’. These selections are used to map the columns database
native type, for instance, a varchar, to both the Column.LanguageType
and Column.DbTarget. Look at the image below.

These mappings are completely customizable. For each window the “From”
represents the native database type for your database while the “To” field
determines what it is mapped to. For instance, in the above example in the
Language Mappings window we map the Microsoft SQL Server type ‘bit’ to the
Microsoft .NET language C# type ‘bool’. In the DbTarget Mappings window we map
the same SQL type of ‘bit’ to the SqlClient type ‘SqlDbType.Bit’. In both
windows you can create mappings for new languages or drivers, change existing
mappings, and delete mappings. Recall from above section, ‘A Quick Example’,
the sample template code used the objColumn.LanguageType property when
generating the properties.
User Meta Data and Aliasing
Often times you will come upon a database with poorly named tables, columns,
views or other database entities. This can present itself as a problem if you
want to use that meta-data as part or all of your business object name, or a
poorly named column as the name of a business object property. MyGeneration
addresses this problem by allowing you to override these names in the User Meta
Data. This is referred to as the Alias.

In the above image the LastName column of the Northwind Employees table has been
renamed or aliased from ‘LastName’ to ‘MyLastName’ for demonstration purposes.
But there is more to user meta-data than just providing aliases as we will see
below.

By selecting an individual database entity such as the LastName column in your
Database Browser you can provide your own meta-data by supplying any number of
key/value pairs and then access that data during your scripts. In fact, user
meta-data can be populated programmatically during scripts and then saved for
later access during other script execution. The above image shows two key-value
pairs that have been entered. Also, you can see that LastName has been aliased
to MyLastName.
Column.Name is the physical name as defined in the database
Column.Alias is the either the Alias if one has been
provider, otherwise it defaults to Column.Name
Regenerating Code
What about regenerating code that you have customized? One of the keys to using
a tool such as MyGeneration successfully is ensuring that you can regenerate
code at a later time without overwriting customizations. The good news is that
object oriented programming techniques supply the answer in a terrifically
useful way. Let’s look at an approach that uses object oriented programming
techniques for generating a business object that can be fully customized and
yet regenerated without worrying about losing those customizations.
public abstract class GenEmployee
{
public virtual decimal HourlyRate
{
get
{
return (decimal)currentRow["HourlyRate"];
}
set
{
currentRow["HourlyRate"] = value;
}
}
}
Notice that the GenEmployee class is abstract, this means that you
must derive your own class from it in order to instantiate or create it. Notice
also that the HourlyRate property is ‘virtual’ which indicates
that you can override it later to provide custom behavior. Let’s look at how
both of these task can be done.
public class Employee : GenEmployee
{
public override decimal HourlyRate
{
get
{
return base.HourlyRate;
}
set
{
base.HourlyRate = value;
}
}
}
The above Employee class derives from GenEmployee thus making a concrete class
based on the abstract GenEmployee class. The Employee class also overrides the
HourRate property and provide custom logic. The key here is that the
abstract class GenEmployee is never modified and can be regenerated at any time
without worry because all of the custom logic lives in the Employee class (not
the generated class). Another side benefit of this approach is that only true
business logic will be in your Employee class.
Does MyGeneration Really Solve These Problems?
Does MyGeneration really solve the initial problems as listed in “The Common
Enemy” section? Let’s address them one by one.
Lack of a consistent architectural approach across the application code-base
MyGeneration inherently brings a consistent approach in that a common template
or script (not a developer) is used to generate the software components such as
stored procedures, business objects, and user interface components. A developer
does however create, maintain, and enhance the templates that generate the
code, so you’re still in charge.
An ever changing data model requiring the application code to be reworked to
reflect those changes
MyGeneration specifically addresses this problem because it uses as its main
source of input the database meta-data itself. And when combined with
techniques like those discussed in the “Regenerating Code” section, absorbing
data model changes is mitigated in most cases to a very minor issue (as opposed
to not using MyGeneration).
Discoveries made during development that cause the code to need modification
(non data related)
At any time you can modify your MyGeneration script(s) to include new methods,
properties, collections, change the inheritance pattern, and then simply
regenerate. This is one of the major benefits of MyGeneration that can easily
be overlooked, and since most development is done in an iterative fashion you
can update your templates to reflect new requirements and regenerate.
Defects introduced into the application code by software developers
Finally, MyGeneration takes a “write it once” approach. For example, suppose
there are fifty tables in a database and each requires a business object. You
can use MyGeneration to create a single template and then generate all fifty
business objects in about thirty seconds or a developer can hand code all fifty
business objects. You can imagine all of the errors that would be introduced by
a developer during hour after hour of such tedious, mind numbing grunt-work. On
the flip side, if you discover an error in your MyGeneration template you
simply correct it and regenerate.
Summary
The benefits gained by using MyGeneration are tremendous and such a tool is
often overlooked or misunderstood. Code Generation has also earned a bad
reputation because poorly thought out tools have associated the term code
generation with rigidness and inflexibility. However, MyGeneration has none of
the negative issues associated with code generation because in fact you write
the scripts, samples are provided for educational purposes, but you are free to
adopt any existing templates or write new ones as needed to fit your
architecture. The author has used this approach on several large and small
projects over a period of several years now and it works.
Part II of this series will address scripting in detail.