Merging branches that are in a different .NET version

At work, my project is preparing to release the current version of our application to the clients.  This release will is still in version 1.1 of the .NET framework, but we will be converting up to version 2.0 for the next phases of our development.  To accommodate the ongoing support effort of the impending release (we will be supporting this for the next 8 months or so) we have split the source code into two branches.  In theory we will be merging all changes from the support and maintenance branch (.NET 1.1) up to the new development branch (.NET 2.0) on a regular basis.

In a spot of uncommon preplanning, I decided that we should give this process a go before we get to far in and have no easy way out.  I worked with the development branch to get it converted up to .NET 2.0 and, a couple of days later, proceeded to merge the changes from the support and maintenance branch into the now converted code.  Things went to the crapper in a hurry.  The biggest problem that I encountered was in the merging of the project files.  The VS2k3 and VS2k5 project file structures are significantly different and the merge process was completely overwriting the project files in the .NET 2.0 branch.  Not a good thing, as we're going to be adding files to those projects in the development branch and the merge was also converting the project files back to the .NET 1.1 format which caused the project to want upgrade every time we opened the solution. 

Another thing that happened related to the changes in the web project styles that occurred between v1.1 and v2.0 of the framework.  In v1.1 there was a *.csproj file for any web project that you create, but in v2.0 it disappeared until you installed the Web Project upgrade (not an option for us as this would take months of bureaucratic processing to see it actually end up on the developer workstations).  When you merge a web project from a v1.1 branch into a v2.0 branch it will add the *.csproj file back to the directory.  This results in another attempt by the IDE to convert the web project from .NET 1.1 to .NET 2.0.

I haven't figured out a smooth way to merge these files, so I started coding.  I've almost completed a tool that will parse solution and project file structures, for both versions of the framework, and output a text report that displays the differences between the files.  One of the more difficult things to deal with has been the removal of a project file for web projects.  I rely on that file to be able to determine what is, or isn't, in the project.  Without it, it's very difficult to perform a proper and complete comparison of that project type.  Additionally, the movement of the code behind files from being co-located with their partner *.aspx or *.asmx files to their own App_Code folder.  A little creative coding and this can be resolved, but it's an extra layer of complexity that isn't necessarily desired.

Overall, I'd say the experiment sucks.  Unfortunately our client and management has decide that the framework upgrade is too risky to perform prior to our once again deadline missing project.  Not only that, but management wants to continue to add new features to the Phase 1 release while it is in maintenance mode and while we are working on the new development of Phase 2.  So instead of just merging up bug fixes that are found in production, we will now be merging up bug fixes and new functionality.  Nothing like adding a little complexity to the situation to add risk to, and decrease the quality of, the next major release.  I'm just glad I'm not a tester.  In the end it will be the fault of the developers.  It always seems to be.  I guess it's my job to stop that from happening.

Best Edmonton Tech Posts in 2006

Inspired by this post by Des Traynor, I'm compiling the top posts for the local community in 2006.  Here they are in no specific order.

This is a great post that covers off a nice pattern that will increase the readability of your code.  Take a look at the comments and see what JP Boodhoo suggests as an alternative.

A great little blurb on a different approach to learning how to use a mocking framework.

This is an awesome post that tells how you can save yourself from the tedium of setting up a new project structure.

These are great things that you need to keep in mind while working on the dark side.

This is a great post that discusses different points on the use and non-use of comments to increase the documentation within your code.

This is an awesome post on a topic area that often gets ignored in the noise generated by the web hype machine.

  • Here and here about the launch of the Edmonton .NET User Group (Edmug)

This has been the single biggest thing I've done in my professional career and seeing the reception from the community has been fantastic.

Here's to another year of great Edmug meetings and fantastic local blog posts.  I lift my glass of scotch to you and hopefully next year I'll lift one with you.

Roy Osherove on Continuous Integration and Agile

The more I see of Roy Osherove presenting, the more I like his style.  It's understated, but he doesn't miss covering and emphasizing the important points.  Maybe one day we will get him up here in the City of Champions.

