comp.lang.ada
 help / color / mirror / Atom feed
* Derived private interface
@ 2011-07-05  3:14 Rego, P.
  2011-07-05  5:10 ` AdaMagica
  0 siblings, 1 reply; 63+ messages in thread
From: Rego, P. @ 2011-07-05  3:14 UTC (permalink / raw)


Hi people, 

I'm just trying to implement a private type derived from an interface, but possibly doing wrong. So, in my code:

   type My_Interface is interface;
   procedure Doit (O : access My_Interface) is abstract;

   type Derived_Class is new My_Interface with private;

[...]
private 
   type Derived_Class is tagged
      record
         First_Record : Integer;
      end record;


so when I try to compile, I get these errors:
   'interface "My_Interface" not implemented by full type (RM-2005 7.3 (7.3/2))'
   'full view of private extension must be an extension'

Does anyone know how can I fix it?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-05  3:14 Derived private interface Rego, P.
@ 2011-07-05  5:10 ` AdaMagica
  2011-07-06  2:24   ` Rego, P.
  2011-07-06  4:34   ` AdaMagica
  0 siblings, 2 replies; 63+ messages in thread
From: AdaMagica @ 2011-07-05  5:10 UTC (permalink / raw)


   type My_Interface is interface;
   procedure Doit (O : access My_Interface) is abstract;

   type Derived_Class is new My_Interface with private;
   procedure Doit (X: access Derived_Class);

[...]
private
   type Derived_Class is new My_Interface with record
     First_Record : Integer;
   end record;




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-05  5:10 ` AdaMagica
@ 2011-07-06  2:24   ` Rego, P.
  2011-07-06  4:34   ` AdaMagica
  1 sibling, 0 replies; 63+ messages in thread
From: Rego, P. @ 2011-07-06  2:24 UTC (permalink / raw)


Thanks, it worked!
:-)



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-05  5:10 ` AdaMagica
  2011-07-06  2:24   ` Rego, P.
@ 2011-07-06  4:34   ` AdaMagica
  2011-07-06  7:55     ` Georg Bauhaus
  1 sibling, 1 reply; 63+ messages in thread
From: AdaMagica @ 2011-07-06  4:34 UTC (permalink / raw)


I should have written

  overriding procedure Doit (X: access Derived_Class);



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  4:34   ` AdaMagica
@ 2011-07-06  7:55     ` Georg Bauhaus
  2011-07-06  8:30       ` AdaMagica
                         ` (3 more replies)
  0 siblings, 4 replies; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-06  7:55 UTC (permalink / raw)


On 7/6/11 6:34 AM, AdaMagica wrote:
> I should have written
>
>    overriding procedure Doit (X: access Derived_Class);

Instead of sprinkling the program with overriding indicators,
shouldn't it be normal for a compiler to detect the status of
a subprogram WRT overriding? (It is, I think, and not just in
Ada.) Consequently, programmers would mark the opposite case.
They'd write "not overriding" only if a subprogram is really
intended to not be overriding.

Premises:
- A subprogram is an overriding subprogram in most cases.
+ I.e., a subprogram following a type declaration is usually
   intended to override. Here, "usually" refers to OOD
   being  ubiquitous.

- Idiomatic use will suggest to place non-overriding subprograms
   in nested packages (factories, for example).

- Compilers will warn in any case whenever they detect
   a subprogram that looks suspicious.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  7:55     ` Georg Bauhaus
@ 2011-07-06  8:30       ` AdaMagica
  2011-07-06 12:59         ` Georg Bauhaus
  2011-07-07 10:37         ` Stephen Leake
  2011-07-06 15:06       ` Adam Beneschan
                         ` (2 subsequent siblings)
  3 siblings, 2 replies; 63+ messages in thread
From: AdaMagica @ 2011-07-06  8:30 UTC (permalink / raw)


On 6 Jul., 09:55, Georg Bauhaus <rm.dash-bauh...@futureapps.de> wrote:
> On 7/6/11 6:34 AM, AdaMagica wrote:
>
> > I should have written
>
> >    overriding procedure Doit (X: access Derived_Class);
>
> Instead of sprinkling the program with overriding indicators,
> shouldn't it be normal for a compiler to detect the status of
> a subprogram WRT overriding? (It is, I think, and not just in
> Ada.) Consequently, programmers would mark the opposite case.
> They'd write "not overriding" only if a subprogram is really
> intended to not be overriding.

OK, the compiler knows what it is - but the programmer perhaps
doesn't. It is a hint for the compiler to check the programmer's
intention.

overriding: the compiler complains - oops, did I misspell the name?
non overriding: the compiler complains - oops, I thought there was an
inherited version.

In both cases, if the compiler suddenly complains when before
everything was OK, something in the hierarchy below the actual type
must have changed. Without those keywords, you will never be informed
and will spend hours or days debugging.

> Premises:
> - A subprogram is an overriding subprogram in most cases.
> + I.e., a subprogram following a type declaration is usually
>    intended to override. Here, "usually" refers to OOD
>    being  ubiquitous.

Really?

> - Idiomatic use will suggest to place non-overriding subprograms
>    in nested packages (factories, for example).

No, a non-overriding operation may well be primitive, so cannot be in
a nested scope.

> - Compilers will warn in any case whenever they detect
>    a subprogram that looks suspicious.

When is something suspicious for the (mind-reading) compiler?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  8:30       ` AdaMagica
@ 2011-07-06 12:59         ` Georg Bauhaus
  2011-07-06 13:23           ` AdaMagica
                             ` (2 more replies)
  2011-07-07 10:37         ` Stephen Leake
  1 sibling, 3 replies; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-06 12:59 UTC (permalink / raw)


On 06.07.11 10:30, AdaMagica wrote:
> On 6 Jul., 09:55, Georg Bauhaus <rm.dash-bauh...@futureapps.de> wrote:
>> On 7/6/11 6:34 AM, AdaMagica wrote:
>>
>>> I should have written
>>
>>>    overriding procedure Doit (X: access Derived_Class);
>>

> In both cases, if the compiler suddenly complains when before
> everything was OK, something in the hierarchy below the actual type
> must have changed. Without those keywords, you will never be informed
> and will spend hours or days debugging.

Besides these cases, there are other cases that will make the
compiler complain only if a programmer has placed overriding_indicators.
With good reason, from his or her point of view.

If a programmer's intent has been to express overriding status, but, when
trying to do so, he or she did not understand the full set of rules
that restrict the set of permissible places for overriding_indicator,
the compiler's complaint may generate anger more than anything else.

And maybe that anger is justified.

