Saturday, December 20, 2008

Doing builds and running unit tests after every check-in has become a standard practice in Agile and non-Agile development teams.  Continuous Integration is the term that describes this process and helps ensure that that nothing has been broken since the last check-in.    One area that is sometimes overlooked is the code generation.    Continuous Generation, the re-generating of code / stored procedures for every check-in and build, should be considered for your TFS builds.  I believe there is a lot of benefit to generating the code with every build.  There are several benefits:

  • Table schema and stored procedure parameters can change.  How do you know that your generated objects are up to date and match the database?
  • It keeps everyone honest so they don’t break the golden rule of never editing generated code.  If the build is going to re-generate the code there’s no way to sneak the semicolon or curly bracket that you manually fix each time after generation.
  • Sometimes we generate just the class we are working on and keep the rest checked in so it doesn’t overwrite the current object.  If any changes are made to the template only this new class will have them.  The other classes will be based on the older version.
  • It gives more credibility to the generation process.  There is sometimes a feeling of nervousness when generating all of the objects.  Since generated code is never edited, you can generate the code as often as you wish.

CodeSmith Tools is the code generation tool that we use.  It offers an easy way to accomplish this from your Team Foundation Builds.   With version 3.2 and newer there is a custom build task included with the Professional edition.  Here is the online help with some information about it.

There are a couple things to consider.  The generated classes will be checked-in to source control.  You will need to check them out before you call the task and then check them back in afterwards. Also, the user guide instructions do not work quite right in the link above.  The guide explains how to use it within your visual studio project.  However, the task needs to be called from Team Build.  Here’s the basic steps and changes for your CI tfsbuild.proj file.

Step 1: Install CodeSmith Professional on your TFS build server.  This will install the MSBuild task and Targets file.   I contacted CodeSmith Tool’s sales department and this does require an additional license for the server.

Step 2: Import the CodeSmith Targets file.  Add the following line just below the import element below the <!-- Do not edit this --> comment.

<Import Project="$(MSBuildExtensionsPath)\CodeSmith\CodeSmith.targets" />

Step 3:  Add TF property in the PropertyGroup element specifying the tf.exe location to be used throughout the process.

<PropertyGroup>
  <
TF>&quot;$(TeamBuildRefPath)\..\tf.exe&quot;</TF>
</
PropertyGroup>

Step 4:  Override the AfterGet target to check out the generated file(s).  This must be called before the CodeSmith task or it will return an access denied error.  This example demonstrates one file but you can use a subfolder or naming prefix for the generated files and recursively check out all of the necessary files.

<Target Name="AfterGet">

    <Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild\"

          Command="$(TF) checkout Measure.cs"  />

Step 5:  Call the CodeSmith task to execute the CodeSmith project(s) in your solution.  This will also be called in the AfterGet target.  Currently the example in the documentation incorrectly shows the CodeSmith task using the ProjectFile attribute.  As the usage description shows, the attribute is actually ProjectFiles. 

<CodeSmith ProjectFiles="$(SolutionRoot)\Main\TestCodeSmithMSBuild\Test.csp"  />

Step 6:  Override the AfterCompile target to check in the updated generated files.  Fortunately TFS will only check in the file if there is a change.  This is good because most of the time re-generating the code should generate the same thing each time.  However, tf.exe returns a code of 1 instead of 0 and results in a partial success of the build.  Use the IgnoreExitCode=”true” to ignore this.  You could additionally update this to create a work item for any other return code.  Here’s a post with a good example of this.

<Target Name="AfterCompile" Condition="'$(IsDesktopBuild)'!='true'">

    <Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild"

          IgnoreExitCode="true"

          Command="$(TF) checkin /comment:&quot;***NO_CI***Auto-Generate&quot; /noprompt /override:&quot;Auto Generate&quot; measure.cs "/>

  </Target>

Step 7:  Undo the check out if the build fails by overriding the BeforeOnBuildBreak.

<Target Name="BeforeOnBuildBreak" Condition="'$(IsDesktopBuild)'!='true'">

    <Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild"

          Command="$(TF) undo /noprompt measure.cs"/>

  </Target>

That is it.  Enjoy!

Mike

Saturday, December 20, 2008 10:49:44 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Wednesday, April 23, 2008

CodeSmith Tools has just published a case study on my work, Farm Credit Services of America.  It talks about how code generation is helping all of our teams.  The cool part is that they quoted me in it.  Check it out and see my 15 bytes of fame :)

