Just want to surface this link to everyone involved in the (rather large)
subthread of OOP flavors:

http://www.javaworld.com/javaworld/jw-07-1999/jw-07-toolbox_p.html

james_b posted it as a footnote but I thought people might easily miss it.

I read this 6-part series a couple of years ago and it really challenged the
way I thought about OO.  While Holub is certainly "extreme" in his views, I
think he does make some very illuminating--and often convincing--arguments.
(It's a long series, but very worth it IMO...)

What finally resolved it for me was reading some of the articles Bill
Venners wrote on artima.com about OOP.  He said something to the effect of,
"OOP is for programmers, not computers."  In other words, the level of
success of a particular design is generally defined by how effective that
design is in managing complexity.

If your program has four simple datatypes with fairly inflexible semantic
definitions (let's call them, oh, String, Fixnum, Array and Hash) and 99 use
cases involving those datatypes, it probably makes sense to have the
datatypes operating on the data.  If, on the other hand, you have 99
arbitrarily complex datatypes that are very likely to change from release to
release--say you're representing bank accounts once served by 40 different
legacy systems--and four very concrete use cases (withdrawal, deposit,
transfer, close), then it probably makes sense for your 99 types to have the
actions hanging off them.

OK, those were pretty bad examples... :)

The point is, I *don't* think the following should be the primary factors
that decide whether x.foo(y) or y.fooTo(x) is best:
* x.foo(y) is more natural because it's x that does the fooing.
* In the Real World, you don't tell a y to fooTo x, you just foo the y with
x.
* It just feels wrong, I don't know why.

Instead I think the thought process should sound more like:
* x is more likely to change in the future, so I would like to keep its
implementation particularly opaque and its public interface particularly
compact.  Therefore I will choose x.foo(y).
* Many classes are likely to have an "is-a" relationship to y, and I would
like future developers to be able to provide their own implementations of
fooTo, so I will choose y.fooTo(x).

The latter two questions may not be as intuitive as the former, but I
believe they are much more relevant if the goal of a design is to
effectively manage complexity.

Thoughts?