The Five Orders of Ignorance

December 30th, 2011

It’s not often you read a paper that has something unique and fresh to say about a topic, and expresses it in a clear and concise way.

Somehow, Phillip Armour’s The Five Orders of Ignorance had eluded me, until I found it referenced in another paper.

It really is an interesting point of view on software development.  You can read the paper here.

Armour’s central tenet is software is a mechanism for capturing knowledge. That is, (correct) software is the result of having understood, and formalised our knowledge about the problem we are developing.

Clearly, at each stage of the development process we have different levels of knowledge (or ignorance; the conjugate of knowledge) about our problem.  As we move towards delivery our knowledge increases; and our ignorance decreases – hopefully!

A stratified, or layered, model of ignorance gives a good measure of our progress through the development – in some ways a far superior model than the traditional time/artefact/activity–based approach.

Armour’s levels – or orders – of ignorance are as follows:

Zero Order Ignorance is knowledge; something we know and can articulate (in software)

First Order Ignorance is something we don’t know; a question we need an answer to.

Second Order Ignorance are the things we don’t know we don’t know.  That is, we don’t even know what questions to ask.

Third Order Ignorance is lack of methodology – we don’t have techniques, tools or processes that can identify and illuminate our lack of knowledge.

Fourth Order Ignorance means we don’t even know there are orders of ignorance!

(In many ways Armour’s work is a far more cohesive version of Donald Rumsfeld’s infamous “Known Knowns” speech.)

Armour’s paper crystallised a couple of very important points to me:

Why requirements analysis is so vital.

For nearly the last decade I have been promoting the importance of requirements analysis as a key part of development.  If we understand the problem we are meant to solve – completely and with precision – developing a solution in software is relatively straightforward. 

It’s heartening that most engineers are actually pretty good at developing solutions. But they’re not really very good at understanding problems. When people call me in to help with ‘design issues’ it’s most commonly the case they don’t actually understand their problem properly. Usually, I help their ‘design’ skills by doing detailed requirements analysis with them!

I have found the teams that spend most time performing requirements analysis spend the least time designing and debugging and have the most comprehensive and maintainable solutions.  This is because their software captures the system knowledge efficiently and their code isn’t riddled with what Armour calls ‘unknowledge’ – irrelevant, or incorrect knowledge about the system captured as code (you know, the stuff that leads to ‘features’!)

What process is all about.

Processes are a technique to give you questions, not answers. I think this upsets many developers (and their managers).  Many people want handle-turning solutions: Feed in some customer requirements, crank the handle, and out comes lovely, pristine software. 

Unfortunately, but the world doesn’t work like that.  If it did, we’d all be replaced by machines (that’s been threatened since the Sixties and it hasn’t happened yet. I’m not holding my breath, either.) 

Every software problem is unique and full of those delicious little subtleties that make our jobs as embedded developers so interesting (and yes, you can take ‘interesting’ in the sense of the old Chinese curse!) There is simply no way you can mechanise the behaviours needed to elicit, understand and formalise all the knowledge required to develop a typical embedded system.

Most approaches to software process description assumes software development is a (linear) mechanical process; and the (procedural) transformation of input artefact to output artefact will (somehow) produce working software.  Whilst this approach works for other manufacturing processes it cannot deal with the simple fact that software development is about knowledge capture and, well, we often don’t know what we don’t know!

The best processes are those that consist of a set of goals and a corresponding set of methodologies.  The goals effectively give you an appropriate set of questions that must be answered before you can continue; the answers to those questions will yield pertinent information about the system. 

One could argue the artefacts are supposed to embody the appropriate design questions but engineers are notorious for simply filling in the blanks with banal waffle just so they can move on to the interesting stuff – that is, hacking code (and learning about the system!)

Overcoming Name Clashes in Multiple C++ Interfaces

December 23rd, 2011

Interfaces

One of our key design goals is to reduce coupling between objects and classes. By keeping coupling to a minimum a design is more resilient to change imposed by new feature requests or missing requirements[1].

An Interface represents an abstract service. That is, it is the specification of a set of behaviours (operations) that represent a problem that needs to be solved.

