パステル色な日々

気ままに綴るブログ

カンバンによるプロセスづくりの紹介

カンバンというメタプロセスをご存知でしょうか。近頃、僕はカンバンでプロセスを改造するようになりました。 今日はその一区切りとして、今までやってきたことをまとめて紹介しようと思います。

カンバンというメタプロセスに期待していたこと

チームができてからメンバーはとても頑張ってくれていました。しかし、四半期が終わったあとの振り返りで、「誰が何をやっているのかわからない」という意見が。確かに、チームは個人プレーで作業を頑張っている印象があったんです。繰り返し聞いてみると、それによって「心理的に安心感がない」「リリースが遅くなる(手伝わなくなるから)」といった重要である理由が見えてきました。

これは取り組んだほうが良さそうだ。僕は思いました。ですが、作戦を練ることが難しかった僕はアジャイルひよこクラブでこの課題について聞いてみることにしました。

agile-hiyoko-club.connpass.com

そこでカンバンというメタプロセスの考え方に触れて、これならプロセスを改造することで作戦を立てられそうと思い立ったのです。

  • 改善活動
  • 見える化による議論
  • WIP制限による協力機会の創出
  • リソース効率化とフロー効率化のバランス
  • リードタイムなどで自分たちの改善結果による影響を知る

いづれもカンバンによるプロセスの改造で、きっかけを作ることができます。 カンバンはメタプロセス。だから、カンバンによるプロセスづくりをした上で、当初の課題に対する根本的原因へのアプローチをしてみようと考えていました。

やってみたいと打ち明けた

ランチの時間。思い立った僕はチームにカンバンをやってみたいと話してみました。リーダーであるため合意形成の必要はないかもですが、お互いの期待値をすり合わせることは大切。実際にプロセスを動かすのはメンバーなのでメンバーと話を行いやることにしました。

カンバンボードを作成

まずはカンバンボードを作成してみました。チームでワークフローを書いてみると互いの認識が違ってて面白かったです。ここで議論が発生。

次に作業項目を書き出してもらいマッピングしていきました。サブプロジェクト(社内の改善活動)での作業も出てきましたが、これはチームでの作業を妨げる要因であったため、ブロック要素としました。ここでも議論が発生。

議論の機会が何度も訪れて、自分以外の作業について感心を持っていてくれたのが嬉しかったです。これも「見える化による議論」ですね。

朝会はカンバンボードを囲む

朝会はもとからやってましたが、カンバンボードを新しく囲むようにしました。

自分が担当していた作業が終わったメンバーが次に何をしたらよいか考えていたときです。この作業を手伝ったら?ともちかけてみました。なにか手伝えることあるかな?専門性が高い作業になってしまっていると協力機会を逃してしまいますが、幸いにもできることがあったので狙い通り協力機会を創出できました。

またあるときには、やりたいけどできない作業が発生していました。ブロック要素です。こういったものには経過日数を書き込んでいきました。例えば、レビュー完了までに5日かかっていることがわかりました。チームはこれを問題視することができ、早く終わらせるためにできることを考えることができました。

カンバンボードの変遷

カンバンボードはたえず変わっていきました。新しい列ができたり、列がなくなったり、呼び方が変わったりしています。自分たちのワークフローに合ってないと感じたらいつでも変わります。

WIPを制限してなかった

するとしばらくして、カンバンボードにない作業が発生していることがわかりました。カンバンボードに載せ忘れていたことが原因みたいですが、このときWIPを制限していませんでした。 まずはカンバンボードになれてもらうとして設定してなかったのです。次にボトルネックとなるところだけ設定していました。詰まりは解消されたのですがいつでも増える作業を抑制することはありません。メンバーは終わらせることよりも新しい作業を開始していたのです。

その後、チーム全体のWIPを制限しました。WIPに対する理解を得るためにコイン渡しのゲームやWIPが増えるとどうなるのかを説明しました。

チームに起こった行動の変化

プロセスを改造してやっと下地ができたところ。まだまだ道半ばです。変化を促すのはこれからなのですが、ここまでの取り組みで起こった行動の変化をまとめます。

  • メンバー間の会話が増えた
  • 協力して作業を進めることがあった

心理的にはどんな変化があったのかわかりません。振り返りでは「俯瞰して見えるようになった」、「チームやタスクの状態に合わせて適宜改善している」といったポジティブな意見を聞くことができました。

いかがだったでしょうか。ようやくカンバンに基づくプロセスづくりのスタートラインに立つことができました。仕事の成果は今の所変わらず生み出せており、ステークホルダーにも満足いただいているみたいです。

今後の改善活動や流れの管理によるわかったことは、また別途学びとしてまとめてみようと思います。

あなたはどんなメンバーでチームを組みますか

組織、チームやグループの言葉についておさらいしてみました。

組織

共通の目標を有し、目標達成のために協働を行う、何らかの手段で統制された複数の人々の行為やコミュニケーションによって構成されるシステムのことである。

出典:組織 (社会科学) - Wikipedia

ここからわかるのは組織とはシステムだということです。つまり相互に影響を及ぼし合う要素から構成される、まとまりや仕組みの全体のことです。統制された、というのがポイントですね。同じ目的を有し、統制された個が互いに影響を及ぼし合うまとまりのことを組織と呼びます。

グループ

複数の人間の空間的・心理的・目的理由その他な集まりのこと。

出典:グループ - Wikipedia

グループはすごく抽象的な概念ですね。同じ目的を掲げる人間の集まりのことをグループと呼びます。

チーム

共通の目的、達成すべき目標、そのためのやり方を共有し、連帯責任を果たせる補完的なスキルを備えた少人数の集合体を理想とすることがある。 ワーキング・グループの目的がメンバ個々の業績水準を底上げする場合がある。成果は個人の成果の総和またはそれ以下のことがある。目的が違えば、行動を打ち消し合うことがあるからである。 チームでは、他人の意見に耳を傾け、建設的に反応し、ときには他人の主張の疑わしき点も善意に解釈し、彼らの関心ごとや成功を認めるといった価値観が集約されたチーム・ワークが存在すると仮定する。この仮定が成り立てば、成果は集合的作業成果による共同の貢献が含むため、グループのそれより大きくなるかもしれない。

出典:チーム - Wikipedia

コミュニケーションの傾向がより具体的になっています。チームワークにより個人の成果の総和を上回る可能性があります。チームワークを仮定と捉えているのが面白いですね。

チームの成果を最大化する

個々の成果の最大化とチームワークの成立の2つを追いかけることがチームの成果を最大化させることに繋がります。

(個々の成果+個々の成果+...+個々の成果)×(チームワーク係数)

チームワーク係数がポジティブだったりネガティブだったりに作用することもあります。

人をチームにする

どういう人達でチームを組めばいいのでしょうか。個々の成果に関しては能力を磨くことで大きくすることができます。人には専門スキルがあります。相対する問題によってどういう人達でチームを組めばいいのかここからなにかわからないでしょうか。

相対する問題に一貫性がないとき

この場合、必要とされる専門スキルに決まりはありません。個々の成果を最大化するなら問題が変わるたびにチームを組み直せばいいでしょう。だたし、チームワーク係数は安定しなくなるので成果が予想しにくくなります。成果が思わしくないときもあるでしょう。

相対する問題に一貫性があるとき

この場合、必要とされる専門スキルは予め分かるでしょう。人数は相対する問題が大きいほど大人数であれば成果が出るまでのスピードを早めることができるでしょう。ただし、問題の大きさはコントロール出来ないため、一定の期間で成果を求めるならチームで取り組みやすい大きさに分割しましょう。

2つを追いかける

チームワーク係数を大きくするためには安定したチームであるべきです。そのためには同じ傾向の問題を与えられるようにする必要があるでしょうか。できればその必要があると考えます。できないようであればチームに専門性を持て余すメンバーが存在することになるでしょう。そうなったとき、一人で専門スキルを活かせる問題を用意しましょう。違う問題を追いかけるためチームワーク係数を大きくすることができないかもしれません。ですが、全く手の打ちようがないわけではありません。このような場合でもチームワーク係数を大きくするための取り組みはあるのです。

性質の異なる問題に挑むことはチームにとって難しいことです。経験値が足りないのです。まずは一定の性質を持った問題から取り組むようにしてください。できないようであれば、経験をチーム間で共有できるような仕組みを作りましょう。そういう組織にするのです。なれてきたら異なる性質の問題に取り組みましょう。そうやってできることを増やしていくのです。

納得すること

チームメンバーに大筋の説明をした時の話。想像してたよりもあまりよくできなかった。

