|
Prev: Teaching OO
Next: multimethod + multiple inheritance
From: Dmitry A. Kazakov on 4 Mar 2006 15:26 On Sat, 04 Mar 2006 17:17:10 +0000, Miguel Oliveira e Silva wrote: > "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). Yes, this is the crucial point of disagreement. A program cannot be correct in one of its states and incorrect in another. Correctness applies to all possible states of a given program. So any shared states don't count. > That is why we should never use exceptions to do normal useful > work in programs (using exceptions as goto's). We should. The use case of exception is when the implementation logic sufficiently deviates for some program states. These states are usually called exceptional, but this does not attribute the program correctness, but merely the states. A typical example is, when decomposition prevents handling of some situations in definite contexts. For instance, when Read determines file end it raises an exception. Read cannot and should not handle file end. It does not have the information necessary for it. To give this information to Read, would be a very fragile design. So the design decision is to handle this state outside Read. This does not make Read or finite files incorrect. Note that a return code for Read would do exactly same, but much less safer and efficient. It is not an alternative. >> 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. Exactly this could happen if the transfer is synchronous. Exception propagation has side effects which change the state. Asynchronous transfer does not have side effects. Which also implies that there is no reasonable way to continue the aborted thing. > On the other hand, to detect false assertions one > is required to observe the programs internal state. > That is what assertions do. Here we go again. To observe state /= to observe correctness. State observation is a contracted behavior. Any program is just a FSM. And what a FSM does? It observes its state and goes to another one. That assertions indeed observe states is the point Daniel, Oliver and I are defending. They don't check correctness. >> 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? Technically it breaks at the first point where it can. > 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). It only appears so. You can use anything you want for correctness checks, if you can be sure that the program being checked does not influence one that checks. Exceptions as they are implemented in all languages I know, are unsuitable for this. ATCs, system traps, calls to supervisor are much better. Physically separated systems are even more better. >> 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!). No. I only claim that a program cannot know anything about its correctness. About itself, a program knows its state. >>> 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! The definition of structured programming isn't that formal. You cannot point at a program and say whether it is well structured or not. There are cases where gotos are better structured than if-then-else. >> Still exceptional behavior is a behavior. Program error is not. > > Exceptional behavior is the behavior a incorrect program > should take. [ Don't you see any problems with such statements? ] A correct behavior of an incorrect program? Would an incorrect program become correct by raising an exception? Was it incorrect before it raised the exception? But it is definitely correct after doing that! Ah, maybe, it was always correct except for a negligible period of time required to raise an exception? Wouldn't be any program correct if we implemented it as: procedure Foo is begin raise Oh_My_God; end Foo; > 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); Isn't is so, that any program is correct as long as it keeps on coping with? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Kenneth P. Turvey on 4 Mar 2006 19:23 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Fri, 03 Mar 2006 18:32:06 +0000, Oliver Wong wrote: > 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. I should note that this isn't strictly true. Client B must do some work to check to see if the constraint is violated. This may be a small amount of work or a large amount of work, but it will take time. Client A will get the same answer on every case in which it is defined and will perform better than client B. - -- Kenneth P. Turvey <kt-usenet(a)squeakydolphin.com> Phone : (314) 255-2199 XMPP IM: kpturvey(a)jabber.org Yahoo IM: kpturvey2 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFECi87i2ZgbrTULjoRArijAJ43kBosnncZ5GaZg0M4TZBXB/3SUwCgnKgN sGD5esbNw9JyP7/Xpo2rcj0= =j2NN -----END PGP SIGNATURE-----
From: Miguel Oliveira e Silva on 5 Mar 2006 14:04 "Dmitry A. Kazakov" wrote: > On Sat, 04 Mar 2006 17:17:10 +0000, Miguel Oliveira e Silva wrote: > > > "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). > > Yes, this is the crucial point of disagreement. A program cannot be correct > in one of its states and incorrect in another. The program as whole no (by definition). But *parts* of it may (and most likely are if the program is modular). A flat tyre in my car does not affect its engine! > Correctness applies to all > possible states of a given program. The total correctness of program, of course. > So any shared states don't count. (Think again.) > > That is why we should never use exceptions to do normal useful > > work in programs (using exceptions as goto's). > > We should. The use case of exception is when the implementation logic > sufficiently deviates for some program states. These states are usually > called exceptional, but this does not attribute the program correctness, In DbC's programmers *choose* to use them (mainly) for that purpose. > but merely the states. And the *programmer* knows that some states show, without doubt, program incorrectness (those in which assertions are false). Hence he uses (in DbC) exceptions to deal with that situation. > A typical example is, when decomposition prevents > handling of some situations in definite contexts. > > For instance, when Read determines file end it raises an exception. I've already mentioned these group of problems. A program should be ruthless in its internal contracts. Since it it its own responsibility to ensure them. Hence whenever an internal contract is broken (false assertions) we are in the presence of a program error. However, when dealing with external entities (whose behavior cannot be controlled by the program), one should use a defensive programming approach (just because it may be normal that a program expecting to read something out of a file, receives a end-of-file. That is not a program error, it is simply an external broken contract). To implement this defensive behavior, one can, mainly, use one of two approaches: 1. Normal control instructions. Using your example, instead of "read" services, one uses "tryToRead" services. A command-query separated interface might look something like these: class IO feature try_to_read_integer is require file_opened; file_opened_to_read; last_read_successful: BOOLEAN last_read_was_an_integer: BOOLEAN last_integer: INTEGER is require last_read_successful; last_read_was_an_integer end_of_file: BOOLEAN (...) end -- IO (As you can see, exceptions are not required for normal behavior) 2. Use the exception mechanism. Another possible approach (already mentioned in: 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 ) is to take an expected behavior from outside entities as an external contract being broken. This type of broken contracts, are much easier to rectify because they are not the expression of a program error. -- All these being said, I still cannot understand your point in this discussion. > Read cannot and should not handle file end. It does not have the information > necessary for it. To give this information to Read, would be a very fragile > design. So the design decision is to handle this state outside Read. This > does not make Read or finite files incorrect. Note that a return code for > Read would do exactly same, but much less safer and efficient. It is not an > alternative. Agreed (but my num. 1 proposal is). > >> 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. > > Exactly this could happen if the transfer is synchronous. What? Only if the programmer chooses to do a very bad thing in catch blocks (to use Ada/C++/Java terminology). > Exception > propagation has side effects which change the state. Asynchronous transfer > does not have side effects. Which also implies that there is no reasonable > way to continue the aborted thing. Really? So in your opinion a new big-bang is *always* required. (If I've used that strategy to my sixteen year old car, I would have bought quite a few hundreds of cars by now.) > > On the other hand, to detect false assertions one > > is required to observe the programs internal state. > > That is what assertions do. > > Here we go again. To observe state /= to observe correctness. (Here we go again.) To observe state = to observe incorrectness if the programmer correctly uses DbC (I've already showed you a few examples, so I don't know why you keep insisting at this point). > State observation is a contracted behavior. Any program is just a FSM. As a result of a program constructed and defined by programmers. A DbC programmer puts *redundant* assertions in the code to detect incorrect states (beats me why this is so difficult to understand by you). > And what a > FSM does? It observes its state and goes to another one. So? What is your point? Are you saying that a FSM machine cannot be built to protect itself from some nasty, non intended behaviors? (That's simply absurd.) > That assertions indeed observe states is the point Daniel, Oliver and I are > defending. That they, doing precisely that, can detect incorrect states has been my point (and DbC's approach). > They don't check correctness. They can detect incorrect behaviors, hence they check the correctness of different parts of programs. They just are unable to ensure total program correctness. > >> 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? > > Technically it breaks at the first point where it can. So, technically, it could be after launching the nuclear missile? > > 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). > > It only appears so. You can use anything you want for correctness checks, > if you can be sure that the program being checked does not influence one > that checks. That's why *pre*conditions (and invariants) are so important (and not expressible as postconditions). Any runtime checked precondition *precedes* nasty behaviors. > Exceptions as they are implemented in all languages I know, > are unsuitable for this. They are not, if exceptions are throwned *before* the program begins an erratic behavior. > ATCs, system traps, calls to supervisor are much > better. Physically separated systems are even more better. We agree in this last point. I just don't see what that was to do with the runtime use of DbC inside programs, and why runtime preconditions are not tested preconditions. > >> 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!). > > No. I only claim that a program cannot know anything about its correctness. (Really?) So a module, that is expected -for example- to solve in R a second degree equation, cannot ever know if the values of "a", "b" and "c" have real roots. I would say that a simple (run time) calculation of the sign of (b^2-4ac) was more than enough. So, in my book, if another part of the program is attempting to use that module expecting that such a solution exists, it is making a program error. You apparently don't think the same way (or you are simply playing with words). On the other hand, if you are claiming that a program *by itself* lacks intelligence to be aware, for example, of its own existence or its correctness. That's obvious (and quite beside the point). The *programmer* knows what are the expected correct behaviors and enforces them by the use of contracts. Run time verifiable contracts, when broken, ensure the programmer that the program is incorrect, and so he can chose to build its programs to respond to such errors, or simply to let the program die gracefully. > About itself, a program knows its state. Exactly. That is more than enough for runtime assertions to detect some incorrect programs. > >>> 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! > > The definition of structured programming isn't that formal. I'm using Dijkstra's approach ("Structured Programming", page 19, 1972, Academic Press). Do you have a better suggestion? (Yes, I'm also know Knuth's articles on the subject.) > You cannot > point at a program and say whether it is well structured or not. There are > cases where gotos are better structured than if-then-else. > > >> Still exceptional behavior is a behavior. Program error is not. > > > > Exceptional behavior is the behavior a incorrect program > > should take. > > [ Don't you see any problems with such statements? ] No. > A correct behavior of an incorrect program? Exactly. > Would an incorrect program > become correct by raising an exception? No (obviously). (Where did I said that?) Read more carefully, and stop playing with words. The appropriate (->correct) behavior a program should take as a response to detected incorrect state, is to raise an exception. If, resulting from that exception, the program is able to recover -correcting itself by the use of redundant code- or not (case in which it should terminate its execution), is a problem up to the programmer. > Was it incorrect before it raised > the exception? If the exception was a result of a false assertion, yes. > But it is definitely correct after doing that! Ah, maybe, it > was always correct except for a negligible period of time required to raise > an exception? Wouldn't be any program correct if we implemented it as: > > procedure Foo is > begin > raise Oh_My_God; > end Foo; I'll take all these last absurd comments as a (funny) joke on your part. Take a little time to understand the other "side"'s arguments, before writing fallacious absurd things. > > 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); > > Isn't is so, that any program is correct as long as it keeps on coping > with? A program is correct if all its runnable and intended contracts are always observed. > -- > Regards, > Dmitry A. Kazakov > http://www.dmitry-kazakov.de -miguel -- Miguel Oliveira e Silva
From: S Perryman on 6 Mar 2006 06:28 "Oliver Wong" <owong(a)castortech.com> wrote in message news:CX_Nf.8680$Ui.8021(a)edtnps84... > <ggroups(a)bigfoot.com> wrote in message > news:1141384594.168474.257720(a)z34g2000cwc.googlegroups.com... >> Oliver Wong wrote: >> [ Design By Contract saga snipped, but acknowledged ] >>> It's bad for the supplier because he cannot get any clients to use it. >>> What's the point of creating a method if it will never be used? It's >>> wasted effort on the supplier's part. >>> But I guess it's useless to proceed further with this until we define >>> metrics for "good" and "bad" for the supplier and client. >>> It is GOOD for the client if he can find an implementation of a contract >>> which solves his problem without imposing too many pre-conditions. >>> It is GOOD for the supplier if he can find a client who will agree to a >>> contract with the supplier. >> The best components from the users' viewpoint are those that have the >> weakest preconditions and strongest post/invariant conditions. >> The suppliers' viewpoint is the converse. >> Within those extremes we have a dynamic where components arrive at >> contracts that are amenable to both (usage, implementation effort etc) . >> Hence the term *contract* . Contracts are negotiated are they not ... > The problem with this is that if it were true that it's best for the > supplier to implement components with the strongest pre-conditions and the > weakest post-conditions, then no one would ever implement any component > except for this one: > /* > pre-condition: false. > post-condition: does nothing > */ > void doesNothing() { > } > But why isn't that what we observe in real life? Because the component *does nothing* . Therefore it is of no use. It is not real life, regardless of its contract. <quote> The art is to find the weakest possible [precondition] and the strongest possible [postcondition] that characterize your intent as to what the module is supposed to do. </quote> The quote captures the essence of the problem. > Because there's an ADDED factor that a supplier will not want to waste > his/her time implementing a component that no one wants to use! That's the > point I was trying to make. But you have not made that point at all IMHO. A supplier generally builds components that is intended for some use. What determines whether a potential user will use that component ?? a) preconditions too strong (usage too constrained) b) postconditions too weak (no observable measures of correctness) Component contracts evolve through usage and horse-trading. Not in a vacuum. Regards, Steven Perryman
From: S Perryman on 6 Mar 2006 06:33
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> wrote in message news:5966u7leuxqk$.nuv7gvvewc93.dlg(a)40tude.net... > On 3 Mar 2006 03:16:34 -0800, ggroups(a)bigfoot.com wrote: >> The best components from the users' viewpoint are those that have the >> weakest preconditions and strongest post/invariant conditions. >> The suppliers' viewpoint is the converse. >> Within those extremes we have a dynamic where components arrive at >> contracts that are amenable to both (usage, implementation effort etc) >> Hence the term *contract* . Contracts are negotiated are they not ... > Maybe, but there is also somebody who assigns suppliers and consumers, > responsible for the problem decomposition. Now the question is, when the > negotiation takes place. Before or after the roles have been identified? Negotiation should be ongoing, based on the realities. Which means before/during/after identification of such "roles" . Regards, Steven Perryman |