初めまして、GoogleのAngular Teamに働いてるブライアンです。よろしくお願いします。
僕はあまり日本語が分からないけども、日本の開発者達の情熱が見えます。勉強会とか、記事とか、イベントがたくさんありますね。日本のAngularのコミュニティはすごいと思います。Angular 2を使ってくれることに楽しみにしています。
When Okuno-san asked me to write an article, I thought for a while on what I could contribute. I wanted to write about my experiences working on Angular, especially what I've learned on the path from Angular 1 to Angular 2.
The power of declarative code
In my opinion, the most important aspect of Angular 1's template system is that it is declarative. The implication of being declarative is that you only have to describe what the end result of the template is.
Contrastingly, applications used to be written with one method to initialize the view, and several others to update it. Consider this code that you might see in a jQuery or Backbone-style application:
function View(name) {
this.element = $('<div>Name: <span class="name">' + name + '</span</div>');
}
View.prototype.addJob = function (newJob) {
this.element.append('Job: <span class="job">' + newJob + '</span>');
};
View.prototype.updateJob = function (newJob) {
this.element.find('.job').html(newJob);
};
Although the above code might work fine initially, if the assumptions around it change, it might break. Consider:
- What happens if
view.updateJob
is called beforeview.addJob
? We throw an error. - What if you need to update the HTML of the view? All of the methods that touch the view must be updated.
- What happens if we want to update the
name
part of the view? We have to write additional code.
In each one of these cases, the developer must manually make changes that are error-prone. In contrast, the AngularJS 1 version of the above would be something like:
<div>Name: {{name}} | Job: {{job}}</div>
With AngularJS, you write substantially less code, and the code is more flexible. We avoid duplication, and we can safely build upon existing code.
From templates to components
Although the declarative approach to templates eliminated one source of bugs, one thing that became apparent with Angular 1 was that the scoping model was confusing.
Consider this code:
<span>{{selectedItem}}</span>
<ul>
<li ng-repeat="item in list">
<a ng-click="selectedItem = item">{{item}}</a>
</li>
</ul>
The problem is that because ng-repeat
introduces scopes, we don't know which scope selectedItem
will be set on.
First we introduced the controllerAs
option to directives. In 1.4, we added bindToController
to try to fix this problem without making breaking changes to Angular. But what we realized was that we needed to explicitly handle the relationship between parent and child components. In order to realize this idea, we had to make semantic changes to how scopes and directives work.
Managing change
We often think about Angular as many lines of code, or as a set of features, or as an API. Each of these are useful lenses, but I think it's also important to think of Angular as a collection of ideas. As we work with Angular, our ideas improve. And that's where change comes from.
In the context of templates above, we see ideas that were both good (declarative), and problematic (inheriting template scope). We often think of "Angular templates" as one thing, but it's really the implementation of a set of ideas.
The art of framework development is in considering individual aspects of a system and trying them in different combination. What happens when we introduce an idea like "one-way data-flow" into Angular? What effect would immutable persistent data structures have? What about observables? Do observables and immutable data structs work together? What about with one-way data-flow?
This is not only the case for the template example, but really for every aspect of framework and application code.
The future of web development
As we've seen, the only constant in the web development world is change. ES6 (or ES2015 as some call it) introduces new language features. Tools like Babel and TypeScript come along and add new possibilities. Browsers add new features (like service workers), and JS engines are constantly adding new optimizations. This changes the performance characteristics of existing and new code. In turn, libraries and frameworks need to accommodate these changes, and improve to take advantage of new capabilities. The changes cascade to application code as well.
The best way to address these changes is to think critically about the code you write: identify patterns and ideas, notice when you encounter the same types of problems. What happens when you reify an idea into a framework-level abstraction? Does everything fit into such an abstraction? What are the costs? Can the idea replace an existing idea? Finally, we need more dialog about high-level ideas in web development. Write a blog post, or file a GitHub issue.
Feel free to contact me even (日本語でもいいだよ!). I'm always eager for suggestions to improve Angular.