エラスティックリーダーシップを読んで考えたこと

この記事はScrumFestSapporo2020 Advent Calendar 202020日目の記事です。

はじめに

安ヶ平です。普段はSIerスクラムマスターとして働いています。
今年は各地のScrumFestにオンラインで参加していて、11月はScrumFestSapporo2020に参加しました。招待講演がすごく良かったので、そこで言及されていたエラスティックリーダーシップアドベントカレンダー駆動で読んで、考えたことをブログにしたためてみました。
記事の前半では、エラスティックリーダーシップという考え方について、私なりの理解を述べます。次に、書籍を読んでスクラムマスター視点で大事だと考えたことを2つ述べます。最後に、この本の内容とSCRUMMASTER THE BOOKの内容はいい感じの補完関係にある気がしたので、その点について述べます。

エラスティックリーダーシップという考え方

エラスティックリーダーシップというのは、「チームにはサバイバルフェーズ、学習フェーズ、自己組織化フェーズという3つのフェーズがあり、リーダーはチームのフェーズに合わせたリーダーシップスタイルを取る必要があるという考え方」と私は理解しています。書籍を読むことで、この考え方の他にも様々な気づきを得ることができましたが、タイトルになっているこの考え方を知れたこと、これが自分にとってのこの本の一番の価値でした。
各フェーズとそれに合わせたリーダーシップスタイルは以下の通りだと理解しています。

サバイバルフェーズ

サバイバルフェーズというのは、メンバが目の前の仕事をこなすことに精一杯で、チームとしての学習時間が取れていない状態を指します。
このフェーズにおいて推奨されるリーダーシップスタイルは、指揮統制型のリーダーです。
アジャイルの文脈で出てくる支援型のリーダーシップは、このフェーズにおいては推奨されません。燃えさかる炎上案件においてチームが必要とするのは、出口を探索するよう背中をそっと後押しするような支援型のリーダーシップではなく、最短距離で一刻も早く、出口まで引っ張っていってくれるようなリーダーシップだからです。
このフェーズだと透明性を上げて検査と適応で改善だ!なんて言ってられません。なぜでしょう?それはこの言葉に尽きると思います。

ゆとりのないところに改善はない。

引用:カンバン仕事術

サバイバルフェーズにいるチームに対してリーダーができるアクションは、とにかくチームをそのフェーズから引っ張り出して、チームが学習時間を設けられるよう、ゆとりある状態にすることです。これが実現できると、チームは次の学習フェーズへ向かいます。

学習フェーズ

学習フェーズは、アジャイルの知識がある人にとってはイメージしやすいと思います。自己組織化したチームを目指して、チームがチャレンジするフェーズです。このフェーズのチームに対して推奨されるリーダーシップスタイルは支援型のリーダーシップです。チームは学習フェーズを経て、自己組織化フェーズへと向かいます。

自己組織化フェーズ

いわゆる自己組織化したチームで、このフェーズにおける推奨のリーダーシップスタイルは、自己組織化した状態が維持されるようファシリテートするリーダーシップです。

スクラムマスター視点で大事だと考えた2つのこと

チームのフェーズをよく観察する

正直にいうと、この本を読み始めた時点では、チームの3つのフェーズのことを以下の通り単純化して捉えていて、サバイバルフェーズはアジャイル開発している自分には関係のないことのように感じていました。

  • サバイバルフェーズ:従来型の開発チーム
  • 学習フェーズ:一般的なアジャイル開発チーム
  • 自己組織化フェーズ:理想的なアジャイル開発チーム

でも書籍を読み進めるうちに、チームのフェーズというのはちょっとした要因で変わってしまうものだということが理解できてきました。例えば学習フェーズにいたチームが、ちょっとバックログ消化がうまくいかない時期が続いたことでサバイバルフェーズに戻ってしまったり、自己組織化フェーズにいたチームが、メンバの入れ替わりで学習フェーズに戻ってしまったり。なのでスクラムマスターとしては、常にチームがどのフェーズにいるのかを観察して、その状況に合わせたリーダーシップスタイルを発揮することが大事なのだと思いました。

守るだけではなく、創る

スクラムガイドには、スクラムマスターの仕事として以下の印象的な仕事が掲載されています。

開発チームの進捗を妨げるものを排除する。

引用:スクラムガイド2017

最近以下の通りになりました。

スクラムチームの進捗を妨げる障害物を排除するように働きかける。

引用:スクラムガイド2020