An Interface is more than a set of cohesive operations. The Interface can be thought of as a contract between two objects – the client of the interface and the provider of the interface implementation.

The implementer of the Interface guarantees to fulfil the specifications of the Interface. That is, given that operation pre-conditions are met the implementer will fulfil any behavioural requirements, post-conditions, invariants and quality-of-services requirements.

From the client’s perspective it must conform to the operation specifications and fulfil any pre-conditions required by the Interface. Failure to comply on either side may cause a failure of the software.

Read more »

Effective Testing: The “Swiss Cheese” model

December 20th, 2011

Why do we test?

Software development is a collaborative effort. You bring in input from customers, managers, developers, and QA and synthesize a result. You do this because mistakes in requirements or architecture are expensive, possibly leading to lost sales.

When we develop products we want them to be successful. We want our customers to buy, enjoy, and recommend our products or services. In other words, we want to build quality products. In this case, quality means four inter-related things:

  • Compliance quality– Can we demonstrate that the software fulfils its requirements?
  • Intrinsic quality – is the product robust, reliable, maintainable, etc?
  • Customer-perceived quality – How does the customer react to our product on a sensory, emotional level?
  • Fitness for Purpose– does our product fulfil the stakeholder’s needs?

Which of these types of quality is most important to us depends a lot on our problem domain and the goals and driving forces of our business.

We take considerable pains (but not enough in most cases – but that’s a different argument!) to analyse, design and implement our system to meet our quality goals. Unfortunately, engineers are not perfect. They are under increasing pressure to deliver more features, in less time, and as a consequence they do not have the luxury of time to learn the problem domain, or examine their solutions.

As a consequence engineers make mistakes. These mistakes appear as corruptions in the translation from a specification (what to do) to an implementation. An error can occur wherever we translate a specification to an implementation.

clip_image002

Figure 1 – Typical errors in embedded systems

 

This raises an important question – how to you measure confidence in a product? That is, how do we know the quality of our product is good enough that we can release it for production?

The simple answer is: we test.

Or, perhaps more correctly: we perform validation and verification activities.

A note on definitions

for this article I will use the following meanings for validation and verification. I’m being explicit because every development group I’ve spoken to uses a different word (or combination of them!) to describe the same concepts.

Verification

Verification confirms some predicate about the system. Verification confirms the existence (or non-existence) of, state of, value of, some element of the system’s behaviour or qualities. Put simply, verification asks questions that yield a yes/no answer.

Validation

Validation is focused on assessment of system predicates, rather than their confirmation. In other words, validation asks the question: should the system actually perform a particular behaviour or have a particular quality. Validation assesses the system in terms of good/bad.

Just to confuse matters, I will use the terms validation and verification (V&V) and testing interchangeably.

Introducing the “Swiss Cheese” approach to testing

Testing is often the last resort for finding mistakes. A requirements specification is produced, a design created and implemented. Then, testing is used to verify the design against the requirements and to validation both the design and the requirements. Testing cannot be a perfect technique. Done poorly, many faults will still remain in the system.

image

Figure 2 – The cost of finding – and fixing – a bug

 

This is a well-known graph. It shows the (relative) cost of finding – and fixing – a fault in a system throughout the lifecycle of the project. In simple terms it shows that it can cost orders of magnitude more to find and fix a problem at the end of the development lifecycle than during the early stages; and even more once the project is in service.

A key point to note is: Testing does not improve your software. Testing is not about proving the software has no faults. (This is impossible!) Testing is a quality improvement technique. It provides evidence – in the form of testing metrics – to support the engineers’ claims (that their design works and is valid).

Just testing the software doesn’t make it better:

• Testing just identifies the faults

Fixing the faults makes the software better (although, not always!)

And simply writing more tests won’t make your software better – You must improve your development practices to get better software. The more testing you do the better your product confidence should be – provided you perform good tests!

Closing the holes (improving) testing requires effort and costs money. Moreover, the more sophisticated, rigorous and detailed you make any particular testing technique the more it will cost. In fact, there is a non-linear increase in the costs of applying a technique:

image

Figure 3 – The cost of improving any particular testing technique

 

Trying to ‘perfect’ one technique – for example, black-box unit testing – is not a cost-effective way to gain product confidence. Using multiple, independent techniques (each playing to their own strengths) is far more effective.

The “Swiss Cheese” approach to testing uses multiple techniques, each with a different focus. The techniques are applied with the clear knowledge that no technique is perfect (nor should it be) but the flaws in any one technique do not overlap (much!) with the flaws of another layer.

image

Figure 4 – the Swiss Cheese model

 

The Error-Fault-Failure chain

clip_image010

Figure 5 – The Error-Fault-Failure chain

 

The Error-Fault-Failure chain shows the propagation of mistakes through the development lifecycle. Mistakes made by engineers lead to errors; errors are manifested as (latent) faults – code just waiting to go wrong!; in some cases a fault may lead to the system deviating from its desired behaviour – a failure.

Clearly finding latent faults before they become failures is more effective than just trying to detect failures; and finding errors that lead to latent faults is more effective still.

Dynamic Testing

Dynamic Testing focuses on identifying failures.

Black box testing is concerned with measuring the correctness of the system’s behaviour, performance or other quality. Black box testing is therefore primarily a verification technique.

Black box testing tests specification without knowledge of implementation. The unit under test is stimulated via its interface(s). Black box testing requires a complete, consistent unambiguous specification to test against.

Black box testing typically involves isolating a subset of the system and executing it in isolation in a simulated environment.

White box testing, or Coverage testing is about establishing confidence in the structure of the code. Coverage testing focuses on the rigour of the dynamic testing process.

Coverage testing is not concerned with verification or validation but with ensuring all code has been adequately exercised. The motivation is that code that has not been executed during testing may have faults in it; and it we don’t check that code the faults may manifest themselves when the system is in service.

Dynamic testing involves execution of the software in a (simulated and, later in the develop cycle, live) environment.

clip_image012

Figure 6 – Environments for executing dynamic tests

 

Dynamic testing does not find latent faults effectively. The amount of effort required to find potential failures in your code is extremely high.

Static Testing

Static testing, using Static Analysis tools, look for latent faults in code.

Static Analysis tools is a generic description for tools that aid verification without having to execute software.

There are (currently) more than three dozen tools on the market. Most are commercial tools, but there are many academic-based tools. There are a small number of free- or share-ware tools available, also.

clip_image014

Figure 7 – Categorisation of static analysis tools

 

These tools are nearly always language specific – that is, there are tools for C, C++, Java, etc.

They are commonly based on compiler technology, since the initial stages of static analysis are the same as those required for compiling code.

Pattern Matching tools

Pattern matching tools look for dangerous expressions. .Grep-like tools search for known incorrect patterns. They can be useful for simple latent faults and enforcing style standards in code.

Semantic Analysis tools

Semantic analysis tools are based on compiler (parser) technologies. They use the first stages of the compilation process to build an Abstract Syntax tree. The parse tree in enhanced with additional semantic information. The enhanced Abstract Syntax tree is then evaluated against a rulebase looking for violations.

Symbolic Execution tools

Symbolic execution tools look at data-flow analysis. Symbolic execution tools are less concerned with language level constructs and instead focus on how data is created used and destroyed.

Abstract Interpretation tools

Abstract Interpretation involves treating the code as an abstract mathematical characterisation of its possible behaviour. The model is then executed to examine its behaviour (for faults).

There is a considerable overlap between Abstract Interpretation, Symbolic Execution and Semantic Analysis in most commercial tools.

In practice most commercial tools use a number of techniques, both to provide better analysis and also to minimise the shortcomings of each of the techniques.

 

clip_image016

Figure 8 – There is considerable overlap between commercial SA tools

 

Most tools will have a bias towards one particular technique. When choosing a tool it is prudent to consider where the tool’s bias lies and whether that suits your usage of static analysis techniques. In some cases you may consider buying more than one static analysis tool.

Static Analysis tools focus on the use (or misuse) of programming language. They cannot make any meaningful judgements on design issues – for example cohesion, coupling, encapsulation of abstraction flaws in the system’s design.

Review

Judgements on design, system evaluation, measures of good/bad, and other aspects of validation cannot be automated easily. The most effective technique to find mistakes in these aspects is human review.

In the past reviews have focused on (attempting to) find latent faults in code by detailed inspection. Unfortunately, this is something humans are particularly bad at so it becomes an activity that either 1) takes a long time or 2) is very poorly executed (that is, merely given lip-service).

The strength of human review is the ability of humans to build abstract representations and evaluate them. Thus reviews should focus on the things tools can’t automate – design, modularisation, evaluation, intrinsic quality, etc.

Applying the Swiss Cheese model

In the Swiss Cheese model no technique has to be perfect. Each technique is used for its strengths with the knowledge faults not found by one technique may be caught by another.

Some faults will still get through, though!

clip_image018

Figure 9 – In this Swiss Cheese approach no technique needs to be perfect

 

The aim is to spread our effort across multiple techniques to get the most effective result for the minimum effort.

Consider: If we are not particularly diligent with any particular technique, such that each technique only finds 50% of the mistakes at each level, with three different levels we have the potential to find 87.5% of the mistakes in the system. And this without disproportionate effort in any area. (and yes, I know this is a somewhat optimistic and simplistic scenario)

More appalling user interface design

December 16th, 2011

I came across a wonderfully counter-intuitive piece of user interface design this week.

The room I was in had a sliding shutter (that, for reasons best known to the architects, opened into the main building and not outside).  The two halves of the shutter are controlled independently – that is, you can close one side or the other, or both.  Each shutter is controlled with independent switch panels.

Common sense would suggest a single rocker switch: pushing one side would close the shutter; pushing the other would open it.  The designers, however, had other ideas and selected the implementation below:

Annotated interface

 

Each shutter has a pair of single-action switches – one to close the shutter (the one at the top) and one to open the shutter.

Pressing the top switch (on its right hand side) closes the shutter – as expected.

Pressing the bottom switch on its left hand side (the intuitive action) does nothing.  In fact, you have to press the bottom switch on its right hand side to get it to do anything.

Even better, the switch panel for the right shutter is an exact copy of the the left; so the controls are completely opposite  – the top switch opens the shutter, the bottom switch closes it!

As they say:  good design is like oxygen – you don’t notice it until it’s not there.

Radio Silence

November 9th, 2011

I would like to apologise about the lack of posting in the last couple of months. Unfortunately due to an unprecedented workload both Glennan and myself have been pretty much maxed out, meaning we have neglected the blog. I’m hoping we can remedy this very soon; not due to a lower workloads but as we are recruiting to expand the Technical team here at Feabhas (if this may be of interest please feel free to contact me via LinkedIn or directly).

Thanks for all your great feedback and words of encouragement regarding the blog.

Niall.

Releasing Code

June 20th, 2011

The Release process

The Release process defines the actions required to deliver a software product to an external customer. The external customer is any entity outside the development department. This may be a true (paying) customer, or may be another engineering department, for example Testing or Production.

The Release process is a triggered activity. The trigger events are scheduled as part of project planning. Defining a release is a project milestone which must define

  • What will be released
  • When it will be released
  • Who it will be released to

 

Release process relationships

The Release process is related to, but independent of, the Change Management, Revision Control and Build Processes.

 

image

Figure 21 – Release management is related to, but independent of, the other CM practices

Change Management

Defines the modifications and/or additions to the product, the order in which the changes are incorporated.

Revision Control

Ensures the configuration of the product is controlled and reproducible.

Build Process

Defines how to build the product.

Release Process

Defines the target recipient of the product.

 

Software release stages

During development the product may be released:

  • To different standards
  • To different customers

The different releases comprise a release lifecycle, with each stage representing an improvement in product quality (Figure 22).

 

image

Figure 22 – Each release type represents a different level of quality, and may be released to different customers
 
Development releases

Development releases are internal releases; usually to (independent) test. These releases are unlikely to be ‘feature-complete’; often the release represents one or more work packages (or, in the case of Agile projects, features or ‘sprints’).

It is not expected that these early releases are perfect. It is likely they have only undergone developer testing. A significant number of bugs can be expected in early releases.

Development releases may be produced at high frequency. Weekly releases would be expected at the beginning of development, possibly rising to daily as the project enters a debug phase.

Alpha and Beta

Alpha and Beta releases focus on usage and/or useability testing. Sometimes these are known as Technical Preview releases. The product may be feature-complete (or close) at this stage. Alpha/Beta releases are relatively stable and should contain no (known) critical bugs.

Alpha testing consists of simulated or actual operational testing. It is normally carried out in-house and performed by non-development users, for example internal proxy-customers (staff acting on behalf of the ‘real’ customers).

Beta testing is also operational testing. It is often performed out-house (that is, outside the control of the development organisation). It is carried out by focus groups, or specially selected users. Very often Beta releases are made available free to existing customers to use and test in their own environment.

It is important not to begin Alpha and Beta releases too early in the development cycle. Although allowing users to test the product is potentially very effective a product with many bugs (particularly in areas of key user functionality) can lead to a loss of confidence in the product that is very difficult to recover.

Production-ready releases

The term Release candidate refers to a version with the potential to be a final product. It is essentially ready to release unless fatal bugs emerge during final testing (or possibly Alpha or Beta testing). The product features all designed functions and no known critical bugs.

A Production release is very similar to a Release Candidate ( in fact, it could be argued the Production release is just the final release candidate!). Any last minute bugs fixed. The Production release represents final product quality and features, and it the release sent to Production engineering.

enum ; past, present and future

June 15th, 2011

The enumerated type (enum) is probably one of the simplest and most underused  features of the C and C++ which can make code safer and more readable without compromising performance.

In this posting we shall look at the basic enum from C, how C++ improved on C’s enum, and how C++0X will make them a first class type.

Often I see headers filled with lists of #defines where an enum would be a much better choice. Here is a classic example:

/* adc.h */
#define ADC_Channel_0                               (0x00) 
#define ADC_Channel_1                               (0x01) 
#define ADC_Channel_2                               (0x02) 
#define ADC_Channel_3                               (0x03) 
#define ADC_Channel_4                               (0x04) 
#define ADC_Channel_5                               (0x05) 
#define ADC_Channel_6                               (0x06) 
#define ADC_Channel_7                               (0x07) 
#define ADC_Channel_8                               (0x08) 
#define ADC_Channel_9                               (0x09) 
#define ADC_Channel_10                              (0x0A) 
#define ADC_Channel_11                              (0x0B) 
#define ADC_Channel_12                              (0x0C) 
#define ADC_Channel_13                              (0x0D) 
#define ADC_Channel_14                              (0x0E) 
#define ADC_Channel_15                              (0x0F) 

which probably would be better re-written as:

enum ADC_Channel_no {
	ADC_Channel_0,
	ADC_Channel_1,
	ADC_Channel_2,
	ADC_Channel_3,
	ADC_Channel_4,
	ADC_Channel_5,
	ADC_Channel_6,
	ADC_Channel_7,
	ADC_Channel_8,
	ADC_Channel_9,
	ADC_Channel_10,
	ADC_Channel_11,
	ADC_Channel_12,
	ADC_Channel_13,
	ADC_Channel_14,
	ADC_Channel_15
};

Before getting onto the advantages and disadvantages of enum’s, let’s have a quick review.

Read more »

Change Management

June 13th, 2011

Change Management is concerned with the proposal, selection and scheduling of changes during the lifecycle of a project.

Change Management is interlinked with, but separate to, Revision Control.

Change Management is the core to controlling your development processes. Without effective Change Management the management of your project is subject to slavish adherence to a (fixed, and pre-determined) project plan, with no mechanism for dealing with inevitable changes in requirements, design, implementation or testing.

It is no surprise that Change Management is at the heart of so many Agile process, such as SCRUM.

Change Request

The core of Change Management is the Change Request (often abbreviated simply as CR) A Change Request has many different names, all meaning the same thing:

  • Change Note (CN)
  • Engineering Change (Order)
  • Engineering Change Request (ECR)
  • Action Request (AR)
  • Request For Change (RFC)