This presentation, from TechEd (Europe? this year?), covers a lot of things including CruiseControl.NET, nAnt, nUnit, MSBuild, Team System.  You will need to use either IE or an IE addin for Firefox to view this.  Firefox by itself doesn't work.

A couple  of the more insightful statements that Roy mentions are these:

During the iterations, the client can not change their mind.  Between iterations they can, but not during.

Agile methodologies are about adapting to the way your team works.  You could say that "My team needs more documentation..."

I wish I had that quote a week or two ago when I was getting hammered at work with the ".NET == C# == Agile == poor design == no documentation == failure" arguments.

I tried to be EViL today

I know what all of you are thinking  "Oooohhh, this is going to be good.  I better pick up tomorrows Frostbitten Times to see what carnage appears on the front page."  Sorry to disappoint, but I'm a lover....really....

After seeing a number of different attribute based validation schemes floating around the web, I decided to give one a try.  I came across David Donaldson's post a few days ago and decided to give the open source project EViL (Entity Validation Library) a try.

Installation of the product was pretty easy.  Download here and unzip the file.  Add a reference to the EvilAttributes.dll assembly.  Now all you need to do is decorate your POO (plain old objects) and turn them into something special.  The list of available attributes is fairly comprehensive, but I did manage to find a few problems areas.  The following code shows a property that represents an Order Amount.  The business rule that I was trying to implement, as you can see by the message, is that the Amount must be greater than zero.

private double _amount;

[EvilAttributes.ValidateMinValue(0.01,"Order Amount must be greater than 0")]
public double Amount
{
    get { return _amount; }
    set { _amount = value; }
}

I couldn't find a way to do this in EViL and ultimately could only come close by using the value of one cent which isn't optimal. What EViL needs is an attributes with the following signatures:

ValidateGreaterThanMinValue(double minValue, string message)
ValidateGreaterThanEqualToMinValue(double minValue, string message)

The second issue that I have with the framework is that none of the attributes are capable of handling multiple datatypes.  Another scenario that I wanted to use was a validation that required that the number of products on an order is greater than 0.  The total Product count is an integer type (we don't sell fractional dog sleds here) but the ValidateMinValue attribute only accepts a double as the minimum value parameter.  Again, this is workable, but not optimal.

A few of my final issues with EViL are to do with how you point an attribute at another property for comparison and the use of the same attribute multiple times.  First the property comparison validation.  As you can see in the sample below, identifying the property that is to be used for comparison is done by passing in the property name as a string value.  I'm a strongly typed kinda guy and I'd really rather see that implementation.  Maybe I'm don't know enough about reflection to understand this isn't possible, but I know what I'd like in my ideal world.  Another thing that I'd really like to see is the ability for the comparisons to be performed against a private property, field or constant (not so much the constant, but I added it here 'cause you just never know).  I really don't like having to create a public property just to be able to compare against a value.

As the example below shows, I really want to be able to compare the Order Date against both the MinimumOrderDate and the Customer object's SignUpDate.  I can't.  I'm not allowed to use the ValidateDateOccursOnOrAfter attribute more than once per property.  That sucks.  My experience shows that validation is rarely that simple.  To top it all off, the EViL accepts the Customer.SignUpDate (Customer is a property on the Orders object) as a parameter for the attribute, but it can't or won't use the embedded objects for validation.  Again, my experience shows that domains will not always have the values in the domain object that you're comparing against.

private DateTime _orderDate;

[EvilAttributes.ValidateDateOccursOnOrAfter("MinimumOrderDate", "Order Date must be on or after today's date")]
[EvilAttributes.ValidateDateOccursOnOrAfter("Customer.SignUpDate","Order Date must be on or after the customer's Sign Up Date")]
public DateTime OrderDate
{
    get { return _orderDate; }
    set { _orderDate = value; }
}

 As a v1 product I think that EViL is going in the right direction.  I hope that the guys writing the code take this as constructive criticism.  I really want EViL to be able to do all of these things.  When it does, I'll be using this in production code.

Rob Windsor @ Edmug

