ユーザー視点凝集をめぐる冒険 (2) – 継続的なリリースという罠

前回は「どのようにシステムを切るか?」ということについて考えた。

ところで、何故システムを「切る」必要があるのだろうか? それはシステムを作る際に、切り分けたシステムを別々の開発者に割り当てて分業したり、スケジュールに割り当てて完成までのロードマップを作るためである。そしてこのとき、切り分けられたパーツが「ユーザー視点凝集」を満たしていれば、パーツ単体でユーザーの反応を確かめる事が出来る。

タスクを、それぞれ何らかのユーザー価値を生み出す「スモールバッチ(small batch)」に分ける事によって、ウォーターフォール開発のようないわゆる「ラージバッチ(large batch)」なアプローチよりも遥かに早い段階から継続的なフィードバックを得る、というのがアジャイル開発の勘所だった。

インクリメンタル開発(漸増型)とイテレーティブ開発(反復型)

ユーザー視点凝集ごとにシステムを区切る事を「vertical slice(縦方向の分割)」と呼ぶ、というのが前回の話だったが、vertical slice ごとにシステムを作り上げて行く手法は「インクリメンタル(incremental)開発」と呼ばれている。

これはアジャイル以前に開発プロセスの標準的な存在だった RUP(Rational Unified Process)や UP(Unified Process)に含まれていた手法である。これらのプロセスモデルが提唱された90年代後半は、ウォーターフォールを捨ててアジャイルを生み出すまでのちょうど過渡期に当たり、ソフトウェア開発に一発勝負のウォーターフォールは馴染まないという反省から、RUP や UP と言った「繰り返し型」開発プロセスが提唱されるようになった。

インクリメンタル開発は、新規の増分(開発部分)を積み上げていく方法です。この方法は、繰り返しの単位となるN回目、N+1回目で対象となるソフトウェア構造がまったく異なるものや、依存関係のないものに適しており、繰り返しの単位の独立性が保てるので非常に分かりやすいというメリットがあります。もし、N回目、N+1回目の中に、共通するソフトウェア構造が含まれていた場合は、共通部分を別々に開発してしまうことになり、ソフトウェアの保守性に問題が出ます。

この記事の中で紹介されているように、インクリメンタル開発は繰り返し型開発の中の一手法に過ぎない。繰り返し型開発で重要なもう一つの手法は「イテレーティブ(iterative)開発」である。

イテレーティブ開発は、ソフトウェアの全体、あるいは部分について、最初は薄く作り、少しずつ肉付けしていく方法です。この方法は、非常に重要かつ複雑なソフトウェアの個所について、徐々に確認しながら肉付けし、中身を濃くしていけるというメリットがあります。

つまり、イテレーティブ開発は、システムを区切るのではなく、同じユーザー視点凝集(のセット)の完成度を段階的に高めて行く手法だ。

RUP や UP には「ユースケース・ドリブン」と「アーキテクチャ・セントリック」という二大ポリシーがあり、それぞれのポリシーがインクリメンタル開発とイテレーティブ開発に対応している。ユースケース・ドリブンでは、ユースケースという vertical slice ごとに開発を進め、アーキテクチャ・セントリックでは、段階を踏んで全体のアーキテクチャを洗練して行く。この二つのポリシーを組み合わせて、インクリメンタルとイテレーティブのバランスを巧く取りながら開発を進めて行くというのが RUP や UP の要諦である。

考え方としては、今改めて検討しても合理的に思える部分も多いが、CI(Continuous Integration)がまだ一般的でなかった当時、繰り返しのたびにテストをやり直さなければならないという問題や、その他自動化が十分でないためにかかるオーバーヘッドなどを考えると、まだ現実的と言える手法ではなかったのではないかと想像出来る。さらに最も重大だと思われるのは、vertical slice ごとのリリースという考え方がないためにアジャイルのようなフィードバックループを得られず、ユーザー(顧客)視点からはウォーターフォールと何ら変わりのない手法に見えることだ。

「イテレーティブ」の再発見

一つ一つの vertical slice を順番にリリースして、早い段階から「本番」を経験させるのがアジャイルの勘所であると説明したが、このような繰り返しをアジャイルでは「イテレーション」と呼ぶ事が多い。しかし、実際にこの繰り返しが意図するところは「インクリメンタル」な開発である。

アジャイルがインクリメンタル開発にフォーカスしていることを典型的に示すのが、スクラム手法で頻繁に参照される「雪だるまモデル(Snowman model)」だ。

scrum-snowman-model

このように、一つのイテレーション(スクラムでは「スプリント」と呼ぶ)が終わる度に「出荷可能(shippable)」な vertical slice が積み上がって行くイメージである。ユーザーは早い段階で製品に触れて開発者にフィードバックを送る事が可能になり、管理者にとっては、開発のペースが安定して進捗も可視化されるなど、良いこと尽くめのように思える。

しかし、2007年にロンドンで行われた XPDay において、「インクリメンタル開発へのこだわりには大きな落とし穴がある」そう指摘したのが Jeff Patton 氏だった。

Patton氏はインクリメンタルにモナ・リザを描くとしたらどうなるかという例を挙げて、仮にインクリメンタルだけで開発を進めようとすれば、結局は最初の段階で全体像を決めておかなければならず、また全てのパーツを完成させない限り全体像の実物を検証する事も出来ないため、結果的にはウォーターフォールと同じ事になると警告した。

Jeff Patton氏のサイトより
Jeff Patton氏のサイトより

インクリメンタルなプロセスとは対照的に、普通に絵を描く時は以下のようなイテレーティブなプロセスを辿る。

Jeff Patton氏のサイトより
Jeff Patton氏のサイトより

全体像をぼんやりと決めてから徐々に細部を詰めて行く。細部を詰めて行く過程で全体像を調整して行くので、最初に完璧な構想を立てる必要はない。

アジャイル時代になって、インクリメンタル開発がイテレーションと呼ばれるようになり、それまでイテレーションと呼ばれていたコンセプトが抜け落ちてしまったというのが Patton氏の指摘だ。

出荷可能(shippable)とは何か?

インクリメンタル開発の落とし穴は、先ほどの雪だるまモデルで登場した「出荷可能(shippable)」という考え方である。

仮にシステムを vertical slice に分けて開発し、イテレーションの度にリリース出来たとして、それらのパーツの集積が本当に出荷可能だと言えるだろうか?

ほとんどの場合、答えは「ノー」である。

出荷可能の本当の意味は、顧客にとって意味のあるプロダクトである、という当たり前の事実だ。そのプロダクトを使って実際の業務を遂行出来る、あるいはサービスや売り物として成立するなど。そのように考えると、多くのケースで vertical slice はこの水準に相当しないだろう。筆者も何度か経験しているが、 vertical slice に分けて開発したとしても、ある程度全体像が完成してこない限り、顧客、あるいはそれに準ずる役割の人たちは、作りかけの製品には興味を示さなかった。

何故このようなズレが生じるのかと言えば、それはおそらく vertical slice の粒度が開発者視点で決定されているからではないだろうか。顧客に決めてもらうとは言っても、そのフレームワークはそもそも開発者側が考えたものだ。つまり、このときの vertical slice はユーザー視点凝集ではない、ということになる。

元々、開発者視点でシステムを区切る「horizontal slice(横方向の分割)」は好ましくないということで、ユーザー視点であるはずの「vertical slice(縦方向の分割)」を持ち込んだ訳だが、そこでも開発者視点を払拭する事は出来なかったということになる。

インクリメンタルとイテレーティブをミックスする

インクリメンタル開発の落とし穴を避けるためには、アジャイル以前の RUP や UP で提案されていたのと同じように、インクリメンタルとイテレーティブを巧く組み合わせようという話になる(実際には意識せずともそうならざるを得ないが)。そのための手法として、ユーザーストーリーをフィーチャーごとに書くだけでなく、一つのフィーチャーをイテレーティブに発展させるためにストーリーを三枚のカードに分けて書くという方法が提案されている。

この方法によって、一度の開発でフィーチャーを完璧(出荷可能)に仕上げなければならないという、インクリメンタル開発のプレッシャーから解放される。

ユーザー視点凝集をそれぞれ同じ完成度で比較すると粒度がまちまちになってしまい、アジャイルが目指す、ペースを維持した開発を実現することが難しくなってしまう。そこで、ユーザー視点凝集の抽象度(曖昧さ)を調節して、一回のイテレーションに収まるサイズに縮めるというのが、イテレーティブ手法が果たす役割である。

スコープ

アジャイルにおけるインクリメンタル開発の落とし穴と、それを回避するためのインクリメンタル/イテレーティブの組み合わせ、なかなかに説得力のある話ではあるが、一つ重大な点が見過ごされているような気もしなくはない。それはスコープと呼ばれる、全体像の問題である。

イテレーティブの導入によって、詳細な全体像を用意する必要は無くなったかもしれないが、それでも依然として全体像は必要になる。アジャイルやリーンの考え方として出来るだけ多くの意思決定を先送りにするとしても、全体像はある程度決定しておかなければならない。しかし、この全体像がちょっと油断するとチームをウォーターフォールへと引きずり込むアリ地獄のような存在になってしまう。

果たしてこの全体像というのは、どのように決定すれば良いのだろうか?

(続く)

受託開発でアジャイルというのはほとんど語義矛盾ではないだろうか

ここ最近、立て続けにアジャイル絡みの事を書きながらこぼれ落ちた考えをここに書き留めておく。

筆者にとってアジャイルというのは、かなりの程度、個人的な問題だということはまず認めておかなければならない。

個人的だと思う背景には、(自分にとっての)アジャイルというものを、それを知らない人に伝達する事の難しさをつくづく痛感しているからである。

アジャイルはそもそも道具ではない。すでに書いたように、アジャイルというのは価値観であるし、もっと言えば文化だと言っても差し支えないだろう。

人間の集団の中で理屈抜きで共有出来る何らかの価値観があれば、それを文化と呼ぶ。

例えば、一つの組織の中で、ある事が組織の利益になるから同意するというのは、基本的に契約の問題であって文化ではない。つまり、組織にとって利益になるからアジャイルを導入しようという(ベタな)言明はそもそも成り立たない。

アジャイルが結果的に組織にとって利益になるという事は当然あり得るが、利益になるからやるという順番だとそれはもはやアジャイルではない(それが「道具ではない」ということの意味だ)。このようなジレンマが文化というものには必ず付いて回る。

文化を築くのには気が遠くなるほどの時間と幸運が必要になるが壊れるのは一瞬である。特に営利組織の中で働いていて、その利益以外の事で価値観を共有するというのは基本的に至難の業である。

アジャイルはもう終わったという話が度々出てくるが、そのほとんどはハイプ・サイクル絡みの話だった。そもそも無理筋なことをやろうとしていた、というだけのことではないだろうか。

アジャイルはそもそも「無理」から出発した方が良いのだろう。

アジャイルはソフトウェア開発にクリエイションを持ち込もうとしたが、ほとんどの現場ではそんなものを求めていなかった。

日本ではソフトウェア開発の多くが受託開発だと言われている。

受託開発というものがそもそも「アイデアを他者によって実現してもらう」という考えで成り立っている以上、開発側にクリエイション(アイデアをいかに発見するか)が入り込む余地がない。

文化という側面で言えば、人に頼まれて何かをやるという仕事の方式そのものが減点ベースの評価にならざるを得ず、アジャイルとそもそも相容れないと言う事も出来る。

これは受託開発だったらウォーターフォールという選択の問題ではない。人に頼まれて何かをやるときは「交渉」が最重要事案になるというだけだ。

自分達で発見したものを世に問うという仕事に就きたいというのは完全に価値観の問題であって、多くの人にとっては「人に頼まれて何かをやる」のがそもそも仕事の定義であり、その上で生活が成り立っている。社会全体としては価値を生み出していなくても「交渉」によってお金を回す事は出来る(それが持続可能なのかは別にして)。

アジャイル最大の難点は、当たり前だが、そこで価値の発見が保証されているわけではないというところだろうか。以前、スティーヴン・キング氏の自伝「On Writing: A Memoir of the Craft」を紹介したが、それを読めば誰もが小説が書けるわけではないのと同じように。

何が見つかるか分からない状況で旅に出ることをこの上ない喜びと感じるか、そんな博打を打っていたら生活が成り立たないと嘆くか、そこが文化の分かれ道かもしれない。

アジャイルはプログラマーに万能を求める。

アジャイルの問題意識がそもそも役割の分断にあるので、必然的に分断された役割を小さな範囲に集約していくことになる。そこを突き詰めると、それは単にフルスタックエンジニアになるというレベルを超えて、各人が自律したマーケターになることも要求されるようになる。

興味深い事に、これはマーケティング分野の側でも同じような事が言われているようだ。

アジャイルにおいて創造のエンジンを担っているのはプログラマーの側である。その外側にいてアイデアや舵取りの責任を持つ人間の存在はアジャイルにとっては単なる非効率に過ぎない。技術がイノベーションの源泉になっている、あるいはそのような組織を目指しているのなら尚更、外側の人間がアジャイルのエンジンに噛み合って仕事ができるという幻想を捨てなければならない。

しかし、冷静に考えてみよう。こんなことが可能な環境や組織が果たしてどのぐらい存在するだろうか? あるいはそれこそがクリエーションの希少性と呼べるものなのかもしれないが。

ユーザー視点凝集をめぐる冒険 (1) – どのようにシステムを切るか?

凝集性というのは、どのような尺度でプログラムを分けるかという問題だ。凝集度は高い方が良いと言っても、この高い・低いという判断は一筋縄で行くものではない。というのは、どのような尺度を利用するかによって、ある視点からは凝集度が高くなるように見えても、別の視点からは凝集度が低く見えてしまうからである。

以前、連載記事『TDD再考』の中で、凝集性の分類として「論理的凝集」と「機能的凝集」というものがあるということを紹介した。論理的凝集は実装上の特徴でまとまりを作り、機能的凝集は(プログラムの利用者から見た)機能の単位でまとまりを作る。つまり、これらの尺度の違いは、それぞれのまとまりの受益者が異なる事に由来する。前者は開発者の視点であり、後者はユーザーの視点だ。

わざわざ「(プログラムの利用者から見た)機能」と前置きのあるところから分かるように、「機能」という概念がそもそも視点を前提としていることに注意して欲しい。機能というのは受益者がいて初めて成り立つ概念である。機能的凝集がユーザーから見た機能に対応する一方、論理的凝集は開発者から見た機能に対応するという意味では、いずれも「機能的凝集」と呼んでも差し支えないはずなのだ。分けるという行為を実際に根拠づけるのは視点であり、そのように考えると、凝集性の分類でより適切なのは視点による分類ではないだろうかと思う。というわけで、ここでは機能的凝集を「ユーザー視点凝集」、論理的凝集を「開発者視点凝集」と呼んでみる事にしたい。

coherence

プログラムデザインの手法としてレイヤーアーキテクチャが人気なのは、レイヤーが開発者視点凝集、つまりプログラマーから見た凝集性を実現しているからだと言っても良いのかもしれない。データアクセスの処理や、ユーザーからのリクエストを各々のロジックに振り分ける処理など、ユーザーにとってはブラックボックスの中身の話であるが、プログラマーにとっては日常である。

『TDD再考』では、Ruby on Rails 開発者の David Heinemeier Hansson 氏が——先ほど導入した言葉を使って説明すれば——開発者視点凝集よりもユーザー視点凝集を重視すべきだという主張を展開していることを紹介した。TDDのような手法を使ってプログラムをデザインすると、ミクロなレベルではどうしても開発者視点に引っ張られて、結果的にユーザー視点凝集よりも開発者視点凝集を優先してしまうというのがDHH氏によるTDD批判の要点である。

21世紀に入ってからユーザー視点凝集はプログラムデザインおいて極めて重要な地位を占めている。ひょっとしたら最も重要な概念だと言っても間違いではないのかもしれない。それはユーザー視点凝集がアジャイル開発を進める際の単位として想定されているからである。

アジャイル界隈では、ユーザー視点凝集を「vertical slice(縦方向の分割)」と呼んでいる。

この vertical slice についての分かりやすい説明が、最近話題の書籍『SOFT SKILLS』の著者、John Sonmez 氏のサイト「Simple Programmer」にあった。

Sonmez氏は vertical slice を「家を建てる」という例で説明している。

普通に家を建てる時の手順を想像してみよう。まず最初に作らなければならないのは土台である。基礎工事で土台を作り、そこに骨組みを乗せる。その後、骨組みに沿って壁を作り、最後に屋根を乗せる。この最後のステップが完了して初めて実際の家の中身を確認する事が出来るようになる。

このように普通の家屋建築で現れる手順は「horizontal slice(横方向の分割)」に基づいて作業が分かれている。

house-horizontal

この horizontal slice に対して、vertical slice で家を建てるというのは、まず一つの部屋を利用出来るような形で完成させ、その次にまた別の部屋を作るという感じで、人間が実際に利用出来る最小単位ごとに建物を作っていくことに相当する。

house-vertical

部屋ごとに家を建てるのは、建築においてはいささか非現実的なアプローチに見えるが、ソフトウェア開発においては重要な考え方になりつつある。

そもそもソフトウェア開発でも、この家屋建築の例と同じように horizontal slice に基づいた開発が主流だった。それは作業を縦に分割するよりも横に分割する方が遥かに簡単だからである。しかし、horizontal slice は一つ一つのスライスがシステム全体に渡るため、最初に全体の設計図を書かなければならない。更には、一つ一つのスライス(レイヤー)を合体して完成品とする最終段階で想定と異なる事実が判明しても、そこから大幅な変更をするためには大きなコストがかかってしまう。変化の速いソフトウェアの世界では horizontal slice による開発ではなく、vertical slice によって、出来るだけ早い段階で機能の検証を行うべきだというのがアジャイル開発の考え方であった。

A vertical slice from the components of a project
A vertical slice from the components of a project

しかし、この「家を建てる」例での説明は、若干ミスリードな部分もあるかもしれないなと思う。というのは、家の場合は例外なくまず先に設計書があって、それに従って現場の大工さんが家を建てる流れになるが、ソフトウェア開発、あるいはプログラミングは、大工さんの作業というよりも、設計書を作る方に相当するのではないかと思うからである。その意味で、家屋やその他の建築物の設計書を作るプロセスはソフトウェア開発と変わりない試行錯誤があるはずである。

ユーザー視点凝集をめぐる冒険 (2) – 継続的なリリースという罠

#noprojects: もう「プロジェクト」というアプローチでは価値を生み出せない

ちょっと前に InfoQ から「#noprojects」という電子書籍が出ていた。

cover-noprojects-emag

この書籍には、それぞれ別の論者によって書かれた6つの記事が掲載されている。「No projects」というそのタイトルの通り、これまで当たり前のように採用されて来た「プロジェクト」というアプローチは既に有効ではない、というのがこれらの記事に共通する主張である。

一見、過激で論争を呼びそうな主張であるが、内容を仔細に検討してみると、アジャイルというものを追求して行けば自然にこの形に到達するだろうなと腑に落ちる内容だった。アイデアとしては、アジャイルがより多くの領域に援用されるきっかけとなった、リーン、あるいはリーン・スタートアップや、このゆびてくでも紹介したインパクトマッピングなどのアイデアをミックスしてより一般的な形で展開させたものである。

そもそも「プロジェクト」とは何だろうか?

プロジェクトには始まりと終わりがある。プロジェクトはあるタイミングで開始されて、そして終了するタイミングは予め決定されている(実際にその通り終了するかどうかは別にして)。プロジェクトの最大の目的は「プロジェクトを終了させる」ことである。プロジェクトには固定の期間と人員、そしてそれに合わせた固定の予算、そして固定のアウトプットが想定されている。つまり、プロジェクトとは、予算を持ってそれを計画する人の都合に合わせる事を目的にしたアプローチなのである。言って見れば、予算と青写真を入れてボタンを押せば、決まった期日にアウトプットが出てくる魔法の箱である。

そんな魔法の箱は存在しない、そして、たとえ青写真通りのアウトプットが出てきたとしても、その時にはすっかり価値がなくなっている、というのが #noprojects の主張である。

プロジェクトというのは、ウォータフォール型開発の最後の遺産だと言えるかもしれない。これまでその存在があまりにも自明過ぎたためにアジャイルの時代になっても生き延びてきた。しかし、アジャイルでは既に、どの段階でもプロダクトをリリース出来るという継続的デリバリー(Continuous Delivery)が普及しつつあり、そのような現場においてプロジェクトというアプローチは形骸化しつつある。

最初に計画を行い、そしてその通りに物事が進んで、予定の期日にものが出来上がってくるという想定は間違っている、必ず想定外の事象が発生して変更を迫られることになるのだから、予め変更に強い体制を整えておかなければならない、というのがアジャイルの考え方であり、自然に #noprojects に繋がるものであるが、実際には多くの管理者がガントチャートを作りたがるし、物事が想定通り進まないのはどこかに原因があって、それを個別に対処して行けばプロジェクトを元のレールに乗せる事が出来ると信じている。頭の中では変化を想定しなければと思う反面、行動としてはどうしてもウォータフォールの影を引きずってしまう。プロジェクトという形態を取る限り、失敗の原因を計画に求める他なく、故により多くの事を予め想定しておこうという考えから脱する事ができない。

あるいは「変化に対応しよう」というアジャイルのスローガンに問題があるのかもしれない。変化があるかないかで言えば、変化がなく想定通りに進むプロジェクトだってあるだろうと主張する人も出てくる。よって、アジャイルかウォータフォールなのかは適材適所なのだという主張も成り立つ。しかし、本当の問題はそこにはない。ソフトウェア開発が開発の中途で想定外の変化を遂げるのは、その中でより価値のあるものを「発見」しようとするからである。ほら、想定通り物事が進んだじゃないか、そういうことだってあるんだ、と言っても、そのようにして出てきたものには既に価値はない、というのがソフトウェアの世界である。よって、スローガンとしては「発見を主眼におかないソフトウェア開発にはもはや価値を産み出せない」と言った方が良いのかもしれない。

