Appears in *The Computer Journal*,
Vol.40.1 (1997):59-61, ISSN 0010-4620.

B is a formal method in the same vein as Z and VDM. Such methods are often referred to as 'model oriented' since they describe system behaviour using an explicit model of the system state along with operations on the state. The B method was developed mostly by Jean-Raymond Abrial and was influenced by his work on the development of Z. Apart from some notational differences, what distinguishes B from Z is that B aims to cover a broader range of the development cycle from specification to coding, whereas Z is perhaps more suited to earlier stages of the development cycle. To quote from the introduction, 'B is a method for specifying, designing and coding software systems'. The method makes use of formal refinement to ensure that the properties of an initial specification are preserved by successive stages in the development of a system and thus that the final implementation is formally correct with respect to the specification.

Evolution of the B method started in the early 1980s and
it has been applied successfully on several industrial projects, most notably
on part of the control system for the Paris Metro. Commercial tools supporting
the method are available in the form of the *B-Toolkit* from B-Core,
UK, and *Atelier B* from Digilog, France. However, up until last year,
there wasn't a single textbook available on the method. Around the same
time that Abrial's book was published, two books on B were published separately
by Kevin Lano of Imperial College and John Wordsworth of IBM UK Laboratories.
Without denigrating either of the other two, it is fair to say that Abrial's
book is by far the most comprehensive. It also has the advantage of having
been written by the method's master. Prior to the publication of these
books, the only source of information on B was the training material supplied
with the B tools and a small number of conference papers. This material
left a lot of important questions unanswered, relating to both the theory
underlying the method and its practical application. Fortunately most of
these questions are now answered by Abrial's book.

At just under 800 pages, the book is certainly not intended
to be read straight through from cover to cover. Instead, Abrial provides
several routes through the book to suit different readers depending on
whether their interest is more practical or more theoretical. These suggested
routes are especially important since the theoretical and practical sections
are interspersed throughout the book. This mixing of theory and practice
suits the presentation of the material as the practical material helps
to motivate the theory. The book will also serve as *the* reference
manual for B.

The presentation of the material is very clear and well structured. There is good use of typesetting, especially tables and boxes, to highlight important parts and to consolidate definitions, laws and examples. The mathematical notation is quite standard making it easy to switch backwards and forwards between chapters. However, a more comprehensive index would have been useful, especially if the book is to serve as a reference manual.

The book consists of four parts:

**Part I**(Chapters 1-3, 220 pages) covers the proof system and discrete mathematics.**Part II**(Chapters 4-8, 150 pages) covers the theory and practice of system specification.**Part III**(Chapters 9-10, 130 pages) covers the theory and practice of 'programming-in-the-small'.**Part IV**(Chapters 11-13, 200 pages) covers the theory and practice of 'programming-in-the-large' using refinement and decomposition.

Part 1 could almost serve as a text book in discrete mathematics
on its own. It starts with a presentation of logic and proof. The logic
is an untyped first order logic while the proof style is natural deduction.
There are plenty of example proofs, as well as some good guidance on constructing
proofs. Use of an untyped logic is quite a pragmatic approach, resulting
in a straightforward proof system, though it is contrary to most modern
mechanical theorem provers such as PVS and HOL where typed logic is used.
Although the logic is untyped, the set theory is typed - a set can be
defined syntactically using a predicate, but this definition will only
represent a valid set if it satisfies some type-checking rules. There is
a detailed presentation of set theory, including relations, partial functions,
natural numbers, sequences and trees, with comprehensive lists of laws
for these structures and their operators. There is also a good treatment
of fixed points and induction which is deeper than is usually found in
formal methods books of this nature. Dealing with the application of partial
functions is notoriously difficult in proof systems. The approach Abrial
uses is to say that *f(x)* is defined by a 'choice' operator - but
only when *x* is in the domain of *f.* Thus he provides a partial
definition of function application at the meta level and avoids introducing
a three-valued logic to deal with undefinedness. While this approach works
quite well (the same approach is used in Z), Abrial could have elaborated
on its consequences.