http://www.codesmithtools.com/lib/casestudies/Farm-Credit-Services-Of-America.pdf

Code Smart Not Hard

Mike

Wednesday, April 23, 2008 8:50:56 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Saturday, July 28, 2007

I presented at our local .NET users group in February on Subsonic.  Here's the slides and a demo project I showed to the users.  It went really good.  Everyone asked a lot of good questions and seem interested.  I'm just finishing up another web project using it.  I know I saved about 25% of time because I didn't have to right all of the redundant DAL code.  Cool stuff!

SubsonicPresentation.zip (406.66 KB)

Also check out the new Subsonic Website

http://subsonicproject.com/

Mike

CodeSmartNotHard

Saturday, July 28, 2007 5:57:48 AM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Saturday, July 21, 2007

Our business problem:  We have properties that are required only when the status code is particular statuses.  This caused us to look at how to dynamically add/remove Validation Rules.

Here’s a small example of the different pieces.  I can’t include the full class because my work doesn’t like me to post that much code.  This should show you the main parts.   The only change to CSLA.NET that I can remember is that we had to make the ValidationRules public so we could call the AddRule and DeleteRule from outside the business object. 

 

In the Extended Property of the FullName column:

        Name  = IsRequiredForStatus
   
Value = Codes.Status.Complete

Property is generated like this:

   <IsRequiredForStatus(Codes.Status.Complete)> _

   Public Overridable Property FullName() As String

In the “set” of the nogen Status property (which is of type Codes.Status  enumeration), it calls the function to check the attributes.  This calls the EVIL attributes to process the rules:

   RunValidationAttributes()

In the Validator, it uses reflection to get all of the properties of the object. It loops through each of the properties and checks to see if any of the attributes are of type VBEvilBaseAttribute.  If so then it calls the ProcessRule of that attribute class such as “IsRequiredForStats”.

 

   Public Class IsRequiredForStatus

       Inherits VBEvilBaseAttribute

 

   Public Overrides Function ProcessRule(ByVal pi As PropertyInfo,

       ByVal entity As Object) As Boolean

 

If the property’s attribute enumeration value matches the enumeration of the Status property then it’s required.  The logic below is done for each datatype.

 

 If IsRequired Then

    If pi.PropertyType Is GetType(String) Then

      Dim args As New Csla2.Validation.RuleArgs(pi.Name)

      args.Description = pi.Name & " is required for this status."

      args.Severity = Csla2.Validation.RuleSeverity.FailsCustomRules

busObject.ValidationRules.AddRule(AddressOf

           Csla2.Validation.CommonRules.StringRequired, args)

 Else

    If pi.PropertyType Is GetType(String) Then

       busObject.ValidationRules.DeleteRule(pi.Name, "StringRequired")

If you have any questions, comments, or better ideas, please let me know.  I always like to hear ideas for using CSLA.NET. I would like to thank Dave Cottle.  He is the one that figured out a lot details to make this work.

Mike

Code Smart Not Hard

Saturday, July 21, 2007 2:50:13 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Friday, June 08, 2007

 

Objects that are tightly coupled to the table that they reflect can be referred to as DataObjects.  BusinessObjects, however are objects that represent a logic unit contain the attributes and methods of the business object.  Using CSLA.NET, CodeSmith Tools for code generation, and partial classes in .NET 2.0 we are able to take the benefits of code generation and a straightforward DAL with the flexibility and options needed for designing Business Objects.   Below are some of the features of my templates that allow me to generate my Business Objects based on table schema but still allow flexibility

Partial Classes

Partial Classes is a key feature to my entire code generation process. The golden rule for generating code is to “Never edit generated code”.  With partial classes this is easy.  All of my custom functionality can be put in to my “NoGen” partial class file.  All of the other features actually contol how and what is generated but I included partial classes because it really is fundamental to code generation and allows unlimited custom functionality added to a pure DataObject.

Foreign Key Fields

This started out a way to display both the key and value data of a code in a particular row.  For example if I had an Employee table with a RoleID column, I could add a RoleName “Foreign Key Field” to the template properties.  This would generate the property just like it was a column in the table.  It is really handy for binding drop down lists to your business object and wanting to display the text value somewhere else without having to go look it up again.  This feature started out as always generating the property as a string and has grown into a delimited array where I specify the column and the datatype.  Keep in mind this will generate code for the fetch, update, and insert logic.

