読者です 読者をやめる 読者になる 読者になる

継続開発のススメ 2012-06 版

変更履歴

  • 2012-06-24
    • ドキュメントの所に *diag シリーズについて追記

概要

開発があればリリースがあり、リリースが終われば、メンテナンスがあり、さらに開発があります。プロダクトが EOSL (End Of Service Life) を迎えるまではこれを続ける必要があります。

去年の 8 月に「継続開発のススメ」というので、やっていることをまとめたのですが約 1 年経ってもう少し細かくまとめて見ようと思いました。基本的には自分がいる環境を前提に書いてます。

継続開発のススメ
http://d.hatena.ne.jp/Voluntas/20110823/1314036482

開発スタイルは常に変化し続けていくべきだと思っています。これだ、というのを作らないのが一番良い開発スタイルでは無いかなと。

脳内を書き出しているので、日本語がおかしい上に一貫性が無いと思います ... すみません。

宣伝

ここの宣伝はそのうち消します

ここに書いてあるErlang よりにした話を 9/1 に行われる 函数プログラミングの集い 2012 in Tokyo でお話しする予定です。
http://partake.in/events/9a5f18bf-ca0c-48cd-a050-8a564c1ab0d9

環境

想定している環境は以下の通りです

  • バージョン管理には git (git-flow) を使用してる
  • コードレビューやバグトラッカには GitHub の機能を使用している
  • 主な使用言語は ErlangPython そしてシェルスクリプト (Bash) である
  • 開発環境は Mac または Linux である
  • 開発メンバーは 10 名以内である

リポジトリ

GitHub

GitHub はとても優れたサービスです。Git だけにはとどまらず様々な管理を行う事が出来ます。ここでは GitHub というよりはリポジトリの話をします。

大きな組織でインフラの管理がしっかりしているのであれば GitHub Enterprise の導入を検討すると良いでしょう。小さい組織であれば GitHub の組織機能の有料プランをオススメします。組織の人数に制限はありません。 制限があるのはプライベートに出来るリポジトリ数です。月額 $200 で 125 個のプライベートリポジトリが作れます。

リポジトリ構成

1 プロダクトのリポジトリ構成は アプリケーション、ドキュメント、テスト、リリースのリポジトリを分けています。 これはあまり多くのプロダクトを保持していないからというのもあると思います。

そのため、プロダクトが多い場合は 1 プロダクトで中にフォルダ分けてしまうというのも良いと思います。

spam というアプリケーションがあるとしたら以下のようにリポジトリを分けています。

spam はアプリケーションのコアです、ここにはリリースに関係するモノは含みません。 ただし、アプリケーションがまだ成熟していない場合は、含めてしまってもいいかもしれません。将来的にリリースが複雑化した場合のみでも十分です。

リポジトリを別にするメリットとしてはそれぞれ独自に修正するものという概念が強いからです。

アプリケーションにバグがあればアプリケーションを修正してバージョンを上げます。ただそれはドキュメントに影響するモノでは無かったりします。テストだけを追加することだってあると思います。

一つのプロダクトでありながら、それぞれ別のラインが存在します。そのためプロダクトのバージョンをリリースリポジトリで管理します。テストを修正したとしてもリリースには影響ないはずです。

「ドキュメントとテストとアプリそれぞれ別のバージョンを持つべき」であり、そしてそれらを統合したバージョンがリリースなのだと考えています。

コマンド一つ

全てのディレクトリで「コマンド一つ」でやりたい事が全てやれるようにしましょう。アプリケーションのリポジトリをチェックアウトしてきて、 make と打てばば依存ライブラリのチェックアウト、コンパイル、テスト、カヴァレッジの取得などです。

これらの作業は一番「良く行う」作業です。良く行う作業を簡易的にしておくことはとても大切です。

主に Makefile を使用していますが、別に何かしらのビルドツールを使っても良いと思います。あまり難しい事をやらないために Makefile を使っています。複雑すぎる場合はどこかがおかしい可能性が高いです。