継続性

プロジェクトに代わって、新たなモデルとして提案されているのが「継続的な変更の流れ(Continuous stream of change)」あるいは「流れ作業生産(Flow production)」と呼ばれるものだ。「流れ作業」というと、アジャイルが目の敵にしていたテイラリズムを想像してしまうが、ここでのフォーカスは顧客価値に基づく小さな変更を継続的に行うことにある。リーンの「かんばん」などはこのモデルに近い。

そして、ここでのキーワードは「継続性」である。プロジェクトは基本的に large-batch なアプローチであり、リスクも高いしオーバーヘッドコストも馬鹿にならない。これまではプロダクト(アウトプット)ごとにプロジェクトを組むのが一般的であったが、この方法だと新しいプロダクトを計画する度にチームを編成してプロジェクトを立ち上げなければならない。同じプロダクトでもバージョンアップや改修があるときに別のプロジェクトを立ち上げるのはよく見かける光景だ。#noprojects が提案するのは、アウトプットではなく「成果(Outcome)」にコミットするチームを編成し、その成果を実現するために継続的な変更をリリースしていくモデルである。成果とは、組織にとってどのぐらいの「価値(Value)」があるかという尺度で評価される何らかの「変化(Change)」のことだ。

このようなモデルにおいて、プロジェクトに代わって重要な存在になるのは「チーム」である。チームは結果的な価値にコミットするため、同じチームが複数のプロダクトに関わることは自然なことであり、そこに継続性が生まれる。このようなチームを「価値提供チーム(Value-delivery team)」と呼ぶ。これまでのプロジェクトモデルの問題は、プロジェクトごとにチームが編成・解散されることが多く、せっかく蓄積した知識やノウハウの連続性がそこで失われる事であった。

これまでのプロダクトにフォーカスするプロジェクトベースの開発では、開発者、営業、マーケティング、サポートといった、組織内の機能ごとにチームを分けるのが一般的だった。そして、このように役割で組織が分断されるという問題が、このゆびてくでも繰り返し取り上げてきた、アジャイルやDevOps、インパクトマッピングといった考え方が繰り返し指摘する、現代のソフトウェア開発における最大の障害なのである。チームが価値にコミットするためには、そのために必要な全ての機能をチームの中に備えておかなければならない。これを「機能横断型チーム(Cross-functional team)」と呼び、たとえれば、チームがミニチュアなベンチャー企業となるようなイメージである。実際に、#noprojects の記事の中では、ベンチャーキャピタルの組織内バージョンだと指摘されている。

このような機能横断型チームが、小さなサイクルで実験と学習を繰り返しながら価値を発見しようと継続的な努力を続ける、これが #noprojects が提案するソフトウェア開発のあり方である。

#noprojectsの重要なコンセプト

#noprojects では、その手法を構成する重要な要素として、以下の5つのコンセプトを挙げている:

  • 価値(Value)
  • 成果(Outcome)
  • アクティビティ(Activity)
  • ルール(Principle)
  • 継続的デリバリー(Continuous delivery)

チームは「成果」を生み出すために「ルール」に基づいて「アクティビティ」に従事し、その「成果」は「価値」によって測定される。そして、その継続性とサイクルの短さは「継続的デリバリー」によって担保される。

価値(Value)

価値というのはなかなかに厄介な概念である。ほとんど「主観」と同義だと言っていいぐらいに不確かなものであるし、多くの賢人が指摘しているように、数字に置き換えて理解しようとすると途端に落とし穴にハマる危険性が高くなる。#noprojects では、その不確かさはそもそもビジネスをする際には付き物であり、そこが正確に予測出来るのであればマーケットも簡単に予測可能になるはずだが実際にはそうなっていないと、価値問題に深入りする事は避けている。しかしながら、組織が成功するかどうかのファクターのほとんどはこの価値に関わっていて、仮に #noprojects を実現したとしても、それは単にスタート地点に立っただけに過ぎない。

この価値の問題については、以前「我々は何のためにソフトウェアを開発するのか?」という記事の中でも取り上げた。その中で、Ron Jeffries氏による価値の定義「Value is what you want(価値とはあなたが欲しいもの)」を紹介した。価値を突き詰めれば、経済の問題だと考える人も多いだろうし、あるいは文学の問題だと思う人もいるかもしれない。

#noprojects によれば、一度成果として実現された価値というものは、変更を継続しなければ、時間が経つにつれて減衰していくと言う。これが、プロジェクトモデルに代えて継続的手法を取るべきだという主張の直接的な根拠になっている。

成果(Outcome)

成果とは、具体的なプロダクトやアウトプットではなく、価値によって計測可能な変化の集積である。このように表現するとなかなかイメージを掴みづらいが、記事の中では「アクティブユーザーの獲得」や「スタッフ満足度の向上」などが例として挙げられている。

Agile India 2016 - Leadership Day Summary より
Agile India 2016 – Leadership Day Summary より

この「成果」は、以前ゆびてくで紹介したインパクトマッピングの「ゴール(Why?)」に相当する。つまり、インパクトマッピングを利用すれば、成果を実現するためにはどのようなアクティビティを行えば良いかを考える際の助けになるし、かつチーム内での情報共有においても効果的である。

map

im_example

アクティビティ(Activity)

アクティビティとは、成果を生むための必要な個別のタスクのことである。#noprojects では、個々のアクティビティを事前に評価するための手法として「アクティビティ・キャンバス(Activity canvas)」というものを提案している。以下のように、アクティビティにかかる手間をX軸、実現できる価値をY軸とするキャンバスを用意し、そこに個々のアクティビティをマッピングして行く。

Agile India 2016 - Leadership Day Summary より
Agile India 2016 – Leadership Day Summary より

上のようにアクティビティをマッピングして行くと、どのような順番でアクティビティを実施したら良いかという優先順位が自然に現れてくる。#noprojects に限らず、アジャイルで重要なのは、タスクを「高」「中」「低」のような役に立たない優先順位に分ける事ではなく、実施の順序を決めることである(次に何をやればよいか?)。タスクを順序付けることによって同時並行で処理するタスクの数を減らせば、チーム全体のスループットを向上させることができる。

ルール(Principle)

アクティビティの実施方法は完全に自由というわけではなく、多少をコストをかけてでも若干のルールを作っておくことによって、アクティビティとプロセス全体の親和性、あるいはアウトプットの品質を保つ。アジャイルで言えばプラクティスに相当するが、プログラミング、コミュニケーション、セキュリティ、ブランディングなど、共有するルールはプラクティスよりも多岐に渡る。ルールでチームを縛るというよりも、最低限守らなければならない作法を明確にしておくことによって、その他はメンバーの裁量に任せるという意味合いが強い。

ルールの導入にはコストがかかるため、「MoSCoW」という優先度割当の方法が紹介されている。MoSCoWではルールごとに以下の4つのカテゴリーから選んで優先順位を割り当てる。

  • M (Must have) – 必ず従わなければならない
  • S (Should have) – 正当な理由がない限りは従う
  • C (Could have) – 個人の裁量に任せる
  • W (Won’t have) – 出来るだけ避けるべき

継続的デリバリー(Continuous delivery)

#noprojects のような考え方が提唱されたり、あるいは現実的になってきたのは、インフラ技術の進歩によって継続的なデリバリーが実現出来るようになってきたからだと言っても過言ではないだろう。継続的デリバリーを、アジャイル以後のDevOps時代に生み出された最も重要な技術的達成だと位置付ける人も多く、より具体的で分かりやすい継続的デリバリーという考え方をアジャイルの後継とすべきだという主張も見かけた。

まとめ

以上、#noprojects の考え方を概観してみた。

プロジェクトは計画の別名だと言ってもよく、計画を軸にビジネスを進めると本当に重要な価値の追求よりも計画の履行を優先してしまうことになる。#noprojects の問題意識をひと言で言えば、そんな感じになるだろうか。計画・施行のモデルは、同じようなプロダクトを作り続ける事に意味があった20世紀型のビジネスモデルであり、21世紀の今では発見的な手法に移行しなければ新たな価値を生み出す事は出来ない。その意味で、本来は技術者よりも、経営者やマネジメントがアジャイルや #noprojects のような手法を理解しなければならないはずである。しかしながら、マネジメントの利害を考えると #noprojects が世の中の大勢を占めるトップダウン型の企業に浸透するとは到底思えない。これまでプロジェクトマネジャーが担当していた責任をチームに委任することになり、マネジメントの役割は大きく変わる事になるからである。

ビジョンを曇らせる誘惑: 技術偏重、一貫性

James Hague (@dadgumjames) 氏は、少年時代に一世を風靡した『パックマン』などのゲームに影響を受けてプログラミングを始めた。高校時代にはコンピュータ雑誌の常連投稿者として活躍、大学卒業後もゲームプログラマーとしてSNES(海外版のスーパーファミコン)向けのゲームを開発した。当時はアセンブリ言語で開発していた彼も、次第にマンネリを感じて高級言語を物色し始め、丁度その頃オープンソース化された Erlang で関数型プログラミングの門戸を叩いて今に至る。

パックマン from Wikipedia

そのようなキャリアを持つ彼が、長らくプログラマとして活動する内に気がついた事があると言う。それは、いつの頃からか新しいアプリケーションをデザインする時には、技術的・実装的な見地から逆算的に物事を考えるようになり、ユーザーやプレイヤーの観点から完成品を想定することが少なくなっていたということだった。

技術者は長くその専門領域に棲息するうちに、その領域の尺度だけで物事の良し悪しを判断するようになる。技術者のコミュニティでは、そのような尺度の元に序列付けが行われて、個々の技術者にプレッシャーを与え続ける。その結果として、何のためにそのアプリケーションを開発するのかということは脇に置かれ、パフォーマンスやプログラムデザインのような技術的達成が優先的に考慮されるようになる。

Hague 氏がプログラミングを始めた頃、プログラミングは彼のビジョンを実現するための道具に過ぎなかった。しかしそれが、プログラミング自体にのめり込むにつれて次第に自己目的化してしまった。そのねじれを解消するために、もう一度原点に戻ろうという思いがこの The Recovering Programmer というタイトルに込められている。

前回の記事「TDD再考 (8) – 凝集性(cohesion)とは何なのか?」で紹介した論理的凝集と機能的凝集の対立もこの問題と密接に関係している。アプリケーションの目的から考えれば機能的凝集を目指すべきところでも、油断すれば技術偏重に陥り、論理的凝集を優先してしまうことになる。そしてこの問題は Hague 氏だけでなく、このブログでも紹介してきたように、ビジネスと技術の対立を解消すべく現れたアジャイルムーブメントによってもフォーカスされてきた。特にその流れの中で提案されたドメイン駆動設計(Domain-driven design, DDD)は、機能的凝集に集中するための方法論だと考えると分かりやすいかもしれない。

アジャイルが指摘したのは、機能的凝集は動くターゲットであるということであった。それまでのソフトウェア開発で念頭に置かれていたような静止したゴールは存在しない。継続的に効果を得るためには、ユーザーとのインタラクションを重ねて、ユーザーにとって意味のある「文脈」を構築していかなければならない。

