This article suggests that lawyers can make an effective
contribution to reducing the scale and extent of software failures witnessed in
recent years. It identifies the unique characteristics of software which
distinguish it in a contractual context and from drawing particular attention
to the area of bugs and defects, the position is advanced
that there is an undeniable need for the special nature of software to be
recognised, respected and accommodated within our legal framework.

Software failures cost the UK economy millions of pounds
each year. The financial cost has reached critical proportions and the extent
of damaging impact is equally far-reaching. As examples, in 2010 in the public
sector, the failed IT system for the fire and rescue service reportedly wasted
£469 million and the software problems experienced by several financial
institutions in the summer of 2012 hit millions of customers (BBC News, 2011
&2012). The consequences of software failure can flow into many areas for
consideration, including for example, safety critical systems which can also be
tested under the law of negligence, but here the focus is how contract law can
be used to reduce the potential for failure and limit the impact of failure
should it occur. The law applicable to contracts for the writing of software
has given rise to a host of questions relating to, for example,
misrepresentation, collateral contracts, warranties and exclusion clauses
(Napier, 1992) and although representing some of the first challenges to be
posed, many issues of contractual liability in this context remain unanswered
and unresolved. In contrast, the panorama of computer law has witnessed notable
changes in matters of criminal liability including moves to computer specific
legislation; developments which have not been matched in contract law. This
article advocates that, at a minimum, a thorough consideration of the extent to
which a computer specific response could be offered in contract law is long
overdue and would be highly useful. Lawyers have a responsibility to question
how contract law can develop to meet the needs of the digital age, and thereby
act in a preventive and constructive manner, to avoid the potential ‘crisis’
which software and legal professionals warn could ensue, if the legal system
does not meet the challenges posed (Thompson, 2007). The considerable
significance of computer systems for the UK economy demands consideration of
appropriate measures to promote and facilitate a healthy and effective legal
environment within which contractual rights and responsibilities in a computing
context can operate – and here lies the contribution which lawyers can make to
reduce the potential scale of failures in the future.

Software failures will inevitably occur but effective
contractual planning and the accurate definition of contractual obligations may
limit such failure occurring, or, if and when such failure does occur, should
ensure the parties can more readily identify how the error is to be corrected
and moreover, which party will bear the cost of correction. An understanding of
something of the nature of software is essential and one of the aims of this
article is to offer an accessible understanding of the nature of software,
identifying the features and characteristics which distinguish it in a
contractual context. Such an understanding brings with it the recognition that
software places particular demands on contracting – software does have special
requirements which need to be recognised and accommodated for, if the legal
framework through which issues and disputes relating to its supply and
development is to be more effective in the future. Building up from this
context, and drawing on the example of nomenclature of software bugs and
defects, the position is advanced that there is now an undeniable need for the
special nature of software to be recognised and respected within our legal
framework.

Distinctions can and indeed should be noted when discussing
software. The format in which software is manifested; the purpose for which
software is created and; the main functions of the software, each pose
different demands when questioning the appropriate treatment of software at
law. For example, software can be expressed in source code, in object code and
as machine-readable and human-readable forms of each. A software supplier will
be mindful of the difference between source code and object code and their
respective readability when deciding the circumstances under which, if at all,
either or both sets of code will be released to the customer. The form of the
developed software can range from standard software which is likely to be mass
marketed, through varying degrees of customisation to the highest level of
customisation in the form of specialist bespoke programs created specifically
to meet the requirements of an individual customer. The main functions of
software draw distinctions between system software, responsible for organising
the way in which the hardware functions; and application software, responsible
for contributing to meeting the end-users eventual needs. An agreement
governing the supply of a computing system can be required to incorporate
contractual arrangements which can overlap and interconnect, operating in
several layers and covering a multitude of different elements. Although certain
scenarios will pose greater challenges for the law than others, whatever the
format, purpose or functionality, and the extent and complexity of these, this
is underpinned in all circumstances by the fact that software has unique
characteristics. Logic suggests that unique characteristics of software produce
special features in software contracts and in the course of the entire
discussion these particular aspects will be brought to light, as will the need
for them to be recognised if the law is to deal appropriately with software
contracts.

The point has been made that software possesses unique
characteristics which in turn place unique demands on software contracting.
Here, the discussion turns to consider four particular features of software:
intangibility, functionality, reliability, and testing for the purposes of
identifying and eradicating bugs, each of which illustrate something of the
nature of software. These features lend further support for the position that
software is special which needs to be borne in mind when negotiating and
contracting for its development and supply and similarly recognised within the
legal framework if the law is to deal appropriately with such contracts.

Although software may be defined as an intangible component,
whether it should be defined as tangible or intangible property in a legal
sense has proved problematic. Consideration of the appropriate classification
has generated different results. In St Albans City & District Council v
International Computers Limited [1996] 4 All ER 481, Sir Iain Glidewell in
the Court of Appeal decided that computer programs, as such, are intangible
instructions and therefore software is intangible property. This contrasts with
the earlier position adopted in the US case of South Central Bell Telephone
Co v Barthelemey 643 So (2d) 1240 (1994) which concluded that software was
tangible, justifying this categorisation on the basis that ‘it is knowledge
recorded in a physical form which has a physical existence, takes up space on
the tape, disc or hard drive, makes physical things happen, and can be
perceived by the senses’ (Hall J). The UK preference was favoured in the New
Zealand case of Erris Promotions Limited and Others v Commissioner of Inland
Revenue [2004] 1 NZLR 811 when the High Court ruled that software
including source code is intangible property. In reaching this decision the
court found in favour of the principle propounded by the defendant that
software is a message and not the medium. Evidence supported the position that
software is a set of instructions and information which cannot be touched and
therefore does not come within the dictionary definitions of tangible [at 826].
Computer source code is simply ideas expressed in a logical form, which is
intellectual property and therefore intangible. Emanating from different
jurisdictions the decisions in these three cases are of course, non-binding
upon each other but nevertheless may be relied upon as persuasive authority
offering guidance of how the law in this context has been interpreted and
applied. At the very least, the decisions draw attention to the fact that
determining whether software should be treated as tangible or intangible is an
issue which continues to test the courts.

This in turn highlights another unresolved issue worthy of
mention: the different approaches to the application of the traditional
distinction between goods and service contracts to software contracts, and the
possible classification of software as goods, services or sui generis. Standards
of performance may be defined expressly by the parties or imposed through terms
implied into their agreement and the question of whether such standards may be
deemed appropriate remains largely unresolved at law, with the debate, as to
whether software should be categorised as goods or services, being a continuing
one. The Council Directive 2011/83/EU of 25 October 2011 on consumer rights,
amending Council Directive 93/13/EEC and Directive 1999/44/EC and repealing
Council Directive 85/577/EEC and Directive 97/7/EEC [2011] OJ L304/64,
(hereafter referred to as the Consumer Rights Directive) which will apply to
off-premises and distance contracts, states that digital content supplied on a
tangible medium, such as a CD or a DVD is to be considered as goods within the
meaning of Directive, whereas contracts for digital content not supplied on a
tangible medium should be classified neither as sales nor as service contracts.
The provisions of the new Consumer Rights Directive [2011] OJ L304/64, due for
implementation by Member States by December 2013, suggest there is breaking
away from the goods/services dichotomy, and yet, there are still likely to be
similar terms implied and therefore their treatment still needs to be
determined. Moreover, classification is relevant not only for determining the
consequences which follow from it, but for the establishment of an appropriate
legal regime which serves to define the base line obligations of the parties.
The more extensive the obligations on the supplier, the more relevant exemption
clauses will become for the purposes of capping liability and thus are vital to
a software supplier in defining the scope of its liability and dealing with
problem management. Although detailed discussion of this aspect is beyond the
scope of this paper it should be noted as an on-going challenge for the legal
framework governing software contracts. Indeed, simply questioning the true
nature of software as goods or services, tangible or intangible, once again
draws attention to the special nature of software. The feature of intangibility
illustrates that while technology continues to develop through diversification
and through convergence, the identification of software as a component which
may be extracted in a metaphorical sense, in order to ascertain its appropriate
treatment within the law, becomes an increasingly challenging task. At a basic
level, software is intangible but with tangible effects; this has consequences
for its legal classification if it is to be fitted into existing
classifications, or alternatively, must be fully taken into account if
proposals for the reform of the law of personal property are to be formulated.
This state of affairs has been neither resolved nor addressed despite being
highlighted for many years and indeed, the same point is true also of the
functionality discussion presented below.

Functionality is a particular feature of software which can
make it distinct from other goods or services, although the extensive
capabilities of modern information technology may encourage software users to
hold a distorted view of its true functionality. Software may be perceived as
being capable of fixing problems which it may not have been specifically
designed for and therefore expected to have capabilities it may not have
(Dilloway, 1987). Given the incredible advancements which have been achieved
through the use of software it is perhaps understandable that its functionality
could be perceived to be omnipotent, however, it must be remembered that such
great power can only be demonstrated within the confines and limits of the
format and setting in which it is designed to operate. The capabilities of
software will undoubtedly be constrained to the scope of the service which it
is designed to perform, and only if a developer is made aware of the function
which a particular program is required to perform, will it be included. As a
very simple example, a program may be designed to record staff members’ names
on a database, but unless there is an instruction to sort those names
alphabetically, this feature may not be included. This is not a failing in the
ability of the software, or in the ability of the developer, but rather the
functionality of the program can only meet that which has been specified. This
illustrates how important it is for the parties to bridge the expectation and
information gaps and also highlights a particular problem with the nature of
software which is the comparatively low level of understanding of how the
software is constructed its users are likely to have. The complex functionality
of computing systems and the software contained therein emphasises the need for
effective communication between the parties with the cautionary reminder that
although the purchaser expects to buy a solution, in real terms the supplier
offers a tool kit (Small, 1997). Recognition of the importance of information
pertaining to functionality and the relevant interoperability of digital
content is made within the Consumer Rights Directive [2011] OJ L304/64, such
that before a consumer is contractually bound, the trader is required to
provide, ‘in a clear and comprehensible manner’, information regarding ‘the
functionality, including applicable technical protection measures’ and ‘any
relevant interoperability of digital content with hardware and software that
the trader is aware of or can reasonably be expected to have been aware of’
(Articles 5 & 6). The potential for extending these requirements is also
noted with the suggestion that future legislative proposal for addressing the
matter may become appropriate (Preamble 19). This is indeed a welcome
recommendation, building on the important changes to strengthen consumer rights
and openly recognising the value of supplying information about functionality
and interoperability in a clear, accessible manner. Effective information
exchange and a high level of communication and co-operation between contracting
parties will promote a higher likelihood of the software meeting the user’s
requirements and moreover, of it being deemed a success.

Reliability is a complex concept and given that the
components in a computing system are interdependent, such that failure in one
component can affect the operation of other components, reliability should be
considered at the system rather than individual component level (Sommerville
2007, p 207). Reliability is defined as ‘the probability of performing the
intended purpose adequately for the period of time intended under the operating
conditions encountered’ (Bott et al 2001, p 286). To determine the reliability
of a system, there are different reliability metrics which may be used and
these include: probability of failure on demand; rate of occurrence of failure;
and mean time to failure and availability.(1)
Although reliability metrics were first devised for hardware components, each
of the metrics named have also been used for specifying software reliability
and availability. However, the reliability of hardware and of software will
need to be measured differently because of the differing nature of the two in
terms of their functionality and the possible failures which may occur.

Hardware reliability is determined statistically and relates
to the failure of individual components to perform their specified function;
its levels can be measured and assessed through mathematical computations (Bott
et al 2001, p 286-88). Failures in hardware may be caused by incorrect
specifications or components which have worn out. Software, on the other hand,
does not wear out and it can continue operating correctly after an incorrect
result has been produced (Sommerville 2007, p 208). The nature of software is
such that it is created for the purpose of producing results and the benefit of
using software to produce results is derived from the reduction in required
resources, such as human, time and financial. This value would be undermined if
those results either required extensive checking or indeed were so rudimentary
that they could be efficiently generated and checked without using a computer.
However, in producing results software may not perform the desired function and
there may be a number of reasons for this, including ambiguity or inaccuracy in
the program specification, or the possibility of a certain combination of
circumstances activating a program error. The introduction and identification
of bugs will affect the reliability of a system. In assessing the reliability
of a system it is very difficult to prescribe a quantitative measurement of
software reliability, although reference to functional specifications may
contribute towards the development of more robust software. Robustness is a ‘measure
of the ability of a system to recover from error corrections, whether generated
externally or internally. [There can be] a relationship between robustness and
reliability but the two are distinct measures; a system never called upon to
recover from error conditions may be reliable without being robust; a highly
robust system that recovers and continues to operate despite numerous error
conditions may still be regarded as unreliable in that it fails to provide
essential services in a timely fashion on demand’ (Dictionary of Computing,
2008 at p 456).

