This document used images from MyGeneration version 088b
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
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>
return (<column-type>)currentRow[ "<column-name>"];
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.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
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.
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.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
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
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
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
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.
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.