Streamed Lines: Branching Patterns for Parallel Software Development

Copyright © 1998 by Brad Appleton, Stephen Berczuk, Ralph Cabrera, and Robert Orenstein.
Permission is granted to copy for the PLoP '98 conference.

Table of Contents
[printing/downloading instructions]
Send us your comments!

Branch Creation Patterns

C1. Policy Branch

Pattern Policy Branch
Aliases Branch on Incompatible Policy
Context A number of developers are working with the same codeline. A CodelinePolicy is being used with the codeline.
Problem Some of the users are dissatisfied with the current codeline policy, and have a need for it to change.
  • Changing the CodelinePolicy to the policy that the dissatisfied users request will cause problems for the other users of the codeline.
  • Adding new policy statements to the existing policy may make the codeline unusable in any form.
Solution Branch the codeline to create a new one based off of it; leave the old CodelinePolicy with the original codeline and attach a new CodelinePolicy to the new codeline.

Figure C1a: A Policy Branch spawned from a Development Line

  • Developers on the original codeline, and on the new policy branch each have a policy more suited to their needs.
  • Additional integration needs to take place to keep one of the two codelines "in sync" with the other via change-propagation.
Don't forget to use Codeline Ownership and Codeline Policy for the new policy branch. Propagate Early and Often to keep the codelines "in sync" as needed.

C2. Branch per Task

Pattern Branch per Task
Aliases Activity Branching, Task Branching, Side Branching, Transient Branching
Context For a given codeline, the set of files affected by any change-task may overlap with that of other changes to the codeline. At some point, all the features and fixes the codeline will need to be integrated together in order to deliver the required combination of functionality.
Problem How can multiple, potentially interfering or overlapping changes be made to a codeline without compromising its consistency and integrity?

  • Parallel development without controlled interaction between concurrent changes can result in lost or corrupted changes, and wasted effort and rework.
  • Concurrent changes need to integrated with care. Otherwise changes which work correctly in isolation from one another could cause incorrect or inconsistent behavior when combined together. A single unanticipated change could destabilize the entire codeline and impact all of its users.
  • Excessive locking may cause very long "busy waits", forcing developers to suspend some of their activities until a locked file becomes available. At its worst, this can cause deadlock between parallel activities.

Solution Fork off a separate branch for each activity that effects changes for a codeline. Once the activity is complete and all of its file changes have been tested, checkin files on the activity branch. Then, if MYOC is being used, merge the activity branch into the appropriate codeline (as a single transaction). Otherwise notify the appropriate codeline owner that the change is complete and ready to be merged (and provide the codeline-owner with any other necessary information for finding, merging, and testing the change-task).

Figure C2a: A separate activity-branch for each development task

An activity-branch is a kind of degenerate a codeline, complete with an owner and a policy. The branch owner is the owner for the particular task or activity. The policy of the single-activity codeline is that it is completed (retired) and merged back to a parent codeline once the first logical change to it has been completed.


Branch per Major Task (a.k.a Major tasks off-line, Minor tasks on-line)

A common variant of Branch per Task is to use an activity branch only for major tasks. Minor tasks are performed "on-line," without any branching off of the codeline. Such tasks are believed to be "short and sweet" and can usually be completed and checked-in before very many other tasks have had a chance to checkout and checkin any of the same files.

Ostensibly, major tasks are those that would be "long transactions": The state of the codeline will have ample time to change between the time the tasks starts and finishes. Often, a certain minimum threshhold of estimated changed lines and/or files is used to discern major tasks from minor tasks. This is an attempt to estimate the inherent complexity of each task and the potential destabilizing effect it may have upon the codeline. The underlying desire is to mitigate and isolate the risk associated with each change, and its impact upon the codeline.

Figure C2.1a: A separate activity-branch for only major development tasks


Branch per Change-Request (a.k.a. CR-Branch, Change-Set Branch, Change-Package Branch)

Use a branch to isolate the changes for each change-request (CR). The branch encompasses a single logical unit of functionality (a feature), or a single logical change in functionality (a bug-fix or an enhancement). The same branch should be used for all files which collectively participate in the lone feature or change.

Personal Activity Branch (a.k.a. Single-User Task Branch)

A personal-activity branch is simply a special kind of activity branch where the owner of the task is the sole performer (developer) of the task. It may be accompanied by a branch-locking policy to ensure that the personal activity branch is also a private activity branch (see Private Branch).
  • The changes along along activity branches are isolated from one another so their corresponding modifications do not interfere even when their corresponding file sets overlap.
  • Making changes independently separable from each other lessens the burden, and the risk, of integrating them with the myriad other changes in the codeline. Packaging them up as branches makes them easier to identify, trace, and query as a group.
  • CR branches and activity branches can be a convenient "packaging" mechanism for grouping together multiple file revisions as a single, logically coherent change. However, when versions from one branch are integrated to another branch, the newly integrated versions lose the grouping provided by the original branch.
  • Merging must be performed for changes which didn't even require concurrent modification of the same files. Although the "copy-merge" will be trivial, numerous copy-merges can add up to significant overhead for files that didn't really change. The variant Branch per Major Task addresses this by reducing the number of trivial merges at the expense of less isolation for supposedly minor changes.

Codeline Policy, Codeline Ownership, and MYOC were mentioned above. If activity branches start to depend on other activity branches (in addition to depending on a baselevel of the codeline), then a Subproject Line should probably be used.

This pattern has some interesting similarities with Thread per Request [Schmidt96].

C3. Codeline per Release

Pattern Codeline per Release
Context During the course of development you will need to perform several software releases. Work tasks are often organized around such delivery dates and their milestones. You would like the branching structure used to readily accommodate the organization of work tasks performed by developers working toward the common goal of a release (contrast this with a project that may be more architecture-centric than delivery-centric).
Problem How should software releases, release engineering, and development for a particular release be reflected in the branching tree of the project?
  • To be sure, labels will be used to tag stable configurations ready for release. But baseline labels alone are insufficient to help structure workflow for a specific release.
  • Major and minor release, as well as patches will often need to have their maintenance and development tasks occur simultaneously, in parallel from one another.
  • Merging causes integration overhead, but some amount of integration is essential for verifying and validating that a configuration to be released is suitable for shipment to customers.
Solution For each planned release (major, minor, and patches), use a separate codeline to organize efforts focused on each individual release-effort.

Figure C3a: Codeline per Release for release 1.0, 1.1, and 2.0

There are essentially two ways of doing this: you can use Early Branching the release lines, or Deferred Branching. With early branching, you will create a release-line as soon as efforts toward that release begin to take place. With deferred branching, a new release-line is created only when changes specific to that release begin to take place. Changes that need to go into that release as well as in an existing release-line would take place in the previous release-line that also needs the change.

For example, a bug-fix might be needed both for release 1.1 as well as release 2.0. With early branching, that bug-fix would go into both the 1.1 and 2.0 release-lines (possibly creating the 2.0-line if it didn't already exist. With deferred branching, if the 2.0-line didn't exist yet, the bug-fix would go into the 1.1-line only and creation of the 2.0-line would be deferred until efforts began for a fix or feature that was needed only for release 2.0 (or later).


Codeline per Major Release (a.k.a Major releases off-line, Minor releases on-line)

In this variant, new release-lines are created only for major releases. So a release-line might be created for release 1.0, and also be used for releases 1.1, 1.1.1, 1.2, etc. (all releases of the form 1.x or 1.x.y).

Figure C3.1a: Codeline per Major Release with Mainline

This variant can also be implemented using either early branching, or deferred branching. But since it already uses deferred branching to some extent (at least for releases with the same major version number), it is more commonly implemented with early branching.

However, it may not always be feasible for each minor release and patch effort to happen on the same codeline. Some efforts will need to continue while release engineering is performed on a more stable branch (see Anti-Freeze Line). So there will frequently be separate branches for minor-releases and patches, which merge back to the major release-line when finished. But there won't necessarily be a separate branch for every such release.

  • The branching structure more closely reflects the organization of work efforts for the various releases of the software.
  • Additional integration effort is required, especially for propagating changes needed by multiple release lines from earlier releases to subsequent releases.
  • If the propagation hierarchy grows to a depth of three or more, this can impose an extremely noticeable amount of integration overhead. Deferred Branching and Codeline per Major Release help to mitigate this risk, but not to eliminate it.
Codeline per Release is a form of Early Branching while its variant codeline per mahor release is a form of Deferred Branching. Codeline per release and per major release often participate in Overlapping Release-Lines, in Parallel Maintenance/Development Lines, and in an Anti-Freeze Line.

It is extremely useful (and often necessary) to use a Mainline when using this pattern, or its variant. Otherwise the project branching tree can get too wide and unwieldy. Both Codeline per Release and Codeline per Major Release may be used with either the Stable Receiving-Line or LAG Line variants of mainline (as well as with both of them at the same time).

C4. Subproject Line

Pattern Subproject Line
Aliases Sub-Codeline, Change-Line, Project Branch, Persistent Branch
Context You are using Branch per Task or Branch per Major Task, and you have a somewhat large-grained change-task to perform. It is large enough to split into several smaller change-subtasks, at least one of which is also deserving of its own separate branch. Some of the subtasks may need to be sequential, with certain subtasks dependent upon changes made in their predecessor tasks. Or perhaps some of the subtasks will be performed in parallel. In either case, you can't permit the individual subtasks to be integrated back into the codeline until all of the subtasks are complete; otherwise the codeline may be in an inconsistent state for other developers working on other codeline tasks in other workspaces.
Problem How do you organize the subtasks of a large-grained task that needs to effect changes to the codeline?
  • We want the composite task to enter the codeline as a single change transaction.
  • The composite task really is large enough that it needs to be further subdivided into discrete subtasks.
  • Checking-in individual subtask-change back to the codeline may compromise the integrity of the codeline if not all subtasks are finished yet

We could just have later tasks refer to the branches for their predecessor tasks. But this has a few problems of its own:

Figure C4a: Multiple dependent activity branches (undesirable)

  • Our activity-branch now depends on other branches that aren't yet part of the codeline. This can wreak havoc at integration time if the branches aren't integrated in exactly the right order.
  • Each subtask has to remember one more branch-dependency than its predecessor. This can become cumbersome and error prone for three or more subtasks.
  • If parallel development is taking place between the subtasks, it may be dangerously easy for undesirable codependencies to arise between their various activity-branches. This can make for an unwieldy integration of all the subtasks back into the original codeline.
  • It can make the branches in the version-tree take on a shape that doesn't really reflect the hierarchical nature of the composite task. This can be very misleading to people.
Solution Create a branch for the composite task, and then create subbranches off the composite-task branch for the subtasks (or just the major subtasks). When a subtask is completed, integrate the subtask branch back into the composite-task branch. When all subtasks are completed and have been integrated into the composite-task branch, then integrate the composite-task branch back into the codeline.

Figure C4b: Using a Subproject-Line to decouple branch dependencies

If the composite-task is for a fix, then this is sometimes dubbed a Fix-Line (not because it is for fixes in general, but because it contains logical changes toward implementing a single bug-fix). Similarly, if the changes are for implementing a single feature, this is often called a Feature-Line.

So we branch off the codeline to create a Change-Line or Subproject-Line: a line which incrementally receives changes for the particular fix or feature. The change-line should be treated like a codeline, having its own Codeline Policy and Codeline Owner. When all change increments have been completed and/or merged into the change-line, the change-line may then be merged into its parent codeline.


Personal Codeline (a.k.a. User-Branch)

A single-user-branch or personal codeline may be used when the subproject in question consists entirely of related tasks that are carried out by the same developer. It may simply be a bunch of maintenance tasks for the same release, or perhaps a more significant feature or enhancement. The personal codeline may be accompanied by a branch-locking policy to ensure that the personal codeline is a "private line" (see Private Codeline).

Experimental Line (a.k.a. Prototype Line or Proto-Line)

A codeline for experimental development. It may be an experimental prototype that is discarded (even upon success) or any other work which isn't yet planned for any known release, and might be totally abandoned.

Multi-Project Lines (a.k.a. Multi-Product Lines)

This is basically the same pattern used at a coarser granularity. Whole project-lines or product-lines are used and releases are configured by selecting the appropriate stable baselevel of each project/product-line and integrating them together. This is an extremely advanced practice used by very mature software shops that have developed a sufficient base of separable and reusable components or products in an integrated product family. In essence, each standalone software asset is escalated to full-fledged product/project status (even if they are not provided to customers on an individual basis).

The hard part is balancing the needs of the individual assets against the needs of the integrated product. There will be much pressure to splinter off project lines for specific deliverable products. Organization's that successfully use multi-project lines are able to manage and resist short-term needs to splinter the project-lines for each project and reap the long-term benefit. This is no small organizational feat.

The composite-task-branch is a mini-codeline or change-line of sorts. It falls short of being a release-line: it still spans multiple change-tasks during its lifetime, but it is shorter-lived and doesn't encompass all the functionality of a release. This is why we refer to it as a subproject-line.

Once again, we have "added another level of integration" to solve our problem. In this case, we just recursively expanded our usual strategy of activity-branches on a codeline to another level of scale, in between the level of a single-activity branch, and release-line or what we might otherwise normally think of as a codeline. We created a subcodeline to fill in the gap between the codeline and the activity-branch. The subcodeline is simply a microcosm of its parent codeline.

This lets us employ frequent incremental integration (Merge Early and Often) on the subcodeline without compromising the integrity of the parent codeline. The project version tree still reflects the hierarchical nature of the composite task and we aren't forced to introduce any weird dependencies or codependencies between the subtask-branches. We do pay the extra costs associated with merging, but merging for sequential subtasks should be trivial, and merging for parallel subtasks will be no more difficult than if we had never created the subcodeline (and might even be less difficult).

Branch per Task (or Branch per Major Task), Merge Early and Often, Codeline Policy, and Codeline Ownership are all used for the subproject-line. The subproject-line may itself be viewed as a recursive form of Branch per Task or Branch per Major Task (or even a fine-grained form of Docking Line). It may also be viewed as a kind of Policy Branch whereby the subproject-line was created due to the need for a codeline policy that is incompatible with its parent codeline (perhaps with regard to its stability/volatility, or its integration rhythm: the mean time between integrations).

C5. Virtual Codeline

Pattern Virtual Codeline
Aliases Floating Label Line, Just-In-Time (JIT) Branching, Branch on Demand
Context You wish to use branches and codelines but one or more of the following is true for your particular situation:
  1. Your VC tool does not support symbolically named branches, and you won't be able to obtain one that does any time soon.
  2. You would like to "optimize out" some of the extra merging associated with branching (especially for files that don't have any concurrent changes to be reconciled against the codeline)
Problem How can use use mnemonic branch names if the VC tool you are stuck with doesn't support them? And how might you eliminate some of the trivial yet frequent merging for files whose contents don't change after they've been merged to the codeline?
  • Branches are good for hierarchically organizing workflow and change-flow into isolated development paths.
  • If your VC tool doesn't support the use of meaningful branch names, it can be very difficult to conceptually keep track of which branches are used for what and of the relationships between branches.
  • When merging a file from a branch or codeline into another codeline, even if there are no concurrent changes to be reckoned with, the contents of the version still needs to be copied to the receiving codeline. This is called a "copy-merge".
  • For large efforts, although copy-merging may be trivial to do, if it needs to be done for lots of files, there may be non-trivial overhead associated with it. Not only does it require extra time, it may require redundant storage and unnecessary network usage (depending on your VC tool).
  • Selecting versions by branch-name can sometimes be less efficient then selecting them by baseline-label. For large projects with lots of files, this can affect the performance of builds, queries, and checkout/checkin operations.
Solution The majority of VC tools support the concept of a "label": a user specified tag attached to one or more revisions. Even if your VC tool doesn't support named branches, there is a good chance it supports labels. Labels are typically used to group together revisions that form a stable configuration of the system or one of its components, or of all the revisions in a logically coherent change-task.

So, implement a "virtual" codeline using a Floating Label! A floating label is a label whose name remains the same but whose definition (the set of files and file versions associated with the label) changes periodically. You will still need to use static labels as well (just as you would with branches) to denote named stable baselevels of the codeline. But the floating label will serve the same purpose as a named branch: a mnemonic selector for the latest version of all files on the codeline. Here's how to do it:

  1. All revisions that should initially participate in a "codeline" or branch are initially tagged with a label having the desired branch name.

  2. To make a change to a virtual codeline, first select an appropriate baselevel on the "codeline" in your workspace. Or select the codeline label itself if using static version selection (if you are using dynamic version selection, you might not want your workspace to be automatically updated with new versions when the floating label definition changes).

  3. When a file needs to be checked out, if no one else has it checked-out, and it is the latest revision on its branch, then just checkout the file without branching. Otherwise, checkout the file onto a branch. This is called "Just-In-Time Branching" or "JIT Branching." It may be easiest to write a script or macro that does this automatically.

  4. Checkin your completed file changes as you normally would. They won't become part of the "virtual codeline" until they are explicitly tagged with the codeline-label.

  5. When the time comes to merge changes back to the virtual codeline, no copy-merging is required. The revisions don't have to come to the codeline, the codeline-label comes to the revisions. Only those files that have genuinely concurrent changes will require merging.

  6. After the merge is complete, create a new baselevel label if that is what you would normally do. Then tag all the new revisions in the change with the codeline-label. Files that had no concurrent modifications during the change are labeled as is (since no copy-merging was necessary), files that required merging will have the codeline-label applied to the newly merged result.
If it is confusing to determine which new revisions to label, you can just relabel the entire "codeline" (but that could be very time consuming for a large project).
  • Allows you to use mnemonic names for your "virtual" codelines and branches.
  • Avoids the overhead of unnecessary copy-merging.
  • Requires additional effort from codeline owner to explicitly redefine the floating codeline-label, applying it to newly integrated revisions.
  • If a single change is large or complex, or if multiple changes are integrated at once, it may be difficult to readily keep track of the new revisions that need to be labeled. Labeling the entire workspace may be undesired or very time consuming for lots of files.
  • You can't use "native" (non-virtual) branches to group activities. You'll have to use labels instead if you need that.
  • Labels don't accommodate the nice hierarchical branch-path names that some VC tools provide (e.g. ClearCase and Perforce). Furthermore, if your VC tool provides nice visual displays of version trees, you forfeit that benefit as well.
  • JIT branching employs file-based "native" branches as a low-level optimization underneath a virtual branch label. For most intents and purposes, the branch label "looks and feels" like a single line of development. But the resulting shape of the native branch-tree may not be fit for human cognition.
  • Assumes that your VC tool supports labels, and that it provides facilities to query what the latest file revision on a branch is, and whether or not the file is currently checked-out by others. This is quite common however (more so than named branching).
  • If lots of file-based branches take place, many files may possess very wide version trees (especially when files are commonly "checkpointed" before committing a change). If left unchecked, this can begin to suffer from some of the performance issues mentioned above; and full-revision names may actually begin to exceed the maximum allowed command-line length for your platform.
  • If the above situation occurs, periodic copy-merges back to a native ancestor branch may be required. But these should be few and far between and can be conveniently scheduled during "low usage" hours.
A virtual codeline needs a Codeline Policy as well as a Codeline Owner just as much (if not more) than a non-virtual line. Often it is beneficial (for performance reasons to decrease build-time) for a virtual codeline to be used for one or more of the branches in a set of Staged Integration Lines or for a Docking Line or Subproject Lines.

C6. Remote Development Line

Pattern Remote Development Line
Aliases Site Development Line
Context You are collaborating with developers at a geographically remote site. The remote developers might be contractors participating in a subcontract agreement with the master-site. It might also be the case that the remote site is using a mirrored repository instead of centralized repository access. Both the local site and the remote site and performing change-tasks that will ultimately be part of the same codeline. But you want changes at the remote site to be verified or validated by someone at the local site before they become part of the master site's local codeline.
Problem How do you organize remote development tasks so that they don't unduly impact the codeline used by the master-site, while still allowing the remote developers to work without unnecessary delays?
  • If the remote site is participating in a subcontract agreement, verifying their changes before integrating them into the codeline may actually be a contractual obligation.
  • If mirrored repositories are used, care must be taken so that conflicting version trees aren't created at each site. For example, if each site does a checkout that creates version 1.5 of a given file, it will be hard to correctly synchronize the repositories if they each have incompatible ideas of what version 1.5 looks like and who made the changes and when. Although work may still occur in parallel, the resulting changes to the names and structure of the version tree at either site will need to be mutually exclusive from the other.
  • You don't want remote changes to compromise the efforts of the local site. Such effort may take even more time than usual to "back out" because of the geographic separation between the two sites (especially if they are in different timezones)
  • You don't want the remote site to be "blocked" any more than necessary when their changes are being verified (especially if you are paying a premium for their efforts, even when they are waiting to hear back from you)
Solution If work on a particular codeline (e.g. a release) is split across multiple sites, then give each remote site its own site-specific codeline while the "main" site uses the primary codeline. The remote sites can continue working on their remote development lines while the master site periodically chooses convenient times to verify remote changes and integrate them back into the primary codeline. The remote sites then resync their remote lines with the primary codeline at appropriate intervals. or they may simply choose to always branch off the primary codeline onto their remote-line for each checkout.

Figure C6a: Remote Development Line for local and remote development sites

An additional possibility would be to have the master-site also use a separate (non-primary) development codeline, and to have all sites (master and remote) integrate to the same primary codeline, under the supervision (or strict control) of the master site. In this case, all sites keep their development lines in sync with the master integration line.

The extra level of integration adds some additional merge overhead, but additional verification/control effort was already required, so some of that would have been necessary anyway.

Since the remote site is a separate entity there is decreased communication between developers at disparate sites. Integration and synchronization is in fact a form of communication between branches and codelines and it too will need to reflect this difference in communication patterns between people at the same site and people across remote sites.

Using a site-release codeline allows the remote site to accumulate changes in the site codeline, which may then "batch up" those changes and allow the master site to incorporate them at their own pace (like a remote Docking Line).

Often, there will be instances of Branch Dictatorship, between the remote sites. Where the remote site is not permitted to create file versions on the primary site's codeline, but must instead create them on the remote site's codeline. This Branch Mastership is little more than a form of Codeline Policy specifically designed to enforce a strict notion of Codeline Ownership for codelines at the primary site, and at each remote development site.

A remote line often requires its own specific Codeline Policy and Owner that are treated differently (or with different status) than non-remote lines. Often the remote line will need to have more Restricted Access than its non-remote counterparts. Or it may behave as a kind of Docking Line for the remote developers pushing their changes to the remote line while the master site periodically pulls in the latest state of the remote-line to the parent integration line in the master repository.

C7. Component Line

Pattern Component Line
Aliases Module Line, Subsystem Line, Product Line
Context Code Ownership is being used to ensure accountability and responsibility for related elements of a configuration component (files, modules, subsystems, etc.). After some time however, it becomes clear that parallel development of the component is necessary. Several fixes may need to happen at the same time, or may need to occur while other feature changes are in progress. The code owner is simply incapable of making all these changes by himself within the requisite time period.
Problem How do you maintain the benefits of code-ownership when you need to allow people other than the code-owner to modify the owner's code?
  • If everybody is responsible for something, than no one is responsible. You still want a single owner to be accountable for the code.
  • If other's can't modify the owner's code, then important features and fixes won't be completed on time and may hold-up a patch or release.
  • Having developers wait for official approval from the code-owner before checking-in changes may still be an unacceptable or unnecessary time delay, especially for critical-path tasks.
Solution Create a new codeline reserved exclusively for development and maintenance of the code-owner's source code. Make the code-owner be the codeline-owner for the components under development on this particular codeline. The code-owner sets the policy for the codeline, deciding when and if changes by others may be made "on-line" or on a separate change-activity branch. The rest of the project will use only stable baselevels of the component-line for integration into releases, or else the code-owner will be responsible for propagating changes from the component-lines into the overall product-line or main development line.

Figure C7a: Two Component Lines that merge back to the development line


Multi-Product Lines (a.k.a. Multi-Project Lines)

This is the same as pattern variant C4.3, Multi-Project Lines.
  • Changes to the owner's code may be made in parallel using multiple developers. This reduces development time for completing changes to the particular component.
  • The added level of integration gives the code-owner final say over what goes into the production version of the component under development on his component-line.
  • Additional time and effort is required by the code-owner to verify, and perhaps even perform, merges into the component-line. However, this effort does not significantly impact others working on the component-line.
  • The additional integration effort may impact the efforts of those waiting for stable versions of the component-line to be included/integrated into the product-line, but no more than they would be if the code-owner had to perform all changes himself, or if developers had to wait for approval from the codeline owner to checkin their changes.
The code-owner will need to be the Codeline Owner for the component-line and adopt an appropriate Codeline Policy. The code-owner will also need to choose from branching and merging patterns such as Branch per Task, Branch per Major Task, MYOC, Docking Line. If a component-line is used in conjunction with a docking-line, or if the component-line itself must be periodically merged into a main development line, then this is an example of Staged Integration Lines.

C8. Platform Line

Pattern Platform Line
Aliases Variant Line, Permanent Variant Branch, Platform Branch
Context You are developing software that will need to execute (and perhaps even build) on multiple platforms or environments. The need to work in the face of varying operating environments may be a new requirement, or an initial one. You have made an honest attempt to handle platform build and execution discrepancies using environment-specific directories and files. However, the nature of this particular project's multi-platform requirements have proven this approach to be unsatisfactory.
Problem How should platform-specific build and execution information be identified, tracked, and controlled for a multi-platform software project?
  • Normally, platform-specific configuration elements (files and directories) with common interfaces and organization are the most appropriate solution. But in this case, this approach has already proved unwieldy.
  • Build and run-time information must be easily separable and discernible for each platform.
  • Platform-specific changes should be able to occur independently from one another without impacting any other platform.
  • There may exist the need to build or execute for more than one platform simultaneously (while the software is already building or running).
Solution For a new platform requirement where no multi-platform needs previously existed, create a new codeline for that platform (a platform-line). If multiple platforms are needed, then a new codeline for each platform. All creation and modification of platform-specific content should take place on the codeline for the given platform. Files that require no special awareness of differing platform requirements can remain on the main (common platform) development line. the platform line should never merge back to the development line while differences in operating platforms are needed in source code or build files.

Initially, it may be sufficient to create only a single platform-line for the first additional platform.

Figure C8a: Permanently diverging codeline for a new OS platform

But, if multiple-platforms are being used, you will probably need to go through the existing codebase and separate out platforms differences into two or more codelines (one for each platform) and maintain a separate primary codeline for platform independent-code.

Figure C8b: Platform Lines sharing a common base subset

In more complex cases, there may be platform families: subsets of platforms with common needs and constraints. In these situations, you may need to create platform-family-lines, in addition to specific platform-lines and a lone common-platform line.

For example, you might have a program that needs to run on multiple varieties of Unix (Solaris, AIX, HP-UX, Linux) and Windows (Windows'95 and Windows/NT). The common-platform line will be the primary development line and contain platform independent files and changes. Branched off of that will be the platform-family lines (e.g., Unix and Windows) containing files and changes common to all platforms in the family. Finally, branching off from the platform-family lines will be the lone platform lines (e.g., Linux, AIX, Windows'95, etc.) for files and changes specific to that platform alone.

  • Platform-specific files, their revisions and configurations can be easily selected by using the platform-line (and platform-family line if present) for a given platform.
  • Once the desired platform lines have been selected in the workspace, the correct contents and information should be present to properly build and execute the software for the particular platform-variant.
  • Platform-specific files and changes can easily be identified by examining the branch to which a file revision belongs.
  • The use and selection of platform lines make only one platform visible at a time in the developer's workspace. This means less confusion about which platform a set of files or changes is intended for.
  • You won't be able to build for multiple platforms at once. Building for multiple platforms simultaneously will require not only a separate build, but the workspace will first have to be reconfigured for each platform. This is one of the main reasons why using platform-directories is preferable if it can be done.
  • Most version control tools let you select specific revisions of files, but not of directories. They will give you all files in a directory, even if some of those files aren't needed for a given platform. For tools like ClearCase that do version control the contents of directories, branching of directory-contents is more complex than of file-contents, and should not be taken lightly. This is another reason why platform-directories are preferable to platform-lines when possible.
Codelines for components that exist only for a certain platform, or platform family, can be treated like a Component-Line. The use of Codeline-ownership is especially important for platform lines since they rarely converge back to their parent codelines. The codeline/platform owner will have to be on the lookout for files can be merged back to a common platform line or family, as well as for file revisions that need to move from a common platform to a family platform, and from a family platform to a single platform. The Codeline Policy used for platform lines will need to make special mention of when and why to merge to and from platform lines, platform-family lines, and the common platform line.

[back to the table of contents]

Send us your comments!