perl 界隈の皆様、YAPC::Asia 2010 おつかれさまでした。

@nipotan のライトニングトークはシャッフルに関する話でした。で、ここで、なぜそもそもシャッフルが出てきたのかについて、チームマネジメント的な観点から補足したいと思います。

(元の発表はこちら: 動画 / スライド )


■相互チェック体制の運用

ライブドアのプログラマは、だいたい一人でひとつのサービスを受け持っています。一人が複数のサービスを受け持つのは普通ですが、一つのサービスに複数のプログラマがフルコミットするという贅沢な状況はあまりありません。

担当が一人ずつしかいないと、
  • 担当の人が休むと何も進まない。やりたいことが色々あっても手が足らない。
  • コード品質の属人性が高い。担当者によってパフォーマンスやバグ発生率が違う。
といった短所がある一方で
  • 設計思想の一貫性が保ちやすい。一人で全体を一気に作り上げられる。
  • 開発環境やテスト環境がひとつで済む
  • 開発がひとつひとつシリアルに進むので、開発→テスト→本番化の流れが単純&コンパクトに保てる。
という長所もあります。(実際は単に人手が足らなくてこうなってるだけですけど。)

例外なのがコアサービスであるブログで、このチームだけは6〜7人のグループがひとつのリポジトリを共有し、常時複数の開発を平行にすすめています。そのため、上とは逆に
  • 設計思想の一貫性が保ちにくい。同じ機能のメソッドが2つも3つも作られていたり、誰かが特定の用途で作ったメソッドを別の人が想定外の目的で再利用しちゃって、パフォーマンスが落ちたりバグが出たりなど。
  • 開発環境は開発チームの人数分必要。テスト環境は同時に進んでいるプロジェクトの数だけ必要。本番化の前にはマージ祭り&コンフリクト祭り。
という、(うちとしては比較的異例な) 課題に直面します。

最初にチームとしてブログを担当することになったとき、この共同体制をどう組むかについてだいぶ悩みました。特に前者の欠点を克服するにはコードレビューの体制が不可欠に思えましたが、これには開発効率の低下や組織の硬直化といったトレードオフがつきものです。
考えられる選択肢はいくつかありましたが、それぞれに致命的な欠点がありました。
  • ペアプログラミングの導入 ... これは前職でも試したことがあり、新人教育とか開発効率の向上といった点で効果があることは確認済みでした。が、各々こだわりのキーボードやエディタがあって、iTunesで音楽を聞きながら時にtwitterを横目でみながら開発をし、好きな時間にふらっと昼食に出て好きな時間にふらっと帰る、といったスタイルで心地良く開発をすすめているラボタイプの職場には不向きなことは明らかでした。
    BlogPaint
  • マネージャをコミッタとし、配下の部下のコードに完全な責任をもたせる ... 部下のコードは必ず上司がチェックし、コミット権限のある上司の責任のもとでコミット&本番化される。まあ正論ではあります。が、非現実的でもあります。他人の書いたコードを読むのはけっこうな精神力を必要とします。ましてや、読んでも読まなくても十中八九ちゃんと動くコードを(自分がコードを書く時間を削ってまで)律儀にレビューする、なんてことを現実的に続けていくことが可能でしょうか。しかも、6〜7人のチームのマネージャにその仕事を課すとすると、マネージャ自身がコードを書く時間は確実になくなって部下のコードにハンコを押すだけの係になってしまうでしょう。(ていうかそれイコール俺がやるってことだったし...) かといって、マネージャの目が十分行き届くまでチームを細分化すれば、縦方向には硬直した官僚的組織が、横方向にはコミュニケーションの断絶が生まれ、当初の「設計思想の一貫性」といった目的にも反する結果になります。
    3cd5bef0
そこで、「ペアプログラミングの利点を生かしつつ、そこまでウザくない」「フラットな組織のまま、コードレビューの責任を全員で分散して請け負う」という目標のもと、下のような仕組みに考えが至りました。

(1) AさんのコードはBさんが監視し、BさんのコードはCさんが監視し、.... というふうに、チームの各々がそれぞれ別の誰かのコード監視(レビュー)を担当する。
3cd5bef0

ただ、「AさんはBさんの書いているコードをちゃんと確認してね」と言うだけだとすぐに形骸化してしまうのは上でも触れた通りです。そこで人のコードを本腰を入れて読む気にさせるための仕掛けとして、以下の制度も同時に取り入れました。

(2) 毎週のミーティングで各自がその週何をしていたかの進捗共有ミーティングをし、そこで、Aさんが今週どんな仕事をしていたかは、レビュー担当のBさんによって発表される。同様にBさんの今週の成果はCさんによって発表される。(Bさんがちゃんと発表してくれなかった場合、Aさんがサボっていたと記録されちゃうことになる。)
(3) 誰が誰を担当するかは、毎週シャッフルして入れ替える。

毎週の進捗ミーティングはもともと行われていたものですが、本来は「自分が今週何をしたかそれぞれ発表する」場だったのを、お互いに他人の成果を発表し合うことで、お互いのやっていることに興味を持ち合えるようにしようという仕掛けです。

ここでシャッフルが出てくるわけですね。

■git移行と個別開発環境の整備

さて、この仕組みの運用は、一見無関係に見える、以下の二つのインフラ整備と切っても切れない関係にあります。
  • 当時社内標準だった subversion から git へ移行する。
  • これも社内標準だった「1サービスにつき1つ開発サーバがある」体制から「開発者全員が自分のマシンに開発環境をおく」体制に移行する。
「他の人が何をしていたか」を把握するには、コミットログをチェックするのが適しています。が、中央リポジトリ方式である subversion の場合、
  • 作業内容を失わないように細かくコミットしがち → それが全部コミットログに現れる→ 他の作業者も同様にコミットログを残す → 細かいコミットログが入り乱れて「誰が何をしたか」を追うのが不可能
    BlogPaint
という問題に陥りがちです。(作業ブランチを使えば改善されるのですが、簡単な変更のためにブランチを作るのは面倒でサボりがちです。一方、大きな変更をブランチで進めるとマージの時にコンフリクト祭りで苦労するのがお決まりのパターンでした。また、開発サーバの数が限られていたため、動作確認のためにこまめにブランチを切り替える必要があるなど、結果として「ブランチ=面倒」という評判が固まりつつありました。)

そこで、分散リポジトリである git に移行し、かつ、開発者毎に個別の開発マシンを用意して
  • 細かい作業は、自分専用の開発マシンにあるローカルリポジトリにだけコミットしておく。
  • 自分専用の開発マシンで動作確認がとれ、本番化する直前になってはじめて、ひとつのまとまった単位で中央リポジトリに push する。
    BlogPaint
という作業フローにすることで、「誰がどういう変更を加えたか」を、機能的にまとまりある単位で確認できるようになりました。
また、git の方が若干マージの性能も良いようで、「本番化直前のマージ祭り&コンフリクト祭り」という事態もあまり見かけなくなった気がします。

ちなみに個別の開発環境は vmware 用に本番サーバと同じイメージを作って全員に配布することで実現しました。
まあ git への移行を完遂したのも、vmware で開発環境構築したのも僕じゃないんですけどね...  その辺の話は、それぞれを担当してくれた人たちが面白い話を別途聞かせてくれることを期待しつつ、次はシャッフルの話をもうちょっと詳しくしようかと思います。