* Preventing type extensions @ 2010-09-12 10:18 Florian Weimer 2010-09-12 11:59 ` Ludovic Brenta 0 siblings, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-12 10:18 UTC (permalink / raw) Suppose I've got a tagged type. I want to expose the fact that it is a tagged type outside its package, but want to prevent type extensons. (In short, I'm interested in something like final classes in Java or C++0X.) Can this be done? ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-12 10:18 Preventing type extensions Florian Weimer @ 2010-09-12 11:59 ` Ludovic Brenta 2010-09-12 12:53 ` Florian Weimer 0 siblings, 1 reply; 107+ messages in thread From: Ludovic Brenta @ 2010-09-12 11:59 UTC (permalink / raw) Florian Weimer writes on comp.lang.ada: > Suppose I've got a tagged type. I want to expose the fact that it is > a tagged type outside its package, but want to prevent type extensons. > (In short, I'm interested in something like final classes in Java or > C++0X.) I think the way to do this is to hide the fact that the type is tagged :/ Why do you want to make the type publicly tagged if not to allow type extension? -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-12 11:59 ` Ludovic Brenta @ 2010-09-12 12:53 ` Florian Weimer 2010-09-12 21:23 ` Maciej Sobczak 0 siblings, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-12 12:53 UTC (permalink / raw) * Ludovic Brenta: > Florian Weimer writes on comp.lang.ada: >> Suppose I've got a tagged type. I want to expose the fact that it is >> a tagged type outside its package, but want to prevent type extensons. >> (In short, I'm interested in something like final classes in Java or >> C++0X.) > > I think the way to do this is to hide the fact that the type is tagged > :/ Why do you want to make the type publicly tagged if not to allow type > extension? I want to use some features which come with tagged types, like the OO call notation or the fact that the type implements an interface. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-12 12:53 ` Florian Weimer @ 2010-09-12 21:23 ` Maciej Sobczak 2010-09-13 5:32 ` Florian Weimer 0 siblings, 1 reply; 107+ messages in thread From: Maciej Sobczak @ 2010-09-12 21:23 UTC (permalink / raw) On 12 Wrz, 14:53, Florian Weimer <f...@deneb.enyo.de> wrote: > > Why do you want to make the type publicly tagged if not to allow type > > extension? > > I want to use some features which come with tagged types, like the OO > call notation Which shows that combining the "OO notation" with tagged types was a bad idea at the language design level. > or the fact that the type implements an interface. If it implements an abstract interface, then why extending it further is a problem? From the user point of view (that is, from the point of view of the subprogram that accepts Some_Interface'Class and operates on it), it does not matter how deep is the hierarchy. -- Maciej Sobczak * http://www.inspirel.com YAMI4 - Messaging Solution for Distributed Systems http://www.inspirel.com/yami4 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-12 21:23 ` Maciej Sobczak @ 2010-09-13 5:32 ` Florian Weimer 2010-09-13 7:13 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-13 5:32 UTC (permalink / raw) * Maciej Sobczak: > If it implements an abstract interface, then why extending it further > is a problem? From the user point of view (that is, from the point of > view of the subprogram that accepts Some_Interface'Class and operates > on it), it does not matter how deep is the hierarchy. Type extensions break encapsulation (at least if there non-abstract dispatching subprograms which contain some non-trivial code): the information which subprograms call each other under what circumstances leaks to the outside of the package. One very drastic way to implement that is to disallow type extensions for most non-abstract types you write, and consider the exceptions carefully. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 5:32 ` Florian Weimer @ 2010-09-13 7:13 ` Dmitry A. Kazakov 2010-09-13 9:19 ` Georg Bauhaus ` (2 more replies) 0 siblings, 3 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 7:13 UTC (permalink / raw) On Mon, 13 Sep 2010 07:32:02 +0200, Florian Weimer wrote: > * Maciej Sobczak: > >> If it implements an abstract interface, then why extending it further >> is a problem? From the user point of view (that is, from the point of >> view of the subprogram that accepts Some_Interface'Class and operates >> on it), it does not matter how deep is the hierarchy. > > Type extensions break encapsulation (at least if there non-abstract > dispatching subprograms which contain some non-trivial code): the > information which subprograms call each other under what circumstances > leaks to the outside of the package. One very drastic way to > implement that is to disallow type extensions for most non-abstract > types you write, and consider the exceptions carefully. No, the actual problem here is re-dispatch. Just do not do that, it is always bad. Final classes make no sense. I am glad that at least this was not borrowed by Ada ... yet. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 7:13 ` Dmitry A. Kazakov @ 2010-09-13 9:19 ` Georg Bauhaus 2010-09-13 9:42 ` Dmitry A. Kazakov 2010-09-13 18:32 ` Preventing " Florian Weimer 2010-09-17 0:16 ` Shark8 2 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-13 9:19 UTC (permalink / raw) On 13.09.10 09:13, Dmitry A. Kazakov wrote: > On Mon, 13 Sep 2010 07:32:02 +0200, Florian Weimer wrote: > >> * Maciej Sobczak: >> >>> If it implements an abstract interface, then why extending it further >>> is a problem? [...] >> the >> information which subprograms call each other under what circumstances >> leaks to the outside of the package. >> [...] > No, the actual problem here is re-dispatch. Just do not do that, it is > always bad. > > Final classes make no sense. I am glad that at least this was not borrowed > by Ada ... yet. People may have reasons that render extensibility of types undesirable, even when internally the software will profit from re-dispatch. "Internally" can refer to both the software and to the organization: in a controlled environment (of people), dispatching at run time adds flexibility. Reasons against extensibility just point to a very real phenomenon, that of (mis)trust among the members of a group relevant to the program/ library: these include programmers, managers, sales personnel, users... Will they trust the currently known programmers, trust future colleagues, to use the extensible O-O library only in ways, say, covered by the legal contract from year X? (Hint: viral callbacks.) If a system must reflect trust and mistrust, shouldn't the mechanics of a language support both? And hence---given the split between Ada's non-tagged and tagged types---shouldn't the langauge support "final" types? Otherwise, which language lawyer can say it should or shouldn't, when the issues are not technical, but social? Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 9:19 ` Georg Bauhaus @ 2010-09-13 9:42 ` Dmitry A. Kazakov 2010-09-13 10:23 ` Niklas Holsti 2010-09-13 15:12 ` Securing type extensions (was: Preventing type extensions) Georg Bauhaus 0 siblings, 2 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 9:42 UTC (permalink / raw) On Mon, 13 Sep 2010 11:19:10 +0200, Georg Bauhaus wrote: > Reasons against extensibility just point to a very real phenomenon, > that of (mis)trust among the members of a group relevant to the program/ > library: these include programmers, managers, sales personnel, users... > Will they trust the currently known programmers, trust future colleagues, > to use the extensible O-O library only in ways, say, covered by the > legal contract from year X? (Hint: viral callbacks.) Mistrust in what? To give some terms: type extension = aggregation of an instance + delegation to the operations of the instance. What is here not to trust? Aggregation? Delegation? As for callbacks, I don't understand your note. My point was that re-dispatch is the problem, not aggregation or delegation. Don't implement anything by means of re-dispatch and you will have no "callbacks." A type extension cannot break anything in the parent's implementation unless it re-dispatches. > If a system must reflect trust and mistrust, shouldn't the > mechanics of a language support both? In Ada it is called visibility. > And hence---given the split > between Ada's non-tagged and tagged types---shouldn't the langauge > support "final" types? This split was a pragmatic decision, to be fixed (removed) some day. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 9:42 ` Dmitry A. Kazakov @ 2010-09-13 10:23 ` Niklas Holsti 2010-09-13 12:55 ` Cyrille ` (2 more replies) 2010-09-13 15:12 ` Securing type extensions (was: Preventing type extensions) Georg Bauhaus 1 sibling, 3 replies; 107+ messages in thread From: Niklas Holsti @ 2010-09-13 10:23 UTC (permalink / raw) Dmitry A. Kazakov wrote: > re-dispatch is the problem, not aggregation or delegation. Don't implement > anything by means of re-dispatch and you will have no "callbacks." A type > extension cannot break anything in the parent's implementation unless it > re-dispatches. Conversely, there are architectures (sensible ones, in my opinion) in which the extension is broken, or is difficult or cumbersome to implement, if the parent does *not* re-dispatch. Some time ago on c.l.a. we had a long discussion on the goodness or badness of re-dispatch, without coming to an agreement. I don't want to repeat that discussion, just to point out, again, that Dmitry's opinion is not universal. Regarding Florian's view that re-dispatch "leaks" information about the internal implementation of the parent type, there was consensus in the earlier discussion that the occurrence of re-dispatch must be considered a public (interface) property of the module, and documented as such. I would not consider it a "leak", although I agree that it is an added "dependency". Next question: Should the language provide means to express the uses of re-dispatch, in the declaration of a tagged type and its operations? For example, "primitive operation Foo calls primitive operation Bar with re-dispatch". An analog would be the exception contracts, as implemented in Java (where I believe they are not praised by all) and proposed for Ada. On my part I feel that a formal "re-dispatch contract" is not needed, partly because the presence of re-dispatch should be fairly simple for a static analyser to discover and report, but mainly because the important point is not that re-dispatch is used, but why and when it is used, and that would be hard to describe formally. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 10:23 ` Niklas Holsti @ 2010-09-13 12:55 ` Cyrille 2010-09-13 13:55 ` Dmitry A. Kazakov 2010-09-13 21:13 ` J-P. Rosen 2010-09-13 13:05 ` Dmitry A. Kazakov 2010-09-13 21:10 ` J-P. Rosen 2 siblings, 2 replies; 107+ messages in thread From: Cyrille @ 2010-09-13 12:55 UTC (permalink / raw) > Some time ago on c.l.a. we had a long discussion on the goodness or > badness of re-dispatch, without coming to an agreement. I don't want to > repeat that discussion, just to point out, again, that Dmitry's opinion > is not universal. Far from it indeed. In order to follow the "simple dispatch" rule as described in OOTiA, one need to (almost) systematically re-dispatch. It seems to me that the vulnerabilities associated with not following the simple dispatch rule are significant: it is difficult to guarantee the integrity of the objects that are manipulated as soon as view conversions are used or some primitives ops are inherited while others are overridden. I understand the arguments in the other direction (against redispatch) but they do not look so compelling to me, especially in a context where LSP is understood and verified. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 12:55 ` Cyrille @ 2010-09-13 13:55 ` Dmitry A. Kazakov 2010-09-13 21:13 ` J-P. Rosen 1 sibling, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 13:55 UTC (permalink / raw) On Mon, 13 Sep 2010 05:55:39 -0700 (PDT), Cyrille wrote: > Far from it indeed. In order to follow the "simple dispatch" rule as > described in OOTiA, one need to (almost) systematically re-dispatch. This rule mandates re-dispatch. > I understand the arguments in the other direction (against redispatch) > but they do not look so compelling to me, especially in a context > where LSP is understood and verified. There is no substitutability issue when manifested types of objects are honored. Actually it is the "simple dispatch" rule which can potentially violate substitutability by using the type T in place of the type S when dispatching to the operation of S. When the object is declared of the type T it is no matter whether it was S in one of its earlier lives or not. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 12:55 ` Cyrille 2010-09-13 13:55 ` Dmitry A. Kazakov @ 2010-09-13 21:13 ` J-P. Rosen 2010-09-21 13:57 ` Cyrille 1 sibling, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-13 21:13 UTC (permalink / raw) Le 13/09/2010 14:55, Cyrille a �crit : >> Some time ago on c.l.a. we had a long discussion on the goodness or >> badness of re-dispatch, without coming to an agreement. I don't want to >> repeat that discussion, just to point out, again, that Dmitry's opinion >> is not universal. > > Far from it indeed. In order to follow the "simple dispatch" rule as > described in OOTiA, one need to (almost) systematically re-dispatch. > It seems to me that the vulnerabilities associated with not following > the simple dispatch rule are significant: it is difficult to guarantee > the integrity of the objects that are manipulated as soon as view > conversions are used or some primitives ops are inherited while others > are overridden. > I understand the arguments in the other direction (against redispatch) > but they do not look so compelling to me, especially in a context > where LSP is understood and verified. These arguments make sense for languages without the notion of class-wide types. However, I think that redispatching can be replaced with class-wide operations, with great benefits from the POV of testing. Cyril, will you come to the workshop? That would be very valuable. -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 21:13 ` J-P. Rosen @ 2010-09-21 13:57 ` Cyrille 2010-09-21 14:19 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 107+ messages in thread From: Cyrille @ 2010-09-21 13:57 UTC (permalink / raw) On Sep 13, 11:13 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > These arguments make sense for languages without the notion of > class-wide types. all OO languages I'm aware of, have the notion of classwide types... They just don't make the distinction between a type on its own and a type with its derived types. If you think about it, it is a peculiar distinction at the "design" level. A horse is an animal... When I deal with animals, I must be ready to accept that maybe the animal I'm dealing with may be a horse, or may be something else. It's peculiar to expect it to be the pure notion of "animal" and nothing else... > However, I think that redispatching can be replaced > with class-wide operations, with great benefits from the POV of testing. In some cases, it may be true. Generally speaking, it is an important to distinguish between primitive operrations and class wide operations. They both have their use. If you are suggesting the rule "any primitive operation that calls another primitive op of the same type (that usually is when redispatch should occur) must be transformed into a class-wide operation", I'm afraid this is a fierce restriction... much fiercer than the simple dispatch rule... which imposes one particular style of programming. > Cyril, will you come to the workshop? That would be very valuable. No, I don't plan to go. Note that on our side, we are already working on our own set of recommendations... maybe we should try to find a vehicle more permanent than a conference to make a community effort on this... ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 13:57 ` Cyrille @ 2010-09-21 14:19 ` Dmitry A. Kazakov 2010-09-21 14:44 ` Cyrille 2010-09-21 14:32 ` J-P. Rosen 2010-09-21 14:50 ` (see below) 2 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-21 14:19 UTC (permalink / raw) On Tue, 21 Sep 2010 06:57:36 -0700 (PDT), Cyrille wrote: > On Sep 13, 11:13�pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > >> These arguments make sense for languages without the notion of >> class-wide types. > > all OO languages I'm aware of, have the notion of classwide types... > They just don't make the distinction between a type on its own and a > type with its derived types. If you think about it, it is a peculiar > distinction at the "design" level. It is a distinction between a member and a set where it belongs to. These are not equivalent. Furthermore a type may be member of more than one classes (sets of types). Also an operation may be primitive in more than one class (AKA multiple dispatch). In this context it is difficult to see how the model of re-dispatching primitive operations could be made feasible. > A horse is an animal... But animal is not necessary a horse. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 14:19 ` Dmitry A. Kazakov @ 2010-09-21 14:44 ` Cyrille 2010-09-21 16:25 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-21 14:44 UTC (permalink / raw) On Sep 21, 4:19 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > > It is a distinction between a member and a set where it belongs to. These > are not equivalent. not sure what you call "set" in this context... probably not the container of the same name ;-) > Furthermore a type may be member of more than one > classes (sets of types). Also an operation may be primitive in more than > one class (AKA multiple dispatch). in Ada? can you show an example? > > A horse is an animal... > > But animal is not necessary a horse. > right. so? ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 14:44 ` Cyrille @ 2010-09-21 16:25 ` Dmitry A. Kazakov 2010-09-21 17:11 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-21 16:25 UTC (permalink / raw) On Tue, 21 Sep 2010 07:44:51 -0700 (PDT), Cyrille wrote: > On Sep 21, 4:19�pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > wrote: >> >> It is a distinction between a member and a set where it belongs to. These >> are not equivalent. > > not sure what you call "set" in this context... probably not the > container of the same name ;-) Set as in mathematics. A class wide type has values corresponding to the values of types from the closure set, the closure set is build upon the relation <: (derived from). >> Furthermore a type may be member of more than one >> classes (sets of types). Also an operation may be primitive in more than >> one class (AKA multiple dispatch). > > in Ada? can you show an example? Both MI and MD partially exist in Ada. MI is restricted to interfaces. MD is restricted to diagonal multi-methods, e.g: type T is tagged ...; procedure MD_operation (X, Y : T); >>> A horse is an animal... >> >> But animal is not necessary a horse. > > right. so? horse /= animal -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 16:25 ` Dmitry A. Kazakov @ 2010-09-21 17:11 ` Georg Bauhaus 2010-09-21 18:11 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-21 17:11 UTC (permalink / raw) On 21.09.10 18:25, Dmitry A. Kazakov wrote: > MD is restricted to diagonal multi-methods, e.g: > > type T is tagged ...; > procedure MD_operation (X, Y : T); > >>>> A horse is an animal... >>> >>> But animal is not necessary a horse. >> >> right. so? > > horse /= animal It will help immensely, I think, at least those of us who do not do type theory on an every day basis, if we had a glossary of terms for interpreting expression like "horse /= animal". (And maybe add qualifying syntax for clarity.) The expression will then consist of names and symbols that can be understood to mean: - this in the general context, and - that in the context of Ada, - something at all. Perhaps some definitions and corollaries, too, like the ones you have given for "restricted multiple dispatch" where it exists? Do you happen to have some notes lying around, maybe, that could be c&p-ed here, for starters? Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 17:11 ` Georg Bauhaus @ 2010-09-21 18:11 ` Dmitry A. Kazakov 2010-09-23 20:00 ` Simon Wright 2010-09-24 13:30 ` Niklas Holsti 0 siblings, 2 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-21 18:11 UTC (permalink / raw) On Tue, 21 Sep 2010 19:11:33 +0200, Georg Bauhaus wrote: > On 21.09.10 18:25, Dmitry A. Kazakov wrote: > >> horse /= animal > > It will help immensely, I think, at least those of us who do > not do type theory on an every day basis, if we had a glossary > of terms for interpreting expression like "horse /= animal". Gosh, it was no more than just this: if horse is an animal that does not imply they are interchangeable. Compare: "all horses have hoofs" and "all animals have hoofs." is-a /= is member /= set Moreover: is-a /= substitutable (greeting to the LSP!) Compare: "some animals have tentacles" and "some horses have tentacles." Absence of unconditional substitutability is IMO a killer argument against re-dispatch, because then see what J-P. Rosen wrote about testing. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 18:11 ` Dmitry A. Kazakov @ 2010-09-23 20:00 ` Simon Wright 2010-09-23 20:49 ` Dmitry A. Kazakov 2010-09-24 13:30 ` Niklas Holsti 1 sibling, 1 reply; 107+ messages in thread From: Simon Wright @ 2010-09-23 20:00 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > Gosh, it was no more than just this: if horse is an animal that does > not imply they are interchangeable. Compare: "all horses have hoofs" > and "all animals have hoofs." I don't see your point. You could make a near-infinity of operations on Animal like has-hooves, has-tentacles etc but that would be silly. The only ops that make sense at the Animal level are ones shared by all animals. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 20:00 ` Simon Wright @ 2010-09-23 20:49 ` Dmitry A. Kazakov 2010-09-24 9:10 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-23 20:49 UTC (permalink / raw) On Thu, 23 Sep 2010 21:00:01 +0100, Simon Wright wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > >> Gosh, it was no more than just this: if horse is an animal that does >> not imply they are interchangeable. Compare: "all horses have hoofs" >> and "all animals have hoofs." > > I don't see your point. It was: the type /horse/ is not the type /animal/. That is not because of Ada's choice to keep them apart, it is because they are behaviorally (semantically) different. > You could make a near-infinity of operations on Animal like has-hooves, > has-tentacles etc but that would be silly. The only ops that make sense > at the Animal level are ones shared by all animals. All primitive operations are already shared, if it were only about type checks there would be nothing to discuss. Ada checks types. Beyond nominal checks, comparing two related types like horse and animal one considers substitutability. S is substitutable for T when any predicate P(T) remains true after substitution S for T. LSP subtype as defined by Liskov & Wang are those maintaining substitutability. (All possible predicates exhaustively determine what in OO is called behavior. This is why Liskov & Wang named it "behavioral notion of subtype.") My example illustrated existence of predicates turning false. Thus horse is not animal and animal is not horse (yet *a* horse is *an* animal). It is a tautology: a subset which is the whole set is not the whole set. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 20:49 ` Dmitry A. Kazakov @ 2010-09-24 9:10 ` Georg Bauhaus 2010-09-24 10:24 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-24 9:10 UTC (permalink / raw) On 9/23/10 10:49 PM, Dmitry A. Kazakov wrote: > On Thu, 23 Sep 2010 21:00:01 +0100, Simon Wright wrote: > >> "Dmitry A. Kazakov"<mailbox@dmitry-kazakov.de> writes: >> >>> Gosh, it was no more than just this: if horse is an animal that does >>> not imply they are interchangeable. Compare: "all horses have hoofs" >>> and "all animals have hoofs." >> >> I don't see your point. > > It was: the type /horse/ is not the type /animal/. That is not because of > Ada's choice to keep them apart, it is because they are behaviorally > (semantically) different. > >> You could make a near-infinity of operations on Animal like has-hooves, >> has-tentacles etc but that would be silly. The only ops that make sense >> at the Animal level are ones shared by all animals. > > All primitive operations are already shared, if it were only about type > checks there would be nothing to discuss. Ada checks types. > > Beyond nominal checks, comparing two related types like horse and animal > one considers substitutability. S is substitutable for T when any predicate > P(T) remains true after substitution S for T. LSP subtype as defined by > Liskov& Wang Wing, Jeanette M. > are those maintaining substitutability. (All possible > predicates exhaustively determine what in OO is called behavior. This is > why Liskov& Wang named it "behavioral notion of subtype.") My example > illustrated existence of predicates turning false. Thus horse is not animal > and animal is not horse (yet *a* horse is *an* animal). It is a tautology: > a subset which is the whole set is not the whole set. [Just trying to follow.] "Subtype Requirement: Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T." (Where "property" is defined a little later.) The authors emphasize that while Stack and Queue may share operations, this type checked sharing of operations is not enough. It does not guarantee that the programs will work the same way if either is used, and likely not as expected. Not working correctly. "Properties of an object's behavior" refers to states and to sequences of states, as effected by prim ops: Invariants: P(state) = True for all states. History properties: P(state_1, state_2) = True for pairs of states. I think that in your example, Horse (S) is not a subtype of Animal (T), since Has-Hooves(x) cannot be proved for any x of type Animal. A Horse object can substitute an Animal object IFF all prim ops of Horse, including "extra methods", can all be expressed in terms of Animal's prim ops *and* respecting the conditions placed on the objects states and state sequences. The programs must behave the same, for Animals and Horses. (That's how I have understood the model so far.) Correct? That is, when I assign an object of type Horse to a variable of type Animal, then what matters is that the Animal program still behaves as would be correct for an Animal program. But not necessarily for a Horse program: The "apparent" type (L&W) of objects will be Animal, a specific type in Ada, and neither aliasing nor objects being used in a different context (view conversions in another partition, for example) will produce a state not correct for Animals. If the program behaves differently when I use a Horse object where an Animalis expected, then Horse is not a behavioral subtype of Animal. Correct? So, up to here, nothing in Liskov & Wing's Subtype Requirement (as quoted above) corresponds to Ada's Animal'Class. [Just to make sure I get the words right.] Correct? ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 9:10 ` Georg Bauhaus @ 2010-09-24 10:24 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-24 10:24 UTC (permalink / raw) On Fri, 24 Sep 2010 11:10:57 +0200, Georg Bauhaus wrote: > On 9/23/10 10:49 PM, Dmitry A. Kazakov wrote: >> On Thu, 23 Sep 2010 21:00:01 +0100, Simon Wright wrote: >> >>> "Dmitry A. Kazakov"<mailbox@dmitry-kazakov.de> writes: >>> >>>> Gosh, it was no more than just this: if horse is an animal that does >>>> not imply they are interchangeable. Compare: "all horses have hoofs" >>>> and "all animals have hoofs." >>> >>> I don't see your point. >> >> It was: the type /horse/ is not the type /animal/. That is not because of >> Ada's choice to keep them apart, it is because they are behaviorally >> (semantically) different. >> >>> You could make a near-infinity of operations on Animal like has-hooves, >>> has-tentacles etc but that would be silly. The only ops that make sense >>> at the Animal level are ones shared by all animals. >> >> All primitive operations are already shared, if it were only about type >> checks there would be nothing to discuss. Ada checks types. >> >> Beyond nominal checks, comparing two related types like horse and animal >> one considers substitutability. S is substitutable for T when any predicate >> P(T) remains true after substitution S for T. LSP subtype as defined by >> Liskov& Wang > > Wing, Jeanette M. Yes, I typed the name from my head without checking. >> are those maintaining substitutability. (All possible >> predicates exhaustively determine what in OO is called behavior. This is >> why Liskov& Wang named it "behavioral notion of subtype.") My example >> illustrated existence of predicates turning false. Thus horse is not animal >> and animal is not horse (yet *a* horse is *an* animal). It is a tautology: >> a subset which is the whole set is not the whole set. > > [Just trying to follow.] > > "Subtype Requirement: Let οΏ½(x) be a property provable about objects > x of type T. Then οΏ½(y) should be true for objects y of type S where > S is a subtype of T." > > (Where "property" is defined a little later.) > > The authors emphasize that while Stack and Queue may share operations, > this type checked sharing of operations is not enough. > It does not guarantee that the programs will work the same way if > either is used, and likely not as expected. Not working correctly. The word "provable" leaves much space for that. E.g. when the computing system has more power than the framework of proving. > "Properties of an object's behavior" refers to states and > to sequences of states, as effected by prim ops: > > Invariants: > P(state) = True for all states. > > History properties: > P(state_1, state_2) = True for pairs of states. > > I think that in your example, Horse (S) is not a subtype of Animal (T), > since Has-Hooves(x) cannot be proved for any x of type Animal. > A Horse object can substitute an Animal object IFF all prim ops > of Horse, including "extra methods", can all be expressed in terms > of Animal's prim ops *and* respecting the conditions placed on > the objects states and state sequences. Horse may have operations of its own. > The programs must behave > the same, for Animals and Horses. > (That's how I have understood the model so far.) > Correct? Depends on what is meant under "can be substituted," we have to distinguish an act of substitution in some given program and a set of programs, some of them non-existing, where substitution might happen. The former is much weaker. For example, in a concrete FORTRAN program you could substitute INTEGER for REAL and get away with that. L&W considered the latter case, there exist programs where such substitution would not work. > That is, when I assign an object of type Horse to a variable > of type Animal, then what matters is that the Animal program still > behaves as would be correct for an Animal program. But not necessarily > for a Horse program: The "apparent" type (L&W) of objects will be > Animal, a specific type in Ada, and neither aliasing nor objects being > used in a different context (view conversions in another partition, for > example) will produce a state not correct for Animals. > If the program behaves differently when I use a Horse object where > an Animalis expected, then Horse is not a behavioral subtype of Animal. > Correct? Yes, but more than that: if exists a program such that ... then it is not a LSP-subtype. [ However, the exemption of non-provable predicates may in the end mean anything. You could define "provable" in a way excluding predicates you didn't like. And that would not be just a cheat. For example, you would like to exclude predicates containing physical memory addresses of the objects, in some cases, and in some cases you would not. ] > So, up to here, nothing in Liskov & Wing's Subtype Requirement > (as quoted above) corresponds to Ada's Animal'Class. [Just to > make sure I get the words right.] > Correct? Hmm, there are 16 subtyping relations (<:) to consider here. You have horse, horse'Class, animal, animal'Class. There are more of them because we have to consider in-, out-, in out- "subtypes" of them, e.g. "in horse" and "return animal". Then come anonymous access types. They too can be substituted when the prefix notation used. E.g. Horse_Ptr.Feed. [ I presume that substitution = the language accepts usage of S, a type/subtype distinguishable from T, which was originally used in the operation profile.] -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 18:11 ` Dmitry A. Kazakov 2010-09-23 20:00 ` Simon Wright @ 2010-09-24 13:30 ` Niklas Holsti 2010-09-24 16:27 ` Dmitry A. Kazakov 1 sibling, 1 reply; 107+ messages in thread From: Niklas Holsti @ 2010-09-24 13:30 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Tue, 21 Sep 2010 19:11:33 +0200, Georg Bauhaus wrote: > >> On 21.09.10 18:25, Dmitry A. Kazakov wrote: >> >>> horse /= animal >> It will help immensely, I think, at least those of us who do >> not do type theory on an every day basis, if we had a glossary >> of terms for interpreting expression like "horse /= animal". > > Gosh, it was no more than just this: if horse is an animal that does not > imply they are interchangeable. Compare: "all horses have hoofs" and "all > animals have hoofs." > > is-a /= is > member /= set > > Moreover: > > is-a /= substitutable (greeting to the LSP!) > > Compare: "some animals have tentacles" and "some horses have tentacles." Those are not properties of "horses" and "animals", but properties of the *set* of horses and the *set* of animals. I don't think such properties have any role in LSP substitutability, as such properties often will be different for the whole set and for a proper subset. The property "all horses have hooves" expresses a universal property of horses: if X is a horse, then X has hooves. The statement "some horses have tentacles" says nothing about any given horse X. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 13:30 ` Niklas Holsti @ 2010-09-24 16:27 ` Dmitry A. Kazakov 2010-09-24 17:47 ` Niklas Holsti 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-24 16:27 UTC (permalink / raw) On Fri, 24 Sep 2010 16:30:29 +0300, Niklas Holsti wrote: > Dmitry A. Kazakov wrote: >> On Tue, 21 Sep 2010 19:11:33 +0200, Georg Bauhaus wrote: >> >>> On 21.09.10 18:25, Dmitry A. Kazakov wrote: >>> >>>> horse /= animal >>> It will help immensely, I think, at least those of us who do >>> not do type theory on an every day basis, if we had a glossary >>> of terms for interpreting expression like "horse /= animal". >> >> Gosh, it was no more than just this: if horse is an animal that does not >> imply they are interchangeable. Compare: "all horses have hoofs" and "all >> animals have hoofs." >> >> is-a /= is >> member /= set >> >> Moreover: >> >> is-a /= substitutable (greeting to the LSP!) >> >> Compare: "some animals have tentacles" and "some horses have tentacles." > > Those are not properties of "horses" and "animals", but properties of > the *set* of horses and the *set* of animals. horses is set of horses. > The property "all horses have hooves" expresses a universal property of > horses: if X is a horse, then X has hooves. The statement "some horses > have tentacles" says nothing about any given horse X. Both are predicates: forall x in horses, x has hooves exists x in animals, x has tentacles [ if you dropped existential quantification, you would not be able to describe functions returning values ] -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 16:27 ` Dmitry A. Kazakov @ 2010-09-24 17:47 ` Niklas Holsti 2010-09-24 19:42 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Niklas Holsti @ 2010-09-24 17:47 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Fri, 24 Sep 2010 16:30:29 +0300, Niklas Holsti wrote: > >> Dmitry A. Kazakov wrote: >>> On Tue, 21 Sep 2010 19:11:33 +0200, Georg Bauhaus wrote: >>> >>>> On 21.09.10 18:25, Dmitry A. Kazakov wrote: >>>> >>>>> horse /= animal >>>> It will help immensely, I think, at least those of us who do >>>> not do type theory on an every day basis, if we had a glossary >>>> of terms for interpreting expression like "horse /= animal". >>> Gosh, it was no more than just this: if horse is an animal that does not >>> imply they are interchangeable. Compare: "all horses have hoofs" and "all >>> animals have hoofs." >>> >>> is-a /= is >>> member /= set >>> >>> Moreover: >>> >>> is-a /= substitutable (greeting to the LSP!) >>> >>> Compare: "some animals have tentacles" and "some horses have tentacles." >> Those are not properties of "horses" and "animals", but properties of >> the *set* of horses and the *set* of animals. > > horses is set of horses. Incomprehensible. What do you mean? >> The property "all horses have hooves" expresses a universal property of >> horses: if X is a horse, then X has hooves. The statement "some horses >> have tentacles" says nothing about any given horse X. > > Both are predicates: No, they are formulas. "has_hooves(X)" is a predicate that can be true or false for a given object X. > forall x in horses, x has hooves That is a universally ("forall") quantified formula that uses the predicate has_hooves. The LSP "properties" are implicitly universally quantified. To quote http://reports-archive.adm.cs.cmu.edu/anon/1999/CMU-CS-99-156.ps, with implicit quantification inserted in [] by me: "/Subtype Requirement/: Let phi(x) be a property provable about [all] objects x of type T. Then phi(y) should be true for [all] objects of type S where S is a subtype of T." The following paragraph makes universal quantification clearer: "We focus on two kinds of properties, /invariants/, which are properties true of all states, and /history properties/ which are properties true of all sequences of states." > exists x in animals, x has tentacles So far as I understand LSP, existentially quantified formulas are not considered. Continuing the quote above: "We do not address other kinds of safety properties of computations, e.g. the existence of an object in a state,...". > [ if you dropped existential quantification, you would not be able to > describe functions returning values ] I don't think the LSP model of computation tries to, or needs to, describe functions in that sense; it uses postconditions which simply assume the existence of a return value and state properties of all possible return values. By the way, note the inclusion of "history properties" in the LSP, this is an important point that (I think) has been ignored in this discussion. For example, in order to show that the class of Squares is not an LSP subtype of the class of Rectangles one must use history properties and consider what happens when the program changes the width of a Square, seen as a Rectangle, without also changing the height to the same new value. A consequence is that LSP depends not only on the static properties of objects (has_hooves) but also on the set of "mutating" operations. If we were to define a Rectangle class that did not allow independent setting of width and height, but only a uniform size scaling, Squares would be an LSP subtype of these Rectangles. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 17:47 ` Niklas Holsti @ 2010-09-24 19:42 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-24 19:42 UTC (permalink / raw) On Fri, 24 Sep 2010 20:47:28 +0300, Niklas Holsti wrote: > Dmitry A. Kazakov wrote: >>> The property "all horses have hooves" expresses a universal property of >>> horses: if X is a horse, then X has hooves. The statement "some horses >>> have tentacles" says nothing about any given horse X. >> >> Both are predicates: > > No, they are formulas. "has_hooves(X)" is a predicate that can be true > or false for a given object X. The objects there are types. > A consequence is that LSP depends not only on the static properties of > objects (has_hooves) but also on the set of "mutating" operations. It depends on the properties of the set as a whole. Properties of individual objects cannot be contained they leak into the whole set and other types involved in the operations. > If we > were to define a Rectangle class that did not allow independent setting > of width and height, but only a uniform size scaling, Squares would be > an LSP subtype of these Rectangles. which would be forall s in Size, exists r in Rectangle, such that Height(r)=s and Width(r)=s Existential quantification cannot be avoided. Using mutators instead of results does not help. One could possibly limit LSP by narrowing the set of properties under consideration in an attempt to make it working. However, my impression is that the point where it starts working, is exactly one, where the corresponding subtype becomes useless. I considered LSP in a usable form, where, inevitably, nothing is a subtype of anything but itself. The other end is: anything is substitutable when types are OK (no properties beyond type membership). -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 13:57 ` Cyrille 2010-09-21 14:19 ` Dmitry A. Kazakov @ 2010-09-21 14:32 ` J-P. Rosen 2010-09-21 15:02 ` Cyrille 2010-09-21 14:50 ` (see below) 2 siblings, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-21 14:32 UTC (permalink / raw) Le 21/09/2010 15:57, Cyrille a �crit : > On Sep 13, 11:13 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > >> These arguments make sense for languages without the notion of >> class-wide types. > > all OO languages I'm aware of, have the notion of classwide types... > They just don't make the distinction between a type on its own and a > type with its derived types. That's exactly what I meant: they don't have a /distinct/ notion for class-wide type. > If you think about it, it is a peculiar > distinction at the "design" level. To distinguish a node from the subtree generated by this node? Does not seem peculiar to me > A horse is an animal... When I deal > with animals, I must be ready to accept that maybe the animal I'm > dealing with may be a horse, or may be something else. It's peculiar > to expect it to be the pure notion of "animal" and nothing else... I don't understand the argument here. Clearly, "Animal" should be abstract, and you can deal only with Animal'Class. >> However, I think that redispatching can be replaced >> with class-wide operations, with great benefits from the POV of testing. > > In some cases, it may be true. Generally speaking, it is an important > to distinguish between primitive operrations and class wide > operations. They both have their use. If you are suggesting the rule > "any primitive operation that calls another primitive op of the same > type (that usually is when redispatch should occur) must be > transformed into a class-wide operation", I'm afraid this is a fierce > restriction... much fiercer than the simple dispatch rule... which > imposes one particular style of programming. No, since the class-wide operation can contain a single (re-dispatching) call. What's the gain? We have concentrated the dispatching into a single subprogram. This subprogram can be tested in isolation, and stubbed in all users. Otherwise, under the "big case" model, every user must be tested for all branches of the "big case". In a sense, it is the opposite effect of inlining. Take the arguments against inlining, you'll have the justification for this strategy. >> Cyril, will you come to the workshop? That would be very valuable. > > No, I don't plan to go. Note that on our side, we are already working > on our own set of recommendations... maybe we should try to find a > vehicle more permanent than a conference to make a community effort on > this... The workshop at the conference is the starting point for a document that will define appropriate restrictions ("Fairfax profile"). Starting such an effort during an Ada conference seems absolutely appropriate. If AdaCore has plans along the same line, by all means, send someone to the workshop (if you can't come - which I regret, since I know that you are deeply involved on this topic). -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 14:32 ` J-P. Rosen @ 2010-09-21 15:02 ` Cyrille 2010-09-21 15:26 ` J-P. Rosen 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-21 15:02 UTC (permalink / raw) On Sep 21, 4:32 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > No, since the class-wide operation can contain a single (re-dispatching) > call. where does this rule come from? > What's the gain? We have concentrated the dispatching into a > single subprogram. This subprogram can be tested in isolation, and > stubbed in all users. Otherwise, under the "big case" model, every user > must be tested for all branches of the "big case". In a sense, it is the > opposite effect of inlining. Take the arguments against inlining, you'll > have the justification for this strategy. which strategy? you seem to be referring implicitly to a document that I'm not aware of. I'm not aware of any "serious" arguments against inlining which is simply a compiler technique for improving performance. > >> Cyril, will you come to the workshop? That would be very valuable. > > > No, I don't plan to go. Note that on our side, we are already working > > on our own set of recommendations... maybe we should try to find a > > vehicle more permanent than a conference to make a community effort on > > this... > > The workshop at the conference is the starting point for a document that > will define appropriate restrictions ("Fairfax profile"). Starting such > an effort during an Ada conference seems absolutely appropriate. It seems a bit early, DO-178C hasn't been published yet and people participating to such an effort will need time to access it once it is published and understand it. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 15:02 ` Cyrille @ 2010-09-21 15:26 ` J-P. Rosen 2010-09-21 16:18 ` Cyrille 0 siblings, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-21 15:26 UTC (permalink / raw) Le 21/09/2010 17:02, Cyrille a �crit : > which strategy? you seem to be referring implicitly to a document that > I'm not aware of. I'm not aware of any "serious" arguments against > inlining which is simply a compiler technique for improving > performance. The one that forbids redispatching in favour of class-wide operations. This can be done only in Ada, and can be a big plus for testing. For inlining, I was referring to the corresponding chapter of OOTiA >> The workshop at the conference is the starting point for a document that >> will define appropriate restrictions ("Fairfax profile"). Starting such >> an effort during an Ada conference seems absolutely appropriate. > > It seems a bit early, DO-178C hasn't been published yet and people > participating to such an effort will need time to access it once it is > published and understand it. I couldn't get my hands on DO-178C, but form what I heard it will be based (at least on the principles) on the work of OOTiA, which originated from the C++ community and ignores the possibilities offered by class-wide types - that was the starting point of this thread. -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 15:26 ` J-P. Rosen @ 2010-09-21 16:18 ` Cyrille 2010-09-22 8:01 ` J-P. Rosen 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-21 16:18 UTC (permalink / raw) > The one that forbids redispatching in favour of class-wide operations. > This can be done only in Ada, and can be a big plus for testing. Well, I don't see anything unique to Ada in that respect except terminology. In term of capabilities with regard to dispatching, at least. > For inlining, I was referring to the corresponding chapter of OOTiA That's what I supposed.... There is little to be reused in that part of the document... > >> The workshop at the conference is the starting point for a document that > >> will define appropriate restrictions ("Fairfax profile"). Starting such > >> an effort during an Ada conference seems absolutely appropriate. > > > It seems a bit early, DO-178C hasn't been published yet and people > > participating to such an effort will need time to access it once it is > > published and understand it. > > I couldn't get my hands on DO-178C, but form what I heard it will be > based (at least on the principles) on the work of OOTiA, which > originated from the C++ community and ignores the possibilities offered > by class-wide types - that was the starting point of this thread. It is not the case. There is very little of OOTiA left in the OO supplement. It was an input to the process but the subcommittee soon realized that little could be reused. For one thing, most of the material is at the level of "coding standard" material and thus not at the right level for a standard such as DO-178. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 16:18 ` Cyrille @ 2010-09-22 8:01 ` J-P. Rosen 2010-09-22 17:28 ` Cyrille 0 siblings, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-22 8:01 UTC (permalink / raw) Le 21/09/2010 18:18, Cyrille a �crit : >> The one that forbids redispatching in favour of class-wide operations. >> This can be done only in Ada, and can be a big plus for testing. > > Well, I don't see anything unique to Ada in that respect except > terminology. In term of capabilities with regard to dispatching, at > least. Ada is unique in that you can have true methods (aka primitive operations) that belong to a specific type, and class-wide operations that are unique for a whole subtree. Because they are unique, coverage testing drops from N to 1. >> For inlining, I was referring to the corresponding chapter of OOTiA > > That's what I supposed.... There is little to be reused in that part > of the document... I agree that there is nothing here specific to OO. However, inlining is a problem when you need level A (code) coverage, because it creates often dead code or hard to test paths. > It is not the case. There is very little of OOTiA left in the OO > supplement. It was an input to the process but the subcommittee soon > realized that little could be reused. For one thing, most of the > material is at the level of "coding standard" material and thus not at > the right level for a standard such as DO-178. Sure. I would expect DO-178C to be more objectives-driven, while the OOTiA was more about processes and issues. Can't OOTiA be considered as a document that explores possible ways to achieve the objectives of DO-178C? -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 8:01 ` J-P. Rosen @ 2010-09-22 17:28 ` Cyrille 2010-09-22 19:30 ` Ludovic Brenta 2010-09-24 8:16 ` J-P. Rosen 0 siblings, 2 replies; 107+ messages in thread From: Cyrille @ 2010-09-22 17:28 UTC (permalink / raw) On Sep 22, 10:01 am, "J-P. Rosen" <ro...@adalog.fr> wrote: > Ada is unique in that you can have true methods (aka primitive > operations) that belong to a specific type, and class-wide operations > that are unique for a whole subtree. what is unique about that? In C++ you also have methods and other subprograms taking a class as a parameter. I don't see any fundamental difference between the latter and what you call "classwide operations" (and by which I suppose you simply mean a subprogram with classwide parameters, right?) > Because they are unique, coverage testing drops from N to 1. No idea of what you are talking about... I suppose this is a reference to what OOTiA calls "pessimistic testing" but I still don't understand your claim. > >> For inlining, I was referring to the corresponding chapter of OOTiA > > > That's what I supposed.... There is little to be reused in that part > > of the document... > > I agree that there is nothing here specific to OO. However, inlining is > a problem when you need level A (code) coverage, because it creates > often dead code or hard to test paths. Level A requires statements+mcdc coverage. inlining doesn't impact any of those coverage metrics. It might impact object coverage, which can be used as an alternative method (with additional work to show equivalene with the aboce mentioned metrics) and it might also impact source-to-object traceability analysis. This is just a potentially complicating factor that you have to take into account when you make your plans and define your coding standard... > > It is not the case. There is very little of OOTiA left in the OO > > supplement. It was an input to the process but the subcommittee soon > > realized that little could be reused. For one thing, most of the > > material is at the level of "coding standard" material and thus not at > > the right level for a standard such as DO-178. > > Sure. I would expect DO-178C to be more objectives-driven, while the > OOTiA was more about processes and issues. Can't OOTiA be considered as > a document that explores possible ways to achieve the objectives of DO-178C? not really. OOTiA raised all the issues that people had in mind when the document was written. Most of the issues come from either - people from the certif community not knowing OO very well (the fear factor) - people from the OO community not mastering DO-178 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 17:28 ` Cyrille @ 2010-09-22 19:30 ` Ludovic Brenta 2010-09-22 19:51 ` Florian Weimer 2010-09-23 16:51 ` Pascal Obry 2010-09-24 8:16 ` J-P. Rosen 1 sibling, 2 replies; 107+ messages in thread From: Ludovic Brenta @ 2010-09-22 19:30 UTC (permalink / raw) Cyrille Comar writes on comp.lang.ada: > On Sep 22, 10:01 am, "J-P. Rosen" <ro...@adalog.fr> wrote: >> Ada is unique in that you can have true methods (aka primitive >> operations) that belong to a specific type, and class-wide operations >> that are unique for a whole subtree. > > what is unique about that? In C++ you also have methods and other > subprograms taking a class as a parameter. I don't see any fundamental > difference between the latter and what you call "classwide > operations" (and by which I suppose you simply mean a subprogram with > classwide parameters, right?) > >> Because they are unique, coverage testing drops from N to 1. > > No idea of what you are talking about... I suppose this is a reference > to what OOTiA calls "pessimistic testing" but I still don't understand > your claim. > >>>> For inlining, I was referring to the corresponding chapter of OOTiA >> >>> That's what I supposed.... There is little to be reused in that part >>> of the document... >> >> I agree that there is nothing here specific to OO. However, inlining is >> a problem when you need level A (code) coverage, because it creates >> often dead code or hard to test paths. > > Level A requires statements+mcdc coverage. inlining doesn't impact any > of those coverage metrics. It might impact object coverage, which can > be used as an alternative method (with additional work to show > equivalene with the aboce mentioned metrics) My understanding (from the days when I worked at Barco Avionics) was that level A requires full path (MC/DC) coverage at the object level, not the source level. This includes proof of absence of dead object code. The only practical way to achieve this is source-level MC/DC coverage *plus* complete source-to-object traceability, including proof of absence of object code not corresponding to any source. In fact, this is the essential difference between levels A and B. > and it might also impact > source-to-object traceability analysis. This is just a potentially > complicating factor that you have to take into account when you make > your plans and define your coding standard... Oh, you said "just"! >>> It is not the case. There is very little of OOTiA left in the OO >>> supplement. It was an input to the process but the subcommittee soon >>> realized that little could be reused. For one thing, most of the >>> material is at the level of "coding standard" material and thus not at >>> the right level for a standard such as DO-178. >> >> Sure. I would expect DO-178C to be more objectives-driven, while the >> OOTiA was more about processes and issues. Can't OOTiA be considered as >> a document that explores possible ways to achieve the objectives of DO-178C? > > not really. OOTiA raised all the issues that people had in mind when > the document was written. Most of the issues come from either > - people from the certif community not knowing OO very well (the > fear factor) > - people from the OO community not mastering DO-178 And people not knowing Ada and thinking that the only OO language was C++. I totally agree with Jean-Pierre that Ada has made a very important contribution to OO technology in distinguishing class-wide from specific types; C++ does not have class-wide types, it only has class-wide *pointer* (and reference) types; and it conversely does not have specific pointer or reference types. Consider: type T is tagged private; function Construct return T'Class; type T_Access is access all T; -- no equivalent in C++ type T_Class_Access is access all T'Class; -- equivalent to T* in C++ Object : T'Class := Construct; -- no equivalent in C++; you need a pointer Another area where Ada helps certification is where it distinguishes pool-specific from general access types. C and C++ are both completely helpless in this respect. Consider: type T_Access is access T'Class; -- no equivalent in C++ type T_General_Access is access all T'Class; -- equivalent to T* in C++ Hey, just a wild idea: how about type T_Stack_Access is access aliased T; which indicates that access values of this type can *only* designate aliased objects that are on the stack, and never on the heap? -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 19:30 ` Ludovic Brenta @ 2010-09-22 19:51 ` Florian Weimer 2010-09-22 20:14 ` Dmitry A. Kazakov 2010-09-22 20:16 ` Ludovic Brenta 2010-09-23 16:51 ` Pascal Obry 1 sibling, 2 replies; 107+ messages in thread From: Florian Weimer @ 2010-09-22 19:51 UTC (permalink / raw) * Ludovic Brenta: > Another area where Ada helps certification is where it distinguishes > pool-specific from general access types. C and C++ are both completely > helpless in this respect. Consider: > > type T_Access is access T'Class; -- no equivalent in C++ > type T_General_Access is access all T'Class; -- equivalent to T* in C++ Iterators are examples of pool-specific allocators in C++. It's also common to define your own pointer types in C++. It's hard to beat the C++ type system in terms of expressiveness. > Hey, just a wild idea: how about > > type T_Stack_Access is access aliased T; > > which indicates that access values of this type can *only* designate > aliased objects that are on the stack, and never on the heap? I don't think this would provide useful information. Tasks blur the boundary between heap and stack allocation. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 19:51 ` Florian Weimer @ 2010-09-22 20:14 ` Dmitry A. Kazakov 2010-09-22 20:25 ` Florian Weimer 2010-09-22 20:16 ` Ludovic Brenta 1 sibling, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-22 20:14 UTC (permalink / raw) On Wed, 22 Sep 2010 21:51:16 +0200, Florian Weimer wrote: > * Ludovic Brenta: > > It's hard to beat the > C++ type system in terms of expressiveness. As someone designing component libraries for both Ada and C++ I would say that the C++'s type system is far behind Ada. Though C++ has some substantial and evident advantages over Ada, e.g. proper constructors, proper MI, partial inheritance from concrete types, that does not pay off, because the rest is too bad. At least to me, it is impossible to achieve consistency and clearness of design any close to what can be done in Ada. Looking at C++ class libraries designed by other people assures me that I am not alone. >> Hey, just a wild idea: how about >> >> type T_Stack_Access is access aliased T; >> >> which indicates that access values of this type can *only* designate >> aliased objects that are on the stack, and never on the heap? > > I don't think this would provide useful information. Tasks blur the > boundary between heap and stack allocation. Stack/heap allocation refer to a memory management policy rather than physical location. This boundary is very sharp: the stack policy presumes two important constraints: 1. LIFO ordering, 2. Ownership by the task. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:14 ` Dmitry A. Kazakov @ 2010-09-22 20:25 ` Florian Weimer 2010-09-22 20:38 ` Dmitry A. Kazakov 2010-09-22 21:20 ` Georg Bauhaus 0 siblings, 2 replies; 107+ messages in thread From: Florian Weimer @ 2010-09-22 20:25 UTC (permalink / raw) * Dmitry A. Kazakov: > On Wed, 22 Sep 2010 21:51:16 +0200, Florian Weimer wrote: >> It's hard to beat the C++ type system in terms of expressiveness. > > As someone designing component libraries for both Ada and C++ I would say > that the C++'s type system is far behind Ada. Though C++ has some > substantial and evident advantages over Ada, e.g. proper constructors, > proper MI, partial inheritance from concrete types, that does not pay off, > because the rest is too bad. > > At least to me, it is impossible to achieve consistency and clearness of > design any close to what can be done in Ada. Looking at C++ class libraries > designed by other people assures me that I am not alone. I don't doubt that this has been your experience, but this in no way contradicts that the C++ type system is way more expressive than Ada's. It's probably the other way round: C++ is too expressive, and it is difficult to find the right amount of type-level programming. >>> Hey, just a wild idea: how about >>> >>> type T_Stack_Access is access aliased T; >>> >>> which indicates that access values of this type can *only* designate >>> aliased objects that are on the stack, and never on the heap? >> >> I don't think this would provide useful information. Tasks blur the >> boundary between heap and stack allocation. > > Stack/heap allocation refer to a memory management policy rather than > physical location. This boundary is very sharp: the stack policy presumes > two important constraints: 1. LIFO ordering, 2. Ownership by the task. Neither is true if you can create tasks dynamically. Instead of using an allocator, you just wrap the object to be created in a task, where you put it on the stack. In effect, you have bypassed both constraints (because the owner is not you, but some other task). ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:25 ` Florian Weimer @ 2010-09-22 20:38 ` Dmitry A. Kazakov 2010-09-22 21:25 ` Vinzent Hoefler 2010-09-22 21:20 ` Georg Bauhaus 1 sibling, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-22 20:38 UTC (permalink / raw) On Wed, 22 Sep 2010 22:25:46 +0200, Florian Weimer wrote: >> Stack/heap allocation refer to a memory management policy rather than >> physical location. This boundary is very sharp: the stack policy presumes >> two important constraints: 1. LIFO ordering, 2. Ownership by the task. > > Neither is true if you can create tasks dynamically. Instead of using > an allocator, you just wrap the object to be created in a task, where > you put it on the stack. In effect, you have bypassed both > constraints (because the owner is not you, but some other task). No, unfortunately task entries returning objects are not allowed, if that is what you meant. But if they were allowed, they would copy out. (I don't consider the ugly limited return from functions. That was a language design bug.) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:38 ` Dmitry A. Kazakov @ 2010-09-22 21:25 ` Vinzent Hoefler 0 siblings, 0 replies; 107+ messages in thread From: Vinzent Hoefler @ 2010-09-22 21:25 UTC (permalink / raw) On Wed, 22 Sep 2010 22:38:22 +0200, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > On Wed, 22 Sep 2010 22:25:46 +0200, Florian Weimer wrote: > >>> Stack/heap allocation refer to a memory management policy rather than >>> physical location. This boundary is very sharp: the stack policy >>> presumes >>> two important constraints: 1. LIFO ordering, 2. Ownership by the task. >> >> Neither is true if you can create tasks dynamically. Instead of using >> an allocator, you just wrap the object to be created in a task, where >> you put it on the stack. In effect, you have bypassed both >> constraints (because the owner is not you, but some other task). > > No, unfortunately task entries returning objects are not allowed, if that > is what you meant. Florian probably meant it more like this: | task type Data_Task is | entry Get_Data (Y : out Data_Access); | end Data_Task; | | task body Data_Task is | X : aliased Data; | begin | loop | accept Leak_Data (Y : out Data_Access) do | Y := X'Unchecked_Access; | end Leak_Data; | end loop; | end Data_Task; A proper set of Restrictions pragmas should easily prevent this. In fact, "pragma Restrictions (No_Unchecked_Access)" should even be sufficient to prevent a task from leaking it's own data to the outside. And if the task allocated X on the heap, the access types wouldn't match anyway. Vinzent. -- There is no signature. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:25 ` Florian Weimer 2010-09-22 20:38 ` Dmitry A. Kazakov @ 2010-09-22 21:20 ` Georg Bauhaus 1 sibling, 0 replies; 107+ messages in thread From: Georg Bauhaus @ 2010-09-22 21:20 UTC (permalink / raw) On 9/22/10 10:25 PM, Florian Weimer wrote: > * Dmitry A. Kazakov: >> At least to me, it is impossible to achieve consistency and clearness of >> design any close to what can be done in Ada. Looking at C++ class libraries >> designed by other people assures me that I am not alone. > > I don't doubt that this has been your experience, but this in no way > contradicts that the C++ type system is way more expressive than > Ada's. The bi-weekly CVEs demonstrate that C++'s fundamental type system, by choice still basically C's, is such that all the expressiveness built on top of it will not effectively compensate. So let's not go nuts and recognize instead that a fantastically powerful type system is just as important as making programmers understand "int". ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 19:51 ` Florian Weimer 2010-09-22 20:14 ` Dmitry A. Kazakov @ 2010-09-22 20:16 ` Ludovic Brenta 2010-09-22 20:34 ` Florian Weimer 1 sibling, 1 reply; 107+ messages in thread From: Ludovic Brenta @ 2010-09-22 20:16 UTC (permalink / raw) Florian Weimer writes on comp.lang.ada: > * Ludovic Brenta: > >> Another area where Ada helps certification is where it distinguishes >> pool-specific from general access types. C and C++ are both completely >> helpless in this respect. Consider: >> >> type T_Access is access T'Class; -- no equivalent in C++ >> type T_General_Access is access all T'Class; -- equivalent to T* in C++ > > Iterators are examples of pool-specific allocators in C++. How so? IIUC, iterators are not even a language construct, only an idiom in the standard library. > It's also common to define your own pointer types in C++. Do you mean that typedef T* T_Pointer; is common? > It's hard to beat the C++ type system in terms of expressiveness. I disagree; I just showed the opposite in my previous post. C++ does not have specific pointer types, for example; only class-wide ones. >> Hey, just a wild idea: how about >> >> type T_Stack_Access is access aliased T; >> >> which indicates that access values of this type can *only* designate >> aliased objects that are on the stack, and never on the heap? > > I don't think this would provide useful information. Tasks blur the > boundary between heap and stack allocation. Insofar as each new task creates a stack from the heap of the environment task, yes. But the Ravenscar profile forbids this, so the "access aliased" feature might be useful in this context, which happens to be the context where certification is needed. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:16 ` Ludovic Brenta @ 2010-09-22 20:34 ` Florian Weimer 2010-09-22 22:45 ` Britt Snodgrass 2010-09-23 8:02 ` Ludovic Brenta 0 siblings, 2 replies; 107+ messages in thread From: Florian Weimer @ 2010-09-22 20:34 UTC (permalink / raw) * Ludovic Brenta: > Florian Weimer writes on comp.lang.ada: >> * Ludovic Brenta: >> >>> Another area where Ada helps certification is where it distinguishes >>> pool-specific from general access types. C and C++ are both completely >>> helpless in this respect. Consider: >>> >>> type T_Access is access T'Class; -- no equivalent in C++ >>> type T_General_Access is access all T'Class; -- equivalent to T* in C++ >> >> Iterators are examples of pool-specific allocators in C++. > > How so? IIUC, iterators are not even a language construct, only an > idiom in the standard library. C++ is so flexible that you can express the concept of a pointer in a library. In the same way, you could argue that C++ does not support numerics because it hasn't got a power operator. 8-) >> It's also common to define your own pointer types in C++. > > Do you mean that > > typedef T* T_Pointer; > > is common? Many C++ libraries have their own variants of the std::shared_ptr and std::unique_ptr templates. >> It's hard to beat the C++ type system in terms of expressiveness. > > I disagree; I just showed the opposite in my previous post. C++ does > not have specific pointer types, for example; only class-wide ones. C++ does not need them because the language is so expressive that you can *define* your own pointer types. Their type constructor is syntactically different from language-provided pointers. But a factorial function in Ada is syntactically different from built-in operators, too. Does that mean that Ada does not properly support the factorial function? Clearly not. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:34 ` Florian Weimer @ 2010-09-22 22:45 ` Britt Snodgrass 2010-09-23 8:02 ` Ludovic Brenta 1 sibling, 0 replies; 107+ messages in thread From: Britt Snodgrass @ 2010-09-22 22:45 UTC (permalink / raw) On Sep 22, 3:34 pm, Florian Weimer <f...@deneb.enyo.de> wrote: > C++ does not need them because the language is so expressive that you > can *define* your own pointer types. Perhaps you meant to say "permissive" rather than "expressive". I agree with the description of these two words as described in the following article: http://www.eetimes.com/design/eda-design/4008921/Expressive-vs-permissive-languages--Is-that-the-question- - Britt ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:34 ` Florian Weimer 2010-09-22 22:45 ` Britt Snodgrass @ 2010-09-23 8:02 ` Ludovic Brenta 1 sibling, 0 replies; 107+ messages in thread From: Ludovic Brenta @ 2010-09-23 8:02 UTC (permalink / raw) Florian Weimer wrote on comp.lang.ada: >>> Iterators are examples of pool-specific allocators in C++. > >> How so? IIUC, iterators are not even a language construct, only an >> idiom in the standard library. > > C++ is so flexible that you can express the concept of a pointer in a > library. In the same way, you could argue that C++ does not support > numerics because it hasn't got a power operator. 8-) Ah, I think I understand what you mean now: any type that has a dereference operator (operator*() or operator->(), IIRC) is a pointer type, right? Sorry, I disagree with that. Pointer types are definite and elementary. An arbitrary C++ type with operator* is not always definite or elementary. This becomes important in the context of safety-critical software; the fact that pointer types are elementary guarantees that no dynamic dispatching occurs when you call an operator of the type; that you can store them in registers, convert them to and from hardware addresses and apply representation clauses to them without worrying where to store the tag. The fact that they are definite means you can store them efficiently in containers, with shallow copy semantics. Ah but perhaps C++ lacks indefinite types, too? -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 19:30 ` Ludovic Brenta 2010-09-22 19:51 ` Florian Weimer @ 2010-09-23 16:51 ` Pascal Obry 2010-09-23 18:37 ` Florian Weimer 2010-09-23 20:28 ` Ludovic Brenta 1 sibling, 2 replies; 107+ messages in thread From: Pascal Obry @ 2010-09-23 16:51 UTC (permalink / raw) To: Ludovic Brenta Ludovic, > And people not knowing Ada and thinking that the only OO language was > C++. I totally agree with Jean-Pierre that Ada has made a very > important contribution to OO technology in distinguishing class-wide > from specific types; Well this was part of Smalltalk since the beginning. Not sure Ada has invented anything there :) Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net - http://v2p.fr.eu.org --| "The best way to travel is by means of imagination" --| --| gpg --keyserver keys.gnupg.net --recv-key F949BD3B ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 16:51 ` Pascal Obry @ 2010-09-23 18:37 ` Florian Weimer 2010-09-23 18:55 ` Pascal Obry 2010-09-23 20:28 ` Ludovic Brenta 1 sibling, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-23 18:37 UTC (permalink / raw) * Pascal Obry: > Ludovic, > >> And people not knowing Ada and thinking that the only OO language was >> C++. I totally agree with Jean-Pierre that Ada has made a very >> important contribution to OO technology in distinguishing class-wide >> from specific types; > > Well this was part of Smalltalk since the beginning. Not sure Ada has > invented anything there :) Smalltalk has compile-time types? I don't think so. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 18:37 ` Florian Weimer @ 2010-09-23 18:55 ` Pascal Obry 0 siblings, 0 replies; 107+ messages in thread From: Pascal Obry @ 2010-09-23 18:55 UTC (permalink / raw) Florian, > Smalltalk has compile-time types? I don't think so. I'm speaking of class-wide vs specific types. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net - http://v2p.fr.eu.org --| "The best way to travel is by means of imagination" --| --| gpg --keyserver keys.gnupg.net --recv-key F949BD3B ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 16:51 ` Pascal Obry 2010-09-23 18:37 ` Florian Weimer @ 2010-09-23 20:28 ` Ludovic Brenta 2010-09-24 9:20 ` Ludovic Brenta 2010-09-25 7:10 ` Pascal Obry 1 sibling, 2 replies; 107+ messages in thread From: Ludovic Brenta @ 2010-09-23 20:28 UTC (permalink / raw) Pascal Obry writes on comp.lang.ada: > Ludovic, > >> And people not knowing Ada and thinking that the only OO language was >> C++. I totally agree with Jean-Pierre that Ada has made a very >> important contribution to OO technology in distinguishing class-wide >> from specific types; > > Well this was part of Smalltalk since the beginning. Not sure Ada has > invented anything there :) I do not remember anything in Smalltalk resembling class-wide types; could you please send me an URL? I'm curious. I do remember about class objects (objects representing classes, with methods such as "new" which create instances of the class). Java introspection similarly has class objects but not class-wide types. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 20:28 ` Ludovic Brenta @ 2010-09-24 9:20 ` Ludovic Brenta 2010-09-24 14:49 ` Simon Wright 2010-09-24 16:21 ` Robert A Duff 2010-09-25 7:10 ` Pascal Obry 1 sibling, 2 replies; 107+ messages in thread From: Ludovic Brenta @ 2010-09-24 9:20 UTC (permalink / raw) Ludovic Brenta wrote on comp.lang.ada: > Pascal Obry writes on comp.lang.ada: > >> Ludovic, > >>> And people not knowing Ada and thinking that the only OO language was >>> C++. I totally agree with Jean-Pierre that Ada has made a very >>> important contribution to OO technology in distinguishing class-wide >>> from specific types; > >> Well this was part of Smalltalk since the beginning. Not sure Ada has >> invented anything there :) > > I do not remember anything in Smalltalk resembling class-wide types; > could you please send me an URL? I'm curious. In fact, after reading up a little bit on Smalltalk, it seems that every message sent to an object (i.e. primitive operation call) dispatches dynamically; the programmer does not seem to have a way to prevent that. As a consequence, a method that sends a message to "self" redispatches dynamically, every time. This leads to what Smalltalk programmers call "the yo-yo problem" whereby a single message (primitive operation call) can in turn cause multiple calls up and down the inheritance tree; this makes it difficult for programmers to follow the flow of control. I believe this is exactly the reason why Dmitry hates redispatching so much. Ada lets programmers choose whether a primitive operation call dispatches statically or dynamically, at the call site. To redispatch dynamically, you do a view conversion to the class-wide type; this is why class-wide types exist in the first place. Also, during code review, you can easily see distinguish dynamic calls from static calls. I believe that, if Smalltalk had class-wide types, it would be able to prevent "the yo-yo problem" just like Ada does. This "yo-yo problem" also exists in Objective-C. In C++, you can force static calls by qualifying the call, e.g. void T::method1 () { this->method2(); // dynamic redispatch: "this" is of a class-wide pointer type this->T::method2(); // static call due to explicit qualifier } -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 9:20 ` Ludovic Brenta @ 2010-09-24 14:49 ` Simon Wright 2010-09-24 15:09 ` Ludovic Brenta 2010-09-24 16:21 ` Robert A Duff 1 sibling, 1 reply; 107+ messages in thread From: Simon Wright @ 2010-09-24 14:49 UTC (permalink / raw) Ludovic Brenta <ludovic@ludovic-brenta.org> writes: > I believe that, if Smalltalk had class-wide types, it would be able to > prevent "the yo-yo problem" just like Ada does. Not sure that the designers of Smalltalk would have described this as a 'problem'! ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 14:49 ` Simon Wright @ 2010-09-24 15:09 ` Ludovic Brenta 0 siblings, 0 replies; 107+ messages in thread From: Ludovic Brenta @ 2010-09-24 15:09 UTC (permalink / raw) Simon Wright wrote on comp.lang.ada: > Ludovic Brenta <ludo...@ludovic-brenta.org> writes: >> I believe that, if Smalltalk had class-wide types, it would be able to >> prevent "the yo-yo problem" just like Ada does. > > Not sure that the designers of Smalltalk would have described this as a > 'problem'! No, only users of the language called it that. Also, this "problem" became prevalent only in the field, with deep inheritance hierarchies and large systems, after the language was designed. Objective-C, Java and, apparently, Object Pascal replicated this same "problem". In these languages, you have no choice but to redispatch every time. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 9:20 ` Ludovic Brenta 2010-09-24 14:49 ` Simon Wright @ 2010-09-24 16:21 ` Robert A Duff 1 sibling, 0 replies; 107+ messages in thread From: Robert A Duff @ 2010-09-24 16:21 UTC (permalink / raw) Ludovic Brenta <ludovic@ludovic-brenta.org> writes: > In fact, after reading up a little bit on Smalltalk, it seems that > every message sent to an object (i.e. primitive operation call) > dispatches dynamically; the programmer does not seem to have a way to > prevent that. Yeah, except for the case of "super". > This "yo-yo problem" also exists in Objective-C. Objective C is essentially just Smalltalk semantics bolted onto C. It's like two languages in one. - Bob ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-23 20:28 ` Ludovic Brenta 2010-09-24 9:20 ` Ludovic Brenta @ 2010-09-25 7:10 ` Pascal Obry 2010-09-25 12:03 ` Brian Drummond 1 sibling, 1 reply; 107+ messages in thread From: Pascal Obry @ 2010-09-25 7:10 UTC (permalink / raw) Ludovic, > I do not remember anything in Smalltalk resembling class-wide types; > could you please send me an URL? I'm curious. My Smalltalk is maybe rusty but I remember about Metaclass. A side of the class definition where a variable is a class variable shared by every instance and where a method is a class method shared also by every instance. This looks like class-wide variable/method applied to some kind of class-wide type (the metaclass). Now, as I said my Smalltalk is rusty and I may have misremembered something. Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net - http://v2p.fr.eu.org --| "The best way to travel is by means of imagination" --| --| gpg --keyserver keys.gnupg.net --recv-key F949BD3B ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-25 7:10 ` Pascal Obry @ 2010-09-25 12:03 ` Brian Drummond 0 siblings, 0 replies; 107+ messages in thread From: Brian Drummond @ 2010-09-25 12:03 UTC (permalink / raw) On Sat, 25 Sep 2010 09:10:58 +0200, Pascal Obry <pascal@obry.net> wrote: >Ludovic, > >> I do not remember anything in Smalltalk resembling class-wide types; >> could you please send me an URL? I'm curious. > >My Smalltalk is maybe rusty but I remember about Metaclass. A side of >the class definition where a variable is a class variable shared by >every instance and where a method is a class method shared also by >every instance. This looks like class-wide variable/method applied to >some kind of class-wide type (the metaclass). > >Now, as I said my Smalltalk is rusty and I may have misremembered something. > >Pascal. My understanding (from Linn Lingo which had Smalltalk-like semantics but a more block-structured syntax) was that class variables and class methods actually applied to the class itself (or derived classes), rather than instances of those classes. Thus a Bounded_String class would have a class variable describing (and perhaps allowing you to manipulate) the upper bound of the string size - this would be used by the constructor for all Bounded_Strings. Class methods relate to the class - e.g. to get/set the class variable above, or describing properties of the class (e.g. "Integer max" = 2^31 - 1) Every class has two methods which list the "instance methods" defined for an instance of the class - one listing the methods defined for the class itself, another listing all methods in the hierarchy above it, back to Object. (possibly TMI : in Lingo it actually returns the selectors - tokens - rather than the methods themselves; finding the methods from there is trivial) "Integer instanceSelectors" (or even "2 class instanceSelectors") returns + - * / asString printedOn: asFloat and others. "Integer inheritedInstanceSelectors" returns the same plus inherited methods (obviously including "class", to support "2 class" above) There are similar methods to return the class methods: "classSelectors" and "inheritedClassSelectors". Their typical implementation is to return "instanceSelectors" on the Metaclass object (a class variable) belonging to the class itself. Thus Metaclass does not seem to be related to class-wide types, but a mechanism for implementing Class as a first-class object. Ludovic is correct on dynamic despatch. It need not be slow; (there are optimisations) but it does hide the flow of control (or abstract over it!) - Brian ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 17:28 ` Cyrille 2010-09-22 19:30 ` Ludovic Brenta @ 2010-09-24 8:16 ` J-P. Rosen 2010-09-24 8:39 ` Cyrille 1 sibling, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-24 8:16 UTC (permalink / raw) Le 22/09/2010 19:28, Cyrille a �crit : >> Because they are unique, coverage testing drops from N to 1. > > No idea of what you are talking about... I suppose this is a reference > to what OOTiA calls "pessimistic testing" but I still don't understand > your claim. > Let's take an example: type T is tagged...; procedure M1 (X : T); procedure M2 (X : T); procedure M1 (X : T) is begin ... M2 (T'class (X)); -- Redispatching end M1; Under the "big case" model, the dispatching call is equivalent to a case statement where each branch corresponds to one of the classes that inherit from T. Therefore, coverage testing will require that M1 (and similarly every primitive operation that includes at least one redispatching) be tested for every descendant of T (even if M1 is redefined by a class D rather than inherited, it is possible to call the original one with a parameter of type D with a conversion). If you define: procedure M2_Class (X : T'class) is begin M2 (X); end M2_Class; and replace every redispatching call to M2 by a call to M2_Class, then the big case disappears. You need (of course) to check coverage for M2_Class, but M1 needs to be checked only for values of type T, not for descendants. That's what I meant when I said that coverage testing drops from N to 1 -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 8:16 ` J-P. Rosen @ 2010-09-24 8:39 ` Cyrille 2010-09-24 9:27 ` Cyrille 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-24 8:39 UTC (permalink / raw) On Sep 24, 10:16 am, "J-P. Rosen" <ro...@adalog.fr> wrote: > and replace every redispatching call to M2 by a call to M2_Class, then > the big case disappears. You need (of course) to check coverage for > M2_Class, but M1 needs to be checked only for values of type T, not for > descendants. That's what I meant when I said that coverage testing drops > from N to 1 OK, I kind of supposed you had something like that in mind. Many years ago, we proposed a similar idea in a few papers, See for instance http://www.adacore.com/wp-content/uploads/2006/03/Certification_OO_Ada_Answer.pdf. Another one written by Franco G. is even mentioned in Chelinsky's FAA study on OO (see http://www.tc.faa.gov/its/worldpac/techrpt/ar0717.pdf). The study is worth reading by the way... We had more automatic translation in mind at the time but the idea is the same. doing this ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 8:39 ` Cyrille @ 2010-09-24 9:27 ` Cyrille 2010-09-29 16:47 ` J-P. Rosen 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-24 9:27 UTC (permalink / raw) On Sep 24, 10:39 am, Cyrille <co...@eu.adacore.com> wrote: > On Sep 24, 10:16 am, "J-P. Rosen" <ro...@adalog.fr> wrote: > > > and replace every redispatching call to M2 by a call to M2_Class, then > > the big case disappears. You need (of course) to check coverage for > > M2_Class, but M1 needs to be checked only for values of type T, not for > > descendants. That's what I meant when I said that coverage testing drops > > from N to 1 > > OK, I kind of supposed you had something like that in mind. Many years > ago, we proposed a similar idea in a few papers, See for instancehttp://www.adacore.com/wp-content/uploads/2006/03/Certification_OO_Ad.... > Another one written by Franco G. is even mentioned in Chelinsky's FAA > study on OO (seehttp://www.tc.faa.gov/its/worldpac/techrpt/ar0717.pdf). > The study is worth reading by the way... We had more automatic > translation in mind at the time but the idea is the same. > doing this Sorry, I hit the send button inadvertently. I was going to say: Suggesting to do such a transformation manually at the source code level as you do is particularly dubious since it is in the category of program transformations whose only purpose is to circumvent specific verifications. There are many such transformations that have been proposed to make MC/DC coverage easier... some would say to cheat on MC/DC... and, not surprisingly, it is not very well perceived by cert authorities. Anyway, DO-178C doesn't impose "pessimistic testing" as the only way to to verify safety of dispatching calls. It allows you to treat dispatching calls as normal calls as long as you can show separately that you have "local type consistency" (read LSP) for the types involved in dispatching calls. This additional verification can be done formally or using specifically designed tests such as verifying that all the functional tests attached to a class also work when the objects of this class involved in the testing are substituted by objects of the subclass. If your class hierarchy hasn't been designed to respect LSP (or if you are in a situation where you need to express properties that don't fit well with LSP, such as the example Dmitry gave earlier) then you have to go the pessimistic testing road. Why? because if you don't, there is a real risk that a non-conforming subclass method misbehave on a given dispatching call and standard coverage criteria doesn't guarantee that you have covered such case. If you want to use the "trick" you mention above, you better find a convincing reason at the design level for such a "peculiar" style because the transformation you suggest doesn't address the specific vulnerability that is supposed to be addressed by either pessimistic testing or the additional local type consitency verification. To conclude about differentiating T and T'Class, the trick you suggest here is easily implementable in other OO languages. There is nothing magic in creating a wrapper around a given dispatching call and use this wrapper at each dispatch point. The only problem is that it doesn't address the (perceived) vulnerability and thus doesn't meet properly the do-178c objective. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-24 9:27 ` Cyrille @ 2010-09-29 16:47 ` J-P. Rosen 2010-09-30 10:08 ` Cyrille 0 siblings, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-29 16:47 UTC (permalink / raw) Le 24/09/2010 11:27, Cyrille a �crit : > On Sep 24, 10:39 am, Cyrille <co...@eu.adacore.com> wrote: >> OK, I kind of supposed you had something like that in mind. Many years >> ago, we proposed a similar idea in a few papers, See for instancehttp://www.adacore.com/wp-content/uploads/2006/03/Certification_OO_Ad.... >> Another one written by Franco G. is even mentioned in Chelinsky's FAA >> study on OO (seehttp://www.tc.faa.gov/its/worldpac/techrpt/ar0717.pdf). >> The study is worth reading by the way... We had more automatic >> translation in mind at the time but the idea is the same. >> doing this Thanks for the pointers, but they seem to be quite close to what I am suggesting > Suggesting to do such a transformation manually at the source code > level as you do is particularly dubious since it is in the category of > program transformations whose only purpose is to circumvent specific > verifications. Not at all, but I may not have clearly explained my line of reasoning. 1) (Most important) I think that a method should really be a "method", i.e. an abstract operation that is implemented in different ways by different objects belonging to a class; i.e. all drawable objects have a "paint" method, but each objet has its own way, its own /method/, of painting itself. Since this is closely linked to a single member of a class, there is no reason to redispatch in such a method. 2) There is often a need to provide higher level operations, that are /not/ methods, but that are generally implemented by a combination of methods: Move=Erase, change position, Draw. Having these as class-wide operations rather than redispatching methods guarantees that the same behaviour is obtained for all members of the class. 3) I propose to enforce this strict separation, with the added benefit that all dispatching calls are located in class-wide operations, and thus reduce the coverage effort. 4) (this is the topic of my previous messages) If in some cases there is a real need for redispatching, it is still possible to follow this pattern by subcontracting the dispatching to a class-wide operation that does nothing else. But this should be a rare exception. There is no question of cheating, or maybe you consider that the patterns for programming under the Ravenscar profile are a way of cheating with the restrictions. The idea here is the same: provide a well defined pattern to ease certification. In some cases this pattern will make things more difficult? Sure. Everything is simpler if you don't need certification ;-) Note that this is quite close to Franco's approach, except that I don't rely on a specific implementation, thus preserving portability. [...] > To conclude about differentiating T and T'Class, the trick you suggest > here is easily implementable in other OO languages. There is nothing > magic in creating a wrapper around a given dispatching call and use > this wrapper at each dispatch point. The benefit of class-wide operations is that they are easily recognizable, and therefore my proposed pattern is easily checkable by tools (read: will appear in AdaControl as soon as I get around to it). I don't think it would be as easy in other languages to ensure that the profile is followed. -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-29 16:47 ` J-P. Rosen @ 2010-09-30 10:08 ` Cyrille 2010-10-05 17:02 ` J-P. Rosen 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-30 10:08 UTC (permalink / raw) On Sep 29, 6:47 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > Thanks for the pointers, but they seem to be quite close to what I am > suggesting my point is that those ideas are not new and in fact not that relevant anymore since they don't solve anything. > Not at all, but I may not have clearly explained my line of reasoning. > 1) (Most important) I think that a method should really be a "method", sure a method should be a method. I think it won't be hard to have a general agreement on that ;-) > i.e. an abstract operation that is implemented in different ways by > different objects belonging to a class; i.e. all drawable objects have a > "paint" method, but each objet has its own way, its own /method/, of > painting itself. Since this is closely linked to a single member of a > class, there is no reason to redispatch in such a method. if there is no reason to use the other methods of the same tagged type in the method in question, there is no issue of redispatch anyway. if there are such uses and they are done through non-dispatching calls, then there are real vulnerabilities and they should be addressed. There is no way around that. > 2) There is often a need to provide higher level operations, that are > /not/ methods, but that are generally implemented by a combination of > methods: Move=Erase, change position, Draw. Having these as class-wide > operations rather than redispatching methods guarantees that the same > behaviour is obtained for all members of the class. if you are saying that not all subprograms should be methods, I also think you should have no problem reaching general agreement. It is true that in Ada, a subprogram that is not a method and acts on a tagged type better be a class-wide operation. > 3) I propose to enforce this strict separation, with the added benefit > that all dispatching calls are located in class-wide operations, and > thus reduce the coverage effort. what coverage effort? You seem to believe that "pessimistic testing" is mandatory... this is not the case in DO-178C as I explained in a former post. > 4) (this is the topic of my previous messages) If in some cases there is > a real need for redispatching, it is still possible to follow this > pattern by subcontracting the dispatching to a class-wide operation that > does nothing else. But this should be a rare exception. The pattern you suggest (using those wrappers) doesn't address any vulnerabilities I am aware of and doesn't help much with coverage since there are other better ways to achieve the new related objective in the DO-178C. > Note that this is quite close to Franco's approach, except that I don't > rely on a specific implementation, thus preserving portability. but all this line of reasoning has been overtaken by events. Once again, "pessimistic" testing is not the preferred way to address the new objective. So trying to make "pessimistic" testing less painful is just not that interesting anymore. > To conclude about differentiating T and T'Class, the trick you suggest > > here is easily implementable in other OO languages. There is nothing > > magic in creating a wrapper around a given dispatching call and use > > this wrapper at each dispatch point. > > The benefit of class-wide operations is that they are easily > recognizable, and therefore my proposed pattern is easily checkable by > tools (read: will appear in AdaControl as soon as I get around to it). > > I don't think it would be as easy in other languages to ensure that the > profile is followed. I don't think that (what I understand) from your profile will be very helpful in a DO-178C context but even if it was, I don't see anything difficulty in implementing it in other languages since it is just a matter of differentiating virtual methods (using C++ parlance) from non-virtual ones or non-methods... ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-30 10:08 ` Cyrille @ 2010-10-05 17:02 ` J-P. Rosen 2010-10-08 7:50 ` Cyrille 2010-10-08 13:58 ` Cyrille 0 siblings, 2 replies; 107+ messages in thread From: J-P. Rosen @ 2010-10-05 17:02 UTC (permalink / raw) Le 30/09/2010 12:08, Cyrille a �crit : >> Not at all, but I may not have clearly explained my line of reasoning. >> 1) (Most important) I think that a method should really be a "method", > sure a method should be a method. I think it won't be hard to have a > general agreement on that ;-) Well... nowadays, many people, and especially the new generation that has been fed with Java, tends to call "method" every subprogram. I meant "real methods". > if there is no reason to use the other methods of the same tagged type > in the method in question, there is no issue of redispatch anyway. if > there are such uses and they are done through non-dispatching calls, > then there are real vulnerabilities and they should be addressed. > There is no way around that. Not that fast. You gave convincing examples of that position. I gave (in my tutorial) convincing examples where redispatching is definitely not what you want. My position here is that when redispatching is desired, in most cases, there is a natural class-wide operation that could handle it. Often enough to make it a general rule. [...] >> 3) I propose to enforce this strict separation, with the added benefit >> that all dispatching calls are located in class-wide operations, and >> thus reduce the coverage effort. > > what coverage effort? You seem to believe that "pessimistic testing" > is mandatory... this is not the case in DO-178C as I explained in a > former post. Not mandatory, but one possible solution to coverage. [...] > The pattern you suggest (using those wrappers) doesn't address any > vulnerabilities I am aware of and doesn't help much with coverage > since there are other better ways to achieve the new related objective > in the DO-178C. Since DO-178C is not currently publicly available, I'd be delighted to have pointers about those "new ways" (if they are different from the other approaches of OOTiA). Or better, come to the workshop! > but all this line of reasoning has been overtaken by events. Once > again, "pessimistic" testing is not the preferred way to address the > new objective. So trying to make "pessimistic" testing less painful is > just not that interesting anymore. Hmmm... pessimistic testing is certainly impractical for C++, but I wonder if it applies to Ada as well. >> To conclude about differentiating T and T'Class, the trick you suggest >>> here is easily implementable in other OO languages. There is nothing >>> magic in creating a wrapper around a given dispatching call and use >>> this wrapper at each dispatch point. Not at all, in other languages either a subprogram is a method (part of the dispatch table), or it applies to a single type. Class-wide operations are not dispatched, but still can be applied to a whole hierarchy. OK, I dismiss "void *" parameters... ---- But my goal is not to force my particular views; the important point is whether an appropriate profile could be defined for high reliability OO Ada programs. Such a profile could give a definitive competitive advantage to Ada in that area. If you (or anyone else on this list, or even in outer space ;) ) have good ideas about what to put in that profile, by all means, come to the workshop, or make a proposal (private mail to me, I'll gather proposals). -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-05 17:02 ` J-P. Rosen @ 2010-10-08 7:50 ` Cyrille 2010-10-08 13:58 ` Cyrille 1 sibling, 0 replies; 107+ messages in thread From: Cyrille @ 2010-10-08 7:50 UTC (permalink / raw) On Oct 5, 7:02 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > Hmmm... pessimistic testing is certainly impractical for C++, but I > wonder if it applies to Ada as well. I don't see any reason why it would be more practical in one language than the other. It depends on the amount of dispatching calls and the size of your class hierarchy. > >> To conclude about differentiating T and T'Class, the trick you suggest > >>> here is easily implementable in other OO languages. There is nothing > >>> magic in creating a wrapper around a given dispatching call and use > >>> this wrapper at each dispatch point. > > Not at all, in other languages either a subprogram is a method (part of > the dispatch table), or it applies to a single type. Class-wide > operations are not dispatched, but still can be applied to a whole > hierarchy. OK, I dismiss "void *" parameters... Well my C++ is a bit rusty but I think this is exactly the other way around. a subprogram is a method or it applies to the whole class hierarchy by default and not a single type as you seem to think. Here is an example in C++, 'subp' has a parameter that is a ref to the specific class C1 and you can pass it an object of any descendant of C1 without any problems. Looks like what you call a classwide operations to me... In the body you can even choose between dispatching or not dispatching using a slightly different syntax as shown. So really, classwide programming is not specific to Ada... only the explicit notation is. << #include <iostream> using namespace std; class C1 { public: virtual int m() {return a;} C1 () { a = 1; } int a; }; class C2: public C1 { public: virtual int m() {return b;} C2 () { a = 2; b = 3;} int b; }; void Subp (C1 &c) { cout << "dispatching to m " << c.m() << endl; cout << "not dispatching to C1::m " << c.C1::m () << endl; } int main () { C1 c1; C2 c2; Subp (c1); Subp (c2); } >> > > If you (or anyone else on this list, or even in outer space ;) ) have > good ideas about what to put in that profile, by all means, come to the > workshop, or make a proposal (private mail to me, I'll gather proposals). > We definitely have ideas and are planning to work on such a profile in the near future but not in the schedule of the workshop so I'm afraid we will have to synchronize at a later date. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-05 17:02 ` J-P. Rosen 2010-10-08 7:50 ` Cyrille @ 2010-10-08 13:58 ` Cyrille 2010-10-08 20:12 ` Dmitry A. Kazakov 2010-10-13 9:06 ` J-P. Rosen 1 sibling, 2 replies; 107+ messages in thread From: Cyrille @ 2010-10-08 13:58 UTC (permalink / raw) On Oct 5, 7:02 pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > Not that fast. You gave convincing examples of that position. I gave (in > my tutorial) convincing examples where redispatching is definitely not > what you want. Well, "not what you want" is not a criteria for me. The issue is clearly identified vulnerabilities. Vulnerabilities related to using method overriding and static dispatch are known and discussed in the literature. > My position here is that when redispatching is desired, in most cases, > there is a natural class-wide operation that could handle it. Often > enough to make it a general rule. Let me have some doubts... class-wide operations exist in all OO languages I'm aware of and if there was such a method, it would be peculiar that nobody had developed it in the standard OO literature in the last 30 or 40 years... Note that you use the term redispatching which I'm not too sure what it means. I'm talking more generally about static dispatch vs dynamic dispatch in the context of a class hierarchy with method overriding. > Since DO-178C is not currently publicly available, I'd be delighted to > have pointers about those "new ways" (if they are different from the > other approaches of OOTiA). Or better, come to the workshop! There will be (parts of) presentations on that topic at the "certification together" conference (http://www.certification-together.com/index.php? option=com_content&view=article&id=73&Itemid=80) > > but all this line of reasoning has been overtaken by events. Once > > again, "pessimistic" testing is not the preferred way to address the > > new objective. So trying to make "pessimistic" testing less painful is > > just not that interesting anymore. > > Hmmm... pessimistic testing is certainly impractical for C++, but I > wonder if it applies to Ada as well. I don't see any reason to see a difference between Ada and C++ in that respect. > >> To conclude about differentiating T and T'Class, the trick you suggest > >>> here is easily implementable in other OO languages. There is nothing > >>> magic in creating a wrapper around a given dispatching call and use > >>> this wrapper at each dispatch point. > > Not at all, in other languages either a subprogram is a method (part of > the dispatch table), or it applies to a single type. Class-wide > operations are not dispatched, but still can be applied to a whole > hierarchy. OK, I dismiss "void *" parameters... Looks to me this is the other way around. for instance, in C++ either a subprogram is a method or it is what you call a class-wide operation. That is to say, when your subprogram has a (ref) parameter of class C, you can pass it an object of any subclass of C and natural calls to method of that object will dispatch to the appropriate one. Note also that C++ offers a choice between static dispatch and dynamic dispatch. My C++ is a bit rusty but here is an example of that. In this program "subp" is your classwide operation. Here is the output of the program: dispatching to m 1 not dispatching to C1::m 1 dispatching to m 3 not dispatching to C1::m 2 ----------- #include <iostream> using namespace std; class C1 { public: virtual int m() {return a;} C1 () { a = 1; } int a; }; class C2: public C1 { public: virtual int m() {return b;} C2 () { a = 2; b = 3;} int b; }; void Subp (C1 &c) { cout << "dispatching to m " << c.m() << endl; cout << "not dispatching to C1::m " << c.C1::m () << endl; } int main () { C1 c1; C2 c2; Subp (c1); Subp (c2); } ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-08 13:58 ` Cyrille @ 2010-10-08 20:12 ` Dmitry A. Kazakov 2010-10-11 7:57 ` Cyrille 2010-10-12 5:23 ` Shark8 2010-10-13 9:06 ` J-P. Rosen 1 sibling, 2 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-10-08 20:12 UTC (permalink / raw) On Fri, 8 Oct 2010 06:58:14 -0700 (PDT), Cyrille wrote: >> Not at all, in other languages either a subprogram is a method (part of >> the dispatch table), or it applies to a single type. Class-wide >> operations are not dispatched, but still can be applied to a whole >> hierarchy. OK, I dismiss "void *" parameters... > > Looks to me this is the other way around. for instance, in C++ either > a subprogram is a method or it is what you call a class-wide > operation. or a free function. 1. method = polymorphic on the class (=primitive in Ada) 2. class-wide = non-polymorphic on the class (=class-wide in Ada) 3. free = non-polymorphic on the type (=other in Ada) > That is to say, when your subprogram has a (ref) parameter > of class C, you can pass it an object of any subclass of C and natural > calls to method of that object will dispatch to the appropriate one. True, but it is not T, it is T&. Just like T'Class is not T in Ada, T& is not T in C++. It is rather so that C++ does not have specific types for dispatching (covariant) operations. Except than in constructors and destructors, implicit "*this" is "class-wide". In constructor and destructor "*this" is type-specific. Explicit arguments and results are class-wide when references. They are type-specific otherwise. I.e. the behavior is determined not only by the type but also by the context... Isn't Ada's model much more simple and consistent than the above mess? > Note also that C++ offers a choice between static dispatch and dynamic > dispatch. I find it misleading. IMO there is only one dispatch, that is when the method's implementation is selected according to the type tag. Whether the tag is statically known or not is IMO irrelevant. An explicit call to a function in the form T::f() is not dispatch to me, it is a call to a free function named T::f(). -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-08 20:12 ` Dmitry A. Kazakov @ 2010-10-11 7:57 ` Cyrille 2010-10-11 8:24 ` Dmitry A. Kazakov 2010-10-12 5:23 ` Shark8 1 sibling, 1 reply; 107+ messages in thread From: Cyrille @ 2010-10-11 7:57 UTC (permalink / raw) On Oct 8, 10:12 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > determined not only by the type but also by the context... Isn't Ada's > model much more simple and consistent than the above mess? > won't argue this part... This is more of a "taste & color" discussion... My main point was to clarify that classwide operations (or their equivalent) are not something specific to Ada at all as Jean- Pierre seemed to assume. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-11 7:57 ` Cyrille @ 2010-10-11 8:24 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-10-11 8:24 UTC (permalink / raw) On Mon, 11 Oct 2010 00:57:43 -0700 (PDT), Cyrille wrote: > My main point was to clarify that classwide operations > (or their equivalent) are not something specific to Ada at all as Jean- > Pierre seemed to assume. Yes, but what I wanted to point out is that class-wide operations cannot be made properly typed if there is no type to denote "class" as whole [and other types to denote members of the class]. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-08 20:12 ` Dmitry A. Kazakov 2010-10-11 7:57 ` Cyrille @ 2010-10-12 5:23 ` Shark8 1 sibling, 0 replies; 107+ messages in thread From: Shark8 @ 2010-10-12 5:23 UTC (permalink / raw) On Oct 8, 2:12 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > > 1. method = polymorphic on the class (=primitive in Ada) > 2. class-wide = non-polymorphic on the class (=class-wide in Ada) > 3. free = non-polymorphic on the type (=other in Ada) > This is a good list and lays out the possible type/operation-on-that- type relationship quite nicely. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-08 13:58 ` Cyrille 2010-10-08 20:12 ` Dmitry A. Kazakov @ 2010-10-13 9:06 ` J-P. Rosen 2010-10-13 17:37 ` Cyrille 1 sibling, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-10-13 9:06 UTC (permalink / raw) Le 08/10/2010 15:58, Cyrille a �crit : [snip] > Looks to me this is the other way around. for instance, in C++ either > a subprogram is a method or it is what you call a class-wide > operation. That is to say, when your subprogram has a (ref) parameter > of class C, you can pass it an object of any subclass of C and natural > calls to method of that object will dispatch to the appropriate one. > Note also that C++ offers a choice between static dispatch and dynamic > dispatch. My C++ is a bit rusty but here is an example of that. In > this program "subp" is your classwide operation. Hmmm... yes, a subprogram acting on T is specific, and a subprogram acting on *T behaves like a class-wide operation. Anyway, the concept is much clearer in Ada. Of course, I don't mind if what is doable in Ada is also possible in other languages. The question is that class-wide programming is a first-class citizen in Ada, and I think that feature can be used in ways that can make HR systems easier to certify. I expect that to be a main topic for the workshop at SIGAda. To all those reading this thread: whether you are more inclined to my position, Cyril's, or something else, please come and discuss at the workshop at SIGAda! -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-13 9:06 ` J-P. Rosen @ 2010-10-13 17:37 ` Cyrille 2010-10-13 18:50 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-10-13 17:37 UTC (permalink / raw) On Oct 13, 11:06 am, "J-P. Rosen" <ro...@adalog.fr> wrote: > > Of course, I don't mind if what is doable in Ada is also possible in > other languages. The question is that class-wide programming is a > first-class citizen in Ada, and I think that feature can be used in ways > that can make HR systems easier to certify. easier than what? As far as I know, what you call class-wide programming is a first-class citizen in all OO languages. It is just part of the OO game ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-10-13 17:37 ` Cyrille @ 2010-10-13 18:50 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-10-13 18:50 UTC (permalink / raw) On Wed, 13 Oct 2010 10:37:28 -0700 (PDT), Cyrille wrote: > On Oct 13, 11:06�am, "J-P. Rosen" <ro...@adalog.fr> wrote: >> >> Of course, I don't mind if what is doable in Ada is also possible in >> other languages. The question is that class-wide programming is a >> first-class citizen in Ada, and I think that feature can be used in ways >> that can make HR systems easier to certify. > > easier than what? As far as I know, what you call class-wide > programming is a first-class citizen in all OO languages. It is just > part of the OO game I think it is oversimplified, almost untrue. 1. Class-wide operations are not supported for hidden arguments. In the main-stream C++/Java style OOP only these considered "true OO", others are out of scope: "parameters", "attributes", not from the class, not objects. A method always dispatches in the hidden argument (and re-dispatches later). It is nether fully primitive nor fully class-wide, it is messy. As such it by no means a good support for class-wide programming. And the class-wide programming is a clear second class-citizen because no class-wide operation can be declared *within* the class. 2. Class-wide programming is non-existent as a concept in the main-stream OOP. I never saw in OO literature class-wide programming described as a concept. There is generic programming, which BTW by many is considered as non-OO. Although the class-wide programming is an instance of generic programming, understood as programming in terms of sets of types, only its static vein i.e. templates is considered in OOP, if at all. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 13:57 ` Cyrille 2010-09-21 14:19 ` Dmitry A. Kazakov 2010-09-21 14:32 ` J-P. Rosen @ 2010-09-21 14:50 ` (see below) 2010-09-21 17:37 ` Cyrille 2 siblings, 1 reply; 107+ messages in thread From: (see below) @ 2010-09-21 14:50 UTC (permalink / raw) On 21/09/2010 14:57, in article c75a88c5-1d51-4342-904a-743e41adeb7f@k9g2000vbo.googlegroups.com, "Cyrille" <comar@eu.adacore.com> wrote: > On Sep 13, 11:13�pm, "J-P. Rosen" <ro...@adalog.fr> wrote: > >> These arguments make sense for languages without the notion of >> class-wide types. > > all OO languages I'm aware of, have the notion of classwide types... > They just don't make the distinction between a type on its own and a > type with its derived types. If you think about it, it is a peculiar > distinction at the "design" level. A horse is an animal... When I deal > with animals, I must be ready to accept that maybe the animal I'm > dealing with may be a horse, or may be something else. It's peculiar > to expect it to be the pure notion of "animal" and nothing else... What is peculiar about abstraction? -- Bill Findlay <surname><forename> chez blueyonder.co.uk ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 14:50 ` (see below) @ 2010-09-21 17:37 ` Cyrille 2010-09-21 19:07 ` (see below) 0 siblings, 1 reply; 107+ messages in thread From: Cyrille @ 2010-09-21 17:37 UTC (permalink / raw) On Sep 21, 4:50 pm, "(see below)" <yaldni...@blueyonder.co.uk> wrote: > > all OO languages I'm aware of, have the notion of classwide types... > > They just don't make the distinction between a type on its own and a > > type with its derived types. If you think about it, it is a peculiar > > distinction at the "design" level. A horse is an animal... When I deal > > with animals, I must be ready to accept that maybe the animal I'm > > dealing with may be a horse, or may be something else. It's peculiar > > to expect it to be the pure notion of "animal" and nothing else... > > What is peculiar about abstraction? Abstraction is a good thing. Differentiating between Animals and Animals'Class doesn't particularly help abstraction, as far as I am concerned. This differentiation was a neat way to introduce OO into an existing language such as Ada 83, I don't think there is more to it than that. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-21 17:37 ` Cyrille @ 2010-09-21 19:07 ` (see below) 0 siblings, 0 replies; 107+ messages in thread From: (see below) @ 2010-09-21 19:07 UTC (permalink / raw) On 21/09/2010 18:37, in article b1409cbd-97c5-4f7b-bbc4-15721a8f6ff7@v23g2000vbi.googlegroups.com, "Cyrille" <comar@eu.adacore.com> wrote: > On Sep 21, 4:50�pm, "(see below)" <yaldni...@blueyonder.co.uk> wrote: >>> all OO languages I'm aware of, have the notion of classwide types... >>> They just don't make the distinction between a type on its own and a >>> type with its derived types. If you think about it, it is a peculiar >>> distinction at the "design" level. A horse is an animal... When I deal >>> with animals, I must be ready to accept that maybe the animal I'm >>> dealing with may be a horse, or may be something else. It's peculiar >>> to expect it to be the pure notion of "animal" and nothing else... >> >> What is peculiar about abstraction? > > Abstraction is a good thing. Differentiating between Animals and > Animals'Class doesn't particularly help abstraction, as far as I am > concerned. This differentiation was a neat way to introduce OO into an > existing language such as Ada 83, I don't think there is more to it > than that. NOT distinguishing between Animals and Animals'Class causes forced polymorphism: it makes it impossible to have an object that is certain to be of type Animals and not any of the descendent types of Animals. This is a Bad Thing in my view. -- Bill Findlay <surname><forename> chez blueyonder.co.uk ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 10:23 ` Niklas Holsti 2010-09-13 12:55 ` Cyrille @ 2010-09-13 13:05 ` Dmitry A. Kazakov 2010-09-13 20:21 ` Niklas Holsti 2010-09-13 21:10 ` J-P. Rosen 2 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 13:05 UTC (permalink / raw) On Mon, 13 Sep 2010 13:23:10 +0300, Niklas Holsti wrote: > Dmitry A. Kazakov wrote: > >> re-dispatch is the problem, not aggregation or delegation. Don't implement >> anything by means of re-dispatch and you will have no "callbacks." A type >> extension cannot break anything in the parent's implementation unless it >> re-dispatches. > > Conversely, there are architectures (sensible ones, in my opinion) in > which the extension is broken, or is difficult or cumbersome to > implement, if the parent does *not* re-dispatch. I am not sure if these case aren't kludges caused by other language deficiencies (e.g. lack of MI, MD, constructors etc). > Next question: Should the language provide means to express the uses of > re-dispatch, in the declaration of a tagged type and its operations? For > example, "primitive operation Foo calls primitive operation Bar with > re-dispatch". In my view a better alternative would be extensible primitive operations, when "overriding" rather inserts prologue or epilogue than replaces all body. One could consider dispatch restricted to class-wide operations while allowing T'Class'Class. Then operations class-wide for T would be primitive for T'Class. I.e. one could override them within T'Class'Class. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 13:05 ` Dmitry A. Kazakov @ 2010-09-13 20:21 ` Niklas Holsti 2010-09-13 21:00 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Niklas Holsti @ 2010-09-13 20:21 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Mon, 13 Sep 2010 13:23:10 +0300, Niklas Holsti wrote: > >> Dmitry A. Kazakov wrote: >> >>> re-dispatch is the problem, not aggregation or delegation. Don't implement >>> anything by means of re-dispatch and you will have no "callbacks." A type >>> extension cannot break anything in the parent's implementation unless it >>> re-dispatches. >> Conversely, there are architectures (sensible ones, in my opinion) in >> which the extension is broken, or is difficult or cumbersome to >> implement, if the parent does *not* re-dispatch. > > I am not sure if these case aren't kludges caused by other language > deficiencies (e.g. lack of MI, MD, constructors etc). I agree that re-dispatching can be used to simulate multiple dispatching (MD) in Ada. I have no experience of languages that allow multiple inheritance or multiple dispatch, so they are not in my design tool-kit. But in the designs where I have used Ada re-dispatching, I don't see how MI/MD could have replaced re-dispatching; they seem unrelated. >> Next question: Should the language provide means to express the uses of >> re-dispatch, in the declaration of a tagged type and its operations? For >> example, "primitive operation Foo calls primitive operation Bar with >> re-dispatch". > > In my view a better alternative would be extensible primitive operations, > when "overriding" rather inserts prologue or epilogue than replaces all > body. That would not have replaced re-dispatching, as I have used it. My re-dispatching calls are interleaved in a more complex way with the logic of the calling operation. > One could consider dispatch restricted to class-wide operations while > allowing T'Class'Class. Then operations class-wide for T would be primitive > for T'Class. I.e. one could override them within T'Class'Class. I think an example is needed before I can understand that. Which objects are in T'Class'Class, but not in T'Class? Re-dispatching calls from a primitive (non-class-wide) operation can sometimes be replaced by dispatching calls from a class-wide operation, and that can clarify a design. Perhaps your suggestion is an extension of this? -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 20:21 ` Niklas Holsti @ 2010-09-13 21:00 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 21:00 UTC (permalink / raw) On Mon, 13 Sep 2010 23:21:28 +0300, Niklas Holsti wrote: > Dmitry A. Kazakov wrote: >> On Mon, 13 Sep 2010 13:23:10 +0300, Niklas Holsti wrote: >> >>> Dmitry A. Kazakov wrote: >>> >>>> re-dispatch is the problem, not aggregation or delegation. Don't implement >>>> anything by means of re-dispatch and you will have no "callbacks." A type >>>> extension cannot break anything in the parent's implementation unless it >>>> re-dispatches. >>> Conversely, there are architectures (sensible ones, in my opinion) in >>> which the extension is broken, or is difficult or cumbersome to >>> implement, if the parent does *not* re-dispatch. >> >> I am not sure if these case aren't kludges caused by other language >> deficiencies (e.g. lack of MI, MD, constructors etc). > > I agree that re-dispatching can be used to simulate multiple dispatching > (MD) in Ada. I have no experience of languages that allow multiple > inheritance or multiple dispatch, so they are not in my design tool-kit. > But in the designs where I have used Ada re-dispatching, I don't see how > MI/MD could have replaced re-dispatching; they seem unrelated. The only case where I am really using re-dispatch (though almost always through the Rosen's trick) is layered protocols, where upper levels are defined in terms of lower levels and the latter are implemented very late (e.g. raw I/O operations). I strongly feel that this could be done simpler and safer using MI and possibly MD. > That would not have replaced re-dispatching, as I have used it. My > re-dispatching calls are interleaved in a more complex way with the > logic of the calling operation. This is exactly the reason why I am reluctant to use it. I don't want to fight this complexity, things are already complex without that. >> One could consider dispatch restricted to class-wide operations while >> allowing T'Class'Class. Then operations class-wide for T would be primitive >> for T'Class. I.e. one could override them within T'Class'Class. > > I think an example is needed before I can understand that. Which objects > are in T'Class'Class, but not in T'Class? T'Class'Class would be a type which values are of T'Class. Such types would appear if we could derive from T'Class. > Re-dispatching calls from a primitive (non-class-wide) operation can > sometimes be replaced by dispatching calls from a class-wide operation, > and that can clarify a design. Perhaps your suggestion is an extension > of this? When re-dispatch is consistently removed, primitive operations are replaced by class-wide ones. Sometimes you want to replace a class-wide operation itself rather than augment it by some primitive operation hook called from it. A consistent way to override a class-wide operation would the class of class-wide types. (I did not much ponder over this model) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 10:23 ` Niklas Holsti 2010-09-13 12:55 ` Cyrille 2010-09-13 13:05 ` Dmitry A. Kazakov @ 2010-09-13 21:10 ` J-P. Rosen 2010-09-14 12:16 ` Niklas Holsti 2 siblings, 1 reply; 107+ messages in thread From: J-P. Rosen @ 2010-09-13 21:10 UTC (permalink / raw) Le 13/09/2010 12:23, Niklas Holsti a �crit : > Some time ago on c.l.a. we had a long discussion on the goodness or > badness of re-dispatch, without coming to an agreement. I don't want to > repeat that discussion, just to point out, again, that Dmitry's opinion > is not universal. > <shameless_plug> I expect this to be a major topic of discussion at the OO for HR systems at SIGAda, since redispatch is what is causing the exponential explosion of tests. Please be there! </shameless_plug> -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 21:10 ` J-P. Rosen @ 2010-09-14 12:16 ` Niklas Holsti 2010-09-14 16:46 ` Dmitry A. Kazakov 2010-09-14 17:04 ` J-P. Rosen 0 siblings, 2 replies; 107+ messages in thread From: Niklas Holsti @ 2010-09-14 12:16 UTC (permalink / raw) J-P. Rosen wrote: > Le 13/09/2010 12:23, Niklas Holsti a �crit : >> Some time ago on c.l.a. we had a long discussion on the goodness or >> badness of re-dispatch, without coming to an agreement. I don't want to >> repeat that discussion, just to point out, again, that Dmitry's opinion >> is not universal. >> > <shameless_plug> > I expect this to be a major topic of discussion at the OO for HR systems > at SIGAda, since redispatch is what is causing the exponential explosion > of tests. Perhaps I am revealing my scanty knowledge of HR testing, but the "exponential explosion of tests" is news to me. Which phase of testing, and which coverage criterion, is affected so much by redispatching? Integration test? Some kind of path test? For unit test I don't see why redispatch should increase the number of tests, since the called operation is typically stubbed. If an operation of a parent type calls several other operations with redispatching, and several derived types override these called operations in diverse ways, perhaps you need to test the calling operation separately for each derived class. But if I understand Dmitry's standpoint correctly, he would avoid the redispatching by overriding the calling operation for each derived class, giving the same total number of operations to be tested, right? -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-14 12:16 ` Niklas Holsti @ 2010-09-14 16:46 ` Dmitry A. Kazakov 2010-09-14 18:08 ` Niklas Holsti 2010-09-14 17:04 ` J-P. Rosen 1 sibling, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-14 16:46 UTC (permalink / raw) On Tue, 14 Sep 2010 15:16:37 +0300, Niklas Holsti wrote: > If an operation of a parent type calls several other operations with > redispatching, and several derived types override these called > operations in diverse ways, perhaps you need to test the calling > operation separately for each derived class. But if I understand > Dmitry's standpoint correctly, he would avoid the redispatching by > overriding the calling operation for each derived class, giving the same > total number of operations to be tested, right? No, I am trying not to override non-abstract or non-null operations. I think you have a certain way of decomposition in mind. This decomposition is driven by the idea of re-dispatch or OOTIA's "simple dispatch" or, more generally, by object's identity (rather than contract). I don't like this sort of decomposition in first place. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-14 16:46 ` Dmitry A. Kazakov @ 2010-09-14 18:08 ` Niklas Holsti 2010-09-14 18:32 ` Niklas Holsti 2010-09-15 8:18 ` Dmitry A. Kazakov 0 siblings, 2 replies; 107+ messages in thread From: Niklas Holsti @ 2010-09-14 18:08 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Tue, 14 Sep 2010 15:16:37 +0300, Niklas Holsti wrote: > >> If an operation of a parent type calls several other operations >> with redispatching, and several derived types override these called >> operations in diverse ways, perhaps you need to test the calling >> operation separately for each derived class. But if I understand >> Dmitry's standpoint correctly, he would avoid the redispatching by >> overriding the calling operation for each derived class, giving the >> same total number of operations to be tested, right? > > No, I am trying not to override non-abstract or non-null operations. Aha! *Now* I understand your concept. In other words, you are trying to avoid all inheritance of behaviour and to allow only inheritance of interfaces and perhaps of structure (components). I guess I can agree with you that such limitations can result in simple designs. I also see the connection (that you mentioned) to multiple inheritance. Still, I would not like to limit my designs in that way. > I think you have a certain way of decomposition in mind. This > decomposition is driven by the idea of re-dispatch or OOTIA's "simple > dispatch" or, more generally, by object's identity (rather than > contract). Possibly so. I have not knowingly modelled my design style on those sources, but may have absorbed such ideas when I first learned about object-oriented programming (and I no longer remember when that was). > I don't like this sort of decomposition in first place. That is your right, and may you live long and prosper. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-14 18:08 ` Niklas Holsti @ 2010-09-14 18:32 ` Niklas Holsti 2010-09-15 8:18 ` Dmitry A. Kazakov 1 sibling, 0 replies; 107+ messages in thread From: Niklas Holsti @ 2010-09-14 18:32 UTC (permalink / raw) Replying to my own, very confused post: > Dmitry A. Kazakov wrote: >> On Tue, 14 Sep 2010 15:16:37 +0300, Niklas Holsti wrote: >> >>> If an operation of a parent type calls several other operations with >>> redispatching, and several derived types override these called >>> operations in diverse ways, perhaps you need to test the calling >>> operation separately for each derived class. But if I understand >>> Dmitry's standpoint correctly, he would avoid the redispatching by >>> overriding the calling operation for each derived class, giving the >>> same total number of operations to be tested, right? >> >> No, I am trying not to override non-abstract or non-null operations. To which I (Niklas) replied: > Aha! *Now* I understand your concept. ... and then I went on to speak nonsense. I must have had such a blinding flash of understanding (of Dmitry) that I was dazzled. I'm better now, thanks, and I do still feel that I now understand Dmitry's approach, which seems very rigorous, almost ascetic in its constraints. I will keep it in mind, as one possibility, when next I design a class. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-14 18:08 ` Niklas Holsti 2010-09-14 18:32 ` Niklas Holsti @ 2010-09-15 8:18 ` Dmitry A. Kazakov 1 sibling, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-15 8:18 UTC (permalink / raw) On Tue, 14 Sep 2010 21:08:16 +0300, Niklas Holsti wrote: > Dmitry A. Kazakov wrote: >> On Tue, 14 Sep 2010 15:16:37 +0300, Niklas Holsti wrote: >> >>> If an operation of a parent type calls several other operations >>> with redispatching, and several derived types override these called >>> operations in diverse ways, perhaps you need to test the calling >>> operation separately for each derived class. But if I understand >>> Dmitry's standpoint correctly, he would avoid the redispatching by >>> overriding the calling operation for each derived class, giving the >>> same total number of operations to be tested, right? >> >> No, I am trying not to override non-abstract or non-null operations. > > Aha! *Now* I understand your concept. In other words, you are trying to > avoid all inheritance of behaviour and to allow only inheritance of > interfaces and perhaps of structure (components). No, I tend to override once. That is rather opposite to not inheriting. Actually I have no problem with implementation inheritance. Regarding interface inheritance I would gladly scrap ugly Ada 2005 interfaces and allow interface inheritance from any type and of course a full MI. >> I think you have a certain way of decomposition in mind. This >> decomposition is driven by the idea of re-dispatch or OOTIA's "simple >> dispatch" or, more generally, by object's identity (rather than >> contract). > > Possibly so. I have not knowingly modelled my design style on those > sources, but may have absorbed such ideas when I first learned about > object-oriented programming (and I no longer remember when that was). It wasn't Ada 95, right? As for me, I somehow missed the tide of OO hype. I just hated (and continue to hate) reading books on OO. I even didn't really use OOP in C++ until Ada 95 came, so I learned both parallel, in comparison. >> I don't like this sort of decomposition in first place. > > That is your right, and may you live long and prosper. (:-)) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-14 12:16 ` Niklas Holsti 2010-09-14 16:46 ` Dmitry A. Kazakov @ 2010-09-14 17:04 ` J-P. Rosen 1 sibling, 0 replies; 107+ messages in thread From: J-P. Rosen @ 2010-09-14 17:04 UTC (permalink / raw) Le 14/09/2010 14:16, Niklas Holsti a �crit : > J-P. Rosen wrote: >> Le 13/09/2010 12:23, Niklas Holsti a �crit : >>> Some time ago on c.l.a. we had a long discussion on the goodness or >>> badness of re-dispatch, without coming to an agreement. I don't want to >>> repeat that discussion, just to point out, again, that Dmitry's opinion >>> is not universal. >>> >> <shameless_plug> >> I expect this to be a major topic of discussion at the OO for HR systems >> at SIGAda, since redispatch is what is causing the exponential explosion >> of tests. > > Perhaps I am revealing my scanty knowledge of HR testing, but the > "exponential explosion of tests" is news to me. Which phase of testing, > and which coverage criterion, is affected so much by redispatching? > Integration test? Some kind of path test? > It's about MC/DC coverage. According to OOTiA, a dispatching call is equivalent to a "big case" for all possible classes (assumed to be known). Therefore, each dispatching call must be stubbed for all classes, and the tests have to exercise every branch of the "big case". -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions (was: Preventing type extensions) 2010-09-13 9:42 ` Dmitry A. Kazakov 2010-09-13 10:23 ` Niklas Holsti @ 2010-09-13 15:12 ` Georg Bauhaus 2010-09-13 15:29 ` Securing type extensions Dmitry A. Kazakov 2010-09-13 17:23 ` Simon Wright 1 sibling, 2 replies; 107+ messages in thread From: Georg Bauhaus @ 2010-09-13 15:12 UTC (permalink / raw) On 13.09.10 11:42, Dmitry A. Kazakov wrote: >> If a system must reflect trust and mistrust, shouldn't the >> mechanics of a language support both? > > In Ada it is called visibility. An event driven parser (or GUI) as an example: the gears of the parser (or event loop) interact with the prim ops of a user defined type. The type will have been derived from some abstract type that I provided. How will Ada's visibility rules help me trust the ops? Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 15:12 ` Securing type extensions (was: Preventing type extensions) Georg Bauhaus @ 2010-09-13 15:29 ` Dmitry A. Kazakov 2010-09-13 17:23 ` Simon Wright 1 sibling, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 15:29 UTC (permalink / raw) On Mon, 13 Sep 2010 17:12:04 +0200, Georg Bauhaus wrote: > On 13.09.10 11:42, Dmitry A. Kazakov wrote: > >>> If a system must reflect trust and mistrust, shouldn't the >>> mechanics of a language support both? >> >> In Ada it is called visibility. > > An event driven parser (or GUI) as an example: the gears of > the parser (or event loop) interact with the prim ops of > a user defined type. The type will have been derived from > some abstract type that I provided. > > How will Ada's visibility rules help me trust the ops? How making the abstract event type final would make it work in first place? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 15:12 ` Securing type extensions (was: Preventing type extensions) Georg Bauhaus 2010-09-13 15:29 ` Securing type extensions Dmitry A. Kazakov @ 2010-09-13 17:23 ` Simon Wright 2010-09-13 20:22 ` Georg Bauhaus 1 sibling, 1 reply; 107+ messages in thread From: Simon Wright @ 2010-09-13 17:23 UTC (permalink / raw) Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes: > On 13.09.10 11:42, Dmitry A. Kazakov wrote: > >>> If a system must reflect trust and mistrust, shouldn't the >>> mechanics of a language support both? >> >> In Ada it is called visibility. > > An event driven parser (or GUI) as an example: the gears of > the parser (or event loop) interact with the prim ops of > a user defined type. The type will have been derived from > some abstract type that I provided. > > How will Ada's visibility rules help me trust the ops? I don't see why this would be a problem for _you_? (unless you're worried about the support calls you might get!) ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 17:23 ` Simon Wright @ 2010-09-13 20:22 ` Georg Bauhaus 2010-09-13 20:41 ` Dmitry A. Kazakov 2010-10-05 5:59 ` Randy Brukardt 0 siblings, 2 replies; 107+ messages in thread From: Georg Bauhaus @ 2010-09-13 20:22 UTC (permalink / raw) Simon Wright wrote: > Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes: > >> On 13.09.10 11:42, Dmitry A. Kazakov wrote: >> >>>> If a system must reflect trust and mistrust, shouldn't the >>>> mechanics of a language support both? >>> In Ada it is called visibility. >> An event driven parser (or GUI) as an example: the gears of >> the parser (or event loop) interact with the prim ops of >> a user defined type. The type will have been derived from >> some abstract type that I provided. >> >> How will Ada's visibility rules help me trust the ops? > > I don't see why this would be a problem for _you_? (unless you're > worried about the support calls you might get!) Yes, exactly, the design decision to declare a publicly tagged type (which of course will not be "final") entails mutual obligations: my calls on overridden subprograms will rely on profiles and further assumptions about overridden ops (such as the LSP that has been mentioned), as do the overriding ops of the user defined type. This kind of mutual trust is unrelated to Ada's visibility rules. At least I don't see how visibility rules can ensure the same "static trust" that, I think, Dmitry wants absence of re-dispatching to achieve. Hence my question. Another reason, not stated, to ask about an event driven parser with user supplied type extensions was to learn how this can be done without dispatching calls on subprograms not known by the author of the parser (and possibly back). (Calling user supplied prim ops might become a problem if some bug (even a misuse) will make parties blame each other. One of them might be socio-economically stronger.) Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 20:22 ` Georg Bauhaus @ 2010-09-13 20:41 ` Dmitry A. Kazakov 2010-09-14 10:02 ` Georg Bauhaus 2010-10-05 5:59 ` Randy Brukardt 1 sibling, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 20:41 UTC (permalink / raw) On Mon, 13 Sep 2010 22:22:30 +0200, Georg Bauhaus wrote: > Yes, exactly, the design decision to declare a publicly tagged > type (which of course will not be "final") entails mutual obligations: > my calls on overridden subprograms will rely on profiles and further > assumptions about overridden ops > (such as the LSP that has been mentioned), as do the overriding > ops of the user defined type. This kind of mutual > trust is unrelated to Ada's visibility rules. Of course it is. You have to see the operation as primitive, you have to see the object class-wide in order to dispatch. > Another reason, not stated, to ask about an event driven parser > with user supplied type extensions was to learn how this can > be done without dispatching calls on subprograms not known > by the author of the parser (and possibly back). This design pattern is not related to either final methods or re-dispatch. > (Calling user supplied prim ops might become a problem if > some bug (even a misuse) will make parties blame each > other. Calling any operation can. Dispatching call is no less or more safe than a non-dispatching one [*, **] * Assuming that dispatch may not fail ** Re-dispatching call is unsafe and relies on luck -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 20:41 ` Dmitry A. Kazakov @ 2010-09-14 10:02 ` Georg Bauhaus 2010-09-14 12:22 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-14 10:02 UTC (permalink / raw) On 13.09.10 22:41, Dmitry A. Kazakov wrote: > On Mon, 13 Sep 2010 22:22:30 +0200, Georg Bauhaus wrote: > >> Yes, exactly, the design decision to declare a publicly tagged >> type (which of course will not be "final") entails mutual obligations: >> my calls on overridden subprograms will rely on profiles and further >> assumptions about overridden ops >> (such as the LSP that has been mentioned), as do the overriding >> ops of the user defined type. This kind of mutual >> trust is unrelated to Ada's visibility rules. > > Of course it is. You have to see the operation as primitive, you have to > see the object class-wide in order to dispatch. I'm asking about visibility and how it can possibly help ascertaining that user supplied subprograms are trustworthy---which is, by definition, not the same thing as "safe". E.g., "I trust this instance of Unchecked_Conversion, because ...". I don't think visibility alone can establish trust. So I'm speaking about trust and operations not known yet, in the presence of user extensible types. (And not about final types, one reason for changing the subject line.) Your_Overriding (My_T'Class (Some_Object)); Some_Object is of a type that may not exist yet when I write the body surrounding the above. Does this qualify as redispatching as seen on p.315 of Barnes (2006), or on p.545 of Cohen (1996)? If so, what is the foundation of trust in this O-O style callback scenario? I think it is a socio-economic issue, interpersonal. Client and supplier must agree that their subprograms will call each other properly (by socio-economic rules, which are not just implied by static properties of partial programs). How can Ada's visibility rules alone warrant this particular kind of trust in the case of a deliberately extensible type? IOW, how can visibility convince anyone that Your_Overriding is going to be trustworthy? If Your_Overriding is to be rules out as a design pattern, what is the alternative? I'm asking for the degree to which Ada's ___, ___, ... can establish trust. That's not the same thing as those purely mechanical static safety properties of programs. It is what human parties rely on when calling user supplied prim ops with LSP enacted in some event driven parser, for example. Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-14 10:02 ` Georg Bauhaus @ 2010-09-14 12:22 ` Dmitry A. Kazakov 2010-09-14 21:18 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-14 12:22 UTC (permalink / raw) On Tue, 14 Sep 2010 12:02:28 +0200, Georg Bauhaus wrote: > I'm asking about visibility and how it can possibly help ascertaining > that user supplied subprograms are trustworthy---which is, by > definition, not the same thing as "safe". Hmm, how "trustworthiness" corresponds to correctness and type safety? > So I'm speaking about trust and operations not known yet, in the > presence of user extensible types. All operations are known. Dispatching call always call a *known* operation, because a primitive operation is defined on the whole class. What you call unknown is late binding to a *part* of the body of the operation. It is no less known as sqrt taken from the standard library and resolved by the linker. It is separation of implementation and interface, after all. > Your_Overriding (My_T'Class (Some_Object)); > > Some_Object is of a type that may not exist yet when I write > the body surrounding the above. So can the computer, where the program is supposed to run. The category of developing time is meaningless to the program semantics. > If so, what is the foundation of trust in this O-O style callback scenario? See above. It is type safe. It is possibly incorrect. More elaborated contracts are applied to the *visible* specification, more can be said about correctness. No difference to sqrt, BTW. > I'm asking for the degree to which Ada's ___, ___, ... can establish > trust. That's not the same thing as those purely mechanical static > safety properties of programs. It is what human parties rely on when > calling user supplied prim ops with LSP enacted in some event > driven parser, for example. Let us not go into a discussion why LSP does not work. If you want to be sure about substitutability it is better to call it so, because LSP is misleading, inconsistent and wrong. So, a member of a class is *always* substitutable for an operation defined on the class. You cannot find anything more here without going into contracts beyond mere types. Ada stops here and this is unspecific to dispatch. So see above. SPARK has to tell more. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-14 12:22 ` Dmitry A. Kazakov @ 2010-09-14 21:18 ` Georg Bauhaus 2010-09-15 8:15 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-14 21:18 UTC (permalink / raw) On 9/14/10 2:22 PM, Dmitry A. Kazakov wrote: > On Tue, 14 Sep 2010 12:02:28 +0200, Georg Bauhaus wrote: > >> I'm asking about visibility and how it can possibly help ascertaining >> that user supplied subprograms are trustworthy---which is, by >> definition, not the same thing as "safe". > > Hmm, how "trustworthiness" corresponds to correctness and type safety? I'd consider the relation of trustworthiness, correctness and type safety at least from two viewpoints, a technical one and one on conflict: 1 - Technically, a program may have certain formal properties, such as no type errors. (Like a program can suffer if written in Python). Each formal property may exclude precisely the corresponding class of errors, if there is such correspondence. Suppose a partial program has "sockets" into which foreign code can be plugged, to make it complete. Such as a type extension with overridden subprograms. The completion is done on site. At the very least the interfaces must match. But the parent type's "plan" might require that the type's operations be called in a certain order, sayoperation A is called before operation D, no matter what comes in between. An exception is thrown otherwise, or worse. So both, the programmer who has written the partial program and the programmer who has written the plug-in code may have an interest in following the plan. How do you talk about this on site? Can you trust the plug-in code? Suppose you don't use Ada, but Python or some other more dynamically typed language. Can you even assume the type has the same interface as its parent? When the absence of a statically known interface destroys all hope for type safety, how can programmers sill trust Google to continue providing meaningful Python objects for Google App Engine? 2 - The utility function of a business might include a variable that stands for cost of conflict. Cost of conflict is in part negotiated, in part a consequence of the legal system. The conflict here is triggered by a malfunctioning program: who/what is to blame when a type extension (by party X) does not work nicely with a partial program (by party Y)? Demonstrable correctness and type safety can be turned into arguments. "Clearly, our partial program is correct, and type safe. Therefore, your type extension makes the product malfunction." -- "But we only varied the order of calls and your type specifies nothing in this area. Why didn't you specify ordering requirements as preconditions?" ... So do correctness and type safety make two parties trust each other with their business? In a more peaceful setting, the utility function of a business might include a variable that stands for income that only high quality software can generate. (Assuming that customers will pay a higher price for a better product.) Again, demonstrable correctness and type safety can be turned into arguments. If correctness and type safety contribute to high quality, if high quality entails a higher price, and if paying a higher price expresses trustworthiness, then correctness and type safety yield trust. (There are other reasons for larger sums payed, but I'll ignore them.) Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-14 21:18 ` Georg Bauhaus @ 2010-09-15 8:15 ` Dmitry A. Kazakov 2010-09-15 20:47 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-15 8:15 UTC (permalink / raw) On Tue, 14 Sep 2010 23:18:36 +0200, Georg Bauhaus wrote: > On 9/14/10 2:22 PM, Dmitry A. Kazakov wrote: >> On Tue, 14 Sep 2010 12:02:28 +0200, Georg Bauhaus wrote: >> >>> I'm asking about visibility and how it can possibly help ascertaining >>> that user supplied subprograms are trustworthy---which is, by >>> definition, not the same thing as "safe". >> >> Hmm, how "trustworthiness" corresponds to correctness and type safety? > > I'd consider the relation of trustworthiness, correctness and type > safety at least from two viewpoints, a technical one and one on > conflict: > > 1 - Technically, a program may have certain formal properties, > such as no type errors. (Like a program can suffer if written > in Python). Each formal property may exclude precisely the > corresponding class of errors, if there is such correspondence. > > Suppose a partial program has "sockets" into which foreign code > can be plugged, to make it complete. Such as a type extension > with overridden subprograms. The completion is done on site. > At the very least the interfaces must match. > > But the parent type's "plan" might require that the type's operations > be called in a certain order, sayoperation A > is called before operation D, no matter what comes in between. This is poor design. Abstract types were introduced in first place in order not to have such uncheckable low-level contracts. One of the ideas of OO decomposition was to introduce objects maintaining their state in order to simplify interfaces. > How do you talk about this on site? Can you trust the plug-in code? > Suppose you don't use Ada, but Python or some other more dynamically > typed language. Can you even assume the type has the same interface > as its parent? When the absence of a statically known interface > destroys all hope for type safety, how can programmers sill trust > Google to continue providing meaningful Python objects for Google > App Engine? This is an unrelated issue. If you have contracts to be checked dynamically, you need a meta framework where contracts were types, statically known. Something must be static. > 2 - The utility function of a business might include a variable > that stands for cost of conflict. Cost of conflict is in part > negotiated, in part a consequence of the legal system. > > The conflict here is triggered by a malfunctioning program: > who/what is to blame when a type extension (by party X) does not > work nicely with a partial program (by party Y)? Any software/hardware decomposition has this problem. The solution is specifications/contracts. More detailed they are less space is left for conflicts. > Demonstrable correctness and type safety can be turned into > arguments. "Clearly, our partial program is correct, and type > safe. Therefore, your type extension makes the product > malfunction." -- "But we only varied the order of calls and > your type specifies nothing in this area. Why didn't you > specify ordering requirements as preconditions?" ... The program semantics cannot be specified exhaustively. I don't know were you want to go, but it is not only impossible to specify all program semantics, moreover, it is also impossible to have LSP subtyping. Substitutability in the context of subtyping cannot be upheld statically. You have to verify substitutability per each case of substitution. Since we trust you, we do not verify it. Is it what you consider as "trustworthiness"? Non-contracted behavior? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-15 8:15 ` Dmitry A. Kazakov @ 2010-09-15 20:47 ` Georg Bauhaus 2010-09-16 7:47 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-15 20:47 UTC (permalink / raw) On 9/15/10 10:15 AM, Dmitry A. Kazakov wrote: > On Tue, 14 Sep 2010 23:18:36 +0200, Georg Bauhaus wrote: >>> Hmm, how "trustworthiness" corresponds to correctness and type safety? >> 1 - Technically, [...] >> But the parent type's "plan" might require that the type's operations >> be called in a certain order, > > This is poor design. Certainly, and a "plan" suffices as an example, if you agree that perfect technical specifications of what (again, just for the sake of an example) a type writer expects an extension writer to do are not always possible. (Which I understand you do.) >> How do you talk about this on site? Can you trust the plug-in code? >> Suppose you don't use Ada, but Python or some other more dynamically >> typed language. Can you even assume the type has the same interface >> as its parent? When the absence of a statically known interface >> destroys all hope for type safety, how can programmers sill trust >> Google to continue providing meaningful Python objects for Google >> App Engine? > > This is an unrelated issue. The issue is related to trust, and to type extension, and it is an existing challenge. Call it poor design on the part of Python framework writers, if that is what it seems to be. But since the framework exists as a foundation for real software, it does affect multi-party work. We can't always control the parent types, and must see if we can find it trustworthy. >> The conflict here is triggered by a malfunctioning program: >> who/what is to blame when a type extension (by party X) does not >> work nicely with a partial program (by party Y)? > > Any software/hardware decomposition has this problem. Yes. The composition problems are varied, though. One language can offer more help than another. > The program semantics cannot be specified exhaustively. I don't know were > you want to go, but it is not only impossible to specify all program > semantics, moreover, it is also impossible to have LSP subtyping. > Substitutability in the context of subtyping cannot be upheld statically. > You have to verify substitutability per each case of substitution. > > Since we trust you, we do not verify it. Is it what you consider as > "trustworthiness"? Non-contracted behavior? More inclusively, a mix of technical and social properties of a software situation will lead to more or less trust. "Contract" is a highly overloaded term, I must refuse to use it in this context, since I cannot refer to just some isolated technical set of definitions but must include rules relevant to program production and use. Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-15 20:47 ` Georg Bauhaus @ 2010-09-16 7:47 ` Dmitry A. Kazakov 2010-09-16 11:52 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-16 7:47 UTC (permalink / raw) On Wed, 15 Sep 2010 22:47:51 +0200, Georg Bauhaus wrote: > On 9/15/10 10:15 AM, Dmitry A. Kazakov wrote: >> On Tue, 14 Sep 2010 23:18:36 +0200, Georg Bauhaus wrote: > >>>> Hmm, how "trustworthiness" corresponds to correctness and type safety? > >>> 1 - Technically, [...] >>> But the parent type's "plan" might require that the type's operations >>> be called in a certain order, >> >> This is poor design. > > Certainly, and a "plan" suffices as an example, if you agree > that perfect technical specifications of what (again, just for the > sake of an example) a type writer expects an extension writer to > do are not always possible. (Which I understand you do.) That is not the type writer. There are three parties, the interface designer, the designer of an implementation and the user of the interface (class). Since it is the last two, who must get along, class-wide implementations do not really change anything in the picture. >>> How do you talk about this on site? Can you trust the plug-in code? >>> Suppose you don't use Ada, but Python or some other more dynamically >>> typed language. Can you even assume the type has the same interface >>> as its parent? When the absence of a statically known interface >>> destroys all hope for type safety, how can programmers sill trust >>> Google to continue providing meaningful Python objects for Google >>> App Engine? >> >> This is an unrelated issue. > > The issue is related to trust, and to type extension, and it is an > existing challenge. > Call it poor design on the part of Python framework writers, if that > is what it seems to be. But since the framework exists as a foundation > for real software, it does affect multi-party work. We can't always > control the parent types, and must see if we can find it trustworthy. and the point is? >>> The conflict here is triggered by a malfunctioning program: >>> who/what is to blame when a type extension (by party X) does not >>> work nicely with a partial program (by party Y)? >> >> Any software/hardware decomposition has this problem. > > Yes. The composition problems are varied, though. > One language can offer more help than another. One like SPARK. >> The program semantics cannot be specified exhaustively. I don't know were >> you want to go, but it is not only impossible to specify all program >> semantics, moreover, it is also impossible to have LSP subtyping. >> Substitutability in the context of subtyping cannot be upheld statically. >> You have to verify substitutability per each case of substitution. >> >> Since we trust you, we do not verify it. Is it what you consider as >> "trustworthiness"? Non-contracted behavior? > > More inclusively, a mix of technical and social properties of > a software situation will lead to more or less trust. The way you described it, trust has no physical meaning. It is a psychological phenomenon, not a subject of CS and SW engineering. Maybe a greater effect in gaining trust could be achieved by painting green walls of the cubicles, by writing "no gene-modified bits inside" on the DVD cover. Whatever... -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-16 7:47 ` Dmitry A. Kazakov @ 2010-09-16 11:52 ` Georg Bauhaus 2010-09-16 12:45 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-16 11:52 UTC (permalink / raw) On 16.09.10 09:47, Dmitry A. Kazakov wrote: >> Certainly, and a "plan" suffices as an example, if you agree >> that perfect technical specifications of what (again, just for the >> sake of an example) a type writer expects an extension writer to >> do are not always possible. (Which I understand you do.) > > That is not the type writer. Party X made a library, L, of O-O types, abstract or not. Party Y extends a type in L, say T I'm talking about how X and Y can trust each other before X licenses the library and before Y writes an extension. Both parties did not co-operate before making L and wishing to extend L.T, respectively. It must be done now, from what is there. What technical factors of a language's type extension mechanism will likely make X and Y be more confident that nothing will go wrong? >> The issue is related to trust, and to type extension, and it is an >> existing challenge. >> Call it poor design on the part of Python framework writers, if that >> is what it seems to be. But since the framework exists as a foundation >> for real software, it does affect multi-party work. We can't always >> control the parent types, and must see if we can find it trustworthy. > > and the point is? The point is to fathom the dark waters of software development from multiple components, of possibly closed source: Is there anything in Ada that acts like a flash light when compared to more dynamic languages? Facilities of Ada that makes one feel more secure when extending a type? (You remember the story often told about Roman bridge builders having to stand under their new bridge on opening day. Just to illustrate trust.) > The way you described it, trust has no physical meaning. When you sign a contract with your name, then this is quite physical. When you pay, or don't pay, this is easily measured. > It is a > psychological phenomenon, not a subject of CS and SW engineering. Psychology, politics, ambition and money are undoubtably parts of SW engineering, steering the decisions. They are essential to engineering in general. This famous rocket did not have an O-ring suitable for the range of temperatures, they say, and then it exploded. There had been some protest before the parts were composed to form the rocket. An example showing that engineering is not just about technical formulas. Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-16 11:52 ` Georg Bauhaus @ 2010-09-16 12:45 ` Dmitry A. Kazakov 2010-09-16 20:53 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-16 12:45 UTC (permalink / raw) On Thu, 16 Sep 2010 13:52:36 +0200, Georg Bauhaus wrote: > On 16.09.10 09:47, Dmitry A. Kazakov wrote: > >>> Certainly, and a "plan" suffices as an example, if you agree >>> that perfect technical specifications of what (again, just for the >>> sake of an example) a type writer expects an extension writer to >>> do are not always possible. (Which I understand you do.) >> >> That is not the type writer. > > Party X made a library, L, of O-O types, abstract or not. > Party Y extends a type in L, say T > > I'm talking about how X and Y can trust each other before > X licenses the library and before Y writes an extension. They need not. > What technical factors of a language's type extension mechanism > will likely make X and Y be more confident that nothing will > go wrong? None, not needed, impossible anyway. >>> The issue is related to trust, and to type extension, and it is an >>> existing challenge. >>> Call it poor design on the part of Python framework writers, if that >>> is what it seems to be. But since the framework exists as a foundation >>> for real software, it does affect multi-party work. We can't always >>> control the parent types, and must see if we can find it trustworthy. >> >> and the point is? > > The point is to fathom the dark waters of software development > from multiple components, of possibly closed source: > Is there anything in Ada that acts like a flash light when > compared to more dynamic languages? Separation of interface and implementation. Strong, static, manifested typing. Static analysis. Least assumption design principle. > Facilities of Ada that makes > one feel more secure when extending a type? Classes consistently mapped onto types. > (You remember the story often told about Roman bridge builders > having to stand under their new bridge on opening day. Just to > illustrate trust.) Huh, it is the pedestrians to stay under the bridge. For the most recent example see: http://www.wired.com/threatlevel/2010/09/first-sale-doctrine/ >> The way you described it, trust has no physical meaning. > > When you sign a contract with your name, then this is quite physical. If only signatures could make programs working... > When you pay, or don't pay, this is easily measured. Measured what? Do you trust Microsoft? >> It is a >> psychological phenomenon, not a subject of CS and SW engineering. > > Psychology, politics, ambition and money are undoubtably parts of > SW engineering, steering the decisions. They are essential to > engineering in general. As a framework they are. That does not make them engineering. > This famous rocket did not have an O-ring suitable for the range of > temperatures, they say, and then it exploded. There had been some > protest before the parts were composed to form the rocket. An example > showing that engineering is not just about technical formulas. Which was a perfect example of the opposite - of how engineering was defeated by trust. They trusted in that the rocket would not explode. People used to trust in silly things. Engineers are those who do not trust. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-16 12:45 ` Dmitry A. Kazakov @ 2010-09-16 20:53 ` Georg Bauhaus 2010-09-16 21:37 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-16 20:53 UTC (permalink / raw) On 9/16/10 2:45 PM, Dmitry A. Kazakov wrote: >> Party X made a library, L, of O-O types, abstract or not. >> Party Y extends a type in L, say T >> >> I'm talking about how X and Y can trust each other before >> X licenses the library and before Y writes an extension. > > They need not. OK, each party to a legal contract may chose to not care about the consequences of joining untrusted partners in software. I trust they do care. This is why there is software evaluation. >> What technical factors of a language's type extension mechanism >> will likely make X and Y be more confident that nothing will >> go wrong? > > None, not needed, impossible anyway. Why does public key cryptography create confidence when the encryption might fail to protect in some time/case/whatever, since it can impossibly be known to be secure, i.e. may go wrong? Yet you enumerate reassuring language facilities of Ada, noting that static analysis frees you from all concerns? Do I understand correctly? If one approaches program semantics from the world outside the sacred halls of formal illusion, there is a lot between "program's semantics cannot be known" and "program will basically function as intended". This is where lawyers, sales people, engineers, support staff, and customers spend a lot of their time. They give effective meaning to the sentences. This is where trust is generated. > If only signatures could make programs working... The purpose of signatures put under a software contract is to express something related to trust and mistrust. Typically, there is a sentence like "we cannot be held responsible for ... the usual stuff you have in software. But otherwise, ...". >> When you pay, or don't pay, this is easily measured. > > Measured what? Do you trust Microsoft? Programmers trust Microsoft's Visual Studio to basically function as they would expect, and to help them achieve their programming goals. Less so the moment some IDE's reputation is ruined because of poor quality, maybe. The makers go out of business. >> Psychology, politics, ambition and money are undoubtably parts of >> SW engineering, steering the decisions. They are essential to >> engineering in general. > > As a framework they are. That does not make them engineering. Of course, if you define engineering to be tautologically not anything but some idealized clean room acting by the book, a standard to strive for, then whatever makes real engineers' hands move cannot have an influence on their produce. Do you mean the immaculate ideal of engineering, and not the engineering we have, perhaps? Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-16 20:53 ` Georg Bauhaus @ 2010-09-16 21:37 ` Dmitry A. Kazakov 2010-09-17 8:45 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-16 21:37 UTC (permalink / raw) On Thu, 16 Sep 2010 22:53:32 +0200, Georg Bauhaus wrote: > On 9/16/10 2:45 PM, Dmitry A. Kazakov wrote: > >>> Party X made a library, L, of O-O types, abstract or not. >>> Party Y extends a type in L, say T >>> >>> I'm talking about how X and Y can trust each other before >>> X licenses the library and before Y writes an extension. >> >> They need not. > > OK, each party to a legal contract may chose to not care > about the consequences of joining untrusted partners in software. You missed the point, there is no such relation between specification (class of L) and implementation (member of the class). There is one between a client and the provider of an implementation. > Yet you enumerate reassuring language facilities of Ada, > noting that static analysis frees you from all concerns? Do I > understand correctly? It frees me from certain concerns. > This is where lawyers, sales people, engineers, support > staff, and customers spend a lot of their time. They give > effective meaning to the sentences. This is where trust > is generated. Generated trust does not free me from the concerns above. Moreover it makes me more concerned about where the catch was. >> If only signatures could make programs working... > > The purpose of signatures put under a software contract > is to express something related to trust and mistrust. > Typically, there is a sentence like "we cannot be held > responsible for ... the usual stuff you have in software. > But otherwise, ...". I see, when you sign up to a no-warranty software licensing agreement that generates a huge amount of trust! Not to me, I know they swindled me again. >>> When you pay, or don't pay, this is easily measured. >> >> Measured what? Do you trust Microsoft? > > Programmers trust Microsoft's Visual Studio to basically function > as they would expect, and to help them achieve their programming > goals. Do *you* trust Microsoft? As for Visual Studio I wonder if you ever used it. Did you hear anything about manifest files? The latest MS joke is that the new Visual Studio does not compile for Windows 9x/me/NT things, which were compilable before. The single thing you can trust in is that the next version will have absolutely different interface and incompatible project files. >>> Psychology, politics, ambition and money are undoubtably parts of >>> SW engineering, steering the decisions. They are essential to >>> engineering in general. >> >> As a framework they are. That does not make them engineering. > > Of course, if you define engineering to be tautologically not anything > but some idealized clean room acting by the book, a standard to strive for, > then whatever makes real engineers' hands move cannot have an influence on > their produce. Do you mean the immaculate ideal of engineering, and not > the engineering we have, perhaps? It is not about qualities of engineering, it is about what it is what it is not. Engineering is applying science to solving technical problems. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-16 21:37 ` Dmitry A. Kazakov @ 2010-09-17 8:45 ` Georg Bauhaus 2010-09-17 9:39 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Georg Bauhaus @ 2010-09-17 8:45 UTC (permalink / raw) On 9/16/10 11:37 PM, Dmitry A. Kazakov wrote: > On Thu, 16 Sep 2010 22:53:32 +0200, Georg Bauhaus wrote: > >> On 9/16/10 2:45 PM, Dmitry A. Kazakov wrote: >> >>>> Party X made a library, L, of O-O types, abstract or not. >>>> Party Y extends a type in L, say T >>>> >>>> I'm talking about how X and Y can trust each other before >>>> X licenses the library and before Y writes an extension. >>> >>> They need not. >> >> OK, each party to a legal contract may chose to not care >> about the consequences of joining untrusted partners in software. > > You missed the point, I wonder if we are moving in the same plane at all. ;-) > there is no such relation between specification > (class of L) and implementation (member of the class). There is one between > a client and the provider of an implementation. -- Toulouse: package X.L.A is type T1 is tagged private; -- description, ops ... end X.L.A; -- Hamburg: package X.L.B is type T2 is abstract tagged private; -- description, ops ... end X.L.B; Company representatives from Toulouse and Munich sign a legal contract about terms and conditions for use of X.L. -- Munich: with X.L.A; package Y is type T is new X.L.A.T1 with private; -- overridings ... end Y; I am trying to understand what you are referring to using "class" and "spcification" and "implementation". (When I said something about company representatives signing a legal contract about software and why they feel they can trust each other to a certain extent ...). Is "class of L" referring to {T1'Class, T2'Class}? What are the clients and implementations in X.L.* and Y, respectively? Is there a relation of (some) trust (state of a human being) between Munich's Y.T programmers/managers and Toulouse's X.L.A.T1 programmers/managers? >> The purpose of signatures put under a software contract >> is to express something related to trust and mistrust. >> Typically, there is a sentence like "we cannot be held >> responsible for ... the usual stuff you have in software. >> But otherwise, ...". > > I see, when you sign up to a no-warranty software licensing agreement that > generates a huge amount of trust! Not to me, I know they swindled me again. I see no reason to sign a contract absent any kind of obligation. Here's an example of trust, showing that trust is not a binary thing (as "trust more than" indicates): A thief engineer (E1) plans to rely on a few other thief engineers (E2, E3). They plan a technically challenging robbery. On site, E2 performs almost as expected, the robbery succeeds, but E2 runs away with half of the haul when he was supposed to carry one third. Partial success. If and only if E1 and E3 can live with the result, trusting E2 was justified, whatever the concerns may have been, or will be. > Do *you* trust Microsoft? The one thing that does not matter in discussing general rules should be one's own specific attitude. Visual Studio is *of* *course* changed in incompatible ways! You known that when you buy, you can trust they will have made a few changes of this kind. This is two-party business, not one-group cooperation! Interests will differ. When dealing with MS products, many swear and curse, hate them, the hatred being extended to Microsoft, but they nevertheless buy because they trust programming with MS VS will still provide for a living. A good opportunity to remember the huge value of standardized languages, and competing implementations, BTW. > Engineering is applying science to solving technical problems. Which does not define engineering at all: there is no one way to "apply" (whatever "apply" might mean) the one and only "science". Science, a term, I think, that is defined only when engineers feel they need to make a gesture of competence. What we do when programming is between science and the ideal of engineering. Between science and engineering lies _craft_. There is a preferred scientific method, there are scientific results, some of them brittle, some preliminary, some rather vague, many temporary. Craftspeople deal with this. If you remember the varied qualities of craftsmanship... Which brings us back to software libraries and type extensions. Georg ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-17 8:45 ` Georg Bauhaus @ 2010-09-17 9:39 ` Dmitry A. Kazakov 0 siblings, 0 replies; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-17 9:39 UTC (permalink / raw) On Fri, 17 Sep 2010 10:45:48 +0200, Georg Bauhaus wrote: > On 9/16/10 11:37 PM, Dmitry A. Kazakov wrote: >> On Thu, 16 Sep 2010 22:53:32 +0200, Georg Bauhaus wrote: >> >>> On 9/16/10 2:45 PM, Dmitry A. Kazakov wrote: >>> >>>>> Party X made a library, L, of O-O types, abstract or not. >>>>> Party Y extends a type in L, say T >>>>> >>>>> I'm talking about how X and Y can trust each other before >>>>> X licenses the library and before Y writes an extension. >>>> >>>> They need not. >>> >>> OK, each party to a legal contract may chose to not care >>> about the consequences of joining untrusted partners in software. >> >> You missed the point, > > I wonder if we are moving in the same plane at all. ;-) > >> there is no such relation between specification >> (class of L) and implementation (member of the class). There is one between >> a client and the provider of an implementation. > > -- Toulouse: > package X.L.A is > > type T1 is tagged private; > -- description, ops > ... > end X.L.A; > > -- Hamburg: > package X.L.B is > > type T2 is abstract tagged private; > -- description, ops > ... > end X.L.B; > > Company representatives from Toulouse and Munich sign a legal > contract about terms and conditions for use of X.L. > > -- Munich: > with X.L.A; > package Y is > > type T is new X.L.A.T1 with private; > -- overridings > ... > end Y; > > I am trying to understand what you are referring to using "class" class = set of types > and "spcification" class specification = the interface of > and "implementation" class instance implementation = the implementation of a type, a member of the class > Is there a relation of (some) trust (state of a human being) > between Munich's Y.T programmers/managers and Toulouse's X.L.A.T1 > programmers/managers? When you derive from the interface of a class (technically you do from the root type) you sign up to the contract the interface describes. The contract relationship is not between you and the class designer because you are among its designers as well. It is not between you and the designer of the type you derive from. He has no responsibilities for you, which is an important advantage for a long-term developing process. The contract is between you and someone who uses the class in his code. interface designer <-> state passing regulation rules for car safety You <-> car manufacturer client <-> car driver >>> The purpose of signatures put under a software contract >>> is to express something related to trust and mistrust. >>> Typically, there is a sentence like "we cannot be held >>> responsible for ... the usual stuff you have in software. >>> But otherwise, ...". >> >> I see, when you sign up to a no-warranty software licensing agreement that >> generates a huge amount of trust! Not to me, I know they swindled me again. > > I see no reason to sign a contract absent any kind of > obligation. Sorry for that, but you have no choice. >> Do *you* trust Microsoft? > > The one thing that does not matter in discussing general rules > should be one's own specific attitude. Great, both of us do not trust them, but in our own interest they are considered trustworthy. That sounds familiar... (:-)) > Visual Studio is *of* *course* changed in incompatible ways! That "of course" directly follows from "trustworthiness", I bet? (:-)) > but they nevertheless buy because they trust programming with > MS VS will still provide for a living. No, they do because Microsoft maintains a monopoly. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Securing type extensions 2010-09-13 20:22 ` Georg Bauhaus 2010-09-13 20:41 ` Dmitry A. Kazakov @ 2010-10-05 5:59 ` Randy Brukardt 1 sibling, 0 replies; 107+ messages in thread From: Randy Brukardt @ 2010-10-05 5:59 UTC (permalink / raw) "Georg Bauhaus" <see.reply.to@maps.futureapps.de> wrote in message news:4c8e87f8$0$6877$9b4e6d93@newsspool2.arcor-online.net... ... > Another reason, not stated, to ask about an event driven parser > with user supplied type extensions was to learn how this can > be done without dispatching calls on subprograms not known > by the author of the parser (and possibly back). > > (Calling user supplied prim ops might become a problem if > some bug (even a misuse) will make parties blame each > other. One of them might be socio-economically stronger.) We worried a lot about this problem in Claw. We eventually learned to not trust the user-defined routines any more than we had to. Because we found that even competent programmers (i.e. me :-) make mistakes which could lock up the entire application. Thus (for instance), most of the (internal) operations have timeouts such that if they can't be completed they are just abandoned raising an exception. We got a lot fewer calls and e-mails once we did that, because tasking mistakes in the call-backs at least showed up in the global exception handlers (rather than just deadlocking). (Recall that Claw was probably the first serious attempt to use Ada 95 OOP in a major serious way. So we had to figure out a lot of this by trial-and-error. The number of bug reports that we sent to compiler vendors demonstrated no one had tried a lot of the OOP features before...) Randy. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 7:13 ` Dmitry A. Kazakov 2010-09-13 9:19 ` Georg Bauhaus @ 2010-09-13 18:32 ` Florian Weimer 2010-09-13 20:30 ` Dmitry A. Kazakov 2010-09-17 0:16 ` Shark8 2 siblings, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-13 18:32 UTC (permalink / raw) * Dmitry A. Kazakov: >> Type extensions break encapsulation (at least if there non-abstract >> dispatching subprograms which contain some non-trivial code): the >> information which subprograms call each other under what circumstances >> leaks to the outside of the package. One very drastic way to >> implement that is to disallow type extensions for most non-abstract >> types you write, and consider the exceptions carefully. > > No, the actual problem here is re-dispatch. Just do not do that, it is > always bad. How do you suggest to avoid redispatch? Make non-dispatching calls to dispatching subprograms? And how does this address the issue? It makes it more likely that you cannot write a useful extension. Wouldn't it be better not to hide this aspect in the implementation? ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 18:32 ` Preventing " Florian Weimer @ 2010-09-13 20:30 ` Dmitry A. Kazakov 2010-09-22 19:41 ` Florian Weimer 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-13 20:30 UTC (permalink / raw) On Mon, 13 Sep 2010 20:32:13 +0200, Florian Weimer wrote: > * Dmitry A. Kazakov: > >>> Type extensions break encapsulation (at least if there non-abstract >>> dispatching subprograms which contain some non-trivial code): the >>> information which subprograms call each other under what circumstances >>> leaks to the outside of the package. One very drastic way to >>> implement that is to disallow type extensions for most non-abstract >>> types you write, and consider the exceptions carefully. >> >> No, the actual problem here is re-dispatch. Just do not do that, it is >> always bad. > > How do you suggest to avoid redispatch? Make non-dispatching calls to > dispatching subprograms? Yes. > And how does this address the issue? Because nothing can get broken by overriding, all targets are resolved. > It makes it more likely that you cannot write a useful extension. Why? I can override anything I need. > Wouldn't it be better not to hide this aspect in the implementation? This does not compute to me. Are you saying that if an operation gets broken upon extension you won't allow to override it? (And if it is not broken, why do you care?) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 20:30 ` Dmitry A. Kazakov @ 2010-09-22 19:41 ` Florian Weimer 2010-09-22 20:34 ` Dmitry A. Kazakov 0 siblings, 1 reply; 107+ messages in thread From: Florian Weimer @ 2010-09-22 19:41 UTC (permalink / raw) * Dmitry A. Kazakov: >>> No, the actual problem here is re-dispatch. Just do not do that, it is >>> always bad. >> >> How do you suggest to avoid redispatch? Make non-dispatching calls to >> dispatching subprograms? > > Yes. > >> And how does this address the issue? > > Because nothing can get broken by overriding, all targets are resolved. Perhaps not directly, but you still have the problem that you make the extension because you want a behavioral change, and that change may break other things. (And unlike Objective Caml, Ada has downcasts, so the fact that there are unblessed extensions is very visible even without resorting to non-portable bit fiddling.) >> It makes it more likely that you cannot write a useful extension. > > Why? I can override anything I need. Yes, but you may have to copy source code from the parent type's implementation because it won't pick up your new code automatically. Back in mid-90s, there was a thought that it should be possible to subclass all (public) classes and override all (public) methods. This design is still followed by the JDK. I think this is quite the wrong way to do OO. >> Wouldn't it be better not to hide this aspect in the implementation? > > This does not compute to me. Are you saying that if an operation gets > broken upon extension you won't allow to override it? (And if it is not > broken, why do you care?) I want to make an explicit statement, "I do not support extending this type" because I do not want to have the additional maintenance burden of this dependency (or the debugging necessary because other code breaks because there is an unexpected extension). I can write this in a comment, but I think it's better to make such things explicit in the interface. ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 19:41 ` Florian Weimer @ 2010-09-22 20:34 ` Dmitry A. Kazakov 2010-09-22 21:10 ` Georg Bauhaus 0 siblings, 1 reply; 107+ messages in thread From: Dmitry A. Kazakov @ 2010-09-22 20:34 UTC (permalink / raw) On Wed, 22 Sep 2010 21:41:35 +0200, Florian Weimer wrote: > * Dmitry A. Kazakov: > >>>> No, the actual problem here is re-dispatch. Just do not do that, it is >>>> always bad. >>> >>> How do you suggest to avoid redispatch? Make non-dispatching calls to >>> dispatching subprograms? >> >> Yes. >> >>> And how does this address the issue? >> >> Because nothing can get broken by overriding, all targets are resolved. > > Perhaps not directly, but you still have the problem that you make the > extension because you want a behavioral change, and that change may > break other things. No, the point is that it cannot break existing code, because it is statically resolved and frozen. In Ada freezing is accomplished automatically by default. Any implementation in is frozen. You can use the implementation inappropriately, but that is your problem as a user. When you call sine instead of cosine you do not break either, you do your code only. > (And unlike Objective Caml, Ada has downcasts, so > the fact that there are unblessed extensions is very visible even > without resorting to non-portable bit fiddling.) That is another issue. In my opinion Ada should abstract all operations of the type. E.g. member access, pointer types evaluation, attributes etc. Conversion to a derived interface is another candidate to become a primitive operation, which you as a provider of the derived type should be able to override in order to have a finer control over downcasting. >>> It makes it more likely that you cannot write a useful extension. >> >> Why? I can override anything I need. > > Yes, but you may have to copy source code from the parent type's > implementation because it won't pick up your new code automatically. I can reuse parent's operations by calling them explicitly. > Back in mid-90s, there was a thought that it should be possible to > subclass all (public) classes and override all (public) methods. This > design is still followed by the JDK. I think this is quite the wrong > way to do OO. Yes, I stick to the design rule: override once. >>> Wouldn't it be better not to hide this aspect in the implementation? >> >> This does not compute to me. Are you saying that if an operation gets >> broken upon extension you won't allow to override it? (And if it is not >> broken, why do you care?) > > I want to make an explicit statement, "I do not support extending this > type" because I do not want to have the additional maintenance burden > of this dependency (or the debugging necessary because other code > breaks because there is an unexpected extension). That is not your business as a provider of the type. You cannot foresee further uses of the type and there is no burden on your side anyway. You publish the interfaces and provide some implementation for, and then you leave. > I can write this in > a comment, but I think it's better to make such things explicit in the > interface. Nope, as I already wrote in a subthread, the contract is between someone who extends the type and someone who uses it. You are not involved. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-22 20:34 ` Dmitry A. Kazakov @ 2010-09-22 21:10 ` Georg Bauhaus 0 siblings, 0 replies; 107+ messages in thread From: Georg Bauhaus @ 2010-09-22 21:10 UTC (permalink / raw) On 9/22/10 10:34 PM, Dmitry A. Kazakov wrote: > On Wed, 22 Sep 2010 21:41:35 +0200, Florian Weimer wrote: >> I can write this in >> a comment, but I think it's better to make such things explicit in the >> interface. > > Nope, as I already wrote in a subthread, the contract is between someone > who extends the type and someone who uses it. You are not involved. Except that they may ignore your theory today and ignore your business in the future... ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-13 7:13 ` Dmitry A. Kazakov 2010-09-13 9:19 ` Georg Bauhaus 2010-09-13 18:32 ` Preventing " Florian Weimer @ 2010-09-17 0:16 ` Shark8 2010-09-17 7:04 ` AdaMagica 2 siblings, 1 reply; 107+ messages in thread From: Shark8 @ 2010-09-17 0:16 UTC (permalink / raw) > Final classes make no sense. I am glad that at least this was not borrowed > by Ada ... yet. I agree; final classes are a bad idea -- Unless the object's behavior is perfect and there can [in no way] be a changed requirement... which almost never happens. There have been times where I've had to 'extend' a final Java class by embedding it into another class and writing all the methods as passthroughs except for the ones I needed to introduce some [usually slightly] different behavior. On the original poster's topic; is there anything from doing something like: Package Some_Object_Package is Type Object-Type is private; -- Elementery functions. private Type Object-Type is tagged null record; end package Some_Object_Package; Sure, a child-package could be introduced to extend the object, but its specification cannot rely on anything not publicly visible in its parent's specification... meaning that the public portion of the object cannot expose that it is a tagged record. Right? ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-17 0:16 ` Shark8 @ 2010-09-17 7:04 ` AdaMagica 2010-09-17 21:05 ` Shark8 0 siblings, 1 reply; 107+ messages in thread From: AdaMagica @ 2010-09-17 7:04 UTC (permalink / raw) On 17 Sep., 02:16, Shark8 <onewingedsh...@gmail.com> wrote: > Sure, a child-package could be introduced to extend the object, but > its specification cannot rely on anything not publicly visible in its > parent's specification... meaning that the public portion of the > object cannot expose that it is a tagged record. Right? package X is type Final is private; private type Final is tagged null record; end X; package X.X is type Extended_Final is tagged private; private type Extended_Final is new Standard.X.Final with null record; end X.X; ^ permalink raw reply [flat|nested] 107+ messages in thread
* Re: Preventing type extensions 2010-09-17 7:04 ` AdaMagica @ 2010-09-17 21:05 ` Shark8 0 siblings, 0 replies; 107+ messages in thread From: Shark8 @ 2010-09-17 21:05 UTC (permalink / raw) On Sep 17, 1:04 am, AdaMagica <christoph.gr...@eurocopter.com> wrote: > On 17 Sep., 02:16, Shark8 <onewingedsh...@gmail.com> wrote: > > > Sure, a child-package could be introduced to extend the object, but > > its specification cannot rely on anything not publicly visible in its > > parent's specification... meaning that the public portion of the > > object cannot expose that it is a tagged record. Right? > > package X is > > type Final is private; > > private > > type Final is tagged null record; > > end X; > package X.X is > > type Extended_Final is tagged private; > > private > > type Extended_Final is new Standard.X.Final with null record; > > end X.X; Yes, but that is NOT exposing that FINAL is tagged, only that Extended_Final is; moreover, since the definition of Extended_Final [which extends FINAL] is in the private portion it cannot be relied upon in the public portion of other specifications... (i.e. we are free to change Extended_Final's implementation in any way we see fit so long as it satisfies all its public specifications.) ^ permalink raw reply [flat|nested] 107+ messages in thread
end of thread, other threads:[~2010-10-13 18:50 UTC | newest] Thread overview: 107+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-09-12 10:18 Preventing type extensions Florian Weimer 2010-09-12 11:59 ` Ludovic Brenta 2010-09-12 12:53 ` Florian Weimer 2010-09-12 21:23 ` Maciej Sobczak 2010-09-13 5:32 ` Florian Weimer 2010-09-13 7:13 ` Dmitry A. Kazakov 2010-09-13 9:19 ` Georg Bauhaus 2010-09-13 9:42 ` Dmitry A. Kazakov 2010-09-13 10:23 ` Niklas Holsti 2010-09-13 12:55 ` Cyrille 2010-09-13 13:55 ` Dmitry A. Kazakov 2010-09-13 21:13 ` J-P. Rosen 2010-09-21 13:57 ` Cyrille 2010-09-21 14:19 ` Dmitry A. Kazakov 2010-09-21 14:44 ` Cyrille 2010-09-21 16:25 ` Dmitry A. Kazakov 2010-09-21 17:11 ` Georg Bauhaus 2010-09-21 18:11 ` Dmitry A. Kazakov 2010-09-23 20:00 ` Simon Wright 2010-09-23 20:49 ` Dmitry A. Kazakov 2010-09-24 9:10 ` Georg Bauhaus 2010-09-24 10:24 ` Dmitry A. Kazakov 2010-09-24 13:30 ` Niklas Holsti 2010-09-24 16:27 ` Dmitry A. Kazakov 2010-09-24 17:47 ` Niklas Holsti 2010-09-24 19:42 ` Dmitry A. Kazakov 2010-09-21 14:32 ` J-P. Rosen 2010-09-21 15:02 ` Cyrille 2010-09-21 15:26 ` J-P. Rosen 2010-09-21 16:18 ` Cyrille 2010-09-22 8:01 ` J-P. Rosen 2010-09-22 17:28 ` Cyrille 2010-09-22 19:30 ` Ludovic Brenta 2010-09-22 19:51 ` Florian Weimer 2010-09-22 20:14 ` Dmitry A. Kazakov 2010-09-22 20:25 ` Florian Weimer 2010-09-22 20:38 ` Dmitry A. Kazakov 2010-09-22 21:25 ` Vinzent Hoefler 2010-09-22 21:20 ` Georg Bauhaus 2010-09-22 20:16 ` Ludovic Brenta 2010-09-22 20:34 ` Florian Weimer 2010-09-22 22:45 ` Britt Snodgrass 2010-09-23 8:02 ` Ludovic Brenta 2010-09-23 16:51 ` Pascal Obry 2010-09-23 18:37 ` Florian Weimer 2010-09-23 18:55 ` Pascal Obry 2010-09-23 20:28 ` Ludovic Brenta 2010-09-24 9:20 ` Ludovic Brenta 2010-09-24 14:49 ` Simon Wright 2010-09-24 15:09 ` Ludovic Brenta 2010-09-24 16:21 ` Robert A Duff 2010-09-25 7:10 ` Pascal Obry 2010-09-25 12:03 ` Brian Drummond 2010-09-24 8:16 ` J-P. Rosen 2010-09-24 8:39 ` Cyrille 2010-09-24 9:27 ` Cyrille 2010-09-29 16:47 ` J-P. Rosen 2010-09-30 10:08 ` Cyrille 2010-10-05 17:02 ` J-P. Rosen 2010-10-08 7:50 ` Cyrille 2010-10-08 13:58 ` Cyrille 2010-10-08 20:12 ` Dmitry A. Kazakov 2010-10-11 7:57 ` Cyrille 2010-10-11 8:24 ` Dmitry A. Kazakov 2010-10-12 5:23 ` Shark8 2010-10-13 9:06 ` J-P. Rosen 2010-10-13 17:37 ` Cyrille 2010-10-13 18:50 ` Dmitry A. Kazakov 2010-09-21 14:50 ` (see below) 2010-09-21 17:37 ` Cyrille 2010-09-21 19:07 ` (see below) 2010-09-13 13:05 ` Dmitry A. Kazakov 2010-09-13 20:21 ` Niklas Holsti 2010-09-13 21:00 ` Dmitry A. Kazakov 2010-09-13 21:10 ` J-P. Rosen 2010-09-14 12:16 ` Niklas Holsti 2010-09-14 16:46 ` Dmitry A. Kazakov 2010-09-14 18:08 ` Niklas Holsti 2010-09-14 18:32 ` Niklas Holsti 2010-09-15 8:18 ` Dmitry A. Kazakov 2010-09-14 17:04 ` J-P. Rosen 2010-09-13 15:12 ` Securing type extensions (was: Preventing type extensions) Georg Bauhaus 2010-09-13 15:29 ` Securing type extensions Dmitry A. Kazakov 2010-09-13 17:23 ` Simon Wright 2010-09-13 20:22 ` Georg Bauhaus 2010-09-13 20:41 ` Dmitry A. Kazakov 2010-09-14 10:02 ` Georg Bauhaus 2010-09-14 12:22 ` Dmitry A. Kazakov 2010-09-14 21:18 ` Georg Bauhaus 2010-09-15 8:15 ` Dmitry A. Kazakov 2010-09-15 20:47 ` Georg Bauhaus 2010-09-16 7:47 ` Dmitry A. Kazakov 2010-09-16 11:52 ` Georg Bauhaus 2010-09-16 12:45 ` Dmitry A. Kazakov 2010-09-16 20:53 ` Georg Bauhaus 2010-09-16 21:37 ` Dmitry A. Kazakov 2010-09-17 8:45 ` Georg Bauhaus 2010-09-17 9:39 ` Dmitry A. Kazakov 2010-10-05 5:59 ` Randy Brukardt 2010-09-13 18:32 ` Preventing " Florian Weimer 2010-09-13 20:30 ` Dmitry A. Kazakov 2010-09-22 19:41 ` Florian Weimer 2010-09-22 20:34 ` Dmitry A. Kazakov 2010-09-22 21:10 ` Georg Bauhaus 2010-09-17 0:16 ` Shark8 2010-09-17 7:04 ` AdaMagica 2010-09-17 21:05 ` Shark8
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox