This is the only intelligent comparison I have seen of Ember & Angular (or actually of Angular with any other modern framework). Thanks!
I am wondering if the uniform access principle is mostly a dynamic language issue: you end up screwing up whether you need a parentheses invocation and you don't know until runtime. If you type everything with TypeScript then you know at compile time if you messed it up. Relatedly, Ember's get/set is more difficult to make strongly typed. In the TypeScript definitions I am looking at, property access is only typed as a string. One could define an enum for each object to be used in place of the string, but overall there is a price to pay with set/get since it isn't baked into the language (like Ruby).
I think the uniform access principle is misguided (or at least misconstrued). It's a bad idea... in general. If you're building an API and you have need some kind of stable, unchanging interface to expose - then it makes sense.
But people are using it everywhere in their programs; and it's not really valid there. First of all, data-access is fast and computed functions may be slow. Hiding this difference means that writing efficient code becomes more tiresome - you need to consider each and every access as potentially expensive, even though the majority are probably trivial. This means you need to know the code better to get anywhere. And if you make it hard to write efficient code, people won't bother (and rightly so, since that's usually premature optimization).
Secondly, in most languages, simple data access is side-effect free and (usually) thread-safe or at least has predictable threading behavior. Managing side-effects - even without threading - is a major pain in any large code base, and although functional purity can be enforced otherwise in some languages, in most cases you've got nothing to go on. Making your life more difficult by discarding annotations that distinguish between method calls and member access isn't helping.
Of course, in a dynamic languages you're in a tricky spot here - it's hard to refactor, so exposing member access is something that's more work to change later when you discover you need computation or a side effect. However, even so; making a system harder to reason about for the purpose of a fairly pointless architectural purity is usually a bad idea.
The uniform access principle as applied to interfaces is another story; but in general use - I think it sounds nice in theory, but works poorly in practice.
JavaScript hasn't had simple data access for a long time if ever. Computed properties have been widely supported for a long time, there's "watch" [1], and of course there's the prototype chain. ES6 adds proxies, which makes practically everything you might want to do with an object potentially have custom behavior. IMHO, in JavaScript you might as well respect the uniform access principle, since "a.b" meaning simple data access has arguably never existed.
Since code could be self-modifying; clearly simple-data access has never been a guarrantee.
But in practice, today as ever, it's a good guideline. When you see an accessor, it will almost always be fast and side-effect free.
Now, part of that is because not all browsers support the features you refer to and therefor these features just don't get used much. But even in languages like C# and python, that have had real accessors for a long time, it's still a good guideline: it's generally considered bad practice to make a slow, side-effectful accessor, and most people don't.
Controlling side effects and performance are important, and the uniform access principle has little upside in most non-public code, yet considerable cost in that it obscures one of the few indicators mainstream languages have for these aspects.
Keep in mind that Computed Properties are also part of the solution to intelligent, efficient data-binding. CPs in Ember are cached and quite efficient and because they are aware of their dependencies, much of the computation that would otherwise need to go into a dirty-checking approach to data-binding can be avoided. So, Uniform Access is part of it, but I would advise against scrapping an initial implementation of your app using CPs on performance grounds considering that data-binding is the main performance bottleneck in Ember (and Angular).
Coming from an Angular background, this presentation really made me question my own ideas of whether POJOs should be the "one-true-way (tm)".
I always thought POJOs made a lot of sense when you're in a RESTful world, where, to a large extent, your client-side model mimics objects from the database schema. Ok, I'm oversimplifying, but generally speaking, it makes sense to map a web service API point to a User table and compute information on the server end of the web service (I'm talking about highly-relational computations like a `IsUserInTheOffice` property derived from entries in several tables(e.g. Vacation, BusinessTrip); not trivial sugar like `Name = FirstName + LastName`)
Realistically though, the highly relational interconnectivity between model entities often require client-side computations. An example from something I've worked on: let's say you're drawing a calendar. What's the maximum start hour/end hour range of entries in a table in your system, plus entries from a 3rd party service (e.g GCal), in a given day?
With POJOs it's much harder to refactor when you suddenly need this type of computation, since you need to audit the whole codebase for insertions, deletions and other user-generated updates on all the relevant model entities. All of a sudden, the reactive style of Knockout, or the uniform access framework in Ember look very desirable.
To be fair, using things like user.firstName without requiring computations/side effects is far more common than using computed properties, and the author made a good point about the size of code vs usage frequency. And as you point out, making it easy to get into side effect hell from the get-go is probably not necessarily a good trade-off for protecting against potentially expensive, but uncommon refactors.
That's kind of exactly my point :-). It rarely has a place in the internals of your webapp, and as such makes no sense as a design philosophy for object patterns aiming to be used largely in the internals of your webapp.
> I am wondering if the uniform access principle is mostly a dynamic language issue: you end up screwing up whether you need a parentheses invocation and you don't know until runtime.
The uniform access principle is mostly about enabling refactoring and information hiding -- consumers of your code shouldn't care whether an attribute is the result of direct member access or method invocation, and if you change from one to the other, it shouldn't break client code.
Uniform access principle is nice to have in JavaScript, a dynamic language like you pointed you. One of the nice things is it makes refactoring a bit easier. Imagine you have code that reads:
All of a sudden your code breaks because person.name needs to become person.name(), person.first() to person.first, etc. That is somewhat hard to track down/refactor in a large JavaScript code base, or any dynamic language code base for that matter.
Uniform access principle is, in my opinion, one of the selling points for implementing your own object model in JS.
Wouldn't TypeScript help a lot in handling these changes?
You break/change something and then the rest of your code wouldn't compile until you fixed it everywhere (and it would show you where). You wouldn't have to worry whether you forgot something since the compiler wouldn't let you get away with it.
Refactoring tools on top of TypeScript (like Resharper and Coderush) will eventually be able to safely do these changes quickly across the whole project.
But it's cumbersome to have to change lots of code just because a property of some object became computed instead of directly stored (or vice versa). And it's unfeasible to do so if you're developing a library (for external usage, or internal usage within a company)... you can't just go and fix all the code that used it.
Computed properties are a good workaround. Getters and setters could be better though. That way no one on the outside of the object needs to know the details at all. Am I right in saying that by sacking off old IE browsers we could switch to getters and setters (as in, native js implementation) already?
Almost.... and Ember can mostly work with that last time I checked.
The missing piece is delegation though, i.e. you can't define a catch-all getter/setter and many Ember.*Proxy classes/mixins (e.g. http://emberjs.com/api/classes/Ember.ObjectProxy.html) rely on that. Like most Ember Controllers are delegating data state to a model, and are supplementing app state/behaviors on top.
ES6 Object Proxies fixes that.
But I'm liking how fast the Ember team has been including ES6 transpilers into directly in to Ember App Kit. So we may be writing more regular JSy looking property dot notation, like Angular, soon enough. And get all the benefits of UAP.
(By the way, for coffeescript fans, ember-script sort of does this for you: http://emberscript.com/)
Having just dug into Angular while wondering if I really wanted to be working with Ember, this was a great comparison. It's obvious to me now I have to look at both frameworks. While done by an Ember.js creator I found the presentation also provided me with a much deeper knowledge of Angular at the same time - well done.
As for the Google popularity, one could snidely remark that Angular's documentation and taxonomy requires significant amounts of searching to solve the problems you are after. While the community is active, it's quite difficult to find examples of the right solution or effective documentation for newbies at times.
My usual trick for getting around this is in rails vs django is to add tutorial to the search, so "emberjs tutorial" and "angularjs tutorial." Unfortunately it looks like we're still too early to have enough data using those terms, which tells me that the google search data should be taken with an enormous grain of salt.
I hate that Google Docs modifies your history when you go to the next slide. This presentation clocks in at 57 slides and Firefox history defaults to truncating after 50 entries, meaning I can only go back to slide 7 and not back to HN.
Is it really better that I can use my browser forward and back buttons to navigate slides? Especially when there are forward/back buttons on the presentation anyway?
I personally enjoy this aspect, as I think it fits the philosophy of the web better. Each slide has an address, because they're separate things. You can also trivially link to a particular slide this way.
I open articles in new tabs, so the going back to HN part hasn't ever affected me.
Each slide should have an address yes but I don't think everything should push do your history stack.
That Git cheat sheet page the was on HN a few days ago. Every time you changed the command it pushed onto your history. I want to click back to HN not back and forth between 2 commands I switched across 6 times.
I was going to comment then but I don't think the site was using push state it is actually browser behaviour.
It would be nice if the history UI wasn't purely linear, but that it remembered the last x pages on the current domain and the last x pages on the previous n domains.
SnapBack in Safari used to be really handy for these sorts of pages, however I think that feature is gone now. From what I recall it would take you back to either the last typed URL, bookmarked URL or search results page.
This is why I never open links in same window, everything is middle click. Even on ios I will tap-hold to open in new window, I can never trust JS apps not to trash my forward/back
I really liked this. Although I prefer to work with Ember.js, Emblem and EmberScript (as the latter addresses some of Ember's syntactical faults), Angular seems very interesting when you view it as more of a toolset for building your own framework than a "complete" framework in and of itself.
When you bring the entire Ember toolchain into the mix, outside of the already-complete framework, it begins to smooth Ember's rough edges in development. It's just the same with Rails, I'm a Ruby developer and we're used to dealing with dependencies already, so it's not really a huge leap outside the box for us to be using tools that will compile down to HTML/CSS/JavaScript to build the frontend to a Rails backend API application.
I still understand Angular as a toolchain/framework/whatever for people who do not understand JS to the point where they want to begin extending it. Angular is a "safe zone", something that frankly JavaScript as a language (without Ember's additions to the object model and such) needs right now. When you write apps in Ember, I feel like a deeper understanding of how JS is working is necessary before you begin to abstract that portion away. Is this still a correct assumption to have? I'm not trying to insult anyone, frankly JS is a pretty screwed up language so I feel like it's a natural tendency to want to just get what you need out of it quickly and safely and then move on to more fun projects. In my opinion, it's simply a different way of doing things, not better and not worse.
One thing that I like about Knockout is that you can easily drop it into a legacy site, allowing you to have some pages that use it and others that don't. Forgive my naivete, but is this something that is easy to do with Ember or Angular as well?
Without knowing the specifics, the best answer I can come up with here is that it's Javascript -- so yeah, you can write it affect parts of the page, or all of the page. You can have it control just the navigation bar on a site, or the whole site altogether.
There are caveats here -- if you have the library loaded from any page with html5 location mode enabled, it'll take over link-handling on those pages. With Angular, it's easy to circumvent by adding a 'target' attribute to the links, but on a legacy site, that might mean having to touch every page that Angular doesn't already exist on, which would be a chore.
The alternative is to not enable HTML5 location mode (so links are to #/link/) or to adjust the targets on links that aren't meant to be handled by JS.
All summed up though, while it may not be written anywhere, I've always gotten the feeling that Angular prefers to own the entire page, loading partials into views where appropriate, and using separate controllers for other portions of the page. That said, it can work either way, but does take some extra special care.
"allowing you to have some pages that use it and others that don't"
Your response seems to dig into a different (though related) issue. If the question is whether, given a whole website, whether angular/ember can exist only on certain pages, but not all pages, then the answer is Yes.
EDIT: whoops, I was answering about Knockout vs Angular here, not Ember.
I think it's actually easier in angular, because you can set the ng-app parameter at the point in the DOM tree you want to bind to the Angular portion of the app. (ng-app is similar to ko.applyBindings, except that unlike KO, with Angular don't have to worry about having parent DOM bindings clash with child DOM binding applications.).
this is one of the nice things about angular. You can just drop it in to make a component of an existing site use angular. I attempted to get that to work with ember, but I don't think it's possible.
Kudos to the author - I am impressed how well Alex Matchneer understands Angular.
Few thoughts of my own:
- Ember is a long term relationship with one particular way of doing web FE, a way invented by someone else for you. Ember philosophy is "one size fits all".
- On directives and transclusion - it's like Lisp's dotted pair.
these new concepts may be hard to understand, but experiments like that often fascinate programmers, and for a good reason - one day those experiments will revolutionize the way we build software.
The debate of a small set of flexible tools vs one tightly integrated system is not new. We had Linux vs Windows, Django vs Flask, etc. It's funny to see it pop up in yet another area.
Thank you for this great write up and raising a bar of this long going discusiion on Ember vs Angular.
I've been working with Ember for a while now, and I love it. Convention over configuration is a big deal, and the Ember team has done it right. I think if you like Rails then you'll like Ember.
I use angular a ton, and just learned more about Ember from this. thanks. I'll have to check it out someday. Ember looks like it has good testing now too :-)
That was a really informative comparison, kudos to the Ember author for injecting minimal bias.
I've been on the fence about switching from jQuery + Coffeescript to Angular/Ember/etc.
Still am, bit of a server-side luddite here, AJAX, client-side form validation, some jQuery effects for dropdown menus, show/hide layers, etc. is as far as I go.
Do we really need either Angular's or htmlbars' (see slide 37) way of "decorating DOM elements with behavior" when it is so trivial with just ES5 and HTML? See this jsfiddle: http://jsfiddle.net/dexygen/nU8VK/ Give me a couple/three strong JS devs and I guarantee you I could take these simple building blocks (as well as spans with data- attributes, and innerHTML, instead of templates), and I could build out a framework way faster than either Angular or Ember.js and would validate as HTML5 to boot. Doubt me? I pretty much did the same thing for PHP; see http://dexygen.com/ria/#!/docs/jackrabbitmvc
So technically what the presentation is trying to say is that you should use Angular to build Ember like framework. hahah
I personally like Angular, the Google support and the community are strong points to it. The documentation used to be hard to find, but now, specially with StackOverflow, finding what you need is easy.
I am wondering if the uniform access principle is mostly a dynamic language issue: you end up screwing up whether you need a parentheses invocation and you don't know until runtime. If you type everything with TypeScript then you know at compile time if you messed it up. Relatedly, Ember's get/set is more difficult to make strongly typed. In the TypeScript definitions I am looking at, property access is only typed as a string. One could define an enum for each object to be used in place of the string, but overall there is a price to pay with set/get since it isn't baked into the language (like Ruby).