Le 05/05/2012 14:46, Stewart Gordon a écrit :
d2. Bertrand Meyer's book explains why this is the way in which it must
work. (But the truth of this claim has been challenged.)


http://se.ethz.ch/~meyer/publications/computer/contract.pdf

The extract of the book covering that specific point is available here. Meyer explain HOW thing work and then how this behavior provide some benefices. Careful reading of the passage show that BOTH behavior we are talking here provide such benefices. This reading isn't going to conclude the discussion.

Additionally, Meyer state that the in contract is a constraint for the caller. This is an argument in favor of view (a).

I do think EIFFEL implementation provide less benefices than the proposed new behavior.

I plan to contact Meyer himself to discuss the subject.

d3. It allows inputs not allowed by the base class contract to be passed
in under controlled conditions - conditions in which some other method
is defined from whose return value the legality of some input can be
determined. Example provided by Walter himself:

class A {
void foo(int x) in { assert(x > 0); } body {}
int bar() { return 1; }
}

class B : A {
void foo(int x) in { assert(x > -2); } body {}
int bar() { return -1; }
}

void fizzbuzz(A a) {
a.foo(bar());
}


The fizzbuzz function here is flawed. bar doesn't provide any guarantee on its return value. foo expect fizzbuzz to provide a parameter with certain properties.

fizzbuzz is unable to ensure it is doing its part of the contract. Correct alternative are either : - adding an out contract on A.bar to ensure that the value returned is above 0 and so can be safely passed to foo. This solution make B.bar invalid, but fizzbuzz now is able to honor its part f the contract. - adding a new condition to A.foo's in contract to accept bar's return value. This also require that A.bar is made pure. - fizzbuzz is rewritten to ensure that the value returned by bar is valid according to foo's contract. The only contract that fizzbuzz knows about is A.foo and so it should apply criteria on that one. It means that B.bar's return valus will be discarded by fizzbuzz and it will not call a.foo in case of a being an instance of B.

d4. Now that D behaves in this way, there is going to be code out there
that does something like the example in d3. Changing to static binding
would break this code. (This seems the one argument for dynamic binding
that I'm inclined to agree with.)


As seen above, cases where things risk to break is exactly what we want. Contract is supposed to break bad code ASAP.

deadalnix has pointed out that design of OOP doesn't say anything about
contracts. In which case any claim that the whole OOP paradigm takes
either view (a) or view (b) is nonsense.


After some thinking, I want to make a stronger point.

A good guideline in OOP is to hide implementation. A contract is an agreement between the caller and the callee, and so, mustn't be hidden in any way. It certainly exclude the contract as being part of the implementation.

view (b) imply that the in contract is part of the implementation (ie, can the provided implementation handle that input or not). OOP don't say anything about contracts, but view (b) is breaking encapsulation, and encapsulation is an OOP principle.

Maybe what's needed is a clarification in the spec of which concept of
an in contract (view (a), view (b) or something else) D intends to
implement.


The spec is very explicit on that point. view (b) is the specified one. But I think it is an error.

If (a), then we need static binding. But how do we deal with the code
breakage pointed out in d4?


Breaking flawed code is a benefit, not an issue.

Reply via email to