AngularJS: The Bad Bits
When a bright new technology appears, it sometimes fascinates us and makes us think that everything is possible.
As we see it exceeding our expectations in some areas, we start believing that we can use that technology anywhere with relative ease. Past experience has proved otherwise: it's rather a recipe for pain! I am going to talk about my experience as part of the thoughtworks.com team using AngularJS to implement the interactive tech radar.
A bit of context
We have a Ruby, Sinatra and plain JavaScript stack. A bit of background on the project stack can be found in this article written by Thoughtworker Andy Robinson. One of the guiding principles is that maintainability of a codebase is achieved by minimising the accidental complexity. A corollary of this is that we strive to use libraries rather than frameworks. One concrete example is the choice of Sinatra over Rails mainly because the former, while a framework, is much lighter than the latter.
The interactive tech-radar was implemented in AngularJS. The choice of AngularJS enabled a fast path towards a Minimum Viable Product. It also allowed implementation of a richer client side interaction. The final product was a great improvement from the boring static page full of text we had before.
The war story
The immediate impact was on our build time. Introducing AngularJS increased the test time significantly. Our testing stack (RSpec, Capybara, PhantomJS) was appropriate for the kind of application we were developing: multiple pages served from a web-server with limited (but growing) JavaScript interaction inside a page. AngularJS put us in front of an interesting challenge: how can we test rich single-page apps with JavaScript interactions going across pages? Using an AngularJS specific tool like Protractor would have meant introducing a parallel testing stack with current one. The complexity of maintaining and working in 2 different testing stacks didn’t seem to pay off. We end up using tools that made our testing stack AngularJS-complaint (e.g capybara-angular). This started showing one of the disadvantages of using AngularJS: it does not work well with tools or libraries that are not AngularJS specific.
For the second iteration more features and bug fixes were on the list. As we started playing the stories we felt the burden of the learning curve more heavily. Small stories lasted for days, as we improved our understanding of AngularJS. We anticipated that, but underestimated how much time it would take us. The main reason was the framework nature of AngularJS. As any other framework, it promotes its own peculiar view of the world. In order to get the most of a framework one has to accept and use its way of doing things. Frameworks are wonderful in the sense that they can get you fast to a Minimum Viable Product but you have to pay the price of maintainability and evolution on the long run.
While working with it, we often found out that the only way is the AngularJS way. The use of JS libraries became heavily restricted. More often than not, you can only use a Javascript tool that's part of the its ecosystem. For example a JQuery based library won’t work very well with pages built in AngularJS. We also found out that doing simple things in JavaScript became hard. One example would be using the DOM onready/onload events (as AngularJS hijacks those events, you can not use them easily). Another example is that google analytics does not work directly with AngularJS. You would have to use AngularJS-specific libraries to make it work (e.g angulartics). Also, AngularJS introduced html in our codebase, as we were using slim for templating purposes. Having a new set of tools meant increasing the accidental complexity in our codebase making maintaining and evolving harder.
One of our business requirements is for our site to be available for non-JavaScript users. This meant that we had to duplicate almost all the interactive information we had in the radar (... breaking the DRY principle). All of it in a huge <noscript> tag! Another issue we looked at was the less than ideal Search Engine Optimization performance AngularJS provides. There are solutions out there to make it better (see this StackOverflow question) but they require additional work to be done.
The future
As we are looking forward to the future of the radar we see that next would be i18n. That means implementing an i18n mechanism in JavaScript that would duplicated the current one we have in Ruby. Given the pain we encounter so far we realise that, as the business requirements become more and more complex, we won't be able to cope by developing in AngularJS. At this point it seems that the likely way forward is removing AngularJS and replacing it with pages served from Ruby and plain ol' JavaScript. Even though it seemed like a tremendous task, a short spike showed that, with smart reuse of some existing JavaScript and html code, is a couple of days’ job.
Conclusion
While I assume that all the small problems we encounter have much simpler and elegant solutions, it does not change that fact that AngularJS brought in a lot of accidental complexity without paying the benefits for it. I would gladly take on board the price of using and learning AngularJS if I were developing a single page JavaScript app but I would think twice before I would consider using it for something else.
More opinions
A set of useful tips for developing an AngularJS application can be found in this Insights article by Thoughtworker Tania Gonzales. Details about a similar experience with AngularJS can be read in the Hacker News discussion. Different opinions can be read here or here. I am very keen to hear other interesting experiences with AngularJS. Please share yours in the comments section.
Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.