目標にしてたみんなの納得感はあまり作り出せなかったと思う。なぜか。

  • 自信なさそうな振る舞いをした
  • 自分の中で納得感が作り出せなかった(結論へのロジックに納得ができなかった)
  • 質問に答えられなかった
  • 板書があまり活用できなかった
  • 自分で自分を卑下した

こんなのが理由だと思っている。すべてチームメンバーの前でやってしまったのがまずかった。

自信なさそうな振る舞い

リーダーにこんな振る舞いされちゃついていきたくなくなりますよね。こういうやるときはやるリーダー像もあるかもしれないけどあまり納得がいってない

自分の中で納得感が作り出せなかった

できた大筋に対してそこに至る道筋に納得ができてなかった。なので要点だけをかいつまんでチームメンバーに納得感を作り出すプレゼンができなかった。まずは自分が納得できることが大切だ。

質問に答えられなかった

納得ができなかったから言わずもがな

板書があまり活用できなかった

今回は全員で顔をあわせて話をしたかったのでテーブルにコンパクトなホワイトボードを使って事前に色々板書を用意して説明に使おうとした。

納得感が薄かったので資料としてのわかりやすさにも精彩を欠いた

自分で自分を卑下した

質問に答えられなくて代わりに答えてもらった。そこで「だめだねー俺」と思わず言ってしまった。情けない気持ちで一杯でも不安に感じてもらうわけにはいかないのでどっしり構えたい。

自分はよく準備するタイプなので納得感が薄いとだんだん言っていて不安になってきて、それがもろに表面に出た。絶対納得した上で進めるようにする。困るのは自分なのだ。

想像を超える瞬間

僕は割と念には念を入れるタイプ。リーダーとして宿題を出された。自分なりにしっかりと考え抜いもはや隙きはない状態にしたと思ったが、フィードバックで普通に想像を超えられてしまった。僕からしてみると「あーたしかにそれも考えないといけないわー」とうなずくばかり。

フェーズは進み大まかなストーリーの合意も取れた。次はストーリーに沿ってどんな課題から向き合うのか。棚卸しと優先順位付けだ。

まだ上流工程で用件を話す段階なので少人数でスピード重視で進めることに。まだどうやってやるのかの話はしてないのとスピードがほしいのでエンジニアの力はまだ借りない。

UXエンジニアもチームにいてどういう働きができるのか事前に聞いた上で今回はもっと先の話のために準備してもらうことにした。

想像を超える瞬間があるとまだこの会社で学ぶことは多いなと感じる。自分も同僚の想像を超えられるようになりたいな。

キーパーソンは誰だ

引き続き目標の言語化。今後の行動の方向性を決めるものなのですごく大切だ。

開発シーンでは開発チームと問題が遠くなる場合もあるが今日は近い場合、そして一緒に解決する場合の話。

チームのオーダーをくれた人

チームが作ったものに対して承認をする人。この人と話をすると合格の方向性が見えてくる。抽象化された目標でも明後日の方向に向かって作られたものは承認されないのだ。この人とは合格の方向性を握ろう。

事業の偉い人

一緒に仕事をする人の上長。ミッションを与えている。進んでほしい理想像を知っている。方向性を決める参考にしよう。なぜそのミッションになったのかもっと聞いてみよう。さらにその先○年後のビジョンなども聞いてみよう。

一緒に仕事をする人

実際の課題を体系的に感じ取っている人。一番課題に近い人。直近の戦略を決めるときの参考になる。どんな問題やどんな人が存在しているのか聞いてみよう。対策をとっているのならどんな人にどんな対策をとっているのか聞いてみよう。技術でサポートできるのはどんなことだろうか。目標達成のためのストーリーが描けるかも すると自ずと優先順位が導き出せそうだ

ここまで話をすると作戦が決まった。ポイントは当事者だけで話をすること。小さくやっていく。

誰と会話するべきなのかはきっちり手持ちの情報を照らし合わせて決めていこう。狙いを持って話を聞きに行くことが肝心。

話のときには着目ポイントに沿ってメモしよう。すると議論に一貫性が生まれる。

大きくうなずき、話に割って入らない。深掘り、向きを変え、欲しかった答えを聞き出そう。

話は色んなエピソードを分解して再構成したり、抽象化と具体化を意識するだけで見え方が変わる。抽象度合いは話す相手によりレイヤーが違う事業責任者に具体策を聞いても組織構造の意味がない。

曲者

