My first-time user experience


#1

Hi everyone!

There has been a lot of discussion on HN and here about how Ember is confusing for first-time users. Many people chimed in and reported how they gave up.

At first I was one of them but the prompt reaction from the Ember team made me reconsider. So last friday I gave Ember another chance. My goal was to replace spine.js in a small rails application with Ember. At the end of the day I was about to give up again.

But during the course of the weekend I reconsidered. Even though I did not accomplish much on friday, I very much like the result. Getting rid of all the jQuery-Code to manipulate the DOM is really really appealing.

So I decided to hang on and post my thoughts hoping it helps to improve the situation.

Ember: Embedding initial data in the page/App initialization

In my app I embed some information in the page as I render it on the server. This includes, but is not limited to, the user currently logged in. This is a use-case I suspect many have, so I searched the usual sources for examples how to accomplish this. And I found quite a few. But each was different, leaving me confused as to what might be the right way to do it.

A few solutions used code like this:

App.initializer({
    name: 'appBootstrap',
    initialize: function() { //...
    }
});

I thought, well this looks just like what I want: A way to hook into the app’s initialization. But being new to Ember I wanted to make sure, this was the right thing to do. Also, I am well aware of the many pre-1.0 API changes, so I also wanted to verify that this was still valid for 1.0.

As it turns out, I could not find documentation for the initializer() function anywhere. The guides do not include it and I could not find it in the API docs either.

So on to another solution:

I found a solution where someone used a route’s setupController() function. This one I could easily follow, but it seems to be only useful if I need the user in a particular Route/Controller context. But this is global state, so it is propably not a good idea to do this here.

Browsing the API docs I found another possibility: Using the ready() function of my application object. Coming from jQuery this looks familiar and indeed works very well for me. Still I remain confused, as I have not found examples on the web using this.

Ember: Storing global state

Once I have fetched my initial data I need to store it somewhere, so it can be easily accessed throughout the app. For the time being I went with setting it as a property on my application object. Works well and seems logical to me.

Still I remain confused as I found a lot of examples on the web where people go to great lengths to solve the very same problem in a much more complicated way. Some write specialized controllers for this, which to me seems wrong as I think controllers are meant to decorate data for views/templates.

Others inject this functionality into every single controller. This looks interesting but I have yet to find documentation for this feature so I can fully understand what they are doing there.

Ember Data: Lack of documentation

To be honest, my biggest concerns currently are with Ember Data. I understand that is is not fully done and that it is not strictly necessary to use it, but I need to share data with my rails app, so I need to use something. So I naturally tried Ember Data.

The biggest problem is of course the total lack of documentation. I know about the Model section in the Ember guides, but that is far from comprehensive. I have listed some areas where it is lacking below.

I was very surprised to find the following commit https://github.com/emberjs/data/commit/0445d7ecae191cd65ec38746d9f3d403c8e92f19. In it almost all actual documention is being removed from the README. The reason given was to remove outdated examples. Sadly not all of this has found its way into the guides. Also, I do not believe that everything that has been removed there was actually outdated.

Adjusting those pieces of information to the current state of the API cannot possibly be that hard. And the README is probably the first thing people turn to. It should at least have some usage examples imho.

Last but not least it would be very nice to have API docs similar to Ember core. I realize that Data’s functions and objects are not nearly as thoroughly documented. Still I would enjoy such a documentation to get an overview of what functions exist, who inherits what etc.

Ember Data: CRUD, but how?

While Data is not ready yet I suppose it already handles simple CRUD cases very well. Still only the Read part is documented. I have yet to find documentation on how to properly create, update or delete records.

One of the first things I tried was to delete a record. Coming from a rails background I immediately tried the destroy() function. That did indeed exist but had no effect whatsoever. I googled and found a note from an Ember dev saying I probably want to use deleteRecord() instead (no reason given). This did the trick for me even though I learned to my dismay that this does not automatically get persisted to the server (see next section).

Ember Data: Committing changes

So I managed to delete my record locally. Next I want it to be deleted on the server as well. I quickly learned that I need to “commit” changes in order for Data to make the necessary requests to the server. Well, I guess that might come in handy sometimes, even though I wished I could disable this in my app for now.

So, how do I commit the changes? Umm. Well, again it took me ages to find out. And again, I am still confused if I am doing it right.

Most examples I found used the following:

App.store.commit();

This seems reasonable. After all I defined the store on my application object and if this is the central authority that tracks all the changes, well then I can work with this. Of course, the store property has been removed/renamed and is written in upper case now. So I tried:

App.Store.commit();

Which of course does not work :cry:

Maybe that is not how you access the store. I found some examples using

DS.get('defaultStore');

But that seems wrong to me. Does this really get me the store I defined for my application?

After some more research, I finally found a solution that worked:

record.get('transaction').commit();

Very well. But I have no idea what I am doing there. And why it is even necessary. After all, I just want to get rid of a record for good. Now I have two function calls to accomplish this, one of which is counter-intuitive (coming a from a rails background that is) and one of which I do not understand. This is not (yet) optimized for developer happiness imho.

Ember Data: Complexity

The last thing I mentioned kind of suggests to me, that Data is a lot more complex than I care for. When I look at the architecture document this feeling is being reinforced. I have great respect for the Ember devs and I am confident that once it is ready, Data will be extremely powerful and handle many edge cases in a very elegant way.

But right now I cannot help but feel that this want to “get it right” and the one size fits all approach is holding Ember (with and without Data) back.

I mentioned wanting to port a spine.js application. Spine’s model layer is almost embarrassingly simple. But it works well for simple CRUD applications and due to its simplicity it can be easily extended to handle special cases if they arise in an app.

I would love to have something like that using Ember’s object model. This could also buy some more time to really polish Data and get it ready for prime time.

I am sorry if this comes off as a rant. It is really meant to be constructive. As I said, I am not giving up. And if you think this is helpful, I will continue to document my findings along the way.

Please keep up the good work!

David


#2

I concur with this; I was recently trying to do some troubleshooting from the Javascript console, and it took me at least an hour to suss out how to actually force the data-store to send the back-end request for a record created with createRecord.


#3

What they should really clean up is what they show on videos are not the same on documentation.