抽象化

問題を解決するには、まず問題を把握しなくてはなりません。 しかし一歩ずつ進めるうえでの最初の一歩から悩むこともあります。 たくさんの要素を同時に考えないといけなかったり、多くの事柄が複雑に関連していて、小さな部分に切り出すのが難しいことがあります。 分割統治するための分割が、難しいわけです。 いちどに把握して検討できるものの数には限度があって、それ以上になるとまとめて考えることができなくなり、見落としや考慮漏れが発生します。

例として、週末にパーティーを開くために買い物をすることになったと考えてみましょう。 ほしいものを考えながら買い物リストを作っていたら、ものすごく長くなってしまいました。 全部で100個はありそうです。 近所のスーパーで買えるものもあれば、駅前の商店街で買いたいもの、デパートまで行かないといけないものもあります。 これを整理しないで買い物に出かけたら、スーパーと商店街を何回も往復したり、せっかくデパートまで行っても買い忘れをしたりしそうです。

そこで、買い物リストを分割することにします。 どこで買うかによって、リストを3つに分けます。 これで、スーパーの買い物リスト、商店街の買い物リスト、デパートの買い物リストの3つのリストができました。 これで買い物を無駄なく、忘れ物もなくできそうです。

いまの例では、100個以上の項目がある「買い物リスト」を、「どこで買うか」という観点で整理して3つの買い物リストにしました。 整理する前の問題は「リストを見ながらどこで買うか考えながら買い物をして回る」というもので、移動と買い物を同時に考える必要がありました。 100個以上も頭の中だけで整理していたら、移動の無駄が起きたり、買い忘れが起きてしまいます。 整理して3つの買い物リストに分けたおかげで、今度は問題も分割できました。 まず「買い物する場所に行く」という問題、そして「その場所で買い物をする」という問題の2つです。

「買い物リスト」を「どこで買うか」という観点で見直す、これが抽象化の一例です。 大きく複雑なひとかたまりの問題を、観点によって整理し、簡単に解けるいくつかの問題に分割するのです。 細かい点を見ないようにしたり、差異を無視して同じものと扱ったり、似た点があるものをグループ化したりするのが、抽象化です。

「抽象的」は「具体的」の反対の意味です。 抽象化とは、具体的の反対にすることなので、必ず情報が失われます。 このことから「抽象」は「捨象」とも言います。 情報を捨てるという意味です。 いま着目したい、重要視したいところだけを取り出し、それ以外の情報は無視して考える。 それが抽象化です。

例題:
  • 最寄り駅から家までの地図を書いてください。書き終わったら地図を観察して、どんな情報が載っているか、どんな情報は捨てたのか書き出してください。なぜその情報を選んだのか、考えてみてください。
  • 会社で泊まりがけの合宿をすることになり、宿泊場所の候補を探してほしいと頼まれてしまいました。いくつかの宿泊施設を選んで、それぞれの特徴や情報を整理して一覧表にしないといけません。どういう情報を載せますか?
    • 家族や仲間との遊びの旅行だったら、載せる情報は変わりますか?それはなぜですか?
  • ブラウザで適当なWebページを開いてください。そのページの構成や内容について、抽象化して説明してください。

抽象化のレベル

整理した3つのリストを、3枚のメモ用紙に分けて書いて、机の上に置いてみましょう。 ここからちょっと離れてみてください。 2メートルくらい離れると(すごく目のいい人なら5メートルくらい)、もうリストになにが書いてあるかはわからなくなるはずです。 それでもリストが3つあることはわかります。 左がスーパー、真ん中が商店街、右がデパートで買うもののリストです。 これくらい離れると、買うもの個々のことは気にせず、どこに買い物に行くかだけ考えられます。 デパート→商店街→スーパーの順に回るか? 商店街とスーパーは仕事帰りに寄って、デパートは土曜日にするか?

行く場所が決まったら、また机のところに戻りましょう。 そしてこれから最初に行く場所のメモを1枚取って、目の前に持ってきてください。 何を買うのかよく見えるようになったので、買い物の内容をチェックできます。 飲み物は3本で足りるか?料理の材料に忘れ物はないか?花を飾ろうか、いらないだろうか? このとき、他のリストは見えなくなっています。 一箇所の買い物だけに集中できて、その後どこへ行くのか気にしなくてすみます。

