Classical inheritance is obsolete

Eric Elliott eric at ericleads.com
Sun Jun 30 14:53:23 PDT 2013


Brendan,

You seem to only be replying to the most recent comment in this thread, and
not considering the objections that I raised at the beginning of the
thread. My argument is that class isn't just a little bit of sugar. I
believe that counter to its goal, it will reduce programmer productivity by
causing code arthritis, duplication, and forcing refactors that would not
be needed if people instead leaned on mixins, functional inheritance, and
other compositional patterns that are already easy to implement in
JavaScript.

I further argue that a programming language has a UX, and good UX design
should involve creating a pit of success that users fall into. It is my
assertion that class is a pit of dispair, that so frequently leads people
down the path of wrong design that is *hard to fix* down the road, it
should not exist in the language at all.


"I get the sinking feeling that someone has had a bad time drinking too
much Java or C# OOP-booze and, in the manner of a reformed drunk, wants us
all to do things the hard way when making prototypal inheritance patterns
with constructors, static and prototype methods, |super|-done-by-hand, etc."

I don't want people to do things the hard way. I want us to give people
easier ways to use patterns that are less likely to lead people down the
path of poor OO design. I go into much more detail about the perils of
class in this Fluent talk: https://vimeo.com/69255635

All of those perils exist in the current ES6 class spec, not just the way
it's done in Java or C#. Yeah, I had a bad time with Java and C++ in the
90's, but I've been programming JavaScript web applications since the late
90's, and having a really good time of it, until popular libraries started
incorporating class-like patterns. I got over my Java hangover more than
ten years ago. The headache I have now is caused by people mimicking
class-like constructs in JavaScript, very similar to what ES6 intends to do.

Backbone making .extend() essentially a required mechanism has been
particularly problematic in several different code bases that I have been
involved in.

Unfortunately, the problem is that requirements change over the lifespan of
an application, and what start out as simple models frequently evolve into
complex models, where single-parent hierarchies fail. Eventually, all
single-parent hierarchies are wrong for new uses.

I know that JavaScript doesn't lose its dynamic nature when we add class,
but, to bring back an earlier example, say you start with:

Animal
* Walking
  * Human
  * Ape
* Flying
  * Bird
  * Bee
* Swimming
  * Fish
  * Whale

Now you need alligator and duck. Alligator clearly needs walking and
swimming, so you go to re-implement them as mixins, but now you have to
refactor all the animals that already rely on those features -- or you end
up reimplementing the functionality as mixins, and now you have the same
features in two different places -- a violation of DRY. This is the
duplication by necessity problem.

You have to refactor everything, or live with a design that is overly
complicated and error prone.


"I observe that many other JS hackers have no such negative hangover-like
reaction, and on the contrary say they could use a little sugar, and even a
bit of the strong stuff (e.g., small kernel extensions such as |super|) in
the punch."

It is my assertion that those same hackers would have an easier time if
we'd just give them better ways to work with prototypes, mixins, and
functional inheritance. For an example in code, see Stampit:
https://github.com/dilvie/stampit


More reading on the perils of class:

http://davidwalsh.name/javascript-objects (three part blog post by Kyle
Simpson)

http://en.wikipedia.org/wiki/Call_super - Super is a code smell


The gorilla/banana problem

"The problem with object-oriented languages is they’ve got all this
implicit environment that they carry around with them. You wanted a banana
but what you got was a gorilla holding the banana and the entire jungle." -
Joe Armstrong

This is a great description from "Design Patterns" (GoF) -

"Once the software has reached adolescence and is put into service, its
evolution is governed by two conflicting needs: (1) the software must
satisfy more requirements, and (2), the software must be more reusable. New
requirements usually add new classes and operations and perhaps whole class
hierarchies. The software goes through an expansionary phase to meet new
requirements. This can't continue for long, however. Evuntually the
software will become too inflexible and athritic for further change. The
class hierarchies will no longer match any problem domain. Instead they'll
reflect many problem domains, and classes will define many unrelated
operations and instance variables."

This never happened to me in JavaScript until I worked in code that used
things like John Resig's Simple Class Inheritance, and Backbone's
.extend(), rather late in my JavaScript career. But of course, we were
using objects and inheriting functionality long before those came along --
we were just using the simple patterns that already existed in JavaScript,
simple single-parent prototypes, module-pattern style modules, and dynamic
object extension (copying properties from one object to another).

No, my hangover is not from Java. It's from class in general -- and we're
about to share that hangover with a whole lot of developers who could have
easily avoided it otherwise.

When you put prototypes in JS, and made objects extensible at run-time, you
did something remarkable. You made classical inheritance obsolete by
bringing these ideas to the mainstream. Now you're arguing to take a step
backwards. I say, let it die. It's had a long life. It's time to let it go.

- Eric


On Sun, Jun 30, 2013 at 10:41 AM, Brendan Eich <brendan at mozilla.com> wrote:

> [Fixing empty subject.]
>
>
> Chris Ryan wrote:
>
>> Do we need classes at all?  In my opinion, given that the concept is
>> implemented in a clear manner and it is possible to be powerful enough
>> to be of use in favour of prototyping (and developing based on the
>> prototypal concept instead), then yes, it would have my support.
>> However, my major gripe with the current classes proposal (and in fact
>> with a few other proposals too, but that's a different story) is that
>> it's just syntactic sugar added for the sake of it - it doesn't add
>> any sort of functionality that cannot be implemented another way with
>> the current toolset, and this contraption will only add complexity and
>> confusion to the language.
>>
>
> No. Complexity would come from adding new kernel semantics (what's left
> when you boil away all the non-primitive forms). Yet you accuse us of doing
> anything but adding new kernel semantics ("it's just syntactic sugar"), so
> you're selling a contradiction here.
>
> As for "confusion", manually implementing |super| and getting it right is
> a confusing and error-prone process. In fact |super| is a case of a (small)
> extension to kernel semantics in ES6, but this tiny under-the-hood
> complexity produces a net savings by eliminating the greater user-facing
> complexity inherent in hand-coding |super|.
>
> Anyone who thinks |class| came from Java is not paying attention. Python,
> Ruby, and other languages (such as CoffeeScript, inspired by Ruby and JS
> with a bit of Python) have |class|, but they are dynamic. What's in a name?
> It depends, I think, on what you were taught.
>
> I get the sinking feeling that someone has had a bad time drinking too
> much Java or C# OOP-booze and, in the manner of a reformed drunk, wants us
> all to do things the hard way when making prototypal inheritance patterns
> with constructors, static and prototype methods, |super|-done-by-hand, etc.
>
> I observe that many other JS hackers have no such negative hangover-like
> reaction, and on the contrary say they could use a little sugar, and even a
> bit of the strong stuff (e.g., small kernel extensions such as |super|) in
> the punch.
>
> /be
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130630/8a953de8/attachment.html>


More information about the es-discuss mailing list