Essentially, a Change Request is a call for an adjustment to a system. Change requests typically originate from one of five sources (Dennis, Wixom, & Tegarden, 2002):

  • Bugs that must be fixed
  • System enhancement requests from users
  • Events in the development of other systems
  • Changes in underlying structure and or standards
  • Demands from senior management

 

The CR Artefact

A CR is a project artefact – that is, it is a entity that is created, worked on, stored and audited, just like every other artefact in the system. The CR represents the lifecycle of a change. As such it has a different lifecycle to other artefacts.

As an artefact the CR may (in fact, should) also be held under revision control.

The CR lifecycle is shown in Figure 19. There are three main parts to the lifecycle.

 

image

Figure 19 – The Change Request is an artefact with its own unique lifecycle

 
Opening the CR

Creating a CR records that some change to the system is requested; it does imply that the work will be performed. Once created the change must be reviewed before it can be worked on. The review is performed by the Change Control Board (CCB). The CCB consists of stakeholders who will be affected by the change, and those who can decide whether the change is worth doing. At the minimum this will be the Project Manager or Team Leader; but may include a multi-disciplinary group including engineering, senior management, marketing, customer support, etc.

The CR must be assessed for impact to the project. This work should ideally be done by the CR submitter. Points considered during the assessment of a change request include:

  • Technical feasibility
  • Timescales
  • Customer expectation
  • Resource
  • Quality
  • etc.

The CR may be Accepted (Opened for working), Rejected (Infeasible or invalid) or Deferred (delayed; therefore inducing technical debt to the project)

Open CRs

Once opened project artefacts can be modified. Each artefact follows its own Configuration Item lifecycle (Figure 20). The CR records artefacts modified. Each artefact records the changes made in support of the CR.

 

image

Figure 20 – Each artefact modified under the Change Request follows its own change lifecycle
 
Including the change

The completed change should be reviewed again by the CCB. The purpose of the review is to assess whether the change is valid – That is, do the modifications made to the system correctly addresses the change requested? An invalid change will be rejected for rework.

Once accepted the change can be integrated into the product.

 

Change Management is often overlooked in CM. Change Management controls precisely what is going to change in the project and when. Without Change Management a project is running on ad hoc and unrecorded decisions by the development team or project manager and runs a serious risk of heading out of control.  Although the Change Management presented here involves project artefacts (CRs) many Agile processes adopt similar principles using techniques such as Product Backlogs and Feature Lists (SCRUM), which are organised by customer priority. These mechanisms are, in effect, simple Change Management processes.

Baselines and Branching

June 6th, 2011

A baseline is an identified set of files and directories in which there is one and only one version of each file and directory.

A baseline identifies one particular configuration of the software (or a subset thereof)

The baseline represents a fixed point in the development; that may be recreated as required.

Specifying a Baseline

A baseline defines a set of files, each at a particular version. These need not be the latest (most recent) version. A baseline label uniquely identifies the configuration. Files may belong to one or more baselines.

image

Figure 12 – A baseline defines a set of files, each at a particular version.

 

In the example of Figure 12 baseline BL1.0 is the first baseline recorded. It consists of seven artefacts, each at a unique revision number. For this example, assume that BL1 records the most recent versions of each artefact. As development progresses each artefact is modified as required (that is, some artefact are modified, some are not). At some time later another baseline is taken – BL2.0. In this case BL2.0 records the current latest revisions of each file. Notice that artefact F is unchanged, so F v1.0 is included in both baseline BL1.0 and BL2.0.

In general each successive baseline contains more recent versions of files (but not always).

When to use baselines

Baselines are a key tool in managing and auditing the state of a project. Baselines should be created prior to any significant project activity:

Development

Baselines provide a ‘working’ point in the project’s configuration. Recording a baseline prior to making a major change to the system allows the development to start from a known working point and, in the event of something going wrong, to ‘roll-back’ to that working configuration.

Baselines should be made prior to starting any new package of work (as evidence of project progress); and new feature development; prior to changing or upgrading any tools; etc.

Release

A baseline records the complete configuration of the product that is being distributed from the development department (whether that is an external customer or just the test department).

Audit

Baselines provide process evidence for audits and also time-stamped evidence of the project’s progress (for example, starting a particular work package)

 

Baseline of baselines

In larger, more complex systems, we may choose to manage the system complexity using a ‘Components’ approach. Each ‘component’ represents some aspect of system functionality – for example a subsystem. Using this approach each component of the system has its own (unique) baselines, independent of any other component (Figure 13).

image

Figure 13 – each component of the system has its own unique set of baselines

Note, not shown in this example is the fact that components may share artefacts. For example, both component A and component B may share a common artefact H; with each component using a different revision.

image

Figure 14 – A complete system constructed from a  ‘baseline of baselines’

The (complete) product’s baselines are constructed from (unique) combinations of the component’s baselines (Figure 14). This method is known as a ‘Baseline of baselines.’

 

Branch Patterns

Branching is the (apparent) duplication of an artefact, or set of artefacts, so that they can be developed independently of the main development activity. Branching is a facility of all revision control systems. RCS systems incorporate mechanisms (such as lazy copying) to avoid the potentially massive overhead of copying artefacts between branches. Branches allow parallel development, which is essential in all but the most simple of software developments.

Conceptually, the artefacts that make up a product or system form the main branch or trunk of the development. The trunk represents the main line of development for the product. Ideally, the trunk represents the most recent (working) configuration of the project. Branches represent alternative paths of development. Motivations for branching include:

  • Maintenance of released products
  • Customer specific additions or modifications
  • New development work
  • Research and development projects

Note, with branching the unique identifier of an artefact must be extended to include the artefact’s branch. Thus artefact MyDoc v1.1 will be extended to be (something like) \main\MyDoc v1.0, which will be different to \main\branch1\MyDoc v1.0. In this case \main identifies the trunk branch and \main\branch1 identifies the first branch from the trunk branch.

Uncontrolled branching can lead to major administrative issues (many companies have a RCS administrator simply to keep the repository ‘healthy’)

The branching patterns presented below are a systematic approach to version tree usage. They are design to reduce the complexity of repository branch management and allow effective project management.

 

Sequential

The Sequential branching pattern (Figure 15) is the simplest model – in that it contains no branching! In essence, it is a ‘pseudo-branching’ pattern.

All development is performed on the trunk branch. All development is linear; no parallel development can be supported. This pattern requires, and enforces mutually exclusive changes to artefacts. By default, this is the pattern followed by all artefacts.

 

image

Figure 15 – The ‘pseudo-branching’ pattern, Sequential.  There is no branching!

The Sequential pattern is fine for projects where there is no parallel development required and the current release always has the most up-to-date developments. In general, this restricts the pattern’s use to simpler projects.

 

Off-Shoot

The Off-Shoot branching pattern allows a legacy version (the mainline development) to have derivative and independent versions created.

 

image

Figure 16 – The off-shoot branching pattern

The off-shoot branch can be created retrospectively – that is, development on the trunk branch could be well advanced before the off-shoot branch is created. The off-shoot is never merged into another branch. Off-shoots may also have their own off-shoots.

Note that the main trunk is baselined before the offshoot is created.

 

Loop

The Loop branch pattern is a variation on the Off-Shoot pattern. The Loop pattern allows basic managed development.

 

image

Figure 17 – The Loop branching pattern

In this example the trunk branch represents the release branch. That is, all releases are from the main branch. New development is performed in an Off-Shoot branch (called \Dev BL 2.0 in the example since it represents the new code that will appear in baseline 2.0 of the product). The new development work is independent of any release code.

Once development has been completed in the Off-Shoot branch the Loop is closed by merging the off-shoot back into its parent branch. Note that baselines in the main branch only represent completed development activities.

 

Integration

The Integration pattern extends the Loop pattern model to allow managed and concurrent development.

 

image

Figure 18 – the Integration branching pattern

As above, the main trunk branch represents the release branch for the code; no development is performed on the main branch.

For a new feature a new branch is created (\Integration). The new development consists of three work packages. In this example Work Package 1 (\WBS1) must be completed before Work Package 3 (\WBS3) can be started.