私はこのあたりの記述から、スクラムマスターはチームを守る存在というイメージを持っていました。スクラムマスターが守るものの1つに「予想外の事態に対処するためのゆとり時間(≒バッファ)」があると考えていて、それを守ることは実践してきたつもりです。ただ、そこからさらに一歩踏み込んで「チームが学習・改善するためのゆとり時間を創る」という意識が薄かったことに、この本を読んで気づきました。
これまで私は「学習はプライベートでやるもの」と考えていたのですが、チームとしてハイパフォーマンスを出すためには、今のチームでうまく働くための学習や実験が不可欠で、それはプライベートでは実践できないことなのだから、スクラムマスターが学習・実験のための時間を創るよう、チームや組織に働きかける必要があると考えるようになりました。

SCRUMMASTER THE BOOKとの補完関係

書籍エラスティックリーダーシップの一番の価値が「エラスティックリーダーシップという考え方」であるのと同様、SCRUMMASTER THE BOOKの一番の価値は「#ScrumMasterWayという考え方」だと思っています。私は#ScrumMasterWayを以下の図のようなイメージで捉えています。*1

f:id:sonomirai:20201219125949p:plain
#ScrumMasterWayのイメージ図

私はSCRUMMASTER THE BOOKを読むまで、#ScrumMasterWayのLevel3がスクラムマスターのスコープという意識がありませんでした。ですが#ScrumMasterWayを読んでからは、チームの先にいる組織・会社を意識するようになってきたと思います。こういった気づきを与えてくれたという点で、この本に出会えて良かったです。ただ一方で、自分がこの本に期待していたのは「自己組織化したチームを作るためにスクラムマスターは何をすべきかのヒント」だったので、その点については肩すかしを食らったような印象を受けました。
そんな時に出会ったのが書籍エラスティックリーダーシップだったので、自分がSCRUMMASTER THE BOOKに期待していたことはこっちに書いてあったんだ!と思いました。*2
チームを自己組織化に導くエラスティックリーダーシップと、そこでの経験を組織や会社、社会に広めていくという#ScrumMasterWayを学んだことで、私はスクラムマスターとして常に意識すべきことを以下のイメージで捉えるようになりました。*3
私はこのイメージを、T型人材になぞらえてT型スクラムマスターと心の中で呼んでいます。

f:id:sonomirai:20201219145341p:plain
スクラムマスターとして意識することのイメージ図(T型スクラムマスター)

T型スクラムマスターを意識して仕事をするようになったのはまだ最近のことなので、実践していくうちにイメージは変わってゆくかもしれませんが、今のところT型スクラムマスターを意識した動き方は自分にしっくりきていて、チームや組織の状態を以前よりもうまく観察できるようになった気がします。

おわりに

この記事では、エラスティックリーダーシップという考え方、書籍を読んでスクラムマスター視点で大事だと考えた2つのこと、SCRUMMASTER THE BOOKとの関係、そしてそこから導いたT型スクラムマスターという考え方について述べました。T型スクラムマスターという考え方はこれからも実践するとともに、他の方とも対話していきたいと考えています。

*1:#ScrumMasterWayについて詳しくはこちらをご覧ください。

*2:改めてSCRUMMASTER THE BOOKを読み返すと、5章の「部族としての組織」はエラスティックリーダーシップに通じるものがあると感じますが、この章だけだと具体的なアクションには結びつけられない印象です。

*3:フェーズとモードの使い分けについて補足します。書籍ではチームの状態をフェーズ、それに対するリーダーシップスタイルをモードと定義しています。従って、サバイバルモードとは「サバイバルフェーズのチームに対して、指揮統制型のリーダーシップを発揮すること」と考えると良いと思います。

Cloud Storage Transfer Serviceをコンソールで設定してS3からGCSへファイル転送してみる

Console を使ったデータ転送の作成と管理を見ながらコンソールで転送設定をやってみる

f:id:sonomirai:20201206223050p:plain
設定画面1

f:id:sonomirai:20201206223119p:plain
設定画面2

f:id:sonomirai:20201206223220p:plain
設定画面3

f:id:sonomirai:20201206223409p:plain
設定画面4

f:id:sonomirai:20201206223510p:plain
確認画面1

f:id:sonomirai:20201206223534p:plain
確認画面2

f:id:sonomirai:20201206223559p:plain
実行結果

転送できた。 一回設定すると、その後定期転送スケジュールを変更できない&一回スケジュールを無効化した後、再度有効化できず、再作成するしかないように見えた。
またジョブ作成時の選択項目に「毎日次の時刻に実行」しかなかったので、コンソールからは毎時での実行設定はできないように見えた。

GCSへのファイル格納を契機にCloud FunctionsでDataflowをキックする

