CONTRACTS October 3, 2006. BILATERAL AGENCY CONTRACTS Contracts.
Adding Contracts to Ada
description
Transcript of Adding Contracts to Ada
Adding Contracts to Ada
Ehud Lamm
Adding
Design By Contract
to Ada
19.7.2002 Ada-Europe’20022
ADT + Contracts
type Stack is tagged private;
procedure Init(S:out Stack);
procedure Push(S:in out Stack; I:in Integer)
at exit Size(S)=old Size(S)+1;
procedure Pop(S:in out Stack;I:out Integer)
use when not(Is_Empty(S))
at exit Size(S)=old Size(S)-1;
function Size(S:Stack) return Natural;
function Is_Empty(S:Stack) return Boolean;
function Top(S:Stack) return Integer use when not(Is_Empty(S));
Overflow: exception;
1. Contracts are checked at runtime (detection).
2. Contract violations raise exceptions.
3. When possible use the type system instead (e.g., Size)
4. Contracts allow expressing arbitrary boollean assertions.
19.7.2002 Ada-Europe’20023
Design By Contract
• Annotate each routine with axioms.
• Pre-Condition & Post-Condition
• (we will not talk about class invariants)
• The classic ADT approach
(Liskov, Guttag, Meyer)
19.7.2002 Ada-Europe’20024
Design By Contract
• A contract carries mutual obligations and benefits.
• The client should only call a routine when the routine’s pre-condition is respected.
• The routine ensures that after completion its post-condition is respected.
19.7.2002 Ada-Europe’20025
A little polymorphic programming
procedure Print_And_Empty(S: in out Stack’class) is
i:Integer;
begin
while not(Is_Empty(S)) loop
pop(S,i);
put(I);
end loop;
end;
Interface oriented
programming
Exercise: Prove termination for all possible stacks S.
19.7.2002 Ada-Europe’20026
Oops…
type Crazy_Stack is new Stack with null record;
procedure Pop(S:in out Crazy_Stack;I:out Integer)
use when not(Is_Empty(Stack))
at exit
(old Top(S)/=9 and then Size(S)=old Size(S)-1)
or (Size(S)=old Size(S));
Does Print_And_Empty work correctly on Crazy_Stacks?
19.7.2002 Ada-Europe’20027
Liskov Substitution PrincipleLSP
Liskov, Wing (TOPLAS, Nov. 1994)
Liskov (SIGPLAN, May 1988)
Otherwise bad use of public inheritance!
19.7.2002 Ada-Europe’20028
Why is this important?
• The foundation for subtype polymorphism
• Bugs surface during maintenance
• Who is responsible?
19.7.2002 Ada-Europe’20029
Assigning Blame
• Crucial for managing software production
• Possible candidates:– The original contractor (Stack)– The polymorphic routine (Print_And_Empty)– The subcontractor (Crazy_Stack)– The user of the pm routine (should know
better than to call P&E on Crazy_Stack)
19.7.2002 Ada-Europe’200210
DbC & Inheritance
• Remember the LSP!
• “The subclass must require less and ensure more” )Meyer, OOSC)
• The only question is how to ensure this property!
19.7.2002 Ada-Europe’200211
DbC & LSP – more formal
Assume B is derived from A,
then for each method P
pre(PA) → pre(PB) and
post(PB) → post(PA)
A
B
A
B
19.7.2002 Ada-Europe’200212
The Eiffel Approach
• The programmer is not allowed to make an LSP error…
• require else
• ensure then
• A subclass can only use “or” in pre-cond / “and” in post-cond
• Other tools are even worse
19.7.2002 Ada-Europe’200213
Wrong Approach
• “Ensuring” correct hierarchies
procedure p(T:A;I:Integer) use when i>0;
procedure p(T:B;I:Integer) use when i>10;
-- synthesized contract (i>0)V(i>10)
• Hierarchy is malformed, language hides error.
19.7.2002 Ada-Europe’200214
Solution
• Interface implied contract can be deduced from code.
• Hierarchy checking is done according to run time tag of object. (Recall P&E)
(more details in the paper and references)
19.7.2002 Ada-Europe’200215
Contract Checking - Analysis
procedure Print_And_Empty(S: in out Stack’class) is
i:Integer;
begin
while not(Is_Empty(S)) loop
pop(S,i);
put(I);
end loop;
end;
P&E is responsible for Stack’s Pop pre-condition. (Stack’s pre implies actual’s pre)
Actual’s Pop post-condition must be satisfied when Pop exits
Actual Pop’s post condition must imply Stack Pop post-condition
19.7.2002 Ada-Europe’200216
Another example: generics
generic
with function Sqrt(X:Float) return Float
use when X>=0;
procedure Print_Quad_Solutions(A,B,C:Float);
-- use when B**2-4.0*A*C>=0;
If actual Sqrt requires X>0, who is to be blamed when P_Q_S fails?
19.7.2002 Ada-Europe’200217
How can the language help?• Run-time enforcement• Should allow the programmer to document
contracts; in a formal, standard notation• Enforce correct contract relations when possible
(Hard!) • Identify faulty components and assign blame,
when violations occur• When you cannot use built-in contracts: types
(Think of trying to break a contract stating that the Stack contains only positive numbers)
19.7.2002 Ada-Europe’200218
Does Ada need DbC?
• Ada, The Software Engineering Language• Good type system; support for generic
programming• Ada interface definitions are lacking (e.g., which
exceptions are raised by which routine?)• Readability and Self-Documenting code• Debugging aid• Everyone else has it (Eiffel, Java: iContract, jContractor, HandShake,
JVMAssert) …• BUT: This is a major change
19.7.2002 Ada-Europe’200219
Conclusion
• Perhaps still too cutting edge?!• Is there market demand?• Should we do it anyway?
• Even a rudimentary implementation has important advantages.
• Simpler than extending the type system• The future lies in sw components) COTS)
19.7.2002 Ada-Europe’200220
Ada needs DbC
Any Questions?
19.7.2002 Ada-Europe’200221
Implementation
• Can be implemented using wrapper routines
• The exact wrapper routine invoked for each call is determined by relevant interface.
19.7.2002 Ada-Europe’200222
Interoperability with the old language
• Old language calling new, not really an issue (but upstream contractual exceptions may be raised)
• New language calling old, not really an issue (but compiler should know that a package was compiled with no contracts)