Within the \Integration branch two new Loops are started (\WBS1and \WBS2). The work on both packages continues independently and in parallel. When Work Package 1 is complete it is merged into the \Integration branch. At this point Work Package 3 can be started, so a new branch is created from the \Integration branch (after baselining the \Integration branch – not shown). Some time later Work Package 2 is completed and merged into the \Integration branch. Finally Work Package 3 is complete and merged. To complete development the \Integration branch is merged back into the mainline development.

The Integration pattern builds on the smaller patterns to form a comprehensive branch/merge strategy. The strength of this pattern is the RCS archive reflects the development project plan.

Configuration Items

May 30th, 2011

A Configuration Item (sometimes referred to as a Computer System Configuration Item, or CSCI) is an artefact (hardware and/or software) that has an end-user purpose – that is, it contributes, in some way, towards the attributes of a system or product, or the development processes followed to produce the system or product. A Configuration Item (CI) is an artefact that is treated as a self-contained unit for the purposes of identification and change control. For example:

  • Specifications
  • Design models
  • Source code
  • Make files
  • etc.

Configuration Item identification

Configuration identification is the process of identifying the attributes and procedures that define every aspect of a configuration item.

Configuration identification performs three distinct roles:

Uniquely identifying each Configuration Item.

CIs are the artefacts to be controlled under Configuration Management. Each CI must be uniquely identified by name, version (revision) and location (on the file system).

Establishing a change policy

The CI’s change policy defines how the artefact is revision controlled; and whether that control changes during the lifetime of the project.

Establishing a review policy

Ideally, every artefact should be reviewed. Configuration identification establishes how the artefact will be reviewed and when it will be reviewed.

Configuration Identification must be performed prior to establishing any revision control system. All CI attributes and policies must be recorded in the project’s CM plan.

Configuration lifecycles

Configuration lifecycles define how an artifact is checked into and out of the revision control system. The configuration lifecycle defines the ‘life’ of one particular change, as it applies to that artifact (c.f. Change Management, below). The lifecycle is typically shown as a state transition diagram.

For any real project of any complexity a number of lifecycles will be required. Also note, an artefact’s lifecycle may change through the lifetime of the project. This is defined by the artefact’s change policy.

Listed below are a number of common configuration lifecycles.

‘Archive’ lifecycle

Archive artefacts are configuration items that are simply stored in the CM system. Archive artefacts are never modified once they exist. For example, the binary (download) file for a particular release.

 

image

Figure 8 – The Archive lifecycle
 
‘Basic CI’ lifecycle

The ‘Basic’ CI lifecycle (Figure 9) is for artefacts that must be archive and may be modified over time. For example, the Compiler used on the project may be updated over the course of the project’s lifetime.

image

Figure 9 – the Basic lifecycle

In addition, this lifecycle is used for artefacts that have not yet been released (see Release Management, below). Such items should be stored in the project’s RCS repository (for completeness) and should have their modification history recorded but these items do not need to be subject to stringent review or quality checks before being checked in.

‘Reviewed CI’ lifecycle

A ‘Reviewed’ Configuration Item must pass a review (peer or formal) before it can be checked back in (Figure 10). For example, a Requirements Specification.

This lifecycle is sometimes known as a Document lifecycle.

image

Figure 10 – The Reviewed CI (or Document) lifecycle

Any artefact that has been released from development, or originates from outside the development department should be subject to this lifecycle.

‘Software CI’ lifecycle

The Software CI lifecycle (Figure 11) is an extension to the ‘Reviewed CI’ lifecycle (above). In addition to being reviewed, a software CI should also pass Static Analysis testing; and pass Unit (component) tests; before being checked in.

 

image

Figure 11 – The software item lifecycle.

The Software CI lifecycle can be implemented in environments that demand very high software quality, for example safety-critical applications.

 

To get the most out of your Revision Control System each project artefact must be defined, with its usage, review policy and, perhaps most importantly, its change policy. This information gives the developer the information needed when an artefact has to change – what is required and who must be involved. Having effective configuration identification in place also ensures that the project’s artefacts retain their quality (at whatever level that quality is set)