That is, in this programming situation involving non-overriding
operations, the [not] overriding_indicator does not entail measures
against the effects of typos (the feature's purpose as stated in the RM).
But it may well create confusion.  Even when some lengthy formal
exegesis will permit putting the blame on the programmer, this does
not seem helpful.  I can't think this has been an intent, either.

The LRM rules regulating overriding_indicator seem to have been
derived form Ada's O-O logic and visibility.  Not so much from the
more general programming situation where any indicators would
instead cater to programmers' intentions, IMHO.

overriding_indicators are all logical and such, and I'll accept it
if they cannot be designed any better.  But somehow I like package C4
below a lot more than I like the others.

(The error message at L.26 and L.37, taken together, are---per
se---confusing, aren't they?)

Example:

Compilation started at Wed Jul  6 11:13:55

gnatmake -gnatwa -gnatvf -gnatl ovrd.ads
gcc -c -gnatwa -gnatvf -gnatl ovrd.ads

GNAT 4.7.0 20110610 (experimental)
Copyright 1992-2011, Free Software Foundation, Inc.


Compiling: ovrd.ads (source file time stamp: 2011-07-06 11:13:47)

     1. package Ovrd is
     2.
     3.     package P1 is
     4.
     5.         type T1 is abstract tagged private;
     6.         procedure Op (X : in out T1) is abstract;
     7.
     8.     private
     9.         type T1 is abstract tagged null record;
    10.     end P1;
    11.
    12.     package P2 is
    13.
    14.         type T2 is new P1.T1 with private;
    15.         procedure Oops (X : in out T2);
    16. 	--  typo, possibly not caught by soundex algorithm etc, but...
    17.     private
    18.         type T2 is new P1.T1 with null record;
                     |
        >>> type must be declared abstract or "Op" overridden
        >>> "Op" has been inherited at line 14
        >>> "Op" has been inherited from subprogram at line 6

    19.     end P2;
    20.
    21.
    22.     package C1 is
    23.
    24.         type T1 is private;
    25.         not overriding  -- E!  `Op` overrides invisibly (in private part)
    26.         procedure Op (X : in out T1);
                |
        >>> subprogram "Op" overrides inherited operation at line 29

    27.
    28.     private
    29.         type T1 is new P1.T1 with null record;
    30.     end C1;
    31.
    32.
    33.     package C2 is
    34.
    35.         type T1 is private;
    36.         overriding  -- E!  Overriding? Yes, but privately
    37.         procedure Op (X : in out T1);
                |
        >>> subprogram "Op" is not overriding

    38.
    39.     private
    40.         type T1 is new P1.T1 with null record;
    41.     end C2;
    42.
    43.
    44.     package C3 is
    45.
    46.         type T1 is private;
    47. 	not overriding  -- OK, not overriding in any place
    48. 	procedure Op (X : in out T1);
    49.
    50.     private
    51.         type T1 is null record;
    52.     end C3;
    53.
    54.
    55.     package C4 is
    56.
    57.         type T1 is private;
    58. 	--  Overriding status is not known.  Should we care
    59. 	--  in this case, for a type that is simply private?
    60.         procedure Op (X : in out T1);
    61.
    62.     private
    63.         type T1 is new P1.T1 with null record;
    64.     end C4;
    65.
    66.
    67.     package C5 is
    68.
    69.         type T1 is private;
    70. 	--  No more `Op`
    71.
    72.     private
    73.         type T1 is new P1.T1 with null record;
    74. 	overriding  -- correct, overriding at this place
    75. 	procedure Op (X : in out T1);
    76.     end C5;
    77.
    78. end Ovrd;

 78 lines: 5 errors
gnatmake: "ovrd.ads" compilation error

Compilation exited abnormally with code 4 at Wed Jul  6 11:13:55



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 12:59         ` Georg Bauhaus
@ 2011-07-06 13:23           ` AdaMagica
  2011-07-06 19:06             ` Randy Brukardt
  2011-07-06 13:28           ` Simon Wright
  2011-07-06 19:45           ` Randy Brukardt
  2 siblings, 1 reply; 63+ messages in thread
From: AdaMagica @ 2011-07-06 13:23 UTC (permalink / raw)


I guess this has to be based on visibility to prevent privacy
breaking. In these cases where overriding indicators are illegal in
the spec, they can be applied in the body.

Note that the RM does not make any statement whether they shall appear
at the spec, body, or both.

I think a general idiom should be: use them at both places as long as
is legal. Thus you provide the most information to the compiler and
future readers of the code.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 12:59         ` Georg Bauhaus
  2011-07-06 13:23           ` AdaMagica
@ 2011-07-06 13:28           ` Simon Wright
  2011-07-06 19:45           ` Randy Brukardt
  2 siblings, 0 replies; 63+ messages in thread
From: Simon Wright @ 2011-07-06 13:28 UTC (permalink / raw)


Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:

> (The error message at L.26 and L.37, taken together, are---per
> se---confusing, aren't they?)

>     22.     package C1 is
>     23.
>     24.         type T1 is private;
>     25.         not overriding  -- E!  `Op` overrides invisibly (in private part)
>     26.         procedure Op (X : in out T1);
>                 |
>         >>> subprogram "Op" overrides inherited operation at line 29
>
>     27.
>     28.     private
>     29.         type T1 is new P1.T1 with null record;
>     30.     end C1;
>     31.
>     32.
>     33.     package C2 is
>     34.
>     35.         type T1 is private;
>     36.         overriding  -- E!  Overriding? Yes, but privately
>     37.         procedure Op (X : in out T1);
>                 |
>         >>> subprogram "Op" is not overriding
>
>     38.
>     39.     private
>     40.         type T1 is new P1.T1 with null record;
>     41.     end C2;

The compiler does seem to be a bit confused, but I wonder whether a
human reader might not be confused too? It might be good at least to say
"type T1 is tagged private;" (though it makes no difference to the
reported problem).



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  7:55     ` Georg Bauhaus
  2011-07-06  8:30       ` AdaMagica
@ 2011-07-06 15:06       ` Adam Beneschan
  2011-07-06 16:36       ` Dmitry A. Kazakov
  2011-07-06 19:20       ` Randy Brukardt
  3 siblings, 0 replies; 63+ messages in thread
From: Adam Beneschan @ 2011-07-06 15:06 UTC (permalink / raw)


On Jul 6, 12:55 am, Georg Bauhaus <rm.dash-bauh...@futureapps.de>
wrote:

> Instead of sprinkling the program with overriding indicators,
> shouldn't it be normal for a compiler to detect the status of
> a subprogram WRT overriding?

To further elaborate on what Christoph said: it does detect that, and
in fact you *never* need to say "overriding" or "not overriding".
Using those keywords will never change the meaning of a legal
program.  They're there just to protect against accidental errors,
which unfortunately were happening.  Misspelling is one way of
introducing an error.  Also, there are some cases where the rules
about what inherited subprograms are visible and where they're visible
aren't entirely intuitive, so that in some cases even when a
subprogram intended as overriding was spelled correctly, it still
didn't override as intended.  Errors like that don't usually lead to
further syntax errors from the compiler, so it's harder to diagnose
when the program doesn't run as expected.

                                           -- Adam




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  7:55     ` Georg Bauhaus
  2011-07-06  8:30       ` AdaMagica
  2011-07-06 15:06       ` Adam Beneschan
@ 2011-07-06 16:36       ` Dmitry A. Kazakov
  2011-07-06 19:20       ` Randy Brukardt
  3 siblings, 0 replies; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-07-06 16:36 UTC (permalink / raw)


On Wed, 06 Jul 2011 09:55:44 +0200, Georg Bauhaus wrote:

> On 7/6/11 6:34 AM, AdaMagica wrote:
>> I should have written
>>
>>    overriding procedure Doit (X: access Derived_Class);
> 
> Instead of sprinkling the program with overriding indicators,
> shouldn't it be normal for a compiler to detect the status of
> a subprogram WRT overriding?

It does. In Ada 95 there were no "overriding" qualifiers.

> (It is, I think, and not just in
> Ada.) Consequently, programmers would mark the opposite case.
> They'd write "not overriding" only if a subprogram is really
> intended to not be overriding.

There are three cases actually:

1. Primitive operation
1.a. Overriding
1.b. New primitive operation
2. Free operation

> - Compilers will warn in any case whenever they detect
>    a subprogram that looks suspicious.

In order to be sure about the programmer's intent the compiler must know
the class of the body being declared. Ada syntax does not provide such
information, e.g.

   type S is new T;
   procedure Foo (Object : S) of T'Class; -- Overrides Foo of T'Class
   procedure Bar (Object : S) of S'Class; -- A new primitive operation
   procedure Baz (Object : S) of null; -- Free operation

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 13:23           ` AdaMagica
@ 2011-07-06 19:06             ` Randy Brukardt
  0 siblings, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-07-06 19:06 UTC (permalink / raw)


"AdaMagica" <christ-usch.grein@t-online.de> wrote in message 
news:7c515c1d-d170-4cd2-8702-6532e09d6f42@y24g2000yqb.googlegroups.com...
>I guess this has to be based on visibility to prevent privacy
> breaking. In these cases where overriding indicators are illegal in
> the spec, they can be applied in the body.
>
> Note that the RM does not make any statement whether they shall appear
> at the spec, body, or both.

Actually, it does. Indicators are not allowed on bodies unless those bodies 
can act as declarations.

> I think a general idiom should be: use them at both places as long as
> is legal. Thus you provide the most information to the compiler and
> future readers of the code.

You can't do that in general (specifically, for protected subprograms) and 
that is intentional. The intent was that the indicators be provided only 
once (on the spec, or on a body acting as a spec). Beyond that, there was an 
allowance to put indicators on bodies when they were omitted from the spec; 
but there was never any intent that indicators would be *repeated* on 
bodies.

                                           Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  7:55     ` Georg Bauhaus
                         ` (2 preceding siblings ...)
  2011-07-06 16:36       ` Dmitry A. Kazakov
@ 2011-07-06 19:20       ` Randy Brukardt
  3 siblings, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-07-06 19:20 UTC (permalink / raw)


"Georg Bauhaus" <rm.dash-bauhaus@futureapps.de> wrote in message 
news:4e141501$0$6629$9b4e6d93@newsspool2.arcor-online.net...
> On 7/6/11 6:34 AM, AdaMagica wrote:
>> I should have written
>>
>>    overriding procedure Doit (X: access Derived_Class);
>
> Instead of sprinkling the program with overriding indicators,
> shouldn't it be normal for a compiler to detect the status of
> a subprogram WRT overriding?

Sure, but what the compiler decides and what the programmer expects are very 
often different. The intent of indicators is to tell the compiler what the 
programmer is expecting.

> (It is, I think, and not just in
> Ada.) Consequently, programmers would mark the opposite case.
> They'd write "not overriding" only if a subprogram is really
> intended to not be overriding.

That would work if the compiler rejected routines that were not overriding 
unless "not overriding" appears. But Ada doesn't work that way (because it 
inherited a bad model from Ada 95).

Routines that didn't override when they were expected to cost us more than 
100 hours of debugging when we building Claw. Typos, changes to the root 
classes, and interactions with Ada's visibility rules all caused routines to 
not override when they should have. Overriding indicators were invented 
specifically to address this problem; the original intent was to include a 
state where it was illegal to override unless the indicator was provided. 
(Semantic issues with that caused it to be abandoned.)

"Not overriding" is far less important.

> Premises:
> - A subprogram is an overriding subprogram in most cases.
> + I.e., a subprogram following a type declaration is usually
>   intended to override. Here, "usually" refers to OOD
>   being  ubiquitous.

That is only true for derived types (including type extensions); it's never 
true for any other kind of type.

> - Idiomatic use will suggest to place non-overriding subprograms
>   in nested packages (factories, for example).

That makes no sense, as any time an extension adds new operations you will 
want those to be primitive and inherited in further extensions. Claw has a 
lot of such operations.

> - Compilers will warn in any case whenever they detect
>   a subprogram that looks suspicious.

That's not possible in any reasonable way. It's quite common to add 
overrloaded operations with additional/different parameters in an extension. 
As a result, Janus/Ada has no such warnings, because we couldn't find 
anything that wouldn't be "crying wolf" more often than it would be telling 
something useful. And proper use of indicators is better anyway, because the 
program is rejected if wrong.

                                           Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 12:59         ` Georg Bauhaus
  2011-07-06 13:23           ` AdaMagica
  2011-07-06 13:28           ` Simon Wright
@ 2011-07-06 19:45           ` Randy Brukardt
  2011-07-06 22:05             ` Georg Bauhaus
  2 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-06 19:45 UTC (permalink / raw)


"Georg Bauhaus" <rm.dash-bauhaus@futureapps.de> wrote in message 
news:4e145c3a$0$6542$9b4e6d93@newsspool4.arcor-online.net...
...
> If a programmer's intent has been to express overriding status, but, when
> trying to do so, he or she did not understand the full set of rules
> that restrict the set of permissible places for overriding_indicator,
> the compiler's complaint may generate anger more than anything else.

If the programmer doesn't understand the model of overriding in Ada, they 
are going to be disappointed. It's better that the compiler complain than 
silently doing the wrong thing.

...
> That is, in this programming situation involving non-overriding
> operations, the [not] overriding_indicator does not entail measures
> against the effects of typos (the feature's purpose as stated in the RM).

I have no idea what you are talking about. The feature definitely prevents 
problems with the effect of typos; of course, if you use it when there is no 
overriding going on, you'll have problems.

> But it may well create confusion.  Even when some lengthy formal
> exegesis will permit putting the blame on the programmer, this does
> not seem helpful.  I can't think this has been an intent, either.

If you don't understand what you are doing, you are going to have problems.

> The LRM rules regulating overriding_indicator seem to have been
> derived form Ada's O-O logic and visibility.

What else would it derive from?

> Not so much from the
> more general programming situation where any indicators would
> instead cater to programmers' intentions, IMHO.

It corresponds exactly to the programmer's intentions, so long as those 
intentions are based on the RM definition of overriding and not some other 
imagined version of the rules.

> Example:
>
...
>    55.     package C4 is
>    56.
>    57.         type T1 is private;
>    58. --  Overriding status is not known.  Should we care
>    59. --  in this case, for a type that is simply private?
>    60.         procedure Op (X : in out T1);
>    61.
>    62.     private
>    63.         type T1 is new P1.T1 with null record;
>    64.     end C4;

You should not use any indicators in this case, as the type in question is 
not a derived type (which for this purpose includes type extensions and 
private extensions). Only derived types inherit anything, so the use of any 
indicators is wrong/misleading. It should be noted that I had wanted to be 
able to use "not overriding" everywhere, but I was overruled.

The private type demonstrates a serious flaw in Ada that unfortunately we're 
stuck with. You should not be able to have a routine that is declared in the 
visible part be overriding in the private part. That should be strictly 
illegal. (OTOH, it is be OK to override solely in the private part.) 
Operations that are visible and are inherited should be visibly inherited.

The work we've been doing recently with contracts (preconditions, 
postconditions, and the like) demonstrate this; you will have all sorts of 
logical problems when the visible contracts on the specification aren't 
appropriate for those on the overriding. You would be many times better 
served to visibly inherit the routine (along with the contracts), either by 
using an interface or by visibly deriving from P1.T1, or to avoid 
inheritance altogether (by using a record with a component of P1.T1.)

Note also that this sort of structure prevents the use of C4.T1 by the 
client in class-wide operations of P1.T1. That is usually a bad thing 
(requiring duplication of operations in order to provide equivalent 
functionality). Sometimes people do this on purpose, in an attempt to 
"eliminate" operations from an extension. But "eliminating" operations 
violates all of the theory about OOP, and generally means that a 
restructuring of your "object" types is needed.

To summarize: this is a bad case that shouldn't have been allowed by Ada in 
the first place -- the problem is with Ada allowing it, not with the use of 
indicators with it.

(You'd have had a better case had you shown examples involving generics. 
Those caused all of the problems that led us to abandoning the "always use 
indicators" restriction.)

                                                   Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 19:45           ` Randy Brukardt
@ 2011-07-06 22:05             ` Georg Bauhaus
  2011-07-06 23:56               ` Adam Beneschan
  0 siblings, 1 reply; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-06 22:05 UTC (permalink / raw)


On 7/6/11 9:45 PM, Randy Brukardt wrote:
> "Georg Bauhaus"<rm.dash-bauhaus@futureapps.de>  wrote in message
> news:4e145c3a$0$6542$9b4e6d93@newsspool4.arcor-online.net...
> ...

>> That is, in this programming situation involving non-overriding
>> operations, the [not] overriding_indicator does not entail measures
>> against the effects of typos (the feature's purpose as stated in the RM).
>
> I have no idea what you are talking about.

(About what you explain later on: that we should avoid overriding_indicators
when they create problems...)

>> But it may well create confusion.  Even when some lengthy formal
>> exegesis will permit putting the blame on the programmer, this does
>> not seem helpful.  I can't think this has been an intent, either.
>
> If you don't understand what you are doing, you are going to have problems.

This topos (of which "Stupid!" seems a possible paraphrase) copies, almost
exactly, that of a zealot defending C's flaws, fiercely. ;-)

But, seriously, as they reportedly say in ARG circles, almost no one
understands Ada.  Therefore, if a substantial amount of understanding
is necessary in order to use indicators properly, there is something
wrong somewhere, IMHO.  You have pointed to flaws and alternative solutions,
Dmitry has hinted at syntactical means of classifications, I think.

>> The LRM rules regulating overriding_indicator seem to have been
>> derived form Ada's O-O logic and visibility.
>
> What else would it derive from?

Like in the days that led to Ada: language features should
meet a requirement. To establish the requirements, you would,
quite naturally, not be taking most input from the language
not defined yet.  In the case leading to overriding_indicator,
the requirements seems to include technicalities with typos
in Ada programs ...


> It corresponds exactly to the programmer's intentions, so long as those
> intentions are based on the RM definition of overriding and not some other
> imagined version of the rules.

And here's a point: when I use Ada syntax, I like to think that
its purpose is to express my intentions with regard to the next
thing, which is describing one part of the problem and its
solution in Ada.  To illustrate, when I write "type" or
"procedure" or "loop", then I want the next thing to be a type,
a procedure, or a loop.  When I write "overriding", I do not
influence in any way what the next thing will be (overriding or
not), as this is a consequence of language rules.

The purpose of syntax should not be to clarify
my understanding of the Ada language.  Or is a program an exam
that tests my understanding of Ada's O-O features?

But OK, seen as a use case of syntax, "overriding" as a keyword
mirrors "limited" in that there is permission to use  and repeat
"limited" in a type's definition even when it is limited anyway.
I like it.

Does "limited" create comparable problems, though?

Your comment above is about permissible programmer intentions,
if I may say so.  Just for contrast, C version:
int behavior near INT_MAX corresponds exactly to the programmer's
intentions, so long as those intentions are based on the standard's,
the compiler's, and the platform's definition (or not) of int
and not some other imagined integers.

While this is correct, it doesn't prevent the bi-weekly CVE
caused by int.


> Note also that this sort of structure prevents the use of C4.T1 by the
> client in class-wide operations of P1.T1. That is usually a bad thing
> (requiring duplication of operations in order to provide equivalent
> functionality). Sometimes people do this on purpose, in an attempt to
> "eliminate" operations from an extension. But "eliminating" operations
> violates all of the theory about OOP, and generally means that a
> restructuring of your "object" types is needed.

Arguably (and I'm not sure I like the pattern implemented using
inheritance), to remove the operations from a type in the visible
part (by not making it visibly inheriting) would serve to establish
an adapter. I don't see the problem with theory about OOP:

- there is then a different type that hides the information that
   it privately inherits,

- clients are prevented form deriving from the visible type.


> (You'd have had a better case had you shown examples involving generics.
> Those caused all of the problems that led us to abandoning the "always use
> indicators" restriction.)

So I was right to not even try, based on a gut feeling. :)



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 22:05             ` Georg Bauhaus
@ 2011-07-06 23:56               ` Adam Beneschan
  2011-07-07 14:09                 ` Georg Bauhaus
  0 siblings, 1 reply; 63+ messages in thread
From: Adam Beneschan @ 2011-07-06 23:56 UTC (permalink / raw)


On Jul 6, 3:05 pm, Georg Bauhaus <rm.dash-bauh...@futureapps.de>
wrote:

> But, seriously, as they reportedly say in ARG circles, almost no one
> understands Ada.  Therefore, if a substantial amount of understanding
> is necessary in order to use indicators properly, there is something
> wrong somewhere, IMHO.

Either I'm having difficulty following your argument, or you've
totally lost the plot.  You do not need a lot of understanding to use
overriding indicators.  If you declare an operation and you intend
that this operation replaces (overrides) the same operation for the
parent, then add "overriding".  If you declare an operation and you
intend that it be a NEW operation that did not exist for the parent
type, then add "not overriding".  Seems simple to me---you don't need
a "substantial amount of understanding" for this!

If you use one of these indicators, the compiler will then complain if
your keyword doesn't match the compiler's concept of whether the
declaration is overriding or not.  Then you (1) check for typos, (2)
check to make sure a new, conflicting operation hasn't been added for
an ancestor or progenitor type, or (3) in the complex case where
visibility rules cause an inherited operation to disappear, then
you'll have to figure out what's going on.  Case #3 is the difficult
one.  But in this case, if you *don't* use the overriding indicator,
*then* you need a substantial amount of understanding of the language
rules, because the compiler won't check for you; it will assume you
know what you're doing.  So I think you have it backwards---you need a
substantial amount of understanding *NOT* to use overriding
indicators.

                                   -- Adam



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06  8:30       ` AdaMagica
  2011-07-06 12:59         ` Georg Bauhaus
@ 2011-07-07 10:37         ` Stephen Leake
  2011-07-07 13:18           ` Georg Bauhaus
  1 sibling, 1 reply; 63+ messages in thread
From: Stephen Leake @ 2011-07-07 10:37 UTC (permalink / raw)


AdaMagica <christ-usch.grein@t-online.de> writes:

> On 6 Jul., 09:55, Georg Bauhaus <rm.dash-bauh...@futureapps.de> wrote:
>> On 7/6/11 6:34 AM, AdaMagica wrote:
>>
>> > I should have written
>>
>> >    overriding procedure Doit (X: access Derived_Class);
>>
>> Instead of sprinkling the program with overriding indicators,
>> shouldn't it be normal for a compiler to detect the status of
>> a subprogram WRT overriding? (It is, I think, and not just in
>> Ada.) Consequently, programmers would mark the opposite case.
>> They'd write "not overriding" only if a subprogram is really
>> intended to not be overriding.
>
> OK, the compiler knows what it is - but the programmer perhaps
> doesn't. It is a hint for the compiler to check the programmer's
> intention.
>
> overriding: the compiler complains - oops, did I misspell the name?
> non overriding: the compiler complains - oops, I thought there was an
> inherited version.

More importantly; oops, I changed the parent, and forgot to change the
child; now the compiler warns me.

If you don't put 'overriding' on all child operations, they silently
become non-overriding when the parent changes. Very Bad Things Happen.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 10:37         ` Stephen Leake
@ 2011-07-07 13:18           ` Georg Bauhaus
  2011-07-08 19:23             ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-07 13:18 UTC (permalink / raw)


On 07.07.11 12:37, Stephen Leake wrote:

> If you don't put 'overriding' on all child operations, they silently
> become non-overriding when the parent changes. Very Bad Things Happen.

An indicator "not overriding" will also "help" when one adds a name
to a parent that had already been used in a child type and has
been duly marked "not overriding" there.
It is only an early hint, though. For example, taking care of LSP
substitutability is not an immediate consequence of the presence
of overriding indicators, but the diagnosis is a start, if not
the best IMHO.

An indicator "overriding" will also help with c&p errors.
For example, when forgetting to adapt parameter profiles to the
child type.

So this is about typos.

What instances of Very Bad Things can be removed with the
help of indicators?

Some of the Very Bad Things happen mostly when the types
do not inherit directly from abstract types or interfaces (as
changing ops will then result in compilation errors).  This,
I think, can be termed The First Bad Thing.

Bad things also happen, more generally, whenever some programming
error would be prevented simply by adding indicators of suitable
sorts that would explain the programmer's intention.  But shouldn't
this kind of information be covered by "normal" language instead?

Or, for an alternative, one might imagine adding a "smart indicator
pragma"

  pragma Fuzzy_Homographs (Threshold => 0.9);

This, then, will prevent frequently quoted errors such as

  Initialse(...) vs Initialize(...).

*Without* restricting the compiler's assistance to just tagged
types!

This, from my point of view, might equip the language with
better means of addressing the real issue, which seems to
be one of naming.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-06 23:56               ` Adam Beneschan
@ 2011-07-07 14:09                 ` Georg Bauhaus
  2011-07-07 15:10                   ` Adam Beneschan
  2011-07-07 15:19                   ` Georg Bauhaus
  0 siblings, 2 replies; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-07 14:09 UTC (permalink / raw)


On 07.07.11 01:56, Adam Beneschan wrote:
> (3) in the complex case where
> visibility rules cause an inherited operation to disappear, then
> you'll have to figure out what's going on.  Case #3 is the difficult
> one.

Yes, and either way, I think I'll have to think about complex issues
in case #3, with or without indicators, insofar as either issue
(backwards or forwards) will point to the same things. Should
an issue arise.  But point taken, every hint from the compiler
is welcome, the better hint wins.

I guess I'm uneasy with indicators (which I use) because they
purport to solve some problem, but this is just accidental,
and ad hoc, and incomplete in several dimensions.  Maybe something
better is still possible.

If indicators are about doing Ada inheritance properly, here is
an alternative. (That's likely a bold attempt, but anyway.)
Like "overriding", it restricts the language's assistence
to just tagged types.  Instead of adding all indicators,
have the programmer explicitly mention each operation.  Let

  T0 = ({...}, {Op1, ..., OpN}),

then deriving T1 from T0 will list all operations {Op1, ..., OpN}.
(Tools will help the lazy writer.)  For N=2:

   type T0 is abstract tagged private;
   procedure Op1 (X : in out T0) is abstract;
   procedure Op2 (X : in out T0) is abstract;

Then,

   type T1 is abstract new T0 with private;
   procedure Op1 (X : in out T1) is <>;  -- abstract
   procedure Op2 (X : in out T1);  -- overriding
   procedure Op3 (X : in out T1); -- DC

   type T2 is new T1 with private;
   procedure Op1 (X : in out T2);  -- overriding
   procedure Op2 (X : in out T2) is <>; -- inheriting
   procedure Op3 (X : in out T2); -- overriding
   procedure Op4 (X : in out T2); -- DC


Remove T0's Op2. Then, T1 and T2 will have a dispatching
operation that no longer overrides their parent's.  Bad?

Add Op17 to T1. T2 will become invalid because it does
not list Op17. (Fix is to list Op17 using "is <>".)

Add Op3 to T0.  T1's Op3 then becomes overriding. Bad?

Misspelling T2's Op2 renders T2 invalid (because all names
of T1 have to be listed and Op2 will not be listed).
A call on an object of type T2 cannot "by accident"
resolve to a call on T1's.


Eiffel has something similar.  A class inheriting from other
classes will list the features (operations) that it is going
to redefine (override).



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 14:09                 ` Georg Bauhaus
@ 2011-07-07 15:10                   ` Adam Beneschan
  2011-07-08  4:29                     ` AdaMagica
  2011-07-08 19:12                     ` Randy Brukardt
  2011-07-07 15:19                   ` Georg Bauhaus
  1 sibling, 2 replies; 63+ messages in thread
From: Adam Beneschan @ 2011-07-07 15:10 UTC (permalink / raw)


On Jul 7, 7:09 am, Georg Bauhaus <rm.dash-bauh...@futureapps.de>
wrote:

> I guess I'm uneasy with indicators (which I use) because they
> purport to solve some problem, but this is just accidental,
> and ad hoc, and incomplete in several dimensions.  Maybe something
> better is still possible.

I think you're right that this was an ad hoc solution to an unforeseen
problem, and that there may have been better ways to do this back in
Ada 95 if the team had realized the potential problems.  On the other
hand, I'm not all that uneasy with it because I realize that if we
waited to make sure that everything was perfect, the first version of
Ada would have been Ada 2317 or something like that, and we would have
been stuck with C until then.

Your idea below seems sensible, but it's not backward-compatible; if
it were added to the next version of Ada, a lot of legal programs
would become illegal, and that's something the designers try to
avoid.  Perhaps there's a solution involving aspect clauses---since
they're new, it would be easier to make them backward-compatible.  One
idea off the top of my head:

   type T1 is new T0 with record ... end record
       with inherit => (Op1, Op3), override => (Op2, Op4);

(Aspect specifications don't currently allow lists of identifiers, but
this could probably be changed compatibly.)  Then the type declaration
would be illegal if T0 has a primitive operation that isn't listed in
either list, if an operation is listed that isn't a primitive
operation of T0, if there is a conflicting declaration for something
in the "inherit" list, or there is no overriding declaration for
something in the "override" list.  This is just a first attempt, and
it definitely won't work because it doesn't deal with overloaded names
and there are probably problems with private parts.

But maybe we could implement your idea and still make things backward
compatible:

   type T1 is new T0 with record ... end record
      with Georgs_Rules;

Then if the "with Georgs_Rules" is present, the operation declarations
would have to follow your rules, and if it isn't, they'd follow the
old rules.  Then GNAT would add an option that would cause the
compiler to reject any type extension without this aspect clause.
(Somebody else would have to come up with a better name for this
aspect.)

I'm just brainstorming here; I don't have any idea whether a feature
like this would be worthwhile, particularly since it could cause the
language rules to become somewhat messy.

                                   -- Adam



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 14:09                 ` Georg Bauhaus
  2011-07-07 15:10                   ` Adam Beneschan
@ 2011-07-07 15:19                   ` Georg Bauhaus
  1 sibling, 0 replies; 63+ messages in thread
From: Georg Bauhaus @ 2011-07-07 15:19 UTC (permalink / raw)


On 07.07.11 16:09, Georg Bauhaus wrote:

> Like "overriding", it restricts the language's assistence
> to just tagged types. 
<del>tagged</del>



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 15:10                   ` Adam Beneschan
@ 2011-07-08  4:29                     ` AdaMagica
  2011-07-08 19:08                       ` Randy Brukardt
  2011-07-08 19:12                     ` Randy Brukardt
  1 sibling, 1 reply; 63+ messages in thread
From: AdaMagica @ 2011-07-08  4:29 UTC (permalink / raw)


     3.     package P1 is
     5.         type T1 is abstract tagged private;
     6.         procedure Op (X : in out T1) is abstract;
     8.     private
     9.         type T1 is abstract tagged null record;
    10.     end P1;
    11.
    55.     package C4 is
    57.         type T1 is private;
    58.         --  Overriding status is not known.  Should we care
    59.         --  in this case, for a type that is simply private?
    60.         procedure Op (X : in out T1);
    62.     private
    63.         type T1 is new P1.T1 with null record;
                -- But do we have to care here?
                overriding -- or any other syntax
                procedure Op (X : in out T1);
   64.     end C4;

All these attempts do not solve the privacy issues of Georg's example
repeated here. Would we have to repeat the declaration of Op after the
full type declaration when we know whether it is overriding or not?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-08  4:29                     ` AdaMagica
@ 2011-07-08 19:08                       ` Randy Brukardt
  0 siblings, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-07-08 19:08 UTC (permalink / raw)


"AdaMagica" <christ-usch.grein@t-online.de> wrote in message 
news:b420bce2-25e9-4500-b31b-60d3c4d7878f@x10g2000vbl.googlegroups.com...
...
> All these attempts do not solve the privacy issues of Georg's example
> repeated here. Would we have to repeat the declaration of Op after the
> full type declaration when we know whether it is overriding or not?

That would be best, but of course Ada doesn't allow it. I wonder what new 
problems would be introduced by such a feature?

                    Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 15:10                   ` Adam Beneschan
  2011-07-08  4:29                     ` AdaMagica
@ 2011-07-08 19:12                     ` Randy Brukardt
  1 sibling, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-07-08 19:12 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:1c98072b-e5b9-43dd-9fde-f6687086deef@w24g2000yqw.googlegroups.com...
...
> (Aspect specifications don't currently allow lists of identifiers, but
> this could probably be changed compatibly.)

Actually, aspect_specifications allow any syntax that the implementer wants 
to support - 13.3.1(38/3). To use them portably, of course, you have to 
stick to the language-defined aspects and syntax, but no surprise there.

This was done so that implementers could experiment with ideas like this, 
the unfinised Global in/global out proposal, and exception contracts, all of 
which require fancier syntax than is currently defined.

                     Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-07 13:18           ` Georg Bauhaus
@ 2011-07-08 19:23             ` Randy Brukardt
  2011-07-08 21:41               ` Jeffrey Carter
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-08 19:23 UTC (permalink / raw)


"Georg Bauhaus" <rm.dash-bauhaus@futureapps.de> wrote in message 
news:4e15b223$0$6541$9b4e6d93@newsspool4.arcor-online.net...
...
> What instances of Very Bad Things can be removed with the
> help of indicators?

The main one is a routine that did not override when it was expected to. 
This sort of bug cost us many hours of debugging time in Claw, because when 
you trace the logic of the program everything seems correct - just the wrong 
body is being called by dispatching routines and typically you can only 
figure that out by adding tracing to all of the bodies. Ugh!

There are some very subtle visibility-based reasons that a routine will not 
be overriding, and no programmer can be expected to understand those. In 
particular, the "sibling inheritance" problem. The "overriding" indicator 
will at least cause the compiler to complain, and then the programmer can 
spend his time restructuring his entire system rather than pointlessly 
debugging. (This particular problem has no workaround; the package structure 
of the program has to be changed. We tried pretty hard to provide a 
workaround in Ada 2012, but we couldn't do so compatibly or even with just a 
compile-time incompatibility, and a runtime incompatibily is unacceptable. 
Blame interfaces for that - another reason that I hate them. :-) See 
AI05-0125-1 and the associated minutes for the details, if you care.)

                       Randy.

> Some of the Very Bad Things happen mostly when the types
> do not inherit directly from abstract types or interfaces (as
> changing ops will then result in compilation errors).  This,
> I think, can be termed The First Bad Thing.
>
> Bad things also happen, more generally, whenever some programming
> error would be prevented simply by adding indicators of suitable
> sorts that would explain the programmer's intention.  But shouldn't
> this kind of information be covered by "normal" language instead?
>
> Or, for an alternative, one might imagine adding a "smart indicator
> pragma"
>
>  pragma Fuzzy_Homographs (Threshold => 0.9);
>
> This, then, will prevent frequently quoted errors such as
>
>  Initialse(...) vs Initialize(...).
>
> *Without* restricting the compiler's assistance to just tagged
> types!
>
> This, from my point of view, might equip the language with
> better means of addressing the real issue, which seems to
> be one of naming.
>
>
> 





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-08 19:23             ` Randy Brukardt
@ 2011-07-08 21:41               ` Jeffrey Carter
  2011-07-09  6:14                 ` Dmitry A. Kazakov
  2011-07-22 22:59                 ` Randy Brukardt
  0 siblings, 2 replies; 63+ messages in thread
From: Jeffrey Carter @ 2011-07-08 21:41 UTC (permalink / raw)


On 07/08/2011 12:23 PM, Randy Brukardt wrote:
>
> This particular problem has no workaround...

I disagree. The use of programming by composition is an effective work around to 
all the problems introduced by programming by extension.

-- 
Jeff Carter
"I don't know why I ever come in here. The
flies get the best of everything."
Never Give a Sucker an Even Break
102



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-08 21:41               ` Jeffrey Carter
@ 2011-07-09  6:14                 ` Dmitry A. Kazakov
  2011-07-22 22:59                 ` Randy Brukardt
  1 sibling, 0 replies; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-07-09  6:14 UTC (permalink / raw)


On Fri, 08 Jul 2011 14:41:05 -0700, Jeffrey Carter wrote:

> On 07/08/2011 12:23 PM, Randy Brukardt wrote:
>>
>> This particular problem has no workaround...
> 
> I disagree. The use of programming by composition is an effective work around to 
> all the problems introduced by programming by extension.

Nope, composition would violate the information hiding principle.

There is no workarounds to establishing a relationship between two types
serving as separate implementations of the *same* abstract concept (except
for generics or overloading (static and ad-hoc polymorphism). Both have
serious problems especially in the context of large systems design.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-08 21:41               ` Jeffrey Carter
  2011-07-09  6:14                 ` Dmitry A. Kazakov
@ 2011-07-22 22:59                 ` Randy Brukardt
  2011-07-23  7:30                   ` Jeffrey Carter
  1 sibling, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-22 22:59 UTC (permalink / raw)


"Jeffrey Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:iv80lh$n8m$1@tornado.tornevall.net...
> On 07/08/2011 12:23 PM, Randy Brukardt wrote:
>>
>> This particular problem has no workaround...
>
> I disagree. The use of programming by composition is an effective work 
> around to all the problems introduced by programming by extension.

Given that the problem in question is related to dynamic dispatching and has 
nothing in particular to do with extensions, this is an amazing statement.

In Claw, the primary reason for using OOP is for the dispatching -- it 
ensures that every object has handlers for each of the relevant messages, 
and also provides useful defaults. And it automatically ensures that the 
right handler is executed for each object -- no manual binding is required. 
There is some value to extensions in Claw, but not a lot.

OTOH, programming by composition would provide nothing, in that there would 
be no way to change the handlers for the base type. One could graft some 
sort of unstructured mechanism on top of the objects (possibly using 
access-to-subprograms), but this would provide many more opportunities for 
mistakes (if you forget to set the access-to-subprogram value, the routine 
might as well not exist).

Remember that there are four legs to the OOP stool: strong typing, 
encapsulation, extension, and dynamic dispatching -- and each of these is 
orthogonal to the others (shown by the fact that Ada has the first two 
without even using tagged types, that is OOP). So there is no necessary 
relationship between extension and dispatching (and working around the one 
does nothing to solve a problem that mainly depends on the other).

                              Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-22 22:59                 ` Randy Brukardt
@ 2011-07-23  7:30                   ` Jeffrey Carter
  2011-07-23  9:29                     ` Maciej Sobczak
                                       ` (2 more replies)
  0 siblings, 3 replies; 63+ messages in thread
From: Jeffrey Carter @ 2011-07-23  7:30 UTC (permalink / raw)


On 07/22/2011 03:59 PM, Randy Brukardt wrote:
>
> Given that the problem in question is related to dynamic dispatching and has
> nothing in particular to do with extensions, this is an amazing statement.

My statement was tongue in cheek, intended to express my dislike for tagged 
types. Their only value seems to be all the traffic here from people who run 
into problems trying to use them; this would be a much quieter place without them.

Maybe I'm missing something, but it seems to me that all dispatching in Ada is 
related to extensions. If you have

type T is tagged ...

procedure P (V : in out T);

and you never extend T, then you never get dispatching (in the sense that a call 
to P results in something other than this P being called). To get dispatching, 
you have to extend T

type T2 is new T with ...

overriding procedure P (V : in out T2);

Then you can get a single call that sometimes calls P for T and other times P 
for T2; that's dispatching. I don't know what dispatching means without an 
extension and an overridden subprogram to dispatch to.

> OTOH, programming by composition would provide nothing, in that there would
> be no way to change the handlers for the base type. One could graft some
> sort of unstructured mechanism on top of the objects (possibly using
> access-to-subprograms), but this would provide many more opportunities for
> mistakes (if you forget to set the access-to-subprogram value, the routine
> might as well not exist).

The equivalent of dispatching in programming by composition is a subprogram that 
contains a case statement that contains calls to other subprograms. No 
access-to-subprogram values involved. It does the exact same thing as 
dispatching, except that it's easier to read and understand and doesn't result 
in large numbers of "what am I doing wrong?" posts to c.l.a.

> Remember that there are four legs to the OOP stool: strong typing,
> encapsulation, extension, and dynamic dispatching -- and each of these is
> orthogonal to the others (shown by the fact that Ada has the first two
> without even using tagged types, that is OOP). So there is no necessary
> relationship between extension and dispatching (and working around the one
> does nothing to solve a problem that mainly depends on the other).

Again, I have no idea what dispatching even means in the absence of extension.

In Ada, "programming by extension" is achieved by the use of tagged types; it 
includes dispatching. I have never seen anything implemented using tagged types 
that could not also be implemented using programming by composition. It follows 
that if there is a case where tagged types cause a problem, the equivalent 
solution without tagged types is an effective work around to the problem.

Of course, in the case where there is no solution using tagged types, there may 
also be no solution without using them.

-- 
Jeff Carter
"If you think you got a nasty taunting this time,
you ain't heard nothing yet!"
Monty Python and the Holy Grail
23



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-23  7:30                   ` Jeffrey Carter
@ 2011-07-23  9:29                     ` Maciej Sobczak
  2011-07-23 10:07                     ` Dmitry A. Kazakov
  2011-07-26 21:04                     ` Randy Brukardt
  2 siblings, 0 replies; 63+ messages in thread
From: Maciej Sobczak @ 2011-07-23  9:29 UTC (permalink / raw)


On Jul 23, 9:30 am, Jeffrey Carter
<spam.jrcarter....@spam.not.acm.org> wrote:

> The equivalent of dispatching in programming by composition is a subprogram that
> contains a case statement that contains calls to other subprograms.

The whole point of dispatching is to allow the open-closed principle:

http://en.wikipedia.org/wiki/Open/closed_principle

It has no direct equivalent in programming by composition.

> No
> access-to-subprogram values involved.

Access-to-subprogram is needed to emulate dispatching and provide the
open-closed principle at the same time.

> It does the exact same thing as
> dispatching, except that it's easier to read and understand and doesn't result
> in large numbers of "what am I doing wrong?"

Without dispatching (and without access-to-subprogram to emulate it)
you would have large number of "why should I modify half of my drawing
application code just because I have added a rectanlge-with-rounde-
corners".

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-23  7:30                   ` Jeffrey Carter
  2011-07-23  9:29                     ` Maciej Sobczak
@ 2011-07-23 10:07                     ` Dmitry A. Kazakov
  2011-07-26 21:04                     ` Randy Brukardt
  2 siblings, 0 replies; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-07-23 10:07 UTC (permalink / raw)


On Sat, 23 Jul 2011 00:30:12 -0700, Jeffrey Carter wrote:

> Maybe I'm missing something, but it seems to me that all dispatching in Ada is 
> related to extensions.

Yes, but that is a language design bug (sorry, feature (:-)). There is
nothing in the idea of a class of types which would instruct a derived type
to add new components, and not to discard existing components, or to
provide an absolutely unrelated implementation.

Extension is an invention of lazy language designers.

> type T2 is new T with ...
> 
> overriding procedure P (V : in out T2);
> 
> Then you can get a single call that sometimes calls P for T and other times P 
> for T2; that's dispatching.

No, it always means the *same* primitive operation P defined on the type
T'Class. P for T is defined on T, P for T2 is defined on T2. Neither is
defined on T'Class.

In Ada you always know which operation is to be called.

> I don't know what dispatching means without an 
> extension and an overridden subprogram to dispatch to.

If you mean the implementation of a primitive operation P, then how is it
different from other operations? Ada separates interface and
implementation. You newer know the implementation without looking into the
body(es).

> The equivalent of dispatching in programming by composition is a subprogram that 
> contains a case statement that contains calls to other subprograms. No 
> access-to-subprogram values involved. It does the exact same thing as 
> dispatching, except that it's easier to read and understand and doesn't result 
> in large numbers of "what am I doing wrong?" posts to c.l.a.

There is a sufficient difference. The case statement needs an enumeration
type (a substitute for the tag type) which should be declared in advance to
all future implementations. This means that you have to know all derived
types at a very early stage of the project. Certainly you don't want
"others =>" in that statement. Furthermore the procedure must "with" all
implementations of all derived types. Now you have:

1. Problems with maintenance (fixing the statement and with clauses)

2. You have to ensure the correspondence between the values of the
enumeration type and the procedures called in "when This => That (X);". The
language cannot help you here.

3. Potential problems with elaboration order (inversed, mutual
dependencies).

4. Lack of static check if each "derived" type has a defined body.

5. Lack of abstract types. An abstract type has no instances, but may have
implementations. I.e. it appear in the switch. But you cannot compose
abstract components. Once abstract always abstract.

And finally, it does not change anything semantically. Whatever problem
(substitutability issues / LSP) the programmer might have with tagged
types, he will under composition.

> In Ada, "programming by extension" is achieved by the use of tagged types; it 
> includes dispatching. I have never seen anything implemented using tagged types 
> that could not also be implemented using programming by composition. It follows 
> that if there is a case where tagged types cause a problem, the equivalent 
> solution without tagged types is an effective work around to the problem.
> 
> Of course, in the case where there is no solution using tagged types, there may 
> also be no solution without using them.

An argument to Turing-completeness? (:-))

Compare: I never saw anything written in Ada, that could not be implemented
in Assembler...

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-23  7:30                   ` Jeffrey Carter
  2011-07-23  9:29                     ` Maciej Sobczak
  2011-07-23 10:07                     ` Dmitry A. Kazakov
@ 2011-07-26 21:04                     ` Randy Brukardt
  2011-07-26 23:43                       ` Jeffrey Carter
  2 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-26 21:04 UTC (permalink / raw)


"Jeffrey Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:j0e0l1$5qh$1@tornado.tornevall.net...
> On 07/22/2011 03:59 PM, Randy Brukardt wrote:
>>
>> Given that the problem in question is related to dynamic dispatching and 
>> has
>> nothing in particular to do with extensions, this is an amazing 
>> statement.
>
> My statement was tongue in cheek, intended to express my dislike for 
> tagged types. Their only value seems to be all the traffic here from 
> people who run into problems trying to use them; this would be a much 
> quieter place without them.
>
> Maybe I'm missing something, but it seems to me that all dispatching in 
> Ada is related to extensions. If you have
>
> type T is tagged ...
>
> procedure P (V : in out T);
>
> and you never extend T, then you never get dispatching (in the sense that 
> a call to P results in something other than this P being called). To get 
> dispatching, you have to extend T
>
> type T2 is new T with ...
>
> overriding procedure P (V : in out T2);
>
> Then you can get a single call that sometimes calls P for T and other 
> times P for T2; that's dispatching. I don't know what dispatching means 
> without an extension and an overridden subprogram to dispatch to.

You're right in language terms, but as Dmitry points out, this occurs only 
because we're discussing tagged types (which include 3 of the 4 OOP legs in 
a single package). I was thinking more generally (and yes, I just complained 
about Dmitry doing that); what I was thinking of by "extension" was actually 
adding components to a type, not just deriving a a type with the same set of 
components.

As I was describing, most of the use of dispatching in Claw does not use any 
extension (that is, adding new components), it just changes the behavior of 
the dispatching routines appropriately. So there is only a change in 
behavior, not a change in representation.

Others have pointed out that using case statements as you suggested is 
essentially worthless unless you know every entity that the program is going 
to process before the fact. And real world programs are not like that (I 
have plenty of experience changing hundreds of case statements each time we 
make a change in node types or intermediate code definitions in Janus/Ada).

                                      Randy.



>> OTOH, programming by composition would provide nothing, in that there 
>> would
>> be no way to change the handlers for the base type. One could graft some
>> sort of unstructured mechanism on top of the objects (possibly using
>> access-to-subprograms), but this would provide many more opportunities 
>> for
>> mistakes (if you forget to set the access-to-subprogram value, the 
>> routine
>> might as well not exist).
>
> The equivalent of dispatching in programming by composition is a 
> subprogram that contains a case statement that contains calls to other 
> subprograms. No access-to-subprogram values involved. It does the exact 
> same thing as dispatching, except that it's easier to read and understand 
> and doesn't result in large numbers of "what am I doing wrong?" posts to 
> c.l.a.
>
>> Remember that there are four legs to the OOP stool: strong typing,
>> encapsulation, extension, and dynamic dispatching -- and each of these is
>> orthogonal to the others (shown by the fact that Ada has the first two
>> without even using tagged types, that is OOP). So there is no necessary
>> relationship between extension and dispatching (and working around the 
>> one
>> does nothing to solve a problem that mainly depends on the other).
>
> Again, I have no idea what dispatching even means in the absence of 
> extension.
>
> In Ada, "programming by extension" is achieved by the use of tagged types; 
> it includes dispatching. I have never seen anything implemented using 
> tagged types that could not also be implemented using programming by 
> composition. It follows that if there is a case where tagged types cause a 
> problem, the equivalent solution without tagged types is an effective work 
> around to the problem.
>
> Of course, in the case where there is no solution using tagged types, 
> there may also be no solution without using them.
>
> -- 
> Jeff Carter
> "If you think you got a nasty taunting this time,
> you ain't heard nothing yet!"
> Monty Python and the Holy Grail
> 23 





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-26 21:04                     ` Randy Brukardt
@ 2011-07-26 23:43                       ` Jeffrey Carter
  2011-07-27 23:56                         ` Randy Brukardt
  2011-07-28 10:06                         ` Maciej Sobczak
  0 siblings, 2 replies; 63+ messages in thread
From: Jeffrey Carter @ 2011-07-26 23:43 UTC (permalink / raw)


On 07/26/2011 02:04 PM, Randy Brukardt wrote:
>
> You're right in language terms, but as Dmitry points out, this occurs only
> because we're discussing tagged types (which include 3 of the 4 OOP legs in a
> single package). I was thinking more generally (and yes, I just complained
> about Dmitry doing that); what I was thinking of by "extension" was actually
> adding components to a type, not just deriving a a type with the same set of
> components.
>
> As I was describing, most of the use of dispatching in Claw does not use any
> extension (that is, adding new components), it just changes the behavior of
> the dispatching routines appropriately. So there is only a change in
> behavior, not a change in representation.

