2009-12-31

近況

プログラマとしての成長が感じられない一年だった. 目先の仕事に気をとられ, 問題についてよく考える時間をとらなかった. 過労を言い訳に勉強もしなかった. 情けない. 一方で仕事のチームでは成長を感じることができた. せっかくだから, "チームがよくなる" 感じについて書いてみたいとおもう.

最近, 私のいるチームはコードレビューをするようになった. 私はこれまで仕事の中でコードレビューを実施しょうと試行錯誤してきたけれど, チームに定着することは少なかった. コードレビューはそれなりに面倒な作業なので, 特に組織的な外圧がないところではさぼられがちだと思う. けれど今のチームは外圧なしでやっている. およそ一年間のプロジェクトを通じ, このチームがコードレビューをするに至った道程を振り返ると, チームが成長する様子をうまく捉えることができるかもしれない.

フェーズ 1 - Trac, Excel, たまにペアプロ

いまのチームはプログラマが 3 人, 上司が 1 人いる. 一年前, プロジェクトが始まったときのプログラマは年寄 A と若者 B の 2 人だった.

プロジェクトのはじめに書くコードの質はその後のプロジェクトを左右する. A はプロジェクトの構造 (たとえば tier の数やプロセスの分割, 使う言語やライブラリ...) にいくつか思惑を持っていたが, 一部のモジュールについてはさっさと B に仕事を押し付けたいとも考えていた. そこで A はいくつかの雛形を書き, そのノリで実装を続けるよう B に作業を引き継いだ. A は B がどんなコードを書くかよく知らなかったので, 最初のうちしばらくは一日の半分程度をペアプログラミングで進めた. たとえば B は単体テストを頼りにコードを書くスタイルを身につけていなかったが, A はペアプロを通じて B が単体テスト主導でコードを書くよう求めた.

機能は第一に Excel 上のリスト ("product backlog") で管理し, 実装作業は Trac のチケットとして管理した. 機能と作業は 1:1 に対応することもあったが, 多くは 1:N だった. product backlog 上の進捗更新は 2 週に一度だった. (つまり 1 イテレーションは 2 週間だった.)

フェーズ 2 - 人がふえる, 印刷チケット

最初のリリースが済んだあと, 別のプロジェクトからプログラマ C がやってきた. (フェーズ 1 の段階で最終的なリリースには間に合わないことがわかっており, 助けを求めていた.)

コードのスタイルは固まってきたように思えたので, 以前ほどペアプロはやらなくなった. C はまだプロジェクトのコードベースに慣れていなかったが, C に頼みたい部分は既存のコードの接合が疎な上に A にも思惑のない部分だったため, フェーズ 1 での B のようにペアプロをすることはなかった.

C はアジャイルを愛好しており, 特にタスクボードなど tangible な路線を好んでいた. C の提案により, チームは進捗の可視化をはじめた. Trac のチケットを印刷して壁に貼り, 進捗に応じてマスを移動していく. 印刷用のチケットは C 謹製のスクリプトで作られた. A4 1 枚あたり 15 のチケットを, ハサミでチョキチョキ切って壁の模造紙に貼りつけた.

フェーズ 3 - Trac チケット廃止, 一方向メールレビュー

アジャイル好きの A と C は オブジェクト倶楽部2009夏イベント に参加した. 基調講演のスライドには様々なプロジェクトのタスクボードが写真で 紹介されており, それが C の興味を引いた.

自分達のチームとあの写真はだいぶ違うというのが A と C の共通見解だった. 写真でみたタスクボードはカラフルだし, カードのテキストも手書きだ. 自分達の印刷したカードはどうもしょぼい. 一方で Trac の内容を色ペンでカードに書き移すのは面倒くさい.

いっそ Trac との二重管理はやめてしまえばいいと C は主張した. A は懐疑的だったが, 実際のところチケットが電子化されている利点を活用していないのも事実だった. イベント参加の勢いもあり, バグ管理以外は Trac をやめてみることにした. 翌日にはポストイットにチケットを転記し, Trac 上ではチケットを close した. B は突然のアナログ化を訝しんでいたが, 勢いに水を差すほどではなかった.

半月後, ポストイットの使いにくさを嫌気した C はどこからかインデクスカードを持ち込み, ポストイットをインデクスカードに転記した. 同時に kakutani.com に学んだという ひっつき虫 も導入された. このときも A は大した興味を示さなかったが, タスクボードの利便性は大きく改善した. インデクスカード+ひっつき虫はポストイットにくらべ剥がす/貼るの繰り返しに強く, 保存もしやすい.

