
Google SoundScript: faster OOP for JavaScript - jashkenas
http://www.2ality.com/2015/02/soundscript.html?hn
======
greggman
This makes sad, as Douglas Crockford said in this recent talk

> The prototypal school has a lot of advantages particularly compared to the
> classical school

> So in the classical school you have to create a classification of all the
> objects that are likely to be in your system. And, it's a lot of work to
> figure out what they all are and identify them and what their
> characteristics are and so on and then you have to determine how they are
> all related to each other, what’s going to inherit from what, what’s going
> to implement what, what’s going to interface with what, and that’s really
> complicated. And it usually happens at the beginning of the project before
> you fully understand what all this stuff means. So it’s likely your going to
> get the taxonomy wrong. It’s inevitable.

> And then you’ve got two hard choices. One is you have to live with a broken
> taxonomy and if you do that then with each new class you introduce things
> get weirder and weirder because everything’s wrong, or you have to refactor
> and refactoring is hard and it’s error prone and it’s another world of hurt.

> Those are your two choices and people who grew up in the classical school
> assume that’s just the way life is so no sense in complaining about it since
> that’s life.

> But in the prototypal school you don’t do any of that. You just make an
> object, if you don’t like the way it works you make another one and that is
> literally it.

> So you can tell people from the classical school “You don’t have to do all
> of that” and they go “Yea, I hear ya, but you still have to do it” and you
> say “no, you don’t have to do it” and they go “yea, yea, yea” (blowing you
> off)

> __And so that’s why I think classes in ES6 are a bad __part because they
> lock you into that paradigm.

> applause

> So when you’re locked in a paradigm like that, when you can’t see past it,
> you just have no understanding how miserable you are. And you’ll never know
> until you change your model

from
[https://www.youtube.com/watch?v=bo36MrBfTk4#t=28m50s](https://www.youtube.com/watch?v=bo36MrBfTk4#t=28m50s)

~~~
jashkenas
I don't mean to be argumentative (being argumentative on HN is so passé), but
what you just quoted is _so full of shit_ that I feel like someone is
obligated to comment.

In the prototypal model — as it exists in JavaScript — you _do_ do all of
that. You make a series of prototypes that you intend to use in your
application, and those prototypes (or classes), serve as the effective
taxonomy for many of the objects you're making in your app.

Classes in ES6 _are_ prototypes. They don't lock you into any such Java-esque
paradigm unless you're going to be willfully ignorant about them.

Please don't repeat baloney just because Crockford said it.

\---

For example, to be concrete:

    
    
        class Crockford {
          speechify() {
            return "...you're going to get the taxonomy wrong. It’s inevitable.";
          }
        }
    

A class. A terrible, inflexible, prototype-destroying, paradigm-locking-in,
JavaScript class. Eww, gross.

But wait! What's this?

    
    
        Crockford.prototype.speechify = function() {
          return "...the shape of an object can change at any instant, because \
                 someone can fiddle with the prototype.";
        };
    

You can have your classical cake and eat prototypal cookies too. Because in
any decent dynamic language, the two concepts are synonymous.

~~~
greggman
It's not baloney IMO. As someone who's coded C since the 80s and C++ since the
90s I find JavaScript massively freeing.

In C++ (and similar classical languages) in order to be able to pass in
different implementations of a class you need to create a base class or
interface. You don't need to do this in JavaScript.

In JavaScript you can build objects on the fly. In fact he goes on to say

> so I used to think that the important thing in JavaScript was prototypal
> inheritance I now think it is Class Free object oriented programing. I think
> that is JavaScript’s gift to humanity. That’s the thing that makes it a
> really interesting important language, is that it did that. That we can use
> functions in order to create objects and it simple and elegant and powerful
> and fast...

And it's true. Look at the mocking libraries for JavaScript. They're
sooooooooo much easier to write than anything for classical languages because
it's so easy to do in JavaScript. In my own experience I have a mutli-user
networking system written in JavaScript and a library in C#. To reimplement
the same things in JavaScript in C# is a huge amount of code bloat. I have to
make classes and meta classes and all kinds of other indirection just so I can
make an Event system that is generic. In JavaScript that's 2 or 3 lines

That we don't actually need all the structure to get shit done is what people
are finally coming to realize.

The problem with 'class' in ES6 is that it will prevent people from learning
this new, easier, faster, simpler way of working because instead they just
bring the classical baggage to JavaScript. That's in fact what most
programmers from classical languages do. It's what I did for years until I
started actually grokking JavaScript. ES6 "class" will only make it take
longer for people to actually get pass their old ways.

~~~
wvenable
> As someone who's coded C since the 80s and C++ since the 90s I find
> JavaScript massively freeing.

I've gone back and forth between dynamic and static and strict and loose in
every combination and I don't find the dynamic/loose to be particularly
freeing anymore. The problem is you can't really rely on anything. It doesn't
so much as solve the problem that Crockford is talking about, it just moves it
somewhere else. You don't have to refactor but you're going to end up with two
(or more) different things that exist at the same time instead of one.

> Look at the mocking libraries for JavaScript. They're sooooooooo much easier
> to write than anything for classical languages because it's so easy to do in
> JavaScript.

This is a great point and it's a perfect example of the advantages and the
horrors of the JavaScript model. A mock is supposed to be an object that does
something completely different (typically nothing) but otherwise looks and
functions like the real thing. Maybe just in one slight exceptional way.
JavaScript makes this easy. But it also makes it easy to make those same
changes outside of mocking and tests and that is just debugging hell waiting
to happen.

~~~
greggman
You can write bad spaghetti code in any language. You avoid that with style
guides, linters, and code review.

~~~
wvenable
I don't see how strict typing couldn't fit at the end of your list as well.

~~~
greggman
It could but some of us have had the experience of massive productive
increases in JavaScript over our decades of experience in statically typed
languages.

And note I'm specifically calling out JavaScript. Other dynamic languages IMO
haven't provided the same benefits because they're still following old models.

When you truly grok JavaScript and stop trying to use it like your other
languages it really starts to shine. It's not perfect but it is different.

------
cromwellian
I see the 'stricter' mode (without types) as a kind of asm.js assertion. The
code is 100% legal JS and will work on all JS VMs, you're just telling the VM
that it can assume you won't modify class prototypes after load. The VM can
check this assertion and fail if you violate it, and then run at fulls peed.

On other VMs that ignore "use 'stricter'" the same code runs, just less
optimized by the VM.

The stricter+types stuff will be harder to swallow by the community since it
extends the language grammar. That will break other VMs without transpilation.

Maybe they could do a "use 'stricter+asm'" which has the class-sealing
properties SoundScript, but with the type-declaration syntax of asm.js (|0, 0,
etc)

~~~
azakai
I'm still unclear on the relevant details, though. If this is just a hint - no
semantic effect - then JS engines already speculate and assume you won't
modify class prototypes after load. Such speculation is what JS engines put a
lot of work into.

Maybe the hint would justify more aggressive speculation, I suppose?

Or, if this is more than a hint - if it has semantic effects, like "use
strict" does - then this would be very different than "use asm".

I guess when more info comes out this will become clearer.

~~~
cromwellian
I'm guessing that it implicitly implies Object.seal() on all prototypes.

Any legal program that uses 'stricter' and depends on sealed prototypes would
be a legal program on a VM that ignores stricter, except in the case of bugs
where code was modifying prototypes when it shouldn't, but those would
presumably be caught during testing on VMs which did use it.

Presumably, "use stricter" on a codebase that contained attempted prototype
modifications would generate errors instead of silent failures.

I don't know the full reasoning behind this, but it might be more about
startup time than runtime speed. If you assume early-bound classes,
snapshotting becomes a lot easier, you can ahead-of-time trivially compile
hidden classes without having to discover them after the fact, and without
having to put in code to revert the assumptions later.

Seems like this would be a startup and memory win mobile web, especially if
you can easily snapshot a previously loaded app.

------
tracker1
IMHO for the most part, programming with classes in JS is just waiting for
pain. If you use generic objects for state, then compose your applications by
using generic functions passing in state, and any other arguments that
function needs to operate, it goes much smoother than OOP.

You can create wrappers by binding independent methods against said state for
composite objects with encapsulation... It tends to keep code cleaner and more
modular. Sometimes just thinking about the problem differently will lead to a
more elegant solution...

    
    
        var Promise = require('i-promise')
            ,getDealerPendingStream = require('./process-get-dealer-pending-stream')
            ,transformDealerPending = require('./process-transform-dealer-pending-stream')
            ,calculatePayment = require('./process-payment-calculation')
            ,logTransaction = require('./process-log-transaction')
            ,updateSalesforce = require('./process-update-salesforce')
            ,runPayment = require('./process-payment')
            ,logItemOutput = require('./process-log-item-output')
            ;
    
        module.exports = function(){
          return new Promise(function(resolve, reject) {
            getDealerPendingStream()
              .pipe(transformDealerPending())
              .pipe(calculatePayment())
              .pipe(runPayment())
              .pipe(logTransaction())
              .pipe(updateSalesforce())
              .pipe(logItemOutput()) //email notifications for processing errors (dataObject.error)
              .on('error', reject) //should never happen
              .on('end', resolve)
              .resume() // needed so last stream can process data
              ;
          });
        }

~~~
aikah
How would you write a GUI framework with this method? because that's where OOP
shines.Here,you're just doing sequential operations on a chunk of data.How
would you write layouts and widgets? people often forget that OOP was kind of
created because it solves the UI problem.

~~~
tracker1
You can still uses events and state against UI constructs without going full-
on OOP. An application can render in similar ways to how flux, mercury, elm
and other patterns are handled. (not suggesting a virtual DOM... but there's
more to an application than the UI alone, and there are more functional ways
to apply state and eventing to a UI.

    
    
        uicontrol.on('eventName', handleSomeEvent.bind(null, state, uicontrol));
    

In this case, you still have a uicontrol, that raises events, and can use that
to trigger a generic handler pre-bound against a given state. You can remove
this farther by having the handleSomeEvent being a method that is already part
of a state machine that is bound against an instance of said state.

If you follow 1-way dataflows (like flux) you can break some of the other
constructs down... just the same, the above example is not OOP, but can still
use UI events, and be composable.

------
adrianlmm
I thing this is a testament that strong typed is more desired than dynamic.

------
misfo
Could this be (partially) motivated by making Dart-compiled JS run faster in
Chrome?

------
chipsy
If I had to place a bet now, it would be on asm.js. It's the abstraction that
nobody wants but everyone can live with, because it takes the standards bodies
out of the equation on the higher level decisions that have to be done
differently per domain.

------
dracolytch
So there have been a lot of contenders to replace JavaScript, and it hasn't
budged from it's market seat at all. Here's why:

You can do almost anything in JavaScript these days. The down side? You can do
almost ~anything~ in JS these days. Including lots of stupid things.

Since JS works extremely well for user interaction, and is "good enough" for
simple object-oriented programs, it will likely never go away in the
foreseeable future in these realms. What I think things like SoundScript are
for, is 1) for people who are used to strongly-typed programming languages to
feel more comfortable on the web (which is actually pretty important), and 2)
for larger OO or enterprise-style systems that really shouldn't have been
written in JS in the first place (I'm looking at you Angular).

I wonder if it will end up like Go, though. An interesting language which
never gets more than a niche market.

~~~
smrtinsert
In my opinion Javascript is on its path to marginalization. Just glancing the
recent tooling options for ClojureScript and TypeScript, I'm pretty sure now
is the time to start putting your alt-js experience ahead of Javascript on the
resume. The syntactical checks are great (typescript ides) or instant feedback
(clojurescript figwheel) but for me the killer is the performance optimization
over 'raw' Javascript due to compilation optimizations.

Better tooling, better performance, why would I want to go back?

The language of the future includes a Javascript compilation target.

~~~
untog
Before you start talking about what to put on your resume, I'd look at what
job descriptions are asking for. I haven't seen many asking for ClojureScript
or TypeScript yet.

TypeScript (and to a lesser extent CoffeeScript) seem fine to me, but
ClojureScript looks very different to JS. I'd always advise someone to learn
JS first, _then_ your compiled language of choice.

~~~
smrtinsert
Which is why I said marginalization. Knowing Javascript is important, but I
believe a savvy team will jump on one these languages to turbo charge their
productivity.

~~~
colin_jack
Possibly, but you can argue the opposite. I've seen a bit of commercial
TypeScript and it's been horrific and to me just matched the anything but
Web/JS approach I was expecting.

I'd also worry that the TS community itself would risk marginalization, end up
as a small niche ghetto, with most of the interesting stuff going on in ES7+.

Hard to be sure but I wouldn't write off JS just yet, people have been doing
it for years as new/better (flash/silverlight/compile to JS) technologies have
promised to make it seem soooo 90s.

