comp.lang.ada
 help / color / mirror / Atom feed
* Re: Interface/Implementation (was Re: Design by Contract)
@ 1997-09-15  0:00 Marc Wachowitz
  1997-09-16  0:00 ` Owen Fellows
  1997-09-16  0:00 ` Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)] Graham Perkins
  0 siblings, 2 replies; 4+ messages in thread
From: Marc Wachowitz @ 1997-09-15  0:00 UTC (permalink / raw)



Nick <nickle@calfp.co.uk> wrote via Owen Fellows <ofellows@calfp.co.uk>
about supposedly "pure" OO a la Eiffel vs. Ada-like modules and types as
different concepts and non-method procedures:
> But it it more likely that you just inherit MATHEMATICIAN somewhere in
> your heirarchy to save on typing.

I find that totally unacceptable, as it creates much too strong coupling
between library modules and their clients. Adding new features to a library
module shouldn't force even the smallest change in any previously existing
clients. The same applies to unavoidable visibility of every parent feature
in children - to avoid potential clashes, one is forced to revert to using
long_feature_names_saying_they_are_only_for_class_X_and_not_for_children,
which is a shame for a somewhat recent language like Eiffel (even in old
K&R C you had private - aka static - functions/variables), in my view. The
point isn't so much about children touching conceptually private features
of parents where they shouldn't do that (though that does get "interesting"
in large projects with say, 50 to 100 programmers of varying quality, and
I'd rather have that checked, too), but about clean separation of concerns
and minimal coupling.

> Having the same implementation as inherits is a hint that it probably is
> inherits!

No more than the implementation of loops via conditional goto is a hint to
drop explicit loops from the language and only provide conditional goto (and
perhaps call/return) as control structure. I expect most people wouldn't
follow the latter reasoning (nor do I), and likewise I disagree with your
above suggestion. In fact, I'd already use inheritance much less than what
seems to be usual in the Eiffel world (if Bertrand Meyer's books are a hint
about general usage): Even if it means more writing, I prefer having a mere
client for an object via a field over implementation inheritance: As long as
the representation type can be used unchanged via its abstract interface,
I'll do so. If it's mostly right, but still no proper "is-a" relation holds,
I'll also seriously consider a different subclass with some small changes
for the different need, and then using this adaption as client in that new
type which really isn't a proper subtype. I find this to be much better at
decoupling, more explicit about the essential relations between those types,
and more readable for my taste. The counter-argument about inefficiency due
to another indirection doesn't hold, as the above is only about source level
stuff: If performance is critical, make the compiler sufficiently clever to
inline the respective data and operations for such cases, which should be
quite trivial. The counter-argument about needing all the facilities which
are used for inheritance again for import doesn't really work either, since
the usage of library modules with qualified names for feature access doesn't
need things like renaming, redefinition, re-export or hiding; simply write
e.g. Math.Sin(X) and stop worrying about name space pollution. (Well, you
do have to think about module names, which should ideally be a hierarchical
name space, similar to Ada child packages or Java packages, but it reduces
the amount of relevant names dramatically.)

-- Marc Wachowitz <mw@ipx2.rz.uni-mannheim.de>




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

* Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)]
  1997-09-15  0:00 Interface/Implementation (was Re: Design by Contract) Marc Wachowitz
  1997-09-16  0:00 ` Owen Fellows
@ 1997-09-16  0:00 ` Graham Perkins
  1997-09-17  0:00   ` Franck Arnaud
  1 sibling, 1 reply; 4+ messages in thread
From: Graham Perkins @ 1997-09-16  0:00 UTC (permalink / raw)



.. hope thread renaming helps rather than hinders.

How to get normal library effect from OO language?
Especially pure one such as Eiffel where there are
no modules (ie, "static" bits of the classes).

IMHO two very important things about libraries, 
regardless of whether you try to provide them 
with modules, classes, or whatever:

 (1) Use the library in client mode (because
     library designer hid stuff in order to
     reduce coupling and allow evolution).

 (2) System should have a single instance of
     the library (because multiple instances
     would simply waste space/time as they're
     indistinguishable).

Modular languages
-----------------
You can easily get both effects 1 and 2 above 
because a module (unit, package, whatever you
call it) has precisely those properties.

Hybrid languages
----------------
You can easily get both effects in hybrid
languages such as C++, Java, Smalltalk ;-))
since class doubles up as module. (part
of class generates 0,1, or more runtime
instances but another part of the class
describes a single runtime instance).  Though
to ensure (1) you should disallow creation
methods in your library class.

Pure class languages
--------------------
You don't have a module or a class-which-is
-also-a-module, but you still have ability
to program in client-supplier mode and create
single system-wide instances.  So you can still
ensure properties (1) and (2).  In Eiffel:

  a) put a once function in ANY (remember
     that ANY is a good place to put your
     per-project stuff).

  b) define an anthropomorphic class (eg
     MATHEMATICIAN) which provides access
     to library via once function.  Make sure
     library creation method is only visible
     to this accessor class.

These alternatives can be implemented in other
languages without much difficulty.

--------------------------

what about

   feature
     math : expanded BASIC_ROUTINES
     ...
     x := math.sqrt( y )

Yes I know it was rather neat to put expanded
library object wherever you want it, but that
relied on 
  - constructed value objects (bye bye Java
    and Smalltalk)
  - static binding for value objects (can't
    be sure in C++)
  - no attributes at all in the class
The last point in particular is a problem, since
it means that the client programmer is taking 
advantage of internals of the class.  Which isn't
safe clientship in my view.

Sorry if I'm stating the obvious, but I hadn't seen anyone
explaining an implementation approach in terms of usability
principles such as (1) and (2) above.




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

* Re: Interface/Implementation (was Re: Design by Contract)
  1997-09-15  0:00 Interface/Implementation (was Re: Design by Contract) Marc Wachowitz
@ 1997-09-16  0:00 ` Owen Fellows
  1997-09-16  0:00 ` Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)] Graham Perkins
  1 sibling, 0 replies; 4+ messages in thread
From: Owen Fellows @ 1997-09-16  0:00 UTC (permalink / raw)




Marc Wachowitz wrote:
> 
> Nick <nickle@calfp.co.uk> wrote via Owen Fellows <ofellows@calfp.co.uk>
> about supposedly "pure" OO a la Eiffel vs. Ada-like modules and types as
> different concepts and non-method procedures:
> > But it it more likely that you just inherit MATHEMATICIAN somewhere in
> > your heirarchy to save on typing.
> 
> I find that totally unacceptable, as it creates much too strong coupling
> between library modules and their clients. Adding new features to a library
> module shouldn't force even the smallest change in any previously existing
> clients. The same applies to unavoidable visibility of every parent feature
> in children - to avoid potential clashes, one is forced to revert to using
> long_feature_names_saying_they_are_only_for_class_X_and_not_for_children,
> which is a shame for a somewhat recent language like Eiffel (even in old
> K&R C you had private - aka static - functions/variables), in my view. 

Well, in practice I haven't found this to be a problem at all. This is
in a 800,000 line
project. Lots of names are the same in different classes, like the use
of
consistent names in the standard libraries (extend, remove etc ...)
This is a strong indication that such name clashes if they happen, are
rare events.

Visibility in all children. This can be an issue but not as much as you
think. 
It is usually indicative of having an implementation at the high level
of a heirarchy
and you should, in my opinion, use facility inheritance lower down where
necessary.
Now other Eiffel programmers would disagree with me, and use facility
inheritance at
the top of the heirarchy, as there is less typing.

> The
> point isn't so much about children touching conceptually private features
> of parents where they shouldn't do that (though that does get "interesting"
> in large projects with say, 50 to 100 programmers of varying quality, and
> I'd rather have that checked, too), but about clean separation of concerns
> and minimal coupling.

Minimal coupling is important. But from practical experience, classes we
have
written that are used for facility inheritance tend to be very stable,
don't
have name changes (implementation varies), and are usually only
extended.
Think about the MATHEMATICIAN for an example. The clashes don't happen
any
where near the level that one may presume they would happen if you
haven't
written systems in practice.

> > Having the same implementation as inherits is a hint that it probably is
> > inherits!
> 
> No more than the implementation of loops via conditional goto is a hint to
> drop explicit loops from the language and only provide conditional goto (and
> perhaps call/return) as control structure. I expect most people wouldn't
> follow the latter reasoning (nor do I), and likewise I disagree with your
> above suggestion. In fact, I'd already use inheritance much less than what
> seems to be usual in the Eiffel world (if Bertrand Meyer's books are a hint
> about general usage): Even if it means more writing, I prefer having a mere
> client for an object via a field over implementation inheritance: As long as
> the representation type can be used unchanged via its abstract interface,
> I'll do so. If it's mostly right, but still no proper "is-a" relation holds,

Agreed, there is no is-a relationship! But is is-a the only valid use or 
description of inheritance. Read the chapter in OOSC II on the taxonomy
of
inheritance. BM writes better and clearer than I do.

> I'll also seriously consider a different subclass with some small changes
> for the different need, and then using this adaption as client in that new
> type which really isn't a proper subtype. I find this to be much better at
> decoupling, more explicit about the essential relations between those types,
> and more readable for my taste. The counter-argument about inefficiency due
> to another indirection doesn't hold, as the above is only about source level
> stuff: If performance is critical, make the compiler sufficiently clever to
> inline the respective data and operations for such cases, which should be
> quite trivial. The counter-argument about needing all the facilities which
> are used for inheritance again for import doesn't really work either, since
> the usage of library modules with qualified names for feature access doesn't
> need things like renaming, redefinition, re-export or hiding; simply write
> e.g. Math.Sin(X) and stop worrying about name space pollution. (Well, you
> do have to think about module names, which should ideally be a hierarchical
> name space, similar to Ada child packages or Java packages, but it reduces
> the amount of relevant names dramatically.)

Which is always an choice that you can make as an programmer, you are
not
forced to use the inheritance for facility inheritance, you can always
do this

feature {NONE}  -- Don't allow clients access

	Math: expanded MATHEMATICIAN -- A valid use of expanded

or


feature {NONE}  -- Don't allow clients access

	Math: MATHEMATICIAN is
	   once
              !!Result.make
           end

If MATHEMATICIAN requires some form of initialisation. 
You don't pollute name space then. Eiffel gives you the choice.

At the end of the day, with things like loops, you want to have
loops because it makes reading the code easier. The code ends up closer
to the logical view of the world, not its phsical implementation.

This was the major argument in my book for the implementation of
'precursor'.
Why should you be telling the compiler how to implement something using
double inheritance, when the compiler can do it for you, and the results
are more readable.

Now in the case of facility inheritance. You don't have to use that
method,
you can get exactly what you want (see above) meeting your criteria for
visibility and name spaces. Therefor, I don't think you need extend the 
language.

I would say that 8 months ago I had the same opinions as you have
expressed,
but I've changed my mind.

Nick (From Owen's account)




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

* Re: Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)]
  1997-09-16  0:00 ` Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)] Graham Perkins
@ 1997-09-17  0:00   ` Franck Arnaud
  0 siblings, 0 replies; 4+ messages in thread
From: Franck Arnaud @ 1997-09-17  0:00 UTC (permalink / raw)



> (remember that ANY is a good place to put your per-project stuff).

No, it's not.




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

end of thread, other threads:[~1997-09-17  0:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-09-15  0:00 Interface/Implementation (was Re: Design by Contract) Marc Wachowitz
1997-09-16  0:00 ` Owen Fellows
1997-09-16  0:00 ` Libraries in pure OO [was Interface/Implementation (was Re: Design by Contract)] Graham Perkins
1997-09-17  0:00   ` Franck Arnaud

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