From: Phlip on
Robert C. Martin wrote:

> However, with OO, adding new functions to existing data structures is
> hard. You have to find every subclass and add a new method.

But you can do that incrementally, which a switch can't so easily do. You
can add the new method as a default in the base class, test, deploy one
specialization to one subclass, test, and keep going until nobody uses the
default. Then you make it pure virtual and retire its stub implementation.

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand


From: Robert C. Martin on
On Sun, 12 Jun 2005 09:14:15 +0200, "Ilja Preuý" <it(a)iljapreuss.de>
wrote:

>Robert C. Martin wrote:
>
>> The tougher one is:
>>
>> Shape intersection(Shape s);
>>
>> That requires a generic shape that can represent any shape at all.
>
>Well, it depends on the other operations on the Shape class, I think. (I
>might just not understand what you mean by a "generic shape", though.)

Let's say we have a simple shape hierarchy of polygons and ellipse,
including corresponding arcs. The intersection of the interiors of
two polygons is not necessarily a single polygon. The intersections
of the interiors of two ellipses is generally not an ellipse. And the
intersection of an ellipse and a polygon is some horrible hybrid. An
object that could represent those intersections must be much more
generic than Polygon or ellipse.

How do we represent these intersections as shapes? Topmind suggested
that intersections be represented *as* intersections. i.e. we simply
represent the resultant shape by storing the two intersecting shapes
in a new derivative of Shape, perhaps called ShapeIntersection. (What
remains, thereafter, is figuring out how to draw, calculate perimeter,
calculate area, rotate, etc, etc, a ShapeIntersection.)


-----
Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716


"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo
From: Robert C. Martin on
On Sun, 12 Jun 2005 07:27:44 -0400, CTips <ctips(a)bestweb.net> wrote:

