
Goodbye, shitty Car extends Vehicle object-orientation tutorial (2011) - Tomte
https://web.archive.org/web/20140416021831/http://lists.canonical.org/pipermail/kragen-tol/2011-August/000937.html
======
colllectorof
_> In good OO programming, we don’t make class hierarchies in order to satisfy
our inner Linnaeus._

This correctly identifies one of the worst problems with how people construct
OO programs when they get out of college. They are infected with the idiotic
desire to make neat taxonomies. They don't know why. They can't even explain
the rules that make one taxonomy good and another one bad. They just feel some
immense pressure to arrange things in trees. I've been like that when
initially learning Java and it took a while to recover from it. It's like
fucking brain damage from bad examples.

Inheritance is not about creating taxonomies.

Namespaces are not about creating taxonomies.

Both are practical solutions to practical problems that occur when writing
code.

Inheritance is a result of several insights:

1\. It's convenient to be able to sketch out a protocol which a set of objects
will follow - without having to work out every damn detail about its
implementation.

2\. Most of the protocol can be implemented once and then reused.

3\. Often you want to use the default protocol implementation _with some
changes_. Instead of re-implementing the rest of the protocol, it's highly
convenient to be able to specify only the differences.

#3 is the core reason why inheritance was developed.

~~~
hota_mazi
Well said.

And #3 is also an area where Functional Programming falls completely flat.

There is simply no easy way in any FP language that I know to capture such a
simple mechanism as: "Reuse 90% of this piece of code but alter just this
10%".

Specialization is a very, very powerful aspect of OOP, one that's extremely
easy to explain and which comes in handy to model a surprisingly wide variety
of problems.

~~~
colllectorof
Functional programmers will reply that you can use partial evaluation and
higher-order functions to do that.

The sad reality is that since so many people are only familiar with the
strawman version of OOP rather than the real thing intelligently discussing
the advantages and disadvantages of these paradigms is very hard.

~~~
hota_mazi
Yes, I've heard them say that indeed. They often gloss over a lot of issues
about these.

For example, partial evaluation is limited by the fact that parameters need to
be ordered a certain way and you can't realistically cover all combinations.

Higher order functions don't enable any kind of useful specialization at all.
And of course, all modern OOP languages also support higher order functions,
so they are the ones giving you more tools.

~~~
nitrogen
Do any functional languages support partial evaluation using named parameters?
That would solve the parameter ordering complaint.

As for higher order functions you would write a function that does the 90% and
accepts a function parameter for the other 10%.

~~~
hota_mazi
> As for higher order functions you would write a function that does the 90%
> and accepts a function parameter for the other 10%.

Surely you see how this doesn't scale, right?

You would need to first write your code, then abstract every single piece of
it as a call to a function passed in parameters. Now your function is
accepting five different functions in parameters, and calls them.

This is a terrible and impossible to scale way to emulate class
specialization.

~~~
tome
So put those parameters in a single record type and just override the 10% of
them that you need to.

~~~
kragen
Abadi and Cardelli identified some ways that this solution falls short—in
particular, the self parameter isn't covariant—and how to fix them.

------
ben509
> You can’t add code to ducks.

> You can’t refactor ducks.

> Ducks don’t implement protocols.

> You can’t create a new species in order to separate some concerns (e.g. file
> I/O and word splitting).

It's odd he makes these complaints, because the comment he's responding has
this caveat:

> unless they are talking about writing a clone of The Sims or something

In the context of a game or simulation, such classes can absolutely do all
these things. And those seem entirely reasonable ways to teach someone about
programming, while being more accessible and engaging than "let's talk about
how to write an IO stack." *

> Penguins don’t implement the “fly” method that can be found in birds.

That's an important issue, though, which an OO tutorial needs to deal with. It
points at two major problems:

1\. The circle-ellipse problem[1].

2\. That nominative types have all the inherent problems that taxonomy has.

