Precondition

Last updated

In computer programming, a precondition is a condition or predicate that must always be true just prior to the execution of some section of code or before an operation in a formal specification.

Contents

If a precondition is violated, the effect of the section of code becomes undefined and thus may or may not carry out its intended work. Preconditions that are missing, insufficient, or not formally proved (or have an incorrect attempted proof), or are not checked statically or dynamically, can give rise to Security problems, particularly in unsafe languages that are not strongly typed.

Often, preconditions are simply included in the documentation of the affected section of code. Preconditions are sometimes tested using guards or assertions within the code itself, and some languages have specific syntactic constructions for doing so.

Example

The factorial function is only defined where its parameter is an integer greater than or equal to zero. So an implementation of the factorial function would have a precondition that its parameter be an integer and that the parameter be greater than or equal to zero. Alternatively the type system of the language may be used to specify that the parameter of the factorial function is a natural number (unsigned integer), which can be formally verified automatically by a compiler's type checker.

In addition where numeric types have a limited range (as they do in most programming languages) the precondition must also specify the maximum value that the parameter may have if overflow is not to occur. (e.g. if an implementation of factorial returns the result in a 64-bit unsigned integer then the parameter must be less than 21 because factorial(21) is larger than the maximum unsigned integer that can be stored in 64 bits). Where the language supports range sub-types (e.g. Ada) such constraints can be automatically verified by the type system. More complex constraints can be formally verified interactively with a proof assistant.

In object-oriented programming

Preconditions in object-oriented software development are an essential part of design by contract. Design by contract also includes notions of postcondition and class invariant.

The precondition for any routine defines any constraints on object state which are necessary for successful execution. From the program developer's viewpoint, this constitutes the routine caller's portion of the contract. The caller then is obliged to ensure that the precondition holds prior to calling the routine. The reward for the caller's effort is expressed in the called routine's postcondition. [1]

Eiffel example

The routine in the following example written in Eiffel takes as an argument an integer which must be a valid value for an hour of the day, i. e., 0 through 23, inclusively. The precondition follows the keyword require. It specifies that the argument must be greater than or equal to zero and less than or equal to 23. The tag "valid_argument:" describes this precondition clause and serves to identify it in case of a runtime precondition violation.

set_hour(a_hour:INTEGER)-- Set `hour' to `a_hour'requirevalid_argument:0<=a_houranda_hour<=23dohour:=a_hourensurehour_set:hour=a_hourend

Preconditions and inheritance

In the presence of inheritance, the routines inherited by descendant classes (subclasses) do so with their preconditions in force. This means that any implementations or redefinitions of inherited routines also have to be written to comply with their inherited contract. Preconditions can be modified in redefined routines, but they may only be weakened. [2] That is, the redefined routine may lessen the obligation of the client, but not increase it.

See also

Related Research Articles

Eiffel is an object-oriented programming language designed by Bertrand Meyer and Eiffel Software. Meyer conceived the language in 1985 with the goal of increasing the reliability of commercial software development; the first version becoming available in 1986. In 2005, Eiffel became an ISO-standardized language.

ML is a functional programming language. It is known for its use of the polymorphic Hindley–Milner type system, which automatically assigns the types of most expressions without requiring explicit type annotations, and ensures type safety – there is a formal proof that a well-typed ML program does not cause runtime type errors. ML provides pattern matching for function arguments, garbage collection, imperative programming, call-by-value and currying. While a general-purpose programming language, ML is used heavily in programming language research and is one of the few languages to be completely specified and verified using formal semantics. Its types and pattern matching make it well-suited and commonly used to operate on other formal languages, such as in compiler writing, automated theorem proving, and formal verification.

Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class declaration to reference via a generic variable another different class without creating full declaration for each of these different classes.

<span class="mw-page-title-main">Design by contract</span> Approach for designing software

Design by contract (DbC), also known as contract programming, programming by contract and design-by-contract programming, is an approach for designing software.

In computer programming, a postcondition is a condition or predicate that must always be true just after the execution of some section of code or after an operation in a formal specification. Postconditions are sometimes tested using assertions within the code itself. Often, postconditions are simply included in the documentation of the affected section of code.