物事を抽象化すると、それぞれ異なる抽象化のレベルが見つかります。 この例では「リストを選ぶレベル」と「買い物で使うレベル」の2つできました。 それぞれのレベルでは、それぞれの問題に集中できます。 そしてあるレベルで考えたり判断したことは、他のレベルに影響しません。 いまは「スーパー」「商店街」「デパート」の3つに整理していますが、たとえば商店街のどの店で買うのか、デパートのどのフロアに行くのかを考えたくなるかもしれません そうすればレベルが増えて、商店街を回る順番や、デパートで寄るフロアを考えることもできるようになります。

具体的に近い方を「低レベル」、抽象度の高い方を「高レベル」と呼ぶこともあります。 これは誰かをほめたり、けなしたりしているわけではなく、単に抽象化の度合いを表している言葉です。 高い低いを、空を飛ぶ鳥や飛行機のような高度でイメージしてみてください。 地面に近い、低いところでは、いろいろなものが詳細に、具体的に見えます。 地面から遠く、高い高度まで上がっていくと、広い範囲が見渡せるようになります。 低レベルでは詳細度が上がりますが視野が狭まり、高レベルでは詳細は見えませんが視野が広くなります。 どちらが大事とか、偉いとかいう話ではありません。 それぞれのレベルで見えるものが違い、考えられることも、解決できることも違うという考え方です。

問題のどの部分を、どのレベルから解決していくのか意識すると、問題全体にどうアプローチしていくのか作戦が立てられるようになります。 そうすると抽象レベルを高く上がったり低く下がったり、行ったり来たりしながら問題に取り組むことになります。 自分がいまどのレベルで考えているのか、そこでどういう問題を解こうとしているのか、忘れないようにしましょう。

例題:
  • Googleマップで自宅周辺の地図を表示して、拡大・縮小してみましょう。4つくらいのレベルを決めて、それぞれ比較してください。(スクリーンショットを保存して見比べるとよいです。)
    • それぞれのレベルでは、何が見え、何が見えないですか?どんなことがわかりますか?
    • それぞれのレベルの地図は、どんな使い道に向くと思いますか?
    • 同じことを、衛星写真(Earth)でやったり、交通状況を切り替えたりして、比較してください。
  • ふだん使っているソフトウェアやアプリについて、4つの抽象レベルで、それぞれ100文字程度で説明してください。
    1. 今日(または最後に使ったとき)の具体的なやったこと、使い方
    2. 自分がなんのためにそのソフトウェアを使うのか、その目的
    3. 類似するソフトウェアと比較した特徴
    4. 90歳のおばあちゃん(または3歳の子供)にそのソフトウェアを説明する
    • それぞれの説明の違いはなにか、なぜそのように変えたのか、整理してください
    • 他にどんな抽象レベルがあるか、考えてみてください
      • 例: そのソフトウェアの開発者なら?その会社の社長なら?株式アナリストなら?ライバルなら?

観点が重要

ここまでの例や例題で見てきたように、抽象化はソフトウェア開発に限らず、あらゆる場面で使われています。 もちろんソフトウェア開発やシステム開発でも、問題解決のためさまざまな抽象化がおこなわれています。 システムは一般的に複雑なものなので、抽象化も様々な観点が必要となります。 設計書、仕様書などのドキュメントはほとんどが、なんらかの観点からシステムを抽象化して記述したものです。 (なおドキュメントの呼称や内容は、会社や現場、人によって大きく違うので、知っているのと違うと思うかもしれません。 あくまで一例です。)

  • ワイヤーフレーム
    • 観点は画面の種類や数と、表示する主要な情報、遷移の流れなど
  • フローチャート
    • 一連の処理がどこから始まりどこで終わるか、どう流れていくかという観点
  • 詳細仕様書
    • 対象としている範囲に限った、プログラミングに必要な情報をすべて含む観点
  • システム概要
    • システムに登場するもの最大粒度で表現する観点で、システムの境界を定め、対象と対象外を区別するのに使う

このように観点しだいで抽象化の結果も目的も変わってきます。 どういう観点を選べばいいのか、どういう問題にはどういう観点を使えばいいのか、これは知識と経験が必要になってきます。 また観点の選び方が悪いと、問題解決の役に立たないどころか、かえって事態を混乱させてしまうこともあります。

