Let me add few valuable comments here in their entirety.
a month ago
You make some good points and I especially agree with the issues raised about accidental complexity and learning curve. However, I have to disagree about a few things:
First, Angular wants to own all your client-side code. Writing your app the Angular way means writing validation logic using Angular-specific validators, putting business logic in Angular-specific services, and connecting to the back-end via Angular’s built-in services.
I don’t think this is true. Angular does not force you to extend any base objects for services or otherwise contort your code to a specific form. Services are plain objects. Factories are plain functions. If you put one in a file, there’s nothing in that file that gives away that you’re even using Angular. Where that becomes Angular-specific is when you register that service or factory to an Angular module, but until then it’s just an object or a function.
Ditto for validators. Validators are functions that take the value and return a boolean that determines whether the value is valid. I don’t see how that’s Angular-specific. See https://docs.angularjs.org/api.
As to connecting to back-ends - yes, Angular provides a built-in $http service for doing that. But there’s nothing forcing you to use it. By all means, use an alternative if you have one. If that alternative isn’t Angular-aware you’ll just need to call scope.$apply() when results arrive from the backend.
Fundamentally, Angular assumes you use stateless “service” objects for logic and dumb data-structure objects (objects without methods) for state. […] By separating state and business logic, Angular breaks encapsulation and splits apart tightly coupled concepts. Rather than putting logic alongside the data it operates on, Angular wants you to spread the logic around your application. It risks the “shotgun surgery” code smell: any change requires making lots of little edits.
Two points about this, as I don’t think it’s as simple as that.
Firstly, Angular does not assume your service objects are stateless. There’s plenty of people writing stateful service layers for their Angular apps and doing just fine.
Now, where it becomes a problem is when you add immutability to the picture. Since services are singletons, that immediately forces you to add some indirection if you want both immutable models and stateful services. I agree that this is a problem and working with immutability should be easier. Mutable models, on the other hand, are no problem.
A couple of additional points on testability:
There’s no support for simulating browser events and it’s flat-out impossible to unit test HTML templates.
Angular doesn’t have support for simulating browser events, but jQuery does. Since Angular uses jQuery when it’s available, you can just include jQuery in your tests and trigger away. http://api.jquery.com/trigger/
If you want to test an HTML template in isolation, it’s certainly possible though perhaps not as simple as it should be. You can $compile and link the template and inspect how it behaves.
Angular focuses on allowing you to unit test business logic. But it only needs to do that because its architecture encourages putting business logic in the UI (specifically, in controllers and services). A better architecture would put business logic in objects that are independent of the UI, rendering the whole thing moot.
I wouldn’t call services “UI”, but yes, generally things like controllers and services are the easiest part to test in isolation. If you have business logic in objects that have nothing to do with Angular, the framework’s testing support won’t do much to help you but it certainly doesn’t get in the way either.
Custom directives can be tested, but it’s ugly to test a directive that contains another.
What I probably would have done in your example is either:
a) Test stockMarketRow and stockMarketCell as a unit, and verify the DOM structures that they together produce.
b) If I really wanted to isolate stockMarketRow for tests, I’d use a “mock directive” for stockMarketCell and verify the values passed to its scope. The same isolation techniques that apply in regular OO code can be used in cases like this.
Leo Horie Tero Parviainen
24 days ago
> Services are plain objects. Factories are plain functions. Ditto for validators
That's technically true, except that the idiomatic way to manage dependencies is via Angular's DI system, and using the injector API is far from being the same as working w/ POJOs and functions. Having actually needed to call Angular code from outside of it, I can say this is one place where the complexity of Angular really shows its face.
Yes, you could get away with using browserify instead of Angular's DI, but frankly, no one would think of doing that out of the box, and it sounds like an unfeasible refactor for even a year-old codebase.
Regarding the opinionated architecture point, I agree that it's not very opinionated (which could be argued as a documentation quality issue, actually). But there are obscure (but real) technical challenges that arise when you try to do things in various ways (e.g. reactive programming style tends to get messy because the need for data to be attached to $scope yields weird services). A co-worker ran into complexity wall issues when trying to create a single-responsibility directive architecture. A recurring problem for us was that the issues themselves were so complex that it's even hard to explain what the problem was.
Gleb Bahmutov Tero Parviainen
15 days ago
Agree with this reply. I have successfully used Angular with other frameworks (it plays nicely as self-contained widgets), including Backbone, Dojo, etc.
As far as testing - if you use my spec helper, you will be able to test everything without almost any boilerplate https://github.com/kensho/ng-d.
Other points raised - maybe complexity, but only because there are lots of parts in the framework.
21 days ago
Fully agree with this article. I used Angular for about a year and switched to Polymer about 7 months ago. Angular directives made it possible to code declaratively as if you were using web components in a time before web components were a thing. Now that they are a thing, unless you need to support IE8/9, I would use Polymer over any other framework, for both performance and simplicity reasons. If I needed to support IE 8/9 I would use React. I recently looked as some Angular code, and after even a short time away from it, it was hard to understand. People argue that it's popular so it much be a good choice for a long term project as it should be easy to find developers for, but few developers have a really strong understanding of it, which you need to get a complex app performing anywhere near reasonably.
V.K. I wish Polymer / Web Components / Shadow DOM were ready to use in a production code and there would be no danger of those mostly-Google technologies to go away. Google is notorious in dropping great things.
In my opinion, there is nothing more revolutionary in HTML / Web development than introduction of Web Components / Shadow DOM