開発の品質を上げた7つの方法 - ソース管理、コード管理、テスト導入、開発環境の4つの視点から
ソフトウェア開発における、開発管理の手法やツールには、「品質」を向上させるという目的が存在しますが、開発者はまず、手法やツールの先にある「品質」とは何かを理解する必要があります。ソース管理、コード品質管理、テスト導入、開発環境の4つの視点から、「品質管理」の現場で直面した実例と課題とその解決策について小林昌弘さんが解説します。
- 多くの開発現場で感じた課題
- 手法やツールは手段であり「目的」ではない。目指すべき「品質」を具体的に考えよう
- ソース管理での作業領域の明確化とコミュニケーション
- コードの品質管理で直面する問題と解決策
- テストのセオリーと目的を見定める
- 仮想ソリューションを利用する開発環境の管理
- ここまでの方針を決める際に生じた共通課題
- 最後に
はじめまして、株式会社エンバインド代表の小林です。私はこれまでいくつかのITベンチャーに所属しつつ、そこで技術的な方針を決める役割を数多くこなしてきました。その中には、新しいスタッフと共に新規のサービスを立ち上げる場合や、既存のプロジェクトがうまく進まない場合に参加し、問題解決方法などについていろいろと実施や提案をしてきました。
また、社内のプロジェクトだけではなく、問題に直面した外部プロジェクトに途中から参加し、問題の原因を探し、ゴールに導く「クローザー」のような役割を担うことも多くあります。
その中で、多くの方が開発管理を難しく考え過ぎているという印象を抱くようになりました。
そこで今回は、私が開発現場で経験した、あるいは見てきた失敗において、どのような課題を見つけて解決案を考えてきたかについて紹介します。同じような課題を感じている方々に、それらの事例を参考にしていただければと思います。
多くの開発現場で感じた課題
筆者は2000年くらいまで、汎用機を使い、COBOLで金融システムの開発をしていました。2000年というと少々古い印象を持つかもしれませんが、COBOLのOS、メモリ、CPUなどは仮想化されています。また、障害の時には緊急リリースの手順やテストの方法なども手法として定まっていました。
2000年以降はインターネット上でサービスを提供するITベンチャーに転職しましたが、そこで体験した開発管理手法は、むしろ金融システム開発時より後退している印象があったのです。また、開発管理の重要性をきちんと認識していない開発者が多いことにも驚かされました。例えば、プロジェクトリリースの直前にハードディスク障害などでコードが消えてしまったというようなアクシデントがあってから、はじめてソースの中央管理の必要性が理解されるといった雰囲気です。
こうした過去の経験と比べてみると、現在のWebシステムの開発現場では、多くの開発者がソース管理を当たり前のように導入し、若いITエンジニアでもいろいろな管理方法に興味を持ち、そしてさまざまなツールを駆使していることに感心します。
しかし一方で、多くの開発現場で管理手法やツールの「べき論」が過剰に議論され、開発自体の楽しさを減衰させてしまっているようにも感じるのです。多過ぎる開発ルールやツール運用などが負荷になり、プログラミング自体が苦痛に感じる、というケースは往々にしてあるでしょう。また、管理ツール導入を推進する側からは、いざ導入してはみたものの、あまりうまく運用されておらず、どうしたらいいのか分からないという話を聞くこともありました。
手法やツールは手段であり「目的」ではない。目指すべき「品質」を具体的に考えよう
管理手法やツールには、「品質」を向上させるという目的があります。では、ここで取り沙汰される「品質」とは? 私たち開発者は、手法、ツールの先にある目的、つまり「品質」とは何かを知る必要があります。そして、目的を達成するための手法こそが「品質管理」なのです。
本稿では、「品質管理」を教科書的に学ぶのではなく、私が過去に経験した、品質管理における課題とその解決を、ケーススタディとして解説します。それゆえ、言葉の定義が多少、ISO(国際標準化機構、International Organization for Standardization)やITILITIL(Information Technology Infrastructure Library)といった中で定義されているものと異なる場合もあるかと思います。ご了承ください。
・ISO - 国際標準規格を定めたもの。品質管理に関してはISO9000sがある。
・ITIL - ITサービスを運用する上でのベストプラクティスをまとめたもの。
個人的には、ISOはあくまで「規格」であり、定義やルールという位置付けを強く感じます。一方、ITILはサービスを運用する上での考え方や必要な事項などが多数示されています。私は、実際の開発現場で試行錯誤した末にITILについて知ったのですが、Webシステムの品質を学ぶ上でより身近な教科書として活用し得るテキストだと感じます。
「品質」と「品質管理」
まず、「品質」とはそもそも何を示しているのでしょうか。私がソフトウェア開発プロジェクトにおける品質について考える際は、以下を項目として挙げます。
- (1) 要求した機能を満たしているか
- (2) 予定したスケジュールに収まるか
- (3) 予定した人数で収まるか
- (4) 安全性(セキュリティやスケーラビリティ)は満たしているか
- (5) 継続性(継続して機能開発ができる、使い続けられる)は満たしているか
「品質」の定義として(1)~(4)については多くの方に同意してもらえると思います。一方で、生み出された品質を“維持する”という指針には違和感を覚える方がいるかもしれません。
ここで「品質管理」について考えてみます。品質管理は、実は「品質」を上げるための手法というよりは、結果を「安定」させる方法です。そして、(5)の継続性が寄与するのが「安定」であり、だからこそ重要なのです。
品質の安定性
「品質の安定」とひとことで言っても分かりにくいので、例えば、入試や資格試験などにおける合格点と平均点を例に、図1で考えてみます。
▲図1: 品質と安定
例えば、同じ平均点でも、左図のように合格点以上の点数と落第点の点数を交互に取ってしまう場合と、右図のように常に合格点以上の点数を取れる場合があります。当然ながら、結果である合格率は、左図が50%、右図が100%と大きな差が生じます。
品質管理の大きな目的の一つは、常に合格点を超える平均点を取れるようにすることです。ここで特に注意すべきなのは、安定すると同時に最高得点数も下がってしまう場合があることです。再び、以下に図を示します。
▲図2: 品質管理がうまくいかない場合の例
上記図2のような場合には「品質管理」を高度に行い、結果をあえて安定させない方が良いこともあります。例えば、左図では平均点が合格点を下回っていて、結果が安定していなくとも、50%の確率で合格しています。しかし、右図では結果は安定していますが、常に不合格になってしまっています。
工業製品のように同じものを大量に作る場合を想像してみてください。製造工程でいくつかの不良品が混じった状態(結果に幅がある状態)であっても、ビジネスは遂行可能でしょう。しかし、品質は安定していても全てが不良品、という状態ではビジネスは成立しません。こう考えると、手法やツールを駆使して品質管理を行うことが、必ずしも最良の結果に結びつくわけではないとイメージしやすいと思います。
しかし、具体的な点数や価値を定量化しにくく、まったく同じ要件は二度とないようなWeb開発のプロジェクトでは、どこまでを管理し、どこから管理しないかなどの判断は非常に難しいものです。だからこそ、管理の手法やツールに注目が集まり、運用に多大なコストが投じられることになります。コストを投じるからには、運用を工夫し、チームに便利さを提供せねばなりません。
ここからは、実際に私が管理手法やツールを導入・経験した際に生じた問題や、その解決のためにどうしたかなどを紹介していきます。
ソース管理での作業領域の明確化とコミュニケーション
Git機能ブランチを使った開発では作業途中でもマスターブランチにマージ
図3のように、開発者がGitで機能ごとにブランチを作り、開発を進めます。
▲図3: Git機能ブランチを使った開発フロー
プロジェクトの初期段階に、以下のような問題が発生しました。
- (1) 頻繁にコンフリクトが発生する。
- (2) 各修正ブランチでは正常に動作するが、マージしてみるとうまく動かない。
- (3) 似たような機能を複数の人が作っている。
- (4) これらの結果、開発スケジュールが遅れる。
解決案
ここでの問題の原因として考えられるのは、各開発者が分担する領域が明確に決まっていないことです。しかし、開発初期には仕様が明確に洗い出されていない、また、共通する機能が多い、といった状況が多々あり、作業領域を明確にすることができません。そこで、以下のような運用ルールに変更しました。
- (1) 機能ブランチを使わなくてもOKとする。
- (2) 機能ブランチを使う場合、1日の開発終了時には開発途中であってもマスターブランチにマージする。
結果
新ルールを運用し始めた際には大きなストレスがあったことは事実です。頻繁にコンフリクトが発生する状況もすぐには改善しません。しかし、他の開発者の変更が作業途中であっても毎日取り込まれることで、以前よりはコードに与える影響が小さくなり、その分コンフリクトも小さくなったのです。
小さいコンフリクトの存在から、他の開発者が何をやっているのかに対し積極的に興味を持つ必要が出てきます。それぞれの作業内容がそれぞれに理解されることで、共通部分では役割が自然と決まり、同じような機能を作ることもなくなります。新たな運用ルールでしばらく開発が進むとコンフリクトも生じなくなり、機能ブランチを使っての開発を再開しても同様の問題は生じなくなったのです。
Gitマージリクエストと承認フローの見直し
Gitではまた他の問題にも直面しました。以下図4のように開発者が修正後、マージリクエストを行い、その内容に問題がないことを確認した管理者が承認してマージします。GitHubのようなツールを使って管理する場合によく利用される管理手法だと思います。
▲図4: Gitマージリクエストと承認フロー
各機能を共通の開発環境に適用させつつ動作検証をするフェーズで、以下の問題が発生しました。
- (1) 修正した内容が本当に正しいのか、管理者がコードを見ただけでは判断がつかない。
- (2) 管理者がコードをマージせず、マージリクエストがたまってしまい開発が遅れてしまった。
- (3) マージ後に問題が発生すると、その問題の原因把握と解決に非常に時間がかかってしまっていた。
解決案
開発が進み機能が複雑になってくると、ある修正の中に、要件上必要な修正と、データベースやネットワークなどの技術的制約の解決のために必要な修正が混在するようになってきます。
こうした状況では、要件上必要な機能について把握する立場の管理者では、是非を判断できない修正も増えてしまいます。そこで、以下のような運用ルールに変更しました。
- (1) マージリクエストと承認フローをやめ、修正した開発者自身がマージする。
- (2) マスターブランチで動作する確認環境を用意する。
- (3) 開発者、管理者は(2)の環境を使い、動作が問題ないか確認する。
- (4) 全体的な動作確認をマイルストーンごとにチェックし、問題は別途不具合として管理する。
結果
このプロジェクトは、開発フェーズ、テストフェーズのようにマイルストーンが分かれていたため、マージリクエストごとに動作が正しいのかを検証しなくても、プロジェクト管理上は問題ないと判断し、修正箇所は開発者自らマージをするように変更したのです。不備が生じないための最低限の動作確認は開発者が担い、機能面での確認は管理者が実際に環境を見てチェックしていく方法です。開発者と管理者が共通の環境をもとに会話できるようになったために、コミュニケーション面での誤解が少なくなり、マージ後の問題切り分けもしやすくなります。
一方で、コミュニケーションが多くなったことにより、改善や実装上の小さな不備などが頻繁にタスクとして積まれてしまう問題も生じました。それらの問題は、不具合タスクとして管理し、別途スケジューリングするという対処を行っています。
コードの品質管理で直面する問題と解決策
コーディング規約の運用で共通理解を深める
プロジェクトに参加する開発者が多くなってくると、チーム内でのコードの記述から統一感が失われ、コードが分かりにくくなってきた、と問題提起がされました。そこで問題提起した開発者を中心に別途チームを作り、コーディング規約を作成することにしました。
しかし、こうしたアプローチは次のような別の問題を生みました。コーディング規約を運用し始めてすぐに、それらのコーディング規約に対する不満や反対意見などが出てしまったのです。
- (1) クラス名や変数名についてコーディング規約だけではよく分からない。
- (2) インデントやスコープなどのコーディング規約があまり守られない。
- (3) コーディング規約を守るための時間が必要なので、スケジュールを増やしてほしい。
解決案
それまで使ってきた言語も所属していた業界も異なる開発者同士では、「全員にとって分かりやすいこと」の尺度が合いません。これが原因となり、コーディング規約が機能しにくくなっていたのです。また、広い範囲をカバーするために多くのルールを作ってしまったことで、むしろ心理面での障壁ができてしまいました。
そこで、コーディング規約の目的を「より良いコードを目指すため」ではなく、「最低減、守るべきこと」に変え、以下のような運用方針へと変更しました。
- (1) クラス名の命名ルールではなく、システムの「用語集」を作り、その用語集にないものは自由とする。
- (2) コーディングスタイルの統一は、自動でできる範囲とし、IDE向けの設定を共有する。
結果
変更前、命名ルールがどの程度守られるか、という悩みもありました。例えば、「クラス名」のルールで、複数データを扱う場合には英語の複数形を使うというルールや、名称の後に「List」や「Map」をつけるなどのルールは、多くの方になじみがあるでしょう。
しかし、複数形というルールであれば、複数形の集合はどういうルールにするのかという疑問が生じます。また、「List」をつけるよりも、重複データを含まない場合には「Set」の方が適切ではないかという意見もあるでしょう。
これらはもっともだと感じる一方で、全てを網羅してルール化することはできず、また、意見の提起を禁止することも建設的ではないと感じます。だからこそ、クラス名は命名ルールで制限するのではなく、「用語集」の形にして、仕様の一部としたのです。
例えば、以下の表のようなものです。
名称 | システム名 | 説明 |
---|---|---|
アカウント | Account | ログイン時に利用するID/パスワードを管理する単位 |
アカウントグループ | AccountGroup | 同じ顧客内のアカウント。同じデータ参照権があるアカウント群。 |
このようにすれば、AccountListやAccountsなどのクラス名が使われることはなくなります。また、用語集を作ったことで、開発上のコミュニケーション時に共通理解が生まれ分かりやすくなる、という一石二鳥の結果となりました。
次に、(2)のコーディングスタイルは、IDEでのコーディングスタイルの設定でエクスポートしたものを共有し、その設定で対応できる範囲のみとしました。IDEなどが共通でない場合には、EditorConfigなどのツールを使用してもいいでしょう。とにかく、各開発者の心理的障壁を下げることを優先し、「ルールを守る」ではなく、「守れるルールのみにする」という方針に変更したのです。
なお、用語集は、他のプロジェクトでも再利用され、仕様書や設計書などでも同じ用語が使われるようになっていき、結果としてコードの再利用にもつながるという副産物も生み出されています。
コードレビューでは図を書くことで理解度を把握する
コーディング規約だけではカバーできない部分や、新しく参加する開発者のコードを既存のシステムに取り込む前に、当該プロジェクトでの経験がより豊富な開発者がコードレビューをしようということになりました。
しかし、いざコードレビューを始めてみると、以下のような問題が生じました。
- (1) レビュー時には分かりやすいコードだと思ったが、後から見返すと何をしているのか分かりにくい。
- (2) レビューをしているのに、コードを書いた人のみが修正しなければならない、もしくは修正するのが当たり前のようになってしまっている。
- (3) 最初のレビュー時にはきれいなコードだったのに、修正のたびに汚いコードになってしまい困っている。
解決案
コードレビューに期待した効果には、以下が挙げられます。
- 分かりやすいコードを記述しているか
- 間違いやすいコードを記述していないか
- 開発チームの中での仕様と実装の共有
コードレビューの導入当初は期待した効果が得られませんでした。まず「分かりやすいコード」とは、コードレビューを実施する人、実施するフェーズによって判断基準が異なる、という課題が浮き彫りになりました。例えば、新規のコードでは、処理が分かりやすい「方法」にレビューの重点が置かれています。しかし、プロダクトの運用開始後の修正では、処理の「目的」が分かりやすいかが重視されます。
「レビューで重視すべき点」が安定を欠いたことで、レビューで一度「良い」とされていたコードが、その後「悪い」と判断されてしまうケースが続いたのです。また、こうした問題が影響し、新しく参加してきた開発者にとってコードレビューは好意的に受け止められず、まるで検閲のように捉えられてしまいます。
このようなコードレビューの不全を改善すべく「評価方法の平準化」「コードを書いた開発者が自分のコードの意味を理解しているか、の把握」という、2つの方針を定めたのです。両方針は、以下の2ルールとして具体化されます。
- (1) コードを書いた人に1枚の図を書いて説明してもらい、説明できれば問題なしとする。
- (2) 設計スタイルの良し悪し、特に各エンジニア間の好みでは判断しない。
結果
(1)は、記述した自身のコードの評価方法に一貫性を持たせるためのルールです。コードの「良い」「悪い」の判断には、各開発者の価値観やその時々の関心事が影響しがちです。こうした変動要素を排除するための手法が、「図を書いて説明する」なのです。ここで、大事なのは図を本人が説明できることであり、図自体の良し悪しはもちろん不問です。そして、図の説明通りにコードが記述されていること自体を重視するために、実際のコードの記述方法や設計スタイルへ話がそれないように、(2)のルールを設けます。
間違いやすいコードが生まれる要因として、コードを記述した人自身が、自分のコードをあまり理解できていない、という点が挙げられます。しかし、コードが果たす役割を図にすることで、理解の境界が明確になり、同時にデータがどのようなインターフェースを持つべきかが明確になります。特にAPI設計においては後者の意味合いは大きく、インターフェースがきちんと理解できていれば、仕様もある程度は把握可能です。説明しやすい図が描ければ、同時にコードも分かりやすく、仕様の共有もしやすくなるのです。
また、一見きれいで分かりやすいコードであっても、図で説明できない、図が分かりにくい場合があります。こうした場合は、コードを記述する人がまだ十分に仕様を整理できていない、といった状況を客観的に把握するための材料としても活用できるのです。
仕様整理が不十分な箇所に修正が入ると、コードはどんどん汚くなっていってしまう傾向があります。図によって各開発者の仕様理解を促進することで、その後のコードがきれいになる、という効果も期待できます。
テストのセオリーと目的を見定める
ユニットテストは特定の環境に依存したテストケースと割り切る
コードについてより客観的に問題ないことを保証するためにユニットテストを導入し、プロジェクト全体に対して適用することにしました。
その中で有効な方法として「テストファースト」や「自動テスト」などに挑戦していくことになりました。テストコードを全体に適用していくと、以下のような問題が生じました。
- (1) テストコード自体が多く、テストが適切かどうか分からなくなってしまった。
- (2) テストコードを記述できない。
解決案
こうした問題が発生する背景には、テストファーストや自動テストといった、「方法へのこだわり」があったと仮定しました。そこで、まずはプロジェクト全体でテストコードを記述することを目的として設定し、以下のような方針を立てたのです。
- (1) 成功ケースのみに限定して記述する。
- (2) 特定の環境に依存したテストケースと割り切る。
- (3) 自動テストにこだわらない。
結果
テストコードを記述する際、「失敗ケース」から記述する、というセオリーがあります。しかし、セオリー通りに行おうとすると、まずその難しさに直面します。意味のないテストコードと失敗ケースのコードの違いが分からなくなってしまうのです。記述すべきテストコードを成功ケースに限定したのはこれが理由です。実際、成功ケースならば、テストが記述できないということはほぼありませんでした。
ただし、データがシステムの外部から入力されるケースなどでは、成功ケースでさえ記述できないことがままあります。こうした場合、モックやスタブなどを使い環境依存を排除することが推奨されますが、そこまでの時間がかけられないという理由から、テスト環境という特定の環境に依存したテストケースを記述するようにしたのです。
結果として、自動テストの実施が難しくなってしまいますが、これはすっぱりと諦めます。何よりも大きな結実は、テストコードを記述する流れができたことであり、プロジェクト全体を通じてテストコードによる機能の確認は実現できたのです。
確認作業が重複しがちな部分から自動テストを導入
一度は諦めた自動テストに、再び取り組まなければならない事態に直面します。既に運用しているシステムで、リリースすると既存の機能が動かなくなるという現象が起きたのです。新規の機能が動くことは確認できたのですが、既存機能のチェックまでは気が付かなかったのが原因です。
こうして私たちは、既に運用フェーズに入っているプロジェクトに自動テストを取り入れるべく、改めて挑戦することにしたのです。ただ、やはり簡単にはいかず、以下のような問題が立ちふさがります。
- (1) TDD(テスト駆動開発)を実施するためには、追加の工数が必要になる。
- (2) テストコードのメンテナンスがプロジェクト遅延の原因にならないか、事業責任者との間で問題になった。
プロジェクト管理者からの視点では、テストを実施した結果スケジュールやコストが増えるのは、簡単には了承できない内容です。顧客や担当営業からは、新しい機能のリリースが遅れるくらいならトラブルが生じてからの修正でもよい、という意見も出てきます。
一方のシステム担当側からは、コストやスケジュールが増えても実施したいという意向があり、しばしば意見の衝突が起きるようになってしまったのです。
解決案
なぜ、システム担当は自動テストにこだわるのか。その目的を改めて確認すると、コード修正のたびに同じ確認を何度も行うことが面倒なので自動化したい、コード変更者自身が修正していないところの影響範囲が分からないのでその影響を知りたい、といった意見が上がってきます。これを受けて、以下のような方針を定めたのです。
- (1) テストコードは、リリース済みの部分のメンテナンスのみに行う。
- (2) テストファーストは、これまでと「変わらない部分」の確認チェックのみに行う。
結果
新規機能の部分は開発者も含め多くの人が注意深く確認しているので、あまり大きな問題が生じることはありません。一方で、運用開始後にリリースする新しい機能や機能修正では、比較的同じ箇所で問題が発生する場合が多く、影響テストでも同じ確認作業が何度も発生します。そこで、確認作業が重複しがちな部分から自動テストを導入していったのです。
幸い、これまでの経緯からテストコードはすでに存在しており、自動化の仕組みづくりに集中できます。そして、以前記述したコードをもとに自動化する工程を経て、初期のコードの問題点なども改めて発見されたのです。
仮想ソリューションを利用する開発環境の管理
プロジェクトが成長し、社内の開発者が増え、経験の浅いメンバーが参加するようになる、また、外部の開発者が参加するようになってくると、スピーディに提供できる開発環境が必要になってきます。私が関わったある新規プロジェクトでも同様の局面に差し掛かります。
まずはVagrantを使った仮想環境を用意したのですが、いざ開発を進めていくと、環境設定当初の定義だけでは実現できない機能が生じました。ある開発者は独自の環境変更をするなどして対応していたのですが、プロジェクトに関わる全ての開発者が環境変更に対応できるわけではありません。やがて、目指すべき機能は実現不可能という結論が出てしまったのです。
さらに、リリース直前には以下のような問題が明らかになります。
- (1) リリース環境が作れない。
- (2) 開発者がシステム環境への興味を持ってくれない。
▲図5: Vagrantを使った開発環境での問題
解決案
こうした問題は、過去に成功したプロジェクトのノウハウを、そのまま新プロジェクトのルールとして転用したことが原因でした。いうまでもなく、新しいプロジェクトは過去のそれとまったく同一の環境ではなく、これまで作ってきたルールがうまく機能しない場合があります。むしろ過去の成功体験が、変更を難しくしていたのです。
つまり、解決に必要なのはルールを変更できるチーム作りと、新しい参加者へのノウハウの継承です。これを実現するべく、以下のような方針を立てました。
- (1) 環境変更をしていい経験者グループと初心者・業務委託グループに分ける。
- (2) 経験者グループに初心者グループから一人だけ参加してもらう。
▲図6: チームを分けて環境をメンテナンスする運用
結果
ルールや仕組みを作る際には「例外」も含めた設計が必要です。しかし同時に、例外が自由に解釈されてしまうのも問題です。新たな方針において設定された「経験者」と「初心者」という2つのグループは、言い換えれば、「例外があった際には自由に対応していいグループ」と、「例外を許容しないグループ」となります。
「経験者」グループは、自由な対応が可能である一方、環境について責任を持つ必要があります。ただし、そのままでは、両グループ間に断絶が生じてしまいます。そのため、「経験者」グループに一人だけ、「初級者」に参加してもらい、以下のような情報やノウハウの共有知化を狙ったのです。
- 環境変更について、経験者グループだけが分かるレベルにしないように、初級者の理解度を見ながら決める。
- 初級者が経験者の作業を目の当たりにすることで、積極的に環境変更の知識を身につけるようになる。「自分は知らなくても問題ない」という意識生成を防ぐ仕組みを作る。
結果、リリース環境が作れないという問題は解決し、さらに、経験者グループに参加した初級者大きく成長するという嬉しい副産物も得られたのです。
制約下での開発を経験することで、ともすれば窮屈に感じられる開発環境への耐性と、前提が変わった場合に経験者たちが作ったルールを疑う視点を、多くの初級者が得たのはうれしい結実でした。(逆にむしろ興味をなくしてしまうケースもあり、新たな方針に対して賛否があったことも付記します。)
ここまでの方針を決める際に生じた共通課題
ここまで局面ごとに直面する問題とその解決策を紹介してきました。数多くの管理ツール、手法、ルールを導入して感じるのは、少数の意見をうまく取り入れることの難しさです。
何か新たな管理ツールを導入する際、できるだけ多くの人から賛同を得られるツールを導入する、というのが一般的な考え方でしょう。たとえ少数の人が不便に感じたとしても、多くの人が便利だと感じるツールであれば、多数決の原理で全体に対してより良い解決方法だと感じると思います。しかし、多数決で採用された手段が、品質管理におけるリスクを最小化するとは限りません。これが、管理ルールやツール導入の難しさだと私は考えるのです。
なぜ、多くの人に効果をもたらす手段が最高の結果をもたらさないのか。それは、プロジェクトに潜むリスクのサイズ、そして大きなリスクに対峙する人員構成にギャップがあるからだと思います。多くのWeb開発の場合、人員配置と担当業務領域は以下の図7のような状態になるでしょう。
▲図7: チーム構成とリスクの関係
Web開発においては、新規プロジェクトであっても、まったく新しい機能だけで構成されるとは限りません。必要となる機能や仕組みの多くは、過去のプロジェクトと共通するもので、技術的なリスクは小さいでしょう。ただ、こうした技術的リスクの低い開発がプロジェクトの中でカバーする領域は広く、その分、多くの人員を配置しなければなりません。つまり、「経験済み」で技術的リスクの低い領域の開発に、大多数の人が関わっているわけです。
一方で、カバーする領域は狭くとも、「どうやれば実現できるか分からない機能」「過去の開発を参照できない機能」が必要とされる部分も存在します。このような部分は、プロジェクト内でのカバレッジが低い分、割り当てられる人員も少なくなりがちですが、そこに潜む技術的リスクは実はとても大きいのです。
こうした前提がある中で、管理手段を多数決で決めてしまうということは、リスクが小さい部分を最適化しているにすぎず、本来管理すべき大きなリスクを見過ごしている、とも解釈できます。このように、管理を考える上では、作業量でバランスを取る以上に、リスクのサイズを見極めてバランスを取ることが重要になってくるのです。
最後に
これまでの経験で見てきた中には、管理ルールやツールを導入することで状況が悪化する組織もあれば、ちょっとしたツールを導入するだけで良い方向に進んだ組織もあります。今回紹介した事例を参照し、実行したとしても、同じような結果や効果が得られないこともあるでしょう。
成功パターンからノウハウは学べますが、見逃してはならないのは、成功パターンとは、多様な問題を乗り越えた上で築かれたものであり、自身が直面する障害と同一のものではない、ということです。
過去の優れたノウハウをいざ試そうにも、目の前にはまだ未知の障害が多く残っており、どのような障害か分からず、どうすればうまく進められるのか分からないこともあります。そんな場合は、成功パターンだけを見るのではなく、失敗パターンから失敗の原因や傾向を探るのも重要です。
また、仮に管理に失敗したとしても、その原因をメンバー間で共有することも非常に大切です。そのためには、ルールはできるだけシンプルにし、そして、失敗はプロジェクトの最初のうちに経験する。ときに、従来の管理方法や信じてきたやり方を廃止してしまうことも必要だと思っています。
プロジェクトのメンバーとともに構築した方法は、多少間違っていても、そのプロジェクトの目的に沿って機能することでしょう。
そして何より、当事者たちが発展的な意思をもって決めたルールならば、それは「やっかいな決め事」ではなく、困難を乗り越える心強い杖となるはずです。
参考資料
著者プロフィール
小林昌弘 (こばやし・まさひろ)
監修:WINGSプロジェクト 山田 祥寛
WINGS @yyamada WINGSプロジェクト