Therefore although a statistical determination or calculation
of software reliability is highly difficult to achieve, there are methods by
which the reliability of software may be increased. Increasing the robustness
of the software may in turn improve the reliability of the software, or in
addition, improvements may also be achieved by referring to a technical
specification including, for example, details of the functions required and the
circumstances under which they would need to operate. Indeed, the financial
consequences of improving reliability may be substantial and should not be
underestimated or overlooked. A significant way in which reliability can be
improved is by testing and debugging and this aspect of software
characteristics is considered in the following section.

Testing for the purposes of identifying and eradicating bugs
is essential to promote the success of software. The United States Space
Agency, Curiosity Mars Rover, which landed on Mars in August 2012 and has been
exploring since, involved the use of software which can search for bugs through
code, in this instance two million lines of code, while it is being written,
rather than having to wait until after the project is completed (BBC News
reports 4 Oct 2012 & 5 April 2013). An extract of code (not from the Mars
Rover project!) is offered here to illustrate the challenges and complexities
involved in the development and supply of software. This fragment of code is
designed to compute efficiently the greatest common divisor of two numbers:(2)

Fragment of Code:

int
gcd(int a, int b)¶
{¶

int
tmp;¶
do
{¶
tmp = b;¶

b = a %
b;¶
a =
tmp;¶

}
while (b != 0);¶
return
a;¶

}¶

This code will operate such that: gcd(12, 20) will return 4;
gcd(12, 19) will return 1; and gcd(823642834, 93628374) will return 14. It will
also operate in some pathological cases, for example, gcd(0, 100) will return
100, as 0 is considered an exact number of any multiple. However, if a zero is
passed in as the second operand rather than the first, then the program will
attempt to divide by zero (the expression in the code ‘a % b’ represents a
division). If an attempt was made to compute gcd(100, 0) using the above
algorithm, it would result in the program crashing. Although the function is
careful not to set b to zero itself, and then divide by it, it does not allow
for the possibility that the value of b provided might already have been zero.
This could be fixed by moving the test (b != 0) to the top of the loop rather
than the bottom with the result that this would happen before any division took
place. If this was done, the revised fragment of code would look as follows:

Revised Fragment of
Code:

int
gcd(int a, int b)¶
{¶

int
tmp;¶
while
(b !=0) {¶
tmp = b;¶

b = a % b;¶
a = tmp;¶

}
return a;¶

}¶

This version of the function would be robust against
nonsensical input values, such that gcd(100, 0) would produce the same result
as gcd(0, 100), namely 100. The revised fragment of code therefore has had the
bug removed, which would cause the program in this instance to crash, noting
that not all bugs, in all circumstances, necessarily cause a crash.

If the code is disassembled into object code the potential
and far-reaching scope for software ‘error’ is highlighted further. When the
code of the above function is disassembled into object code it looks as
follows:

First, the version with
the bug:

0:

55

push

%ebp¶

1:

89
e5

mov

%esp,%ebp¶

3:

83 ec 08

sub

$0x8,%esp¶

6:

8b
45 0c

mov

0xc(%ebp),%eax¶

9:

89
45 fc

mov

%eax,0xfffffffc(%ebp)¶

c:

8b
55 08

mov

0x8(%ebp),%edx¶

f:

8d
45 0c

lea

0xc(%ebp),%eax%para;

12:

89
45 f8

mov

%eax,0xfffffff8(%ebp)¶

15:

89
d0

mov

%edx,%eax¶

17:

8b
4d f8

mov

0xfffffff8(%ebp),%ecx¶

1a:

99

cltd¶

1b:

f7
39

idivl

(%ecx)¶

1d:

89
55 0c

mov

%edx,0xc(%ebp)¶

20:

8b
45 fc

mov

0xfffffffc(%ebp),%eax¶

23:

89
45 08

mov

%eax,0x8(%ebp)¶

26:

83
7d 0c 00

cmpl

$0x0,0xc(%ebp)¶

2a:

74
02

je

2e <gcd+0x2e>¶

2c:

eb
d8

jmp

6 <gcd+0x6>¶

2e:

8b
45 08

mov

0x8(%ebp),%eax¶

31:

c9

leave¶

32:

c3

ret¶

Second, the fixed version:

0:

55

push

%ebp

1:

89
e5

mov

%esp,%ebp

3:

83
ec 08

sub

$0x8,%esp¶

6:

83
7d 0c 00

cmpl

$0x0,0xc(%ebp)¶

a:

