開発手法の大半は、まずKent Beckの有名な著書『Extreme Programming Explained: Embrace Change』(邦訳『XPエクストリーム・プログラミング入門』)、そしてGerald Weinbergの『The Psychology of Computer Programming』(邦訳『プログラミングの心理学』)で詳細に述べられています。それらを試したところ、多くの手法を開発中に採用することで、作業の品質とチームの幸せを高められることが分かりました。
バージョン管理
私たちは常にソースコード管理を行います。タイムマシンのようなものです。ソースコードが平行宇宙のように存在し、作業内容を失う恐れなく実験できるのです。うまくいかない場合はロールバックします。
Gitは、Linus Torvaldsによって書かれた、オープンソースのソースコード管理システムです。高速で分岐作業に優れています。
GitリポジトリをホスティングするにはGitHubを使用します。
スタイルガイド
私たちは、コードの読みやすさとチームの円滑なコミュニケーションを重視する、一貫したスタイルでコードを書きます。
上位レベルのガイドライン:
- 一貫性を保つ。
- 既存のコードに関して、このガイドラインに従うためのリライトはしない。
- 十分な根拠なくガイドラインに違反しない。
- 十分な根拠とはチームメイトを納得させられるものとする。
ペアプログラミング
隣同士に座る2人が、1台のコンピュータを使って書いたコードはペアプログラミングされたコードと言われます。そのようなコードは高品質で、保守性も高いことから低コストにつながると考えられます。
長い目で見ると、この開発スタイルでは、バグが減り、あとで修正する必要も少ないことから、コストが低減されます。
ペアプログラミングは有用であり、頻繁に行われるべきだという例を以下に示します。
あなたがコードの重要な部分を書いているとき、それを本番環境に移す前に他の人に目を通してもらいたいと思いませんか?
作業時間の100%をペアプログラミングするわけではありませんが、離れたところで作業している場合はお互いにチームとして働くことに難しさを感じます。設計者同士、開発者同士、または設計者と開発者間での円滑なコラボレーションを生み出すのに、同じキーボードに向かうことほどよいものはありません。
テスト駆動開発
テスト駆動開発(TDD)は、私たちが実践するエクストリーム・プログラミング(XP)の中で、恐らく最も重要なルールです。
ビジネスにおけるTDDの効果:
- よりよい価値を、より速く届けられる
- 常に有用なソフトウェアを提供する
- 素早く変化に適応できる
コードにおけるTDDの効果:
- 可読性の高い仕様とコード
- 洗練されたパブリックインターフェイス
- 分離されたモジュール
プロセスにおけるTDDの効果:
- セーフティネットとしてのリグレッション
- 大胆なリファクタリング
- チーム内の信頼関係
非常にシンプルな上位レベルのテスト:
- テストファースト
- レッド(失敗)-グリーン(成功)-リファクタリングの作業サイクル
より詳細を知りたい場合は、Upcaseが月1回開催するTest-Driven Railsのワークショップをお勧めします。特にRuby on Railsの開発者向けにTDDのワークフローについてかなり詳細に説明しています。
受け入れテスト
受け入れテストはユーザの要求から作られるコードです。このような感じです。このコードはアプリケーションに対して実行されます。最初に実行されたとき、テストは失敗するでしょう。開発者はテストに合格するまでアプリケーションのコードを書きます。
テストに合格すると、開発者はそのコードをバージョン管理システムへ以下のようなメッセージを添えてコミットします。
ゲストが承諾書を作成
次にコードは受け入れテストが本番環境と一致するような環境でも合格するか確かめるために継続的インテグレーション(CI)サーバ上で実行されます。
それと同時にコードはステージング環境へプッシュされ、開発者と顧客はブラウザでスモークテストを実行します。
受け入れテストがCIサーバにおいてグリーンで、あなたや他の設計者・開発者・クライアントがステージングでユーザの要求を満たしていると満足すれば、その機能は自由に本番環境へデプロイできます。これにより様々な機能が本番環境へ極めて頻繁にプッシュできるので、より多くの価値が顧客へより早く供給されます。
リファクタリング
“レッド、グリーン、リファクタリング”の3番目のステップはリファクタリングであり、外的な振る舞いを変えることなく既存コードの設計を改善するプロセスです。これは開発プロセスにおいて重要なステップですが、しばしば見落とされます。私たちはリファクタリングについてとても熱心なので、それについて『Ruby Science』全体で書きました。
コードのレビュー
以下はコードレビューの流れです。GitコマンドについてはGitプロトコルを参照してください。
- マスターに基づくローカルのフィーチャーブランチを作成する。
- 機能が完成してテストに合格したら、変更をステージングする。
- 変更をステージングしたら、それをコミットする。
- 適切なコミットメッセージを書く。
- ブランチを共有する。
- GitHubプルリクエストを送信する。
- Slackでコードのレビューを依頼する。
- 作者以外のチームメンバーがプルリクエストをレビューする。彼らは誤解を避けるためにコードレビューガイドラインに従う。
- GitHub WebインターフェイスかSlackでコードの各行について直接コメントや質問を行う。
- 満足したら、プルリクエストについて”マージの準備ができた”とコメントする。
- 対話的にリベースする。”ホワイトスペースを修正”のようなコミットを一つか少数の有益なコミットへ圧縮する。意図を明らかとするためにコミットメッセージを編集する。
- 新たなコミットのリストを見る。変更されたファイルを見る。ブランチをマスターへマージする。
- リモートのフィーチャーブランチを削除する。
- ローカルのフィーチャーブランチを削除する。
テスト駆動開発は開発過程の初期においてコードの不具合を修正します。本番環境より開発マシン上で不合格のテストを生じさせる方が好ましいです。またフィードバック周期をより短くすることもできます。
コードがマスターとなる直前でのコードレビューは同様の恩恵をもたらします。
- チーム全員が新たなコードについて書かれたとおりに理解する。
- 誤りをより早く見つける。
- コーディング標準を確立して、議論して、模範とすることがより期待できる。
- コードレビューのこの方式によるフィードバックは適用される可能性がより高い。
- 作者の記憶がまだ新しいので、誰も文脈を忘れない(「なんでこれ書いたんだっけ?」)。
継続的インテグレーション
継続的インテグレーション(CI)については、Martin Fowlerが詳しい解説を行っています。基本となるのは以下の点です。
- テストスイートを有しており、それは各開発者が自分のマシン上で実行する。
- 共有のバージョン管理リポジトリに開発者がコードをコミットすると、テストが再び行われて、他の開発者のコードと”統合”される。
これは、テスト合格が開発者のマシン特有の環境に依存していないということを確実にするのに役立ちます。バージョン管理を行っているコードは、のちに本番環境で正しく動作する必要があるので、本番環境へのデプロイを行う前にCIサーバまたはサービス上で動かすのです。
ビルドが失敗したときにはSlackにアラートが通知され、メールも届きます。アラートをクリックしてバックトレースを見ると、”ビルド修正”のヒントを得ることができます。
修正コードを書いてバージョン管理システムに再びコミットすると、”成功ビルド”のアラートがSlackに通知され、メールも届きます。アラートをクリックすると、そのビルドを確認できます。
グリーンは成功を表します。
信頼性のあるテストスイートはWebアプリケーションの絶対的な要件であると、私たちは考えています。しかし、テストスイートには、サイズが大きくなると時間がかかるという大きな問題があります。
CIは、テストを同時に動かすことで、この問題に対処できます。私たちはこの技術を使って、45分のテストスイートを2分に短縮しています。
私たちは管理ツールとして、CruiseControl、Integrity、Hudson(現在はJenkinsと呼ばれています)などのCIライブラリを使用してきました。その結果、コストの高い作業に多くの時間をかけられるようになりました。
私たちは、オープンソースプロジェクトにはTravis CI Free、プライベートリポジトリにはTravis CI Proを使っています。なぜなら、ユーザインターフェイスが一貫しており、設定がシンプルで、GitHubと緊密に連携しているからです。
CIのテストはGitHubのpost-receiveフックによって実行されます。私たちがGitHubリポジトリの多くで設定しているフックは、以下のとおりです。
- CIのためのTravis
- コードの質やセキュリティをチェックするためのCode Climate
- スタイルガイドを守るためのHound
- チャットルーム通知のためのSlack