買い物リストの話で考えてみましょう。 どこで買うかという観点でリストを整理し、3つのリストを作って、「どこに行くか」と「その場所で何を買うか」を分離して考えられるようにしました。 ところで、もし花を買うとしたら、どこで買うといいでしょうか? 花はデパートでも買えるし、商店街にも花屋がありそうですし、スーパーでも売っています。 花を実際に見て値段も確認してから買おうと思ったら、どのリストに入れておくといいでしょうか。 もし3箇所見比べたかったら、「どこに行くか」を考えるとき考慮しないといけなくなります。 こうなると、せっかくリストを整理したのに、「花をどこで買うか」という新たな問題が発生してしまいます。

また別の観点もあるかもしれません。 たとえば、予算が決まっていて、ほしいものは全部買えないかもしれません。 リストが1つだけだったら、リストの中身を必要な順に並べ替えて、予算がなくなるまで上から順に買えばいいでしょう。 しかしリストが3つに分かれていると、どのリストをどこまで買うべきなのかわからなくなってしまいます。 全体の予算があると、「どこで買うか」という観点の抽象化は不適切なわけです。 先に予算の問題を解決しないと、適用できない観点だということになります。

観点と抽象化レベルによって、もともとの大きな問題を分割してそれぞれ個別に解いていけます。 しかし、分離しきれない問題が残ることもあって、これはレベルをまたいで考える必要があります。 観点が間違っていて、問題が複雑化してしまうこともあります。 もともとの問題を全部理解して把握できていれば、あとからこんなことに気づいたりしないですむかもしれません。 しかしそもそも、問題は複雑で理解も把握も難しいから、いろいろ工夫をしているわけです。 「考えればわかること」は「考えたからわかる」ので、最初からわかっていれば苦労しません。

そこで、抽象化がうまく働いているか、問題がきれいに分割できているか、進めながら確かめる必要が出てきます。 高レベルで問題を解決したら、それが低レベルでもちゃんと解決できているか調べます。 また、他のレベルに不要な影響を与えていないかも、要確認です。 こうした確認を通じて、設定した観点と抽象レベルが妥当なものだったかわかってくるのです。 抽象レベルを自由自在に行き来しながら問題を解決し検証するというのは、とても高度なスキルですが、これができるようになるとプログラマとしての問題解決能力が大きく広がります。

コラム: アーキテクトも実装する

ソフトウェア開発ではよく「上流の設計が、下流で矛盾を生む」という事態が起きます。 その理由のひとつが、こうした抽象化の誤りです。(理由は他にもたくさんありますが。) 上流SEや、アーキテクト、プロジェクトリーダーといった立場の人が、高レベルのことだけ考えて低レベルでの確認を怠ると、実装時に設計を考え直さないといけなくなったり、実装できない設計になったりしてしまいます。

『組織パターン』には「アーキテクトも実装する」というパターンがあり、全体の方向性を決定するアーキテクトもプログラマーと一緒にコードを書くことの重要性を説いています。 また『人月の神話』の「第3章 外科手術チーム」では、生産性の非常に高い10名の開発チームには「執刀医」に当たるチーフプログラマーがいて、「自ら機能と性能を定義し、プログラムをデザインし、コーディングし、テストして文書を書く」と述べています。 ソフトウェア開発において実装というのはかなり具体的な活動、低レベルなものですが、ここまで下りてこないと本当には確認できない問題というのがたくさんあるのです。 (ちなみに、さらに低く、OSやメモリ、通信プロトコルや物理マシンといったレベルまで下がっていくこともできます。)

例題:
  • 何人かのグループを男女に分けるという場面をよく目にすると思います。どんな状況があるか、男女に分けることでどんな問題を解決しようとしているのか、いくつか書き出してください。
    • 男女に分けるという問題解決が、どういった観点からもたらされたのか、考えてください。
    • 男女に分けたせいで問題が起きることもあります。どんな観点だと、かえって状況が悪化すると思いますか。
  • いま利用しているプログラミング言語を、他の言語と比較しながら、なぜ自分がいまそちらを使っているのか説明してください。できれば他の言語は2つ以上選んでください。

https://github.com/yattom/text_for_programmer/wiki/%E6%8A%BD%E8%B1%A1%E5%8C%96

C言語でTDDを学ぶ?TDDでC言語を学ぶ?

Facebook上で議論になったのですが、C言語でTDDを勉強していると、「よりよい設計」になりにくいという話になりました。

例として整数の区間の最初のほうの課題を考えてみます。

課題1-1
下端点と上端点を与えて閉区間を生成しよう
区間から下端点と上端点を取得しよう

TDDで実装したコードとテスト

    // プロダクションコード
    int upper_point;
    int lower_point;
    
    // テストコード
    TEST(Range, Endpoint) {
        lower_point = 3;
        upper_point = 8;
        EXPECT_EQ(3, lower_point);
        EXPECT_EQ(8, upper_point);
    }

問題:どうしたら関数を導入できるでしょうか?

元のお題はオブジェクト指向を想定しているところがあって、「生成しよう」でオブジェクトを作り、「取得しよう」でオブジェクトから値を取り出すという形になるんですが、C言語では「値を与えて取り出す」のならば、変数があればいいよねと。とりあえずグローバルでも構わない、というのは、お題(要求仕様)に何も書いてないから。(externがないのでモジュール内に閉じていますけれど。逆に、プロダクションコードとテストコードを別モジュールにしたら、グローバルになってしまいますね。)

TDDのやり方に律儀に従うなら、新たなテストによって現在の(グローバル変数だけで生成は関数不要という)設計の限界が明らかになり、よりよい、シンプルな設計が導かれます。区間のお題の続きに「閉区間が別の閉区間と等しいか」があるので、複数の区間を扱うにはグローバル変数では困るよね……と思いきや、こうなります。

    // プロダクションコード
    int upper_point;
    int lower_point;
    
    int range_equal(int lower_point2, int upper_point2) {
        return lower_point == lower_point2 && upper_point == upper_point2;
    }

    // テストコード
    TEST(Range, Endpoint) { /* 略 */ }

    TEST(Range, Equal) {
        lower_point = 3;
        upper_point = 8;
        EXPECT_TRUE(range_equal(3, 8)); // [3,8]と[3,8]は等しいはず
        EXPECT_FALSE(range_equal(1, 9)); // [3,8]と[1,9]は等しくないはず
    }

うん、グローバルに設定したものとパラメータで渡すものを比較すればいいよね……間違ってはいない。

TDDでシンプルな解を追求する

TDDには(ひいてはXPには)「シンプルさ」という価値があります。TDDではシンプルな解をよしとします。ここには「(与えられた問題や制約をすべて充足するなかでもっとも)シンプル」という条件が隠れています。テストコードを眺めて、「比較対象を片方は変数に、片方はパラメータで渡すのは、シンプルでない」と思えば、以下のように書き直せます。

    // プロダクションコード
    int upper_point;
    int lower_point;
    
    int range_equal(int lower_point1, int upper_point1,
                    int lower_point2, int upper_point2) {
        upper_point = upper_point1;
        lower_point = lower_point1;
        return lower_point == lower_point2 && upper_point == upper_point2;
    }
    
    // テストコード
    TEST(Range, Endpoint) { /* 略 */ }
    
    TEST(Range, Equal) {
        EXPECT_TRUE(range_equal(3, 8, 3, 8)); // [3,8]と[3,8]は等しいはず
        EXPECT_FALSE(range_equal(3, 8, 1, 9)); // [3,8]と[1,9]は等しくないはず
    }

しぶといな、グローバル変数

TDDが自動的に良い設計を保証するわけではありません。「TDDを使ってよりよい設計に到達する」のと「TDDを使えばよりよい設計になる」の間には、深い深い溝があります。TDDを使うと設計品質が悪くなるという調査もあります。少なくとも、何が「良い設計」であるか、言語やライブラリやフレームワークのどんな特性を利用すれば「良い設計」になるか、知識がなければ設計として実現できません。

元々のお題にはありませんが、このようなグローバル変数を使った設計に対しては、別の課題を設定してあげるという手を思いつきました。グローバル変数を避けるべき理由として「いつの間にか値が書き換わって危険」という知識があります。range_equal()を呼ぶと書き換わってしまうので、自明でない挙動をする。そこで「比較しても値が書き換わらないようにする」という課題が考えられます。それをテストで表現すれば、TDDの流れで設計を改善できます。

    // テストコード ※失敗する
    TEST(Range, Equal_DoesNotChange) {
        lower_point = 3;
        upper_point = 8;
        range_equal(0, 5, 3, 8);
        EXPECT_EQ(3, lower_point);  // range_equal()を呼んでも変化しないはず
        EXPECT_EQ(8, upper_point);
    }

このテストは失敗するので、グリーンになるように実装を直します。目指すのはグローバル変数の除去ですが、そうすると実装を直す過程で上端・下端を生成したり取得したりというテストが、成立しなくなってしまいます。おまけに今書いたばかりのテストも、中身がなくなってしまいます(EXPECT_EQで比較するものがなくなってしまう)。

    // プロダクションコード
    int range_equal(int lower_point1, int upper_point1,
                    int lower_point2, int upper_point2) {
        return lower_point1 == lower_point2 && upper_point1 == upper_point2;
    }
    
    TEST(Range, Endpoint) {
        // なくなってしまった
    }
    
    TEST(Range, Equal) {
        EXPECT_TRUE(range_equal(3, 8, 3, 8)); // [3,8]と[3,8]は等しい
        EXPECT_FALSE(range_equal(3, 8, 1, 9)); // [3,8]と[1,9]は等しくない
    }
    
    TEST(Range, Equal_DoesNotChange) {
        // なくなってしまった
    }

なくなってしまったテストは、消してしまうのがいいでしょう。万が一あとで復活させたくなっても、一度書いたことはきっと憶えているはずです(それにバージョン管理してますよね?)

よい設計を目指すTDD

さて、話を前に戻して、「比較しても変化しないこと」という課題は、グローバル変数の除去を意図して導入しました。なぜグローバル変数を除去したかったのか?不用意にグローバル変数を用いるのは「悪い」設計で、しかしTDDのサイクルの中でグローバル変数を止める自明な方法が見つからなかったためです。ここではいくつかの議論が考えられます。Facebook上の組み込みTDD勉強会(クローズドグループ)での議論を踏まえています。みなさんありがとうございます。

  • グローバル変数の利用のような初歩的な設計上の問題は、設計判断を持ち出すまでもなく常識的に取り除く(最初から使わない)べきだ。そうしたレベルならコーディング標準で制限できるし、そういうレベルのプログラマはしっかり教育したりレビューで改善すべきだ。
  • このタイミングで無理にグローバル変数を除去する根拠はない。お題を進めて仕様を拡充していけば、自然にグローバル変数を止めたくなるときが来るはず。そのときにこそ、最適な設計判断ができるのであって、いま強引に変えるのは拙速で、YAGNIでムダだ。
  • 特にC言語ではデータ構造の自由度が(純粋なオブジェクト指向プログラミングに比べると)高く、初期に十分検討しないと後でリファクタリングするのに苦労する。TDDでもC言語を使うときは事前設計をもっと念入りにやったほうがいい。
  • 「シンプルにする」というTDDの方針だけでは、必ずしもよい設計に到達できない。十分な知識と広い視点で、より望ましい設計を考え、そちらに向かって(やや強引であっても)TDDで進んでいけばいい。

いずれの言い分も妥当ですし、環境や状況や人によって重視すべき事項は変わってきます。私自身は最後の考え方がわりと好きで、よりよい設計を仮説として(できればテストに書き)、TDDで実証するというアプローチを選ぶことが多いです。

グローバル変数の話は、これでいったん片付いたことにして、データ構造を整理することを考えてみます。上端と下端は常にペアで使うものなので、ひとまとめにしたいですね。方法はいくつか考えつきます。

  • 構造体を作る
  • 長さ2の配列を作る
  • 1個のINT32の上位16bitと下位16bitに格納する
  • など

どれが望ましいでしょうか。C言語の適用範囲を考えると。いずれも妥当な解法になり得ますが、ここでも「シンプルに」、つまり「与えられた仕様を満たす範囲でできるだけシンプルに」考えたいです。メモリや処理時間の制約がなければ、構造体が素直でしょうか。

    // プロダクションコード
    struct range {
        int lower_point;
        int upper_point;
    };
    
    int range_equal(struct range range1, struct range range2) {
        return range1.lower_point == range2.lower_point && range1.upper_point == range2.upper_point;
    }
    
    TEST(Range, Endpoint) {
        // 復活!
        struct range range1;
        range1.lower_point = 3;
        range1.upper_point = 8;
        EXPECT_EQ(3, range1.lower_point);
        EXPECT_EQ(8, range2.upper_point);
    }
    
    TEST(Range, Equal) {
        struct range range1;
        range1.lower_point = 3;
        range1.upper_point = 8;
        struct range range2;
        range2.lower_point = 3;
        range2.upper_point = 8;
        EXPECT_TRUE(range_equal(range1, range2)); // [3,8]と[3,8]は等しい
        range2.lower_point = 1;
        range2.upper_point = 9;
        EXPECT_FALSE(range_equal(range1, range2)); // [3,8]と[1,9]は等しくない
    }

構造体を導入したコードを見ると、どうもテストコードが煩雑で、これなら前のほうが良かったように見えますね。rangeを簡潔に生成する方法を導入すれば改善できそうですが、本稿では省略します。

知らない解法を使えるか

また話を少し戻して、構造体導入の判断を考えてみます。構造体を使おうと思うには、少なくとも構造体を知らないといけない。カジュアルにグローバル変数を使っちゃうプログラマーが構造体を知っているか、知っていても適切に使えるかは疑問です。

知らない解法を使うことは誰にもできません。ここでは構造体を取り上げていますが、「知ってはいるけどちゃんと使ったことのない○○○(任意の手法・技法)」と考えれば誰でも遭遇し得る状況です。こうした状況で、TDDは無力なのでしょうか。きちんと勉強した熟達プログラマしかTDDは活用できないのでしょうか。

その逆で、TDDは新しい技術を使いこなせるようになったり、未知の技術を発見する役に立ちます。それ自体がシンプルな解の探究になるためです。いまある問題に対してよりシンプルな解に到達するには、以下の4レベルを上がっていく必要があります。

  1. 動く
  2. よりシンプルに書き直す
  3. 他の書き方を複数試して、一番シンプルなものを選ぶ
  4. さらにシンプルな書き方を勉強してくる

グローバル変数の例ではレベル2を取り上げました。構造体を知っているけれどうまく使えないのであれば、レベル3にチャレンジする必要があります。先のコードでは構造体を導入したものの、かえって煩雑になってしまいました。

よりよい設計、よりシンプルな解法を見つけるには、レベル3の試行錯誤が必要になってきます。試してみる、他のアプローチで試してみる、リファクタリングでいろいろなパターンを見比べてみる。その中で一番よいと思えるものを残す。TDDの回転は一直線ではありません。行きつ戻りつしながら少しずつ上がっていくのです。

試行錯誤で最善と思える結果が出ても、まだよくなる可能性があるかもしれない。そう思えたときが、レベル4になってまったく新しい解法を探しに行くタイミングです。レベル3までをきちんとこなしていれば、問題について十分に理解できているはずです。いまある解法の効用と限界も知っているでしょう。それならば、新しい解法を見つけても適切に評価できます。中途半端な解法に飛びついたり、不適切な解法を盲目的にコピーしてしまうこともありません。

レベル3までは問題を深く理解するためのステップで、レベル4が本当の問題解決だと見ることもできるかもしれませんね。

スクラムマスターというファシリテーター

スクラムというソフトウェア開発プロセスには、スクラムマスターという役割がいます。スクラムではチームメンバーが信頼に基づいた協力関係の中で価値を創出し、ときには対立もしながらよりよい成果を模索し、チーム全体の成長とプロダクトの成功を目指します。その中でスクラムマスターは全体が円滑に進むようにし、明白なルール違反を指摘し(ルールの数はごくわずかです)、対立を解消し、チーム全体が与えられた状況で長期的に最善のパフォーマンスを出すことにコミットしています。ファシリテーターならスクラムマスターができるわけではありませんが、スクラムマスターはファシリテーターの役割を果たします。

以前に紹介したパターンによると、スクラムマスターには以下の8つの役割があります。

  • 触媒: スクラムに欠かせない大量のコラボレーションを発現させる。
  • 完成マスター: スクラムマスターはチームに完成の定義(Definition Of Done)を守らせる。
  • 牧羊犬: チームが常にプロセスを守るよう支える。監視して、ズレを補正する。
  • 鏡の剣士: スクラムマスターは鏡の剣士となり、チームの行動を投影してみせる。チームは自分自身の長所と弱点に気づく。
  • コーチ: チームに改善を促し、改善のためのアドバイスを与える。
  • チアリーダー: チームを元気づけ、ポジティブなフィードバックをする。
  • ファイヤウォール: 不必要な外部の影響からチームを保護する。
  • プロダクトオーナートレーナー: スクラムマスターはプロダクトオーナーがより上手になるのを手伝う。

この中では触媒と鏡の剣士が、スクラムマスターとファシリテーターの交叉する部分になっています。スクラムマスターはミーティング(スクラムではイベントやセレモニーと呼ばれる)のファシリテーションをします。スクラムに不慣れなチームは上手な進め方が分からないので、経験あるスクラムマスターがガイドすることになります。進行はもちろん、議論の活性化や、多様な意見を表出させたり、タイムボックスを守るのもスクラムマスターになります。

同時にスクラムマスターはチームの成長を促します。特に朝会(15分以内の毎日全員が参加するミーティング)は、進行をスクラムマスターからチームメンバーに委譲する最初のセレモニーとなることが多く、進め方を全員が把握したらスクラムマスターは後ろに下がって、チームにファシリテーションを任せます。他のミーティングも、多かれ少なかれチームが進行するように段々なっていきます。スクラムマスターはファシリテーションを手伝うこともあるし、100%チーム任せにすることもあります。

ミーティング以外でも、スクラムでは始終活発なコミュニケーションが起きています。スクラムマスターはその様子を見て、チームが進む方向を把握したり、長所短所に気づいたり、問題の芽を見つけたりします。スクラムマスターはコミュニケーションが上手くいくよう手伝いながら、そうした知識をできるだけ透明にチームに伝えて、チームが気づかずにいた点を直せるよう仕向けます。チーム内で対処しきれない問題があれば、スクラムマスターが代わって解決します。

いっぽうチームはスクラムマスターからの指摘を受けながら、スクラムの進め方やコミュニケーションの取り方に上達していきます。連携すべきステークホルダーとの関係性も、徐々に確かなものになっていきます。そうするとスクラムマスターは、今までと同じように観察していても、指摘することは減ってきます。問題(スクラムの言葉では障害物、インペディメント)の解決も、チーム内の問題から、チーム外へと重心が移っていきます。

ここでは一部しか例を挙げませんが、このように、ファシリテーターとしてのスクラムマスターは、ひとつの場をファシリテートする役割と同時に、その役割をチームが吸収できるよう成長させる役割を持っています。チームのミーティング、チームのコミュニケーション、チームの問題解決、いずれもチーム自身で対応できるのが一番効果的であると信じて、その方向に向かってゆくのもスクラムマスターの仕事です。

スクラムを導入した開発チームにおいて、スクラムマスターの最終ゴールとは、自分が不要になることだとも言われています。チームと一緒に働きながら、スクラムマスターとしての全力でチームを支援し、そうした支援のやり方やテクニック、思想までチームが吸収してくれれば、名誉ある用済みになれる。スクラムマスターとして、自分の価値や効用を提供できれば、喜んでもらえるし満足度もありますが、それにチームを縛ってはならないと思います。

私が気をつけているのは「手を出さない」「口を出さない」ことです。我慢も辛抱もいるし、非難されることもあるし、逆効果のこともあります。それでも、みんな自分で考えて発言して行動できるし、私が関与するよりもきっと良い結果を出せるはず、失敗するかもしれないけどそこから学ぶことだってできる、そう信じています。経験は場で起きるかもしれないけれど、学びと成長は場を超えていきます。ファシリテーターって、促進する人だとすると、長い時間をかけた成長を促進するのもやはりファシリテータだと思いたい。まあ、「参加者に任せれば最高の結果が出るはず」よりは「私なんか大して役に立たないし」と思うほうが、簡単だしきっと現実に近いんですけれども。

そう思えば、大して役に立たないけどちょっとは役に立つことをしながら、みんなが失敗しながら学んでいく速度を最大化する、やがては役立たずの烙印を押されるその日に向かっていくこともできるのかな。

最後になりましたが、ファシリテーター Advent Calendar 2015 - Adventarには id:DiscoveryCoach ことがおりゅうさんに誘っていただきました。場違いなエントリかもしれませんが、読んでいただいてありがとうございます。

Scrum Master as a facilitator

This entry is a part of Facilitator's Advent Calendar.

In a software development process called Scrum, there is a Scrum Master. Scrum emphasizes trust between team members and though it, they create values in collaboration, search for the best possible outcome sometimes with a conflict, and aims for team's growth and success of the product. Scrum Master's job is to remove frictions in communications, point out obvious violations from Scrum's rule (there are very few rules), and commit to the team so that they can achieve the best performance in a given situation. Being a facilitator is not enough to become a Scrum Master, Scrum Masters often play facilitator roles.

In the published ScrumMaster pattern, Scrum Master has at least 8 functions.

  • CATALYST: In order to ensure that the high amount of collaboration needed for Scrum to succeed happens.
  • The ScrumMaster keeps the team adhering to their DEFINITION OF DONE by taking on the role of DONEMASTER.
  • SHEEPDOG: Continually encourage the team follow its processes; watch for and correct deviations.
  • The ScrumMaster can become the KNIGHT OF THE MIRRORS, reflecting the team's behavior back to them so that they understand their strengths and weaknesses.
  • COACH: Challenge the team to improve, and give advice on how to improve.
  • CHEERLEADER: give the team encouragement and positive feedback.
  • FIREWALL: protect the team from unnecessary external distractions.
  • The ScrumMaster may also help the PRODUCT OWNER become more effective, assuming the role of PRODUCT OWNER TRAINER.

Among the list, Catalyst and Knight Of The Mirror is the place where Scrum Master and facilitator cross. Scrum Master facilitates meetings (in Scrum, they are called events or ceremonies.) A team new to Scrum is not familiar with Scrum meetings, so an experienced Scrum Master usually guides through them. Scrum Master is responsible not only the agenda but also energizing discussions, exposing diverse opinions, and to keep time boxes.

At the same time Scrum Master facilitates the growth of the team. For example, usually daily standups are the first meetings which team receives the responsibility to run a meeting by themselves. At first Scrum Master guide the meetings and dictate what to talk about. Once team understands why and how to run the meeting, Scrum Master stands back to let team do by themselves. Sooner or later, team will run other meetings also. Scrum Master might help facilitating, or might leave the team do it 100%.

Outside meetings, there are live communications and discussions everywhere in and around any Scrum teams. Scrum Master watch them carefully and grasps the direction teams are going, notices strong and weak points, or finds potential problems. While Scrum Master facilitates and helps the communications, it's also Scrum Master's job to let the knowledge transparent to the team so that the team understand their behavior clearly. When team have a problem which they cannot solve by themselves, Scrum Master helps.

On the other hand, the team is getting better and better at those communications with suggestions from Scrum Master. The relationship between the team and stakeholders get stronger. That means Scrum Master will have fewer and fewer things to point out, though the observation continues. Problems (or impediments) will be shifted from inner-team to outer-team.

These are only a few examples to show that Scrum Master as facilitator has two roles; one is to facilitate a Ba, the other is to let the team absorb the first role. Meetings, communications, problem solving, they are all managed most effectively when managed by the team. While it is satisfying to be pleased by providing values and effects from Scrum Master, Scrum Master should never bind the team with them, even with good will.

It is said that the ultimate goal of Scrum Master is that the Scrum Master is no longer needed. Scrum Master, working with the team, doing the best to support the team, becomes honorable useless when the team absorb Scrum Master's methods, techniques, and even ideologies. It won't happen soon, will be difficult even after enough time. Yet it must be something any Scrum Master should have in mind.

My way of doing so is, not to do, not to say. It requires patience. Sometimes get blamed. Perhaps it backfires. Still, I believe they can think and speak and act and achieve better without my interference. Even if they fail, I believe they will learn from it. A Ba can provide experience to the people. But learning and growth happen beyond a single Ba. Facilitators are said, well, they facilitate. Facilitating a long term growth is also part of the facilitator's scope, or so I think. Anyway it's easier to replace the idea of "They can attain the best when left themselves" with "I won't be much of help to them anyway!" And latter's more realistic.

With the idea in my mind, I provide not much of help, but sometimes a bit of help, so that the speed of learning from failures can be maximized. That is the way toward the uselessness, perchance.

Thank you for reading so far. Gaoryu-san, or id:DiscoveryCoach, invited me for this year's Facilitators Advent Calendar. I want to express my thanks for the invitations and the interesting chance to write about my view of facilitator.