はじめに

一つの前の記事で、GCSからBigQueryにファイルを送るDataflowを作った。
前の記事の状態では、Dataflowは手動で起動する必要があり、自動化ができていない。
そこで本記事では、GCSへのファイル格納を契機にDataflowをキックするCloud Functionsを作成する。
GCSからBigQueryへファイルを送るところにCloud Functionsを使う(≒Dataflowを使わない)方式もあるが、この方式だと大きいサイズのファイルを送る場合にCloud Functionsの実行時間の上限に引っかかるリスクがある。
そこで今回はCloud FunctionsからDataflowをキックする。
Dataflowの起動を自動化する方法は、Cloud Functionsの他にApp Engine, Cloud Composer, Compute Engineなど様々な方法があるが、サンプルが多い&学んだことが他にも応用しやすいということで、Cloud Functionsを使う。
ランタイムにはPython 3.8を使う。

Cloud Functionsの設定

f:id:sonomirai:20201031163254p:plain
Cloud Functions設定画面
f:id:sonomirai:20201031163316p:plain
ファンクション設定

from googleapiclient.discovery import build

def execute_dataflow_template(event, context):
    project = <PROJECT_ID>
    job = "trialJob"
    template = "gs://dataflow-templates/latest/GCS_Text_to_BigQuery"
    parameters = {
        "javascriptTextTransformFunctionName": "transform",
        "JSONPath": "gs://dataflow-template-trial/schema.json",
        "javascriptTextTransformGcsPath": "gs://dataflow-template-trial/function.js",
        "inputFilePattern": "gs://dataflow-template-trial/FinancialSample.csv",
        "outputTable": project + ":dataflow_dataset.FinancialSample",
        "bigQueryLoadingTemporaryDirectory": "gs://dataflow-template-trial/tmp",
    }

    dataflow = build("dataflow", "v1b3")
    request = (
        dataflow.projects()
        .templates()
        .launch(
            projectId=project,
            gcsPath=template,
            body={
                "jobName": job,
                "parameters": parameters,
            },
        )
    )

    response = request.execute()

動作確認

  • BigQueryのテーブルのデータを空にするとともに、GCSのFinancialSample.csvを削除する。
    この状態でFinancialSample.csvのアップロードを契機に、 BigQueryにデータが転送されることを確認する。
% gsutil cp ./FinancialSample.csv gs://dataflow-template-trial
Copying file://./FinancialSample.csv [Content-Type=text/csv]...
- [1 files][ 71.4 KiB/ 71.4 KiB]                                                
Operation completed over 1 objects/71.4 KiB.                                     

Dataflowを見るとジョブが走っているのが見えて、BigQueryにもデータが入る。Cloud Functionsのログは以下の通り。

f:id:sonomirai:20201031163843p:plain
Cloud Functionsのログ

おわりに

わかったこと

  • Cloud Functionsのファンクションの引数は、デフォルトで設定されている数(今回だと2つ)にしておかないといけない。引数を使っていなくても
  • Cloud FunctionsのGCSトリガーは、バケットまでしか設定できないので、そのままだと特定のファイルが作成されたタイミングで処理をキックする設定はできなそう

わからないこと

  • 接続を「内部トラフィックのみを許可」に設定する際は、認証の設定をしないといけない気がするが、そこはやっていない
  • Goでのファンクションの書き方(Pythonのサンプルが多かったからそっちでやった)

参考URL

DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)を触ってみる

2020/10/31追記 DataflowのUDF(function.js)を行削除と現在日付をカラム追加する内容に更新


はじめに

GCSからBigQueryにCSVを送ってテーブルを作成するに当たり、DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)が使えそうだったので触ってみた。
結論から言うと、ちょっと触った限りではDataflowのCloud Storage Text to BigQueryテンプレート(バッチ)の良さがわからなかったが、やったことを記録しておく。
なお私はこの記事を書いている時点ではDataflowのドキュメントをほぼ読んでおらず、Dataflowのことを全然分かっていない。
とりあえず動かしてみたという程度で、DataflowやGoogle提供のテンプレートについて誤解があるかもしれないので、その点に留意してほしい。
使ったファイルはGitHubリポジトリにまとめてある。

流れ

  • インプットとなるデータの準備
  • BigQueryセットアップ
  • GCSセットアップ
  • Dataflow実行

インプットとなるデータの準備

今回はMicrosoftが公開している財務サンプルデータを利用する。様々な型のデータがそれなりの量用意されているので、サンプルとしていい感じなので。Power BI 用の Excel の財務サンプル ブックのダウンロードからFinancial Sample.xlsxをダウンロードしてCSVに変換する。この時、フォーマットによっては価格欄に「$」が入ったり、3桁区切りの「,」が入って後々扱いづらいので注意する。Macのnumbersで編集する場合は、セルを全選択した上で、画面右のフォーマットのセルでデータフォーマットを数字にして、3桁区切りのチェックボックスをオフにすると良い。また1行目のカラム名の行も使わないので削除する。ファイル名はFinancialSample.csvとする。

BigQueryセットアップ

データセット作成

適当にデータセットを作成する。ここでデータセットはdataflow_datasetとしている。
入力

bq --location=asia-northeast1 mk \
--dataset \
--default_table_expiration 0 \
--default_partition_expiration 93600 \
--description "" \
<PROJECT_ID>:dataflow_dataset

出力

Dataset '<PROJECT_ID>:dataflow_dataset' successfully created.

スキーマ作成

スキーマ準備は面倒。とにかく手間かけず進めたいので、BigQueryのスキーマ自動検出機能を使ってスキーマを作成する。コマンド打つ時点でテーブルはなくても大丈夫。
入力

bq --location=asia-northeast1 load --autodetect \
--source_format=CSV \
<PROJECT_ID>:dataflow_dataset.FinancialSample \
~/Downloads/FinancialSample.csv

出力

Upload complete.
Waiting on bqjob_r1520ec4b3b8ef942_000001755d6471f2_1 ... (1s) Current status: DONE 

なおここで欲しいのはスキーマだけなので、スキーマ作成後にTRUNCATE TABLE dataflow_dataset.FinancialSample;でデータは削除しておく。 Cloud Storage Text to BigQueryテンプレートを利用するためには、BigQueryのスキーマを後述の2箇所で利用する必要があるため、自動検出されたスキーマJSON形式で出力する。
入力

bq show --schema --format=prettyjson dataflow_dataset.FinancialSample

出力

[
  {
    "mode": "NULLABLE",
    "name": "Segment",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "Country",
    "type": "STRING"
  },
〜中略〜
  {
    "mode": "NULLABLE",
    "name": "string_field_16",
    "type": "STRING"
  }
]

こうして出力したスキーマは以下2箇所で利用する。スキーマをどこで必要になるのかわかりづらくて混乱したので、ここで記しておく。詳細は後述。

  • GCSにスキーマ情報を格納して、Cloud Storage Text to BigQueryテンプレート利用時に指定する

  • Cloud Storage Text to BigQueryテンプレート利用時のUDF内でJSONのキーとして利用する

とりあえずこれでBigQUeryセットアップは終わり。

GCSセットアップ

バケット作成

dataflow-template-sandboxという名前でバケットを作成する。

コマンド

gsutil mb -p <PROJECT_ID> -c STANDARD -l ASIA-NORTHEAST1 -b on gs://dataflow-template-template

出力

Creating gs://dataflow-template-sandbox/...

ファイル格納

作成したバケットには以下を格納する。

  • BigQueryに突っ込むデータ。ここではFinancialSample.csvとする。これは作成済み
  • BigQueryのスキーマ。ここではschema.jsonとして、この後作成する
  • UDF用のJavaScript。ここではfunction.jsとして、この後作成する
  • DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)実行時に吐き出される中間ファイル。Dataflow実行時にフォルダを指定するだけでよい。(そのディレクトリがなくても作ってくれる。)

BigQueryのスキーマ作成

先ほどBigQueryから出力したJSON形式のスキーマをBigQuery SchemaというJSONオブジェクトにする。(なぜ出力したスキーマがそのまま使えないのか。。。管理しづらい。。。という気はするが。)

{
  'BigQuery Schema': [
    {
      "mode": "NULLABLE",
      "name": "Segment",
      "type": "STRING"
    },
    {
      "mode": "NULLABLE",
      "name": "Country",
      "type": "STRING"
    },
  〜中略〜
    {
      "mode": "NULLABLE",
      "name": "string_field_16",
      "type": "STRING"
    }
  ]
}

UDF用のJavaScript作成

UDFでは、BigQueryに突っ込むCSVを、スキーマ名をキーとしたJSONに変換して返却する必要があるらしい。BigQueryにはCSVをそのままインポートする機能があるのに、なぜ途中でJSONに変換する必要があるのか。。。別にUDF内でちょっとデータ加工する分にはCSVのままでもいい気がするが。。。よくわからない。
CSVだとDateは1/1/14のフォーマットになっていてBigQueryに格納できないので、UDFの中で2014-1-1のフォーマットに変換しつつ、CSVJSONに変換していく。
また試しに、ContryがGermanyだったら行を削除する処理、string_field_16カラムに現在日付を設定する処理も追加する。(2020/10/31追記)

function transform(line) {
  var values = line.split(',');
  var obj = new Object();
  obj.Segment = values[0];
  obj.Country = values[1];
  obj.Product = values[2];
  obj.Discount_Band = values[3];
  obj.Units_Sold = values[4];
  obj.Manufacturing_Price = values[5];
  obj.Sale_Price = values[6];
  obj.Gross_Sales = values[7];
  obj.Discounts = values[8];
  obj._Sales = values[9];
  obj.COGS = values[10];
  obj.Profit = values[11];
  var date = values[12].split('/');
  obj.Date = '20' + date[2] + '-' + date[1] + '-' + date[0];
  obj.Month_Number = values[13];
  obj.Month_Name = values[14];
  obj.Year = values[15];
  var dt = new Date();
  var insert_day = dt.getFullYear() + '-' + (dt.getMonth()+1) + '-' + dt.getDate();
  obj.string_field_16 = insert_day;
  var jsonString = JSON.stringify(obj);
  if (obj.Country == "Germany") {
    return null
  }
  return jsonString;
}

GCSに格納するファイルの準備ができたので、FinancialSample.csvとschema.jsonとfunction.jsを格納する

gsutil cp ./FinancialSample.csv gs://dataflow-template-trial
gsutil cp ./schema.json gs://dataflow-template-trial
gsutil cp ./function.js gs://dataflow-template-trial

Dataflow実行

準備ができたので、Dataflowを実行する。
入力

gcloud dataflow jobs run trialJob \
    --gcs-location gs://dataflow-templates/latest/GCS_Text_to_BigQuery \
    --parameters \
javascriptTextTransformFunctionName=transform,\
JSONPath=gs://dataflow-template-trial/schema.json,\
javascriptTextTransformGcsPath=gs://dataflow-template-trial/function.js,\
inputFilePattern=gs://dataflow-template-trial/FinancialSample.csv,\
outputTable=<PROJECT_ID>:dataflow_dataset.FinancialSample,\
bigQueryLoadingTemporaryDirectory=gs://dataflow-template-trial/tmp --region=asia-northeast1

出力

createTime: '2020-10-25T14:54:52.699960Z'
currentStateTime: '1970-01-01T00:00:00Z'
id: 2020-10-25_07_54_50-9162729669340431769
location: asia-northeast1
name: trialJob
projectId: <PROJECT_ID>
startTime: '2020-10-25T14:54:52.699960Z'
type: JOB_TYPE_BATCH

CLIの戻り値だと成功/失敗はわからない?コンソールで成功していること、BigQueryに確かにデータが格納されていることを確認する。(BigQueryに挿入される順番はCSV通りの順番ではないっぽい)

f:id:sonomirai:20201026002751p:plain
dataflowのjob成功画面
f:id:sonomirai:20201031014327p:plain
BigQueryのプレビュー画面

おわりに

わかったこと

  • DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)の動かし方
  • Dataflowのデバッグの仕方
  • Dataflowはコンソールだとできない操作方法が多いっぽいということ
  • DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)で指定するJavaScriptのUDFは、BigQueryのUDFとは役割が違いそうなこと
  • GCS上のtmpバケットは処理がコケると残って、成功すると削除される
  • そもそもDataflowのCloud Storage Text to BigQueryテンプレート(バッチ)はβ版

わからなかったこと

  • Dataflowのジョブの操作方法(停止や更新など)
  • Dataflowのジョブ(バッチ)は、バッチということだけど時刻の設定箇所がわからなかった。そういう類のものではない?
  • GCSのデータが更新されたらどのタイミングでBigQueryのデータが更新されるのか?そもそも更新されるのか?更新時は追記されるのか?上書きされるのか?
  • Dataflow全般(DataflowのCloud Storage Text to BigQueryテンプレート(バッチ)を動かしたくらいではDataflowのことはわからないことがわかった笑)

参考サイト

クネビンフレームワークとステークホルダの期待値コントロール

9/14更新 9/11にScrum Masters Night!でこのブログをネタにディスカッションさせていただいたので、その内容を踏まえて全体的に改訂


はじめに

ソフトウェア開発が扱うのはクネビンフレームワークの煩雑系(Complicated)と複雑系(Complex)で、アジャイル複雑系に向くという話をよく聞くが、個人的には煩雑系もアジャイルでやればいいのでは?と思っていた。
しかし最近、ステークホルダの期待値コントロールという観点で考えると複雑系アジャイルを導入するより、煩雑系にアジャイルを導入する方が骨が折れるということに気づいたので、記事に残しておく。*1

スクラムの成果のステークホルダへの見え方

クネビンフレームワークの煩雑系と複雑系を雑に言い換えると、煩雑系は(どうやるかはさておき)やればできる領域、複雑系はやってみないとわからない領域と言い換えられると思っている。
アジャイルだと開始時点で「いつまでに、何を」は約束できず、やりながら徐々に見積の精度を高めていくので、例えば半年とか一年とか、ステークホルダが気にするタイミングでのアウトプットとしては、「(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積」ということになる。
スクラムを導入する際には、あるタイムボックスで見たときのスクラムの成果が「(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積」になることをステークホルダに説明し、納得してもらう必要がある。ではこの情報が、複雑系のステークホルダと煩雑系のステークホルダの目にどのように映るかを考えてみる。

複雑系のステークホルダの場合

スクラムを一定期間実践すると得られる成果(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積複雑系のステークホルダの目にどう映るかというと、これは価値ある情報として映るものと思われる。なぜならやってみないとわからない領域について、継続するにせよ撤退するにせよ、半年後には何らかのジャッジができるようになるからだ。なので複雑系の場合、ステークホルダへの説明は割とすんなりいくものと思われる。

煩雑系のステークホルダの場合

次に煩雑系の場合を考える。複雑系のステークホルダには価値があった(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積が、煩雑系のステークホルダにとって同じように価値を持つかというと、そうではないと思う。
なぜなら煩雑系のステークホルダは、煩雑系のプロダクトはやればできることはわかっているので、あとはいつ完成するかだけが知りたいと思っているからだ。
(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積は、ともすれば未完成の機能と、開発初期には出てこなかったのに今更出てきたスケジュールに見えてしまい、いつ完成するのかを気にしているステークホルダからすると、期待外れと思えてしまうのだ。

煩雑系にスクラムを導入するためにはどうすればよいか

上記で説明した通り、一定期間後の成果物という観点だけでステークホルダと話をすると、スクラムを導入するメリットがステークホルダには伝わらないので、スクラムを導入する側としては、スクラムの導入により、従来型の開発プロセスと何が変わるかをステークホルダに説明し、納得してもらう必要がある。例えばスクラム導入によるステークホルダのメリットには以下がある。

  • 開発後期でも追加要望を出すことができる
  • 紙の進捗資料ではなく動くモノとして進捗を確認できる

おわりに

本記事では、複雑系アジャイルを導入するより、煩雑系にアジャイルを導入する方が骨が折れる理由として、煩雑系のステークホルダにとっては、スクラムの成果である「(優先順位が高い順に実装した)いくつかの動く機能と今よりも精度のいい見積」の価値が感じづらいこと、そのような場合にスクラムを導入するためには、ステークホルダにどんな説明をする必要があるかを述べた。

*1:実際のところあるプロダクトが煩雑系か複雑系かなんてわからないので、スクラムチームおよびステークホルダが対象とするプロダクトをどのように捉えているかが重要となる。この記事は、スクラムチームおよびステークホルダの間で、対象とするプロダクトが煩雑系と複雑系のどちらに該当するかは、共通認識が持てていることを前提として記載している。

TDDワイワイ会その32参加レポート

はじめに

3/1にTDD+モブプログラミングでワイワイする会 その32に参加してきた。 スクラムマスターとして案件に参画することが多いが、XPの開発プラクティスの実践経験に乏しく困ることがあったので、手を動かして実感を掴みたいと思ったのが参加の動機。 この記事では「イベントの流れ」、「モブプロについての学び」、「TDDについての学び」の3項目で、イベントをふりかえる。

イベントの流れ

  • 最初にイベント全体の説明があった。
    f:id:sonomirai:20200303205349j:plain
    当日の様子(@miholovesqのTwitterから拝借)
  • この日の参加者は12名だったので、4人チームを3つ作った。得意な言語でチーム分けするのかと思っていたが、そういうわけではなかった。
  • チームごとに別れてから改めて自己紹介をして、今回使う言語と誰のノートPCを使うかを決めた。
  • 次に使用する言語の選択。メンバの得意な言語はRubyJavaだったが、みんなが知らない言語の方がモブプロ の力を体感できるということで、使用する言語にはあえてPythonを選んだ。(テストフレームワークはpytest)
  • 最後にコーディングの題材をcyber-dojoから選んだ。
    • 前半戦はFizzBuzzをやった。実際に私のチームがやった軌跡はここから見れる。(いつまで見れるのだろう。ずっと見れるのかな?)
    • 後半戦はHally Potterという題材をやった。Hally Potterはあまり関係なくて、シリーズ物の書籍を複数冊購入した際の最適な割引率を算出する問題。チームの軌跡はここ。難しかった。とりあえず実装は始めたものの途中で行き詰まって、ホワイトボードで実装イメージについてディスカッションして、コーディングを再開したあたりでタイムアップになってしまった。
  • 最後にイベント全体をふりかえって、片付けをして、イベントは終了となった。

モブプロ についての学び

  • 楽しい
    • スキル面で不安があって、実際足を引っ張ってしまう場面もあったが、モブプロだとフォローしてもらいつつ進めることができるので、いたたまれない想いはしなかった。それよりも「楽しい」の気持ちの方がずっと大きい。
    • TDDワイワイ会は「テストが落ちると思って落ちた時」「テストが通ると思って通った時」はワーと拍手をすることになっていて、これも大いに場作りに貢献していた。
    • 逆に「テストが通ると思って落ちた時」はみんないっせいにガタッ!となってエラー原因の特定に努めた。この一体感。これはこれで楽しかった。
  • ドライバーはYouTuberのように声を出しながら手を動かすのが大事
  • 可能なら椅子は人数分+1つ用意するとよい
    • 人数分だと毎回ほかのメンバとの入れ替わりが発生してしまうため)
  • 可能ならノートPCは人数分+1つ用意するとよい
    • 他の人のPC触るのはけっこう心理的なハードルが高いことに気づいた。あと時間が経つとロックがかかってしまう。。。いちいち解除してもらうのもリズムを崩してしまう。
  • リモートでモブプロするときはVS CodeのLiveShare機能がけっこういい感じというのをメンバに教えていただいたので、今度使ってみたい
  • TDDワイワイ会のページにも貼ってあるMob Programming Startup Manualがモブプロの資料としてとても参考になった。

TDDについての学び

  • 事前にt_wadaさんのFizzBuzzを題材にしたTDDのライブコーディングの動画を見て「歩幅の調節」を知識として知ってはいたが、実感がなかったので、そこを体感できたのはとても良かった。今回は初対面のメンバでモブプロしたので丁寧にやったが、業務にTDDを取り入れて慣れてしまえば、基本は明白な実装を前提として実装を進めて良いのかなと思った。

  • すぐに実装イメージが合わないような難しい題材を扱う際、ホワイトボードを使った設計とTDDでの設計を、どうバランス取りながら進めるかというのは、難しい問題だと感じた。ここは経験を積んでバランス感覚を養うしかない気はするので、またTDDワイワイ会に参加して、"筋トレ"させてほしいと思った。

さいごに

イベント運営が大変な社会の状況の中、対策を講じた上でイベントを開催してくださった運営の皆様に感謝します。またぜひ参加したいと思います。

スクラム初心者お悩み相談参加レポート

はじめに

1/28(火)にアジャイルチームを支える会主催の「スクラム初心者お悩み相談」に参加した。(募集サイト
悩み相談は、参加者の持ち寄ったスクラムの悩み事について、標準5分〜最大20分で対話するという形式だった。
参加者は8名だった。冒頭のアンケートでスクラム実践前の悩みを抱える3名、スクラム実践中の中身を抱える5名でグループに分かれた。そこへ各2名の相談員の方に参加いただき、計5名のグループと7名のグループで対話をした。
私はスクラム実践前の悩みを抱えるグループに参加した。対話の時間はおよそ1時間で、この間に5個くらいのトピックについて対話をした。
いずれの悩みも共感せざるを得ない悩みで、相談員の方のコメントもとても参考になった。
ここではその中から、私が一番聴きたかった、QAチームとの連携に関する悩み相談と相談結果を共有する。

f:id:sonomirai:20200129091914j:plain:w400
私が相談したQAチームとの連携についての悩み

悩み

上記のポストイットを説明する際に、口頭で説明した内容を補足すると、悩みは以下の通り。

相談結果

参加者の方、相談員の方と対話させていただき、自分の中では悩みは解消した。(とりあえず次の一歩を踏み出せそうという感触を持てた。)

対話した内容と、それを受けて考えたことをまとめると以下の通り。

  • 従来のQAチームが何をしているのかを理解することは次の一歩を踏み出すために大事なので、資料を展開してもらうなり、対話をする必要がある。
    • QAチームがウォーターフォール案件を見るときにどんな営みをしていたかは、スクラム案件には関係ない気がしており、資料の展開をしてもらう必要はないかと思っていたけど、ウォーターフォール案件のQAで何を担保しようとしていたかを理解することは非常に重要だと、対話を通じて考え直した。
  • QAチームのメンバ(例えばモチベーションの高い若手など)を自分たちの案件にステークホルダの位置付けでアサインしてもらい、一緒に品質保証に向けた取り組みを進めるのは効果的。(その後スクラム案件が拡大することを見越すと、試験項目の内容を見てもらったり、完了の定義を一緒に検討するのも良さそう。)
  • QAチームと話す際は、ウォーターフォール案件かスクラム案件かという観点で話す必要はない。「お客様に価値を早く提供するためには、どう連携できるか?」という観点で話をした方が良い。
    • 悩みのところに「スクラムの話をしていても品質の話は出てこない」と書いたけど、それは当たり前で、品質保証というもののはウォーターフォールスクラムかという案件特性とは関係なく守らねばならないものだからだ。なのでQAチームにスクラムの話をしてもあまり意味はない。それより、QAチームがクオリティゲートを設けていることで価値の提供速度が下がってしまうという課題を取り上げて、その課題をどう解決することができるかを話し合ったほうが建設的な議論ができるということだった。めちゃめちゃ納得した。
  • 早い段階で成果物を見せてもらうというのは、QAチームにとっても嫌な話ではない。最後の最後に品質の低い成果物を持ってこられて打つ手なし、となるよりは、早い段階で品質の低い成果物を見て早めにその旨をフィードバックをする営みをしたほうがお互いによい。こういった営みをする時、実はQAチーム側としては対応稼働は従来から増えない。それに対してスクラムチーム側は、QAチーム用の環境を構築してメンテする必要があるので、対応稼働は増えるので、そこはスクラムチームが頑張る。
    • このあたりも実践しないとわからない知見だと思う。教えていただけて大変有難かった。

悩み以外の対話内容

上記の悩みに関連して、調査する中で気になったことを2点伺ってみた。

スクラム案件が増えた際にQAチームがボトルネックになる懸念ついて

  • QAチームがスクラムチームに寄り添う(≒各スクラム案件に担当者をアサインしてサポートする)事例は素晴らしいと思うが、スクラム案件が増えると、QAチーム側がボトルネックになるというリスクはある?
    • スクラムチームが成熟して毎回安定した品質の成果物を提供することができるようになった結果、QAチームが「品質保証のために入り込む必要はない、スクラムチームの判断でリリースして問題ない」となった国内事例がある。
      • その事例を踏まえると、QAチームはスクラムチームの立ち上がりの際に寄り添ってサポートして、スクラムチームの十分な成熟を見届けて、QAチームのところから卒業させるような世界観がありうる?
        • これは結構な理想論で、従来型のQAチームがそこまで変われるかは難しいところ。QAチームの営みが従来の品質保証から発展して、QAトレーナーとしてスクラムチームの指導ができるところまで行かないと、この世界観は実現されない。

海外事例について

  • アジャイル関連の書籍を見ると、基本的にはスクラムチームがリリースの判断をすべきとある。「スクラムチームでリリースの判断ができる」というのは、海外だと元々QAを専門としていたメンバが開発チームの一員となっていて、品質保証に人一倍の責任を持っているから成り立っているのではないか?と仮説を立てたのだが、海外事例などご存知か?
    • その側面もあるかもしれないが、大切なのはその場合でもリリース判断しているのは、QAの専門家ではなく、スクラムチームだということ。
      • 質問の背景として、日本の開発現場だと、チームにQAの専門家がいるのではなく、QAの組織が別にあり、そこがリリース判断に関与するので、日本の開発現場って、海外に比べて品質保証の意識が薄いのでは?という仮説を持っている。(この仮説が全くもって違うかもしれない。) そうした時に、品質保証について意識の薄いスクラムチームが「アジャイルだとクオリティゲートは設けず、チームでリリース判断するんですよー。それが普通ですよー。」みたいな形で上位層を言いくるめてリリースして、結果として故障が出て、上位層が「アジャイル駄目じゃん」みたいになってしまわないかという懸念があったので聞いてみた。 「アジャイルになってQAチームの役割は変われど、QAチーム自体はなくならないと思う。」とおっしゃっていた相談員の方もおり、自分もそんな気がした。

おわりに

品質保証という難しい悩みについて、相談会でここまで色々な学びを得られるとは思っていなかったので、本当に有難かった。悩み相談にのってくださった相談員、参加者の皆様、ありがとうございました。