ARM 3.9.1 defines a type extension as

record_extension_part ::= with record_definition

and record_definition includes "null record", so these are all extensions and
examples of programming by extension. I wouldn't have thought that I'd have to
define what I meant when using an Ada term with you.

> Others have pointed out that using case statements as you suggested is
> essentially worthless unless you know every entity that the program is going
> to process before the fact. And real world programs are not like that (I have
> plenty of experience changing hundreds of case statements each time we make a
> change in node types or intermediate code definitions in Janus/Ada).

Yes, it's called "design", and it's part of what distinguishes S/W engineers
from coders. As you note, it's an iterative process. The extra work and extra
code is worth it for the significant improvement in ease of reading and
understanding that results.

-- 
Jeff Carter
"I was in love with a beautiful blonde once, dear.
She drove me to drink. That's the one thing I'm
indebted to her for."
Never Give a Sucker an Even Break
109



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-26 23:43                       ` Jeffrey Carter
@ 2011-07-27 23:56                         ` Randy Brukardt
  2011-07-28  0:18                           ` Jeffrey Carter
  2011-07-28 10:06                         ` Maciej Sobczak
  1 sibling, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-27 23:56 UTC (permalink / raw)


"Jeffrey Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:j0nmqd$voi$1@tornado.tornevall.net...
> On 07/26/2011 02:04 PM, Randy Brukardt wrote:
...
> and record_definition includes "null record", so these are all extensions 
> and
> examples of programming by extension. I wouldn't have thought that I'd 
> have to
> define what I meant when using an Ada term with you.

