From: Robert C. Martin on
On 14 Jun 2005 19:44:19 -0700, "topmind" <topmind(a)technologist.com>
wrote:

>I am having difficulty finding coherent requirements or code samples
>for a dosage system. How about we focus on stuff that polymorphs in
>that example. What are the polymorphic types or classes?

The requirements are reasonably well stated in overview form in the
first article. By the second or third article there is a very
concrete requirement specified in detail as an acceptance test.

If you follow the example through the columns, you'll find a number of
polymorphic entities. Perhaps the first you'll find are the test
cases themselves. They derive from the JUnit framework. Next, you'll
find that the acceptance test fixtures are based on a polymorphic
framework (FIT). Within the application you find a polymorphic
gateway to the database, and (Manufacturing) which is a mock object
that masquerades as another system. You find that the messages show
hints of polymorphism, and may become fully fledged polymorphic
entities in a later iteration.

Bit by bit, as the application evolves, more and more polymorphism
creeps in. The application does not start with a lot of polymorphism.
Rather, polymorphism gets added over time in order to keep the
application flexible and decoupled.



-----
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 17:33:59 -0400, CTips <ctips(a)bestweb.net> wrote:

>Contrast this to the implementation using a big-old-switch (of switches)
>statement. Each shape will have a tag to control the switch() statement.
>This tag will (probably) be an enumerated type. It is relatively
>straightfoward for:
>- the user to determine all the pairs that are required
>- the compiler to spit out a waring regarding an unimplemented pair

I quite agree that there are issues. And for some problems switch
cases are a better solution than polymorphism. However, OO developers
don't melt-down when faced with dual-dispatch problems.

In any case, whether the intersection problem is solved by switch, or
by visitor, the issue is the same. When a new shape gets added, an
intersection method must be written for each other shape that
currently exists. Compilers *might* help in either case. In the
switch case, you must add to the enumerated type in order to get the
switch statements to complain (if you have a language that complains).
In the visitor case, you have to add an abstract method to the visitor
base class, which will cause the compiler to complain if any of the
visitor derivatives don't implement that method. Same difference.



-----
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: topmind on


> >I agree there is a trade-off, but my observation is that change favors
> >case statements most of the time.
>
> That's where we disagree. I think change favors neither approach, and
> that any approach that favors one technique over the other is
> necessarily imbalanced.

Well, case/if statements are a slightly lower level of abstraction than
polymorphism. This also means they can be more flexible. Higher
abstraction is great when changes fit that abstraction, but worse off
if they don't. I am sure you've encountered situations where you
purchase a high-level tool to do a job, but found it lacked some key
feature such that you end up buidling one from scratch to get the
needed feature.

But I admit I cannot readily show this right now. We would have to
collect some change scenarios and run them through the code counting
line changes, named unit changes, block changes, etc.

-T-

From: topmind on
Oscar Meyer. I'm liked.

From: Miguel Oliveira e Silva on
"Robert C. Martin" wrote:

> On Tue, 14 Jun 2005 19:01:53 +0100, Miguel Oliveira e Silva
> <mos(a)det.ua.pt> wrote:
>
> >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.
>
> Consider a function named "rotate()" that has a switch on shapes.
> What does this function do for circles? Nothing.

Correct. But that decision required the knowledge (on the part
of the programmer) of the circle's semantics (hence, even the
"rotate" procedure needed to know the new circle's ADT).
how would you do that automatically as happens in the OO
approach?

On the other hand, if a method has enough information
to be implemented in a given class, it need not to know
what will be its possible future descendant classes (as long
as those unknown new classes respect that class's
ADT semantics and method invocation is dynamically
binded, this implementation can be automatically inherited
and reused by all of them). This is the power of OO data type
abstraction.

> There are times when adding a new data structure to a switch
> architecture has no impact. There are times when adding a data
> structure to an OO architecture has no impact. I think you'd be hard
> pressed to prove that the duality is not balanced.

(Ok, let me try again.)

As said in the other message, there is a very important difference
between both approaches which make them unbalanced: the
existence of subtyping/subclassing in OO languages.

In the OO approach a new class may not be build from scratch, it
can and should reuse existing classes (as long as it is able to respect
those classes's ADTs). Hence, it needs "only" to implement its
differences to those existing (inherited) types.

On the other hand, a procedural "switch" approach without a subtyping
mechanism between data types (I would mostly exclude from this
comparison the type structural equivalence present in some functional
languages), is required to know all of the semantics of new data types,
hence inhibiting the automatic correct reuse of existing procedural code.
That existing procedural code may sometimes work in new data types,
but there is no way of knowing (and depend on) that in advance
giving it poor modularity properties (in particular: modular continuity).

A more balanced dual approach to OO programming, would be a functional
approach with structural type equivalence, allowing the construction of
functional code which work for structural equivalent data types.

So the "thing" that makes both (dual) approaches unbalanced is the
type/class relations which are part of OO programming (no such
dual "thing" exists in procedural "switch" code).


All this being said, the main reason that led me to participate in this
thread was my disagreement to one of your points:

You wrote:

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

As showed, this is not (often) true.

Best regards,

-miguel

> -----
> 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 Oliveira e Silva
mos at det.ua.pt - http://www.ieeta.pt/~mos
DET-IEETA, Universidade de Aveiro, PORTUGAL


First  |  Prev  |  Next  |  Last
Pages: 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
Next: Use Case Point Estimation