Saturday, May 24, 2014

Ember take two

I went back to Rails for my latest project (personal / family photo store) and have been having quite a bit of fun with it.

The project had reached a bit of a crossroads, where the basic proof of concept was in and working, and it was actually functional. I have an idea of what the app should look like, and I've used it enough to know a few things that work well and a few things that won't work the way I had initially thought they would.

Basically, I had a prototype. And we all know the rule for a prototype: throw it away. But that means I need to know what to replace it with.

While my last project with Ember.js was a success, it performed poorly on mobile devices. However this project is not going to be mobile specific, and I can have a basic (js-lite) front end with minimal functionality for mobile. (Basically, I want to be able to upload photos from my phone, but I don't need the photo management tools on the mobile version)

(I hear the word "mobile" in my head with a British accent. It makes me feel proper.)

Another developer I've been working with recently has been advocating vanilla web development with turbolinks for speed. And I think that could work well, for a certain class of application. But that's not the application I build.


I like my client-side functionality. The prototype I built was actually developed with minimal javascript to start - but the repetition in the html pained me. Think of it this way: on a button click, we need to package up all of the data for that server request together. If we're not using a javascript framework, all of that data needs to be encapsulated in the html elements, ideally via data-* attributes.

We have two choices: either we use jQuery to navigate around the html finding all of the pieces of data we need to send the server request, or we encapsulate all of the required data onto the element that has the functionality assigned to it.

The first way, we've now bound our html and javascript together in this really fragile way. We have to change them in unison, and if we have multiple functions that depend on a root id (as a random example) we have to be careful not to break one when we modify another. We're building logic puzzles into our code.

The second way is safer - when clicking on an html element we only need that element to satisfy the requirements for the server request. This is the direction I went in, and while it does work, it leaves us with a lot of repetition. And since we're trying for minimal javascript, we ideally need to refresh the page after any server request which modifies state. (and what request wouldn't modify state?)  So now our HTML is bloated and we're making a lot of requests for it.

The way this problem is usually solved is to limit functionality to very specific pages. Effectively, you use REST principles and can only modify a single domain-model object from it's own page. Thus, you never have to reload the entire list, because there are no "mutation" functions on the list page.

It may be harsh, but I think that's lazy. If you're building an application that is so cumbersome that you don't want to use it, why build it? It reflects poorly on you the developer and on developers as a profession.

Build it correctly. Put commonly used functionality in places where it can be easily accessed. If your application structure doesn't allow that - then your application structure is wrong. Modern webapps are javascript client applications talking over HTML to the server. It's going to be more and more difficult moving forward for a webapp to simply be a static view into the server state with a few sprinkles of javascript.

What does this mean for me? It means that I restarted my application in Ember.js. It may not always be the best choice, but I think that they have the right idea. Ember's goal is to be able to build applications that run in a browser, and that is the future. It was the future in 1996 when Microsoft was pushing ActiveX, and it's still the future today.

It's taken me four hours to get my app displaying a page of photos. This was mostly due to me still trying to wrap my head around the way Ember works. I'm using the ember-rails gem, which adds some neat albeit poorly-documented generators. I've also finally started using ember-data for my models. The documentation is much improved from the last time I looked at it, and I managed to get my models up and running in less than an hour. There was a lot of Google searching, but this blog post and this stack overflow question and answer were really helpful.

One thing that does discourage me - I've had limited success in finding walkthroughs on setting up even slightly complex ember apps. Most walkthroughs explain how to get rails and ember running, but stop once the application itself is loading. Might be something to do once I feel more comfortable with Ember.js.

No comments:

Post a Comment