To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
Here is a sample of notations that might be useful to people who are considering Z. All are based on the discrete mathematics taught in Chapters 8 to 11.
In addition to Z itself, the Z family includes several object-oriented dialects including Object-Z, MooZ, OOZE, and Z++ [Stepney, Barden, and Cooper, 1992a; Stepney et al., 1992b; Lano and Haughton, 1993]. Some early contributors to Z went on to create a development method called B that includes a specification language and a tool for automating calculations and proofs [Lano and Haughton, 1995].
Of the other formal notations, VDM [Jones, 1990] is most similar to Z. Like Z, VDM is a model-based notation. You model a system by representing its state and a collection of operations that can change its state. VDM lacks the boxed paragraphs of Z and has nothing quite like the Z schema calculus. VDM stands for the Vienna Development Method. The VDM community emphasizes refinement, not just modelling. Z and VDM are compared in Hayes [1992b].
Combinations of conditions that define complex predicates can sometimes be made easier to grasp by presenting them in a two-dimensional tabular format. A particularly rigorous and comprehensive tabular notation was invented by Parnas and others [Parnas, 1994] and has been applied to nuclear reactor shutdown software. Leveson and colleagues invented a tabular notation called AND/OR tables and applied it to an aircraft collision avoidance system [Leveson et al., 1994].
This chapter presents a more realistic model for the graphical user interface we introduced in Chapter 6. It is based on the control console of a real medical device, but the same techniques can be applied to any system where the operator uses a pointing device such as a mouse to select items from on-screen windows and menus, and uses a keyboard to enter information into dialog boxes. Such facilities are provided by many software systems in wide use today, for example the X window system.
A graphical user interface is an example of a state transition system driven by events. This chapter explains how to model event-driven state transition systems in Z, and shows how to illustrate a Z text with a kind of state transition diagram called a statechart. This chapter also shows how to use Z to express designs that are partitioned into units or modules that are largely independent. In Z these units can include both data and the operations that act on it, so they can represent classes in object-oriented programming.
Events
A great advantage of a graphical user interface is that it allows the users to choose operations in whatever order makes the most sense to them, it does not force users through a fixed sequence determined by the designers. All operations are always potentially available, although some operations might have to be disabled at certain times.
This chapter teaches a practical method for writing code from Z specifications that supplements intuition and experience with formal derivation.
The preceding Chapters 26 and 27 on refinement and program derivation show how to get from Z to code by purely formal methods, where each development step is a formula manipulation. As you must have realized, it is rarely necessary to develop an entire system in this completely formal way. The programming problems that arise within a single project usually present a range of difficulty. Large parts of the project may be so routine that there is no need for any formal description other than the code itself. Only a portion requires specification in Z. In this portion, you might refine only a fraction to a detailed design in Z. And in this fraction you might derive and verify only a page or two of code. The rest is so obvious that it can be translated to code by intuition and then verified by inspection.
Nevertheless, you can choose a strategy for implementing Z that you could justify formally by the methods of Chapters 26 and 27 if you were challenged to do so. This chapter presents such a strategy. When you have a formal specification, you can check designs and code rigorously if doubts remain after informal inspection.
The examples in this chapter are in C. They could easily be adapted to other programming languages.
Formal methods are not project management methods, but some programmers fear that using formal methods would impose a burdensome and inflexible way of working. This chapter should dispel that misconception and reassure you that formal methods are compatible with many different development methods and management styles. This chapter discusses dividing projects into stages, learning users' requirements, translating informal requirements to formal specifications, and validating formal specifications.
Work in stages
There is one assumption that underlies all formal methods: A programming project is divided into stages, where each stage produces a product that can be examined, reviewed, and assessed for correctness and other qualities.
Three products that must be produced by almost any programming project are the specification, which describes the behavior of the product; the design, which describes its internal structure; and the code, which is executable and is expressed in some particular programming language. Most projects produce other products as well, such as manuals and other materials for instructing users, assurance evidence such as test plans and test results, and so forth.
Working in stages is a central concept in every systematic software development method. Formal methods add these innovations: express the specification and design (not just the code) in a formal notation, and use formula manipulations (such as calculation and proof) to derive the products and check that they are correct.
Experienced programmers are often skeptical of programming methods that proceed in stages.
Some problems present us with a large collection of facts and rules, but no underlying theory that we can use to design a compact algorithm for calculating a solution. Examples of such problems include medical diagnosis and treatment planning, scheduling jobs in a machine shop, diagnosis and repair of malfunctioning machinery, and determining customers' eligibility for financial credit. In these areas there are no simple first principles from which everything follows; instead, there are a lot of empirical observations and rules gleaned from hard experience or laid down by fiat. Sometimes you can find an acceptable solution by searching for relevant facts and applying the pertinent rules. Rule-based programming mechanizes this style of problem solving.
Rule-based programs are sometimes called expert systems and are said to display artificial intelligence, but they are just computer programs that employ some specialized techniques that have been found useful for certain kinds of problems. If such a program is intended for a serious purpose, it must meet the same standards of quality and correctness required of other programs. How can we tell if a rule-based program has computed the right answer?
Rule-based programs are often evaluated by submitting some sample results to a panel of human experts. This kind of validation can be helpful but it does not provide sufficient coverage to detect every incorrect result nor does it provide any guidance for design and implementation.
Object-oriented programming is a method for creating programs that use a particular kind of model. Object-oriented programming languages such as Smalltalk and C++ can implement these models, but a simpler notation that is independent of any programming language is more useful when you are creating and analyzing the models. Z can serve as that notation. You can do object-oriented design in ordinary Z, and there are several Z dialects that are intended to provide better support for object-oriented programming.
The object-oriented model and Z
The data in an object-oriented program are encapsulated in record-like data structures called objects. Objects belong to types called classes. You change or examine the data in an object, called its attributes or instance variables, by invoking one of the methods defined for the object's class.
Z is a good match to this object-oriented model. A Z state schema together with the operation schemas on that state define a class. The state variables in the state schema are the attributes or instance variables of that class; the operation schemas are the methods. Bindings, which are instances of the state schema type, are objects, which are instances of the class.
The cyclotron control sytem model in Chapter 23 can be considered an object-oriented design in this sense. All the data are encapsulated in objects, and the only way to read or change any data is by invoking a method.
We have already learned how Z can be used to describe data structures. Sometimes the solution to a problem is just a data structure that has some particular properties. In that case, the description of the data structure is the central element in the whole specification. A well-known example is the problem of the eight queens.
Many books on programming show how to solve the problem of the eight queens (for example, see Wirth [1976]). Here is the problem statement in English:
Eight queens must be placed on a chessboard so that no queen attacks any others. A chessboard is a square grid with eight columns, or files, and eight rows, or ranks. When a queen is placed on a square, it attacks any other queen that sits on the same rank, file, or diagonals.
Figure 18.1 illustrates one solution to the problem.
This is not a problem of great practical significance, but it does illustrate some common difficulties of prose specifications: They usually turn out to be imprecise and incomplete. The English problem statement is usually considered sufficient because “everybody knows what it means.” When we write real specifications, usually everybody does not know what is needed. When we write the program, we can't appeal to visual impressions and intuitions. Could you explain the eight queens problem to somebody who had never seen a chessboard? What if you had to communicate by telephone and couldn't refer to a picture?
Z is a set of conventions for presenting mathematical text, chosen to make it convenient to use simple mathematics to describe computing systems. I say computing systems because Z has been used to model hardware as well as software.
Z is a mature notation. Conceived in the late 1970s, it developed through the 1980s in collaborative projects between Oxford University and industrial partners, including IBM and Inmos (a semiconductor producer). The first Z reference manual to be widely published benefited from this long experience when it finally appeared in 1989. At this writing a draft Z standard (including a formal semantics) is being considered by the American National Standards Institute (ANSI), the British Standards Institute (BSI) and the International Organization for Standardization (ISO). Z has served as the basis for other notations, including several variants adapted for object-oriented programming.
Z is a model-based notation. In Z you usually model a system by representing its state — a collection of state variables and their values — and some operations that can change its state. A model that is characterized by the operations it describes is called an abstract data type (ADT). This modelling style is a good match to imperative, procedural programming languages that provide a rich collection of data types, and also to some physical systems (such as digital electronics) that include storage elements. Z is also a natural fit to object-oriented programming.