74
22

je

2e <gcd+0x2e>¶

c:

8b
45 0c

mov

0xc(%ebp),%eax¶

f:

89
45 fc

mov

%eax,0xfffffffc(%ebp)¶

12:

8b
55 08

mov

0x8(%ebp),%edx¶

15:

8d
45 0c

lea

0xc(%ebp),%eax¶

18:

89
45 f8

mov

%eax,0xfffffff8(%ebp)¶

1b:

89
d0

mov

%edx,%eax¶

1d:

8b
4d f8

mov

0xfffffff8(%ebp),%ecx¶

20:

99

cltd¶

21:

f7
39

idivl

(%ecx)¶

23:

89
55 0c

mov

%edx,0xc(%ebp)¶

26:

8b
45 fc

mov

0xfffffffc(%ebp),%eax¶

29:

89
45 08

mov

%eax,0x8(%ebp)¶

2c:

eb
d8

jmp

6 <gcd+0x6>¶

2e:

8b
45 08

mov

0x8(%ebp),%eax¶

31:

c9

leave¶

32:

c3

ret¶

The differences between the first example including the bug
and the second version which includes the fix are as follows:

In the first listing, on the 13th line down, is
the ‘idivl’ instruction which performs the actual division. A further four
lines down is ‘cmpl’ which is a compare instruction, which is responsible for
checking whether the next number the program intends to divide by is zero. As
the compare occurs after the division, this means that the initial division
will happen before any comparison occurs and hence a zero could occur where it
should not be. In contrast, in the fixed version, the ‘cmpl’ has been mo0ved
up to the top of the listing and occurs before the ‘idivl’, so the division
instruction is protected from any unwanted zeros.

This example represents one of the most common types of bug
which causes serious problems in software; it does not show up on every run and
the function works perfectly well in almost all situations. It is only when the
software is used in one particular way that it falls over. Paradoxically, bugs
which cause the program to fail every time are much less problematic: they can
be spotted immediately during initial testing and fixed quickly. A competent
programmer would be able to debug this particular problem quickly, as
experience would have shown that these cases often provoke errors of exactly
this type, and therefore checking correct functioning in extreme or trivial
cases, (e.g. ‘what happens if one of the operands is zero?’) will typically be
carried out. Consequently, this function, if implemented and tested with proper
care and attention, would be unlikely to contain this bug. However, a program
may not be written and tested with due care and attention; or the function may
be part of a much larger function and the programmer may not have the time to
test each piece of it individually. If the test data fed to the entire program
never happened to cause a zero to be passed into the ‘gcd’ function within the
depths of the code, the bug might easily go unnoticed until the program was out
in the field.

Bugs can be reduced by testing and one of the aims of
testing is to detect bugs, remove them by debugging techniques and follow with
a retest to ensure no new bugs have been introduced during the process (Bott et
al 2001, p 292). As the example of code shows, the level of detail required in
lines of code is high, as too is the fact that there are many possible
permutations which may produce an error in software. From reviewing a short
piece of code at a micro level, it is possible to widen out to the broader
perspective and recognise that the greater the functionality of the software
and the more complex the specification, the increased possibility there will be
for errors to be introduced. This will carry with it the increased scope for
system failure, and particularly in the case of the supply of a complex
computing system, the possibilities for failure as influenced by the number of
possible permutations is considerable. A claim that software is without errors
could only be confirmed absolutely by exhaustively testing the system which
even for the most trivial system is unfeasible, not least because of the
impossibly long time it would take. Thus, an important distinguishing feature
of software is that although ‘program testing can be used very convincingly to
show the presence of bugs, [it can] never demonstrate their absence, because
the number of cases one can actually try is absolutely negligible compared with
the possible number of cases’ (Dijkstra 1974, p 608). Although reliability can
be improved through testing, exhaustive testing is impossible, a zero
probability of failure cannot be guaranteed and thus reliability cannot be
absolute. Given the possible permutations that may occur with the production of
software, as the characteristics of intangibility and functionality examined
earlier further attest, the complexity of software is such that although it can
and indeed should be tested, ‘… every piece of software will contain errors
which may not materialise until a particular and perhaps unrepeatable set of
circumstances occurs’ (Lloyd 2004, p 571). Software is not infallible and it is
inevitable that a sizeable software system will contain bugs. Even though
highly complex IT systems may undergo comprehensive and rigorous testing, such
testing can never be complete and for these reasons a supplier cannot
legitimately offer a complete guarantee that software will be bug free.

