We have a project that needs to be build for both .Net 1.1 and 2.0 due to server compatibility issues (Windows Server 2000 and Windows Server 2003 production servers). I am looking for help making the decision between conditional compiliation or branching the code in source control. There are pros and cons for each. Thanks in advance.
One thing that would impact my solution is knowing how long I expected the 1.1 solution to survive and what it's purpose was. If the solution was in maintanence mode and really wasn't going to be adding too many new features, I would pick a separate branch solution. I would then carefully migrate needed changes between the two branches.
If however it is a full fledged version that will have most if not all of the same features I would go the conditional compilation route. Otherwise every single check in you make would also have to be merged into another branch before it was complete.
You have a number of options:
- Write to the lowest common denominator i.e. 1.1. This should run fine on .NET 2.0
- Create a legacy branch in SVN/CVS for 1.1 and maintain that separately.
- Use conditional compilation
- Isolate functionality specific to each version in separate assemblies and ship the appropriate assembly with each version
- Seriously investigate the upgrading of the servers to the latest release. I have been in this position before and I did a cost-benefit analysis for management and showed that it would cost more money to do the dual versions than do the upgrades.
Definitely go with conditional compilation over branching (and isolate it as best you can into specific modules).
Branching would mean that if you found a bug in an unrelated part of the code (i.e. code that is independent of the .Net version), you'd have to fix it on both branches. Don't go down that road if you don't have to.
I prefer to use an Abstract Base Class (ABC) that defines an interface and platform-specific derived classes, in concert with a factory object/method and whole-file conditional compilation to get around these matters (I've got a GUI library that works on Win32 and X11 implemented this way).
Gratuitous branching is never a good thing!
Branching is usually a nightmare (duplicated effort and merge problems abound). IMHO it should only be used for a dead-end branch that you never expect to keep in sync with the main branch (i.e. you're not expecting to make many changes to the old branch, perhaps only the most critical bug fixes from the main branch).
Conditional compilation allows you to see the differences "side by side" in the code, and it's immediately obvious when you start changing something inside an #if that you also need to consider the #else section.
Conditional compilation will only give you trouble. Conditional compilation litters your code with #IFDEF macros. It hints the programmer to force abstractions where one doesn't exist. Say you wanted to make a generic class, and now you want to make it compatible with .NET 1 so you have ifdefs around all cast operations. The bullet you have to bite is fixing issues in two branches if one arises, hopefully you aren't writing too many bugs :)
Branching allows you the option of using shared program text files .CS from two different solutions targeted to the different platforms in the case where there's no difference between .NET 1 and 2.
The only thing I would add to the above is, if you do branch, merge your changes early and often. Have one person in charge of the merging. Merging large volumes is painful, merging small amounts often is not nearly so bad.