ちゃぶ台を返しそうな人。鶴の一声でいろいろ変えられるひと。ストーリーが決まったらこの人に合意を取ろう。

チームメイト

この時点で同意を一度取ろう。このあと具体策がでてきてもストーリーに沿っていれば疑問は生まれない。納得感を作り出そう。

目標の言語化の間にいろんなキーパーソンが存在する。ひたすら話をしてまとめて戦略を練って話を聞くことの繰り返し。こうして戦略は練られていく。

チームの一歩先を行く人

チームを率いるリーダーになりました。 日記のような形で日々の学びを書き出したくなったので頻度上げて書いていこうと思います。

なので自分に対する話し言葉で書き残します。

チームメイトの一歩先を行き、水先案内人になろう

リーダーに求められることは大きく2つあった。

  • チームに期待されている成果を上げること
  • チームメイトの先を行き水先案内人になること

特に下について、だいたい1Qを見渡すことから始めることに。大変。 チームメイトが頑張ってくれたのに結果を出せなければリーダーの責任と言われる。全くそのとおり。 戦略をしっかり練って水先案内をしないといけない。なのでリーダーの仕事は考えることっぽい。 このあたりで意識が引き締まった。

大きなプロセスイメージを描く

早速わからなくなったのが次にどうすればいいか。 先を行くにあたりどういう動きをすればいいんだろう。

  1. 目標言語化
  2. 目標共有
  3. タスク設定
  4. アサイ

こうらしい。水先案内人をするってことは抽象度が高い目標をチームメイトに見せる前にある程度具体化の作業が必要。 なぜなら新しい開発をするに当たり、問題提起した人がいるわけで、それに関わるキーパーソンからのヒアリングはすることになるから先んじてやっておけばチームメイトが迷いなくスタートを切れる。 抽象度が高いと不安になるし、それに集団で立ち向かって機能的に動けるほどまだチームは成熟してない。ならばリーダーが率先して動いたほうが良い。

業務のつながりを意識したコミュニケーションを取る

大きい組織になれば分業制は当たり前。そうなると仕事のパスが行われるときにたいてい取りこぼしがある。つながりを意識したコミュニケーションを取ることで個々の知識が流動的につながっていることを感じられてチームとして一体感を作れそうだと思った。

メンバーの体験設計でも生きる。チームメイトのバックグラウンドなんて多種多様。ならばちゃんとチームメイトが直前にお世話になっていた人 (コーチやメンター)に話を聞きに行くと目指していくキャリアやどういう人なのかわかる。これはメンバーが気持ちよく仕事をできるようにする材料になる。大いに役立ちそうだ。

まとめ

まだ動き出したばかり、言葉もつまり、ヘルプを出すシーンも多い。悔しいがしょうがない。とりあえず明日の動き方を決めて今日は良く寝よう。

UIから考えるモデリング in Elm

Modelは大切

皆さんは何を考えながらモデリングしてますか?まずはElm Architectureを見てみましょう。

elm_architecture
Elm Architecture

ViewはModelに依存しUpdateもModelに依存しています。したがってModelの影響の大きさは言わずもがなです。

ちょっとしたModelの修正も影響範囲が多くて溜息をつくことは少なくありません。影響は少ないほうがいいですよね。

今回はモデリングについて考えてみましょう。

UIから考える

今回はこの動画にある方法を使ってモデリングをやってみようと思います。

youtu.be

リチャードさんはまずはUIから考えようと言っています。インライン編集可能なブログ記事のページを考えてみましょう。

blog_article_page
ブログ記事のページ

TitleとStoryという本文で構成されたブログ記事のページです。記事の作成者はインライン編集ができます。

ペンのアイコンをクリックすると右のページようなインライン編集状態になります。Saveボタンをクリックすると左のページのTitleが編集したものに置換されます。

みなさんもこのようなページをモデリングしてみてください。それでは次に私がモデリングしてみます。

type Article
    = Article { title : Title, story : Story } Property


type Property
    = ReadOnly
    | WriteTitle Title


type alias Title =
    String


type alias Story =
    String


-- MODEL

type alias Model =
    { article : Article
    }

Titleのインライン編集に着目してモデリングしてみました。皆さんのモデリングと見比べてどうでしたか?

それでは次のモデリングと見比べてみましょう。

type Property
    = ReadOnly
    | WriteTitle Title


type alias Title = String


type alias Story = String

-- MODEL

type alias Model =
    { title : Title -- READ/WRITE
    , story : Story -- READ/WRITE
    , property : Property -- READ/WRITE
    }

前者と後者は何が違うのでしょうか?後者はレコードの要素をいつでも操作することができます。

そのためPropertyがReadOnlyであってもtitleとstoryは変更できます。もちろんそのようにしないロジックを構築すれば防ぐことができます。

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ToggleEditTitle ->
            ( { model | property = WriteTitle model.title }, Cmd.none )

        SetTitle title ->
            case model.property of
                WriteTitle _ ->
                    ( { model | property = WriteTitle title }, Cmd.none )

                ReadOnly ->
                    ( model, Cmd.none )

        SaveTitle ->
            case model.property of
                WriteTitle title ->
                    ( { model | title = title, property = ReadOnly }, Cmd.none )

                ReadOnly ->
                    ( model, Cmd.none )

それでは前者の場合はどうでしょう。

module Article exposing (Article, empty, mapTitle, toggleTitle)


type Article
    = Article { title : Title, story : Story } Property


type Property
    = ReadOnly
    | WriteTitle Title


type alias Title =
    String


type alias Story =
    String


empty : Article
empty =
    Article { title = "", story = "" } ReadOnly


toggleTitle : Article -> Article
toggleTitle (Article edits property) =
    case property of
        ReadOnly ->
            WriteTitle edits.title
                |> Article edits

        WriteTitle title ->
            ReadOnly
                |> Article { edits | title = title }


mapTitle : (Title -> Title) -> Article -> Article
mapTitle modifier ((Article edits property) as article) =
    case property of
        ReadOnly ->
            article

        WriteTitle title ->
            WriteTitle (modifier title)
                |> Article edits
module Page.Article exposing (..)

import Article exposing (Article)


-- MODEL

type alias Model =
    { article : Article
    }

-- UPDATE

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ToggleEditTitle ->
            ( { model | article = Article.toggleTitle model.article }, Cmd.none )

        SetTitle title ->
            ( { model | article = Article.mapTitle (always title) model.article }, Cmd.none )

        SaveTitle ->
            ( { model | article = Article.toggleTitle model.article }, Cmd.none )

いかがでしょうか。モジュールを2つに分けてみました。

これならArticleはReadOnlyのときにtitleを変更できません。なぜならそのような関数がArticleモジュールから公開されてないからです。

また前述のパターンと異なり、WriteTitleコンストラクタも公開していません。このためArticleモジュール内部にArticleの実態は隠蔽されています。

この方法をOpaque Typeと呼びます。テクニックの一つですが動画では必須とまで言われています。

これで、Articleモジュールを編集してもUpdateやViewに影響が出ないように作ることができました。ネストが浅くなり多少見やすくなってないでしょうか。

また、title編集時の状態を WriteTitle Title と定義しているのもポイントです。

type alias Model =
    { title : Title
    , story : Story
    , editableTitle : Maybe Title
    , editableStory : Maybe Story
    }

少し定義を変えてみました。それではこの状態はとり得るのでしょうか。

type alias Model =
    { title : Title
    , story : Story
    , editableTitle : Just Title
    , editableStory : Just Story
    }

インラインで編集可能なのは一箇所だけとします。するとeditableTitleとeditableStoryの両方がこのような状態を取ることはありえません。

このようなアプリケーションにありえない状態を作り出すことが可能なモデリングを避けることでバグの少ないアプリケーションを構築できます。不可能な状態はモデリングで防ぐことができます。

youtu.be

サマリ

  • UIから考えることでモデリングができる
  • Oppaque Typeで変更に強いモデルを作ることができる
  • 不可能な状態 (Impossible state) を排除することができる

所感

またもや動画からモデリングの方法の一部を紹介しました。Elmでアプリケーション開発をしているとモデルを変更する機会は多々訪れます。

そのたびにModel, Update, Viewのすべてを変更するのはとても大変です。今回の方法を用いてなるだけ変更の影響がもれないように気をつけてみてください。

しかし、モデリングのポイントはこれだけではありません。UI StateとDomainをどのようにモデリングするのかという話題もあります。

フロントエンドでDDDをしようものならもっと複雑になることでしょう。一概にこれが正解というわけではないので皆さんの課題に沿った最善の方法を模索していきましょう。

そしてどんどん私に教えてください。 (違