Last night my old buddy (he claims the Leafs have won the cup in his life time....musta been programming on papyrus back then Rob!) Rob Windsor presented to Edmug on An Introduction to WCF.  He did a great job and covered a huge number of topics in the two hours he spent with us.  It was also great to see the audience really get into the topic and ask a bunch of questions.

One of the questions that came up was around the concept of programmatically adding and changing WCF MetaData EndPoints.  As always the web is a great place and I found this post by Rick Strahl in my aggregator this morning.  Rick covers off some great things there and hopefully it will answer some of the questions that the one guy in the audience had.

Thanks again to Rob for making the trip to Edmonton and doing his little tour of western Canada this week.

Published at

Tweaking Cyclomatic Complexity Calculations

I've been looking at a number of different tools and techniques that I can implement at work to help us figure out where this pile of code that our team has inherited is in the most trouble.  One of the techniques that I've used in the past is to implement a cyclomatic complexity evaluation during each build.  There are a few tools out there to do this, but, being a cheap bugger, I have only used the free devMetrics tool.  I went out looking to grab it again this week for us to start implementing and lo-and-behold if the folks at Anticipating Minds haven't thrown this great tool out to the Open Source world.

I downloaded the tool from SourceForge only to find that the only thing available is the source code, in a .NET 1.1 form, and not compilable.  Disappointed is an understatement.

Like all other disappointments, I decided to have a couple of scotch to take the edge off.  As I sat and reflected on the possible implementations of cyclomatic complexity I began to figure out that it really wasn't what it was all cracked up to be.  The standard calculation used to determine cyclomatic complexity is referred to as McCabe's Metric and it comprises of a set of rules that essentially boil down to an increase in complexity by a value of 1 for each decision point that exists.  Rough guidelines state that if your complexity number for a method is 1-5 then you're good, 6-10 means you should consider some way to simplify and 11+ should be a big red flag for refactoring.

The purpose of these guidelines is to help keep your code at a place where, when reading individual methods, you have minimal decision points to consider at any one time.  The way to reduce the complexity that exists in a specific method is to refactor the decision points out of that method and into other methods that are called by the original code.  Take the following example where the first block of code has a complexity of 4 and the second block where the two methods both have a complexity of 2.

public double GetCustomerDiscountPercentage(Customer cust, DateTime applyDate)

{

     if (cust.Type == CustomerType.Wholesale && applyDate >= START_OF_WINTER_DATE)

     {

          return 0.15;

     }

     else

     {

          return 0.10;

     }

}

public double GetCustomerDiscountPercentage(Customer cust, DateTime applyDate)

{

     if (WinterWholesaleCustomer(cust, applyDate) == true)

     {

          return 0.15;

     }

     else

     {

          return 0.10;

     }

}

public bool WinterWholesaleCustomer(Customer cust, DateTime applyDate)

{

     if (cust.Type == CustomerType.Wholesale && applyDate >= START_OF_WINTER_DATE)

     {

          return true;

     }

     else

     {

          return false;

     }

}

By doing this refactoring (yes, it is quite trivial and the original was not all that hard to read) all we did was reallocate the total complexity.  There is still an overall complexity of 4, but it has been split between two methods and has achieved the goal of reducing the level of complexity that you have to deal with at any one time.  Or has it?

The refactoring that I've shown above has added an extra layer of call depth to your code, and for that I would argue that this should be treated as an addition of 1 to the cyclomatic complexity calculation in the GetCustomerDiscountPercentage method.  Any time you add layers to the code's execution path you force the person reading it to mentally manage a call stack.  I don't know about you, but I'm not capable of handling all that many items on my mental call stack.

What I'd like to see is a change to the criteria for complexity that is prescribed by McCabe's Metric.  In addition to having the complexity determination only using the keywords (or language specific equivalents) to  if  while  repeat  for  and  or  , we should also add a component to the equation that deals with the depth of the code.  Each time a method makes a call to another method, the calling method's complexity should increase by a value of 1 for each level of depth that the call stack can reach because of that method call.

In my refactoring sample this would take the first block from it's initial complexity of 4 to a refactored complexity of 3 which reflects the call to the newly created method.

I have other ideas for tweaking McCabe's Metric, but I'm going to explore them more before I put them to virtual paper.

