AngularJS Post-mortem

August 08, 2013

AngularJS is the new popular client-side Javascript application framework developed by Google. We have recently adopted it at Vista Higher Learning for building our latest features that require a lot client-side logic. Now that I have a few applications under my belt, it’s time to talk about my experience.

If you want a quick TL;DR: I think AngularJS is good, but it has a steep learning curve and there’s no well defined set of best practices.

Note: I will be using plenty of terms that will probably only make sense for people that have used AngularJS.

The Good Stuff

These are the things that went well. The things that made me glad that we chose to use AngularJS.

Easier Testing

Our Javascript test suite uses Jasmine. AngularJS is built with test frameworks like Jasmine in mind. AngularJS could tends to be easily testable due to dependency injection. When the components of an application don’t rely on global state, it is easier to mock services for unit tests.

Separation of Concerns

AngularJS stresses separating the view from the data structures and logic behind it. I think everyone that’s written a somewhat complex JQuery application can relate to the mess of CSS selectors and click callbacks that the code quickly degenerates into.

AngularJS allows you to break up the DOM into logical chunks that are handled by separate controllers. Treating the application as many small pieces working together rather than one giant DOM blob keeps the code clean. Message passing via $emit and $broadcast keeps controllers loosely coupled to each other.

No More JQuery Spaghetti

Directives, the strategy for encapsulating DOM manipulation, are wonderful. It is an elegant solution to the mess that was JQuery selectors and event callbacks. AngularJS comes with a lot of directives out of the box to handle the most common stuff like showing/hiding elements, handling clicks, dynamically setting CSS classes.

More Maintainable Code

AngularJS is feature-rich. It does a lot on your behalf, which greatly reduces the amount of boilerplate code needed to get a prototype up and running. I had the opportunity to essentially rewrite an existing JQuery application using AngularJS. The results were clear: The AngularJS version had fewer lines of code, was more readable, and was easier to debug.

Bumps in the Road

These are the things that didn’t go smoothly. They boil down to AngularJS having a steep learning curve and ill-informed software design decisions on my part.

Understanding the Magic

A lot of things seem to happen by magic. For example, it is possible to make a asynchronous request and get a promise object in return. When the promise is assigned to a variable on $scope, AngularJS not only knows to ignore it while the request hasn’t finished, but it will re-assign to that variable the value of the asynchronous call when it completes. It is a nice feature, but it takes some digging to find out what is really going on.

Poor Documentation

I know I’m not the only one that hates the official AngularJS documentation. The documentation is getting more complete, but its still not very useful. Functions frequently have a blurb describing what they do, but no explanation of the parameter list. It’s hard to use a function that doesn’t describe what it expects for input.

When the documentation confused us, which it did frequently, we turned to the AngularJS book from O’Reilly for help. I need to get around to reading more of it.

RESTful Resources and Rails

AngularJS claims to be targeted at CRUD applications, but using the HTTP backend and the Resource abstraction that sits on top of it was particularly difficult. A good amount of time was spent on trying to get the HTTP requests from resources to conform to what our Rails backend expects, like root-wrapping.

Bloated Controllers

I frequently made controllers that had too much state and logic that should have been extracted into services/factories/etc. A controller would start out slim but would quickly grow to several hundred lines of code as features were added. Controllers should be the middle man between the view and the model and that’s it.

Some tell-tale signs that a controller is becoming bloated:

  • There are a lot of private functions (not defined on $scope)

  • Functions are defined on $scope just so you can unit-test them, but are never used in the template

I attribute controller bloat to a lack of knowing the appropriate uses for other AngularJS components. It was easy to just keep adding to the controller.

Conclusion

Overall, I think things went well, but I (and the rest of my team) made a lot of beginner mistakes. But that’s the learning process, isn’t it?

Now that I know more about AngularJS, it will be easier to make better design decisions moving forward.

I believe that as AngularJS continues to mature, some concensus in the community about best practices will emerge that will make things easier for beginners.