In computer programming, a type system is a logical system comprising a set of rules that assigns a property called a type to every "term". Usually the terms are various constructs of a computer program, such as variables, expressions, functions, or modules. A type system dictates the operations that can be performed on a term. For variables, the type system determines the allowed values of that term. Type systems formalize and enforce the otherwise implicit categories the programmer uses for algebraic data types, data structures, or other components.

In computer programming, specifically when using the imperative programming paradigm, an assertion is a predicate connected to a point in the program, that always should evaluate to true at that point in code execution. Assertions can help a programmer read the code, help a compiler compile it, or help the program detect its own defects.

In computer programming, a parameter or a formal argument is a special kind of variable used in a subroutine to refer to one of the pieces of data provided as input to the subroutine. These pieces of data are the values of the arguments with which the subroutine is going to be called/invoked. An ordered list of parameters is usually included in the definition of a subroutine, so that, each time the subroutine is called, its arguments for that call are evaluated, and the resulting values can be assigned to the corresponding parameters.

<span class="mw-page-title-main">C syntax</span> Set of rules defining correctly structured programs

The syntax of the C programming language is the set of rules governing writing of software in the C language. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development.

In computer programming, specifically object-oriented programming, a class invariant is an invariant used for constraining objects of a class. Methods of the class should preserve the invariant. The class invariant constrains the state stored in the object.

In computer science, a tail call is a subroutine call performed as the final action of a procedure. If the target of a tail is the same subroutine, the subroutine is said to be tail recursive, which is a special case of direct recursion. Tail recursion is particularly useful, and is often easy to optimize in implementations.

The computer programming languages C and Pascal have similar times of origin, influences, and purposes. Both were used to design their own compilers early in their lifetimes. The original Pascal definition appeared in 1969 and a first compiler in 1970. The first version of C appeared in 1972.

<span class="mw-page-title-main">SystemVerilog</span> Hardware description and hardware verification language

SystemVerilog, standardized as IEEE 1800, is a hardware description and hardware verification language used to model, design, simulate, test and implement electronic systems. SystemVerilog is based on Verilog and some extensions, and since 2008, Verilog is now part of the same IEEE standard. It is commonly used in the semiconductor and electronic design industry as an evolution of Verilog.

this, self, and Me are keywords used in some computer programming languages to refer to the object, class, or other entity of which the currently running code is a part. The entity referred to by these keywords thus depends on the execution context. Different programming languages use these keywords in slightly different ways. In languages where a keyword like "this" is mandatory, the keyword is the only way to access data and methods stored in the current object. Where optional, they can disambiguate variables and functions with the same name.

In computer programming, a semipredicate problem occurs when a subroutine intended to return a useful value can fail, but the signalling of failure uses an otherwise valid return value. The problem is that the caller of the subroutine cannot tell what the result means in this case.

This article describes the calling conventions used when programming x86 architecture microprocessors.

This article compares a large number of programming languages by tabulating their data types, their expression, statement, and declaration syntax, and some common operating-system interfaces.

In object-oriented programming, behavioral subtyping is the principle that subclasses should satisfy the expectations of clients accessing subclass objects through references of superclass type, not just as regards syntactic safety but also as regards behavioral correctness. Specifically, properties that clients can prove using the specification of an object's presumed type should hold even though the object is actually a member of a subtype of that type.

Whiley is an experimental programming language that combines features from the functional and imperative paradigms, and supports formal specification through function preconditions, postconditions and loop invariants. The language uses flow-sensitive typing also known as "flow typing."

<span class="mw-page-title-main">Dafny</span> Programming language

Dafny is an imperative and functional compiled language that compiles to other programming languages, such as C#, Java, JavaScript, Go and Python. It supports formal specification through preconditions, postconditions, loop invariants, loop variants, termination specifications and read/write framing specifications. The language combines ideas from the functional and imperative paradigms; it includes support for object-oriented programming. Features include generic classes, dynamic allocation, inductive datatypes and a variation of separation logic known as implicit dynamic frames for reasoning about side effects. Dafny was created by Rustan Leino at Microsoft Research after his previous work on developing ESC/Modula-3, ESC/Java, and Spec#.

References

  1. Meyer, Bertrand, Object-Oriented Software Construction, second edition, Prentice Hall, 1997, p. 342.
  2. Meyer, 1997, pp. 570–573.