I wasn't thinking of it as an Ada term. My mistake.

>> Others have pointed out that using case statements as you suggested is
>> essentially worthless unless you know every entity that the program is 
>> going
>> to process before the fact. And real world programs are not like that (I 
>> have
>> plenty of experience changing hundreds of case statements each time we 
>> make a
>> change in node types or intermediate code definitions in Janus/Ada).
>
> Yes, it's called "design", and it's part of what distinguishes S/W 
> engineers
> from coders. As you note, it's an iterative process. The extra work and 
> extra
> code is worth it for the significant improvement in ease of reading and
> understanding that results.

I don't agree; the 30 page case statements found in our optimizer and some 
other parts of our compiler don't add anything to ease of reading! And there 
is no choice with case statements, you have to have a bunch of lines for 
each option; when there are literally hundreds of options there is no way to 
simplify.

And updating those cases typically takes about a week's work; it is so time 
consuming that we avoid making changes to the intermediate code if any 
workaround can be found even when that is the best solution to a problem.

Ada 2012 will help a tiny bit by providing useful set subtypes (even if they 
aren't called that), so at least it will be possible to give a name to 
groups of discontiguous enumerations and that will reduce the work in some 
cases.

I admit that dispatching takes a leap of faith ("it just works" when used 
properly), and not everyone seems to be able to understand it. But having a 
lot less code in the critical parts of the application should help 
understanding.

Note that OOP (at least in Ada) does not really provide an answer for the 
"it takes a week to modify" problem. The Claw Builder (a full OOP design) 
has a similar problem in the other dimension, in that defining all of the 
needed overrides also takes a week or so. And in neither case (OOP or 
non-OOP) is is usefully possible to do just part of the work (as an agile 
programmer such as myself would prefer) -- neither program will even compile 
until all of the overridings or case statements are defined. Either way, Ada 
makes it too hard to add new abstractions to an existing set.

                                                     Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-27 23:56                         ` Randy Brukardt
@ 2011-07-28  0:18                           ` Jeffrey Carter
  0 siblings, 0 replies; 63+ messages in thread
From: Jeffrey Carter @ 2011-07-28  0:18 UTC (permalink / raw)


On 07/27/2011 04:56 PM, Randy Brukardt wrote:
>
> I don't agree; the 30 page case statements found in our optimizer and some
> other parts of our compiler don't add anything to ease of reading! And there
> is no choice with case statements, you have to have a bunch of lines for
> each option; when there are literally hundreds of options there is no way to
> simplify.
>
> And updating those cases typically takes about a week's work; it is so time
> consuming that we avoid making changes to the intermediate code if any
> workaround can be found even when that is the best solution to a problem.

There are as many options and as many lines of code per option no matter which 
implementation technique you use. At least with composition they're all together 
in one place; programming by extension puts them in as many places as there are 
options, with no links in the code to tell you where they are; the odds of 
leaving some options unmodified is much greater.

As you mentioned later, it doesn't save you any effort, either.

> I admit that dispatching takes a leap of faith ("it just works" when used
> properly), and not everyone seems to be able to understand it. But having a
> lot less code in the critical parts of the application should help
> understanding.

Everyone I know who has worked with code that uses programming by extension 
misunderstands it at least some of the time. (Perhaps you are an exception.) 
Composition does not seem to have this problem.

-- 
Jeff Carter
"Propose to an Englishman any principle, or any instrument, however
admirable, and you will observe that the whole effort of the English
mind is directed to find a difficulty, a defect, or an impossibility
in it. If you speak to him of a machine for peeling a potato, he will
pronounce it impossible: if you peel a potato with it before his eyes,
he will declare it useless, because it will not slice a pineapple."
Charles Babbage
92



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-26 23:43                       ` Jeffrey Carter
  2011-07-27 23:56                         ` Randy Brukardt
@ 2011-07-28 10:06                         ` Maciej Sobczak
  2011-07-28 23:24                           ` Randy Brukardt
  1 sibling, 1 reply; 63+ messages in thread
From: Maciej Sobczak @ 2011-07-28 10:06 UTC (permalink / raw)


On Jul 27, 1:43 am, Jeffrey Carter
<spam.jrcarter....@spam.not.acm.org> wrote:

> > Others have pointed out that using case statements as you suggested is
> > essentially worthless unless you know every entity that the program is going
> > to process before the fact. And real world programs are not like that

> Yes, it's called "design", and it's part of what distinguishes S/W engineers
> from coders.

This statement is unfair and uses a very superficial argumentation.
No matter how much extensive is the "design" and how good are the S/W
engineers doing it, a complete view on the system is not always
feasible.
Software is built from components that are prepared in separation,
possibly by different vendors. They have no way to know the complete
set of types that will be used in the final system, as the final
system might not be even invented yet when the components are
produced.
Using the open/closed principle with the help of dispatching
operations is the cleanest and the least intrusive way to integrate
such components and generics are not always applicable - a canonical
example is the web server component that delivers the client request
to the layer that can handle it. I've yet to see an approach that is
cleaner and less error-prone than the dispatching call via an
interface type.

> As you note, it's an iterative process. The extra work and extra
> code is worth it

It is iterative on which side? The extra work by whom?

> for the significant improvement in ease of reading and
> understanding that results.

Did you try that with web servers?

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-28 10:06                         ` Maciej Sobczak
@ 2011-07-28 23:24                           ` Randy Brukardt
  2011-07-29  6:45                             ` Simon Wright
  2011-08-09 21:10                             ` Maciej Sobczak
  0 siblings, 2 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-07-28 23:24 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:b0633538-6038-4167-860f-65ee9e7cddcc@k9g2000yqf.googlegroups.com...
On Jul 27, 1:43 am, Jeffrey Carter
<spam.jrcarter....@spam.not.acm.org> wrote:
...
>> for the significant improvement in ease of reading and
>> understanding that results.
>
>Did you try that with web servers?

Fasinating. While I agree with most of your points, it is interesting that 
the web server that runs the AdaIC archive site, the ada-auth.org site, the 
search engine for the RM, and RR Software's web site (which is an all-Ada 
design based on Claw's socket library) uses very little OOP. The only OOP in 
it is in the low-level socket operations, mainly because Claw sockets are an 
OOP design. But all of the high-level stuff is implemented as a table-driven 
approach (special handling, domain roots, and the like are all described in 
data form), and the specialty handlers (like the search engine) are all 
called from case statements driven from those data tables.

The design was driven by an extra-paranoid approach to security: if the 
server had any way for a URL to execute foreign code (a plug-in), then it is 
highly likely that an attacker would find a way to use buggy URL to execute 
some foreign code of their choice. Thus the ability to execute foreign code 
is not provided at all -- all handlers have to compiled into the web server. 
(Combined with Ada's near prevention of buffer overflows and stack attacks, 
the two most common vectors of the time were firmly plugged. Of course, 
traversal prevention and sanitization of parameters still have to be 
accomplished -- there is no silver bullet to security.) Once you've done 
that, there isn't much benefit to an OOP approach, since you have to 
enumerate all of the handlers somewhere in any case.

                                        Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-28 23:24                           ` Randy Brukardt
@ 2011-07-29  6:45                             ` Simon Wright
  2011-07-30  0:04                               ` Randy Brukardt
  2011-08-09 21:10                             ` Maciej Sobczak
  1 sibling, 1 reply; 63+ messages in thread
From: Simon Wright @ 2011-07-29  6:45 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> The design was driven by an extra-paranoid approach to security: if
> the server had any way for a URL to execute foreign code (a plug-in),
> then it is highly likely that an attacker would find a way to use
> buggy URL to execute some foreign code of their choice. Thus the
> ability to execute foreign code is not provided at all -- all handlers
> have to compiled into the web server.  (Combined with Ada's near
> prevention of buffer overflows and stack attacks, the two most common
> vectors of the time were firmly plugged. Of course, traversal
> prevention and sanitization of parameters still have to be
> accomplished -- there is no silver bullet to security.) Once you've
> done that, there isn't much benefit to an OOP approach, since you have
> to enumerate all of the handlers somewhere in any case.

Interesting. I'd have thought that "implementing the server using OOP"
and "not providing plugin facilities" were quite separate things. The
OOP approach could, I suppose, be thought of as a way to provide you
(Randy) with plugin facilities, but not attackers!



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-29  6:45                             ` Simon Wright
@ 2011-07-30  0:04                               ` Randy Brukardt
  2011-07-30  6:32                                 ` Simon Wright
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-07-30  0:04 UTC (permalink / raw)


"Simon Wright" <simon@pushface.org> wrote in message 
news:m2sjpp4mar.fsf@pushface.org...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>> The design was driven by an extra-paranoid approach to security: if
>> the server had any way for a URL to execute foreign code (a plug-in),
>> then it is highly likely that an attacker would find a way to use
>> buggy URL to execute some foreign code of their choice. Thus the
>> ability to execute foreign code is not provided at all -- all handlers
>> have to compiled into the web server.  (Combined with Ada's near
>> prevention of buffer overflows and stack attacks, the two most common
>> vectors of the time were firmly plugged. Of course, traversal
>> prevention and sanitization of parameters still have to be
>> accomplished -- there is no silver bullet to security.) Once you've
>> done that, there isn't much benefit to an OOP approach, since you have
>> to enumerate all of the handlers somewhere in any case.
>
> Interesting. I'd have thought that "implementing the server using OOP"
> and "not providing plugin facilities" were quite separate things. The
> OOP approach could, I suppose, be thought of as a way to provide you
> (Randy) with plugin facilities, but not attackers!

The root of the problem is that Ada 95 had no way to create a factory short 
of writing a giant case statement. That's annoying but OK if you have a 
complex interface with many operations to implement. However, the web server 
only has a single interface ("here's a URL and a socket, write the result to 
the socket"). So there is no advantage to having a separate case statement 
in the factory - that would just add complexity. (The output to the socket 
has many helper routines in order to make it easier to write the correct 
formats, but in any case the output is nearly free-form text and there is no 
obvious advantage to any extensions there.)

Even in Ada 2005 (which has somewhat better support for factories), you 
still have to "with" all of the units involved. It isn't much harder to 
write calls into a case statement (especially given the simplity of the 
interface).

The dynamic is different if the interface is more complex. For instance, the 
output modules of the ARM formatter program are based on an OOP-design 
(these output in various formats: RTF, HTML, plain text, etc.). For that, 
there is a case statement in the main program to select which output format 
is desired. But the interface has a significant number of routines to deal 
with output formatting, particularly of graphics and tables. Having to 
maintain 50 case statements would not be anywhere near as clean as the OOP 
design.

                                         Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-30  0:04                               ` Randy Brukardt
@ 2011-07-30  6:32                                 ` Simon Wright
  2011-08-01  9:30                                   ` Alex R. Mosteo
  0 siblings, 1 reply; 63+ messages in thread
From: Simon Wright @ 2011-07-30  6:32 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Simon Wright" <simon@pushface.org> wrote in message 
> news:m2sjpp4mar.fsf@pushface.org...
>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>
>>> The design was driven by an extra-paranoid approach to security: if
>>> the server had any way for a URL to execute foreign code (a
>>> plug-in), then it is highly likely that an attacker would find a way
>>> to use buggy URL to execute some foreign code of their choice. Thus
>>> the ability to execute foreign code is not provided at all -- all
>>> handlers have to compiled into the web server.  (Combined with Ada's
>>> near prevention of buffer overflows and stack attacks, the two most
>>> common vectors of the time were firmly plugged. Of course, traversal
>>> prevention and sanitization of parameters still have to be
>>> accomplished -- there is no silver bullet to security.) Once you've
>>> done that, there isn't much benefit to an OOP approach, since you
>>> have to enumerate all of the handlers somewhere in any case.
>>
>> Interesting. I'd have thought that "implementing the server using
>> OOP" and "not providing plugin facilities" were quite separate
>> things. The OOP approach could, I suppose, be thought of as a way to
>> provide you (Randy) with plugin facilities, but not attackers!
>
> The root of the problem is that Ada 95 had no way to create a factory
> short of writing a giant case statement. That's annoying but OK if you
> have a complex interface with many operations to implement. However,
> the web server only has a single interface ("here's a URL and a
> socket, write the result to the socket"). So there is no advantage to
> having a separate case statement in the factory - that would just add
> complexity. (The output to the socket has many helper routines in
> order to make it easier to write the correct formats, but in any case
> the output is nearly free-form text and there is no obvious advantage
> to any extensions there.)
>
> Even in Ada 2005 (which has somewhat better support for factories),
> you still have to "with" all of the units involved. It isn't much
> harder to write calls into a case statement (especially given the
> simplity of the interface).

In my EWS (https://sourceforge.net/projects/embed-web-srvr/) there are
two 'classes' of response, Static and Dynamic. For static responses, the
page to be returned is fixed, and is baked in at build time. For dynamic
responses, I have a function

   type Creator
      is access function (From_Request : HTTP.Request_P)
                         return Dynamic_Response'Class;

and a means of registering Creators

   procedure Register (The_Creator : Creator; For_The_URL : HTTP.URL);

('URL' isn't quite right, it's the 'abs_path [ "?" query ]' part of an
HTTP URL, eg /embed-web-srvr/ in the URL above).

For_The_URL is really a String, and the result of registration is
effectively a run-time factory. But no case statements!




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-30  6:32                                 ` Simon Wright
@ 2011-08-01  9:30                                   ` Alex R. Mosteo
  2011-08-01 10:12                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Alex R. Mosteo @ 2011-08-01  9:30 UTC (permalink / raw)


Simon Wright wrote:

> "Randy Brukardt" <randy@rrsoftware.com> writes:
> 
>> "Simon Wright" <simon@pushface.org> wrote in message
>> news:m2sjpp4mar.fsf@pushface.org...
>>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>>
>>>> The design was driven by an extra-paranoid approach to security: if
>>>> the server had any way for a URL to execute foreign code (a
>>>> plug-in), then it is highly likely that an attacker would find a way
>>>> to use buggy URL to execute some foreign code of their choice. Thus
>>>> the ability to execute foreign code is not provided at all -- all
>>>> handlers have to compiled into the web server.  (Combined with Ada's
>>>> near prevention of buffer overflows and stack attacks, the two most
>>>> common vectors of the time were firmly plugged. Of course, traversal
>>>> prevention and sanitization of parameters still have to be
>>>> accomplished -- there is no silver bullet to security.) Once you've
>>>> done that, there isn't much benefit to an OOP approach, since you
>>>> have to enumerate all of the handlers somewhere in any case.
>>>
>>> Interesting. I'd have thought that "implementing the server using
>>> OOP" and "not providing plugin facilities" were quite separate
>>> things. The OOP approach could, I suppose, be thought of as a way to
>>> provide you (Randy) with plugin facilities, but not attackers!
>>
>> The root of the problem is that Ada 95 had no way to create a factory
>> short of writing a giant case statement. That's annoying but OK if you
>> have a complex interface with many operations to implement. However,
>> the web server only has a single interface ("here's a URL and a
>> socket, write the result to the socket"). So there is no advantage to
>> having a separate case statement in the factory - that would just add
>> complexity. (The output to the socket has many helper routines in
>> order to make it easier to write the correct formats, but in any case
>> the output is nearly free-form text and there is no obvious advantage
>> to any extensions there.)
>>
>> Even in Ada 2005 (which has somewhat better support for factories),
>> you still have to "with" all of the units involved. It isn't much
>> harder to write calls into a case statement (especially given the
>> simplity of the interface).
> 
> In my EWS (https://sourceforge.net/projects/embed-web-srvr/) there are
> two 'classes' of response, Static and Dynamic. For static responses, the
> page to be returned is fixed, and is baked in at build time. For dynamic
> responses, I have a function
> 
>    type Creator
>       is access function (From_Request : HTTP.Request_P)
>                          return Dynamic_Response'Class;
> 
> and a means of registering Creators
> 
>    procedure Register (The_Creator : Creator; For_The_URL : HTTP.URL);
> 
> ('URL' isn't quite right, it's the 'abs_path [ "?" query ]' part of an
> HTTP URL, eg /embed-web-srvr/ in the URL above).
> 
> For_The_URL is really a String, and the result of registration is
> effectively a run-time factory. But no case statements!

I have done basically the same for my component-based robotic library, but 
still you have to /with/ all the units you want and call the register 
procedure... Still, I find this sufficiently neat (you don't have to edit 
any central piece of code (besides the main procedure, but that's OK to me 
--you're expressing your necessities there).




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-01  9:30                                   ` Alex R. Mosteo
@ 2011-08-01 10:12                                     ` Dmitry A. Kazakov
  2011-08-01 21:56                                       ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-01 10:12 UTC (permalink / raw)


On Mon, 01 Aug 2011 11:30:33 +0200, Alex R. Mosteo wrote:

> Simon Wright wrote:
> 
>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>> 
>>> "Simon Wright" <simon@pushface.org> wrote in message
>>> news:m2sjpp4mar.fsf@pushface.org...
>>>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>>>
>>>>> The design was driven by an extra-paranoid approach to security: if
>>>>> the server had any way for a URL to execute foreign code (a
>>>>> plug-in), then it is highly likely that an attacker would find a way
>>>>> to use buggy URL to execute some foreign code of their choice. Thus
>>>>> the ability to execute foreign code is not provided at all -- all
>>>>> handlers have to compiled into the web server.  (Combined with Ada's
>>>>> near prevention of buffer overflows and stack attacks, the two most
>>>>> common vectors of the time were firmly plugged. Of course, traversal
>>>>> prevention and sanitization of parameters still have to be
>>>>> accomplished -- there is no silver bullet to security.) Once you've
>>>>> done that, there isn't much benefit to an OOP approach, since you
>>>>> have to enumerate all of the handlers somewhere in any case.
>>>>
>>>> Interesting. I'd have thought that "implementing the server using
>>>> OOP" and "not providing plugin facilities" were quite separate
>>>> things. The OOP approach could, I suppose, be thought of as a way to
>>>> provide you (Randy) with plugin facilities, but not attackers!
>>>
>>> The root of the problem is that Ada 95 had no way to create a factory
>>> short of writing a giant case statement. That's annoying but OK if you
>>> have a complex interface with many operations to implement. However,
>>> the web server only has a single interface ("here's a URL and a
>>> socket, write the result to the socket"). So there is no advantage to
>>> having a separate case statement in the factory - that would just add
>>> complexity. (The output to the socket has many helper routines in
>>> order to make it easier to write the correct formats, but in any case
>>> the output is nearly free-form text and there is no obvious advantage
>>> to any extensions there.)
>>>
>>> Even in Ada 2005 (which has somewhat better support for factories),
>>> you still have to "with" all of the units involved. It isn't much
>>> harder to write calls into a case statement (especially given the
>>> simplity of the interface).
>> 
>> In my EWS (https://sourceforge.net/projects/embed-web-srvr/) there are
>> two 'classes' of response, Static and Dynamic. For static responses, the
>> page to be returned is fixed, and is baked in at build time. For dynamic
>> responses, I have a function
>> 
>>    type Creator
>>       is access function (From_Request : HTTP.Request_P)
>>                          return Dynamic_Response'Class;
>> 
>> and a means of registering Creators
>> 
>>    procedure Register (The_Creator : Creator; For_The_URL : HTTP.URL);
>> 
>> ('URL' isn't quite right, it's the 'abs_path [ "?" query ]' part of an
>> HTTP URL, eg /embed-web-srvr/ in the URL above).
>> 
>> For_The_URL is really a String, and the result of registration is
>> effectively a run-time factory. But no case statements!
> 
> I have done basically the same for my component-based robotic library, but 
> still you have to /with/ all the units you want and call the register 
> procedure...

You have not. The procedure Register is called from the body of the package
that provides an implementation. It adds an entry into the global map id ->
object constructor. The object factory sees only this map, it need not to
with any implementations. This is the way I implement persistency layers.

BTW, Generic_Dispatching_Constructor of Ada 2005 did not change much to Ada
95 because of tags. You still need a registering layer to maintain external
name to tag mapping.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-01 10:12                                     ` Dmitry A. Kazakov
@ 2011-08-01 21:56                                       ` Randy Brukardt
  2011-08-02 10:03                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-01 21:56 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1rlxo1uthv5xt.1agapd9q0mek4$.dlg@40tude.net...
...
> BTW, Generic_Dispatching_Constructor of Ada 2005 did not change much to 
> Ada
> 95 because of tags. You still need a registering layer to maintain 
> external
> name to tag mapping.

It did eliminate one thing, the need to have a scheme to create an object of 
each tagged type. That forced the use of either a case statement or an 
access-to-subprogram, either of which is error-prone.

There is no possibility of eliminating the need for some sort of registry --  
although in some cases you can use the one built-into the language (the 
External_Tag). There has to be a mapping somewhere of some sort of key to a 
tag, since it isn't possible to export tags to the "real world".

                                Randy.







^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-01 21:56                                       ` Randy Brukardt
@ 2011-08-02 10:03                                         ` Dmitry A. Kazakov
  2011-08-02 21:16                                           ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-02 10:03 UTC (permalink / raw)


On Mon, 1 Aug 2011 16:56:17 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1rlxo1uthv5xt.1agapd9q0mek4$.dlg@40tude.net...
> ...
>> BTW, Generic_Dispatching_Constructor of Ada 2005 did not change much to 
>> Ada
>> 95 because of tags. You still need a registering layer to maintain 
>> external name to tag mapping.
> 
> It did eliminate one thing, the need to have a scheme to create an object of 
> each tagged type. That forced the use of either a case statement or an 
> access-to-subprogram, either of which is error-prone.

I don't consider the case statement because it is just a wrong pattern.
Regarding mappings type ID to either a constructing function or tag, they
are equivalent. Both require the same amount of maintenance.

> There is no possibility of eliminating the need for some sort of registry --  
> although in some cases you can use the one built-into the language (the 
> External_Tag). There has to be a mapping somewhere of some sort of key to a 
> tag, since it isn't possible to export tags to the "real world".

It is possible, and even required for distributed weakly coupled
applications, but in order to do that you have to export the types
themselves rather than their tags.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-02 10:03                                         ` Dmitry A. Kazakov
@ 2011-08-02 21:16                                           ` Randy Brukardt
  2011-08-03  9:01                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-02 21:16 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1nvqqny2226ro$.1ixvoiht8zu8l$.dlg@40tude.net...
> On Mon, 1 Aug 2011 16:56:17 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1rlxo1uthv5xt.1agapd9q0mek4$.dlg@40tude.net...
>> ...
>>> BTW, Generic_Dispatching_Constructor of Ada 2005 did not change much to
>>> Ada
>>> 95 because of tags. You still need a registering layer to maintain
>>> external name to tag mapping.
>>
>> It did eliminate one thing, the need to have a scheme to create an object 
>> of
>> each tagged type. That forced the use of either a case statement or an
>> access-to-subprogram, either of which is error-prone.
>
> I don't consider the case statement because it is just a wrong pattern.
> Regarding mappings type ID to either a constructing function or tag, they
> are equivalent. Both require the same amount of maintenance.

There are more sources of error when using access-to-subprogram; it's easy 
to forget to create a routine or use the wrong one. Neither of those are 
possible with generic dispatching constructor (or with a case statement, for 
that matter, presuming that you use Ada's completeness checks). This is a 
minor advantage, but it is real; it's the major reason that I don't even 
think about using access-to-subprogram (and have to be reminded of the 
possibility).

 >> There is no possibility of eliminating the need for some sort of 
registry --
>> although in some cases you can use the one built-into the language (the
>> External_Tag). There has to be a mapping somewhere of some sort of key to 
>> a
>> tag, since it isn't possible to export tags to the "real world".
>
> It is possible, and even required for distributed weakly coupled
> applications, but in order to do that you have to export the types
> themselves rather than their tags.

It might be possible for some non-Ada language, but it's not possible for 
Ada (and this is an Ada site and I was only talking about Ada here). There 
is no way in Ada to "export the types"; you have to export some type 
indication -- and that requires some sort of mapping of indication to type.

                             Randy.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-02 21:16                                           ` Randy Brukardt
@ 2011-08-03  9:01                                             ` Dmitry A. Kazakov
  2011-08-03 20:16                                               ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-03  9:01 UTC (permalink / raw)


On Tue, 2 Aug 2011 16:16:27 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1nvqqny2226ro$.1ixvoiht8zu8l$.dlg@40tude.net...
>> On Mon, 1 Aug 2011 16:56:17 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1rlxo1uthv5xt.1agapd9q0mek4$.dlg@40tude.net...
>>> ...
>>>> BTW, Generic_Dispatching_Constructor of Ada 2005 did not change much to
>>>> Ada
>>>> 95 because of tags. You still need a registering layer to maintain
>>>> external name to tag mapping.
>>>
>>> It did eliminate one thing, the need to have a scheme to create an object 
>>> of
>>> each tagged type. That forced the use of either a case statement or an
>>> access-to-subprogram, either of which is error-prone.
>>
>> I don't consider the case statement because it is just a wrong pattern.
>> Regarding mappings type ID to either a constructing function or tag, they
>> are equivalent. Both require the same amount of maintenance.
> 
> There are more sources of error when using access-to-subprogram; it's easy 
> to forget to create a routine or use the wrong one.

Yes there is some advantage that the function in dispatching constructor is
primitive:

   function Create (...) return T;

For access-to-subprogram it is class-wide:

   function Create (...) return T'Class;

As for using a wrong subprogram you can also register a wrong tag. That is
same.

BTW, the patterns are:

      -- with generic dispatching constructor
   type T is tagged ...;
   function Create (...) return T;
   procedure Register (ID : ID_Type; Construct : Tag);

   --- Usage:

   package P is
      type S is new T with ...;
      overriding function Create (...) return S;
   end P;

   package body P is
      ...
   begin
      Register (S_ID, S'Tag);
   end P;

vs.

      -- Ada 95 access-to-subprogram solution
   type T is tagged ...;
   type Factory is access function Create (...) return T'Class;
   procedure Register (ID : ID_Type; Constructor : Factory);

   -- Usage:

   package P is
      type S is new T with ...;
   end P;

   package body P is
      function Create (...) return T'Class is
         ...
      end Create;
      ...
   begin
      Register (S_ID, Create'Access);
   end P;
   
>>> There is no possibility of eliminating the need for some sort of registry --
>>> although in some cases you can use the one built-into the language (the
>>> External_Tag). There has to be a mapping somewhere of some sort of key to a
>>> tag, since it isn't possible to export tags to the "real world".
>>
>> It is possible, and even required for distributed weakly coupled
>> applications, but in order to do that you have to export the types
>> themselves rather than their tags.
> 
> It might be possible for some non-Ada language, but it's not possible for 
> Ada (and this is an Ada site and I was only talking about Ada here).

Well, if Ada designers are serious about addressing distributed systems
(Annex E), that has to happen. Either a kind of IDL must be put into the
Ada standard (highly undesired) or some other, more reasonable, means must
be provided to populate types. [Of course the type system must be brought
in order before even considering this sort of issues.]

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-03  9:01                                             ` Dmitry A. Kazakov
@ 2011-08-03 20:16                                               ` Randy Brukardt
  2011-08-04  8:15                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-03 20:16 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:nwyetwf3hqn7$.gm3c388p0s3c$.dlg@40tude.net...
> On Tue, 2 Aug 2011 16:16:27 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1nvqqny2226ro$.1ixvoiht8zu8l$.dlg@40tude.net...
>>> On Mon, 1 Aug 2011 16:56:17 -0500, Randy Brukardt wrote:
...
>>>> It did eliminate one thing, the need to have a scheme to create an 
>>>> object of
>>>> each tagged type. That forced the use of either a case statement or an
>>>> access-to-subprogram, either of which is error-prone.
>>>
>>> I don't consider the case statement because it is just a wrong pattern.
>>> Regarding mappings type ID to either a constructing function or tag, 
>>> they
>>> are equivalent. Both require the same amount of maintenance.
>>
>> There are more sources of error when using access-to-subprogram; it's 
>> easy
>> to forget to create a routine or use the wrong one.
>
> Yes there is some advantage that the function in dispatching constructor 
> is
> primitive:
>
>   function Create (...) return T;

There's another advantage (for this use): the language requires you to 
override it, or you get an error. So it is impossible to forget to write the 
routine or have it return the wrong kind of object. Errors of omission are 
the hardest to find, and this property at least prevents those errors. (Of 
course, it doesn't prevent putting the wrong contents into that object.)

                              Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-03 20:16                                               ` Randy Brukardt
@ 2011-08-04  8:15                                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-04  8:15 UTC (permalink / raw)


On Wed, 3 Aug 2011 15:16:08 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:nwyetwf3hqn7$.gm3c388p0s3c$.dlg@40tude.net...

>> Yes there is some advantage that the function in dispatching constructor is
>> primitive:
>>
>>   function Create (...) return T;
> 
> There's another advantage (for this use): the language requires you to 
> override it, or you get an error.

Yes, this is the advantage I had in mind.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-07-28 23:24                           ` Randy Brukardt
  2011-07-29  6:45                             ` Simon Wright
@ 2011-08-09 21:10                             ` Maciej Sobczak
  2011-08-09 21:35                               ` Randy Brukardt
  1 sibling, 1 reply; 63+ messages in thread
From: Maciej Sobczak @ 2011-08-09 21:10 UTC (permalink / raw)


On Jul 29, 1:24 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> >Did you try that with web servers?
>
> Fasinating. While I agree with most of your points, it is interesting that
> the web server that runs the AdaIC archive site, [...]
> the specialty handlers (like the search engine) are all
> called from case statements driven from those data tables.

I assume that this particular web server was written from scratch and
on top of some lower-level primitives (sockets). That's OK, but very
likely an overkill. That's why I have mentioned the possibility to
integrate off-the-shelf components, in which case there is simply no
place to put your case statement.

> The design was driven by an extra-paranoid approach to security: if the
> server had any way for a URL to execute foreign code (a plug-in),

I don't see any conflict between OOP and security here. The complete
application can be statically bound, in which case the execution of
dynamically loaded code is excluded.

What I'm talking about is a kind of dependency inversion - instead of
the web server calling each particular module from some single giant
case statement (which has to with all packages, etc.), you might have
a set of modules that register themselves in a single registry, which
is later used to resolve the call. By doing this, the web server and
its registry do not have to with anything other than the common
interface specification. Of course, you might still need to do some
magic in order to force all those modules to elaborate/initialize (so
that they can register in the web server central module), which might
turn out to be a ladder of with clauses that we wanted to avoid in the
first place, but this has nothing to do with OOP - it is only a
peculiarity of Ada and I can imagine a language where this can be done
externally by a build script or even by a mere presence of source
files.

We can also think about the automated generation of the with
statements that are need to force the elaboration of all modules.
But then - the giant case statement can be also automatically
generated, which could in turn be taken as an argument against OOP.
Oh, dear... :-)

Still, I believe that the open/close principle and the dependency
inversion are two (only?) good use cases for dispatching and that when
this design approach is needed, the dispatching offers the cleanest
solution.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-09 21:10                             ` Maciej Sobczak
@ 2011-08-09 21:35                               ` Randy Brukardt
  2011-08-10  9:11                                 ` Dmitry A. Kazakov
  2011-08-10 10:07                                 ` Maciej Sobczak
  0 siblings, 2 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-08-09 21:35 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:4a4f185d-5268-4d73-a5df-8149bd117e0f@h9g2000vbr.googlegroups.com...
On Jul 29, 1:24 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

>> >Did you try that with web servers?
>>
>> Fasinating. While I agree with most of your points, it is interesting 
>> that
>> the web server that runs the AdaIC archive site, [...]
>> the specialty handlers (like the search engine) are all
>> called from case statements driven from those data tables.

>I assume that this particular web server was written from scratch and
>on top of some lower-level primitives (sockets).

The Claw sockets and HTTP packages, to be specific.

> That's OK, but very
> likely an overkill. That's why I have mentioned the possibility to
> integrate off-the-shelf components, in which case there is simply no
> place to put your case statement.

What off-the-shelf components? We're talking about Ada here, and the only 
components I know of are procedural libraries. After all, the only part of 
the core web server not covered by the Claw components was the URL parser 
(completely procedural, basic string to string transformations), and the 
code to stream in files (predefined Ada components).

The interesting parts are in the specialized handlers, and those were also 
built out of existing components (various proto-containers originated by Tom 
Moran, the crawler skelton that Tom created early on as a Claw sockets 
sample program, etc.) And none of those components use much OOP (or could).

>> The design was driven by an extra-paranoid approach to security: if the
>> server had any way for a URL to execute foreign code (a plug-in),
>
>I don't see any conflict between OOP and security here. The complete
>application can be statically bound, in which case the execution of
>dynamically loaded code is excluded.

It's less of a conflict than a need; once the application is statically 
bound, most of the value of OOP vanishes (particularly when the requirements 
aren't likely to change much, as in this case).

>What I'm talking about is a kind of dependency inversion - instead of
>the web server calling each particular module from some single giant
>case statement (which has to with all packages, etc.), you might have
>a set of modules that register themselves in a single registry, which
>is later used to resolve the call. By doing this, the web server and
>its registry do not have to with anything other than the common
>interface specification. Of course, you might still need to do some
>magic in order to force all those modules to elaborate/initialize (so
>that they can register in the web server central module), which might
>turn out to be a ladder of with clauses that we wanted to avoid in the
>first place, but this has nothing to do with OOP - it is only a
>peculiarity of Ada and I can imagine a language where this can be done
>externally by a build script or even by a mere presence of source
>files.

I mentioned all of that in one of my previous messages. The point is that in 
Ada, OOP doesn't help unless you have multiple interfaces associated with an 
object. That's not unusual, but it isn't always the case (and it isn't the 
case in the web server).

>We can also think about the automated generation of the with
>statements that are need to force the elaboration of all modules.
>But then - the giant case statement can be also automatically
>generated, which could in turn be taken as an argument against OOP.
>Oh, dear... :-)

Now you get it: the two organizations are equivalent in Ada if there is only 
a single interface. In which case, the simpler organization is probably 
better, especially if the lead designer was programming long before OOP was 
mainstream. :-)

>Still, I believe that the open/close principle and the dependency
>inversion are two (only?) good use cases for dispatching and that when
>this design approach is needed, the dispatching offers the cleanest
>solution.

I don't see any dependency inversion in the web server. (The web server 
calls packages to evaluate particular commands or operations -- that's how 
almost all programs work!) This sounds more like a case of trying to make 
everything look like a nail (to the OOP hammer).

I understand the value of the Open/Close principle, but it only is a win in 
Ada if there are multiple interfaces associated with an object. Otherwise, 
the amount of change is the same (or even less) for the non-OOP solution.

                                    Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-09 21:35                               ` Randy Brukardt
@ 2011-08-10  9:11                                 ` Dmitry A. Kazakov
  2011-08-10 21:56                                   ` Randy Brukardt
  2011-08-10 10:07                                 ` Maciej Sobczak
  1 sibling, 1 reply; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-10  9:11 UTC (permalink / raw)


On Tue, 9 Aug 2011 16:35:14 -0500, Randy Brukardt wrote:

> I understand the value of the Open/Close principle, but it only is a win in 
> Ada if there are multiple interfaces associated with an object. Otherwise, 
> the amount of change is the same (or even less) for the non-OOP solution.

It could be true only if there were only one place of dispatch. In reality
there are many dispatching calls and many class-wide operations (for which
there is no typed procedural equivalent). Procedural solution would
necessary have to bend design in order to reduce the number of such places,
each requiring maintenance.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-09 21:35                               ` Randy Brukardt
  2011-08-10  9:11                                 ` Dmitry A. Kazakov
@ 2011-08-10 10:07                                 ` Maciej Sobczak
  2011-08-10 11:26                                   ` Georg Bauhaus
  2011-08-10 22:21                                   ` Randy Brukardt
  1 sibling, 2 replies; 63+ messages in thread
From: Maciej Sobczak @ 2011-08-10 10:07 UTC (permalink / raw)


On Aug 9, 11:35 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> I don't see any dependency inversion in the web server. (The web server
> calls packages to evaluate particular commands or operations -- that's how
> almost all programs work!)

The dependency inversion is in the fact that the web server does not
have to know the modules it is calling. It is enough if the modules
know the web server (and its registry, to be exact) - thanks to this
new modules can be added without touching the web server itself
(that's the open/close principle at work now). What is needed for the
dependency inversion to work is a spec of something common - in the
case of OOP this is an interface.

> This sounds more like a case of trying to make
> everything look like a nail (to the OOP hammer).

No, this is trying to reduce the effort to maintain a heavy component
that is tested and verified only once.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10 10:07                                 ` Maciej Sobczak
@ 2011-08-10 11:26                                   ` Georg Bauhaus
  2011-08-10 22:27                                     ` Randy Brukardt
  2011-08-10 22:21                                   ` Randy Brukardt
  1 sibling, 1 reply; 63+ messages in thread
From: Georg Bauhaus @ 2011-08-10 11:26 UTC (permalink / raw)


On 10.08.11 12:07, Maciej Sobczak wrote:
> On Aug 9, 11:35 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> 
>> I don't see any dependency inversion in the web server. (The web server
>> calls packages to evaluate particular commands or operations -- that's how
>> almost all programs work!)
> 
> The dependency inversion is in the fact that the web server does not
> have to know the modules it is calling. It is enough if the modules
> know the web server (and its registry, to be exact) - thanks to this
> new modules can be added without touching the web server itself
> (that's the open/close principle at work now). What is needed for the
> dependency inversion to work is a spec of something common - in the
> case of OOP this is an interface.

One example of this style of OOP web server at work is Google's
mainframe operating system called App Engine.

Programming for this web server, you will typically define
request handler types and override one or more of the
get/post/delete/... operations of a parent type.
Next, you indicate which of your types should handle requests
for which URL. The server software loads your programs,
inspects them for request handler types, and runs the
overridden subprograms (get/post/delete/...) when corresponding
HTTP requests (GET/POST/DELETE/...) come in. (Requests will be
from the web, or from the mainframe when it has been instructed
run task queues, cron jobs, or pipelines.)

I don't think Google will, or even could, change a rather
large case statement whenever some new request handler is
added to the system. The system is running large number of
app engine programs, each having a number of request handler
types.  They use a registry.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10  9:11                                 ` Dmitry A. Kazakov
@ 2011-08-10 21:56                                   ` Randy Brukardt
  2011-08-11  8:07                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-10 21:56 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1bs0xoar40rx.6yb23bgkfrew.dlg@40tude.net...
> On Tue, 9 Aug 2011 16:35:14 -0500, Randy Brukardt wrote:
>
>> I understand the value of the Open/Close principle, but it only is a win 
>> in
>> Ada if there are multiple interfaces associated with an object. 
>> Otherwise,
>> the amount of change is the same (or even less) for the non-OOP solution.
>
> It could be true only if there were only one place of dispatch.

That's exactly the case I meant.

> In reality
> there are many dispatching calls and many class-wide operations (for which
> there is no typed procedural equivalent).

Reality? The reality is in the web server interface I was describing there 
was only one such point of dispatch, and only a single interface to dispatch 
to. It's clearly a special case, but one that is pretty common in the 
systems I've worked on.

All I was saying is that in that special case, there is no value to OOP in 
Ada.

> Procedural solution would
> necessary have to bend design in order to reduce the number of such 
> places,
> each requiring maintenance.

Not necessarily; a lot of problems have obvious bottlenecks where everything 
goes through a single point. Making complex dispatching designs in such 
cases only increases complexity and difficulty of maintenance.

                                     Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10 10:07                                 ` Maciej Sobczak
  2011-08-10 11:26                                   ` Georg Bauhaus
@ 2011-08-10 22:21                                   ` Randy Brukardt
  2011-08-11 13:50                                     ` Maciej Sobczak
  1 sibling, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-10 22:21 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:b6049447-8479-46ca-82e8-b6031a4b4d1a@q15g2000yqk.googlegroups.com...
On Aug 9, 11:35 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

>> I don't see any dependency inversion in the web server. (The web server
>> calls packages to evaluate particular commands or operations -- that's 
>> how
>> almost all programs work!)
>
>The dependency inversion is in the fact that the web server does not
>have to know the modules it is calling. It is enough if the modules
>know the web server (and its registry, to be exact) - thanks to this
>new modules can be added without touching the web server itself
>(that's the open/close principle at work now). What is needed for the
>dependency inversion to work is a spec of something common - in the
>case of OOP this is an interface.

But adding new modules without somehow modifying the web server is simply 
not allowed in the problem statement that I had (that is, all code that the 
server can execute is statically compiled into the web server). So there can 
be no "inversion" here -- some piece of the server needs to know about all 
of the code that it possibly can execute. (Ada requires with clauses at a 
minimum.)

>> This sounds more like a case of trying to make
>> everything look like a nail (to the OOP hammer).
>
>No, this is trying to reduce the effort to maintain a heavy component
>that is tested and verified only once.

I have no idea what you are talking about; no part of my web server (other 
than the case statement) is modified to add a new capability. [Note that 
something list the case statement has to exist in the OOP model anyway - ,at 
a minimum for with clauses and a series of registration calls (there is 
insufficient control over elaboration in Ada to use elaboration for that 
purpose in a real system).]

I can explain the mechanism in a bit more detail. The web server has a data 
list of (normalized) URLs that require special handling, along with a 
special handling key. When the web server sees any of these, it calls the 
special handling interface routine (passing the record containing the GET 
parameters and the output socket). Otherwise, it tries to serve a normal web 
page.

The special handling interface contains a case statement on the special 
handling keys, and calls the appropriate handler for each one. Since the 
original requirement was for all of the code to be statically compiled, that 
code is also part of the web server executable, and of course the special 
handling interface needs to be modified to add a new module. But it (and the 
data table) are the only things that need modification in this scenario.

An OOP design would have been identical (the data table was intended to be 
modified "on the fly", although we never needed that capability and thus 
never implemented it - the data is just an Ada aggregate currently), with 
the exception that the case statement would be replaced by a registration 
routine that gathered all of the units together. I fail to see how that 
would have improved anything about the design.

It would, however, have provided an easier way to make the design far more 
complex (and less maintainable, IMHO), by adding interfaces to support 
dubious capabilities (and thus changing the behavior of the core web 
server), rather than funneling everything through the interface.

                                   Randy.









^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10 11:26                                   ` Georg Bauhaus
@ 2011-08-10 22:27                                     ` Randy Brukardt
  0 siblings, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-08-10 22:27 UTC (permalink / raw)


"Georg Bauhaus" <rm.dash-bauhaus@futureapps.de> wrote in message 
news:4e426ae0$0$6584$9b4e6d93@newsspool3.arcor-online.net...
...
> I don't think Google will, or even could, change a rather
> large case statement whenever some new request handler is
> added to the system. The system is running large number of
> app engine programs, each having a number of request handler
> types.  They use a registry.

That's not remotely the same problem (see my other message - and indeed my 
original messages). If you have an open system, and don't care about 
security and correctness, then of course a registration scheme is far 
preferable. I'm paranoid enough that I'm not willing to allow anyone else to 
put code into the server without the extensive vetting of an Ada compiler. 
(This is one of the same reasons that I rarely make any of my code open 
source -- I don't trust anyone else near my code. Even with RRS, I always 
verify every change someone else makes before adding it to my personal 
copy -- I've saved a lot of wasted debugging time by doing that.)

                                 Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10 21:56                                   ` Randy Brukardt
@ 2011-08-11  8:07                                     ` Dmitry A. Kazakov
  2011-08-12  4:52                                       ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-11  8:07 UTC (permalink / raw)


On Wed, 10 Aug 2011 16:56:00 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1bs0xoar40rx.6yb23bgkfrew.dlg@40tude.net...

>> In reality
>> there are many dispatching calls and many class-wide operations (for which
>> there is no typed procedural equivalent).
> 
> Reality? The reality is in the web server interface I was describing there 
> was only one such point of dispatch, and only a single interface to dispatch 
> to. It's clearly a special case, but one that is pretty common in the 
> systems I've worked on.

The problem is that starting a project without OO, you have to gamble on
whether this indeed is a special case and will remain special.

This is called fragile design.

It is bad that Ada offers a choice between types having classes and types
without classes. A decision which should not be taken at all.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-10 22:21                                   ` Randy Brukardt
@ 2011-08-11 13:50                                     ` Maciej Sobczak
  2011-08-12  4:43                                       ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Maciej Sobczak @ 2011-08-11 13:50 UTC (permalink / raw)


On Aug 11, 12:21 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> But adding new modules without somehow modifying the web server is simply
> not allowed in the problem statement that I had (that is, all code that the
> server can execute is statically compiled into the web server).

I see - but isn't it a special case?

The advantage of OOP is in its run-time nature. That is, the registry
can be modified at run-time according to anything from startup options
to real-time data input. Modifying a giant case statement (or is it a
chain of ifs? after all, URLs are not discrete in the Ada sense) might
be acceptable between deployment cycles of the given system, but
making this structure dependent on some run-time values would be too
much.
Of course, I don't claim that such run-time liberty is always
required, but is certainly more general. This is an important point
when designing reusable components. That is, if you implement the
final web server you might be in a position to define your problem
completely (or not - see the "fragile design" risk that Dmitry
mentioned), but if you implement the web server component for reuse in
potentially many future systems, then targeting the more general
problem seems to be a way to go.

This is why message delivery in YAMI4 is based on callbacks via
interfaces and why the object registration is dynamic - new objects
(they correspond to message targets or inboxes) can be added and
removed on the fly. This still allows a completely static structure
where all components are known statically and wired at program
startup, so in this sense both approaches are addressed without
unnecessary compromises.
I think that web servers are not much different from this - in fact,
they do exactly the same stuff, which is delivering external stimuli
to some program handler. I would certainly use OOP for this part of
any reusable web server component.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-11 13:50                                     ` Maciej Sobczak
@ 2011-08-12  4:43                                       ` Randy Brukardt
  2011-08-12  7:00                                         ` Maciej Sobczak
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-12  4:43 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:f44209e4-8677-4995-8b17-d641bae2b698@hl8g2000vbb.googlegroups.com...
>On Aug 11, 12:21 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
>> But adding new modules without somehow modifying the web server is simply
>> not allowed in the problem statement that I had (that is, all code that 
>> the
>> server can execute is statically compiled into the web server).
>
>I see - but isn't it a special case?

Yes, in today's world, safety and security are surely a special case --  
hardly anyone seems to care, and thus they get PWNed all the time.

Yes, of course there are ways to enforce safety and security in a dynamic 
loading environment, but they aren't practical for a no-budget project 
(certificates and encryption aren't cheap).

>The advantage of OOP is in its run-time nature. That is, the registry
>can be modified at run-time according to anything from startup options
>to real-time data input. Modifying a giant case statement (or is it a
>chain of ifs? after all, URLs are not discrete in the Ada sense) might
>be acceptable between deployment cycles of the given system, but
>making this structure dependent on some run-time values would be too
>much.

Well, actually, the URL mapping (URL to key mapping is stored in a data 
table - of ordinary records) was intended to be a run-time data structure. I 
never actually implemented run-time changes for that table, but it would be 
simple to do so. The "requirement" that I started with is that no code 
outside of that known to the web server could be executed, but of course 
that has nothing to do with the mapping of the URLs to those existing 
routines.

Adding a new module requires modifying the case statement, but that would 
require modifying a with clause and recompiling in any case. Don't see any 
difference there.

Anyway, I think I've said everything on this topic that needs to be said. 
There is no one right answer to program design challenges -- only that no 
design at all is wrong!

                                          Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-11  8:07                                     ` Dmitry A. Kazakov
@ 2011-08-12  4:52                                       ` Randy Brukardt
  2011-08-12  8:54                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 63+ messages in thread
From: Randy Brukardt @ 2011-08-12  4:52 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1luxw3i4h9z8e$.7a8ee3cf99u2.dlg@40tude.net...
> On Wed, 10 Aug 2011 16:56:00 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1bs0xoar40rx.6yb23bgkfrew.dlg@40tude.net...
>
>>> In reality
>>> there are many dispatching calls and many class-wide operations (for 
>>> which
>>> there is no typed procedural equivalent).
>>
>> Reality? The reality is in the web server interface I was describing 
>> there
>> was only one such point of dispatch, and only a single interface to 
>> dispatch
>> to. It's clearly a special case, but one that is pretty common in the
>> systems I've worked on.
>
> The problem is that starting a project without OO, you have to gamble on
> whether this indeed is a special case and will remain special.
>
> This is called fragile design.

No, this is called "agile development"! There is no circumstance where a 
designer can possibly predict all possible ways their project is going to 
evolve. It's silly to try.

It doesn't matter how you design your interfaces -- you're going to have to 
change them at some point. And I've never seen any difference in the amount 
of work in a OOP design. If anything, the OOP designs are harder to 
modify -- adding a new interface to the ARM formatter or the Claw Builder 
takes a long time and requires inserting a lot of similar code in a number 
of packages. I've rarely seen that sort of behavior with a purely procedural 
design (probably because ad-hoc sharing of code is much easier in a 
procedural design).

I could imagine that there could exist some extremely fancy tools for 
creating the common structures of all of those "implementations" of the new 
interfaces automatically -- but I'm not aware of any such thing for Ada --  
and in any case, I wouldn't have one (I only use Janus/Ada tools for 
[virtually all] programming here; have to do so in order to figure out what 
needs to be improved).

                                   Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-12  4:43                                       ` Randy Brukardt
@ 2011-08-12  7:00                                         ` Maciej Sobczak
  2011-08-12 21:59                                           ` Randy Brukardt
  0 siblings, 1 reply; 63+ messages in thread
From: Maciej Sobczak @ 2011-08-12  7:00 UTC (permalink / raw)


On Aug 12, 6:43 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> >I see - but isn't it a special case?
>
> Yes, in today's world, safety and security are surely a special case --  
> hardly anyone seems to care, and thus they get PWNed all the time.
>
> Yes, of course there are ways to enforce safety and security in a dynamic
> loading environment,

Never in my posts I have mentioned dynamic loading of anything (in
fact, I have always stressed that the whole program can be compiled
and linked statically) and I think that your focus on safety and
security in this discussion is artificial. That is, I don't see in
what way OOP, applied in the way I have described, would compromise
either safety or security in this kind of systems.
Without this connection your "hardly anyone seems to care" is just a
strawman argument.
I think that everybody on this group cares about safety and security
(we would not be here otherwise), we just cannot agree on how to get
there while also preserving some other engineering values like
flexibility of design evolution or component integration.

> There is no one right answer to program design challenges

Right.

> -- only that no
> design at all is wrong!

This case was never proposed here.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-12  4:52                                       ` Randy Brukardt
@ 2011-08-12  8:54                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 63+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-12  8:54 UTC (permalink / raw)


On Thu, 11 Aug 2011 23:52:13 -0500, Randy Brukardt wrote:

> It doesn't matter how you design your interfaces -- you're going to have to 
> change them at some point.

Yes. But it does not imply that there should be no interfaces designed.

> And I've never seen any difference in the amount 
> of work in a OOP design.

I disagree, but in order to show the truth we would need some metrics and
data.

IMO, OO is just an evolution of the concept of ADT used to accommodate
mathematical ideas of categories. Arguing against OO is arguing against
types in general.

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



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Derived private interface
  2011-08-12  7:00                                         ` Maciej Sobczak
@ 2011-08-12 21:59                                           ` Randy Brukardt
  0 siblings, 0 replies; 63+ messages in thread
From: Randy Brukardt @ 2011-08-12 21:59 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:970ef0a5-da4b-4463-b411-aa3ef116fad1@f7g2000vba.googlegroups.com...
On Aug 12, 6:43 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

>> >I see - but isn't it a special case?
>>
>> Yes, in today's world, safety and security are surely a special case -- 
>> hardly anyone seems to care, and thus they get PWNed all the time.
>>
>> Yes, of course there are ways to enforce safety and security in a dynamic
>> loading environment,
>
>Never in my posts I have mentioned dynamic loading of anything (in
>fact, I have always stressed that the whole program can be compiled
>and linked statically) and I think that your focus on safety and
>security in this discussion is artificial.

Your previous message had expounded on the advantages of run-time management 
of modules. I had assumed that you suddenly were talking about dynamic 
module management, because I had already shown (twice in fact) that there 
was no advantage in this system to run-time management (or any other OOP 
characteristics) in terms of effort to add new interfaces.

Perhaps you've missed a critical point: static binding should always be 
strongly preferred to any sort of run-time management, because it is many 
times easier to analyze statically (both by tools and by the programmer), 
it's easier to debug (because the run-time management doesn't interfere with 
determining what the system is actually doing), and it typically performs 
better (because compilers can do better optimizations, although this effect 
is usually marginal and is far below the importance of the first two). These 
are critical to program maintenance, especially when having to understand 
existing code (even code you wrote when you come back to it 10 years later).

There has to be a strong reason for using dynamic module management:

(1) The interface is complex and interrelated, so that dynamic dispatching 
actually buys something beyond confusion (for instance, the "action 
routines" of Claw for handling events);
(2) Dynamic loading/reconfiguration of capabilities has to be supported;
(3) Following OOP religion even when it demonstratably doesn't help is more 
important than the benefits of a fully static design (a so-called 
"object-based design").

I'd previously shown repeatedly that (1) did not apply to the web server 
problem (at least with the design we selected); thus I had assumed that 
you'd veered off into discussing (2) -- because otherwise you are simply 
following (3) and there is no point in discussing anything with a religious 
fanatic (of any stripe) -- they don't really care about facts.

So at this point it is clear that we really have nothing to talk about. 
Sorry.

                                        Randy.





^ permalink raw reply	[flat|nested] 63+ messages in thread

end of thread, other threads:[~2011-08-12 21:59 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05  3:14 Derived private interface Rego, P.
2011-07-05  5:10 ` AdaMagica
2011-07-06  2:24   ` Rego, P.
2011-07-06  4:34   ` AdaMagica
2011-07-06  7:55     ` Georg Bauhaus
2011-07-06  8:30       ` AdaMagica
2011-07-06 12:59         ` Georg Bauhaus
2011-07-06 13:23           ` AdaMagica
2011-07-06 19:06             ` Randy Brukardt
2011-07-06 13:28           ` Simon Wright
2011-07-06 19:45           ` Randy Brukardt
2011-07-06 22:05             ` Georg Bauhaus
2011-07-06 23:56               ` Adam Beneschan
2011-07-07 14:09                 ` Georg Bauhaus
2011-07-07 15:10                   ` Adam Beneschan
2011-07-08  4:29                     ` AdaMagica
2011-07-08 19:08                       ` Randy Brukardt
2011-07-08 19:12                     ` Randy Brukardt
2011-07-07 15:19                   ` Georg Bauhaus
2011-07-07 10:37         ` Stephen Leake
2011-07-07 13:18           ` Georg Bauhaus
2011-07-08 19:23             ` Randy Brukardt
2011-07-08 21:41               ` Jeffrey Carter
2011-07-09  6:14                 ` Dmitry A. Kazakov
2011-07-22 22:59                 ` Randy Brukardt
2011-07-23  7:30                   ` Jeffrey Carter
2011-07-23  9:29                     ` Maciej Sobczak
2011-07-23 10:07                     ` Dmitry A. Kazakov
2011-07-26 21:04                     ` Randy Brukardt
2011-07-26 23:43                       ` Jeffrey Carter
2011-07-27 23:56                         ` Randy Brukardt
2011-07-28  0:18                           ` Jeffrey Carter
2011-07-28 10:06                         ` Maciej Sobczak
2011-07-28 23:24                           ` Randy Brukardt
2011-07-29  6:45                             ` Simon Wright
2011-07-30  0:04                               ` Randy Brukardt
2011-07-30  6:32                                 ` Simon Wright
2011-08-01  9:30                                   ` Alex R. Mosteo
2011-08-01 10:12                                     ` Dmitry A. Kazakov
2011-08-01 21:56                                       ` Randy Brukardt
2011-08-02 10:03                                         ` Dmitry A. Kazakov
2011-08-02 21:16                                           ` Randy Brukardt
2011-08-03  9:01                                             ` Dmitry A. Kazakov
2011-08-03 20:16                                               ` Randy Brukardt
2011-08-04  8:15                                                 ` Dmitry A. Kazakov
2011-08-09 21:10                             ` Maciej Sobczak
2011-08-09 21:35                               ` Randy Brukardt
2011-08-10  9:11                                 ` Dmitry A. Kazakov
2011-08-10 21:56                                   ` Randy Brukardt
2011-08-11  8:07                                     ` Dmitry A. Kazakov
2011-08-12  4:52                                       ` Randy Brukardt
2011-08-12  8:54                                         ` Dmitry A. Kazakov
2011-08-10 10:07                                 ` Maciej Sobczak
2011-08-10 11:26                                   ` Georg Bauhaus
2011-08-10 22:27                                     ` Randy Brukardt
2011-08-10 22:21                                   ` Randy Brukardt
2011-08-11 13:50                                     ` Maciej Sobczak
2011-08-12  4:43                                       ` Randy Brukardt
2011-08-12  7:00                                         ` Maciej Sobczak
2011-08-12 21:59                                           ` Randy Brukardt
2011-07-06 15:06       ` Adam Beneschan
2011-07-06 16:36       ` Dmitry A. Kazakov
2011-07-06 19:20       ` Randy Brukardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox