Thursday, November 21, 2013

ES6 - Really?

Everyone seems to be SO PUMPED UP about the upcoming ES6. All of these new features "everyone" has been begging for - they are finally here! JavaScript will finally be fixed (mostly)!

Let's start with the requirements for ES6.  There are only 3, so sounds simple enough.  Who could argue with 'New features require concrete demonstrations'?  This does not capture what I think (hope) it actually means:  New features require concrete demonstrations of their usefulness.  I do not care if someone CAN implement a feature, it needs to be proved to me WHY ES6 needs this feature.  Unfortunately I have yet to see that 'why' answered for most of the new features.
On to the second requirement: 'Keep the language pleasant for casual developers'  HOLY CRAP as a professional JavaScript developer this is the LAST thing I want to hear.  I do not mind if the casual developer enjoys using JavaScript but please do not cater to that person at the expense of someone who must use the language daily.  This requirement will come to bite ES6 in the ass with several of its new features as we will see later in this post.  Is this really a requirement for ES6?  That casual developers find it pleasant?  Wow.  Is this so they don't get scared off and start using Go/Dart/TypeScript/CoffeeScript??  Does the ECMAScript crew get paid per developer or something?
Finally the third requirement: 'Preserve the “start small and iteratively prototype” nature of the language' - YES!  I'm all in on this one.
So of the 3 requirements, 1 is worded strangely, 1 scares the hell out of me, and 1 I completely agree with - not too bad I guess.

The goals for ES6 all sound reasonable except making the language easier for code generators targeting the new edition.  Sounds like a cop out for Google & Microsoft to keep cooking up Go/Dart/TypeScript/CoffeeScript to run in browsers.  Or maybe ES6 is afraid if that if is not a goal Google will drop JavaScript support in Chrome for Dart or something and totally destroy JavaScript?  Who knows but that goal sounds 'political' to me somehow, not directly useful to the language itself and therefore should be not be baked into the language specification.  Maybe that's just the cost of doing ECMAScript business.

Ok on to the proposed ES6 features!

Block scoped variables
This is the first casualty of 'making the language pleasant for casual developers'.  Function scoped variables are 'confusing' so rather than actually have a professional user of the language actually LEARN THE LANGUAGE, let's try to make it easier for them. Now instead of only having to understand function scope, which of course they have to anyway, we must now also throw in block scope to make matters MORE CONFUSING.  Block scope and Function scope in the same language, in the same function, in the same block!  That won't be confusing at all.
Which is more prone to cause errors, only having to understand one concept or having to understand and be on the look out for two? But programmers already understand block scope?  Do they understand how it will play with function-scoped variables? Are people so lazy that they refuse to learn the actual language? I don't like Java because I don't want to learn about public/protected/private. Well TOUGH SHIT you have to because that is an integral part of the language. It's not like 'function scoped variables' are some hidden unknowable feature of JavaScript. There are TONS of books ready to explain in gory detail to you, dear professional programmer, what it is and how to use it. TONS of online material that will hold your hand and gently introduce you to the concept. 
The canonical use-case for this is the avoidance of creating a new scope within a loop when creating functions using the loop variable.  Fine I get that, it makes that single case slightly simpler.  But I do not think this feature is worth it just for that single useful case for which there are several well-known patterns for deal with this in JavaScript.
This is a completely unneeded 'feature' to fix something that is not broken. Merely a bone for lazy professional programmers to feel 'more at home' using JavaScript, professionally, in their job, for which they get paid (a lot) of money. Who just can't wrap their pretty little heads around a relatively simple very integral feature of the language despite TONS of material to help them. You think beginners are confused about function scope? What until we also throw in block scope.  And surprise!  You are going to have to learn about function scope anyway!  Ok need to cool down now.

This perl feature does come in handy and of course is an answer to the age-old interview question about swapping variables without a temporary variable. As for array destructuring I never liked how now one must rely on the order of values in an array when objects are a better semantic fit. Not hideous for small arrays, but over 2 or 3 elements you probably want an object anyway for sanity.  Us perl old timers have fond memories of deconstructing perl's 'date' method to pluck out the various pieces we needed.  Indeed most examples I've seen of this have employed 'date'-type operations.  It can be handy, it can be tricky.  It is however completely unnecessary.
Object destructuring makes the most sense looping but boy do all of the examples I've seen look confusing! This syntactic sugar may be pleasing to some eyes but to my old curmudgeonly ones it just looks more confusing and I will probably only use for simple cases if at all.  Again it looks more tricky than handy.  There is never anything wrong with being explicit, this feature will certainly not make the language any more pleasant for casual developers.

The Spread/Rest Operator
Related to array destructuring comes the 'spread' operator. This thing evaluates arrays in 'array context' as we'd say in perl ($array vs. @array). A perhaps useful but again completely unnecessary piece of syntactic sugar perhaps only added to confuse you further.  If you have to deal with arrays then pass them around as arrays. I have no idea what 'problem' this operator is trying to solve. It does, however, add to the cognitive overload that ES6 provides. This same argument applies when using the Spread operator as the Rest operator.  The fix here may just be finally making the 'arguments' array-like object an actual array and be done.

Oh boy these are fun. Proxies are best used for the fabled 'cross-cutting concerns' of application development land. Stuff like logging, debugging, security, &c are prime candidates for these constructs. Sounds reasonable and pretty modern on first blush - but we already have a pattern for these that work just fine: the Decorator. And the pattern is exceptionally easy to express in JavaScript (see here). Do we need actual syntax in the language to express this?

Method Definitions
The syntactic shortcut for defining methods in objects looks freakin weird. I know no one likes typing 'function' all the time (a job for IDEs) but is it really that bad that we need to introduce new syntax?

Object literal definition shorthand
More syntactic sugar, more confusion to save some keystrokes. Since when is being explicit so horrible?

Arrow Functions
Hey these aren't so terrible! Functions without writing 'function'! Returns without writing 'return'! I'm sure that will work out great for all the newbies out there!  But it gets much worse, using an 'arrow' function also lexically scopes 'this'.  This random confluence of 'features' really scares me.  Please tell me this will not be true of ES6 final.

Default Arguments
These are great - long live default arguments! Completely unnecessary of course but groovy.

Maps and Sets
Spectacular - love 'em - HOWEVER...

Holy Confusion Batman! I do not see the point of these at all except to incite mass confusion. Why should this be baked into the language with specific (confusing) syntax? These should remain userland, JavaScript is NOT (thankfully) Java - even in Java Iterators are not a core part of the language.  Again, no way should there be dedicated syntax for this trivial-to-implement feature.

Oh boy don't get me started. Has ANYONE come up with ONE LEGITIMATE use case for generators? "They are sort of cool" (and very confusing) does not count.  This harkens back to my re-writing of ES6's first requirement: Show me WHY is this necessary.  Plus, this will make causal developers sad and they will surely find generators unpleasant.

Class Syntax
This really makes me sad :'( sniff. Suddenly we are indeed turning JavaScript into Java after years of trying to tell everyone how different we are and what a bad choice of name 'JavaScript' was. 
Just like block-scoped variables this is a bone to lazy professional programmers who REFUSE to learn how the language they are using actually works. Prototypical inheritance is not that bad I promise.  Another casualty of 'making things pleasant'.
That said there is a more fundamental problem here: object hierarchies. They are hard to construct and maintain in any language. You should be minimizing their use and I'm sad that this new syntax may 'encourage' developers to object-ize their world, which is the path to madness (haven't we all learned that yet?). It ain't 1995 anymore; interfaces, decorators, and factories are where we are in 2013.

Prototype for
Wow this one is a biggie.  I can't decide if this is the operator I love to hate or the operator I hate to love.  In certain cases this operator will be awesomely spectacular.  However it will be abused.  It will be confusing.  I cannot decide if the extra complexity and misuse of this operator outweighs the benefits it will provide for a relatively few use cases.  If you look at this construct:

  Array.create=function(proto,props) {return Object.defineProperties(proto <| [ ], props)};

And think 'Oh this creates a sublcass of Array' then you are a sick individual.  Also the operator seems backwards to me, I guess the '<' is supposed to be like an arrow but it just reads backward to me.  Maybe native Hebrew readers will have a better time of it.

Something needs to be done here, might as well bake it into the language. Go for it! I like CommonJS but we will never agree so I beg of you ES6 authors pick something and stick to it and we'll all fall grumbling into line.  This is important and should be done in ES6.

API Improvements
Yes, Yes, and Yes!  We need more of this kinda stuff! Would love to see full perl regex support.

The End of JS?
The Sky Is Falling! Ok it's not. I'm sure all of the language nerds are enjoying themselves coming up with all of this stuff. And who am I to begrudge the biggest names in the JS industry, Mr. Eich and his dreams included?  It's his freaking language and if he wants to add generators then knock yourself out. But the JavaScript we have now actually works and is used by millions(?) of developers worldwide. Due to its unique place in the browser we do not really have a choice. Is JavaScript perfect the way it is? No. Does is need polishing? Absolutely. Does it need perl6-style treatment? Please no.
A stated goal of ES6 is making larger programs easier to write in JavaScript.  The new class syntax seems to be an anti-pattern for this goal for us minimal object/SOLID-types.  All of the added syntactic sugar also seem antithetical.  A Module specification is really all that is required here.
Finally I'd like to add that the ES6 specification is more than twice as long as the previous ES5 specification.  That also makes me sad.

So Now What?
JavaScript can use some tweaking - instead of morphing into Java I want to double-down on JavaScript.  Here is what we should do:

Make 'arguments' a real array
Seems like the least we can do.

Get rid of the 'new' operator
Ya I said it.  Get rid of it, we don't need it, we don't want it.  It only encourages 'object hierarchy' based thoughts which are naughty.  Bad 'new', bad.  We've got Object.create and soon the 'prototype of '<|' operator, 'new' can now be banished.  So while we're at it...

Dump Classes, Add Interfaces 
Classes are sad remnants of a once powerful sect that once ruled the universe, why would we want to pollute our language with them?  Prototypical inheritance + Interfaces + Objects es muy bueno.

Type Checking for 'use types'
Add a new 'type' pragma (a la 'strict') that enforces type checking.  Let's keep all rabid type checkers (looking at you Google and Microsoft) off our backs by throwing them a bone - give them an optional mode whereby types are checked.  Gotta keep them code generating transpilers happy.
I am surprised V8 and equivalent haven't gone off and defined their own pragmas already a la 'use types' to add non-standard functionality.  Maybe the specification itself should say 'you are not allowed to do this!'

Sum It Up
JavaScript is Good.  JavaScript is not Java.  Let's keep it that way!  ES6 is a mishmash of 'making the language pleasant for the casual user' (block scope & class syntax) and making functional programmers/CoffeeScript'ers happy (am not sure what else to call these features: iterators & generators & shorthand syntax) but unfortunately both attempts, yes, make me sad :'( sniff!

PS Thanks to Ariya Hidayat and his excellent blog to which I've linked to extensively in this post.  My complaints about new ES6 features in no way diminish the excellent work he has done explaining what these features are and how they work.  Thanks Ariya!  Now repeat those previous 3 sentences with Nicholas Zakas and his blog.