What I learned from bringing an AngularJS app to production

A couple of months ago, I was innocently asked by co-worker, author, F# MVP and all-around-nice-guy, Jamie Dixon if I wanted to participate in a work-based hackathon for the weekend. I naively said “sure!” Well, we ended up winning 1st place and part of first place was that you then had to bring that idea to production. We just did one of our final drops to production, for a bigger roll-out later in the month – and I thought I’d write down what I learned.

image

Hackathon vs Rapid Application Development:
The first thing I realized, which causes some problems, is that the motivations and incentives are different, when you are just trying to “crank out an app” in a very short period of time for a hackathon, versus doing legitimate development for a real app.

Now, you might say: “what do you mean by that, isn’t all of your code production quality? You don’t have two ways of writing an app, do you?”

Let me clarify. I do definitely try to always write production code. However, in the example of a hackathon, where you literally have hours or minutes left – there will be many more shortcuts taken, versus what would be tolerable in a production environment. But wait, that wasn’t even our problem. Me and Jamie both believe in writing good-quality code and trying to keep the codebase as clean as we can, regardless. The problem was that in a Hackathon, you want the most bang for your buck.

So, we used some previously unproven technologies to try to be as innovative as possible. This is great for a hackathon; and horrible for a production app!

This ended up being one of the main problems. I’d done Hello, World! functionality with these technologies before, but haven’t taken an app to production with them before, and not together.

Put another way, if you are starting a new app, you want to embrace some innovation, integrate some new technologies, but if the WHOLE APP is nothing but cutting edge stuff, you are setting yourself up for a world of hurt! This is bad because newer technologies aren’t going have as good documentation, and there isn’t going to be nearly as much on StackOverflow.

This is the crux of the problem. You take one approach for a hackathon, and you take a different approach for a production app. Because we wrote this as a hackathon app, this really killed later on!

So – if you are coding a hackathon, then use all cutting-edge stuff if you want! But if you are writing a brand new app, use mostly-known technologies and leverage one, maybe two new things, to keep your sanity. In our case, we shot ourselves in the foot because we used all innovative things (to us), but then had to suffer the learning curve of quickly bringing them to production!

The Architecture of the app:
This was an app around people self-reporting campaign contributions. This means that we needed:

  • Authentication/authorization
  • Web front-end
  • A database
  • A rules engine

So, what we used was:

  • Authentication – used SiteMinder, because OAuth would’ve taken too much work
  • Authorization – used Web API custom attributes. There will be a future blog post on that – lots of lessons learned.
  • Look/feel – bootstrap, because that’s my go to technology for that
  • UI Data binding/UI logic – AngularJS v1.x
  • REST API – ASP.NET Web API
  • Database access – Code-First Entity Framework with the Repository Pattern
  • Database – SQL Server (code-first, push changes when the app runs, and re-seed known values)
  • Rules engine – very small amount of curt, complexticated F# code. I don’t really understand it, so you’d need to talk to Jamie about that one – or maybe he’ll be doing a blog post on it?

One of the biggest unknowns was the viability of using AngularJS for a tediousness of a production app. It’s great for simple stuff, but what about when things start getting nasty and you need all sorts of special cases, like you do in real code. How well does it scale?

In this case, we did build this as an AngularJS single page application (SPA), which uses AngularJS client-side routing – which has some pros and cons.

As it turned out, the rules engine, repositories, server-side code and unit tests were all pretty-well taken care of in that first hackathon weekend. The remaining 2 months was almost exclusively working in HTML and JavaScript. That means, the app is mostly JavaScript. Ugg.

But what’s wrong with JavaScript?
I know, I know, JavaScript is the darling of the technology world at the moment. The reason for that is because it’s a relatively simple technology, which works on everything, and can generally get the job done.

However, it’s not as simple as that. A big benefit of object oriented programming is that you can easily manage and abstract dependencies – via interfaces. A big benefit of functional programming is you can do the same, but with function pointers. With these professional-level languages, you can purposely create a well-managed codebase.

With JavaScript, I found that no matter how much I tried to organize my code into: namespaces, classes, or AngularJS controllers, directives, and services – I just ended up with a lot of disorganized JavaScript.

JavaScript is like earbud cables, it naturally wants to keep finding it’s way from order, to disorder.

Worse is that although you can technically unit test JavaScript, in reality, that too is kind of a big mess. If you are coming from a world where your production code is separate from unit testing code, and where a nice, clean unit testing framework runs tests and gives you code coverage – the JavaScript equivalent is a far, far cry.

I didn’t do any JavaScript unit testing, but it seems like Jasmine is the de facto standard. If you want to get a taste for how that works, check out this YouTube playlist which seems to be quite good!

So, with an architecture like this, a big majority of the code is going to be JavaScript – which is both very difficult to effectively organize, and very difficult/tedious to test.

The good things:
Some things which I think work really well in this stack that we used:

  1. Entity Framework – we came up with some good, creative ways to deal with .Include(“..”) statements to make sure you’re bringing back the smallest graph of data possible, for each call.
  2. Repository Pattern – I still remain convinced this is the most-ideal way to abstract-away Entity Framework. For God-knows what reason, there is still no IDbContext or IDbSet so you can’t effectively mock any away your database. It’s crazy, but to get around that, having a simple repository interface makes everything downstream, completely testable!
  3. Web API – the patterns for Web API are pretty good – and the built-in support for giving back standard error codes was helpful too. We came up with some great, small, succinct code for our REST API.
  4. Bootstrap + Font Awesome – both of these made it very easy to lay out professional-looking, consistent pages, with appropriate icons. No complaints, here!
  5. AngularJS – this framework does the routing of the requests and the data-binding. On both fronts, it does this well, generally. There are some notable exceptions though, listed below.

