

CourtesyImplementation (2004) - joeyespo
http://martinfowler.com/bliki/CourtesyImplementation.html

======
cousin_it
That's indeed the right pattern to use in OO. However, OO isn't necessarily
the most concise approach to such problems :-)

    
    
        data Node = Elephant | Box [Node]
    
        count Elephant = 1
        count (Box nodes) = sum (map count nodes)

~~~
djur
It's easy to golf a more concise solution to a contrived example like that,
yes.

The Haskell implementation starts to get more complicated when you want to be
able to define additional participants in the role of 'Node' without the
original implementation having to know the name or structure of those
participants. That's extremely common in game programming, for example.

~~~
cousin_it
Well, if the additional participants only need to support the "count"
operation, then you can do without tree-shaped data types at all, and just use
a single Integer for the whole thing. After all, a single lazy Integer in
Haskell is already an unevaluated tree of computations, there's no need to
build additional trees out of it :-) Also this way you get memoization for
free.

If we need to support other operations as well, Haskell is perfectly capable
of expressing the usual extensible OO solution, by using a record of
functions. (A record type containing functions in FP is basically the same as
an interface type in OO, and instances of that record type correspond to
implementations of the interface.)

~~~
djur
A record of functions permits polymorphism in behavior, but I'm not clear on
how it can provide polymorphism in state or structure.

I'm certainly no expert in pure FP so there may be something I'm missing, but
if the operations have to produce a change in the state of an entity, each one
of the functions would have to both receive and return a state, right? Or you
use a record of closures, each which returns a new record of closures?

It seems to me that in both cases you're discarding a lot of the benefits of
Haskell's type system.

~~~
cousin_it
For what it's worth, I agree that a graph of stateful objects referencing each
other is much easier to express in an OO language than in a pure functional
language. There are many functional solutions, but none of them are very nice
IMO. Maybe that's one reason to use an impure functional language like ML,
which I consider an overall better language than Haskell.

~~~
djur
I think we agree on this one. I've really been enjoying using OCaml exactly
because I can make use of mutable state or OO-style polymorphism when I want,
but otherwise it feels very natural to write pure functional code.

All I need to do is wrap my head around functors and first-class modules and
I'll actually feel like I understand it well enough to use it for real work.

------
mattfenwick
It's difficult to see the point because it's not a very good example. Why do
Elephants inherit from Node (they seem entirely unrelated)? How can I put
things other than Elephants in boxes -- by also having them inherit from Node?
Why isn't there a "Leaf" subclass of Node that contains one of anything?

I think the tradeoff between adding methods to a class hierarchy and adding
cases to functions is relevant here (I think this is known as the expression
problem --
[http://en.wikipedia.org/wiki/Expression_problem](http://en.wikipedia.org/wiki/Expression_problem)
\-- but I'm not sure), but it's not mentioned:

> Now the kind_of? test in num_elephants is a smell, since we should be wary
> of any conditional that tests the type of an object.

~~~
jrochkind1
Since it's ruby, there's actually NO reason for Elephant to inherit from node,
and all his code would work just the same if it didn't. I think that was
basically an error on his part.

And, since it's ruby, the answer to "how can I put things other than Elephants
in boxes", with the current code example, is "just make sure they have a
#num_elephants method". Which, yeah, seems kind of insane, although part of
that is the artificial example.

An IMO better solution still within this kind of OO world would be to declare
an interface of some kind "CountableNode" or something, and say, anything you
put in a box has to implement that interface (which to begin with has one
method, #num_elephants). There are ways to do that sort of thing in ruby
(there are ways to do almost anything in ruby), but they aren't done very
often in rubyland, which I do think is a failing in the ruby idiom. Although
many rubyists will say they've never found it a problem in practice (maybe
they're right, maybe they just didn't recognize the root of the problems they
did have).

Anyway, you make reasonable points even with these 'corrections', but Fowler
could have made his example a bit tighter while still staying firmly within
conventional ruby and/or OO best practices.

------
jrochkind1
In fact, some OO purists from the original days of OO suggest using this
technique generally to always avoid conditionals anywhere. Polymorphism over
conditionals.

[http://sourcemaking.com/refactoring/replace-conditional-
with...](http://sourcemaking.com/refactoring/replace-conditional-with-
polymorphism)

------
icebraining

      def num_elephants
        result = 0
        @children.each do |c|
          if c.respond_to? :num_elephants
            result += c.num_elephants
          else
            result += 1
          end
        end
        return result
      end
    

Personally, I just wouldn't mix my boxes with my elephants :)

~~~
djur
If the duck type is going to be checked, it should be checked when the child
is added. Ensures you only call #respond_to? once per node, fails earlier.
Checking types during a computation is a code smell to me.

------
rowyourboat
Why would you get disturbed by an elephant proclaiming to be exactly one
elephant?

~~~
gpvos
Being and containing are different things. (Although I would not be disturbed
by that in this cases like this.)

