AngularJS from an Ember.js perspective
docs.google.com
docs.google.com
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).
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.
The uniform access principle is a principle of interfaces, it doesn't apply to anything else.
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
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.
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.
person = {
name: "ryan to",
first: function() {
return this.name.split(/\s/)[0];
},
last: function() {
return this.name.split(/\s/)[1];
}
}
But you realize this could be harmful, so you want to change it to: person = {
name: function() {
return this.first + " " + this.last;
},
first: "ryan",
last: "to"
}
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.
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/)
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.
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.
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.
- A toolset’s mindshare is predictably going to be greater than that of a framework
- Angular interest (per Google) dwarfs Ember; jQuery interest dwarfs Angular, etc
- Angular encourages you to build the framework; Ember is the framework
https://docs.google.com/a/steveklabnik.com/presentation/d/1e...
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 open articles in new tabs, so the going back to HN part hasn't ever affected me.
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.
i think a good compromise is to use the left/right keys for onpage slide nav, but leave the browser history alone.
http://i.imgur.com/8nSjOu1.png
(exact same behavior in Firefox and IE too)
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.
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.
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.
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.).
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.
That could also be because angular has horrible documentation!
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.
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.