










Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
This course introduces the concept of formal specifications in software engineering, exploring their importance, characteristics, and applications. It covers the use of logical theories as formal specifications, building on the logic learned in the first term. The course focuses on state-based specifications using classical logic, as well as class-based formal specifications for object-oriented systems. It then delves into program specifications, including the use of class invariants, pre- and post-conditions of methods, and loop invariants. The course also discusses the refinement process of transforming formal specifications into program specifications, and the role of formal specifications in validating and verifying computer systems. The course emphasizes the benefits of formal specifications for novel, complex, and critical systems, and their utility throughout the software development lifecycle, from modeling to design and verification.
Typology: Study notes
1 / 18
This page cannot be seen from the preview
Don't miss anything!











This part of the course will begin with a general introduction of what formal specifications are, why and when they are useful for the development of (large) computer systems. We will then concentrate on the use of logical theories as formal specifications, building on the logic you have learned during your first term. Much of the notation is borrowed from the Z specification language, for instance the schema notation. It is not the purpose of this course to teach you how to use Z, but rather to learn some of the basic notations common in most formal specifications languages, and see how these notations can be used to write state-based specifications using classical logic. In particular we will define the concepts of state schema and operation schemas.
We will then extend these notations in order to define class-based formal specifications , which are often used to formalise object-oriented systems. We will in this case borrow notations of class schemas and related features from the Object-Z specification language. We’ll then look at a particular case study which will be related to one of your assessed coursework. We will then move towards the implementation stage and introduce concepts of program specifications. We will in particular see how to specify Java classes using class invariants, pre- and post-conditions of methods, and loop invariant. We will see some reasoning techniques for checking the correctness of Java programs with respect to their specifications. The course will then conclude with linking together these two parts (formal and program specifications), showing how formal specifications can be refined and transformed into program specifications.
As mentioned in the previous slide, to deliver X-ray (photon) treatments, a high energy electron beam is generated and flatted by a beam flattener attached to the turntable (i.e. position 2). One of the safety properties of the system is that such a high energy beam should never hit the patient directly. Positions 1 or 3 are then wrong positions of the turntable, when the machine is programmed to deliver an X-ray treatment. Extremely unsafe circumstances would therefore arise when the system is in X-ray mode, delivering a high energy electron beam and the turntable is in one of these wrong positions. Previous versions of Therac-25, called respectively Therac-6 and Therac-20 used only hardware interlocks to guarantee that the turntable and attached equipment were in the correct position before starting any treatment. The software component merely added convenience (e.g. interface) to the existing hardware system. In Therac-25, hardware interlocks were fully substituted by software checks. The software in Therac-25 had, therefore, more responsibility for maintaining safety than its predecessors. BUT software from the previous version systems were used in Therac-25 and some unsafe situations were not detected. As a consequence six accidents occurred of massive overdose and, for some, this resulted in death of the patient. The main failing factors were that Therac-25 was built by taking into account design features and modules of Therac-6 and by re-using some of the software routines developed for Therac-20. However, hidden bugs and problems of these two predecessors had been covered in these previous systems by their hardware interlock mechanisms. This wasn’t the case for Therac-25. The unsafe architecture of Therac-25 and the lack of formal specifications of the software developed for Therac-20 hadn’t therefore revealed existing software bugs, which were aggravated by problems such as quality control, lack of good documentation of previous failures, etc.
Formal notation has a precise formal semantics and reasoning laws, which facilitate precise reasoning about the specifications. Reasoning about the program specification helps develop software that does something of value for the user (i.e. quality software) and that does conform with the specification (i.e. correct software ). In the previous slide, we stated that specifications are precise descriptions of a computer system, which should not be confused with implementations or programming codes. The question is, then, “ what distinguishes specifying from programming ”. Programming and specifications both use formal notations. An implementation is in fact an extremely precise description, just about as precise as you’ll ever get. Specifications are less precise than implementations, as they leave unspecified a lot of implementation details. They are essentially abstract models capturing some views of the system. They can be constructed at different stages of the development process to reflect the way the various views evolve. For instance at a requirements stage they often reflect client and engineer’s perception of the system and they model real-world entities. At design level, they are defined so to model software (virtual) entities, and at the implementation stage, they can be even more detailed so to capture some low-level code detail. Formal specifications come before coding. It is not necessary to execute a formal specification to know its meaning. One of the advantages of formal specifications is therefore to be able to understand what a program will do without running any code in fact, without writing any. This means that we can discover many errors without having to run any test. Specification languages are usually different from programming languages. They need not be executable, and resemble traditional symbolic logic more than any programming language. They can be
more expressive, more concise and easy to understand than a programming language and they usually have less syntactic clutter. But, what most distinguishes programs from formal specifications is that the latter come with a formal semantics and reasoning laws. These laws facilitate an analysis of the system, in the sense of understanding the system without actually running programs. They enable us to simplify formulae, to derive new ones and to determine whether one formula is a consequence of others. This is important because, as we will see later in the course, it makes it possible to guide the implementation and to formally check whether a piece of code correctly implements a specification, i.e. meets its requirements. In this way, you will not need to rely on error to validate programs.
An implementation is there to tell the computer what to do, with a program of execution steps – i.e how the problem is solved. But it does not usually explain what is achieved by those execution steps. The example above is a program describing how to calculate a square root. This program does not have any formal reference to what is calculated – an output whose square root is the input. On the other hand, the formal specification on the left end side of the slide, defines this output together with its properties (e.g. post-condition). We will see examples of these specifications towards the end of the course. In this course we are interested in (large) systems that have to achieve something in the real world, where objects are less well-defined. Specifying “what” the system has to do also means making reference to the real world and incorporating assumptions about it. This is one of the challenging aspects of formal specifications.
Ultimately, what we are interested in software engineering is to have quality software, i.e. software that fits its purpose and that does something of value for the user, as well as correct software, i.e software that respects (satisfies) the specifications. Formal specification brings these two aspects together. It helps achieve quality by facilitating an understanding of the user requirements and therefore helps not to loose sight of user needs. Once a formal specification of a system has been developed, system properties can be defined using the same formal language and checked whether they are met by the specification. This process, known as “ validation ”, guarantees that the model of the system fits its purposes. At the same time, it provides a means for proving that the implemented system satisfies its specified model. Refinements processes are often used to transform formal specifications into program specifications that preserve the same set of system properties and system requirements. Reasoning processes can then be used to analyze whether an implementation of the system would meet its program specifications. This process is known as “ verification ” process, and guarantees that the implemented system is built correctly. Specifications can therefore be used to both validate and verify a (computer) system. It’s the precise semantics and reasoning laws of a formal specification that enable these two tasks to be performed. Users’ needs can be formalized and proved to be satisfied by the specifications of the system. In the same way, program code can be proved to verify the specifications, and therefore to satisfy the user’s requirements.
Formal specifications are particularly useful for novel systems, difficult systems and critical systems. In the case of novel systems, formal specifications facilitate an analysis of the system prior to any implementation. In particular for large systems, it’s not good practice to just plunge ahead and implement the first idea that comes along. In real industrial environments, it cannot be afforded to build several versions of entire systems. Analysis of the specifications are needed instead.
helps to focus on some aspects of the system, by leaving out all the details that are inessential to that aspect. Complex systems might well be described by several specifications, each focusing on a different aspect. This leads to the following use of specification as support for design. Design. In design different approaches can be taken. But in the case of large systems, it might be useful to take a “bottom-up” approach, i.e. to identify building blocks and to assemble them together to obtain the whole system. Specifications can, in this case, be used to describe the behavior of each individual block and enable us to calculate how the entire system would work once the blocks are combined. This is particularly the case for class-based formal specifications, which can indeed be seen as a first definition of the architectural and design of the system in terms of classes and their inter-relationships. Verification. The use of formal specification for verification is quite renown. Verification deals with the final product of the development process and basically consists in constructing proofs, which are convincing demonstrations that the code does what its specification requires. Such proofs use only the specification and a program test. Proving the correctness of the program is better than testing the program. Testing considers only a finite number of cases, while a proof considers all (possibly infinitely many) cases. A language commonly used for writing state-based specifications is the Z language. This contains a lot of special-purpose notation that takes a while to learn, but it also has good notational ideas that we are going to borrow and apply to the standard classical logic. Object-Z is instead an extension of Z that allows the definition of class-based specifications by providing appropriate constructs for specific object- oriented features, such as classes and inheritance.
In this course we will learn some of the main notations of Z and apply them to classical logic. We will then be able to write state-based specifications that look somewhat like Z but without being correct Z. We’ll then look in more detail at part of the Object-Z language and object-oriented features in formal specifications, enough to enable you to write class-based formal specifications of simple real systems. As for the specification of programs we will use mainly classical logic and we will see a (simple) approach for mapping Object-Z specifications into program specifications. Time permitting we will also see a particular formal language for specifying Java programs called JML language which is supported by an automated tool for reasoning about the correctness of Java programs We are going to be using formal logical notations, and it takes some training to be able to do this. It is therefore easy to flatter yourself that merely writing something in formal logic takes cleverness and is a worthwhile thing to do. The reality is otherwise. When we don’t yet understand the underlying problem, this only serves to complicate and obscure it. A good rule is that it is better to understand the important things imprecisely than to understand the unimportant things precisely!