大規模なjavascript開発の話
DESCRIPTION
大なごやJS#3(2012/07/21)で使ったスライドです。割と「当たり前のこと」をまとめなおしただけな感じです。TRANSCRIPT
大規模なJavaScript開発の話
terurou/YAGI.Teruo
自己紹介
2
terurouです。
• Web・GUI・分散処理を手広くやってます
–Windows 8(Metro Style Apps), Silverlight, JavaScript, Android, …
–Cassandra, 自作KVS, AWS, …
–DataGridの自作に定評があるらしいです
• フロントエンド寄りのアーキテクチャの設計が割と得意です
–MVC/MVVM, Client-side Cache, 通信, …
3
大規模なJavaScript開発とは?
4
私の大規模プロジェクト経験
• 大規模なJavaScriptプロジェクト経験は2回
–似たところではSilverlightの大規模プロジェクトも
• 全て業務系システム開発プロジェクト
–Web/ゲーム系のことはわからないです
–基本的なことは同じだと思いますが…
5
私の関わった大規模JavaScript開発(1)
• SaaS セルフカスタマイズエンジン
–Salseforce.comみたいなやつ
• 5人体制(JS担当者は2名)
–プロジェクト全体では50名体制
• 開発規模:数万行(記憶があいまい)
–ライブラリ未使用、フルスクラッチ
–現在のスキルであれば25K行程度で作れそう
6
私の関わった大規模JavaScript開発(2)
• SaaS フレームワーク
–現在進行中
• 6人体制(JS担当者は3名)
–プロジェクト全体では最大30名程度になる?
• 開発規模は30K行程度に収まる?
–Ext.JS利用、DataGrid自作
7
「大規模」の定義が難しいですが…
• 単純にステップ数が多いアプリケーション
–並みの規模だとJS単体で10K行は超えない
–cybozu.comがJS単体で65K行程度らしい
• http://b.hatena.ne.jp/articles/201112/6709
• 開発人員が多い
–プロジェクト全体では数十名規模とか…
8
大規模プロジェクトでのチーム構成
• PMO(Project Management Office)
–プロジェクト管理
• 共通基盤チーム
–フレームワーク開発、インフラ整備など
• アプリケーションチーム(業務チーム)
–機能設計、実装など
–このチームが一番人数が多くなるはず
• その他に企画、品質管理、保守運営など
9
大規模プロジェクトでのチーム構成
• PMO(Project Management Office)
–プロジェクト管理
• 共通基盤チーム
–フレームワーク開発、インフラ整備など
• アプリケーションチーム(業務チーム)
–機能設計、実装など
–このチームが一番人数が多くなるはず
• その他に企画、品質管理、保守運営など
← 今回話す範囲
10
大規模プロジェクトでの基盤開発で意識すべきこと
11
大規模プロジェクトならでは「急所」
• どうしても「変更」に対して弱くなりがち
–チーム制による分業のため、変更発生時には関係各所との調整が必要
• 人数が多い分だけオーバーヘッドが大きくなる
–問題の発覚が遅くなるほど影響が大きくなり、最悪のケースはプロジェクトが頓挫することも
• プロジェクトメンバのスキルのばらつき
–対策をしなければ、生産性、品質、保守性に大きな影響が出てしまう
12
どのように「急所」に向き合うか
• 早期の技術検証/プロトタイピング
–プロジェクトの序盤に問題点をクリアしておけば、後から変更をする必要がない
• 「できていいことだけができる」環境を作る
–コードの品質(保守性・可読性)がメンバーのスキルに影響されないようにする
–品質が高レベルで安定していれば、もし変更が必要になっても対応しやすい
13
技術検証/プロトタイピングで注意すること
• 些細なことでも必ず検証するのが理想
–「実現できるはず」という思い込みをしていても、実は実現できないことは多々ある
• あまり作りこみ過ぎない
–所詮は検証用、書き捨てコードでOK
• 目的(何を検証したいのか)を見失わない
–実装可能? パフォーマンス? 生産性?ユーザビリティ? …
14
「できていいことだけができる」環境
• プロジェクトに特化したフレームワークを作り、実装パターンを単一化/テンプレート化する–「穴埋め実装すればアプリが作れます!」
–必要な機能を提供しつつ、不要な機能は隠す• 汎用化≒複雑化、保守性・学習性が落ちる
• OSSのフレームワークを導入しただけではダメ
• 規約での制限は最後の手段–コードの品質が実装スキル、規約の理解度に
依存してしまう
15
ちょっと難しく書きすぎた…
• 一人プロジェクトと大差はない
–「画面ごとに実装方法やクラス構成が違う」とかわざわざやらないよね
• 大規模開発は小規模開発のサブセット
–と、前に誰かが言っていたような気がする
–「自分ならこう書く」を分業体制でやるためには段取りが必要
–どれだけうまく環境構築しても、基盤チームの実力以上の品質にはならない
16
JavaScriptでの大規模開発
17
JavaScriptは大規模開発に向いていない
• 言語仕様が柔軟すぎる
–「クラス的なもの」ですら書き方がいくらでもある
– prototypeを拡張/改変できる
• ECMAScript 5なら制限できるけど…
• モダンな書き方をするとコードが冗長に
–var前置、stacktrace対策(function名を明記)
• そもそもGUIを作るにはAPIが貧弱
– jQuery UIやExt.JS等の範囲内ならよいが…
18
JavaScriptエンジニアが少ない問題
• 「jQueryできます!」とか言われましても…
–案件によってはそれでもいいのだけど…
–それで済む時はJavaScript部分は小規模…
• そもそもJavaScriptは難しい
– prototype型のオブジェクト指向言語
–HTML/CSS、クロスブラウザ、ブラウザハック
–GUI実装パターン(MVC)の知識
–など、覚えないといけないこと沢山
19
柔軟すぎる言語仕様への対策
• JavaScriptを生成する言語の採用
–CoffeeScript, Haxe(, JSX, and more)
–個人的にはHaxe押し
• JavaScriptで開発する場合、モジュールやクラスの書き方は必ず統一する
–開発ガイドやコーディング規約書が必須
– jsdocコメントも必須にすべき
• Closure Compilerがコメントを元にチェックしてくれる
20
Haxe
• 静的型付けのオブジェクト指向言語
–C#やActionScript3(ECMAScript4)に似た構文
–型安全、コンパイル時の型チェック
–型推論や構造的部分型などの機能のおかげでJavaScriptより簡潔にコードを書ける
• インライン展開やマクロにより、現実的には人の手では行えない最適化が可能
• コンパイルが速い
21
Haxeで解決できるJavaScriptあるある
1. ライブラリの関数の定義変更が発生
2. 呼び出し側を1か所だけ直し忘れる
3. 忘れたころにバグに遭遇…
– 原因がわかりにくいパターン
一方Haxeはコンパイラが修正漏れを検出した
22
JavaScript MVC
• ViewとModelを分離することで分業しやすい
–デザイナとプログラマ
–JavaScriptハッカーとプログラマ
• 難しいViewはJavaScriptハッカーに委ねる
• 保守性・可読性の向上
• MVCライブラリはいろいろある
–Backbone.js, Ember.js, Spine, AngularJS, …
23
MVCライブラリだけでは足りない部分
• Modelのモジュール構成
–Template Methodパターン
–Facade/Mediatorパターン
–Factory Method/Abstract Factoryパターン
–Observerパターン(MVCライブラリ未使用時)
• プロジェクト固有の処理
–入力チェック
–通信処理(特にエラー処理)
24
View(GUIコンポーネント)の細かいテクニック
• invalidate(遅延描画)
–GUIコンポーネントを作るときに必須
–描画パフォーマンスが改善
• 不要な描画処理を走らせないようにする
• 部分描画と組み合わせるとなお良い
–ActionScript, iOS, Android, Windows, …など、どれでも用意されている
–JavaScriptでの解説を見かけたことがない…
25
invalidateを使うと改善できる例
• プロパティを変更する毎に描画処理が呼ばれてしまい、パフォーマンスに影響が
function Box() {/*省略*/ }
Box.prototype = {
setWidth: function (width) {
this._width = width;
this._draw();
},
setHeight: function (height) { /*プロパティ更新後、描画*/ },
setFillColor: function (color) { /*プロパティ更新後、描画*/ },
setBorderColor: function (color) { /*プロパティ更新後、描画*/ },
_draw : function (style) { /*描画処理*/ }
}
26
invalidateを実装するfunction Box() {/*省略*/ }
Box.prototype = {
setWidth: function (width) {
this._width = width;
this._invalidate();
},
/*中略*/
invalidate: function() {
if (!this._drawer) {
var self = this;
this._drawer = function () {
this._draw();
this._drawer = null;
};
setTimeout(this._drawer , 0);
}
},
_draw : function (style) {/*描画処理*/ }
}
• setTimeoutで描画処理を遅延
• 何度invalidateを呼んでもdrawは一回だけ実行
27
まとめ
28
まとめ
• 一人開発でも複数人開発でもやることには大差はない
–ただし人数が多い分だけ修正する際のコストが増加するので、段取りには注意する
• JavaScriptは柔軟すぎる言語仕様の割には冗長なコードになりがち
–可能であれば、JavaScriptを生成する言語の採用を検討したほうが良い(Haxeとか)
29
ご清聴ありがとうございました
30