Ember
before publishing it. it took longer then I thought and the more I learned about Ember
it became clear I shouldn’t publish my following post. Unfortunately until now I did not have the time to write anything else so I should apologies it took so long and I should probably apologies again since its not really going to be a sequel for the previous post.
- I gave it a very antagonizing title ( I later changed it).
At the time I thought being a bit rude and blunt will help to stir up the community a bit, I thought it would help starting a discussion and although it got some attention I think most people couldn’t read past the title and I can’t blame them. - When I wrote it I thought I’m really going to enjoy working with Ember and that I would be able to contribute to the community and help improve it. Since then I discover that I don’t really fit with the Ember mindset. I don’t like the way its built or thought of. I should probably have selected a different framework. I’m not here to say Ember is a bad framework but personally for me it raised more issues then it solved.
Since a lot of the frustration I have with Ember relates to the fact that I don’t fit the Ember mindset I wasn’t sure if I should publish this post. The same frustration that drives me to write this post will probably cause the post to be very negative. Being highly opinionated and critical person I can find flaws in great and amazing things and since we already have enough negativity online I was hopping to take my blog into a more positive direction. I thought of just doing a minimal post without going into too much detail but I don’t think this is fair since it wont allow either to argue against my claims or to Ember developers to fix any of the issues if they find them reasonable.
So I hope this post will be more informative then negative, but if it makes you in anyway think less of the Ember project just remember that the post author clearly states he doesn’t fit with Ember mindset and you should probably find some other information about Ember elsewhere before reaching any conclusion.
So with that in mind here is part two Rethinking Ember
About a year and a half ago I started working on a new project. I was very lucky to have almost full control over the stack and technologies to use. After considering and checking a few frontend and backend frame work I decided on a stack that will build upon 3 major components
Each of this projects has a more popular substitute in the JavaScript ecosystem but I tested the alternatives and didn’t like them much.
hapi
is an amazing API/backend framework I tried both Express and Sails before setting my heart on hapi. Today I can say hapi is one of the most enjoyable project I ever worked with. The lead maintainer, Eran Hammer, can be a shmock. He has a clear view of where the project should go and he is unwilling to compromise. The result is amazing. Every time I need to solve a new server related problem hapi has my back and usually has 80% of what I need built in. Eran’s clear ideas and views make this project one of the most inclusive, secure and community driven open source project I have ever seen and I will get back to hapi in this post and future ones.
Sequelize
is a really nice SQL ORM, I can’t give it the same praises as I can give hapi but if you need to talk to an SQL server from node, Sequelize is probably the best option. I still have some issues with it every now and then but they are usually easy to solved. Overall it’s clear intuitive and works great.
And then there is Ember
.
Ember became a hurdle in my work process, while I enjoy working on my app backend I feel a small shiver whenever I need to add a new feature to my frontend. To be fair I didn’t tested Ember too thoroughly before deciding to use it. I had some experience writing Backbone and Angular apps and I wanted to try something new. I also didn’t like angular dirty checking or mixing logic into HTML. At the time React just started to become more popular but it was still too young to rely on and although there might be some other frameworks Ember looked like the best bet especially since Ember clearly stated it is going to keep supporting IE8 When Angular was planning to drop support when Angular 2.0 comes along. In the end Ember 2.0 dropped support for IE8.
I find this pattern of false advertising to be a common pattern in Ember.
Here is a few more –
- Stability without stagnation (See Discourse one of Ember’s flag and runs the community forum is still using Ember 1.12.x and not 2.x or even 1.13.x which was released a year ago)
- Betting on ES6 ( Didn’t see any official notice about dumping ES6 yet but Glimmer 2.0 is written in TypeScript which you can argue that it might be really close to ES6 but it’s still not ES6)
- Dirty checking is slow, Ember is fast way faster than angular (we’ll maybe 2.0 is now I don’t really know since it seem every JS framework is four times more per formant then the other one this days, but it was probably one of the slowest framework two years ago when I first heard this claim)
And although I find this advertising issues a bit disturbing, it’s hard to blame Ember advocates for using them. The framework ecosystem is highly competitive and while Angular
and React
gained large user base and has the resource of huge companies to back them up, it seems Ember is loosing what ever stand it used to have.
But If we’ll put the PR aside my main issue is with the convention over configuration mindset. Convention is at its best configuration with good defaults not having configuration options only introduces limits with no benefits, hapi
on the other end is configuration centered yet it is easy to get start with and if your only doing simple routes you don’t need to bother with any of the configuration options.
It is probably impossible to have a reasonable sized software that doesn’t have any configuration. Pushing configuration options to the side and ignoring them means they will not be document properly and it will be harder for people to use the software for anything other then the bare basics.
There are just some problems you can’t solve with Ember without braking out of the Framework. Breaking out of the framework is ugly and dangerous. This Hacks are bound to break on future versions. Since Ember has relatively small community and addons users are bound to resolve to hacks sooner or later. Ember stiffness is pitched as a good and thought out feature, something that will make every Ember app architecture to be relatively same and makes it easy for a developers to be productive in any Ember project even if it was written by someone else. I doubt if it is easier than with Angular
or React/Redux app or any other reasonable framework. And if you consider the amount of hacks your going to have in any proper size Ember app it is probably going to be a lot harder.
Ember has too much Dark magic. Good magic gives you syntactic sugar and saves you significant amount of abstraction without loosing clarity and meaning and since your code is shorter and DRYer it’s usually a lot clearer. I guess it might not even be considered magic cause magic is a term we use where we can’t understand whats going on. Dark magic on the other hand might look really cool, but after the smoke fades you have no idea what you just saw or where’s your wallet.
Here is some of the good magic you can find in Ember –
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//Code from Ember Docs https://guides.emberjs.com/v2.5.0/object-model/observers/ Person = Ember.Object.extend({ firstName: null, lastName: null, fullName: Ember.computed('firstName', 'lastName', function() { return `${this.get('firstName')} ${this.get('lastName')}`; }), fullNameChanged: Ember.observer('fullName', function() { console.log(`fullName changed to: ${this.get('fullName')}`); }) }); |
I don’t think I need to explain this code as it is very clear. Without knowing any of the mass amount of underline implementation code or even if it’s the first Ember code a person encounters it is easy to assume what the above code is doing. Even the most clueless developer will recognize a few methods he is not familiar with and it is very clear which information he should search for (the observer
and computed
documentation)
Now lets look at some dark Magic –
1 2 3 4 5 6 7 |
//Code from Ember Docshttps://guides.emberjs.com/v2.5.0/testing/acceptance/ test('should add new post', function(assert) { visit('/posts/new'); fillIn('input.title', 'My new post'); click('button.submit'); andThen(() => assert.equal(find('ul.posts li:first').text(), 'My new post')); }); |
Now at first glance this code looks very clear. The test visit a route, fill in data, click the submit button and then it gets a bit weird but it seems like it validates the text of the first post. An alert developer might decide to check what the andThen
method does and why she needs to use it. But the clueless developer when looking at this code might just miss it since there’s nothing here that gives any clue about the real underline magic.
If you never seen Ember test before you are probably not even getting where I’m going for, but let me show you how we write this code without the magic and see if it fits with what you thought was happening –
1 2 3 4 5 6 |
test('should add new post', function(assert) { visit('/posts/new') .then(() => fillIn('input.title', 'My new post')) .then(() => click('button.submit')) .then(() => assert.equal(find('ul.posts li:first').text(), 'My new post')); }); |
Now you can clearly see all the functions in this test are actually running asynchronously returning a promise. the only function that doesn’t do that is the find
which is synchronous function so on the previous test it’s necessary to wrap it in the andThen
method forcing it to wait for all the previous async methods to finish. But isn’t using the regular Promise way is a lot clearer ? isn’t the code almost the same length ?
The code didn’t gain much from the magic here and it lost a lot of clarity.
Reading the docs carefully it might be that the code lacks not only clarity but some important functionality –
Asynchronous Helpers
…
Also, these helpers register themselves in the order that you call them and will be run in a chain; each one is only called after the previous one finishes. You can rest assured…
So asynchronous helpers will always run in chain and wait for previous helpers to finish. But what if we want to test interactions where the user does not wait for previous events to fully finish.
lets say our app has some route with pagination that fetches data remotely. It has forward, backward and reset buttons. The test need to make sure if the user clicks on any of the buttons multiple times without waiting for a response only the last action sent is the one being displayed.
We might write the test like these –
1 2 3 4 5 6 7 8 9 |
test('should always end back in initial state', function(assert) { visit('/pagination') .then(() => Promise.all([ click('button.next'), click('button.next'), click('button.prev'), click('button.reset') ])).then(() => assert.equal(find('.state').text(), 'Initial')); }); |
Since Ember test suite will decide for us that it should wait for each click event to finish before calling the next click event, this test will always pass regardless if our actual logic knows to cancel or ignore previous requests when a new request is started before the previous one is finished.
This is such a common mistake in UI code that I can only hope that the description in the docs is lacking in some way.
My previous post talked mostly about Ember cli. so I won’t go into much details here but I would say that I see Ember Cli as the ultimate Dark Magic feature of Ember. I think having a consistent way for building and adding Ember modules is a great feature. But this could be done as easily by using a git seed and some Broccoli build scripts. for the absolute beginners who might find it intimidating to run multiple shell commands Ember cli can be used to concat nicely this tools and scripts together. But the cli should only come last and as a wrapper for existing and clearly defined tools. The way we have it now the cli holds all the logic and completely hides everything away with no easy way to find the information.
Ember modularity is highly laking. When Ember forked out of SproutCore a great decision was made to split the framework into smaller modules, yet the modules were never made to be truly autonomous. for example look at one of the dependencies of Ember morph-range this module allows some of the magic of Ember HTML data binding. can you see any docs ? would anyone be able to use this module alone for his own project ? probably not .Chances are that this module is highly coupled to Ember and should have never left its code base (that way it might have gotten just a little bit more documentation). Other modules like HTMLBars has some documentation but it seems to be more centered around the module architecture then the actual API. Anyone who would like to use it separately or even try to understand how Ember might be using it will not find the docs to be very useful.
A great modular project for comparison is hapi
. Check for example joi and hoek which are part of hapi core. It is very clear from each module docs how to use it even without using hapi. This not only makes each individual module easier to understand but also hapi and how it fits together.
it seems Ember relies on reinventing the wheel. When wanting to incorporation external and existing UI components that were not written specifically for Ember, users sometime have to make the hard choice between breaking out of the framework or completely rewrite the external component. But what concerns me even more is that whenever a new and shinny technology arrives to the JS world, Ember core re implements it. Don’t get me wrong I’m really glade Ember learned a lot from React
and Angular
. Ember core developers did amazing job with HTMLBars
and Glimmer
, but wouldn’t it be great if we could use React with Ember ?
Couldn’t we save thousands of development hours if we had a way to incorporate a more performant view layer in Ember without just rewriting it from scratch ?
How much better Ember and React could have been today if all this effort would have been invested to other places ?
Maybe we had a working and stable Fastboot that can serve pre rendered pages of both Ember and React. Maybe we would already have routable components or engines. And maybe just maybe somebody would find the time to write all the missing documents and help get more developers contributing to Ember.
I doubt if there is any other framework that does what I’m asking Ember to do but I think this will be the ultimate framework solution. Setting a standard API for Models, Views, Routers, Controllers and Components will not only give frameworks using it an amazing edge but will help boost the entire ecosystem. In the last year it feels like Ember core is mostly busy copying features from other framework then leading the way with new and exciting features.
I really hope this post didn’t make you think Ember is a bad framework. Ember today is a great deal better than it was a year a go and it keeps improving rapidly. Many of the documentation have been improved even for the external modules. I’m going to keep using Ember since my code base to big to switch now and while I do plan to try other frameworks for newer projects it is mostly because I want to find a framework that is a better fit to my personal mindset. I’m sure that with whatever framework I will settle on I will still find issues and things that could be done better. So as I said at the beginning of this post you should look for more information than this post if your considering using Ember.