Angular.JS - Are you holding it wrong?
Over the past year, I have spent a fair amount of time introducing and working with Google's client-side framework: Angular.JS. Leveraging the inevitable gift of hindsight, I have been left with some interesting takeaways regarding when it is or is not appropriate to select Angular for addressing specific client-side concerns.
Before I go any further, I would like to go on record as saying I am not an Angular expert, just an adopter of the technology based on the decision to improve the readability, functionality and efficiency of our application's client-side code. That being said, I would like to address the first and most talked about concern of this robust framework: The learning curve.
Developers love to try new things, and when a new technology comes along and is created and championed by one of our greatest technological innovators, in this case Google, the initial rush of adoption can generally be based on the intrinsic need for developers to learn and improve. Normally this is an awesome trait to have as a developer, but the major drawback to this inherent tendency is that sometimes the learning curve can be so steep, that by the time a developer has any real traction with the technology, they are already over-invested to the point of not having the luxury of backing out.
If you find yourself using Angular, and you are somewhere past the initial learning peak, and feel like you may have made the wrong decision... you could be holding it wrong. This graphic from Ben Nadel describes the process for many developers:
The concept of "holding it wrong" can be defined in the following ways:
- Applying the technology to an environment that either did not need such a full-featured framework, or does not structurally lend itself to Angular implementation at all.
- Usage in an environment where the learning curve of the development is not conductive to meeting project goals and deadlines.
At the O'Reilly Fluent conference earlier this year, I had the chance to speak to web developers from all different middle tier technologies regarding their particular preferences for client-side technology. The conference itself is a "full stack" web developer conference, but the obvious overlap is that although developers may be using different web server technologies and databases, everyone's application has to run in the same browsers, so everyone will be dealing with the same client-side challenges.
An overwhelming, almost religious response to the Angular appropriateness "debate" was that it could be most efficiently leveraged in the following scenarios:
Single Page Applications
If you're developing a single page application with a server-side technology like Node.JS, and are looking for a way to easily manage the view data and UI, with 2-way binding to your data model, this is the way to go. This is the architectural space that birthed the MEAN stack (Mongo, Express, Angular, Node), and to me is Angular's natural habitat.
New Projects in General
If you're not using MEAN stack, and you have some experience with Angular and are looking to expand on this experience, a new project (regardless of server-side technology) is a great place to start. This way you will have the opportunity to build your UI, directives, and core methods around Angular vs. trying to get your existing code to play nicely with it.
Now, during the time of speaking with other developers at Fluent, we were already well into our "conversion" process from pure JS/JQuery and other JS templating engines that I won't mention, to Angular within our legacy .NET web application. I began to notice that some of the pain points I was having were directly related to the choice made to use Angular for the purpose of converting/refreshing existing non-Angular code, and having the existing pages built around a relatively robust server-side technology, and out-dated pure Javascript and JQuery.
In summary, our team ran into the following issues:
Where do you stop?
In the process of "converting" existing JS functionality to Angular (which generally looks like more of a rewrite or reverse engineering), we ran into the issue of forming appropriate segues from existing code to Angular code. Angular tends to be overbearing with the DOM within its scopes, so often times more work had to be done for a particular page than was initially expected, causing scope creep.
Initial Page Load
Coming from a standard web back end with simple DOM-manipulating JS on the client, the initial page state was previously rendered by the server itself. We found ourselves in a scenario where the Angular framework was being loaded, and then making requests back to the server for data, which caused controls and resources on the page to be loaded at different times and behave strnagely. This initially created a bad user experience and was partially addressed by employing more loading graphics. The question at hand was whether this was ideal to begin with, given that our MVC pattern could easily render the view from the server on the first load, providing no strange behavior for the user.
Accepted Practice
As the team learned Angular at their own pace, they began to understand more as they went along, and want to refactor their old, less-than-ideal code. As this happened, it became obvious that some directives were being rewritten vs. reused, and that there was a deviation of certain preferences like where template files would be housed, whether the JS would be on-page or in separate includes, or where the shared directive resources would live. This caused extra time to be spent, which is seldom accounted for in project planning.
Pattern Inception
In taking a closer look at the pattern we had going with the project, it became obvious that some of the more robust features of the view engine were being offset or inappropriately replaced by the ability to do similar things on the client. When you have a MVVW pattern as part of the V in MVC, you COULD end up with something like MMVVWVC if you're not careful. At this point you risk having business logic on the client, and other scary no-nos. More training and compliance from developers is required to make sure that everyone is on the same page, and your full-stack developers feel themselves becoming front-enders.
Our ongoing learning experience with Angular has been a journey of peaks and valleys, and we await the release of 2.0, which currently does not include a migration path from the original version, but promises to be a bit of a "softer" approach. It also comes complete with collaboration from Microsoft on TypeScript, and moves toward advancing the capabilities of the modern browser and client-side development as a whole, which I think most of us can get on board with.
At this point, I'm wondering if I took the wrong approach in the conversion. Instead of replacing individual elements with angular and then gluing that into the existing code, it might have made more sense to write angular wrappers for everything up front and then turned on angular for the entire page.
The other issue is completely underestimating the complexity of cleaning up the existing code so that it can be converted. Some of those files are extremely obtuse.
I think the biggest thing going against the angular grain on "that application" are the pages where angular is handling multiple disconnected elements on the same page. The pages that are completely angular load faster and have fewer issues.
Great article, Ian. You're more brave than I am, I thrice loaded up the Angular libs and docs ready to code my next project, and each time the learning curve blasted my time estimates out of the water. Backbone has been my staple for a while now, but I'm waiting for the perfect project to take up that Angular challenge again.