.NET training in Edmonton

When you live out here in the hinterland, good software development training is hard to come by.  When it does roll around it's usually not for the technology or tools that you're using.  Times are changing.

JP Boodhoo is coming to Edmonton the week of February 19th to 23rd to put on a comprehensive training course on .NET development.  If you've seen JP present you know what you're going to miss by not attending this course.  If you haven't I'll tell you.  You'll miss passionate diatribes about the .NET Framework, Visual Studio and ReSharper.  You'll miss techniques and ideas that will tie your knickers in a knot while you're wearing them.  You'll miss having the opportunity to sit in the same room with good looking, sexy (in a sultry, I-implemented-interface-years-ago kind of way) .NET developers like me.

Now if you're one of my co-workers you probably don't want to miss this opportunity to get your hands on the throat of a developer who once represented the company that has made you hate right-clicking and selecting "Go to Definition".

Unique values for surrogate keys

Don't you hate those days when you think you've seen and heard it all only to find out that there is one more thing that is going to make you want to poke your eyes out?  Well, today I went past poking my eyes out as the only remedy.  Now that I'm thinking about this again, I'm regretting having a scotch at the desk with me.  I'm seriously considering trying to wash away the image burned into my retinas by dousing my eyes with said scotch.  If that doesn't work I might have to carve out my eyes and dig around in the empty sockets with a rusty ice pick trying to destroy all the optical nerves.  Anyways, enough drama.

Surrogate keys.  I've worked in a number of databases that have these and in those experiences I've used a number of different schemes to generate unique values.  One system used an Identity field, another used GUIDs and still another used a managing table that incremented the value every time you requested a new one from it.  As bad as that last one sounds, it works fairly well for a system with a small number of concurrent transactions being processed.  I probably wouldn't use the last one again simply because of the scalability issues (I can always dream that my systems will become big one day), but, in all it's ugliness, it will work.  Today I saw uglier.

So this afternoon I'm pawing through a bunch of stored procedures (apparently our timestamps aren't really timestamps...another story for another day) and I stumble on this block of code where we're generating a new surrogate key value.  After my initial and immediate shock, I had to start asking other people on the team what they knew as being our standard way to generate these values.  The first guy I ask confirms what I've just seen on the screen.  The second guy says "Well....." to which I respond "Please don't tell me it's what I think it is." and receive a laugh and nod of confirmation.  Believing that the first guy burned out all his cognitive capabilities on beer at our last team pub night and the second guy spent too many years exposed to the searing Caribbean sun, I went off to developer number 3 in search of the answer I so dearly wanted to hear.  Once again the code on the screen was confirmed to be correct.

It's at this point that I thought that I had two things left to do.  First I needed to submit my inaugural code snippet to The Daily WTF and then I needed to buy a new bottle of scotch (the second part of this has become a code related theme this week).  After some second thoughts I decided who really reads The Daily WTF anyways?  If you want perversion you go this Edmonton blog and if you want curious information technology you come to the Igloo.  So I decided to post it here (there also was the fact I hadn't posted for quite a while too, but honestly that was down on the list).

I introduce you to my pseudo code version of the standard way that we are told to get surrogate keys.

Do some stuff...

Restart Loop:

Loop

       Get Random Number and multiply by 1 billion

       Insert to database with value above as the surrogate key

       On error go to Restart Loop

End Loop

Carry on doing more stuff...

Yes folks, we are generating a random number and testing it's uniqueness by inserting to the database and responding to key violations.  This would be great if you had a hundred billion available key values and only expected a few thousand entries in the table.  Unfortunately though, the more and more entries that are successfully added to the table, the more and more probably it becomes that you will encounter a collision and thus an error.  There's also the fact that more collisions will slow the system down.

The scary thing to me is that this is the enterprise standard for generating surrogate keys and we're not dealing with a tiny data set in this company.  I don't know how close to being truly random the DB2 rand command is, but even if it is great no computer generated random number generator is truly random.  Maybe I'll be lucky and this won't become a problem during my tenure.  Chances are it will though, that's just the way it works for me.