それはさておき, A は最近一月ほどのチケットのスループット低下を気にしていた. 著しくスループットをおとしていた B にインタビューすると, テストの実装に時間がかかっているという. コードをみると xUTP のアンチパターンを絵に描いたような光景が広がっていた. その反省から A はチームのコードをレビューするようになる. Subversion から前日の差分を確認し, 指摘事項をメールする形でレビューを開始した.

フェーズ 4 - 炎上, 野ざらし

中間リリース前の試験でいくつか大きな問題がみつかり, 解決にむけ過労な日々がはじまった. 序盤の計画に不備があったためのトラブルで, 簡単な解決はなかった. 試行錯誤を通じいくらか改善した上で顧客に謝罪し, 最終的に一応の決着はみた.

過労期間中のイテレーションは破綻した. 作業時間のうち調査が多くの割合を占め, 計画が立たない. また外出も増えてスプリント計画のミーティングは流会が続いた. 結果として一ヶ月以上イテレーション計画が更新されなかった. タスクボードにはインデクスカードが山積していった. (作業をインデクスカードに書くことはやめていなかった.) 各人が作業に忙殺され, レビューも行われなくなった.

チームは誰もが疲弊していた. 気がつくと夏が終わっていた.

フェーズ 5 - イテレーション短縮, ハンコレビュー

フェーズ 4 は正しく終えることができなかった. 書面の都合で形式的なリリースをしたあと, 次の工期に食い込みながら問題の改善を続けていたからだ. リリースの区切れ目がはっきりしないまま, 済し崩し的に次のリリースに向けた作業が始まるなか, B がポストモーテムを強く求めた. A と C はミーティングを好まない上に横着な性格だったため, わざわざ管理職を掴まえて場所を確保して...と面倒の多いポストモーテムに積極的でなかった. B はそれを察知し, なかば強引にポストモーテム開催を押し切った.

ポストモーテムでは, イテレーションのミーティングやコードレビュー, ペアプログラミングといったそれらしい活動が壊滅していた点が問題点に挙がった. たとえばイテレーションは二週間で区切られていたが, 月に二回の再計画ではミーティングが流会すると予定がずれすぎて悲惨という指摘があった. ちょうど アート・オブ・アジャイル デベロップメント を読み終えたところだった C は Shore にならった一週間のイテレーションを提案し, 試してみることになった.

結果としてこれは上手くいった. もともとチームは誰も計画能力が高くないため, 二週間のイテレーションにぴったりの作業を積み上げるのは難しかった. またプロジェクト自体も流動性が高く, 新しい要望を二週間保留するのは現実的でなかった. なにより作業の単位として "一週間" は区切りがよく, ミーティング場所の確保や管理職の都合, 対外的な足並みなどを融通しやすかった.

レビューについては, 風化しやすい点と A だけが一方的にレビューをしている点が問題視された. どうすればレビューをさぼらずに済ませるかを相談し, タスク=インデクスカード単位のワークフローにレビューを持ち込むことになった. 作業が終わったインデクスカードを適当なメンバーに渡し, レビューを求める. レビューが済んだら作業完了とする. 全員がレビュアであり, 同時にレビュイにもなる.

加えて, レビューを受理したメンバーはインデクスカードにハンコを押すことになった. これもうまく行った. タスクボード上でハンコの押されたカードの量がチームの進捗を表すようになると, ハンコをおさずに作業を終えたと主張するのが難しくなる. だからレビュイーはレビューをさぼらなくなる. レビュアー側も, レビューをさぼっていると机に手渡されたインデクスカードが溜まってしまう. だから最低でも一定数のカードがたまると重い腰をあげてレビューをするようになる. ハンコを押すのがそれなりに気分が良いのも思わぬ発見だった. カードとハンコがレビューに tangibleness を与えた. (ハンコとレビューの高い親和性は他でも見ることができる. 基本的にレビューを必須とする webkit では, ふだんは "Reviewed By" と書くべき ChangeLog のエントリに時折 "Rubber Stamped by" という メッセージがあらわれる.)

ハンコによって進捗を見せるため, タスクボードを進捗ステータスによって分割しなくて済むようになったのも 思わぬ副作用だった. チームが使っているタスクボードはそれほど大きくないため, ステータス毎に面積を食わないのは都合が良い.

フェーズ 6 - プラニング・ポーカー

プロジェクトのなりゆき上, 炎上フェーズ以降このフェーズまで大きな機能要求が保留され, 細々とした機能追加と様々なインフラの準備で日々が過ぎていた. しかしこのフェーズ以降, また大きな機能追加がいくつも予定されていた.

イテレーションを 1 週間に縮めてタスクボードが秩序をとりもどしてから, 顧客から要望が届き次第とりあえず見積りをする習慣ができつつあった. 顧客とのミーティングから戻った A が "また要望が増えた..." とぼやくと, それじゃ見積りですかね, と手近な机で見積りがはじまる. タスクボードにもある種の割れ窓効果があり, ステータスの曖昧なカードが散乱していると見積りの意欲が削がれる. 逆に手綱を持っている実感があると見積りにも精がでた.

チームではプラニング・ポーカー風の見積りを採用していた. ただしポーカーのカードはなく, 紙切れの端に数字を書いていた. また Trac 主体で作業を管理していた頃はチームでの見積りをさぼりがちだった.

あるとき C がどこからかプラニング・ポーカーの実物を入手してきたので, 実際の見積りにも使ってみた. トランプと紙切れの差は, インデクスカードとポストイットの違いほど大きくはなかったが, メンバー間の見積りが不一致だった場合の議論と再見積りは身軽になった.

フェーズ 7 - product backlog の復活

フェーズ 3 の頃から, プロジェクトの冒頭で作った product backlog は保守しきれなくなっていた. イテレーション感覚が長すぎたこと, product backlog と trac の二重管理, 長期間のトラブル対処などがあり, 新しい作業はタスクボードに直行するようになっていた.

一方で, 大きな単位の作業見積りや進捗の報告にタスクボードとインデクスカードは向かなかった. タスクボードに収まるのは 1-2 週間分の作業に過ぎず, これまでの作業を振り返るのはやりにくい. 将来のリリースに関する計画についても同じことが言える.

直近 1-2 フェーズの見直しで目先の秩序は取り戻せていたため, チームは大局的な混乱の回復に目を向けることができた. 顧客から新しい機能要求の見積りを求められたとき, C の提案によって古い product backlog は一旦捨てることになった. そしてタスクボード(とプレ・タスクボードのカード入れ)に積み上がった 機能のリストを product backlog の Excel シートにバックポートした. こうして作成された product backlog は顧客への進捗報告に用いるようになった.

進捗報告のためにアドホックな資料を捏造しないというのも, フェーズ 5 のポストモーテムからあらわれた反省だった. 顧客からのプレッシャーに晒された人間がアドホックに資料をつくると, 都合の悪い事実(=遅れ)を顧客から隠しがちになる. そうした目先のごまかしも炎上を招いた一因だという反省があった.

ごっこあそびの習熟

ハンコレビューの話をするつもりが, 一年をだらだら振り返る内容になってしまった. まあ年末ですからね...

今のチームの成果が文句なし, という気はない. テストが遅いとか, 顧客のフィードバックを十分にとりこめてないとか, 運用のやりづらいシステムとか, 不満は色々ある. "アジャイルだ" というつもりもない. プロジェクトは大粒のリリースからなる半ウォーターフォールで, 毎週顧客にデモすることもない. 契約も硬直的で変化を抱きしめるどころか下手すると突き放しかねない. いわゆる "アジャイルごっこ" の域を出ていない. でも "ビジネスとアジャイル" のような議論を蒸し返したくないので, 今はごっこ遊びを卒業するアイデアを考えない.

ここ 1-2 年, チームで働く意義や, チームの善し悪しに興味を持ってきた. 今日の話もそれが主題. 今年の仕事はこの興味にいくらか答えてくれたと思う.

たとえば, 私は上で紹介したハンコレビューを気に入っている. それは仕組み自体よりこの方法に至った経緯を支持したいからだ.

ハンコレビューはインデクスカードを使う. インデクスカードはプロジェクト途中に C が持ち込んだものだ. (しかも最初はポストイットだった.) 最初にレビューをはじめたのは A だったし, プロジェクトの混乱後にプロセスを立て直せたのは, 規律にうるさい B がポストモーテムを開催したからだった. 見積りにポーカーを持ち込んだのは C だった. 継続的な見積りをさぼらず続けられたのは B の姑気質によるもので, 開発者の見積りが幅を効かせているのは A がはじめにそうしたからだ.

チームの記憶

こう書くと, チームはメンバー選びが重要で 1+1 が以下略とありがちな主張を続けたくなるかもしれない. メンバー選びがどうでも良いとは思わないけれど, 私はその手の組合せ最適化主義によってチームの価値を裏付けるのを好まない. チームメンバーの組合せがよければ, 最初から良い仕事ができるのだろうか?

ハンコレビューの話にもどると, まずインデクスカードを使う気になったのは, しばらく Trac を使っていた二人がタスクカードに関する基調講演を聞いたからだ. Trac の善し悪しに関する共通の体験があったからこそ, それを捨ててインデクスカードを使う気になった. 体験を共有していないプロジェクトの冒頭に同じ議論はできない. (私の勤務先はどのチームも Trac を使っているけれど, その依存度はまちまち. "共通の体験" とはいえない.)

レビューのプロセスを改善する気になったのは, その前に不完全なレビューをしていたからだろう. プロセスのまずさに合意があったからこそ, それを正そうという議論ができる. レビューをはじめたのも, それまでに書いたコードの負債に対する不安をわかりあっていたからだ. 見積りを改善する気になったのは, ザルな見積りのせいで迎えたリリース前の酷い夜を思いだすからだし, 流会つづきで野ざらしになったタスクカードの苦い記憶がイテレーションの短縮につながった. タスクボードのレイアウト変更に抵抗がないのは, Trac 放棄に大した手間を要さなかった過去の体験があるからだ.

共に失敗したからチームとして反省できるし, チームでの反省があるから各人の好みにあわないプロセス変更にも手がだせる. 何かをうまくやった記憶があるからそれを失なったことがわかる. メンバーの性格を理解できるから自分の立ち位置を選べる. 信頼して仕事を任せることもできる.

反省や体験, 記憶や理解には時間がかかる. 逆に言えば, チームとして過ごした時間にはそうした代えがたい価値が潜んでいる.

Grady Booch は, ソフトウェアのアーキテクチャが <種族の記憶> に潜んでいると語った. (とむかし平鍋 blog に書いてあった.) Booch の文脈はレガシーソフトウェアの保守に関するもので, だからアーキテクチャを明らかにするには当時の開発者にインタビューをする必要がある, といった話につながる. レガシーコードから失われたアーキテクチャを復元する取り組みを, Booch は "ソフトウェア考古学" と呼んだ.

チームの記憶は, Booch のいう "種族の記憶" に似ている. ソフトウェアのアーキテクチャだけでなく, もっと多くの記憶が蓄積されている. (上司の寝坊の程度, 同僚の飽きっぽさ, バグの調査にでかけた日の昼食...) Booch の興味は失われた記憶の復元にあったが, 私達開発者は失われる前の記憶をもっている. その記憶を失わずにすめば, 考古学者の世話にならなくても済むだろう.

プロジェクト指向の組織は, プロジェクト単位でチームを集め, 解散する. "チームの記憶" に価値を認めるなら, こうしたプロジェクト単位のチーム構成がどれだけ散財なのかがわかると思う. プロジェクトを通じて蓄えた記憶の山を, 納品と同時に処分してしまう. シュレッダーにかけられた機密書類のように切り刻まれるチームの記憶.

考古学者にさよならを

伝え聞く限り, チームの記憶がもつ価値に意識的なソフトウェア開発組織は多くない. チームの価値創出を組合せ最適化だと捉えている組織もある.

パッケージソフトウェアや自社サービスの開発など, プロジェクトのおわりで解散する動機のうすい開発チームは, 結果としてチームとしての能力を高める傾向があるようだ. 単発の受託開発が主体の組織は, プロジェクト毎に記憶を捨てがちになる. 失われた記憶を取り戻そうと引き継ぎ文書書きに明け暮れる様は悲しい. 生きたソフトウェアをつくるはずの費用が博物館づくりに消えていく.

様々な商業上の制約によって, チームを壊さなければいけないことがあるのもわかる. けれど無自覚にそれを破壊しているように見える場面に出会うことは多い. 本当にその解散は割に合っているのか? 無形の財を踏みにじりながら, ソフトウェアで価値を生み出していると胸を張れるのか?

未来のソフトウェア考古学者より, いま目の前にいる利用者のために働きたい... と大仰な主張をする気はないけれど, チームの記憶を大切にした方が楽しく働けると思うんだよね.

といったところで良いお年を.