ビルド専用ツールを作ったりしても良いかも知れません。ただしメンテナンスがちゃんとされるのであれば、ですが。

タスク管理

バグや実装すべき事など様々な作業はタスク(チケット)にする事が可能です。これを行っていない所は無いと思います。

ツールを使うのがほとんどだともいます。基本的に GitHub の issues 機能を使っています。ただ、これ低機能なんです。

それでも issues にこだわっているのは「GitHub だけ見れば良い」というシンプルな構成ができるからです。GitHub の組織であれば Timeline が RSS を吐いていますのでそこさえ見れば何が起きてるか把握する事が出来ます。

もちろん GitHub と連携する素敵なタスク管理ツールはあると思いますが、今のところ困っていません。
Pivotal Tracker とか AgileZen とか良いらしいですね。

低機能な GitHub issues ですが、ラベル機能、アサイン機能、マイルストーン機能があります。ここではラベルとアサインについて書いていきます。

GitHub issues ラベル

ラベルは全てのリポジトリで共通に作っています。全てのタスクに対して何かしらのラベルを貼ることを必須としています。

  • task
    • task は作業で、なにか作業が発生するものはすべてこのラベルを付けます
  • doc
    • ドキュメントにも影響する場合はこのラベルを付けます
  • feature
    • git-flow による feature ブランチを切るくらい大きめの作業です。ほとんどの場合が pull-request ベースで作業します。
  • bug
    • bug に重みはなく、最優先事項で対応されるのでプライオリティは今のところ用意していません
  • test
    • doc と同様で、受け入れテストにも影響する場合はこのラベルをつけます
  • discussion
    • 何かしら議論が必要な場合はこのラベルを付けます。

discussion ラベルを付ける場合はいくつかルールがあります。

  • 提案内容は一つでは無く複数であること (複数提案必須)
  • 提案全てに反対する場合は必ず提案をすること、ノーだけは禁止 (代替案無しの反対禁止)
  • あまりにも決まらない場合は、顔を付け合わせての打ち合わせを行う (文字での議論より顔をつきあわせての議論)

今のところこれらのラベルでなんとかやり過ごしています。シンプルにやることで判断がやりやすいというメリットはあるのかなと思います。
ただ GitHub issues ... もっと使いやすくなって欲しいです。

アサイン

GitHub issues ではチケットを人に割り当てることが出来ます。残念ながら Notification が飛ばなかったり、複数の人がアサインできなかったりと問題はあります。

アサインで特殊なのが「誰もアサインしない」状態です。これは「誰かよろしく」という状態で、誰かがやるというスタンスになっています。別にタスクをこなした量が評価対象にはならないのですが、今のところ上手く回っています。

タスクが残っている方が気持ち悪いというスタンスの人の方が多いからかも知れません。

マイルストーン管理

GitHub issues ではマイルストーンも指定します。基本的にはマイルストーンはバージョン事に切っていきます。ただマイルストーン名はバージョンだとわかりにくいなぁと感じたりしています。

1.2.5 とかのバージョン名だと何をやるのかわからないので、バージョン番号はマイルストーンの説明に書けばいいかなと思い始めてきました。 大事なのは「このマイルストーンの目的」がタイトルになってるべきだと思います。

また、マイルストーンでオススメなのがリリース直後の fix マイルストーンを用意するというのが良いです。プロダクトにバグはつきものです。リリースしたからバグが無いわけでは無いので、特定のリリースに対するバグ修正ようのマイルストーンがあると、タスクが切りやすくなります。

レビュー

レビューは開発においてとても重要です。コードレビューから、タスクレビュー、さらにはドキュメントレビューを含みます。さらにレビューはショートカットがありません。人が確認する作業です。

ショートカットはありませんが、それぞれのレビューで何かしらスタイルはあるとおもいます。

コードレビュー