And since one solution is "duck typing"[2] it's worth noting that it's
entirely clear what it means, despite being named after ducks.

[1]: [https://en.wikipedia.org/wiki/Circle-
ellipse_problem](https://en.wikipedia.org/wiki/Circle-ellipse_problem)

[2]:
[https://en.wikipedia.org/wiki/Duck_typing](https://en.wikipedia.org/wiki/Duck_typing)

* IO stacks are good to learn, but to do them in OO you have to understand IO first, and though it's very satisfying when you get tricky IO code right, it's not really something you can show to your friends.

~~~
overgard
Experienced modern game programmers would never write a "Duck" class though.
For instance, in Unity, it would be a set of small components representing
narrow behaviors attached to a generic scene graph object. So the "Duck" would
only exist as a data object that happens to have maybe a unique Quack
component, along with a lot of common non-duck components like MeshRenderer,
AudioSource, Collider, RigidBody, etc. You would see similar things in
something like Unreal, or even in-house engines. The implementation is likely
also to be way more interested in acting on aggregate data streams rather than
enforcing strict encapsulation and object boundaries and such.

It's still very OOP, but not in the sense of representing real-world
taxonomies.

I know there's an argument that this real-world metaphor is good for
beginners, but at least in my personal experience I don't think that's the
case. I remember when I was a kid, my dad tried to teach me coding with a lot
of object oriented examples with like Cats and Dogs and stuff. He was really
well meaning, but it never really made sense to me. I only kind of "got it"
when I did something nobody would recommend anymore, and learned QBasic, and
wrote a bunch of ghastly code with goto's all over the place and practically
everything being a global. Awful code, but 10 year old me was able to reason
about that a lot easier than polymorphism/encapsulation/scoping/etc.

~~~
eckza
> I only kind of "got it" when I did something nobody would recommend anymore,
> and learned QBasic, and wrote a bunch of ghastly code with goto's all over
> the place and practically everything being a global.

An aside: It's okay to learn that way, when you're 10.

A lot of my own big programming revelations have come from ignoring best
practices and accidentally trying to implement or construct them from first
principles once my problem becomes unmanageable.

"Doing it wrong" is an even better teacher than "doing it right all of the
time", because the mistakes you make can lead you to a deeper understanding of
why things are done a certain way.

~~~
overgard
Totally agree. I think we make a mistake trying to harp on doing things
"right" too much for new programmers, because they end up with analysis
paralysis.

~~~
TeMPOraL
That's my current approach to teaching people programming concepts. I try to
provide an example of _not_ using that concept, point out the quickly growing
complexity of the code, and then show how that complexity can be reduced with
the new concept I'm introducing.

(And yes, as a kid, I was hurt by all those "Cat : public Animal" examples
too. It took me many years before I figured out _why_ they didn't work in
practice for me.)

------
hota_mazi
The article completely misses the point because it sets up a large amount of
straw men that are completely unrelated to the point

The fact that "Car extends Vehicle" is sometimes a subpar modelization has
nothing to do with OOP or inheritance and everything to do with the fact that
the English language is not specific enough to describe what a Vehicle is
well.

Same goes with "Duck extends Bird". Yes, there are a few birds that don't fly.
This problem has nothing to do with programming languages, inheritance, or
OOP.

I still find these two examples, "Duck extends Bird" and "Car extends Vehicle"
as extremely powerful to teach beginners what OOP is about.

Like all metaphors, they tend to leak if you push them too far, but they do a
splendid job at introducing beginners to the concept of OOP, which is going to
serve them well for probably most of their professional life.

------
dang
Discussed at the time:
[https://news.ycombinator.com/item?id=2914405](https://news.ycombinator.com/item?id=2914405)

------
rdiddly
Oh my god, not all birds fly, it ruins the whole thing!!!!!

No, it's a perfectly fine place in the analogy, to have a teachable moment.
Since not all birds fly, just don't make flight part of your base class. I
mean? Or get clever and have flighted and flightless bird classes inherit from
Bird? If you want to be that much of a pain about it, you can; the paradigm
supports it.

------
Ididntdothis
I tend to agree. The “duck extends bird” examples sound good at first but they
have done a lot of damage to OOP.

~~~
hota_mazi
I find this a largely unsubstantiated claim, much like the "Once you learn
BASIC, your brain is damaged beyond repair" from Dijkstra that is so
depressingly repeated over and over, and which is complete nonsense.

These are introductory metaphors that help people get up to speed with a
complex concept. You refine your understanding of these as you become more
expert on the subject.

~~~
overgard
I definitely agree that like these things aren't going to cause any sort of
lasting brain damage or something. It gets overwrought.

I think that the taxonomy thing is kind of harmful though in that, as far as I
can tell anyway, it only seems to be now that a lot of programmers are coming
around to the idea that modelling things are taxonomies is less useful than
other techniques.

Some code sins are pretty easy to cleanup: if someone writes a function that's
doing too many things, it's not too hard to break it up, or if someone names
things badly, usually it's enough just to rename it to better concepts. But
deep inheritance hierarchies are often a massive pain to clean up, if you can
even clean it up at all (outside packages might come to depend on your weird
structure for instance).

------
jrochkind1
This is good.

I've even seen OO tutorials which make it explicit to give the bad advice that
all your objects should match real world _things_.

This does not match my experience of OO programming or what the actual
challenges or rewards are:

> We make class hierarchies in order to simplify the code by allowing
> different parts of it to be changed independently of each other, and to
> eliminate duplication (which comes to the same thing). Without any context
> as to what the code needs to accomplish, you can’t make a judgment about
> whether a particular design decision is good or bad.

YES.

------
crtlaltdel
i sat down with tech yourself java in n-days (forget the exact title) around
1998/99 and promptly returned the book because of my frustration with the
`vehicle->wheeled vehicle->engine powered vehicle->motorcycle` explanation of
OOP. i had been using a niche OOP lang (lpc) for quite a while and the
examples in that book felt oddly ridiculous. just my opinion (at the time),
but it certainly did not resonate with me

------
kizer
Geez, chill out. I can't stand profanity.

~~~
inopinatus
Pot, kettle, black. Blasphemy is a subclass of profanity.

~~~
kragen
“Geez” is a minced oath designed specifically to avoid blasphemy—avoiding it
by a millimeter, to be sure. Even some devout Christians say things like
“gosh”, “darn”, and “geez”.

~~~
inopinatus
_" Overhead, without any fuss, the stars were going out"_

I once knew a baptist preacher who was a serious student of theology and moral
philosophy. He liked to discuss the distinction between theology and law,
particularly when framing behaviour as the imperative expression of faith, and
not faith as the expression itself. Needless to say, the parishioners loathed
him and he was hounded out for exposing their constant hypocrisy. Also
possibly for declaiming in classical Greek on a Sunday morning; he was truly a
latter-day Socrates.

My wife and I recently re-watched that unfortunately truncated classic,
HBO/BBC/Rai's _Rome_ , and were once again thoroughly entertained by the
multitude of colourful epithets. Sadly, exclaiming "by Juno's cunt!" during a
contentious meeting of the audit sub-committee or weekly retro would require
more explanation than I'd care to give in context. And yet, a devout Christian
should have no problem with this, at least on a theological level, since no
scripture is violated.

~~~
kragen
Landīca!

Some Christians aren't in favor of cursing in general, even if it's not
blasphemous. My best understanding is that they feel that it expresses a lack
of gratitude for the blessings they have—that, at least for a moment, you are
forgetting that every moment of life is a miracle, allowing yourself to become
enslaved to your wrath, which is of course a sin in standard versions of
Christianity. (This does of course pose some difficulties to reconcile with
the stories of cursing the fig tree and the money changers, which the
Christians resolve in various creative ways.)

