From: ulf on
Hi everybody,

I don't consider myself an expert on the delegation side of the
subject,
but among all the issues raised in this thread, let me add my $0.03
worth to one particular Q about inheritance aka. subclassing:

Rick Elbers wrote:
> Op 7 Aug 2006 09:15:21 -0700 schreef "Thomas Kowalski" <th-ko(a)gmx.de>:
....
>> >> First attempt to reduce the codelength of the classes contour was to
>> >>> subclass it, resulting in a class like DividableContour.
> >> Are there contours that are not ?
>
>> No, there is just one typ of contour used throughout the whole
>> software.
>> The hierarchy would be something like:
>> contour extends dividablePolygon extends closedPolygon
>
> We are not on the same wavelength. My question is not if its in the
> code or software . My question was: are there, in your view, contours
> that are not dividable ?

Thomas, I am a bit confused: First you talk of
DividableContour --[> Contour
then of
Contour --[> **Dividable**Polygon --[> ClosedPolygon

In the following I will talk of the class hierarchy
(I) DividableContour --[> Contour --[> ClosedPolygon

This is obviously a CORRECT hierarchy, since all dividable
contours are contours, and all contours are closed polygons.

Reason #1 for this to be a GOOD hierarchy would be the
presence of a second subclass in your domain/system:
UndividableContour --[> Contour

But this is not a necessary reason.
Contour is a valid abstraction in its own right, an abstraction
at a level of generalization where the issue of dividability
is not yet decided. The absence of the divide() method in
Contour does not express the negative property that Contour
instances CANNOT have a divide() method.

Reason #2 for (I) to be a GOOD design would be - as I suspect -
that noteworthy parts of the domain/system work with contour-objects
(which, as Thomas confirmed, are all dividable contours)
but need to know only that these are contours, not whether
they are dividable. In particular, most Contour methods would
seem to be independent of dividability.

(Was your question, Rick, about undividable contours just a Q
of pure interest, or did you intend to use the answer for an
argument?)

Finally, I see Thomas' original concern also as a valid reason #3
for (I) to be GOOD: In modeling a domain, also pragmatic issues
play a role. For example, the elements of the class model
should better not be too complex to understand them in one chunk.
Hence it seems justified to separate the complex property of
contours' dividability - or rather the complex behavior of a
contour dividing itself along a graph (did I get this right?) -
into a specialized subclass.

Now, all this of course does not say whether replacing inheritance
by delegation would lead to a BETTER structure. For the Q at hand,
that would mean that DividableContour does not inherit from Contour
but lets its instances delegate Contour-messages to a particular
Contour object. - Sorry, but I fail to see the advantage of that.
But then again, I'm no expert in delegation.


Regards,
Ulf Schünemann

From: Dmitry A. Kazakov on
On 10 Aug 2006 02:26:27 -0700, Thomas Kowalski wrote:

> Hi Dmitry, Steven,
>
> maybe I didn't understood exactly what your discussion is about, but
> IMHO the word inheritance is not choosen well. The paradigma
> inheritance describes the s/w industrie is simply specialization.

Not necessary. Inheritance is just a way to define a relationship between
two types. Specialization is a specific property of that relationship.
Generalization is another. But the most common case is neither
specialization nor generalization.

> Every time we define an objects we are adding constraints. Each
> methode, each member constraints this class to an actually usable
> "item". Since we say an square is a special rectangle, it would be
> perfectly fine too have it "inheriting" is this direction, as you
> stated already.

For in-methods, yes. But out- and inout-methods will be broken. Results are
outs.

In fact, you can inherit rectangle from square or square from rectangle,
that changes little.

> The Idea of breaking the "contract" with is implied by the constraints
> made by a certain class might be a neat feature in some situations, but
> is most of the time not neccessary and would just complicate the whole
> typesystem.

The problem is that you cannot get a new type without breaking something. A
thing exposing same behavior is just the same thing. It walks like a duck
it quacks like a duck, it is a duck.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: H. S. Lahman on
Responding to Kazakov...

>>>>In a classic recent example here
>>>>the debate centered around deriving Rectangle behaviors from Square
>>>>behaviors. The real problem was that Square was defined with a
>>>>sideLength knowledge attribute while Rectangle was defined with
>>>>majorSideLength and minorSideLength -- apples & oranges.
>>>
>>>It is not apples and oranges. It is squares and rectangles. (:-))
>>>
>>>SideLength is a direct reflection of a trivial geometrical fact (theorem)
>>>about squares. This theorem does not hold for rectangles. End of story.
>>
>>Not necessarily. The geometrical facts are: (A) both have four sides;
>>(B) for a square all sides are of the same length; and (C) for a
>>rectangle opposing sides are the same length but adjacent sides are not.
>> So if one defined sideLengthN (N = 1..4) for Square, then Rectangle
>>could be a subclass without any LSP inconsistency in the knowledge
>>attributes.
>
>
> But that wouldn't be a definition of square. Because geometrical squares
> form a set of things having all properties of squares, which includes the
> property B. Of course, you can say that B isn't essential for the problem
> at hand, but then I would wonder if squares aren't either.

I think a square having four sides of equal length is <part of> the
formal definition of a square. So with respect to defining side length
using four sideLengthN (N = 1..4) attributes is a valid abstraction (the
equality is enforced in initializing the attributes). Similarly, using
one sideLength is a valid abstraction.

The difference lies in whether LSP is an issue; if one also needs a
definition that is consistent with Rectangle, then only the first
abstraction of the geometric properties works.

>>Nonetheless I think LSP is quite useful in an OO context because one
>>tailors object abstractions to the problem in hand. That allows one to
>>use tricks like abstraction and a flexible view of logical
>>indivisibility to make many LSP issues in the problem space irrelevant
>>to the solution context. IOW, one only has to resolve the LSP issues
>>that are relevant to the problem in hand.
>
>
> True, but to me that means a defeat of LSP as a principle. It was
> introduced solely to ensure substitutability. When you say OK, we have to
> check for substitutability in each given case (context), then you merely
> return back to the beginning.

I see the issue differently. LSP requires that one define what
substitutability means in the current problem context and then construct
the classes, interfaces, and client contracts around that definition.

The real problem here is that current 3GLs do not document what such
definitions are. If those definitions are not documented elsewhere,
then future maintainers do have to check every context when making a
change. If those changes are documented, then the maintainer only needs
to check client contexts if the change modifies the original definition
of substitutability


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl(a)pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info(a)pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



From: S Perryman on
"Thomas Kowalski" <th-ko(a)gmx.de> wrote in message
news:1155201987.219606.310760(a)m79g2000cwm.googlegroups.com...

> Hi Dmitry, Steven,

> maybe I didn't understood exactly what your discussion is about, but
> IMHO the word inheritance is not choosen well. The paradigma
> inheritance describes the s/w industrie is simply specialization.

Inheritance is a well-chosen word.
A relationship whereby one thing acquires the properties of others.
Just like the inheritance of your parents' physical characteristics.
Or in the event of their demise , (possibly) acquiring their material
belongings.


> Every time we define an objects we are adding constraints. Each
> methode, each member constraints this class to an actually usable
> "item". Since we say an square is a special rectangle, it would be
> perfectly fine too have it "inheriting" is this direction, as you
> stated already.

> The Idea of breaking the "contract" with is implied by the constraints
> made by a certain class might be a neat feature in some situations, but
> is most of the time not neccessary and would just complicate the whole
> typesystem.

We are not breaking the contract.
We are debating how to define the exceptions to the rule in a succinct
manner so that a type system can enforce our intent.


Regards,
Steven Perryman


From: Dmitry A. Kazakov on
On Thu, 10 Aug 2006 14:04:51 GMT, H. S. Lahman wrote:

> Responding to Kazakov...
>
>> But that wouldn't be a definition of square. Because geometrical squares
>> form a set of things having all properties of squares, which includes the
>> property B. Of course, you can say that B isn't essential for the problem
>> at hand, but then I would wonder if squares aren't either.
>
> I think a square having four sides of equal length is <part of> the
> formal definition of a square. So with respect to defining side length
> using four sideLengthN (N = 1..4) attributes is a valid abstraction (the
> equality is enforced in initializing the attributes). Similarly, using
> one sideLength is a valid abstraction.

Yes, any true proposition about square remains true independently on
whether we are aware of other propositions.

> The difference lies in whether LSP is an issue; if one also needs a
> definition that is consistent with Rectangle, then only the first
> abstraction of the geometric properties works.

The point is that, surely, you can take any set of propositions about
squares, name them abstractions, and find some of them being compatible
with rectangles. BUT, there are propositions which actually make squares
what they are, like width=height is. One could find small sets of those,
from which one could infer all others. This is how mathematicians define
their objects. Let name them sufficient sets. Now, each such sufficient set
will not be a subset of the set of propositions about rectangles.

In other words, you can model squares as IS-A rectangles, but they won't be
much square...

>>>Nonetheless I think LSP is quite useful in an OO context because one
>>>tailors object abstractions to the problem in hand. That allows one to
>>>use tricks like abstraction and a flexible view of logical
>>>indivisibility to make many LSP issues in the problem space irrelevant
>>>to the solution context. IOW, one only has to resolve the LSP issues
>>>that are relevant to the problem in hand.
>>
>> True, but to me that means a defeat of LSP as a principle. It was
>> introduced solely to ensure substitutability. When you say OK, we have to
>> check for substitutability in each given case (context), then you merely
>> return back to the beginning.
>
> I see the issue differently. LSP requires that one define what
> substitutability means in the current problem context and then construct
> the classes, interfaces, and client contracts around that definition.

I agree with that, but I see no contradiction.

> The real problem here is that current 3GLs do not document what such
> definitions are. If those definitions are not documented elsewhere,
> then future maintainers do have to check every context when making a
> change. If those changes are documented, then the maintainer only needs
> to check client contexts if the change modifies the original definition
> of substitutability

Again agree. That were a pragmatic solution I liked to have much. But in my
eyes it still kills LSP subtyping idea. You say, look, let at the
declaration point subtype be anything you wish. Most of the questions about
substitutability are postponed until instantiation, when the context will
be known. As long as that happens no later compile time, I don't worry.

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