コミット後レビューを採用しています。コミット前レビューを採用しない理由は失敗コミットがあったって困るわけでは無いというスタンスからです。コミット後レビューで問題無いのは GitHub の Pull-Request 機能を使っています。レビューが欲しい場合は feature ブランチを切ります。その後 develop に対しての Pull-Request を発行します。レビューワーはその pull-request のコード内容をレビューします。仕様は確定しているはずなので、その仕様にあっているかどうかも確認します。

何度かのコメントをやりとりして最後に Pull-Request Merge して終わりです。

これは残念ながら GitHub 依存のやりかたです。GitHub の Pull-Request 単位で diff にコメントがかけるのはとても大きいです。コレを使うことでコードレビューを積極的に行うような習慣作りはできる気がします。

コードレビューで大事なのは「空気を読む」というのが悪だと言うことです。変な書き方していたら突っ込めばいいですし、気になったらコメントしましょう。

設計レビュー

まずは設計書を二段階に定義します

  • 要件設計書 ... ざっくりとした「何がやりたいか」が書かれている資料
  • 基本設計書 ... 社内外に残す正式な資料

新しい何かを作る際は要件があって、それを元に書き出した要件設計書が必要です。これはとてもざっくりとした形で構いません。何がやりたいかがまとまっていれば十分です。理想を言えばそれに「どんなイメージ」といったサンプル実装が書いてあったりすると良いかも知れません。

要件設計書と基本設計書の作成担当者を別にするのがレビューを行う良い方法だと考えています。 設計段階での情報共有ははかなり時間がかかります。ただコーディングやテスト等を行う際は、設計の情報共有が必須です。

要件設計書担当者は基本設計書のレビューを担当します。基本設計書担当者は要件設計書担当者からの情報を元に基本設計書を作成します。これで情報共有が一気に進みます。あえて別にすることでコストが高く見えますが、実際は情報共有作業も含んでいるので結果的にはコストは押さえられます。さらに要件設計書担当者はレビューワーに徹することで、自分の伝えている仕様に漏れが無いか、第三者的な視点でも見れることになります。

何よりも設計段階でバグが入る仕様バグだけは避けたいので、この段階でのレビューはかなりしっかりやる必要があります。

要求設計書は 1 つのテキストファイルでまとめます。それを淡々と更新していきます。それに追従するように基本設計書を作成していきます。 基本設計書については Sphinx からの PDF 出力でテンプレートを用意しています。

この辺りはまだまだ、やり始めたばかりなのでもっとやりようがあると思います。

タスクレビュー

タスクレビューは主に顔を合わせて残りのタスクをどうするかレビューします。実際やってるのを見る限り週1程度が良いようです。
時間を決めて、その時間内に収まるように作業をしましょう。タスクレビュー後に気になっている事を話すのも実はありで何か色々生まれるかも知れません。

集まって話をするという時間を設けるのも大事な事だと思います。逆にそれ以外はあまり集まりません。

注意点としてはタスク管理であった discussion ラベルの議論をやる場所にしないようにしましょう。あまり意味の無いだらだらが生まれてしまいます。

まず継続的に時間を決めてタスクレビューを行う、それだけで十分だと思います。参加する人はプロジェクトで主に関わっている人だけで、あまり関係ない人は参加しないようにしましょう。人が多いと無駄が生まれます。

ドキュメントレビュー

日本語がおかしかったり、実装と合っていないなど、かなり負荷の高いドキュメントレビューも基本的には pull-request ベースでやりますが、一番の作業は最後に印刷して読み合わせするのが良いようです。

学校の事業でやった音読です。音読すると目で読んでいるときとは違う「飛ばす」ということが無いので確実です。ただ時間もかかるのである程度落ち着いてきてから、時間を取って1回やる程度で十分だと思います。

音読って意外にやらないですけど、バカに出来ないと思います。

技術的な文章では無い場合は営業などを巻き込んで見るのも良いかも知れません。ドキュメントレビューに関しては日本語として、というのが大きく影響するので沢山の意見を聞くのが一番です。

継続的インテグレーション

新しいコミットが合った場合、リリース環境と同一の環境でビルドやテスト、リリースまでが行われる事を指します。ツールには Jenkins を使用しています。

自動のビルドや単体テストはコマンド一発で出来ているはずなのであとは Jenkins 側との親和性のテスト一覧やカヴァレッジなどが取れるプラグインを入れると良いです。

実際の流れは GitHub からチェックアウトしてビルド、単体テストが走ります。その後リリースされてパッケージングされたバイナリが出来ます。それらのパッケージングされたバイナリをつかって受け入れテストを行います。現在実験としてキャパシティテストも行っています。

さらにどこかで失敗した場合は XMPP 経由で Google Talk にエラーが飛んでくるようになっています。

受け入れテスト

受け入れテストとは単体テストとは別のテストです。実際に動かしたり API 叩いたり、画面いじったりする外部インターフェースへのテストです。

単体テストはテストというよりも開発者の自己満足に近いので、本当のテストは受け入れテストになります。基本設計書をベースに作っていきます。

大事なのは受け入れテストは自動化前提で行うということです。テストは全て Pytohn とシェルスクリプトで出来ています。ただここは作るプロダクトが何かで色々変わってきます。

受け入れテスト用のツールを成熟させていく事が一番大事になってきます。たとえばテストのパフォーマンスチューニングです。受け入れテストはかなり細かいテストを行うため数時間かかります、これを短くしていくのも大事な作業です。

受け入れテストがあることで、製品の品質を担保しやすくなります。ただしがむしゃらにテストを増やすべきではありません。短くて読みやすく、効率の良いテストを作る事が大事です。これはプロダクトのコードと同じレベルで重視すべきです。

テスト環境に投資することは無駄になることはありません。

キャパシティテスト

簡単に言えば性能検証です。データベースに大量のデータを突っ込んでもレスポンスが遅くならないか、複雑なロジックにしても応答速度は下がらないか等です。

手動では意味が無いのでこれも自動化前提です。ただしキャパシティテスト環境を作るコストはとても高いです。検証結果の可視化やネットワーク環境まで影響します。ここまでやる必要があるかどうかはプロジェクト単位で判断する必要があると思います。

検証結果の可視化には R を使ったグラフ作成や検証用の初期データの作成をスクリプトで自動生成する必要があります。この辺りは仕様がかわると1から作り直しになるので、この辺も注意が必要です。

ただキャパシティテストは「性能の劣化」や「思いがけないバグ」を見つけてくれます。実際にプロダクトを本番環境の様な使い方でテストするため、単体テストや受け入れテストでは見つからないものが見つかる可能性が高いです。

ただ品質を高める場合にはここまでやれる時間とお金と人材が必要です。

ドキュメント

パッケージを提供する場合はドキュメントが必要です。サービスの場合は社内向けのみで良いですが、パッケージではユーザズガイドや基本設計書などどのタイミングでもドキュメントは重要視されます。製品よりもドキュメントの品質が問われる場合も多々あります。

Sphinx からの PDF 生成を使う事で、高品質な PDF を生成する事が出来ます。さらにフォントを商用のものを使い、見栄えをデザイナーに見て貰うことで劇的に変わるとのことです。フォントを商用のモノを使うのはまだ出来ていませんが、今後の課題として持っています。

ドキュメントは全てテキストで扱います。バージョン管理下に置くのは大前提です。全てのドキュメントはテキストで、バージョン管理下におかれる必要があります。そうではないドキュメントは存在してはいけません。

これを徹底することが、まず最初です。

ドキュメントをテキストにすると図はどうするんだという話になりますが、内部資料であれば ASCII アートで十分です。外部に出すモノであれば *diag シリーズが良いでしょう。特に seqdiag はシーケンス図を書くのにとても役立ちます。

http://blockdiag.com/

次へ

まだまだ課題は山積みで、やることは沢山あります。今後も定期的に書き出していこうおともいます。