>Robert C. Martin wrote:
>> On Fri, 10 Jun 2005 18:57:21 -0400, CTips <ctips(a)bestweb.net> wrote:
>>
>>
>>>topmind wrote:
>>><snip>
>>>
>>>>OO is good for .... shapes.
>>>>
>>>
>>>Not really. Anytime someone comes up with the shapes example, ask them
>>>how they would add the method:
>>>
>>>class shape {
>>>// true if object has any points in common with <B>
>>>boolean intersects(shape B);
>>>}
>>>
>>>See how quickly mind-lock sets in....
>>
>>
>> That one is not so hard. Simply algebra can solve it without too much
>> difficulty (I've done it). The tougher one is:
>
>Nah, the problem isn't the implementation. Its the fact that you have to
>(in general) have to write a separate function for each _pair_ of
>subclass types.

You *may* have to do that, if you don't have a generic way of
representing shapes. Let's say that we don't. The solution to this
problem has been around for a long time. It's called multiple
dispatch. (e.g. some languages allow you to polymorphically dispatch
on more than one argument. Thus (intersect(s1, s2) selects a function
that conforms to the type of both s1 and s2.

Most OO languages don't have multiple dispatch. However, just as
general trees are isomorphic with binary trees, so too is multiple
dispatch isomorphic with dual dispatch. (i.e. the Visitor pattern).

Visitor provides a very nice solution to *dispatching* aspect of the
shape intersection problem. Indeed, using Visitor for this kind of
stuff is pretty much run-of-the-mill OO.

The harder problem to solve is how to accurately represent the
resultant intersected shapes. Now *that* is a problem worth study.

>This means that you need to know _ALL_ other shape sub-classes out there
>before you can actually implement the function intersects().

Granted. And when you add new shapes you have to modify the
intersection visitor. That's just part and parcel of the problem.

>[I have deliberately picked some fractal shapes so that a certain
>mathematical ignoramus (not you) doesn't start quibbling; however I am
>_NOT_ certain that intersects() is actually computable for both the koch
>snowflake and the mandelbrot set.]

I don't know about the snowflake. As for the Mandelbrot set, it is
not solvable in general, but is trivial to solve to any particular
tolerance. Remember that a point is in M only if the recursive
iteration *eventually* converges. Practically speaking, one must
choose a tolerance for *eventually*. Otherwise one could spend an
infinite amount of time checking certain points.

-----
Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716


"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo
From: Robert C. Martin on
On Tue, 14 Jun 2005 04:35:23 GMT, Jeff Brooks <jeff_brooks(a)nospam.com>
wrote:

>Jeff Brooks wrote:
>
>> It appears you don't you understand what a fractal is.
>
>Oops, that should say "It appears you don't understand what a fractal is."


A fractal is like a newsgroup thread. They are all self similar
regardless of scale.


-----
Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716


"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo
From: Miguel Oliveira e Silva on
"Robert C. Martin" wrote:

> On 12 Jun 2005 10:11:39 -0700, "topmind" <topmind(a)technologist.com>
> wrote:
>
> >
> >Switch/case statements are more flexible.
>
> For some thing, and not for others.
>
> If you use switch statements then adding functions to existing data
> structures is relatively easy. All you do is replicate the switch
> statement in the new function, and fill in all the cases.
>
> However, with switch statements, adding new data structures to
> existing functions is hard. You have to find every existing switch
> statement and add the new case.
>
> If you use polymorphism then the reverse is true. Adding new data
> structures to existing functions is easy. All you do is write the new
> class, and all the existing functions polymorphically deploy to it.
>
> However, with OO, adding new functions to existing data structures is
> hard. You have to find every subclass and add a new method.

This is not (often) true. In languages in which sub-typing (substitutability)
is sub-classing (code reuse), it is only necessary to implement the new method,
in the classes with sufficient information for that implementation.

As an example, suppose we have a class TWO_FIGURE_INTERACTION
exporting a "distance" real method, with many descendant classes
(such as CIRCLE_RECTANGLE_INTERACTION).

(Eiffel code:)

class TWO_FIGURE_INTERACTION
feature
distance: REAL is
-- minimum distance between the two figures
deferred -- method without implementation ("pure" virtual in C++ terminology)
end;
...
end -- TWO_FIGURE_INTERACTION


If this class's ADT (Abstract Data Type) is to be extended with a
new method "intersect", then it is only necessary to add it in this
class (regardless of their descendant classes):


class TWO_FIGURE_INTERACTION
feature
intersect: BOOLEAN is
do
Result := distance < 0.0
end;
...
end -- TWO_FIGURE_INTERACTION


Since ADT are much (much) more stable than methods, adding new
operations to existing ADTs (at least as ADTs are implemented in OO
languages!), has lesser effects in the program's modularity than adding
new data types to existing methods. The reason for this very important
difference is in the key continuity modularity criteria (a small change
in the problem's specification results in changes in one or few modules).

Although both approaches (OO and functional/procedural) are in a
sense dual (as you correctly mentioned), the duality is not balanced
at all. An ADT need not to know all of its methods possible
implementations (it may even not know one!). On the other hand,
the "switch" alike method approach needs to know most (if not all)
of the possible data types.

> Sometimes you want to be able to add new functions to existing data
> structures, and so you use a switch statement. Sometimes you want to
> be able to add new data structures to existing functions, and so you
> use polymorphism.
>
> They are yin and yang, opposite and complementary. Using just one or
> the other is imbalanced.
>
> -----
> Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com
> Object Mentor Inc. | blog: www.butunclebob.com
> The Agile Transition Experts | web: www.objectmentor.com
> 800-338-6716
>
> "The aim of science is not to open the door to infinite wisdom,
> but to set a limit to infinite error."
> -- Bertolt Brecht, Life of Galileo

-miguel

--
Miguel Oliveira e Silva
mos at det.ua.pt - http://www.ieeta.pt/~mos
DET-IEETA, Universidade de Aveiro, PORTUGAL


First  |  Prev  |  Next  |  Last
Pages: 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
Next: Use Case Point Estimation