The impossibility of exhaustive testing has to some extent
been recognised in the courts as judicial opinion towards software has evolved
to demonstrate an increased awareness and understanding of the nature of
software acknowledging its functionality and reliability and the particular
range of issues it presents relating to testing (see further Macdonald 2005).
For example, in the early case of Eurodynamic Systems plc v General
Automation Ltd (unreported, 6 Sept 1988), Steyn J reported that
expert evidence had convincingly shown that it is acceptable and even
unavoidable practice to supply computer programs that contain errors and bugs.
In the subsequent case of Saphena Computing Ltd v Allied Collection Agencies
Ltd [1995] FSR 616 Staughton LJ acknowledged that software may well
have to be tested and modified as necessary in order to pass the acceptance
tests as prescribed in the contract stating ‘… software is not a commodity
which is delivered once, once only, and once and for all, but one which will
necessarily be accompanied by a degree of testing and modification’ (at 652).
In both Eurodynamic and Saphena, it was recognised that software
could be delivered with a bug in it and that not every bug or error should be
categorised as a breach of contract.(3)
Whereas Saphena indicated that ‘it was not reasonable to expect software
to be error-free’ (at 652), the decision in St Albans, raised the
possibility that the presence of errors may constitute a breach of contract.
This is likely to be decided by looking at the number and gravity of the errors
(Warchus 1999, p 119) and the later case of SAM v Hedley [2002] EWHC
2733 also drew a distinction between the type of system supplied, suggesting
that a developed system would present a much stronger justification against
toleration of bugs than a bespoke system.

In SAM Business
Systems Ltd v Hedley & Co Bowsher J stated that he was: ‘… in no doubt
that if a software system is sold as a tried and tested system it should not
have any bugs in it and if there are any bugs they should be treated as
defects’ (para 20). It is respectfully suggested that this approach fails to
recognise the true nature of software and the fact that no software is bug
free, and moreover, that no software can be guaranteed to be bug free. Expert
evidence in the case made reference to a minor bug which was promptly fixed and
the submission was made that this therefore did not constitute a breach. Such
line of reasoning was rejected with the comment that the bug ‘was a breach, but
because promptly fixed there was probably no damage and certainly none proved’
(para 137). The court noted that there was an element of inevitability of bugs
within software but the point was restated that bugs are defects, and
responsibility and expense for rectifying those defects rests with the supplier
(para 166). To fail to distinguish between bugs and defects is a significant
flaw in the legal reasoning of the issues presented by the nature of software
and does not respect the semantic differences which should be noted between the
two terms. The case did concern the supply of ‘tried and tested’ software
however, and therefore it is possible that the law applicable to complex
bespoke IT systems may be more accurately described as the positions laid down
in Eurodynamic, Saphena and St Albans. Nonetheless,
whether bespoke or standard is treated in this manner, there remains a
fundamental problem with Bowsher J’s conclusion which is that it implies all
bugs can be identified. It also fails to recognise that some bugs will never
manifest themselves. Although testing of software systems can, and should be,
comprehensive it is impossible to cover every possible permutation and
therefore to eradicate any potential bug.

A distinction should be
drawn between bugs which are appropriately classified as bugs and which are
sounded in no legal liability (Eurodynamic and Saphena) and bugs
with their status elevated to that of a defect which render the supplier
potentially liable (St Albans) (Stephens 2003, p 23). The inherent
difficulties in determining whether a minor defect may constitute a breach of
contract, which at the most extreme level could entitle the customer to reject
the system, could be alleviated by express terms in the contract. By
incorporating detailed and thorough acceptance tests, the contractual
documentation may serve as a highly effective project management tool and
indeed, the contract can be used as a point of reference for all involved in
the implementation and continual monitoring of the project. If the scope of the
acceptance testing procedure is clearly laid out, everyone involved in the
project should be in a position to know, for example, how the tests are to be
carried out, what is to be done in order to successfully complete the tests,
and what is to be done in the event of failure of any part of the tests
(Atkins, 2005). If the definitions of bugs and defects proposed here are
employed, parties should be aware of the significance of any type of error and
moreover, acceptance tests can contribute towards defining the particular
requirements and functionalities of a system. Particularly in the case of
projects for complex IT systems the parties should be able to negotiate the
areas to be covered by the acceptance tests and thereby jointly contribute
towards determining what standards are to be met. In this respect the parties
will active contribute towards defining the scope of their rights and
responsibilities towards each other. If the law was developed to distinguish
clearly between bugs and defects on the basis of the definitions proposed this
could further assist the parties in achieving contractual certainty.

The status of a
software bug can be considered in respect of identifying what the appropriate
classification of a software bug should be, and also from the perspective of
determining what the appropriate contractual effect of a bug should be. The
example of a fragment of code illustrated the manner and extent to which
software and bugs can be introduced. Whereas the first example of code could be
reported as containing a bug, the second example of code would be described as
the bug having been removed. The scope for introducing a bug is extensive and
the question must be posed - when does a bug constitutes a defect? A
distinction can, and indeed must, be drawn between the two; the distinction can
then translate into the appropriate treatment at law of the two types of
errors.

The word ‘bug’ can be
defined as ‘an error in a program or system’ (Dictionary of Computing 2008, p
61) and here it is proposed that the term should be used to define any error
within the system which generates functionality which is not required or
desired. Thus the term ‘bug’ can be used broadly to define any computation or
action which may be generated by the program and has not been originally
intended for the purpose of the program. Although ordinarily a bug may produce
a negative result, perhaps by failing to do an action required, it is of course
possible that a bug could generate a positive action. All bugs however, should
not be classified as defects. The term ‘defect’ should be reserved for when the
software fails to meet its specified functionality. It is not appropriate for
all bugs to be classed as defects owing to the nature of software and the
possible permutations which can arise through its design and development.
Moreover, to prove that a program is completely correct cannot be achieved or
guaranteed and confirmation of the level of correctness is only acquired
through a negative expression, namely that testing will confirm the presence of
a bug. This emphasises the importance of the specification of a program’s
capabilities and an accurate description of what the program will perform. In
the event that those capabilities are not met it is appropriate to classify the
bug as a defect.

If the definitions
proposed here are applied to the example of the program designed to compute the
greatest common divisor of two numbers, it can be seen that the fact that the
program will not, in the first instance, compute as required with a second
operand of 0, this would fall within the broad classification of bugs. If this
is to be classified as a defect, it would be necessary for this particular
required functionality to be expressed in the program’s specifications and
capabilities. The distinction can be made clearer: if the program was described
as one which computed the greatest common divisor of all integers then the problem
result would be a bug and also a defect, as the program is failing to do that
which it is described as being designed for. If however, the program was
described as one which computed the greatest common divisor of positive
integers, the function could be classed as a bug but should not be classified
as a defect. If the program specification does not prescribe the capabilities
to this level, for example by simply stating that it is a program for computing
the greatest common divisors, the intention of the parties in contracting
should be considered and use of a test such as the officious bystander test (Shirlaw
v Southern Foundries (1926) Ltd [1936] 2 KB 206 at 227) may serve as an
appropriate justification for determining the reasonable expectations of the
parties (see further Steyn 1997).

In practical terms, how
does this translate into consequences for a software supplier? If a bug is
discovered during the acceptance tests it could be corrected by the supplier.
The potential danger is that bugs will be repeatedly found and therefore it is
necessary to set out what bugs will be fixed in order to pass the acceptance
test. If the distinction between bugs and defects is made and adhered to, then
only the bugs which constitute defects represent those which a supplier should
have contractual responsibility to correct. The acceptance testing criteria
should clearly distinguish between the types of errors which could occur, for
example, ‘dividing those which threaten or stop the system functioning from
those which are merely ‘cosmetic’ in effect and can be easily remedied’
(Warchus 1999, p 119). Of importance to a supplier at this stage is that ‘it is
not reasonable for acceptance to be delayed or jeopardized by minor errors
which will not affect the normal operation of the system’ (Warchus 1999, p
119).

If the system has
passed the acceptance tests and bugs are subsequently discovered, the question
arises as to whether the bug constitutes an error which the supplier has no
responsibility to correct, one which the supplier should be allowed time to
correct, perhaps within a warranty provision, or whether the bug constitutes a
breach of contract for which the customer may choose to take action against the
supplier. By distinguishing between bugs and defects at a practical level, it
is possible to determine how this distinction can translate into the
appropriate treatment at law of the two types of errors. In simple terms, the
consequences of acceptance are such that the rights and remedies of the
customer will change: the customer may lose the right to reject and any
available remedies will lie in damages rather than termination (see further
Cranston 1990). The impact of acceptance upon the supplier is that a final
payment may become due and any claim of faults will fall under a warranty
provision and therefore the contractual position of both parties will change.
Here an agreement for software maintenance may be of high relevance to the
parties and particularly when there is a supply of a complex bespoke system, the
parties are likely to have in place a maintenance agreement where for example,
error correction is performed by the supplier in accordance with a cascade of
severity levels and a time-frame for the work to be carried out. This
emphasises another feature specific to software contracts, which is that the
supply of software may not be merely a one-off transaction between the parties
but rather the start of a continuing working relationship.