Overall though, this collection of technologies worked very well together and development went VERY fast, despite the learning curve.

The bad things:
If the app was built pretty quickly, where did all of the time go? Well, it was troubleshooting problems. Looking back, here are the biggest problems I’ve had:

  1. AngularJS – maintaining state (at the site level) – although you can use $rootScope to keep track of the current user, we never came up with good techniques for figuring out when the user is logged-in, when we got their user info back from the REST call, and detecting if there was any change in that. In other words, sometimes the site is awkward when it first loads and it takes 4 seconds for the user information to populate.
  2. AngularJS – maintaining state (at the page level) – this isn’t so much difficult, but it just got to be unwieldy. Since your $scope object for that page is available to everything, it basically acts like a global variable. Global variables are inherently difficult to keep contained, and other actors can unexpectedly change a value.
  3. AngularJS – maintaining state (using a wizard, within a wizard) – this is the hell I was in the for the last two weeks. There was a $scope for the page, the $scope for a “wizard” I made, with it’s own controller, and then on one step of that wizard, that could pop another wizard, which had it’s own $scope. Sometimes I needed to notify the parent window from the inner wizard; sometimes I needed to trigger something from the main window, in the inner wizard. This really got to be unwieldy. I spent a lot of time in the JavaScript debugger to figure out which scope could see which data from which other scope.
  4. AngularJS – dealing with a DatePicker ending up being a 2 day ordeal. Despite there being AngularUI and countless implementations, I didn’t find any that worked correctly AND which worked on all browsers. I ended up using a raw jQuery UI data picker, and $watch-ing some events. It does technically work, but it’s a mess, every place I need to have a date field.
  5. Performance when developing locally – I still have no idea why, but locally, all of my REST calls took just about 5 seconds. On the server, it would be sub-second. So, this made local development slow and annoying. The workstation I worked on was an i7 with 16GB of RAM and an SSD – it wasn’t a simple resource problem.

So although development did move quickly, there were some significantly frustrating problems that came about too.

 

Bottom line:
So now that we are in production, what is my take on AngularJS v1.x? Well, it’s a mixed-bag. For a simple app, man, this entire stack works really well together. However, as we got into more complexity, the JavaScript quickly started turning into a mess. You just can’t really organize that code very well for some reason.

The other thing is: should you use single page applications with AngularJS routing? Well, again, for a simple app – I think it’s kind of ideal to do it that way, because it can be executed  pretty nicely. However, for a medium to large app, I think the way to do would be to use something like ASP.NET MVC to provide the structure of the site and initial HTML – and then use AngularJS on those specific pages, to make each one of those views dynamic, by using data binding and REST services.

Having done web development for 20+ years, I will say that the current state of the art is the best it’s ever been. The developer can be so productive, with so little code, in comparison with yesteryear. So, although I found some limitations with AngularJS – I still think it’s a pretty great framework.

Posted in ASP.NET, ASP.NET MVC, Computers and Internet, Development Tools, Entity Framework, General, JQuery, New Technology, Professional Development, SQL, Uncategorized, Visual Studio, Web Services
8 comments on “What I learned from bringing an AngularJS app to production
  1. Mark S. says:

    Great perspective Rob. I’d love to hear what Jamie has to say about the rules engine. Keep sharing as you learn.

    Like

    • Robert Seder says:

      Hey Mark – long time no hear!! Thanks, and yeah, he’s pretty much a sorcerer when it comes to F# – he said he is going to pick up blogging, now that his book is finished. Anyhow – thanks much and I hope you are well!

      Like

  2. Ven says:

    I love your observations Rob! we are doing a project using the same technologies/modules you mentioned and I concur with you. A couple of things I would like to add is to use TypeScript for large client side code projects. This will help to organize the code and use client side JScript frameworks only when you have a matured team!

    Like

  3. keslavi says:

    enjoyed the perspective! I’m trying to implement angular2 against an existing siteminder rest service. the jquery call works and i see the smssession cookie.
    but the angular call does not have it.
    what’s the secret recipe to make the http call work?

    Like

    • Robert Seder says:

      Glad you found it useful! I’m not sure, but I do know that jQuery “context” seems to be incompatible with the $scope context of AngularJS. There is a lot written up on not “crossing” these two technologies. Whatever you can do in jQuery, you can do with AngularJS, so the guidance is to just stick with one technology. I hope that helps!

      Like

  4. Daniel Lee says:

    Very interested to hear more about how you ended up integrating SiteMinder authentication with the Angular front end. Could you offer more details or point me to the material you used to get that off the ground?

    Like

    • Rob says:

      In the end, we never did come up with a good solution. First, we had to use ENTLM authentication (it doesn’t prompt you for credentials), so it would magically re-authenticate the user as REST API calls were made. However, that still doesn’t work quite right. We tried FORMS authentication, where you use a login.fcc, and in AngularJS, look for a 302-Redirect when you go to make REST API calls (because that means SiteMinder is redirecting you to a login page), and then redirect the whole web page to that login page. In the end, it’s ugly! The ENTLM solution works OK and the users know to just CTRL+R (refresh without using cache) if the website ever acts up. Terrible, I know – but we didn’t have any more time to work on it.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 2 other followers

%d bloggers like this: