Jan 16 2008

Top tips and tricks for code generation

Category: .NetTiers, Programminglomaxx @ 11:07 am

If you’re like me, a lot of your development work will involve generated code. I love code generation and use CodeSmith and Iron Speed regularly so I’ve put together my list of top tips and tricks for code generation.

  1. Databases are the cornerstone of code generation so it is crucial that you keep your database in pristine condition at all times. Your database should never be taken lightly and some of these suggestions might seem obvious, but they are doubly important for databases that are used for code generation. If you’re creating a table with foreign key references, always ensure that you add them in when you’re building your table. It will save you much heartache and probably a re-generation or two in the long run.

    Use a naming convention for tables and fields and make sure you stick to it. By doing this, you can design your templates to behave consistently.

    Try not to use keywords from SQL or the programming language you are using for table or column names as it will mean you either have to cater for these in your templates, or spend time debugging the problems when the code is generated.

    Ensure that you have primary keys on all your tables.

  2. Active Generation + Passive Generation = Total Control.
    Active generation is the concept that your files are blown away and overwritten on each code generation. Passive generation refers to generating code once and never touching it again. There are people that will argue that one method is better than the other, but I’m a big fan of using both to ensure that you have complete control over your application. In a perfect generation scenario, you will actively generate base classes for each file that are constantly being overwritten each time your code is regenerated, but then you will also have passive classes that inherit from the base classes. These passive classes are generated once and never generated again and will then contain your custom code that can’t be generated.

    The advantage is that you are able to add custom code without fear of it being blown away yet still have confidence to know that a regeneration will completely refresh your code files.

    Passive generation is even easier in .net 2.0 with the introduction of partial classes meaning that you don’t even have to inherit the passively generated class from the base class, you just need to name them differently.

  3. Allowing your functions to be overridable is an extra way to ensure that your generated code is completely flexible. So often I see people generating a method like SaveData() and then in their custom code they’ll have another method that is named something like SaveCustomData(). This then creates confusion because someone wanting to use that object in the future isn’t sure which Save method to use and if it’s even safe to use the SaveData() method. If you had allowed your SaveData() method to be overridable in the first place, you could have simply written your custom code in the overridden method and there would be no confusion as to which method to use.

    It also means that if you change the save logic, you don’t have to go and find every instance where the original method was used and change it to the SaveCustomData() method.

  4. Not everything can be generated and nor should it be. It is very important to realise that whilst code generation is useful for cutting down the mundane tasks such as building objects or writing stored procedures, there are times when you’re just going to have to roll up your sleeves and write some custom code. Don’t fall into the trap of thinking that code generation means you won’t have to write code ever again.

  5. Generate often. Once you have your templates, you should re-generate and re-compile your code often to ensure that you pick up any problems with your templates or the generated code quickly. I’ve found that the quicker you find a bug with your templates or the code generated from your templates, the less time it takes to track down the cause of the problem and the easiest way to do this is to re-generate your code.

  6. Continually add to your codebase via your templates. People are often adding really useful bits of custom code to their generated classes which is great, but you shouldn’t be afraid to add that custom code to your templates if you can find a way to apply it in a generic fashion. Don’t be afraid to let your codebase grow, having extra methods on your classes is only going to make those classes more useful and the framework you’ve created around your templates more powerful.

In summary, I feel code generation is a great asset to any developer’s toolkit and hopefully these tips and tricks can help you get even more out of these already powerful tools.


Aug 01 2007

Using Predicate Generic Delegates in VB.Net with .NetTiers

Category: .NetTiers, Programminglomaxx @ 11:23 pm

This post is absolutely essential if you use the Find method on generics lists in VB.Net with .NetTiers. Here’s some background. I was recently doing some work on an application that required me to loop through a TList that contained nearly 37000 objects and see if they existed in another TList that also contained around 37000 objects. So to achieve this I whipped up some code that looked a little like this:

For Each item As BaseAddress In lstProdContacts

Dim tmpContact As BaseAddress = lstTempContacts.Find(BaseAddressColumn.IdBaseAddress, item.IdBaseAddress)

'Use tmpContact here

Next

It worked, but the thing I found was that it was horribly slow. To execute on my list of 37000 contact it took well over 8 minutes which was simply unacceptable.

This post from the .NetTiers team pretty much confirmed what I had suspected and that this Find method was in fact using reflection. From my previous experience as a DNN programmer, I knew that reflection was expensive and should be used sparingly.

The post however, offered me an alternative solution: Anonymous Methods. However, this also presented another problem, VB.Net does not support anonymous methods. I was able to hack up some code that would use a wrapper class but it was all starting to get a little messy until I came across a brilliant post by Paul Stovell on Almost Anonymous methods in VB.net.

It wasn’t exactly what I wanted because I still had to define a function that would match the contacts, but it was a still a far cleaner solution. I put Pauls class in my Utility namespace and now when I want to use an (almost) anonymous method I do something like this:

For Each prodContact As BaseRfaAddress In lstProdContact

Dim tempContact As BaseRfaAddress = lstProdContact.Find(New PredicateWrapper(Of BaseRfaAddresse, BaseRfaAddresse)(prodContact, AddressOf ContactMatch))

'Use tmpContact here

Next

Then in the same class I define a function that will determine if a contact is a match or not and we’re done.

Public Shared Function ContactMatch(ByVal item As BaseRfaAddress, ByVal argument As BaseRfaAddress) As Boolean

Return item.IdBaseRfaAddress.Equals(argument.IdBaseRfaAddress)

End Function

It isn’t by any means as clean as anonymous methods in c# but now when I run the loop it runs in well under a minute which is an almost unbelievable performance gain and well worth the effort of implementation.