AngularJSの導入の際に注意すべきこと

フロントエンド歴(累積で)6ヶ月くらいです。主に知識不足と経験不足から間違った内容を記述してしまうことがあるかもしれません。その際はコメント欄やツイッターなどで指摘していただけると助かります。

## 対象
Javascript の知識はあり、Angular JS を初めて導入することになった方。
AngularJS を触ったことがない人が、最初に間違えやすい部分(正直には、自分が間違えて後々修正することになった部分)について主に紹介します。AngularJS のメリットや仕組みについては紹介しません。

## 結論
Angular JS のスタイルガイドを読みましょう．
#### 理由
新しいフレームワークや言語を導入するときにスタイルガイドは大きな助けになります。よく考えられて書かれているいるスタイルガイドには、`なぜ`そうするべきなのか、という理由もかかれています。そのため、特に自己流で書いている場合は今まで気がつくことが出来なかった発見があります。(AngularJSにかぎらず、現在使用している技術に関するスタイルガイドは読む価値があると思います。)

#### 参考1
[johnpapa/angular-styleguide (英語)](https://github.com/johnpapa/angular-styleguide)
[johnpapa/angular-styleguide (日本語版)]
(https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md)
#### 参考2
[mgechev/angularjs-style-guide (英語)]
(https://github.com/mgechev/angularjs-style-guide)
[mgechev/angularjs-style-guide (日本語版)]
(https://github.com/mgechev/angularjs-style-guide/blob/master/README-ja-jp.md)


## AngularJS を導入する上での注意点

すでに結論を書いてしまっているので、以下の内容はスタイルガイドを読んで頂けば読む必要はありません。その上で、自分が`スタイルガイドを読まなかったために(orz)`気がつくのが遅れ、後々大きく変更した部分を紹介します。読む上での注意なのですが、
*スタイルガイドはあくまでガイドであり、強制されるものではありません。*
以下の内容についても、あくまでも個人的な判断を元に書かれている点にご注意ください。

## ディレクトリ構造
*関連のある HTMLファイル, controller, directive などがわかるようにしましょう。* [参考](https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md#style-y152)

##### 具体例
```
app/
    app.js
    components/
        calendar.directive.js
        calendar.directive.html
        user-profile.directive.js
        user-profile.directive.html
    layout/
        shell.html
        shell.controller.js
        topnav.html
        topnav.controller.js
    people/
        attendees.html
        attendees.controller.js
        people.routes.js
        speakers.html
        speakers.controller.js
        speaker-detail.html
        speaker-detail.controller.js
...
```
##### 理由

* 新しくプロジェクトに関わる人が、変更するファイルに関連する実装を探しやすくするため


[ここ](https://github.com/mgechev/angularjs-style-guide/blob/master/README-ja-jp.md#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E9%80%A0) などにも記述されていますが、AngularJS のディレクトリ構造を考える際に以下のような構造が思いつかれると思います。

```
├── app
│   ├── app.js
│   ├── controllers
│   │   ├── FirstCtrl.js
│   │   └── SecondCtrl.js
│   ├── directives
│   │   ├── directive1.js
│   │   └── directive2.js
│   ├── filters
...
```
`controller` や `directive` といった機能ごとに分離されたディレクトリ構造です。( オブジェクト思考的には [関心の分離](http://ja.wikipedia.org/wiki/%E9%96%A2%E5%BF%83%E3%81%AE%E5%88%86%E9%9B%A2) なんて言ったりするんでしょうか。自信ないですが。) 

自分はまさにこの構造でコードを書き始めました。が、主に `プロジェクトのファイル数の増加が原因` で管理が困難になりました。結果としては

* `controller` や `directive`, `html ファイル` を探すためにファイル移動をして、探して、というのが、ファイルを配置した本人であってもめんどくさい
* 新しくプロジェクトに加入した方が、変更に関連するファイルを探すのが難しい/面倒くさい

という状況になりました。

そのため、AngularJS のプロジェクトでは関連のあるファイルがわかるようにディレクトリ構造を区切ることを薦めます。

(余談ですが、バックエンドの方が触る機会が多かったため、、`controller` や `model` といった機能ごとにディレクトリを分けると信じて疑ってなかったです。そういう意味でも、AngularJS を触ることでこのようなやり方もあるのだと勉強になりました)


## `$scope` の代わりに `this + controller as` を利用する

#### 具体例

```js:customer.controller.js
function CustomerCtrl() {
    var vm = this;
    vm.name = {};
    vm.sendMessage = function() { };
}
```

```html:customer.html
<div ng-controller="CustomerCtrl as vm">
    {{ vm.name }}
</div>
```

#### 理由
* コントローラーがネストする際などに柔軟に対応できる

```html:customer.html
<div ng-controller="Customer1Ctrl as vm1">
    <div ng-controller="Customer2Ctrl as vm2">
       {{ vm1.name }}
       {{ vm2.name }}
    </div>
</div>
<!-- Customer1Ctrl も Customer2Ctrl も name を持っているとする -->
```
[ここ](https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md#style-y030) の辺が参考になります。


## その他の一般的に役に立ちそうなスタイルガイド
上記のもの(たとえばディレクトリ構造)と比較して、コードを書き初めでなくても対応はしやすく、どのプロジェクトでも参考になりそう(かも？)なものを以下に列挙します。他におすすめなどを教えていただけると、今後の自分の勉強のためにもなるので助かります。

* [Javascript Closure](https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md#style-y010)
* [Named vs Anonymous Functions](https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md#style-y024)
* [Feature File Names](https://github.com/johnpapa/angular-styleguide/blob/master/i18n/ja-JP.md#style-y121)


## 余談: AngularJS 導入に至った経緯

インターン先での小さいデモの作成のため Javascript と D3.js を使ってその場で終わるコードを書いていました。もともとは AngularJS を使うプロジェクトではありません。が、結果としてデモのウケがそこそこ良かったので、[コードを外部に公開](https://github.com/CiscoSystems/cognitive)する、ということで急遽コードの整理をすることになります。フレームワークなんて必要ないだろう？と当時思っていたので、TypeScript を用いてクラスで管理するようにしよう、と試みていたのですが、大量のイベントハンドリング、Ajax で取得したデータを元に動的に HTML を Javascript で生成、といった作業が思いのほか大変だった(html タグのいたるところに id="idタグ" を追加してjavascript でハンドリングしたり、`<table>`や`<td>`,`<tr>`タグをJavascriptで作成したり...)ことに加え、そもそもフロントエンドで TypeScript 導入してクラスを使えるようにしたところで、適当なクラス設計を思い浮かべられない、というのが課題でした。

これらの問題を解決するのにフレームワークを用いるというのは理にかなっていて、候補としては ReactJS と AngularJS が選択肢として上がります。

結論としては AngularJS が選択されたわけですが、一番の理由としては

* `Kibana`, `Grafana` などの周囲で見かける他の OSS が AngularJS で書かれていた

というのが決定打でした。とくにコードを外部に公開するような場合(この例は特殊です。)、使用されているプロジェクトの数が多いということも、そのフレームワークの価値になります。このような経緯のもと、AngularJS が利用されることになりました。
(AngularJS を導入したあとも自分の経験不足などで苦労したり、[AngularJS 2.0](https://angular.io/) もでるらしく、対応はどうするのか、といった部分は懸念として残りました。この辺に関しては今後の話になるかもしれません。)

## まとめ

AngularJS に限る話ではないですが、スタイルガイドを読みましょう。特に今まで関わったことのない技術であるほど、最初に読んでおくと後々の苦労を減らすことができると思います。ただし、スタイルガイドはあくまでもガイドなので、読んだあとの判断は各人でする必要がある点に注意です。