Brad Appleton | <brad@bradapp.net> | Motorola Network Solutions Group |
Stephen P. Berczuk | <berczuk@acm.org> | NetSuite Development |
Ralph Cabrera | <cabrerar@agcs.com> | AG Communication Systems |
Robert Orenstein | <rlo@perforce.com> | Perforce Software |
Send us your comments! |
|
|
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. |
Forces |
|
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.
|
Resulting Context |
|
Related Patterns |
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. |
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? |
Forces |
|
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).
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. |
Variants | |
C2.1 |
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.
|
C2.2 |
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. |
C2.3 |
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). |
Resulting Context |
|
Related Patterns |
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]. |
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? |
Forces |
|
Solution |
For each planned release (major, minor, and patches), use a separate
codeline to organize efforts focused on each individual release-effort.
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). |
Variants | |
C3.1 |
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).
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. |
Resulting Context |
|
Related Patterns |
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). |
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? |
Forces |
We could just have later tasks refer to the branches for their predecessor tasks. But this has a few problems of its own:
|
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.
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. |
Variants | |
C4.1 |
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). |
C4.2 |
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. |
C4.3 |
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. |
Resulting Context |
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). |
Related Patterns |
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). |
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:
|
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? |
Forces |
|
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:
|
Resulting Context |
|
Related Patterns |
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. |
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? |
Forces |
|
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.
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. |
Resulting Context |
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. |
Related Patterns |
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. |
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? | |
Forces |
| |
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.
| |
Variants | ||
C7.1 |
Multi-Product Lines (a.k.a. Multi-Project Lines) | This is the same as pattern variant C4.3, Multi-Project Lines. |
Resulting Context |
| |
Related Patterns |
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. |
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? |
Forces |
|
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.
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.
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. |
Resulting Context |
|
Related Patterns |
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. |