I will consider Parts II, III and IV from a practical point of view firstly, and then consider them from a theoretical point of view.

Chapters 4 and 5 deal with *abstract machines.* An
abstract machine is the basic unit of specification in B and is essentially
a state machine with state variables and operations that act on the state
variables. The description of an abstract machine also contains some types,
constants and invariants. Continuing with the theme of an untyped logic,
the state variables of an abstract machine are declared without types,
but must then be constrained to be of some type by the invariant. Any of
the set-theoretic structures of Part I can be used to describe types. The
operations of an abstract machine are described using the so-called *generalised-substitution
language.* This is an extension of Dijkstra's guarded-command language
and includes specification constructs that allow an operation to be specified
by a predicate describing a before-after relation on the state variables
in the manner of VDM and Z. Those familiar with B will be interested to
note that Abrial has added two new clauses to abstract machines: *abstract
constants* and *concrete variables*. I refer readers to the book
for the significance of these additions and just say they lift some restrictions
in the earlier version of the language that had always seemed unnecessary.

Chapter 7 describes the ways in which abstract machines may be combined to form larger specifications. This support for modular specifications is an important feature of B, and is one that Z, for example, lacks. B provides more than one way of combining machines and prior to reading this book, I hadn't fully appreciated the need for some of them. The book provides some good intuition on why the different ways are important and in which situations they should be used.

Chapter 8 presents three medium-sized case studies in specification using abstract machines. These examples nicely illustrate the use of some of the different mechanisms for combining machines. The third case study, involving a lift control system, contains an interesting example of a 'liveness' argument. Here, in an analysis of the formal specification, a variant argument is used to demonstrate that any request for lift by a user is eventually met. This is not justified in terms of any formal treatment of liveness, but the intuition appears to be sound. Perhaps researchers interested in liveness might like to tackle this example more rigorously using temporal logic.

Part III is concerned with implementation issues, in particular loop correctness, while Part IV is concerned with moving from specifications to designs. Although these parts may appear to be in the wrong order in terms of the development cycle, there is a progression on terms of the formal concepts covered. Chapter 9 develops the standard proof rule for loops. It does this in a way that is more general than usual in textbooks which I found attractive. Chapter 10 presents what is in effect a methodology for developing loop-based algorithms. This involves the use of loop templates which may be instantiated into more specific problems. This approach appears to be very effective and practical since much of the proof effort is already taken care of by the templates. I hadn't expected to see a chapter such as this in the book and I think it would be of interest to anyone who cares about the design of algorithms.

Chapter 11 introduces machine refinement both intuitively
and formally. An abstract machine is refined by making its operations more
algorithmic. The standard technique of data refinement may also be used.
This involves replacing abstract state variables with more concrete variables
that are closer to the data types provided by programming languages. While
the intuition behind refinement is well explained I felt that more guidance
is needed on how to 'invent' data refinements though I accept this could
be difficult to elucidate. The way in which the correctness of refinement
steps is checked in B is through the use of verification-style proof rules.
This contrasts with the approach used in the *refinement calculus*
developed by Back, Morgan, Morris and others where calculational rules
are used to gradually transform specifications into implementations. I
believe it would be quite feasible to combine these two styles in B.

Chapter 12 deals with the relationship between modularity in specifications and modularity in implementations. Abrial shows how the modular structure of a specification may be different to that of an implementation. I found this chapter very illuminating and I feel that the issue receives insufficient attention in the formal methods community. The structured-design community could also learn from Abrial's treatment of the relationship between modularity and machine refinement.

Curiously, Chapter 12 also introduces a construct for general recursion to the generalised-substitution language. The previous literature on B restricted iteration to 'while' loops. However, Abrial's insistence that the use of loops and sequential composition (and now also recursion) be restricted to implementations and not used in specifications remains - a restriction that I don't fully agree with.