デジタルマーケティングの世界で長年活躍してきた Joanna Lord (@JoannaLord) 氏は、ブランドマーケティングの観点から、一貫性への過剰な執着がブランドの機能的凝集(coherence)を損なう要因になり得ると指摘する。

彼女によれば、ブランドの一貫性とは、裏を返せばそのブランドが変化せず、(環境が変わっても)常に同じ体験を提供し続けるときに実現されるものだと言う。コメント欄で指摘されているように、コカコーラのような長い歴史の中でブランドが確立しているようなケースではその一貫性を維持する理由があるが、現代の状況の中で新しいブランドを構築していかなければならない場合、一貫性より機能的凝集を目指さなければ生き残りは難しい。

一貫性というのは分かりやすい価値であるが故に過剰に追求されやすい。そして、一貫性を保とうとすれば、新しいアイデアを試したり、大胆な変更を行う事に対して臆病になってしまう。その結果としてユーザーにとっての価値、つまり機能的凝集が時間とともに失われてしまうことになる。

フィーチャーブランチを利用した開発はチームを継続的インテグレーションから遠ざける

つい最近、たまチームでは Git Flow を利用したブランチ管理に移行したばかりだったので、この記事を見かけた時は一瞬ムムッとなったが、実際に読んでみて、なるほどと思える反面、どのようなブランチ管理を導入するかはそのプロジェクトの性格に依る部分も大きいのではないかと感じた。というわけで、今回はブランチ管理とアジャイルの関係、そしてその理想からはやや距離を取ることになったたまチームの現状についてまとめてみたい。

Git Flow による Integration Feature Branching

以下は、Steve Smith氏によるブランチ管理方法の4分類:

これまでたまチームは、Gitのブランチ管理に関しては何も方針を決めておらず(単純に master に push されたものがステージング・本番、双方へのデプロイ可能なバージョンとしてビルドされる)、結果的に Trunk Based Development という、今回の記事で推薦されている、ブランチを極力作らないシンプルな開発モデルになっていたのだが、後述する事情で以下のような Vincent Driessen氏提案のブランチ管理に移行した。

このブランチモデルについては、Driessen氏による図を見てもらうのが一番分かりやすい。

git-model@2x

基本のブランチとして master と develop の二つを用意し、developが開発用の基本ブランチ、masterが本番用のブランチとなる。開発の基本的なフローは、「フィーチャーの開発」と「リリース」の二つが軸となり、それぞれ、

  • フィーチャー
    • フィーチャーブランチを作って、終わったら develop にマージ
  • リリース
    • リリースブランチを作って、終わったら master と develop の双方にマージ
    • masterにマージしたところで、リリースバージョンのタグを付けておく

これらのフローにまつわる git の操作を簡単にしてくれるのが、git-flow というgitコマンドの拡張である。以下のようなコマンドを打つだけで、ブランチの作成から移動・マージまで全部自動でやってくれる。

$ git flow feature start feature_name
... (code and commit)
$ git flow feature finish feature_name

Smith氏は、この Git Flow によるブランチ管理を Integration Feature Branching と呼び、継続的インテグレーションを実現するためには全くお勧め出来ないとしている。

フィーチャーブランチと継続的インテグレーション

フィーチャーブランチと継続的インテグレーションの関係については、2009年に書かれた Martin Fowler氏の記事でより詳細に説明されている。

今回の InfoQ や Fowler氏の記事で説明されているフィーチャーブランチの問題点を一言で言えば、共有ブランチに対する変更の粒度が大きくなるため、マージの際のトラブルが起こりやすくなる、ということになるだろうか。

フィーチャーブランチのメリットは、共有のブランチに影響を与えることなく個々の機能を独立して開発出来ることである。一つ一つの機能がブランチとして分かれることによって、リリース(マージ)する機能をその場で選択する cherry-picking のような運用が可能になる。しかし、独立しているが故に、個々の機能の間のコミュニケーションが不十分になり、いざ共有ブランチでマージしようとした時に、解決の難しい衝突を引き起こす可能性があるとFowler氏は指摘する。

衝突のリスクは開発者に心理的な影響を及ぼす。例えば、自分のフィーチャーブランチで行った変更が、他人のフィーチャーブランチに対して意図せぬ影響を及ぼすのが怖くなり、大胆なリファクタリングがやりづらくなる。これは一つ一つのフィーチャーブランチが大きくなればなるほど顕著になるだろう。

継続的インテグレーションのそもそもの目的は、プログラム全体を頻繁に結合することによって、結合に関する問題の粒度を小さくしようということであった。つまり、フィーチャーブランチの考え方は、そもそも継続的インテグレーションと相容れないということになる。

インクリメンタルな開発を実現するためのコスト

継続的インテグレーションの理想は、全てのコミットがリリース可能な単位になることである。その理想状態の元では、当然のことながらブランチを分けて開発する必要は無くなる。しかし、そのようなインクリメンタル開発を実現するコストは決して低くない。例えば、一つの機能の開発が一つのコミットで完了することはむしろ稀だろう。一つのコミットで終わらない場合、その中途半端に実装された機能を抱えたシステムをどのようにリリースすれば良いのか? その問題に対処するために提案されているのが FeatureToggleBranchByAbstraction と言ったテクニックである。

上のようなテクニックがあったとしても、全てのコミットをリリース可能にするためには、Steve Smith氏も認めているように、かなりの訓練と経験を必要とする。これは以前の記事でも書いたように、システムをそれぞれ完結した vertical slice 単位で開発しなければならないアジャイルの本質的な難しさである。

たまチームの場合

理想的な継続的インテグレーション、さらにはその到達点である継続的デリバリーを実現するためには、いつでもカジュアルに本番を更新できるような体制と環境を整えておかなければならない。それは技術的な面だけではなく、文化的な面でも高いハードルをクリアしておく必要があり、残念ながらたまチームの場合は、まだそこまでのレベルに達しているとは言い難い。カジュアルに本番を更新出来ない場合、つまり本番更新の頻度が比較的少ない場合、ステージングと本番でビルド(ブランチ)を共有しているといろいろと不便なところが出てくる。例えば、どのビルドが本番に上がっているかが分かりづらくなったり、本番に対する Hotfix がやりづらくなったりする。そういった問題に対処するためにステージングと本番でブランチを分けておいた方が良いのではないかという話になり、Git Flow によるブランチ管理を採用するに至った。

フィーチャーブランチについては、現状だと一つのリポジトリは基本的に一人の開発者が担当していることが多いので、それほどこだわらずに開発者個人の裁量に任せる感じで問題ないように思える。しかし、これが複数人で共同開発するようになった場合は、フィーチャーブランチの扱いには十分気をつけなければならないだろう。

アジャイルがうまくいかないのは何故か?(2015年版)

The GROWS Method™

「アジャイルの失敗」という話は、今となっては特に目新しいものでもない。筆者が記憶している限りで古いものだと、2008年に書かれた James Shore氏の「The Decline and Fall of Agile」という記事がある。

「ソフトウェア開発に銀の弾などない」と、あらゆるIT専門書のイントロダクションに断わりが入れてあるのに、未だに「○○を試したけど効果がない」という苦情が後を絶たないのは何故なのだろうか。

今回のブログ記事「The Failure of Agile」を書いた Andrew Hunt氏は、「達人プログラマー」の共著者であり、「アジャイルソフトウェア開発宣言」の発起人17名の中の一人でもある。彼は、7年前の James Shore氏と同じく、アジャイルがうまく行かないのはアジャイルを正しく実践していないからだと指摘する。

具体的にはこういうことである。初心者がアジャイル開発を始めるに当たっては、何かリファレンスになるような書籍やルールを参照するのが普通である。しかし、ほとんどの初心者はルールに従うという最初の段階から先に進む事ができない。アジャイルは参加者に「変化」を求める。既存のルールに問題があれば、そのルールを変えて、自分たちの状況にあったルールを新たに生み出し、そしてそれを継続的に更新していかなければならない。アジャイルを継続的に行うためには、アジャイルの書籍に書かれている事にこだわっていてはいけない、というねじれを乗り越えて行かなければならない。その上、コミュニティの中には正規のプラクティスを実践しているかどうかに執拗にこだわるアジャイルポリスみたいな人たちがいる(cf. TDDポリス)。ますますアジャイル本来の意図からは遠ざかるわけである。

この状況を打開するため、Hunt氏は「GROWS™」という手法を提案している。GROWSは「GRowing Real-World Oriented Working Systems」の略語にもなっており、これは商標として扱われている。誰でも自由に使えるようにしてその本来の意味を歪められてしまったアジャイルの轍を踏まないように、というのが商標にした理由らしい。

GROWS™の詳細は現段階でまだ明らかにされていないが、基本のステップを「実験」と捉えることや、フィードバックに対するエビデンス(証拠)ベースの判断等、かなりリーン・スタートアップに近い手法なのではないかという印象を受けた。

さて、言葉を占有して解釈を限定させようという方法は、本当に良い方法だろうか? 個人的にはそう思えない。オブジェクト指向やアジャイルという考え方は、本質的には、物事のInsight(見識)を提供してくれるものであって、何らかの手順を踏めばプロジェクトがうまく行くといったような処方箋を与えるものではないと思う。もしそれらの考え方が役に立たなかったのであれば、それは単に受け手側の問題である。自分(の状況)には合わなかったと思って次をあたるべきだ。しかしながら現実には、以前の記事で書いたように、ある考え方が流行るとその周辺をコンサルタントやコンサルティング会社が商機を求めて集まってくる。そこで「○○を使ったらお宅のプロジェクトもうまく行きますよ」という具合に喧伝する。その中でことごとく裏切られた期待が炎上を引き起こし、Andy Hunt氏や James Shore氏のようなコミュニティを代表する人たちが火消しに走らなければならなくなる。この風景はソフトウェア開発産業に限らず、セールスマンが存在する限り、あらゆるところで繰り返されているのだろう。

さらに思うのは、アジャイルのような手法が難しい原因は、ほとんど政治的な問題に収斂するのではないかということである。その内容が誰かに歪められたから正しいアジャイルが実践されなくなったというよりも、従来的な組織の中でアジャイルになるというその事自体が根本的な矛盾を孕んでいるのではないか。アジャイル以後にリーン・スタートアップが出てきたのも、このことに関係しているのかもしれない。そもそもスタートアップのようなラディカルな環境でないとアジャイルというのは成立しないのではないか。

アジャイルを完全体にするインパクトマッピング

ソフトウェア開発は、開発の根拠となる「必要」をどう捉えるか、その考え方の変遷とともに進化してきたと言えるかもしれない。

例えばウォーターフォール開発では、「必要」は疑いの無いもの、予め決定可能なもの、固定のものとして存在していた。製造業において当たり前のように繰り返されて来た、青写真(設計図)があって、それを実現(施行)するという手法である。その後、ソフトウェア開発において「必要」は予め決定出来ないという問題意識の元、計画・実施を細かく繰り返してフィードバックを得られるようにし、ビジネスと開発で密なコミュニケーションを取りながら本当の「必要」を探る、アジャイルという手法が生み出された。そして更には、計画段階で提案された仮説を、計測に基づく客観的な検証にかけて「必要」の精度を上げようというリーンスタートアップに辿り着いた。

インパクトマッピングは、「必要」の背後にある根拠をマインドマップで図示化することによって、アジャイルやリーンスタートアップが見過ごしていた部分を補完し、ソフトウェア開発を更に一歩先に進めるための技法である。

インパクトマッピングの問題意識は、アジャイルと同じところから出発する。我々が見当違いなものを作ってしまう、あるいは必要とされるスピード感がなかなか得られないのは、開発プロジェクトが役割で分断されているからである。ビジネスはビジネスの言葉を語り、エンジニアはエンジニアリングの言葉を語る。利害も一致しない。このようなコミュニケーションの問題をまず解決すべきであるというのがアジャイルの問題意識であった。そこでアジャイルはフィードバックにフォーカスを当てる。イテレーションによりフィードバックの機会を増やし、決して読まれない重厚なドキュメントを廃して、ユーザーストーリーと動くソフトウェアによるコミュニケーションの効率化を計った。

アジャイルによって色んな役割の人間が同じ船に乗り込み、効率の良いコミュニケーションが可能になったが、それでも最後に大きな問題が残されていた。それは、その船がどこに向かっていて、そして何故そこに向かっているかという航海のビジョンをどのように共有するかという問題である。いくらフィードバックを頻繁に密に実施していても、何のためにその作業をするのかという根拠が、単にステークホルダーやマネジャーがそのように言っているから、というだけでは、エンジニアは依然として下請け作業者のままである。チーム全体で「何故」を共有しなければ、マネジャーはエンジニアから知恵を引き出す事は出来ず、ゴールに最短で辿り着くのは難しくなってしまう。

そこでインパクトマッピングは、「我々はどこに行くのか?」というゴールをマインドマップの中心に配置し、そこから具体的なプロダクトを導出する事によって、作業に根拠を与えて、開発チームが自律的に動けるようにする。

map

上図のように、インパクトマッピングは極めてシンプルである。「ゴール(Why?)」に辿り着くためには、「誰に(Who?)」に働きかけて、「どのような変化(How?)」を生じさせるか? そしてその変化(これを「インパクト」と呼んでいる)を実現させるためには「何(What?)」をすればよいのか(作れば良いのか)? おそらく、ゴールを合理的に説明する手法として、これよりシンプルな方法はないのではないだろうか?

何を作るかの根拠は、いつでも中心のゴールを念頭に考える事が出来るので、作業の優先順位や重要度は、このインパクトマッピングを共有する人間全てがクリアに理解出来るようになる。今まではステークホルダーの頭の中だけにあったものが、マインドマップとして視覚化されるわけである。さらにこのマップは、情報の共有だけでなく、新たな「必要」を発見するための強力なツールとしても機能する。誰に働きかけるべきなのか、何を作るべきなのかは、もうマネジャーだけが考えるべき問題ではない。インパクトマッピングによって、参加者誰もがゴールを念頭にアイデアを出す事が出来るようになった。

以下は、インパクトマッピングの公式サイトで紹介されているオンラインゲーム開発におけるマッピングの例である。中心には「100万プレイヤー」というゴールが掲げられている。

im_example

TDD再考 (4) – TDDはプログラム初心者にとって自然な方法になり得るか?

前回取り上げた、TDDが解決しようとした問題の一覧を眺めていると、それらの問題は Dave Thomas氏が言うところのアジャイルの価値とも共通する部分が多く、TDDというのはアジャイル手法全体のメタファーとなるような、言わばミニアジャイルのような存在と言っても差し支えないように思える。

間違っているかもしれないが、アジャイル以前から長くプログラムを生業としていた人ほど、テストファーストという考え方に抵抗感を抱くのではないだろうか?

TDD、あるいはアジャイルという考え方は、外部からの要件(「機能」)が、結果として、その機能を実現するために必要な「構造」を生み出す、という考え方である。これは、この命題だけに注目する限りは当たり前の事実のようにも思える。しかし、プログラマは、経験を積み重ねる内に同じような構造のパターンに何度も遭遇することになる。そうやって頭の中に有用なコンセプトが蓄積されて行く。それらがイディオムとかデザインパターンなどと呼ばれたりする訳だが、TDDの問題意識は、それらのコンセプトの適用範囲は思ったほど広くなく、そして耐用年数は思ったよりも短く、濫用すれば過剰性能を作り込む罠に落ちるというものであった。

しかし、人間はどうしても知識を貯えてしまうので、解法を先に考えてしまうというバイアスから逃げるのは至難の業である。そしてこれが、経験者ほどテストファーストに抵抗感を抱くのではないかという、推測の根拠である。

要件が構造を生み出す、というロジックはとても反論しづらい。何のためにソフトウェアを作るのかということを考えれば、それが至極当然の流れのように思える。ミニアジャイルであるTDDがプログラマの間でドグマ化してしまうのも頷ける気がする。

では、経験者のバイアスが存在しない初心者のプログラマにとって、TDDは自然な手法になり得るのだろうか?

TDD以前では、プログラムデザインのフォーカスはやはりプロダクトコード側にあって、より良いモジュール、あるいはより良いオブジェクトのデザインは何かということについて、様々なデザイン原則やパターンなどを学習し、デザインの質を高める事によって、プロダクトの保守性や信頼性を担保するという方法が一般的であった。

TDDの出現によって、プログラミングのフォーカスは、プロダクトコードからテストコードに移動する。テストをしやすいようにプロダクトコードをデザインすると、結果的に、モジュール間の疎結合を実現でき、自然によいデザインへと導かれるというわけだ。テストコードを検証すれば要件との齟齬をチェックでき、テスト自体を実行してプロダクトコードの正しさも確認出来るという、まさに一石二鳥・三鳥の方法であった。

実際に筆者も以前、初心者はTDDのやり方から学べば、自然にプログラムデザインも学べるし、管理者視点からは要件との齟齬もチェックしやすく、なかなか良いアプローチではないかと考えていた時期もあった。

しかし、実際には様々な障害があることが分かった。例えば、テスト駆動で小さなステップを踏むことの難しさである。

think of a test that will force you to add the next few lines of production code. This is the hardest part of TDD because the concept of tests driving your code seems backwards, and because it can be difficult to think in small increments. (James Shore: The Art of Agile Development: Test-Driven Development)

TDDでは、API視点からプログラムをデザインすると言っても、実際はインクリメンタルに開発するために、どういうテストを書けばプロダクトコードの変更を最小限に出来るかというアクロバティックなことを考えなければならない。これは、TDDに限らず、vertical slice単位で開発するアジャイルの難しさの中心的な課題といってもよく、とても初心者が太刀打ち出来る問題とは思えない。

もう一つ例を挙げると、James O Coplien氏の指摘にも通じるが、自動テストが(現実的に)カバー出来る範囲というのは思ったより広くない、ということである。

これはつい最近、たまチームで遭遇したばかりの出来事だが、テスト(外部)からは期待通り動作しているように見えるのだが、実はプラスアルファの余計なことをやっていて、関係ないデータを壮大に破壊していたという事例があった。原因は、ライブラリのAPIについての理解が足りなかったという、ごく初歩的な問題である。こういった問題を考えると、テストプログラムで担保出来る信頼性など、特に初心者を対象とした場合、取るに足らないことが分かる。まさに、Coplien氏が言うところの「テストがコードのクオリティを上げる訳ではない、上げるのは開発者自身である」。

TDD再考 (5) – ユニットテストの「ユニット」とは何を指すのか?

TDD再考 (3) – TDDが解決しようとした問題は何か?

DHH氏の「TDD is dead」を受けて、TDDの生みの親である Kent Beck氏が Facebook に投稿した記事。

いささかアイロニカルな反論ではあるが、TDDが解決していた(とBeck氏が考える)問題の一覧が挙げられているので、以下にまとめておく。

  • 過剰性能(Over-engineering)
    • どうやって作り過ぎに対応するか?
    • アジャイルでいう YAGNI
    • 要件を満たす最低限の実装に留める(Just enough)
  • APIフィードバック
    • API設計の妥当性をどのように検証するか?
    • プログラムを利用者視点(API視点)でデザインできる
  • 論理エラー
    • コンパイラでは捕捉出来ないエラーをどうやって発見・防止するか?
  • ドキュメンテーション
    • プログラム(API)の利用方法をどのように伝えるか?
  • 大きな問題
    • 一度に解決しようとするとハマってしまいそうな大きな問題にどう立ち向かうか?
    • 簡単に解ける小さな問題を積み上げていく(小さなステップ)
  • インタフェースと実装の分離
    • どうやってAPIが実装依存にならないようにするか?
  • 問題共有
    • どうやってプログラマ同士の問題共有を正確に行うか?
  • 不安
    • どうやってプログラムが期待通りに動作している事を確認するか?

このようにして、TDDが解決しようとしていた問題点を並べてみると、問題そのものの妥当性にはそれほど異論はないように思えるが、その解決策については必ずしもTDDに限る必要はないようにも思える。前回の記事に書いたように同じ価値を実現できるなら、必ずしも誰もが同じ方法をとる必要はない。

テストを先に書かなくても、一つ一つのステップを小さくする事は出来るし、小刻みな Test-Last アプローチでも、API視点でプロダクトコードを検証する事は出来る。エラーの抑止、リグレッションテスト、あるいはドキュメンテーションという観点から言えば、テストをいつ書くかは問題にならないはずである。

あるいは、DHH氏やJames O Coplien氏が指摘しているように、ユニットテストにフォーカスし過ぎる事は、より重要で本質的な問題、つまりビジネス価値の軽視につながる可能性もある。これは、TDDの手法そのものではなく、その問題設定に対する疑義である。

TDD再考 (4) – TDDはプログラム初心者にとって自然な方法になり得るか?

アジャイルにとって不変なのは価値であって、方法論は状況に応じて変化していく

以前の記事で少し触れた「Agile Is Dead (Long Live Agility)」について、InfoQ が Dave Thomas氏本人に行ったインタビュー。

2001年、ユタ州のスノーバードに集まった、Kent Beck氏を始めとするソフトウェア開発の思想的リーダー17名。そこで自分たちの思想の共通点は何なのかという事を議論し、その成果を「アジャイルソフトウェア開発宣言」として世に公表したとき、その宣言がここまで大きく世の中を変える事になるとは全く想像していなかったと、Dave Thomas氏は語る。

agile

この宣言が発表される以前から、Kent Beck氏らによるエクストリーム・プログラミング(XP)や、Martin Fowler氏の記事「The New Methodology」など、開発者コミュニティの中では、アジャイルのような思想を受け入れる素地が出来上がっていた。

このように最初は開発者による日々の実践だったものが、成功したスタートアップの秘訣として紹介されるなどして、徐々に開発者以外の注目を集めて行く。

この過程を、Thomas氏は面白い表現で説明している。組織の管理者がアジャイルの評判を聞いて、それを自分の組織にも導入しようと号令をかける。すると、血に引き寄せられるサメのごとく、その周りをコンサルタントやコンサルティング会社が旋回し始める…

当然の事ながら、コンサルタントのアドバイスは管理者受けが良いように最適化されるため、その段階で個人の主体性を大事にするアジャイルの価値は失われてしまった。

Thomas氏曰く、「我々が提案する〜をやればアジャイル開発を実現できます」というコンサルタントは間違っている。理想的なコンサルタントはこのように言う、

「あなた達にとって何が最適か、私には分かりませんし、あなた達自身にも分からないでしょう。でも、とりあえずどこからかスタートすることは出来ます。まずは適当なプラクティスを選んで一ヶ月間実践してみるところから始めてみましょう。その後、何がうまく行って、何がうまく行かなかったか評価をします。そして、その評価に基づいてやり方を変えて行きます。おそらく最初に採用するプラクティスは、XPやスクラムの本を参考にするでしょう。でも、今から半年後、あなた達のやっていることは、どの有名な手法にも当てはまらなくなっています。何故なら、自分たちに最適な方法を自分たちで編み出す事になるからです。やり方はずっと変わって行きます。変化を楽しみましょう。」

アジャイルの導入として、これ以上分かりやすい説明はないのではなかろうかと、個人的には思う。

アジャイルで不変なのは「アジャイルソフトウェア開発宣言」にも謳われているその「価値」であって、方法論はチームによって、あるいはチームが置かれている状況によって変化する。

ここが、アジャイル以前に存在したウォーターフォール手法などとの決定的な違いである。そもそも同列に比較されるものではない。価値原則に照らし合わせれば、アジャイルを方法論として売り込む言説に対しては常に疑ってかからなければならない。逆に言えば「〜を実践してないなら、お前らはアジャイルじゃない」ということも言えないはずだ。

Thomas氏は、アジャイル実践手法の基礎となる、メタプラクティスなるものを提案している。それは、

  • 自分たちの現在地を把握する
  • ゴールに向けて小さなステップを踏み出す
  • そのステップによって起こった事を評価し学習する
  • 繰り返す

によって構成されるプロセスだ。ここに具体的なプラクティスは何も含まれていない。自分たちのアジリティーを向上させたいのなら、このプロセスをあらゆるレベル(関数の命名レベルの細かさから、新しいビジネスの計画に至るまで)に適用出来るように、自分たちでプラクティスを編み出して行かなければならない。

改めて考えてみると、管理者というのは常に「状況をコントロールしなければならない」というプレッシャーを受け続けている。計画出来ずに「今はまだ何も分かりません」では、ステークホルダーを説得出来ないからだ。そのような管理者によって、アジャイルは流行のバズワードとしてステークホルダー向けのプレゼンテーションに利用されてきたのかもしれない。しかし、アジャイルの考え方というのは、そのような(事前に青写真を書かないといけないという)ビジネスのあり方自体に疑問を投げかけるものだ。

TDD再考 (2) – 何故、ほとんどのユニットテストは無駄なのか?

TDD is dead」の最後で紹介されている、TDD否定派として有名な James O Coplien氏の論文。なかなか読み応えがある。

ユニットテストには基本的に価値がないので、よりビジネス価値を反映する粒度の大きなテスト(functional tests, integration tests, system testsなど)に軸足を移すべきである、というのがこの論文の論旨。

何故ユニットテストに価値が無いのかという部分の説明についてはなかなか説得力がある。論点を挙げてみると、

  • TDDの実践者が言及するテストカバレッジ100%には意味が無い
  • バグを取り除く最大の機会はテスト以外のところにある
  • ユニットテストにビジネス価値はほとんどない
  • TDDはプログラムデザインに害を及ぼす
  • ユニットテストの維持コストは馬鹿にならない
  • テストがコードのクオリティを上げる訳ではない、上げるのは開発者自身である

一つ一つの論点を追いかけてみよう。

テストカバレッジ100%には意味が無い

Coplien氏によれば、一般に言われるカバレッジ100%というのは、計算理論の見地から言えばまったくのナンセンスであり、本当の意味で100%を目指すのならば、到達可能なパスの全パターンと、その時にアクセス可能なデータの全パターン、それら全部の組み合わせを検証しなければならないとのこと。そうでなければ、正式にそのプログラムが「正しい」とは言えないのだそうだ。

TDDのメリットとしては、もちろんプログラムの信頼性向上も謳われる事が多いが、いわゆる品質保証としてのテストとは区別される事がほとんどで、TDDとしてのフォーカスはプログラムデザインに当てられる事が多いように思う。なので、この批判はTDDに対する攻撃としてはそれほど有効ではないように思える。

一方、ユニットテストを品質保証の根拠として捉える向きには、計算理論的にコードの正しさを証明する事は非現実的であり、ほとんどのケースでは恣意的な基準によって判定されていることを明らかにした、ということになるだろうか。しかし、果たして未だにそのような勢力(ユニットテストを品質保証の根拠として捉える向き)が存在するんだろうか…?

それとは別にして、プログラマの仕事をメトリクスで計ろうとする事の落とし穴については注意深く考えた方がよいだろう。筆者自身も過去のプロジェクトで、テストプログラムを書いた経験のないプログラマが、カバレッジを基準値まで上げるために、ただプログラムを実行するだけで Assertion が全くないようなテストプログラムを書いているのを目撃した事がある。

バグを取り除く最大の機会はテスト以外のところにある

これはウォーターフォール時代から言われていた事だが、プログラムの品質にもっとも重大な影響を及ぼすのは、要求・ドメインの分析結果を設計に落とし込むタイミングである。

その前提の上で、ユニットテストという高コストな手法でバグを潰すのは、果たして費用対効果的にどうなんだろうかという話である。

TDDも設計手法ではあるが、Coplien氏は他の論点でも述べているように、TDDはプログラムデザインに害を及ぼすと主張している。なので、プログラムの信頼性を向上させる手法として、TDDに従来の設計手法以上の価値があるとは認めていない。「コードのクオリティ向上に寄与するのはテストではなく、結局のところそれは開発者自身である」というのが、彼の基本的な立場である。

ユニットテストにビジネス価値はほとんどない

おそらくこれが一番重要な論点だと思われる。Coplien氏によれば、ビジネス要件から導出されたテストだけがビジネス価値を持つ。ほとんどのユニットテストは、ビジネス価値とはあまり関係のない開発者の独断によって設計されている。

もちろんユニットテストにビジネス価値と直結する部分が全くないとは言い切れない。例えば、キーとなるアルゴリズムを実装している部分などだ。しかし、基本的にビジネス価値はより粒度の高いテストで表現すべきである、というのがCoplien氏の主張である。

ユニットテストの価値を計る方法として、もしそのテストが失敗したら、どのようなビジネス価値を毀損することになるかを考える。もし、よく分からない、あるいは明確でない場合、そのテストのビジネス価値はほとんどゼロだということになる。価値が無いのにも関わらず、そのテストを維持管理するのにはコストがかかる。であれば、そのようなテストは捨てた方が得策である。

TDDはプログラムデザインに害を及ぼす

これはDHH氏も指摘していたが、TDDがプログラムデザインを改善するという客観的な根拠や事例はなく、それを調査した研究によればむしろ逆の結果が出ているようだ。

TDDが及ぼす悪影響として、プログラムを過剰に細分化してしまうため、ドメインとプログラムで表現の粒度が釣り合わなくなり、プログラムが理解しづらくなる事、ユニットレベルでのビジネス価値が小さくなってしまうこと、などが挙げられている。

しかし、仮にCoplien氏が言うように「テストがコードのクオリティを上げる訳ではない、上げるのは開発者自身である」のであれば、TDDがデザインに与える影響を客観的に計る事自体が無理筋であるように感じられるのだが、どうだろうか。

ユニットテストの維持コストは馬鹿にならない

この問題はTDD支持者の中でも多くの人が認識するところだと思う。

テストコードもプロダクトコードと同様(あるいはそれ以上に)、デザインとメンテナンスにコストがかかる。

特にテストコードの設計においては、プロダクトコードとは異なる方法論を採用する必要があり、これが想像以上に難しい。ただテストコードがあるというだけで良しとしているプロジェクトも多いが、テストの品質がプロジェクトに与える影響は想像以上に大きい。

プロダクトコードの設計を改善するためには、より良いテストの設計手法を学習しなければならないが、そのためには前提としてプロダクトコードの設計手法に精通する必要がある。プロダクトコードの設計手法に精通しているのなら、何故設計手法としてのTDDにわざわざ手を出さなければならないのかという矛盾がある。

プロダクトコードの coupling(結合度)とcohesion(凝集度)を改善するために、テストを書くというのがTDDであるが、テストコードがプロダクトコードに強く依存してしまう(高結合度)という問題がある。プロダクトコードに大きな修正が入った場合の、テストコードに及ぼす影響は甚大であり、粒度が小さく数の多いユニットテストのメンテナンスコストは想像以上に大きくなる。

テストがコードのクオリティを上げる訳ではない、上げるのは開発者自身である

ユニットテスト・TDD批判のベースにある考え方であり、これはある種の正論として多くの人が賛成出来る部分では無いだろうか。

Dave Thomas氏の「Agile Is Dead」宣言にも見られるように、いわゆる銀の弾丸的な存在としてアジャイルやTDDがあるように喧伝されるために、このような違和感を表明しておきたいというのは多分にあるのではないかと思う。

Coplien氏は、件の記事の締めくくりに、コンピュータ資源が豊富になって何でも簡単に試したりやり直したり出来るようになると、自分の頭で考えなくなってしまう(ツールのアウトプットを盲信してしまう)とう話をしている。

参考資料

James O Coplien氏のTDD批判については、氏に直接話を聞いたという安井力氏のブログとFacebook上のやり取りが大変に興味深かった:

TDD再考 (3) – TDDが解決しようとした問題は何か?

TDD再考 (1) – テストファーストとユニットテストへの死刑宣告

いかにも物議を醸しそうな(そして実際に醸しまくった)この記事を、Ruby on Rails の作者である David Heinemeier Hansson (DHH) 氏が発表したのが去年の4月、ということはあれから既に一年以上が経過している訳で、今更感が若干漂うところではあるが、このシリーズ「TDD再考」では、このDHH氏の記事に端を発して行われた様々な主張や議論を振り返りながら、アジャイル以後のプログラムデザインについて再考してみたいと思う。

件の記事でDHH氏は、「TDDは死んだ」と高らかに宣言しているわけだが、まず始めに気をつけなければならないのは、DHH氏が言うところのTDDというものが、かなり極端な例を念頭に入れて想定されているという事である。それは彼が「fundamentalism(原理主義)」や「fanatical(狂信的)」のような強い言葉を使っている事からも伺われる。

彼の批判を紐解くとポイントは二つある。一つはテストファーストこそがプログラミングのあるべき姿であり、プログラムのクオリティはそれをいかに正しく実践しているかによって査定されるという考え方が蔓延した結果、実際にそれが有効かどうかとは関係なく、それを実践しているかどうかで技術者の値踏みが行われるようなってしまったということ(ドグマ化)。そして、二つ目は、厳密な意味でのユニットテストでTDDを実施してプログラムデザインを導出すると、必要以上の細分化(これは James Coplien氏による指摘)と間接化(大量のMockオブジェクト)によって、過剰な複雑化を招くという事である。

そして、テストファーストという実践は捨てて、ユニットテストよりもシステムテストの方に重心を移すべきだと提案している。ユニットテストの対抗として挙げられているのが、データベースアクセスも含む形で Rails の Active Record をテストする例や、Webブラウザ経由のテストを自動化するフレームワーク「Capybara」などである。

実際にアジャイルやTDDの実践者の話を思い返しても、彼らがDHH氏が言うところの厳密な意味でのユニットテスト(依存関係は全てMockにして、対象となるユニットだけをテスト対象にする)にこだわっている印象はない。むしろ、DHH氏と同様、過剰なMockの導入は無駄が多いし、本来テストすべき箇所をテスト出来ないという問題意識を持っている人が多いように思う。Mockにこだわるのは厳密な Outside-in デザインにこだわる Behavior Driven Development (BDD) の一派ではないだろうか。実際にオリジナルTDD派とBDD派にはそのような対立も散見される。

TDDがドグマ化しているという指摘が、この記事の主題であり、多くの人の興味と共感を得るきっかけとなった部分だと思われるが、仮にそれが正しいとして、何故このようなことが起きたと考えられるだろうか? 

まず、TDDが提案した、プログラムデザインとテストを一体化するという考え方のインパクトが大きかった事が挙げられるだろう。ここにはドグマ化の要因となる二つの要素があったと考えられる。一つは、DHH氏も指摘しているように、これまでのソフトウェア開発の中で主要な不作為の一つだと見られていた、テストを書かない・しないということへの処方箋だったこと。専門家はこういった不作為を特に厳しく糾弾する傾向がある。そして、更に重要だと思われるもう一つの要因は、それが「要求駆動」のデザイン手法だったという事である。

テストをやらないというのは、将来起こりえる問題への不作為であるが、ここを過剰に追求するのはアジャイルとは矛盾すると考える事もできる。以前取り上げた記事の事例では、リーンスタートアップ的な実験フェーズにおいてテストを省略するという話が紹介されていた。

TDDが要求駆動であることの意味は大きく、それはアジャイルにとっても主題になるが故に、TDDがアジャイル実践の基礎だと捉えられている事が多い。そして要求駆動というのは、ユーザー中心設計や顧客中心主義のような、今の時代にとっての最大のドグマと言ってよい領域に属する。そして、これらの逆算的思考というのは本質的に反論がしづらい。

TDD再考 (2) – 何故、ほとんどのユニットテストは無駄なのか?

我々は何のためにソフトウェアを開発するのか?

達人プログラマー』の著者であり、アジャイルソフトウェア開発宣言の発起人の一人でもある Dave Thomas氏によって書かれたブログ記事「Agile Is Dead (Long Live Agility)」が、アジャイル界隈に少なからぬ波紋を投げかけたのは記憶に新しい。

その記事で彼は、アジャイルという言葉が、その人気ゆえに、マーケティングの道具にされて有名無実なものになっていることを嘆いていた。

同じくアジャイルソフトウェア開発宣言の発起人である Ron Jeffries氏が年初に出した「The Nature of Software Development」という本は、もしかしたらこの流れに何らかの影響を受けているのかもしれない。

この本でJeffries氏は、いわゆるアジャイルと呼ばれるものの本質について、アジャイルという語やその周辺の専門用語を極力使わずに、おそらく技術者でなくても理解出来るような平易な言葉で解説をしている。150ページほどのコンパクトな内容にたくさんの手書きイラストと専門用語を排した説明。2015年の今、アジャイルの(再)入門として読むには最適な書籍だ。

Dave Thomas氏の記事もそうだが、アジャイルが生まれてから十年以上が経過した今、アジャイルってそもそも何だ? というところに一度立ち返ろうという流れが出てきているように見える。

本来、アジャイルというものは、自分が置かれた状況に合わせてどのように行動したら良いか、ということを考える上での原則を与えるものであって、複雑な手順やツールを利用したり、専門用語に精通したり、ましてやスクラムの資格などとは本質的に関係のないもののはずである。

Jeffries氏は、我々は何のためにソフトウェアを開発するのか? それは「価値」を提供するためである、という当たり前(だけど忘れがちな)事実からスタートして、その効率を最大化するための基礎となる要素「Guiding」「Organizing」「Building」「Slicing」「Quarity」について説明する。

この本の中で個人的に面白いと思ったのは、「価値とは何か」という問いに踏み込んでいるところである。

これまでのアジャイルでは、価値の決定は顧客、あるいはそれに準ずる利害関係者に託されていた。開発の透明性を高めて判断材料を増やし、イテレーション開発で判断機会を頻繁に設けることで、より高い価値を目指す。

アジャイルの考え方を起業に応用したリーンスタートアップでは、さらに踏み込んで、計測可能な価値というものを考える。価値仮説を立てて、実験と計測を繰り返す事で価値の最大化を目指す。

そして、「The Nature of Software Development」では、基本的に価値は計測可能なものではなく「Value is what you want(価値とはあなたが欲しいもの)」だと定義する。一見、何も説明していないようにも読めるが、Jeffries氏は価値というものの多様性を説く。我々は色んなものに価値を認める。例えば「情報」だったり「人命」「資本」「スピード」「幸福」「創造性」などなど、あらゆるものに。

つまり、「価値とはあなたが欲しいもの」の意味は、価値、あるいは何が役に立つかという事は、その価値を受ける人とその人が置かれた状況・文脈に依存するのであって、その状況ごとに自分の頭で考える他はない、ということになる。

DevOpsの起源とOpsを巡る対立

たまチームとして技術ブログを書くようになって、ある日ふと気付いたのだが、そのメインのトピックの一つであるDevOpsという言葉の起源については深く追求しないまま今日に至ってしまっていた。開発と運用が一緒になるとか、あるいはインフラの自動化ぐらいのぼんやりとしたイメージはあったのだが、その運動を起こした人たちとその意図、歴史などについては無頓着なままであった。そこで今回はこの辺の事情について調査を行い、今の知識と照らし合わせながら現状の考えをまとめておきたい。

DevOpsの起源

まず、DevOpsの起源と歴史については以下のサイトに簡単にまとまっている。

Agile 2008 conference

これらの記事によれば、DevOpsという言葉が生まれる一年ほど前、2008年にカナダのトロントで開催された Agile 2008 conference にて、ベルギーのITコンサルタントであるPatrick Debois氏が「Agile Infrastructure & OperationsPDFのプレゼン資料)」というプレゼンテーションを行い、これが後のDevOpsムーブメントの萌芽となったらしい。

このプレゼンテーションで提示されている文脈としては、まず「開発と運用の分離」がある。「What is DevOps?」という資料にも歴史的経緯が解説されているが、元々は分かれていなかった開発(Development)と運用(Operations)という役割が、コンピュータの進歩と共に、次第にそれらを担う別々の専門家が生まれて、最終的には職能として、組織の中では別々の部門に配属される事が多くなったという流れである。

そして、発表が行われたカンファレンスのテーマである「アジャイル開発」も重要な文脈である。このプレゼンテーションのために実施されたアンケートでは、(科学的なサーベイではないと断り書きがあるものの)開発者はアジャイルという方法論に慣れ親しんでいるが、それ以外の部署、運用やインフラ、営業などになると、いわゆるアジリティーはかなり低くなるという結果が出ている。

そして、発表者のPatrick Debois氏は、開発と運用の両方で豊富な経験を持ち、両者の問題をよく理解している、いわば開発と運用のブリッジとなるような人である。その彼がプレゼンテーションで紹介しているのが、データセンターの移行というインフラの仕事をどうやってアジャイル(スクラム)でやるかという事例で、アプリケーションや運用チームがProduct Ownerになるという大変に興味深いものだ。

Velocity 2009 – O’Reilly Conferences

Patrick Debois氏の発表から約一年後、カリフォルニア州サンノゼで開催されたVelocity 2009というイベントで、Flickrのエンジニア(John Allspaw, Paul Hammond)によって発表された「10+ Deploys per Day: Dev and Ops Cooperation at Flickr」というプレゼンテーションがDevOpsという言葉を生み出すきっかけとなった。

このO’Reilly主催のVelocityというカンファレンスのことは知らなかったのだが、インフラ・運用(Web Performance & Operations)がテーマになっていて、参加者もどちらかと言えば開発者より運用系の人が多いようである。このカンファレンスの存在自体が「開発と運用の分離」という事情を象徴するようであるが、そこからDevOpsという言葉が生まれたというのはなかなか興味深い事実である。

さて、件のプレゼンテーションの内容はと言えば、開発者と運用担当者が共通の目的に向かって手を携える事で、一日に10回以上デプロイするような高速な開発を実現できるというものである。まさに Wikipedia などに書かれているようなDevOpsの定義につながる。そして、そこで指摘されていたのは、職能によって分けられてしまった開発者と運用担当者の利害が衝突するようになり、いわゆるセクショナリズムが生じて、いつまでも対立を続けるようになった結果、組織全体が目指すべき本来の目的を見失っているということであった。

この問題は、開発・運用だけにかぎらず、例えば、営業・開発の関係でも、職能で部署が分けられている場合は不可避的に生じる問題である。何か問題が発生した場合に、セクショナリズムが存在すると、その問題を「我々の問題」として認識出来なくなる。そして責任転嫁(finger-pointing)や責任を回避するような保守的な言動が横行するようになる。これは普通の会社の中で働いているたまチーム自身もまさに経験していることでもある。

そして、このプレゼンテーションをベルギーからストリーミングで視聴していたPatrick Debois氏が、「Devopsdays」というイベントを開く事を思い立ち、それが本格的なDevOpsムーブメントの始まりとなった。

devops

NoOps炎上事件

さて、以上の流れでDevOpsというムーブメントが生まれるまでの経緯は大体把握する事が出来たが、その後の2011年から2012年にかけて「NoOps炎上事件」とでも呼ぶべき興味深い事件が起こっているのでここで紹介しておきたい。

事の発端となったのは、2011年にマサチューセッツ州ケンブリッジに本拠地を置くフォレスター・リサーチという調査会社の出した「Augment DevOps With NoOps」というレポートである。

このレポートの主張は、クラウド環境の進歩により自動化が促進されて、将来的に DevOps は NoOps となる、つまり運用というものは必要なくなるというものである。開発者の立場で考えると、昨今のPaaSの隆盛などを見るに、普通に納得出来そうな将来予測ではある。しかしながら、この NoOps という言葉が、運用だけでなく、運用を担ってきた人間さえも否定するように響き、DevOpsという言葉を生み出すきっかけを作ったコミュニティに少なからぬ波紋を引き起こす事となった。

象徴的なのが、DevOpsでは頻繁にその名前が言及される Netflix という会社に当時勤めていたAdrian Cockcroft氏の NoOps に関する記事「Ops, DevOps and PaaS (NoOps) at Netflix」と、それに対するJohn Allspaw氏の反論である。

John Allspaw氏の反論を全部読み通すのはなかなかに骨が折れるが、その長さからして運用のコミュニティを代表する彼の怒りが伝わってくるようだった。しかし、そもそもここで問題にされている事は何なのか?

それは「運用」とは一体何なのか? ということである。Allspaw氏によれば、Cockcroft氏が言うところの「運用」とは、90年代に存在した古い存在であり、相互不理解が原因で開発者にとっての障害かつフラストレーションの原因となっていたが、その反省によってまさに DevOps が生み出されたのだと、そして現代の我々運用コミュニティの人間はとっくにそちらにシフトしているのだと、今更お前は何を言っているんだと、Opsを無くして悦に浸っているようだけど、「運用」という専門領域あるいは責任は変わらずそこにあるし、全然 NoOps になってないじゃないかと、そのような言葉の誤解を指摘している訳である。

この議論は果たして有益だろうか? Allspaw氏の反論は、Opsの誤用を諭しているようで、その実は、彼の所属するコミュニティが信奉しているOpsの定義を主張しているだけのようにも見える。つまり、彼はOpsコミュニティの利害を代表して抗議する事によって、DevOpsが避けようとしていた落とし穴に再び陥っているかもしれないのである。

専門用語の定義問題というのは、その専門性によって縄張り意識を生み出し、セクショナリズムにつながる危険性を孕んでいる。

物理から仮想へ

この言葉を巡る炎上問題から学べる事は何だろうか? それはおそらくDevとOpsという区別自体がナンセンスな時代になったということではないだろうか。その区別が引き起こしていた障害を解消するために DevOps が発明された訳だが、依然として言葉上では区別していたために「NoOps炎上事件」のような対立が起きた。

DevOpsの背景にあった重大な変化は、あらゆるものがソフトウェア化しているということである。分かりやすい例で言えば、仮想化技術によって実現されたクラウドやVPSのような、物理リソースから論理リソースへの移行である。その他、元々はOpsの領域だった、OSのインストールやコンフィグレーション、アプリケーションのデプロイなどの操作もコード化されるようになった。それぞれ、Infrastructure as Code, Operations as Code と呼ばれるものである。

そのようなソフトウェア化した世界にとって、Infrastructure や Operations の区別というのはそれほど重要ではなくなる。あるいは別のレイヤーの話になる。例えば、Microservices概念の出現によって、一つのサーバー(Service)と、プログラム上の一つのモジュールとの概念的な違いが無くなっていくように。

物理から仮想へと言っても、物理的なハードウェアが無くなる事はあり得ない。もしOpsという言葉が有効に機能する領域があるとすれば、それは物理的装置に関連する領域ではないだろうか。言葉というのは視点の問題である。Infrastructure も Operations も、コード化してソフトウェアとして扱えるようなれば、ソフトウェア開発の技術がそこに応用出来る。そこで重要なのはDevとOpsの区別ではなくて、物理なのか仮想なのかという問題である。

ドキュメンテーションを成功させるには

ドキュメンテーションをうまく機能させるのは本当に難しい。

たまチームの開発は、同じフロアにいるマーケティングチームからの要求に従って行われている。ミーティングなどで要件のヒアリングを行い、それを簡単なタスクの箇条書きに落とし込む。PDCAサイクルを一週間(場合によっては二週間)ごとに行うイテレーション開発を採用しているので、全ての要件を一度に明らかにせず、次のイテレーションのタスクが埋まる程度にヒアリングを行う。ミーティングではイテレーションの成果を踏まえて次の要件やタスクを考えるので、想定外の事象が発生しても早い段階で軌道修正を行える(ここに落とし穴があったのだが、これはまた後日)。

いわゆるアジャイル的な開発である。進捗は可視化されていて、軌道修正もしやすく、見当違いなものを作ってしまうリスクも抑えられるので、なかなか効果的な開発方法に思えるが一つ大きな問題があった。それは、きちんとしたドキュメントを残すタイミングがなく、ほとんど全てが現物主義になってしまうことだ。

そもそもアジャイルという手法に現物主義の傾向があるとも言える。動くソフトウェアとクリーンなコードが何よりも現状を雄弁に語るという考え方だ。

しかし、それはある程度小規模な開発であれば当てはまるかもしれないが、一年以上に渡って開発し続ける複雑なシステムではなかなか難しい状況になる。たとえ動くソフトウェアがあったとしても全貌を把握することは難しくなるし、全てのコードをクリーンに保つことも現実的には難しい。

ある日、こういうことがあった。開発がスタートしてから一年半が経過し、システムの機能も大分増えてきた頃だ。

マーケティング担当者「そう言えば、この機能って XXX のような仕様だったと思うんですけど。」

開発者「え、そうでしたっけ。私は YYY と聞いたように記憶してるんですが。」

マーケティング担当者「うーん、それは困るな。お客さんになんと説明すればよいのか。。。」

もの凄くありがちな光景である。イテレーションごとに現物を確認していても、同じ機能を何度も修正している間に、マーケティング担当者の想定と現物がズレてきてしまったのだ。

その後もシステムはどんどん複雑化することが予想されたので、たまチームとしても何か対策を打たざるを得なくなった。仕様書を書こうということになったのだが、常に変化し続けるシステムの仕様書を維持管理することの難しさは重々承知している。そこで、どのようにドキュメントを管理したよいかを入念に検討して以下の指針を作った。

  • 分かりやすさ: XXXを知らない人でもシステムの目的・機能要件が理解できること
  • 網羅性: 要件が一通りカバーできていること
  • 探しやすさ: 必要な情報をすぐに見つけられること
  • ステータス管理: 要件ごとに「実装待ち」「実装済み」「検証済み」のようなステータスを管理すること
  • 変更容易性: 文書の内容が常にup-to-dateになるように、変更のコストを最小化すること
  • テスト仕様書: この文書を見ながらシステムを操作して要件をテストできること

今回のお題である「Lean Documentation」に書かれている指針と大体同じである。Lean Documentationで紹介されている「良いドキュメンテーションのためのルール」は以下の通り:

  • 素早く書けて更新出来るようにする。現状を反映してない情報は、まったく情報が存在しないことより有害である。
  • 簡単に正しい回答を得られること。必要な情報が見つけづらければ誰もそれを利用しなくなる。
  • ドキュメンテーションが対話を置き換えるわけではない。「プロセスやツールよりも、個人や対話に重きを置くべきである(Manifesto for Agile Software Development より)」。

変更容易性はかなり重要な要件で、これを考えるとWordやExcelなどで仕様書を管理することの問題がよく分かると思う。プロジェクトメンバー全員で情報を共有しつつ、かつ変更も容易に行えるとなると、データベース的な仕組みがどうしても必要になる。

昨今の開発プロジェクトだとWikiで仕様を管理することも多いのではないかと思う。しかしWikiでも、まだ変更容易性に若干の不満があり、ステータス管理やフィードバックなどの扱いに難がある。そこで、たまチームではチケットシステム(具体的には GitHub の Issues)を試してみることにした。

仕様を独立した小さな単位に分割してチケットとして管理すれば、その単位でステータスを管理したり、フィードバックをチケットのコメントとして行えるようになる。変更についても、そのチケット自体を修正したり、破棄したり、また新しく作ったりと、より柔軟に行える。どのような機能が修正されたかも把握しやすい。

全体の構成について、Lean Documentation では「Structure it like Google Earth(グーグルアースのように構造化せよ)」というプラクティスが紹介されている。全体像から詳細に向かって徐々にズームインしていく仕組みがあれば、情報が格段に見つけやすくなるというわけだ。たまチームでは、細かい単位であるチケットだけだと全体像が見えないので、Wikiページに概要とチケットへのインデックスを作った。

「さて、これで完璧なドキュメントが出来上がったぞ(ドヤァ)」

数ヶ月後、苦労して作ったドキュメントは誰にも読まれなくなっていた。読まれないので更新もされない。ドキュメントは徐々に現実からズレていく。

つまり、大失敗である。

原因は一体何だったのだろうか? Lean Documentation にあるように、ドキュメントがマーケティング担当者のニーズに沿った構成や内容になっていなかったのだろうか(「Practice 1 – ドキュメントの利用者とその目的を特定せよ」)?

マーケティング担当者曰く「GitHubを見ることが習慣化していないというのと、同じフロアにいるので、つい直接尋ねてしまう。」

ドキュメンテーションを成功させるために、最も重要でかつ最低限必要なことは「(継続的に)読まれること」である。

このことは文書そのものをどう書くかということよりも遥かに重要である。文書が適切に書かれるから読まれるのではなくて、読まれるから適切な形に変わっていく。読まれなければその文書は死んだも同然である。

ドキュメンテーションというのは固定化されたものではない。コミュニケーションの記録である。口頭の対話は記録されないが、ドキュメンテーションという対話は記録され、かつ構造化される。かなり効率は落ちるが、その記録が残ることの価値はかなり大きい。

ここで重要なのは、「読まれること」は「読ませること」ではないということだ。「GitHubを見ることが習慣化していない」という人に対して「じゃあ、習慣化して下さい」と言うのは間違っている。ドキュメンテーションを行うものは、その文書を読んでもらうためのあらゆる努力をしなければならない。それには、Web上にブログを開設して読者を集めることと同様の難しさがある。

仕様を表現するための一手法である「Specification by Example」も、手法としては素晴らしいと思う。Living document のコンセプトも良いし、Given-When-Then 形式の Acceptance Test Scenario(あるいは、Acceptance Criteria)も分かりやすく書きやすい。実際に、たまチームの一つのプロジェクトでは英語話者と日本語話者が効率的にコミュニケーションするためにこのフォーマットを採用している。しかしこれでも「読まれること」とは、全く別次元の話なのだ。

ビジネスパーソンとエンジニアは、そもそも異なる言語で会話をしている。アジャイルコミュニティではドキュメントの限界を理解しつつも、テストプログラムに通じる形式的な文書を、いかにビジネスパーソンに読ませる(書かせる)かということに苦心してきた。しかしこの試みも Fit の失敗 に代表されるように、うまく行っているとは言えないように見える。ビジネスパーソンとエンジニア、両者の想定があまりに違うのである。

書いたものを読んでもらうというのは、人を動かすということである。Stackoverflow の共同創業者で、Joel on Software で有名な Joel Spolsky 氏は、編著「The Best Software Writing I」の中で「ストーリー」の重要性を説いている(「”Show, don’t tell” rule」)。いくら内容が正しくとも、ストーリーなき文章を長々と読めるわけがないというわけだ。

ストーリーなんて仕様書のような形式的な文書とは関係がないと思うだろうか? アジャイル開発で要件の単位となる「ユーザーストーリー」は、形式的表現に慣れているエンジニアからビジネスパーソンに歩み寄った結果として生み出されたものだ。ドキュメンテーションとはコミュニケーションであり、その質にはコミュニケーション能力がそのまま反映される。だからこそプログラミングそのものよりも難しいと言っても過言ではないように思える。