From: Dmitry A. Kazakov on
On Fri, 03 Mar 2006 18:13:15 +0000, Miguel Oliveira e Silva wrote:

> You assume that exceptions raised due to false preconditions,
> disguised as a postcondition, are part of a correct program.
> I do not (is this reasonable to you?).

No. In my view a run-time precondition [a real one] if evaluated, then that
shall happen on an independent context. So exception propagation would be
wrong. Exception is a synchronous transfer of control. Failed precondition
shall perform asynchronous transfer of control (ATC.) Like hardware
interrupts do. Ada has software ATCs. Anyway, after an ATC any continuation
on the context caused ACT is impossible. Basically it is an abort, this the
only way real preconditions might be checked at run-time - by an
*independent* system. The states of that system are not ones of the
monitored system.

> My point, is that P3 is not part of "do_y"'s precondition
> (an exception is never a precondition of normal
> routines/instructions, only for catch/rescue blocks).

Yes.

> So I was using a "reductio ad absurdum"
> argument, in which I attempted to show
> that exceptional behavior (being goto like)
> is outside normal structured (single entry
> and exit points) view of programs.

Sort of. It is like jumping out of a loop. It might become very nasty when
misused. Still exceptional behavior is a behavior. Program error is not.

> So, exceptions are required to take into
> consideration code outside normal
> program structured instructions
> (as you did, by including a possible
> catch block). Using them for normal
> program behavior is not a structured
> approach, hence it makes it much
> harder to reason on program
> correctness.

They need better language support. For example, Java's contracted
exceptions is a great idea, though, maybe, poorly implemented. When
considered as a part of the contract, exceptions can be statically checked.
This definitely requires language designers to do some homework. But if
done properly, it should allow building much safer fault-tolerant systems.
Did you saw a program which can really recover after a storage allocation
fault?

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Miguel Oliveira e Silva on
Oliver Wong wrote:

> "Miguel Oliveira e Silva" <mos(a)det.ua.pt> wrote in message
> news:44087328.68DFA1A7(a)det.ua.pt...
> > Oliver Wong wrote:
>
> [snipped everything except Contract-A and contract-B, which seems to be the
> core issue now]
>
> >> There's is no disagreement here. I'm just saying there exist a
> >> mapping
> >> from contract A to contract B, where A has one or more pre-condition, and
> >> contract B has fewer pre-conditions, such that any client who accepts A
> >> will
> >> be willing to accept B as well.
> >>
> >> E.g.:
> >>
> >> /*
> >> Contract A:
> >> Pre-condition: s is never null.
> >> Post-condition: returns s.
> >>
> >> Contract B:
> >> Pre-condition: none.
> >> Post-condition: if s is null, throws NullPointerException; otherwise,
> >> returns s.
> >> */
> >>
> >> Any client who accepts contract A here, should also be willing to
> >> accept
> >> contract B. From his perspective, they do the same thing.
> >
> > In contract B the precondition should have been the same
> > as in A: (s != NULL).
> > You just made the mistake to hide it inside the postcondition
> > (wrongly making the clients belief that the routine can do
> > useful work regardless of the value of s).
>
> Whether something is "useful" or not depends on the client's opinion.
> Perhaps the client specifically wants a NullPointerException (and not ,
> e.g., AssertionException) to be thrown when s is equal to null, and
> therefore B is MORE useful than A.

If throwing an exception is useful to the client (other than
to track program errors), then I claim that he is using a
disguised goto (the exception).

I claim that in your example, there is always a much
simpler structured control instruction that can do the
same useful work, in a much better way (and easier
to ensure its correctness). That way we need not
to confuse normal behavior with exceptional
behavior.

So, what I am arguing, is that that exception should
only be reserved to signal a program error (s == NULL)
on the responsibility of the client (precondition).

B's contract does not guarantee the object's
invariant when the exception is throwned. A does.

Thinking better, A ensures even more than the
invariant. It guarantees that *nothing* happens
inside the object when (s==NULL).

> A does not specify what will happen if s is null.

If it is DbC and a runnable assertion: an exception
will be raised.

> If the client is
> writing code which critically depends on NullPointerException being thrown
> when s is null, then the client MUST use B, and CANNOT use A.