Chapter 13 presents two major case studies in specification and design using B. The first deals with the development of a database system and involves several stages of design including the introduction of a file system for data storage. The case study provides a good illustration of the relationship between refinement and modularity. The second major case study deals with the specification and design of a pump controller for a steam boiler. The requirements come from the nuclear power industry and the system is surprisingly complex since it provides a degree of fault tolerance. The case study very nicely illustrates how a formal specification may be synthesised from informal requirements. The case study is also interesting in that Abrial uses machine refinement not just as a design technique, but also as a way of structuring and elaborating the initial specification - another idea that I found attractive. Abrial also attempts to illustrate how the specification can deal with changes to the requirements, but this is not entirely convincing since the modifications in question are quite trivial.

I now turn to some of the more theoretical aspects of
Parts II, III and IV. Abrial uses two levels of semantic definition to
model abstract machines. In Chapter 5, the language used to describe operations
is shown to be an be an extension of the logic. That is, statements in
the language are defined as substitutions that act on predicates, hence
the name 'generalised substitution'. If *S* is a statement and *P*
is a predicate, then *S[P]* represents the predicate that results
from applying substitution *S* to *P*. This approach corresponds
to Dijkstra's weakest-precondition formalism, that is, *[S]P* corresponds
to Dijkstra's *wp(S,P).*

Chapter 6 presents a set-theoretic semantics in which
predicates are modelled as sets of states and statements are modelled as
functions from sets to sets, so-called *set transformers.* The set-transformer
semantics is more rigorous than the substitution semantics since it can
deal with types and higher order concepts such as fixed points and refinement
(the logic is first order, so cannot be used to express '*for all predicates
P, T holds*'). There is a degree of redundancy in having
the two levels of semantics and this decision is not fully justified by
Abrial. I suspect the reason for it is partly historical in that the substitution
semantics appears in previous literature by Abrial, but the set-transformer
model is newer. Also, the previously mentioned tools for B only work with
the substitution semantics so the set-transformer semantics can be seen
as providing a justification for the soundness of the tools. Abrial's two
level semantic approach may be compared with related work by Ralph Back,
for example, who also uses a weakest-precondition style semantics. Rather
than having a two level semantics, Back works with a single level semantics
that uses a typed higher order logic. An advantage of Back's approach is
that it uses a more uniform notation, and indeed, I would say more elegant
notation as I found the notation used in Abrial's set-transformer model
somewhat cumbersome. However, these issues are a matter of personal preference
and are only of concern to those who need to work with the semantics, such
as tool builders, not to those who wish to apply the B method in practice.

The definition of refinement is given in Chapter 11 in terms of the set-transformer semantics. This is equivalent to the definition used by others who work with a weakest-precondition semantics. The definition is higher order but Abrial uses the neat trick of showing that it is equivalent to a first order definition. This is important since he wants practitioners of the method to only have to work with first order logic. I found that Chapters 6 and 11 deal with a lot of previously unanswered questions about the semantics of B.

So what about tool support? I was surprised to find that Abrial doesn't cover the tool support available for B in this book (Atelier B is briefly mentioned in the introduction but the B-Toolkit isn't mentioned at all). Surely the availability of tool support is a major reason for the industrial take up of B. Perhaps one reason for leaving it out is that tool support is likely to evolve more rapidly than the definition of the language and methodology presented in the book.

As I have already made clear, this book covers a broad and coherent range of issues at more or less the right depth. I particularly admire the emphasis it places on proof throughout the book. There is a view that to gain from the use of formal methods, it is sufficient just to use formal specification and not to use proof. But there is also the view that it is ultimately unsatisfactory and wasteful to employ a tool and not use it to its full potential. Abrial's book goes some way towards showing how a formal method can be used to its full potential in a way that is beneficial and practical. I would thoroughly recommend it to anyone interested in the correct design of computer systems.

Michael Butler, University of Southampton, 1997.