At first glance I was very impressed with Angular – the two-way binding removes the need for constantly updating the view and the scope objects makes for a clean separation between the controller and the view. There were other elements which were very appealing as well – a complete documentation site, a focus on testability, and a clean separation of concerns through built-in dependency injection. As I said, at first glance it definitely looks very impressive.
I’ve spoken to other developers who use Angular and the common complaint is always about the documentation. The Angular documentation is incredibly thin – meaning it briefly covers every topic – and suffers from a lack of code examples. For example, one of the things I struggled with early on was to use the $httpBackend module in E2E testing. Sure enough, there is a page in the documentation and it explains how to setup the $httpBackend object to mock out certain responses. However, after the 14-line code snippet the documentation simply states:
Afterwards, bootstrap your app with this new module.
What the documentation conveniently ignores is that you can’t simply inject a mock httpBackend into your application since your application will then stop working when you’re not in test mode. So you need to figure out a way to load all the test dependencies and setup only in test mode while avoiding possible issues when you deploy your application. There is also an additional dependency on the angular-mocks script which you need to include. These kinds of omissions are very common and can very easily cause you to waste fruitless hours experimenting with different solutions to find the answer.
Of course, since Angular is an open source framework many enthusiasts will simply see this as a community problem – the source code is available for anyone to read – we can simply write the documentation ourselves. While I disagree with the sentiment, I find this even more difficult with Angular since the framework is very large and complicated. It takes a substantial effort from any developer to understand the source code to the extent where writing documentation is possible. For example, the uncompressed AngularJS core library is 14,846 lines of code. Compare this to the the uncompressed core library for SpineJS which is only 1174 lines! I would be the first to advocate that lines of code is a terrible measure of source code, but the numbers definitely indicate that Angular is a large framework which makes the lack of documentation very painful.
The other problem with the documentation is the incredible lack of any SEO (Search Engine Optimization) focus. I say incredible because I would expect a library created and maintained by Google developers to at least be decently optimized for search, while the exact opposite is true. The Angular documentation site is actually a very good example of how bad SEO can be. For example, this afternoon I couldn’t remember all the different matchers for E2E testing so I simply googled it.
The only link to the Angular documentation is to a tutorial link – the actual page that contains the matchers is nowhere to be seen. If you add ‘documentation’ to the search term you simply get the root of the documentation site.
Angular supports two types of testing – Unit testing and E2E testing (end-to-end). The Unit testing uses Jasmine (which is great) and the E2E testing is part of the Angular framework.
Angular does go a long way towards making your code testable (and you can definitely TDD most of it), but there are some rather painful issues along the way. For one thing, the documentation doesn’t really offer much in the way of best practices (at the time of writing, the Unit testing documentation has 6 sections which are blank) which means you will probably spend quite some time figuring out how to properly create your controllers and inject mock objects where necessary.
Once you get over the initial learning curve you will need to contend with 2 frameworks which have very similar – yet different – syntax. The Unit testing framework uses the popular Jasmine matchers while the E2E framework uses it’s own set of matchers. The documentation describes it as Jasmine-like BDD syntax.
The Angular framework doesn’t have any sort of test runner built-in, although Karma is suggested. Unfortunately this is another pain point. For example, this is some example output from a test failure in my current project (obfuscated, of course).
.................................... PhantomJS 1.9 (Mac) Validations should return false when none of the subfields are filled in FAILED Expected true to be falsy. PhantomJS 1.9 (Mac) Validations should return false when only month subfield is filled in FAILED Expected true to be falsy. ................................................................................
Unfortunately the runner doesn’t give us any indication which file the test belongs to, or which line number. This means you usually need to do some creative grep-ing to find the culprit. To avoid this issue we have started to use describe blocks with the name of the controller or service, which is less than ideal.
The Overall Complexity
The bottom line is that Angular has a steep learning curve. Don’t underestimate it, especially given the lack of documentation and best practices.
Angular is still great
After all this negativity you might think that I’m completely against Angular. Not in the least. I am merely pointing out the different pains you might experience if you’re working with Angular on a daily basis.