If you insist to specify a particular value for the exception
(NullPointerException), then simply put that behavior
in the precondition comment, thus ensuring to the
client that the object's state won't be modified if
"s" equals NULL (which is much more information
to the client than in B's).

> If the client will never set s = null, the nthe client can use either B
> or A, as they will both perform identically for all situations the client
> will encounter.

Correct.

> That is why I say any client who accepts contract A will also accept
> contract B.

Wrong.

(Unmodified object.)

> >
> > Contract B, is much (much) worse than A's because,
> > if s happens to be NULL, the client is not ensured (since
> > the exceptional behavior is in the postcondition) that
> > the routine did not do nothing else besides raising an
> > exception. Hence he may lose the extremely important
> > guarantee that the supplier object invariant is still correct
> > even if the exception was raised (DbC ensures that).
> > That's a very (very) serious problem resulting
> > from putting the (exceptional) behavior of broken
> > preconditions inside postconditions.
>
> This is a problem with all contracts: post conditions generally don't
> list all the things they DON'T do.

Precisely one of my points. I'm glad that you agree with me
that it is absurd to express non-behavior in assertions.

> E.g.:

> /*
> Pre-condition: None.
> Post-condition: Returns true. Does not emit anything to standard out. Does
> not allocate RAM. Does not kill children. Does not cause your car to
> explode. Etc.
> */
> bool getTrue() {
> return true;
> }
>
> Usually, if a contract does not mention behaviour Foo, it can safely be
> assumed that the method will NOT do contract Foo.

Only the theoretical optimistic programming world. In the
practical (and also theoretical) world we can only be sure
that nothing nasty has not been done by a routine *before*
it starts its execution (precondition).

> If this is a problem for
> the client, the client should negotiate a new contract where the desired
> behaviour is made explicit.

Here I agree with you.

I just don't agree that any client who accepts A also accepts B.
However, anyone accepting B will most likely accept A, if
it is ensured that a NullPointerException exception is
raised in the precondition fails (Right?).

> Contract B says that the method will return s except when s is null, in
> which case it will throw NullPointerException. Note that the post-condition
> does not say things like "BTW, I am free to violate any class constraints,
> etc." And because it doesn't say that, it won't do that.

You are a very optimistic person.

If a condition is tested after the fact, it cannot be 100%
sure something nasty has occurred, neither on the exact
location inside the routine in which the exception was
throwned.

> Exceptions do not indicate that class invariants might have been
> violated. This fear is unjustified.

Exceptions are an abrupt and immediate interruption of
the execution of a routine. Hence they cannot ensure
nothing. It is only their *location* that ensures (or not)
the invariant. The only location in which we are
ensured that nothing has happened in the object,
is before the routine starts its execution (precondition).

> >
> > Another serious problem with B's like contracts
> > happens when the programmer misses an
> > exceptional behavior in postconditions for
> > some runnable (hidden) precondition.
> > The client knows that such a precondition
> > exists, but he will be unsure if the supplier
> > will indeed respond with an exception.
> > Isn't it much simpler to take that for
> > granted as in DbC (without moving
> > assertions to wrong places)?
>
> There is NO pre-condition in contract B. Not even a hidden one. I don't
> know why you say there is.

Just tell me what useful work -other than error
detection- a client expects from that exception,
that should not be done with normal structured
instructions?

If the client wants an exception as useful work
(whatever that might be) out of the routine,
why then doesn't he raises the exception itself?

I claim that if there is no useful work out of
that exception (other than error handling)
then *it is* a disguised precondition.

A postcondition with exceptions, that
do not result from a false assertion (program
error), is just a way to ask for trouble, and to
promote the use of exceptions as goto's.

> If the client "knows" that such a pre-condition
> exists, then that client has obviously misunderstood the contract. There is
> not pre-condition.
>
> If the client carefully reads the contract, he will see that the
> behaviour of the method is to return s when s is not null, and to throw
> NullPointerException when s is null.

> The client therefore knows the behaviour of the method in the cases
> where s = "Dog", s = "Hello World!", s = null, and an just about every other
> situation that will arise. The behaviour is explicitly stated in the
> contract.
>
> >
> > Tell me, why do you put exceptional behavior
> > inside postconditions, and not inside preconditions?
> > (Which would bring your normal *and* exceptional
> > behavior to match DbC.)
>
> Contract A and contract B describe two different behaviours. If I want
> the behaviour of contract B, I must use contract B. I cannot use contract A,
> because it (might) do something different than contract B.
>
> The original claim up thread is that all contracts with runnable
> pre-conditions that are accepted by a given client can be converted into
> another contract with fewer (possibly zero) pre-conditions which will also
> be accepted by a client.

That claim is wrong (unmodified object state).

> The reverse is not nescessarily true.

I have the opposite view. A client expecting B
will easily accept A, if it is ensured that
a precondition failure raises that very same
exception. He is 100% ensured in this case that
the object did not do anything.

> >
> > Afterall, the exception was caused by something
> > that the client did (s=NULL), and not as a result
> > of something inside the supplier's code. (Do we
> > agree in this point?)
>
> No, I'm not sure that we are in agreement. When you talk about "cause",
> it can get philosophical too:
>
> A: "Why was this exception thrown?"
> B: "Because there's a throw clause in the supplier's code."
> A: "Why is there a throw clause in the supplier's code?"
> B: "So that the code satisfies the contract given."
> A: "Why is the contract written the way it is written?"
> B: "Because that's what the client and the supplier agreed upon."
> etc.
>
> >
> > Again, DbC approach is much simpler and safe:
> > any detected false assertion raises an exception.
>
> This sentence does not nescessarily imply that ALL raised exceptions are
> caused by a detected false assertion.

Agreed.

(Just be careful to not enforce the use disguised goto's.)

> - Oliver

-miguel

--
Miguel Oliveira e Silva




From: Daniel T. on
In article <16nNf.9996$dg.1352(a)clgrps13>,
"Oliver Wong" <owong(a)castortech.com> wrote:

> "Miguel Oliveira e Silva" <mos(a)det.ua.pt> wrote in message
> news:4405BE7C.41AD05C9(a)det.ua.pt...
> >
> >> yet you spend a lot of bandwidth
> >> considering what the behavior of the code should be when a precondition
> >> is not met...
> >
> > (... normal versus exceptional ...)
>
> The problem is the conflating of two concepts of "exceptional" here.
> There's exceptional situations which are correctly handled (e.g. by using
> catch blocks) and can be part of the well defined behaviour of a correctly
> implemented program. Then there's the "super-exceptional" situations which
> indicate that there is a bug in the program.
>
> /*
> Pre-conditions: filename should refer to a valid file.
> Post-conditions: Returns a handle to the specified file, or throws
> FileNotFoundException if the file does not exist.
> */
> void File openFile(String filename) {
> //Implementation goes here
> }
>
> If the file doesn't exist, by contract, the method MUST throw an
> FileNotFoundException. It is NOT a pre-condition that the file must exist.
> The file may or may not exist; the behaviour of the method is defined in
> both cases.

Nor is it possible for the file's existence to be in the require clause.
Despite the fact that it can be tested, the file may be removed between
the test and the actual attempt to open it.

This is something Miguel didn't catch.


> > Another thing that puzzles me, is why do you keep arguing that
> > runnable preconditions are not preconditions just because
> > they do what is required to be done when an incorrect program
> > is detected?
>
> I believe Daniel is taking the position that if "preconditions" are
> runnable, then they are part of the well defined behaviour of the program,
> and thus are part of the post-condition contract. It's not something I agree
> with though.

Close, I'm taking the position that if "preconditions" are runnable AND
they are part of the well defined behavior of the function (as these so
called "runnable preconditions" in Eiffel, then they are part of the
post-condition contract. If you explicitly define what happens if value
== 0, then that is what *must* happen, it is no longer undefined.

> (IMHO,) whether something is a pre-condition or not depends on the
> person writing the contract, and NOT on the implementation of the method
> that is supposedly fufilling that contract.

I agree with the above, in Eiffel when you put an assertion in the
require clause, you are establishing a definitive behavior for a
particular condition, not simply leaving it undefined.

As I said, this is a good thing. Undefined behavior is bad, lots of
preconditions are bad.
From: Miguel Oliveira e Silva on
"Daniel T." wrote:

> In article <16nNf.9996$dg.1352(a)clgrps13>,
> "Oliver Wong" <owong(a)castortech.com> wrote:
>
> > "Miguel Oliveira e Silva" <mos(a)det.ua.pt> wrote in message
> > news:4405BE7C.41AD05C9(a)det.ua.pt...
> > >
> > >> yet you spend a lot of bandwidth
> > >> considering what the behavior of the code should be when a precondition
> > >> is not met...
> > >
> > > (... normal versus exceptional ...)
> >
> > The problem is the conflating of two concepts of "exceptional" here.
> > There's exceptional situations which are correctly handled (e.g. by using
> > catch blocks) and can be part of the well defined behaviour of a correctly
> > implemented program. Then there's the "super-exceptional" situations which
> > indicate that there is a bug in the program.
> >
> > /*
> > Pre-conditions: filename should refer to a valid file.
> > Post-conditions: Returns a handle to the specified file, or throws
> > FileNotFoundException if the file does not exist.
> > */
> > void File openFile(String filename) {
> > //Implementation goes here
> > }
> >
> > If the file doesn't exist, by contract, the method MUST throw an
> > FileNotFoundException. It is NOT a pre-condition that the file must exist.
> > The file may or may not exist; the behaviour of the method is defined in
> > both cases.
>
> Nor is it possible for the file's existence to be in the require clause.
> Despite the fact that it can be tested, the file may be removed between
> the test and the actual attempt to open it.

Correct.

> This is something Miguel didn't catch.

I did mentioned that problem, which I have
classified as an external contract broken.

http://groups.google.com/group/comp.object/tree/browse_frm/thread/b9462e645bc4798d/fcc473cb64842ae2?rnum=21&_done=%2Fgroup%2Fcomp.object%2Fbrowse_frm%2Fthread%2Fb9462e645bc4798d%2F76f50acc016b1fbb%3Ftvc%3D1%26#doc_269e3a59a5710360

My position about it, is that normal program behavior
should rule out normal attempts to open inexistent
files (meaning that a program attempt to open
a file is required to be always preceded by the
precondition that the file exists).

To increase the reliability of a program, one
is required to expect exceptions when such
(rare, but quite possible) situations occur,
and to act accordantly.

> > > Another thing that puzzles me, is why do you keep arguing that
> > > runnable preconditions are not preconditions just because
> > > they do what is required to be done when an incorrect program
> > > is detected?
> >
> > I believe Daniel is taking the position that if "preconditions" are
> > runnable, then they are part of the well defined behaviour of the program,
> > and thus are part of the post-condition contract. It's not something I agree
> > with though.
>
> Close, I'm taking the position that if "preconditions" are runnable AND
> they are part of the well defined behavior of the function (as these so
> called "runnable preconditions" in Eiffel, then they are part of the
> post-condition contract.

Don't call it postcondition. Postconditions are conditions which
apply only after the execution of a routine. A failed precondition
ensures the client that the exception was raises before the routine
executes (nothing happens in the supplier object).

When you put a exception behavior in a postcondition, as a
result of a hidden precondition (as you are acknowledging)
the client looses the absolute certainty that the exception
was indeed raises *before* anything has happened inside
the supplier object.

It is expected, in such exceptional behaviors (which we
both agree that should occur), that the supplier won't do
anything useful (to raise an exception is never the goal
of a routine, or else the client could do it himself
directly). So it is an exceptional behavior resulting
from something the client did: Hence it is a
precondition.

Why don't you put the exceptional behavior
within the precondition (if s == NULL then
exception NullStringPointer is raised)?

This way the contract is clearer, and the client
will be correctly informed that if he persists
to pass NULL pointer to the routine he
will receive an exception.

> If you explicitly define what happens if value
> == 0, then that is what *must* happen, it is no longer undefined.

Broken detected contracts have a very well defined behavior
(exceptions).

> > (IMHO,) whether something is a pre-condition or not depends on the
> > person writing the contract, and NOT on the implementation of the method
> > that is supposedly fufilling that contract.
>
> I agree with the above, in Eiffel when you put an assertion in the
> require clause, you are establishing a definitive behavior for a
> particular condition, not simply leaving it undefined.
>
> As I said, this is a good thing.

Agreed.

> Undefined behavior is bad, lots of preconditions are bad.

Why do you keep attaching undefined behavior
to preconditions?

A precondition is a condition expected to occur
before a routine starts its execution. That is
not necessarily equal (as I have been arguing
since the beginning) to undefined behavior
when the precondition is false. If such broken
contract is detected, its behavior is to raise
an exception.

To move this to postconditions is to fool
everyone about the real (useful) routine's
intents (which is never to raise exceptions),
and to loose the guarantee that the supplier
object will remain untouchable (and usable).

Contracts, either expressed as preconditions,
postconditions and invariants, are good
in the construction of reliable quality
programs.

Best regards,

-miguel

--
Miguel Oliveira e Silva

From: Miguel Oliveira e Silva on
"Dmitry A. Kazakov" wrote:

> On Fri, 03 Mar 2006 18:13:15 +0000, Miguel Oliveira e Silva wrote:
>
> > You assume that exceptions raised due to false preconditions,
> > disguised as a postcondition, are part of a correct program.
> > I do not (is this reasonable to you?).
>
> No. In my view a run-time precondition [a real one] if evaluated, then that
> shall happen on an independent context.

Well, in DbC -although both worlds share the program state- the
exceptional world should be taken as being separated from the
normal world (this has been one of my main "fights" in this thread).
That is why we should never use exceptions to do normal useful
work in programs (using exceptions as goto's).

> So exception propagation would be
> wrong.

Wrong would be to not propagate exceptions when a false
assertion is detected.

> Exception is a synchronous transfer of control.

A very important property for assertions, as it ensures
nothing else happens in the program state (no attempt
to write in arrays outside their boundaries, etc.)
after its failure.

> Failed precondition
> shall perform asynchronous transfer of control (ATC.)

(Do you mean that the program is allowed to
continue after such failure?)

What if, in the program being monitored, a false
precondition was detected in a routine which
launches a nuclear missile?

The synchronous internal exceptional behavior
is essential (regardless of possible external
concurrent, synchronous or asynchronous,
entities).

On the other hand, to detect false assertions one
is required to observe the programs internal state.
That is what assertions do.

Nothing prevent you from having external independent
entities to redundantly approach that monitoring
behavior, but it is essential that inside programs
a false detectable assertions is taken care of
in the right place (where the assertion applies,
so in the case of preconditions: before the
routine starts its execution, and not in
postconditions).

As I said, in DbC, assertions not only allow a precise and
correct (although not complete) error detection, but they
also prevent that nasty things happen to the program state
(out of bound accesses to array, etc.). So, many times we can
recover safely from a broken exception. If not, then
not only the program aborts, but also, with DbC
assertion mechanism, it may also precisely
inform the outside world what has happened, thus
allowing a more precise program replacement.

> Like hardware
> interrupts do. Ada has software ATCs. Anyway, after an ATC any continuation
> on the context caused ACT is impossible.

So the failed program behavior is synchronous after all.
It stop immediately. Are ATC's an exception
mechanism to outside concurrent entities?

Exception are a similar internal thing. They stop normal
program execution, passing the control to the separated
exceptional world (we don't disagree that much in this
regard).

> Basically it is an abort, this the
> only way real preconditions might be checked at run-time - by an
> *independent* system.

I've already showed you that is not true (you take a very
extreme outside view of programs, as if programs could
not know nothing of themselves!). A correctly placed
precondition prevents the program to harm itself.
Hence its state remains quite trustable.

It is trivial to test inumerous real preconditions
when a program is executing (non negative square
roots, etc.). That does not mean, of course,
that *all* preconditions can always be safely
tested. In such cases I agree with you that
it is important to rely on outside independent
entities (protected by process alike runtime
boundaries).

But, Dmitry, to pick in such *particular*
cases and generalize them to *all* cases
as you are doing, is simply absurd.

> The states of that system are not ones of the
> monitored system.

That is good, because they are protected.

That, however, does not rule out the
inumerous cases in which the states can
be safely shared.

> > My point, is that P3 is not part of "do_y"'s precondition
> > (an exception is never a precondition of normal
> > routines/instructions, only for catch/rescue blocks).
>
> Yes.
>
> > So I was using a "reductio ad absurdum"
> > argument, in which I attempted to show
> > that exceptional behavior (being goto like)
> > is outside normal structured (single entry
> > and exit points) view of programs.
>
> Sort of.

Either it is, or it isn't!

> It is like jumping out of a loop.

And isn't that exactly what I'm saying (goto like)?

> It might become very nasty when misused.

Of course. Structured programming should
be part of the formation of all programmers.

> Still exceptional behavior is a behavior. Program error is not.

Exceptional behavior is the behavior a incorrect program
should take. Then, either the program is unable to cope
with the failure and exceptions are propagated until
the final abortion of the program (nothing stops
another program to take its place as you suggest);
or else somewhere in between the program is
able to safely replace the faulty code (avoiding
a new "big-bang").

> (...)

> --
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

-miguel

--
Miguel Oliveira e Silva

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Prev: Teaching OO
Next: multimethod + multiple inheritance