
In search of the perfect JavaScript framework - jsargiox
https://dev.opera.com/articles/perfect-javascript-framework/
======
danabramov
_> We want to apply values to variables and get the DOM updated. The popular
two-way data binding should not be a feature, but a must-have core
functionality._

Strongly disagree. I find one-way bindings and one-way data flow much easier
to reason about. A little less boilerplate code is not worth mental overhead,
cascading updates and hunting down the source of wrong data in my experience.

What _is_ important is _not updating the DOM from the code and instead
describing it with a pure function_. React, Cycle, Mithril, Mercury do it, and
it's time we get used to this. _This_ is the real timesaver, not two-way
bindings.

`Object.observe` is the wrong way to approach this problem. If you own the
data, why invent a complex approach to watch it, if you could update it in a
centralized fashion in the first place? Here is a great presentation on that
topic: [http://markdalgleish.github.io/presentation-a-state-of-
chang...](http://markdalgleish.github.io/presentation-a-state-of-change-
object-observe/). I strongly suggest you read it ("Space" to switch slides) if
these ideas are still alien to you.

Even _Angular_ is abandoning two-way bindings.
[http://victorsavkin.com/post/110170125256/change-
detection-i...](http://victorsavkin.com/post/110170125256/change-detection-in-
angular-2)

I, for one, welcome our new immutable overlords.

~~~
dustingetz
While I have been using React since it launched in May 2013 and I agree with a
lot of what you said, using words like "right" and "wrong" doesn't help. React
is a great way to write applications but it isn't the most mature library
ever, and the junior developers I worked with had quite a bit of trouble
working with it for a while because functional programming is so _different_.
The ecosystem is filling in, things are great, but "you are wrong and I am
right" harms as much as it helps.

~~~
danabramov
Of course there isn't a “right” or “wrong” way. I'm sorry I didn't write it
more clearly.

Approaches like jQuery soup or making SQL queries from PHP templates aren't
“wrong” either. They are friendlier to beginner, too.

When I wrote “wrong” I meant “in my experience, inferior for building
applications with complex stateful user interfaces and later maintaining them
for a period more than several months in the face of changing requirements”.

Also, I'm not talking specifically about React. Of course it has its own
shortcomings. All I'm saying is that relying on `Object.observe` and giving
out global state to all components to mutate is the same as using global
variables throughout the program. I don't know whether it is helpful to call
global variables “right” or ”wrong” but I'd certainly stay away from them when
there are ways to achieve the same without future maintenance nightmare.

------
ef4
> "Abstraction is dangerous"

The fact that Javascript people keep saying this with a straight face is
getting really absurd.

You _do_ realize Javascript is also just an abstraction, right? And that the
browsers that run it also abstractions, and the operating systems, and the
kernels, and even the hardware itself has multiple layers of abstraction?

"Abstraction is dangerous" is just fundamentally wrong. Abstraction is the
only way we get anything done.

What you really mean to say is that bad abstractions are bad. But stated so
clearly, it becomes obvious that it's a tautology. Well-designed abstractions
that leak as little as possible are essential to everything we do.

This stuff matters, because instead of having stupid arguments over "how much"
abstraction we want (which really boils down to 99 layers vs 100 layers) we
should be debating _exactly what_ abstractions we want.

~~~
juliangregorian
"Black boxes are dangerous" is maybe a more precise way of expressing the
concept. I don't think the author literally believes you must be writing
machine code.

~~~
ef4
If black boxes are dangerous then you really should be writing machine code.
Which is absurd of course, and demonstrates that black boxes are a very good
thing.

Javascript itself is a black box. It would totally suck if you had to know how
it's implemented inside to use it.

~~~
kristopolous
Ok let me try. Bad abstractions are bad.

Additional complexity without additional functionality, increased dependencies
without increasing stability, poor documentation and buggy implementations;
strongly coupled things which have no business being coupled and overt
assumptions on what kind of application you are writing and how you ought to
structure it.

They have fundamentals which don't interact with anything else - events that
won't be caught, arrays that use their own iterator, etc.

They decide to suppress language features like console logging and replace it
using different names. You never learn this by reading the outdated
documentation but by startling discoveries 45 minutes into what ought to have
been a 15 second bug.

And let's not get started on how utterly useless the call stack or object
inspector becomes.

They presume there are fewer coherent approaches to programming in a language
then there actually are so they shoehorn you into writing things in one
specific poorly documented, buggy, highly complex, inappropriate, monolithic,
and fragile way.

One of the main arguments for the abstraction approach is that they assist
average programmers like a golfing handicap. But the reality is that the
quality of the programmers work remains the same - but now with the abuse and
misuse of the language AND a convoluted abstraction. You are far worse off.

The historical problem is that these things despite all of these clear flaws
become immensely popular - each one for about 6 months.

And then your business critical application gets locked in. Locked in to the
hottest framework from 5 years ago.

Awesome

btw, I tweet about my hatred of this specific topic here:
[https://twitter.com/frameworkhater](https://twitter.com/frameworkhater) ... I
think a proper manifesto may be in order.

~~~
z3t4
I can see all sides of the arguments here. I do love API's, but I hate
"frameworks", especially when they consist of useless functions like

    
    
      function _MY_framework.enterprise.displayMessageInConsole(msg) {
        console.log(msg);
      }
    

That does something that would actually be easier in vanilla JS. All years of
writing JS may have made me blind, but that's how I see most JS frameworks.
Mostly useless.

That said, manipulating the DOM in JS is a PITA. I can totally understand why
you would want to do it another way.

I guess the DOM is not meant to be manipulated with ... And breaks if JS is
turned off.

I think in the near future in maybe 5-6 years we'll see apps that are a mix of
Browser and Native. That has the protected environment like a browser, that
ask for permission to use hardware features, that can be accessed through high
level API's, have native performance and run by typing an domain address much
like WWW.

------
carsongross
My theory is that, for much of the web, the perfect javascript framework is
_no_ javascript framework.

Get rid of all the abstraction, local state, dependency injection, symbol
management and so on. Take HTML/HTTP seriously and think about REST in terms
of HTML rather than JSON.

That's intercooler.js:

[http://intercoolerjs.org](http://intercoolerjs.org)

Here's an image I tweeted trying to explain how to get there mentally:

[https://pbs.twimg.com/media/B9QNU-
ZCQAECP-K.png:large](https://pbs.twimg.com/media/B9QNU-ZCQAECP-K.png:large)

Yes, it's a simple model. And no, it doesn't work for every app. But many apps
would be infinitely simpler and more usable in a browser by using this
approach, and almost _all_ apps have some part of them that would be simpler
to implement using it.

~~~
thirdsun
As a developer that recently made the transition from FileMaker, which is very
user-friendly but limiting, to Rails, I love the new possibilities and the
fact that Rails provides nearly everything I need and comes with established
best practices, but I'm always a little helpless when interactivity (without
reloading the page) is required. The apps I'm working on (internal, business
apps) mostly work perfectly fine with a document-based approach and most
features can be integrated as simple CRUD actions, but from time to time I
need just a little interactivity - like in a classic scenario of an order with
several line items that needs to calculate and display totals in a form as
soon as the input changes. It's that simple, no need for a framework, even
most libraries feel overblown for that use case.

I looked at various data-binding javascript libraries, but they all seem like
targeting much bigger problems than mine. So I resort to classic jquery, data
attributes and ajax calls, but it feels very messy, like a hack not intended
to work that way. It may be the fact that I'm new to this but it feels as if
I'm missing something very obvious whenever I have to deal with that kind of
very basic interactivity and dynamic. It's a simple form that temporarily
needs to calculate and process inputs until the user saves the record and
solving this seems way too complicated and messy. Are there any options for
those simple cases and apps that otherwise would do just fine with a document-
based architecture?

~~~
lastofus
I found Knockout to be a great middle ground for when "I can do this in
jQuery, but it's gona be messy" and "I'm building a SPA".

It hits the sweet spot between easy learning curve, abstraction, and
interacting with the DOM nicely.

Sadly, it's not as hip as React/Angular/Ember these days.

~~~
muraiki
I've also had a good experience using Knockout. I used it to add some
interactivity to a largely static site, and then expanded its use to create a
fairly complex management interface. It's easy to pick up with great
interactive tutorials on the web site, and with component support in the
latest version you can build some larger web apps.

Microsoft uses it their recent remake of their Azure portal; this page has a
video on building large apps with Knockout:
[http://jbeckwith.com/2014/09/20/how-the-azure-portal-
works/](http://jbeckwith.com/2014/09/20/how-the-azure-portal-works/)

------
drawkbox
As long as your javascript framework is a micro framework and not a monolithic
one, the abstraction does not make the project foggy.

Building the core and then using micro frameworks or components like react,
jquery, etc leads to less walls as swapping is easier as time progresses.

You don't want to be caught high and dry stuck in years of monolithic to
cleanup when the fad dies and at that point having abstracted away everything
you need to know.

Outside of javascript, .NET WebForms and Drupal are classic examples of too
much abstraction in monolithic fashion (those poor bastards stuck there - dead
man walking), Angular might be another. The whole time you spent building
addendums and machinations to a framework, not building the core of what needs
to be known.

If the framework changes everything you do and abstracts core logic or the
systems you are building doing things without you being aware, it might be
easy to start 90% but there are gonna be problems and eventually walls and
walls against you.

The only thing that should be monolithic and the base is programming languages
and platforms. Everything else should be micro components or messaging.

------
beat
It's a thought-provoking article, but I would also like to see something about
React in it. It seems to me that React is a very pragmatic way to get around
the global complexity-driven performance issues with DOM manipulation.

When we're coding, we're optimizing for a couple of different things, really.
First is real-world performance (represented by slowpoke DOM manipulation).
Second is programmer performance (represented by inappropriate abstractions).
A lot of things we can do in Javascript to make programming less difficult and
complex result in poor real-world performance, and vice versa.

But what do I know? I'm not by any stretch of the imagination a Javascript
expert.

------
hippich
I yet to find "perfect" JS framework. I bet, it will never happen.

Nevertheless, I have a favor to ask any framework developer out there -
please, make it disassemblable and usable piece by piece outside of framework.

OP was right - sometimes i find some aspect of framework nice, but more often
than not it is monolith part of the whole framework, which as a whole I
dislike.

ps: current combination it seems to fit my mind workflow is Backbone (models +
collections) + Ractive.js (Views) + Machina.js (for routing and defining
"controllers"/states.) Although I am looking to use something else besides
Machina.js in next project, as I want to have hierarchy now. And since it is
all loosely coupled, I can replace parts.

------
tel
The whole "abstraction is dangerous" spiel is so wrong (imo) that I don't even
know how to respond to anything that follows.

The primary complaint appears to be that abstraction eliminates your ability
to operationally trace the meaning of a program. This is true, but sacrificing
operational denotations only hurts if you replace it with nothing else— _and
abstractions of general purpose languages are almost always more interpretable
than the operational denotation of the base language itself!_

Of course, there are always places for poor abstractions. I am not talking
about these. Abstractions which are intentionally opaque, have confusing
action-at-a-distance, etc---you're bringing down the name of abstraction in
general. "Leaky" is insufficiently demeaning.

A good abstraction will have its own semantics. These can be equational,
denotational, operational, what-have-you but, essentially, these semantics
must be easier/simpler/more relevant than the semantics of the base language
they're embedded in. Otherwise why abstract?

So what does React give you? It gives you, more or less, a value-based
compositional semantics. Components have some "living" nature (an operational
semantics w.r.t. to state) but they're mostly defined by their static nature.
Because you can build whole applications thinking only about the static,
compositional nature of components you can take massive advantage of this
abstraction.

Ultimately, _you do not want_ operational semantics for React. This is what
gives us React Native, background rendering, and probably what will lead to
sensible animations (in time). To define operational semantics, especially
ones which have to look like or (worse) be identical to those of Javascript,
would destroy almost all possibility of extension. At the cost of making
things more complex and harder to reason about.

All so that you can just stick to "obvious" Javascript base operations.

------
djabatt
Where does react.js fall in this discussion? Or does it? Just reading a lot
about react.js this week.

------
wwweston
> Abstraction is dangerous

True statement. Of course, it's _more or less_ true, depending on how much the
abstraction you're using leaks. Few (if any) abstractions completely
encapsulate complexity, almost all will leak. But there's a range. Some
abstractions elegantly cover a modular portion of your problem space and do it
so well you only rarely have to think about what's going on under the hood
(and will even produce effective clues as to what's going wrong when something
does go wrong). Some abstractions awkwardly cover only part of a modular
portion of your problem space, require a high intellectual down payment to
even start to use, have gotcha cases that chew up performance or even break
things, and require continual attention to what's going on just to keep
development going.

Most are probably in between.

I think this is what JWZ is talking about in his famous "now you have two
problems" assessment of regular expressions. I don't read him as saying
"regular expressions suck," I read him as saying anything but tools from the
high end of the abstraction quality spectrum means now you have two problems:
(1) the problem you started with (2) the problem of keeping the model/details
of how the tool works in your head. Regular expressions are arguably in the
(maybe high) middle of the spectrum -- they may not cover your case well
(ahem, markup) and they can send your program's performance to hell or even
halt it if you don't know what you're doing.

Now, they're also broadly useful enough in all kinds of development that the
benefits go up with the costs and so they're probably worth investing in
anyway, as part of a suite of other parsing tools/techniques. So I'm not
bringing the topic up to bash them.

But to take us back to the topic, I might be bringing it up to question the
ROI of popular JS frameworks, which, as far as I can tell, are generally not
at the the high end of the abstraction quality spectrum, don't have the broad
usefulness of regular expressions to recommend them, and may not even survive
longer than a handful of years.

~~~
ef4
No, it's not a true statement. It's fundamentally wrong. Because if
abstraction is dangerous, we should all be laying out transistors by hand
instead of writing code.

People get so comfortable with their familiar abstractions that they forget
they're still abstractions.

Taking the article as an example, even his "less abstracted" examples are
_absurdly abstract_ , and I doubt anybody here can really say for sure how
they work completely, underneath all the abstractions. That's a good thing,
because it lets us get things done and express ideas in hardware-independent
ways.

~~~
Bahamut
Abstractions are dangerous - if you abstract wrong, your code is potentially
worse than the unabstracted version since it is easy to impose an abstraction
where there is none, but a poorly abstracted component is harder to correct.

~~~
aikah
ANYTHING done wrong can be dangerous,abstraction or not. The problem isn't
abstraction but "poor code",whatever it means. spec writers chose to go with
the DOM,which is a poor API and it led to things like DHTML because DOM just
sucked. It was clearly not made for what devs are doing with the web
today,thus the need to abstract a bad API with a framework or a library.

I bet you don't write web apps adding DOM nodes to the DOM document.You're
already using an abstraction if you're using any DHTML api.But you didn't know
that.

------
iEchoic
The Knockout example in this article is a bit strange - Knockout is not a
framework (it is explicit about this) - but besides that, Knockout components
actually do allow the "framework" to decide when things are instantiated.

------
akrymski
One super simple framework is
[https://github.com/techlayer/espresso.js/](https://github.com/techlayer/espresso.js/)

It's a bastard child of React and Backbone.

------
thekingshorses
I like the direction author is going. I have used similar methodology
designing my applications (for mobile), simple, micro libraries, one way data
binding.

[http://hn.premii.com/](http://hn.premii.com/)

[http://reddit.premii.com/](http://reddit.premii.com/)

* I have bunch of helper functions (UI and non-UI). Each function define in its own file and independent (easy to unit test). Personal library like jQuery but not a jQuery replacement.

* App is route based. One route to many controllers. Each controller is a page/screen on mobile.

* There is only one model (API) that interface with 3rd party library. API layer talks to 3rd party library to get data or gets data from server directly, caches data, etc. Provides sync (Cached data) and async (Cached data or fresh from server) interface to controllers.

* There is a app class or I call it a page manager. Responsible for managing pages like ordering, loading, unloading etc (Kind of big and complex 200+ lines of logic).

\- Decides which page to animate in which direction on mobile (Loading new
page or going back).

\- Order of pages (Back button)

\- Passes events to its controllers

\- Decides which pages to keep in DOM, and which to remove.

\--- If you go from homepage to comments to profile page, all pages are in
DOM.

\--- When you go back to comments page from profile page, profile page will be
destroyed and controller will be notified. Same happens when you go from
comments to home page.

\--- If you go to same comments page again, it will be loaded as a new page.

* Controller:

\- Each controller may have multiple CSS and templates

\- Controller uses its template to render

\- Using sync API to get data to renders page.

\- If sync API returns no data, renders empty page with loading, and makes
async API call.

\- Controller are idle when transitioning (animating) from one page to another
on mobile. (Very important for smooth animation)

\- Simple but fat controllers

\- Controller handles events, UI logic

\- Self cleaning so that browser can collect garbage when necessary

I package app using node/gulp. Anything that is not specific to page/app
related, it becomes part of a helper library. Each app has its own model (Data
layer), and controllers. I use micro templates, precompile using node for
faster performance.

~~~
mercer
Thanks for creating hn.premii.com! About half my use of Hacker News is through
your web app. I even wrote a little bookmarklet that turns all links on
hn.algolia.com and hckrnews.com into links to your app when I happen to be
browsing on mobile! And I'm always happy to find out you introduced a new
feature (which I would like to see more regularly, not that I'm complaining!).

Alongside Alien Blue, your app is my most used app on my phone. Your work is
very appreciated!

------
itsbits
I don't agree with DOM event handling: setting events at every node comes with
a cost. And I think you forgot to mention the performance issues with that
approach and so now a days almost all frameworks prefer to event delegation.

I think author except in 1,2 points didn't bother to take side with
performance aspects.

------
RehnoLindeque
> We all like simple tools. Complexity kills. It makes our work difficult and
> gives us much steeper learning curve. Programmers need to know how things
> work. Otherwise, they feel insecure. If we work with a complex system, then
> we have a big gap between “I am using it” and “I know how it works”.

One answer to this problem of opaqueness in abstractions is having a well
defined denotational semantics. This makes it clear that something can work in
one way & only one way (without the need to dive into library internals). I
feel that Elm is doing a pretty good job of tackling this for GUIs and
signals.

------
fiatjaf
I don't think people use frameworks and abstractions because they have a
smoothier learning curve, or because they are simpler, but because of DRY.
After repeating the same pattern twice, the programmer turns it into a module
and abstracts it. After having a lot of modules, the programmer packages them
all in a framework. This is good for the author of those modules and the
framework, because he understand them, but not always for the outsider who
just looks at the complete framework and don't know what's inside.

------
mark_l_watson
A difficult article to write - I would not have tried. There are so many good
alternatives and choice depends on the application and available skill sets.

I spent time today working in Clojurescript which wraps the Closure library.
In the last month I have used Ember.js, Clojure with hiccup, and meteor.js. I
really like all of these tools and frameworks. I used to use GWT a lot, and
almost committed to Dart. So many good choices.

------
acdlite
Bad abstractions are dangerous. Good abstractions are empowering.

 _cough_ React Native _cough_

------
mathgeek
I was slightly disappointed that this didn't point to a 404.

------
closetnerd
This article reminds me quite a bit about Vuejs. Its got an interface similar
to Backbone but with the addition of two way data binding while also allowing
you to define web components style tags, attributes.

------
mperret
I like the structure of google closure, thoughts?

------
jcoffland
Vue.js meets most if not all the criteria outlined in this article. I've been
have great luck with vue.js after a nightmare of fighting with writing a big
SPA in Angular.

------
jbeja
The perfect JS framework won't exist until 2079.

------
rhapsodyv
I LOVE ExtJS!

