At Handmark, we use Subversion for source code control. (Check out this Subversion Quickstart at the Polymorphic Podcast.) Like most systems, it supports concepts like branching and tagging. The mechanics for each system varries, so check your documentation for those details. But a more interesting question is, how do you manage branches and tags? Where do you make your changes? What steps do you take when it's time to release?
There are essentially two schools of thought for branching: for features or for releases. We've chosen to branch for features and merge into the trunk to build a release. But another option would be to make all code changes in the trunk and branch at the point of release. You choose your policy based on where you will accept instability. If you can tolerate an unstable trunk, then branch for releases. If you need to isolate instability in the branches, then branch for features.
We've chosen to branch for features because our priorities change quickly. This strategy allows us to isolate changes away from each other, put them on hold for a time if necessary, and keep the trunk stable. All builds are performed from the trunk, so changes must be merged from their branches to the trunk prior to release.
Once we've build a release, it moves through various staging areas. A build starts in integration, moves to testing, and finally into production. At each point along the way, there are checks in place to ensure that it is ready to move forward. The pipeline is rigid in that no build may pass another on the way to production, and no build can move backward. If a build fails one of the checkpoints, it drops out of the pipeline. If we need to expidite a change to production, the build that's currently in the pipeline is dumped.
We find that this policy works best for our environment. It may or may not apply to yours. Choose the policy that fits your team, discuss it, document it, and stick to it.
A spreadsheet contains both formulas and the data on which they operate. This makes it difficult to share formulas with someone else without sharing the data. If you want the same calculations performed on a different set of data, you have to make a copy of the spreadsheet. If you later need to update the calculations, you have to make the change in both places.
A Visual Source Safe database contains one tree of folders. A folder can represent a project, a package, a branch, or a shared library. Through discipline, programmers keep these different degrees of freedom on different levels of the tree. We will create a folder under a project to represent the trunk, and another to represent a branch. But what about branches of the shared libraries? Where do they go? Sometimes it is not easy to place one concern neatly below another.
An Ant build script contains several targets. A target can represent an action (clean, compile, deploy, etc.), or it can represent a project (shared library, business logic, web application, etc.). Targets depend upon other targets: deploy depends upon compile, and the web application depends upon the business logic. I need to clean and compile each of my projects, but only deploy my web applications. The web application deployment should include all dependent projects. When describing this to Ant, I end up with a cartesian product of actions for each project. If I later have to modify an action, I have to do so for every project. Similarly, to add a new project, I have to copy and paste all of the actions from another one.
All three of these scenarios suffer from a coupling of concerns. Different dimensions of the problem should be allowed to vary independently. But when the design of the solution mixes these dimensions, it becomes difficult to pull them apart later. Unfortunately, this sort of design flaw is usually not detected until the system has been in use for some time. Please take the time during the design phase to ask if yourself if you can separate concerns.
Earlier this week, I talked about an error message that appeared in Microsoft Visual Studio as a result of VSS integration. While the error message itself offered a few lessons for the software adventurer, I would now like to examine the core of the problem: VSS is not ACID.
If you are not familiar with the acronym ACID, please see this Wikipedia article. Basically, the idea is that you get to work on isolated snapshots of the data, with no interference from others who may be working concurrently. When you want to commit your work, you synchronize with others.
This is a fundamental flaw in the way that VSS works. Other source code control systems are ACID, like CVS, Subversion, and StarTeam, just to name three. Let's walk through a scenario to see why this is important.
Suppose you are working on a bug or enhancement and you have some files checked out. Now you need to change code in a file that you haven't checked out to complete your work. You open VSS and check out the new file. Or, if you are using VSS integration, you just start typing and Visual Studio automatically checks out the file for you.
But wait, someone else has modified the file and checked it in. Their change was part of a larger modification. They have also changed other files that it depends upon, including some that you currently have checked out. As a result, when VSS checks out this one file, thereby getting the changed version, it is incompatible with the other source files in your project. You will spend an hour or two getting your project to compile again, which may mean merging with the changes you've already completed.
The only way to continue working without interruption is to start making your changes from the version of the file that is already on your system. This ensures that you have a consistent set of source (the C in ACID), and keeps you isolated from other peoples changes (the I) until you are ready.
There is a way to do this in VSS, but it is tedious. First, turn off Visual Studio integration. Then, when you need to check out a file, go to the VSS file history window. Click on the version that you already have (you may have to click Diff to find it, or better yet create a label before starting your work). Perform the check out from history. When you are ready to check in, VSS will help you perform the merge, if necessary.
Better yet, invest in an ACID version control system. CVS and Subversion are free, but they take a little setting up. StarTeam and others cost money, but may offer the usability and features that you need. Whatever you choose, you will recoup your investment by avoiding interruptions due to inconsistency.
Visual Studio in a Zombie State!
Never let a programmer write error messages. In our own software, we have one error message written by a former employee which reads, "Problem shutting down server! A cold blooded murder will now be performed." This, of course, indicates that the server is terminating the background thread.
"Cannot access data for the desired configuration since it is in a zombie state."
Being a programmer, I think I can understand why my configuration might be in a "zombie state". I can also figure out that all I have to do is cancel the dialog and try again. This time, the project file will be checked out before I begin.
But while this error message may speak to the programmer who wrote it, it does not mean much to me.