Require Gen  Column

Sometimes I don’t want the property to be generated but I still want the fetch, insert, and update data portal functions generated.  In this case, I specify in my template properties, to skip particular property generation. Then I can create the custom property in the no-gen partial class.  One example for this is if you have a lookup id field in your table and want the property to be an enumeration instead of an integer.

“GenOnly” Tables

“GenOnly” tables are tables that I create to base my object when the data isn’t in the format I want the data displayed.  For example I had a table with 6 columns each with a date.  If I bound this to a grid, each data for a particular row would display across in column s.  However the users wanted to see each date in its own row.  I couldn’t change the format the data is stored, so I created a “GenOnly” table with the schema in the format I wanted.

MyDates Table

·         MyDateID

·         Year1Date

·         Year2Date

·         Year3Date

·         Year4Date

·         Year5Date

·         Year6Date

GenOnly_MyDates

·         MyDateID

·         YearNumber

·         YearDate

Now I can use my templates to generate my readonly collection and object classes based on the “GenOnly” table.  I then create the SELECT stored procedure to pivot the data into the format of my objects.  Lastly I can load the objects and bind it to my grid so the data displays down.  In this example the data is readonly so I didn’t need to worry about deletes and updates.  However, if I needed to that I could create the UPDATE and DELETE procs to use a CASE statement or some dynamic SQL.

I like to think you can get the best of both worlds in using a code generator to generate your objects based on table schema but still have some flexibility because something will be different. 

Code Smart Not Hard

Mike

Friday, June 08, 2007 9:54:10 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Wednesday, April 11, 2007

SubSonic 2.0 Beta 1 is released on CodePlex.  SubSonic is a Ruby on Rails like implemention in ASP.NET.  It combines the best of both worlds for a really cool code generation/object framework.  Download it here.  http://www.codeplex.com/actionpack

I just downloaded it.  I'll have some more to report in a couple days after playing with it.

Code Smart Not Hard

-Mike

Wednesday, April 11, 2007 9:05:45 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Saturday, March 24, 2007

Schedule that meeting to talk to your boss about a raise.  CodeSmith Tools will show you exactly how much it is saving your company.  Well almost.  If you pull up the About dialog form, it will show you lines it has generated and use its advanced calculation (Lines generated / Average lines of code per hour) * Average cost per hour.  As you can see from the screen shot I have saved my company almost $80K!  I don’t think it is too much to ask for just 10% of that J

 

 

While for new code generation it is more useful, it keeps adding the lines every time you re-generate the code.  So you could sit there and click on the “generate outputs” a few dozen times and easily add some zeros to the end of that number.

 

I am a huge believer in code generation.  My golden rule for code generation is to never edit generated code, so after you are done coding, you can reset the counter, re-generate, and then your number should be a good representation of what you generated and most importantly, your savings!   While you might not get a raise it does show some interesting numbers and its more evidence to show the benefits of code generation.

 

Code Smart Not Hard!

 

Mike

Saturday, March 24, 2007 10:05:20 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 
Thursday, March 15, 2007

A little over a year ago I presented at the Omaha.NET User Group meeting about using CSLA.NET and Codesmith.   My team and I have been using these two products together in a project for over a year now.   I absolutely believe these two products have contributed to the success of the projects.  

CSLA.NET gives us

  • Unlimited Undo
  • Binding to UI Controls
  • Base Collection and Editable Objects with CRUD
  • Broken rules notification to client via IDataErrorInfo
  • Remoting / Direct Data Access with only config change
  • much more!

We extended CSLA and features provided by our templates

  • Standard business rules through extended properties in SQL Server like MinLength, MaxLength, ReadOnly, IsRequired, etc
  • Custom business rules for any property by overriding AddCustomBusinessRules()
  • Add any custom code in partial classes
  • Parent object can contain 0 to many children collections
  • CRUD stored procs are generated
  • Load Multiple levels at once so that there is only one round trip to the server
  • Created SortedFilteredView object to act like a DataView
  • Custom column formatting for grids in our business objects

Take a look at the zip file attached.   I included the demo and the slides I used in the presentation.

CSLA2Demo.zip (1.34 MB)

If you have any questions or comments you can email me at  mike *at* doitconsultants.com

Mike

Thursday, March 15, 2007 9:44:58 PM (Central Standard Time, UTC-06:00)  #    Comments [0]  | 

Theme design by Jelle Druyts

Pick a theme: