Monday, November 22, 2004

Design by contract for Python

Plosch, R., Ch Doppler Laboratory of Software Engineering, Johannes Kepler University of Linz

Software Engineering Conference, 1997. Asia Pacific ... and International Computer Science Conference 1997. APSEC '97 and ICSC '97. Proceedings, Vol., Iss., 2-5 Dec 1997, Pages:213-219

Building an Object-Oriented software class library in a customizable format is one of the main tasks in understanding the OO-Software of a particular application. This is called Design by Contract (DBC). Many of these features are present in static typing languages like Java, C++, Eiffel, etc. But these languages realize DBC only in development phase of the Software development life cycle. To carry out DBC even in analysis and design one has to have a dynamic typed interpreted language such as Python and this paper deals with how to introduce DBC in Python.

The main goal of DBC is to introduce some sort of invariants at different levels of the Object-Oriented Constructs. These levels are the:

(i)      Class level invariants

(ii)    Methods invariants

(iii)    Loop invariants and

(iv)   Check instructions

Lets look what are these invariants and how they provide customization and better understanding of software.

Invariants are set of “preconditions” and “post conditions” that has to assert during the execution of the software. For Example:

put (v: T) is -- add item v to queue

require

not full

do

ensure

...

count = old count +I;

(old empty) implies (item() = v)

not empty

item((last - 1 + capacity) \\capacity) = v

end -- put

Here put (v, T) is to put element “v” in queue “T”. So the precondition is defined by require statement “not full” that means the queue should not be filled and the post condition is given by ensure statement saying the capacity of queue is greater by one and the last element is “v”. Any implementation (overridden) which does not adhere to it will fail. Similarly one can introduce invariants at class level as you can see below:

deferred class Person feature

invariant

...

age >= 0;

age < 100;

len(name) 0;

socialSecurityNumber > 1000;

end

Here age of the person should be between 0 and 100 and SSN should be above 1000. Class invariants are checked during the instantiation of the Object. Now all the overriding classes also inherit its pre and post conditions. Similarly it is applicable to overridden methods also.

Check instructions are satisfied at the point of definition. And loop invariants are check on loop variables.

To achieve this in dynamic typed interpreted language, the pre and post conditions are checked at the runtime. Because of its dynamic typing nature all the parameters has to type checked during the runtime. So how do you incorporate pre-post conditions (DBC) in Python with out changing the language itself because changing the language involves lot of overhead and moreover the developers has to learn these new concepts. To do this the author has introduced meta-programming approach which is interpreted by the Python interpreter.

Multiprogramming approach is achieved by introducing a wrapper class for all the classes which uses DBC. This is done in the __init__() a constructor of a class. The wrapper object is initialized and the actual object is set on it. So every method call which has invariants calls the wrapper object by wrapper.checkBefore() which is precondition check at the beginning of the method and wrapper.checkAfter() which is a post condition check at the end of the method.

So how can one introduce these checks? This is done by the parser during the generation of the intermediate code. And the logical statements (invariants) are provided in the form of configuration files to the parser while generating the code. This shows the simplicity of the design with out changing the language at all. So by this mechanism of meta-programming it is easily to incorporate Design By Contract in dynamic typing language like Python.

No comments: