
Announcing Amber.js - wycats
http://yehudakatz.com/2011/12/08/announcing-amber-js/
======
asolove
I know what you're thinking: great, another MVC library for Javascript. But
wait: Yehuda knows what he's doing, it will be interesting to see what Amber
includes.

As I've discussed before [1], the current discussion about MVC frameworks in
JavaScript is very superficial, and meaningful API differences between, e.g.
Spine and Backbone, are not sufficiently understood by people who are picking
between them.

Yehuda has a lot of experience thinking about framework APIs from the
standpoint of modularity, performance, and developer convenience.

He is absolutely right to emphasize that calculated properties and managed
attributes on the model layer are the key to easily building JavaScript
interfaces. The difference between nice MVC code and poor MVC code or jQuery
soup is the idea that in each method data is only flowing one direction:
nowhere are you manually updating both a UI and a data object. Two-way data
flows make up the majority of the code in non-MVC jQuery-oriented code. In
contrast, a robust model layer with lots of events is the best way to get code
reuse and composition.

[1] <http://news.ycombinator.com/item?id=3248552>

~~~
sid6376
I am new to web development and have just started using/learning javascript
and so my knowledge is limited, to say the least. But isnt what you are saying
easily achievable through backbone.js.(by calling a set on a model and
triggering an event which the view catches and updates itself.)

~~~
judofyr
Indeed. Bindings are just triggers that makes sure the data model is in sync
with the view. It's just for convenience.

There is also a model binding plugin to Backbone:
<https://github.com/derickbailey/backbone.modelbinding>

~~~
jashkenas
Just to be clear -- the Backbone.js "party line" is that automatic 2-way
binding between views and models is usually undesirable.

The model contains the "truth" -- the current state of the app. Views should
be bound to models and automatically update when the model changes.

But when the view changes, the reverse is not the case. You don't want every
checkbox click, radio button twiddle, and keystroke to be causing your model
to change ... thereby emitting changes which may cause other pieces of your
app to re-render, changes which may cause Ajax requests to persist the model
state to the server, and so on.

Instead, most apps have a "save" button for some changes, a mouse click for
others, or drag and drop, or a gesture, or an "undo" link.

It's much more convenient and flexible to allow your app to react to DOM
events as it needs to, instead of having specific model attributes hard-bound
to concrete DOM elements. ... that said, if the latter is your cup of tea,
there's a plugin for that.

~~~
grayrest
It took me a while to figure it out, but the model concept in Backbone doesn't
completely correspond to the model concept in Amber.

Backbone, at least as I practiced it, has a model that very closely
corresponds to what goes over the wire. You observe stuff on that, you react
to events, the event observers react and update the model and as a result the
model is sent over ajax.

Amber, again as I practice it, has a model that corresponds to the complete
application state of a particular component of the page. If you have a
checkbox that doesn't 1-1 match with something you'd send to your server, you
create an attribute on your model purely to track the state of that checkbox
and wire up observers to update the appropriate "real" attributes you're
sending to the server. This is not immediately apparent when looking at the
two frameworks but I find the difference to be crucial.

I started using backbone the day you open sourced it since I had a personal
version of more or less the same thing that was twice the code and less
elegant. I found that it was fantastic as long as you could do idempotent DOM
updates (i.e. innerHTML) but got lost as soon as I wanted to start adding sub
components that needed to be initialized and I was back to dealing with a lot
of event twiddling and dom manipulation for updating the view. I believe the
split in state between the DOM and application model causes this complexity
which is avoided in Amber by having all client side application state in one
place. I think I could apply the same ideas in Backbone but I haven't tried
since switching over.

~~~
jashkenas
Neat. Do you have any open-source examples of this simpler "client side
application state in one place" up on GitHub? I'd love to take a peek.

I think that I'd tend to agree with your interpretation -- you write:

    
    
        > [In Amber] If you have a checkbox that doesn't 1-1
        > match with something you'd send to your server, you
        > create an attribute on your model purely to track the
        > state of that checkbox ...
    

That sort of approach would be against the Backbone "party line". A large part
of the point is to have your canonical state for a given resource in one
place: the model. If you now have both "model" and a "view-model" for the same
resource, one of which has been adopted to be more checkbox-y, just so that
its attributes correspond more closely with the DOM ... it would be a shame.

~~~
grayrest
> Neat. Do you have any open-source examples of this simpler "client side
> application state in one place" up on GitHub?

I do not. I plan on writing a blog post on this topic within the month that'll
have examples. I'll ping you on twitter when I post it.

In the meantime, the Sproutcore todos app has a simple example of this:

[https://github.com/sproutcore/todos/blob/master/js/app.js#L2...](https://github.com/sproutcore/todos/blob/master/js/app.js#L24)

The allAreDone propery. It's not something you'd have in the canonical data
you'd send to/from the server but exists as a property so it can be observed
and so the template bindings can manipulate it.

> If you now have both "model" and a "view-model" for the same resource, one
> of which has been adopted to be more checkbox-y, just so that its attributes
> correspond more closely with the DOM ... it would be a shame.

The model is more checkboxy but the checkboxy bits are initialized from the
canonical bits and your sync equivalent has to strip them back off. This is
annoying but less annoying than DOM twiddling.

~~~
spoondan
Link is now <https://github.com/amberjs/todos/blob/master/js/app.js#L24>
because of the re-branding.

------
CoffeeDregs
I guess I'm excited that a community figure is forking/creating/updating a
new-ish Javascript framework and I should focus on AmberJS in my comment,
but...

I can't help but feeling that the oh-so-confusing situation with SproutCore
just got more confusing. I, like many others, tried to start using SproutCore
and found it to be a poorly documented jumble of code. Fortunately, SproutCore
2.0 was going to fix a lot of that. Only now it isn't. Do we have two half-
baked, related frameworks? Are they kinda ports of each other? Is SproutCore
1.x now deprecated? And how confusing will it be when SproutCore 1.x upgrades
to a not-AmberJS SproutCore 2.x?

This smells of politics/investor-meddling/internal-disagreements/something to
me: fresh, innovative, though-derivative take on an existing codebase is
forked out of the original company and is moved under another company (Tilde).
Something seems amiss.

~~~
wycats
"Fortunately, SproutCore 2.0 was going to fix a lot of that. Only now it
isn't. Do we have two half-baked, related frameworks? Are they kinda ports of
each other? Is SproutCore 1.x now deprecated? And how confusing will it be
when SproutCore 1.x upgrades to a not-AmberJS SproutCore 2.x?"

SproutCore 2.0 _becomes_ Amber. We'll be moving the code into the amberjs
organization today. The SproutCore folks, who are now focusing on native-style
applications, will be carrying the torch on the (not deprecated) SproutCore
1.x.

------
mahmoudimus
A little off-topic, but, how are developers staying up to date in the
JavaScript community?

I've been an observer of the JavaScript eco-system and it is changing so
rapidly, particularly in the MVC space (i.e. SproutCore 1.xx, SproutCore 2.xx,
BackBone.js, Spine.js, Knockout.js, etc etc).

It's so easy to get stuck in analysis paralysis. Is there a discussion list or
a website that can help make some decisions for my next hack project?

I'm coming from a heavy backend background and I think the JavaScript MVC
space warrants a hack-day project :)

~~~
Cushman
Pick one that seems cool. Build something with it. Share it on HN; you will
get comments like "Cool-- but why are you using X instead of Y?"

Repeat using Y.

~~~
Androsynth
I'm not sure why you are getting downvoted. Although I don't feel you
necessarily need to share it on HN, the best way is the build some simple apps
and find out for yourself what the libraries are all about.

~~~
Cushman
It's not downvoted right now, so I think most people get what I'm saying. I
think it's important to get feedback from the community, but I agree you don't
need to show everything to HN, as most random projects won't get a lot of
attention here-- and I think you've picked out my real point that no blog is a
substitute for getting your hands dirty.

------
andrewvc
I thought this was going to be about <http://amber-lang.net/> , smalltalk on
javascript. Another project worth checking out.

~~~
mark_l_watson
+1 that is very cool, thanks.

------
Androsynth
Is it still in beta? Are the core objects going to be built up further (to
their sc1 levels) or left sparse as they are now? Is it going to get a full
set of guides and object documentation?

I recently tried out SC2 (now Amber, I suppose) and I had a "Wow this is
cool!" moment immediately followed by a "Wow I can't do shit" moment due to
lack of documentation combined with the steep learning curve. I had to put the
project on hold; I hope the framework gets some serious love in the next
couple months.

------
autarch
Maybe it's just me, but I find this idiom incredibly gross:

    
    
      var prop = model.get('prop')
    

It seems much more elegant to write:

    
    
      var prop = model.prop()
    

You can do the computed properties and binding thing the same way, it's really
just a small difference in the model API.

But really, what I'd love to see is more model-agnostic tools. Why do I have
to buy into SproutCore or Backbone's model implementation just to use the
other features?

~~~
tomdale
The advantage of using accessors is that your implementation can switch
between static properties and computed properties and the consumers of your
API don't have to know which is which. This is called the uniform access
principle and ends up being extremely useful.

For example, imagine you have an Store object that saves the tax rate:

    
    
      Store = SC.Object.create({
        taxRate: 0.0895
      });
    

Since this is a static value, I don't technically have to use an accessor. But
imagine my state implements a tax holiday, and so for one day per year, the
tax rate is different. In Amber, this is a simple change:

    
    
        taxRate: function() {
          if (this.get('isTaxHoliday')) {
            return 0;
          }
          return 0.0895;
        }.property()
    

Instead of trawling my codebase to references for this property and changing
them to method invocations, because everything goes through get(), I know the
change will be transparent. It's this transparency that leads to very
maintainable web apps.

Some people object to the extra method invocation, but I think the
expressiveness it gets you is worth it. As soon as proxies land in JavaScript,
we'll add support for them so you can use the dot notation and still get the
same functionality.

~~~
autarch
I don't think you really read what I wrote code-wise. I'm all for using
accessors, that's why I wrote:

    
    
      var prop = model.prop()
    

Note the parens there. I just like giving each accessor a unique method name
as opposed to getting at all properties through a single get() method.

~~~
tomdale
Sure, but then you have to create a function for each property, even if it's a
number or a string. Those bytes add up significantly in large applications.

Additionally, specifying the property as a string allows you to implement
"unknown property" handlers, which is another extremely powerful idiom.

~~~
mbostock
This might become more common when Proxy is supported more widely in
JavaScript implementations.

[http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxie...](http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies)

------
burke
Exciting! It really does make sense to rebrand SproutCore 2.0. As a (light)
user of both 1.x and 2.0, I completely understand the change. So much has been
simplified -- the barrier to entry has dropped considerably, and the
boilerplate factor is basically gone. Yehuda and Tom have done a great job
with SproutCore, and I'm excited to use (continue using) Amber in the future.

------
spatten
"If you played with SproutCore and liked the concepts but felt like it was too
heavy, give Amber a try. And if you’re a Backbone fan, I think you’ll love how
little code you need to write with Amber."

Sold! You read my mind there, Yehuda.

I don't _exactly_ know why, but I'm excited by this. Heart beating noticeably
faster excited. I'll be playing around with this on the weekend.

------
erichocean
I wrote about the future of SproutCore 1.x here:
<http://dl.dropbox.com/u/323974/Future%20of%20SproutCore.pdf>

~~~
caycep
hm, so does this mean a fork into 2 different development environments?

i.e.: sproutcore.js/blossom - "desktoppy" MVC framework with HTML5/js as a
display layer

amber.js - "web-appy" MVC framework with HTML5/js as a display layer?

*edit:

~~~
wycats
"Blossom will use the GPLv3 license, with commercial licensing similar to the
Sencha model."

I don't have a clear idea about what's going on in the SproutCore community,
but I don't think this has universal support.

One of the reasons we rebranded to Amber is that our codebase is inspired by
SproutCore 1, but it is a complete rewrite, targeting a smaller file size and
web-centric development.

All of the fragments of SproutCore 1.x target native-style applications with a
ton of JavaScript, while Amber targets ambitious web-style applications using
HTML and CSS for the presentation layer. Amber apps don't have much in common
with SproutCore 1 (or "blossom") apps, so a clean naming break felt like a
clarifying thing to do.

~~~
erichocean
Blossom is a commercial product, it's not part of the proposed SproutCore.js
path forward for SproutCore 1.x.

It is, however, API-compatible with the MIT-licensed view layer (called
"Classic") in SproutCore.js.

See the paper for more details.

------
MatthewPhillips
The biggest problem for me with any JS framework I've tried in the past is
that it doesn't give an easy way to divide code into multiple code files. For
me personally, I find any single file/module/class that is more than a few
hundred LOC to be difficult to read. For this reason I've usually rolled my
own frameworks. Does Amber.js address this?

~~~
tolmasky
Cappuccino's @import does this really well: it is both asynchronous and
blocking. In other words, having three @imports one after the other will all
load in parallel (without having to explicitly request it, even if they are
separated by other lines of code), but the code itself will not execute until
the imports are done:

    
    
        @import "one.js" // loaded in parallel to the other two
        @import "two.js" // loaded in parallel to the other two
    
        code code code // this is run only after one.js and two.js (but not three.js) have been loaded and run
    
        @import "three.js" // loaded in parallel to the other two

~~~
cousin_it
Very nice! Just a note: that seems to break some things that Ruby developers
take for granted, like importing stuff conditionally, or importing a bunch of
files in a loop. Or is there some other way to do that?

~~~
tlrobinson
There are JavaScript APIs in the loader you can call directly, but they will
be asynchronously loaded _and_ executed (so you'll need to pass in a callback)

Basically the only way to get this asynchronously loading / synchronously
executing behavior is to statically analyze your "root" module for
dependencies and load them (and their dependencies, etc). Once they're all
loaded you can begin execution and synchronously execute every module as
they're imported.

FYI CommonJS (not AMD) loaders for the browser do the same thing to avoid
synchronous XHRs that will cause the UI to hang.

------
carldall
Good news. I wonder though, what will happen to Sproutcore? My former company
build a huge application based on 1.4 (at that time), and now they're kinda
left in the rain. Does anybody know when or if all the Sproutcore 1.x changes
that Apple made for iCloud/MobileMe make it back into SC 1.x?

~~~
ynniv
There are three contingents right now. Facebook (SC2/Amber) wants to make rich
web pages. Tilde (SC 1.7+) wants to continue the Strobe direction of deploying
client side web applications in different contexts. Erich Ocean (1.4 fork)
wants to go back to his original philosophy of creating applications that can
be deployed on the natively or on the web. The primary break Erich Ocean wants
to make is to drop templates and construct interfaces in the desktop / Cocoa
style, not a mixed HTML templating one.

So there are still core folks working on 1.x, but in different contexts.

~~~
wavephorm
This sounds like a broken development community.

~~~
erichocean
It is, but it's being fixed. I expect the situation to be __very__ different
by JSConf 2012.

It's been clear where SproutCore has need to go since 2009, but there hasn't
been the support to do that, due to the various personalities involved. Those
people have moved on, and now SproutCore can do what it's good at: building
fast, desktop-style applications that run in a web browser.

Things haven't looked as positive for SproutCore in two years. I pumped.

------
atomical
If the people developing Amber are reading this and I'm sure they are I hope
they take away the message that the community wants better documentation,
examples, tutorials, and use cases. It's not features, abstraction X, Y, or Z,
it's support!

------
kqueue
I tried using SC2 (aka Amber), while it has a lot of potential and I love the
powerful binding mechanism it has, it simply lacked documentation and support.
I hope Amber has tackled this issue.

------
seddona
Why anybody thought it was a good idea to replicate desktop applications
verbatim on the web i dont know, the era of composing GUI's from complex fully
featured widgets is dying.

Declarative presentation in HTML/CSS coupled to JS (or better CS) is the right
layer of abstraction for building GUI's for most applications in the
foreseeable future.

Amber.js looks very interesting, i hope it paves a new wave of client
frameworks that concentrate on state sync between client/server (and multiple
clients) with some simple binding to presentation.

~~~
scelerat
HTML was made with documents in mind. Ever since the web's inception HTML has
been pushed beyond its original design specs and now people are writing
applications in it (actually they have been since CGI). That interfaces
continue to evolve and even replicate "native" interfaces shouldn't be a
surprise.

As far as the "right" abstraction on the web... this too is evolving and
highly dependent on your application. Are you curating a collection of
hyperlinked documents? Or are you writing a drawing application?

If your answer is closer to the latter than the former, then the analogy
you're looking for is something more like Postscript, where HTML and
Javascript serve as a display language for an output device (a browser),
driven by an underlying application.

------
koudelka
I certainly hope this doesn't splinter the community. Moving the version up,
then just forking, seems like it'd do just that.

------
gfodor
Can someone explain how far along this is on the spectrum of creating a
constraint-based UI toolkit like OpenLaszlo or (I think) Flex? Constraint
based programming is amazing for the view tier, and I've been waiting to see
if someone comes along and builds one comparable to the Flash based ones that
have been around for years.

------
krmmalik
Will it be possible to incorporate something like this into Node.js? I know it
can be done with something like Backbone, and does it provide any distinct
advantages over Backbone that would be worth investing the time in this
library?

~~~
wycats
A few months ago I showed a demo at a meetup of using Amber in node. The main
benefit of Amber in a node environment is the way it abstracts asynchronous
behavior through bindings and observers.

I could easily imagine an Amber object representing a File in node, for
instance, allowing other objects to bind to properties like mtime, etc.

In my demo, I used socket.io to update an HTML page whenever one of those
properties changed.

~~~
krmmalik
Thanks for responding. Do you have a video of the demo?

~~~
joubert
Hi - here's a video of the meet up and a link to the demo Amber-on-NodeJS code
[http://joubert.posterous.com/yehuda-talking-about-amberjs-
sp...](http://joubert.posterous.com/yehuda-talking-about-amberjs-
sproutcore-20)

------
tree_of_item
Is there a way to use SproutCore without the command line programs like sc-
init or sc-server, and without it forcing a directory structure on you?

I like the idea of SproutCore, but I really just want to do <script
src="sproutcore.js"> and have it get out of my way from there. YUI seems to be
able to do this and it seems even larger than SproutCore, recently including
MVC in its "App Framework". Of course, you need to bring your own templating,
but even then that's just another JavaScript include.

Or am I missing the point of SproutCore? What is it adding that, say, YUI or
Dojo isn't, that it requires so many programs?

~~~
grayrest
The sc-init and sc-server are Sproutcore 1.X. Sproutcore 2.X (now Amber, what
we're discussing here) works exactly like you'd want:

    
    
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
        <script src="js/libs/sproutcore-2.0.beta.3.min.js"></script>
        <script src="js/app.js"></script>

------
jebblue
It seems like new JavaScript frameworks are popping up every week.

I think Google with GWT and Eclipse less so with RAP had the right idea. Come
up with technologies that abstract away the need to touch JavaScript directly.
Just Java (or I suppose C# could work) on the client and the server means the
developers are more in sync.

I'm more on the back-end so my perspective is more from the side lines, please
don't read too much into it.

~~~
funksta
Some people actually like writing javascript ;^)

~~~
jebblue
I get it, it's cool, maybe it's jealousy I'm experiencing.

------
tomkr
It looks like it's actually called ember.js. <http://www.emberjs.com/>

~~~
mvzink
Indeed, for those of us who missed it, they had a poll:
<http://news.ycombinator.com/item?id=3335916> and Yehuda announced the change
yesterday: [http://yehudakatz.com/2011/12/12/amber-js-formerly-
sproutcor...](http://yehudakatz.com/2011/12/12/amber-js-formerly-
sproutcore-2-0-is-now-ember-js/)

------
barumrho
I couldn't help but think about AngularJS while reading this article.
(<http://angularjs.org/>) I am not sure why it isn't as popular as other
JavaScript frameworks like Backbone.

~~~
ludicast
AngularJS is ridiculously good so I'm not sure either.

For those who are unfamiliar: Angular examples are about 1/4 the size of
backbone equivalents. I'm working on an angular version of the most recent
peepcode backbone cast. It's about 1/5 the code size, and available here:
<https://github.com/ludicast/angular-peepcode-todo>

------
pbreit
So SproutCore 2.0 is being renamed Amber.js?

~~~
rxcfc
Yes.

------
swah
Is this like Backbone?

------
ghempton
Amber looks to be getting awesomely close to a CSS/HTML version of Flex.

------
andyl
The Amber claim is "if you’re a Backbone fan, I think you’ll love how little
code you need to write with Amber".

Can anyone explain the differences between Amber and Backbone, why Amber might
require less coding?

~~~
grayrest
Both Amber and Backbone fall into what I call the KVO frameworks category
(Angular, Javascript MVC, Knockout, Batman, others). Both use jQuery for DOM
manipulation and revolve around the idea of having a canonical model and
having that as the center of your app. As you change the model, it fires
events that you use to update the DOM. The difference is that Backbone is
philosophy.

Backbone provides a basic but complete set of tools for observing model
changes combined with a set of utilities that are useful but not prescriptive
to make wiring up DOM events, URL handling, etc straightforward. It works with
what's in jQuery/the browser. All together, it provides the organization most
js apps are sorely lacking but doesn't dramatically reduce LoC over what you
could do with well factored jQuery and underscore. It's nice enough that the
YUI team basically adopted it wholesale for the App framework in 3.5.

Amber is all about binding. You can not only observe properties but bind them
to other properties bidirectionally so that changing one causes the change to
propagate through all bound values including things like values being arrays.
This extends to the Handlebars templating (which was written for Amber) where
you can bidirectionally bind, for example, a boolean on your model to a
checkbox and to a class on a div so that checking the checkbox toggles the
class without anything in your app directly manipulating the DOM. The
implementation is an attribute plus two object path strings in the template.
It's not panacea but since DOM/Event/State manipulation is ~60-70% of most JS
apps I've worked with, you can achieve dramatic code size reductions.

The cost is that Amber is 10x the size of Backbone, the templating language is
tied to the framework, and there's more overhead in understanding the
concepts, how they fit together, and how to apply them to your code. When I
talk to people who are writing jQuery spaghetti, I steer them towards Backbone
for the simplicity and superior docs but mention that I use Amber for my own
projects.

------
tenderlove
AMBER ALERT!