A study of the nature of software, presented here with
reference to intangibility, functionality, reliability and testing, contributes
to identifying the software specific issues which the law can be called upon to
address. Contract law is indeed challenged by the nature of software and the
application of existing legal principles to this unique provision has met with
varying levels of success. In some instances, the law has been applied on a
best fit basis which has created much uncertainty, and in other judicial
decisions, it is evident that a lack of understanding of the technology
involved has led to the law being applied on an ill-informed basis. This has
not necessarily led to an incorrect or inappropriate application of the law but
the justification for the application is unclear and thus has generated further
uncertainty, rather than promoting certainty, which could be a highly relevant
and legitimate objective of the legal framework (see for example, Hughes &
Bowling 2005). Existing contract law principles are failing to accommodate the
unique characteristics of software and consequently, the effectiveness of the
legal framework to manage software contracts is being undermined by
uncertainty. With implementation of the Consumer Rights Directive due later
this year, this further highlights the fact that although the issues raised are
not new, they do indeed remain of contemporary relevance and significance.

To promote a healthy IT business environment, it is
fundamental that software contracting parties can define the scope of their
rights and responsibilities with a suitable level of certainty and the law
should facilitate this approach. Although there has been recognition in the
courts that software cannot be supplied bug-free, the distinction between bugs
and defects, and when either may give rise to a breach of contract remains
unclear. One approach which could be promoted within the existing legal
framework is to draw a distinction between bugs and defects offering some much
needed clarity in determining when either may give rise to a breach of contract.

If the proposed terminology for bugs and defects is adopted,
reserving the term ‘defect’ for when software fails to meet its specified
functionality, the classifications would translate more readily into recognised
practical consequences for a software supplier and could facilitate a clearer
and more appropriate treatment of the two types at law. Determining this issue
would depend upon the functionality as expressed in the program’s specification
and capabilities, again emphasising the supplier’s responsibility to present
that information in a comprehensive manner, which could further promote the
contract as an effective project management tool. The responsibilities of a
software supplier could extend to promoting active and effective co-operation
between the parties, with corresponding responsibilities of the customer
serving as a necessary balancing mechanism.

It is hoped that with an increased recognition of the unique
characteristics of software, a greater understanding of the issues for specific
consideration by parties when contracting for software will develop. Equipped
with such knowledge, lawyers can raise further awareness amongst clients in
pursuit of effective contract planning and the accurate definition of
contractual obligations; and software failures, although perhaps inevitable,
may be reduced in terms of scale, frequency and damaging impact.

(1)
Probability of failure on demand is the likelihood that the system will fail
when a service request is made. A POFOD of 0.001 means that one out of a
thousand service requests may result in failure. Rate of occurrence of failure
is the frequency of occurrence with which unexpected behaviour is likely to
occur. A ROCOF of 2/100 means that two failures are likely to occur in each 100
operational time units. The mean time to failure and availability is the
average time between observed system failures. An MTTF of 500 means that one
failure can be expected every 500 time units. See further Sommerville 2007, p
208-10.

(2)
The examples reproduced here have been devised with Simon Tatham, professional
and free-software programmer. Other examples of sample software code have been
examined but those presented here are, in the author’s opinion, the most
comprehensive and easy to understand for a non-technical reader. For a more
extensive and challenging list of available sample code, see for example, the
code written in the Lua language, distributed under a liberal licence and which
can be downloaded and used for both academic and commercial purposes free of
charge, available from: http:///www.lua.org

(3)
In Eurodynamic Systems plc v General Automation Limited, (Unreported, 6
September, 1988) - ‘Not every bug or error in a computer programme (sic) can
therefore be categorised as a breach of contract’; and in Saphena Computing
Limited v Allied Collection Agencies Limited [1995] FSR 616 at 652 - ‘it
would not be a breach of contract at all to deliver software in the first
instance with a defect in it’.