「アジャイルコーチとスクラムマスターの集い」に参加してきた

はじめに

9/12-14で「アジャイルコーチとスクラムマスターの集い」に参加してきました。 www.attractor.co.jp

私は初めて参加しました。私以外にも初参加の方は何名かいましたが、全体としては2回目、3回目の参加の方が多い印象でした。
開催場所はライムリゾート箱根という箱根のめちゃめちゃ快適な合宿用施設です。 バスタ新宿からバスで1本で行けるというのも楽で良かったです。

参加の目的・背景

3日間OSTなどを活用して研鑽するというプログラムを見て「これ絶対参加しないとわからないやつだ。」と思い、申し込みました。
申し込んだ時はこの営みのことをよく分かっていなくて*1、過去の回に参加された方は参加しないものだと思い込んでいたので、申し込んだ後、過去回の写真に写っていたコーチの方々も参加されると知り、ミーハー気分で高まりました。(漫画「ミワさんなりすます」のミワさんはこんな気分なんだろうなぁと妄想しました。)
その一方で「憧れは理解から最も遠い感情だよ」と心の中で藍染惣右介が囁くので、今回コーチの方々とお話しすることで、コーチの方々がアジャイルとどう向き合ってきたのかを理解したいと考えていました。

参加した感想

参加者の皆様とOSTで色々な話を聞いたり、自分の出したテーマについて話し合ったり、散歩しながらお話ししたり、温泉入りながらお話ししたり、美味しいビールを飲みながらお話ししたりできて、最高に楽しかったです。何年経ってもこの3日間を忘れないと思います。
特に良かったのは、自分がアジャイルに携わり始める前のお話を聞けたことと、OSTでテーマを2つ出して、それについて話し合ったことなので、これらについて述べます。

アジャイル黎明期のこと

私はDXを推進するという文脈の中で2018年からアジャイル開発に携わり始めたので、それ以前のアジャイルの黎明期のことが分からなかったのですが、そのあたりを色々なコーチの方々にお伺いして、理解を深められたことが良かったです。
特に「アジャイル開発宣言」が出たときにどう感じたか?を、何名かの方にお伺いして、「共感した」や「ふわっとしたことを言っていると思ったというのが第一印象」といった、その時の感想を教えてもらえたことが良かったです。(「アジャイル開発宣言」は今だと原典として扱われていて、それがなかった時代や出た瞬間を想像できないので。)
その他にもコミュニティや研修、書籍についても色々お伺いできて、コーチの方々がどういった姿勢で仕事に臨んでいたり、コミュニティに貢献されているのかをお伺いできました。
ただまだまだ聞き足りないので、コミュニティ活動などを通して色々な方にお話をお伺いし、ゆっくり理解していきたいです。

OSTテーマ1【観察できているのか?】

テーマを出した背景

以前参加した観察力がテーマのワークショップで、人々の行き交うバス停の様子を収めた動画を見て、観察したことを書き下すというワークを実施しました。
私はSMとしてチームを観察しているつもりだったので、このワークでも成果を出せると思っていたのですが、蓋を開けてみると、[ 1 ]記述量は一番たくさん書けていた人の1/5程度、[ 2 ]多くの方が気づいていた「人々の様子を見るに、バス停の文字盤が見づらい可能性が高い」というポイントにも気づけていないという散々な結果でした。
SMはチームを観察して得た情報をインプットに次のアクションを判断するので、観察できていないポイントがあったということは、少ない情報量で次のアクションを決めていたことになり、これにより質の低い判断をしていた可能性があると感じ、怖くなりました。
そこでこのセッションでは、他のコーチの方々は何をもって観察できていると考えているのか、また観察力を鍛えるために意識していることをお伺いしたいと思いました。

書き留めた付箋たち

受け取ったアドバイスと今感じていること

まず学生時代人類学を専攻していたという石井食品の石井さんに「観察は人類学でも大きなテーマになるものだが、人は先入観で見るもの、見ないものを取捨選択しているので、そもそも全てを見るすることはできない」と大前提となるコメントをいただき、その上で「チームで見たものを持ち寄って、対話する方法もある。」とアドバイスをいただきました。
このアドバイスをいただいた時、「観察はSMの重要な役割だから、自分が高いレベルでやり遂げる必要がある」という考えに自分が囚われていたことに気づき、自分が山王戦のゴリの状態に陥っていたんだと気づきました。

おそらく現段階でオレは河田に負ける でも 湘北は負けんぞ

というやつです。自分ひとりで達成できないことがあるなら、周りの力を借りて、チームとして判断の質を上げていけばいいだけ、と気づけました。

また「観察できている/できていない、より重要なことは、観察などを通して得たインサイトを頭の中でどう構造化するか。観察もインサイトを構造化するためのインプットの1つに過ぎない」というアドバイスをいただきました。
「観察もインプットの1つに過ぎない」という点については、最近はトライアンギュレーション*2を意識して様々な人の話を聞いたり、成果物を見たりして判断をするよう心がけているところだったので、これを継続します。「インサイトの構造化」は今まで意識していなかったので、これから意識します。

OSTテーマ2【SMはチームに「プロセスより対話」をどう伝えればいい?】

テーマを出した背景

私はSMはアジャイルスクラムの価値観を理解した上で、それを示す行動を率先して行い、その背中をチームに見せることが重要だと考えて、そのようにふるまっているつもりでした。特に「プロセスやツールよりも個人と対話を」は強く意識して、DEVが最初の一歩を踏み出せないところのサポートやPOの困りごとの相談・対応には注力してきたつもりでした。
しかし自分がSMの任を外れてチームの外に出た後にチームを観察すると、「スクラムだと◯◯だから」とスクラムが都合のいい言い訳に使用されるシーンや、「これはPOの役割」「これはSMにやってほしい」「これはDEVよろしく」などセクショナリズムの兆候を示すシーンが頻繁にあることに気づきました。
私はスクラムもプロセスでしかないので、価値あるプロダクトを開発するため、チームのお互いの状況に関心を寄せた上で、自分たちに最適なプロセスを対話を通して探索してほしいと思っていましたが、そういった想いはチームに全く伝わっていなかったのです。
この経験を通して、背中を見せることでアジャイルスクラムの価値観までチームに伝えられると考えるのはSMに都合の良い幻想で、背中を見せる以外の方法で、アジャイルスクラムの価値観をチームに伝える必要があると思ったので、参加者の皆さんがこの辺りをどう意識されているかを伺いました。

書き留めた付箋たち&様子

受け取ったアドバイスと今感じていること

「現場の細かい話をすると拠り所がなくなってしまい「これはPO」みたいな結論になりがちなので、『なんでプロセスより対話が大事なんだと思う?』と問いかけたり、『逆に対話よりプロセスを大事にするとどうなるでしょう?』と問いかけて嫌なことを書き出すと良い」というアドバイスをいただきました。私は現場の細かい話からスタートをして、結果としてチームが腹落ちする結果に辿り着けないこともあったように思うので、これはぜひ実践したいと思いました。
また「背中を見せるだけだと、チームからはSMが選択しなかった行動が見えず、その判断基準が分からないので、判断基準をチームに示す必要がある。その上で、意図が伝わっているか直接メンバに確認するような営みは必要」というコメントもいただきました。このコメントをくださった方は、この3日間折を見て「何を学びましたか?」など様々な問いかけをしてくださって、「伝わっているか確認する」というコメントを背中で示してくださっていたと、今ふりかえって感じます。
スクラムはゴールではなくゲート。スクラムの先に自分たちの目指すべきスタイルがあるとチームに伝える必要がある」というコメントもいただきました。スクラムがゴールではないということは理解していたつもりですが、果たしてそれをチームに伝えて、スクラムの先にある自分たちにあったスタイルをメンバみんなで目指せていたかというと、そうではなかったので、今後はスクラムのその先を目指します。スクラムの先にゴールがあるという意識をメンバみんなで持てれば、会話は「スクラムだと◯◯だから」で止まらず、「スクラムだと◯◯だよね。これは何でだろう?自分たちはどうすべきだろう?」というところまで踏み込めると思うので。
さらに「背中を見せる行為自体は尊いことで、それをしなくなると理論だけ、口先だけの存在になってしまうので、背中を見せる行為は続けた方が良い」という励ましのコメントもいただきました。この時自分は、背中を見せる行為はプラクティスレベルを伝えるためには有効でも、価値を伝える上では有効に機能しないような気持ちになっていました。このコメントをいただいたことで、背中を見せる行為の問題ではなく、自分がまだ上手に背中を見せる行為ができていないことが問題で、そこを改善していけば良いのだと気づけて、めちゃめちゃ勇気づけられました。
この3日間ずっといい体験をさせてもらいましたが、自分の心が一番震えた瞬間を選ぶとしたらこの時だと思います。

最後にちょっと余談で、帰り道で高江洲さんとお話しさせていただいた時、2年前に参加したアジャイルマインド・インストレーション体験セミナーの話になりました。(参加レポート:アジャイルマインド・インストレーション体験セミナー参加レポート - 其未来
このセミナーの中で、高江洲さんが考案された「スクラム・ペルソナ・ロールプレイ」というワークショップを実施していたのですが、今思うと、このワークショップの内容は今の自分の困りごとにドンピシャで刺さる内容でした。
すごくいいワークショップだったと記憶しているのに、必要なタイミングで頭の引き出しから引き出せなかった理由は一つで、教わったところで止めてしまって、自分でワークショップを開かなかったからです。参加レポートの最後にこう書いているのに。。。

ぜひ組織に持って帰ってほしいということだったので、折を見て自社でもロールプレイをやってみたいと思う。

自分でやらないと身につかないと強く感じたので、このワークショップを今年中にやるとともに、OSTでいただいたアドバイスは明日からどんどん実践しようと心に決めました。

おわりに

学びの一部を書いただけですが、それでも長くなりました。それくらい濃密な3日間でした。
主催のアトラクタの方々をはじめ、集いに参加された全ての方々に感謝します。本当にありがとうございました。
最後に集合写真を貼るとそれっぽいと思うのですが、私なんと呑気に部屋の片付けをしていて、集合写真に写り損ねるという失態をおかしたので、集合写真は載せません。
集合写真に写るという忘れ物を取りに行くためにも、次回も参加したいです。

更新履歴

9/17 10:00 石井さんのお名前と「スクラムはゴールではなくゲート。」の段落を追記

*1:その後このイベントはコーチングリトリートとも呼ばれ、リトリートは「日常生活から離れてリフレッシュする時間をもち、心身ともにリセットする」という意味と知り、やっとイベントの趣旨が理解できました。

*2:複数の視点(データ、調査者、方法、理論など)を組み合わせることで、物事の理解の妥当性をより高めること

Vue.jsでブックマークツール「Quick Bookmark」を作った

はじめに

この記事はVue Advent Calendar 202120日目の記事です。
ちょこちょこ作っていたツールの開発をアドベントカレンダー駆動で加速させ、とりあえず紹介するところまで持ってきました。
この記事では前半でツール自体の紹介、後半でツールの技術面の紹介をします。

f:id:sonomirai:20211220081329p:plain
Quick Bookmark

Quick Bookmarkについて

エレベータピッチ

Quick Bookmarkの価値を、アジャイル界隈でよく使われるエレベータピッチのフォーマットでまとめました。

資料のリンクを見失って、メールやチャットを掘り返すのを何とかしたいユーザ向けの、  
Quick Bookmarkというプロダクトは、ブックマーク用のツールです。  
これはブックマークを端末内に保存し、保存したリンクを絞り込み検索できます。  
はてなブックマークやPocketといったブックマーク用のサービスとは違って、  
ブックマークを端末内に保存するので、社内ファイルサーバのパスを保存しても問題ありません。  
Proxy環境下でも利用できます。  
ブラウザのブックマーク機能と違って、絞り込み検索ができるので、ブックマークが増えた時も探しやすいです。

触ってみる

こちらからQuick Bookmarkを触ることができるので、まずは軽く触ってみてください。
ブックマークを登録できます。Quick Bookmarkは登録したブックマークを端末のlocalStorageに保存するので、ブラウザを閉じた後もブックマークは消えずに残ります。端末に保存するので、インターネット上の誰かにあなたが登録したブックマークの内容を見られてしまうこともありません。

デモ

デモ用のGIF動画を作成したのですが、はてなブログに貼れなかったので、こちらの下の方に貼り付けています。もしよければご覧ください。

Quick Bookmarkの技術面について

利用技術

Quick Bookmarkで利用している技術は以下の通りで、導入順に並べています。

利用技術 利用シーン
Vue.js 全体
vue-good-table 「ブックマーク絞り込み検索」の表で使っています。多機能の上に、自分で定義した関数を実行することもできてとにかく便利です。削除やソートはまんまvue-good-tbleの機能です。
wanakana ひらがなとカタカナが異なっていても検索ヒットさせるために利用しています。
Puppeteer 動作確認テスト用に追加して、GitHub Actionsでテストが回るよう設定しましたが、vue-router導入時に既存のテストコードが壊れてからは、直せていません。
vue-router 機能ごとにページを分割するために導入しました。
vuetify 見栄えを良くするために導入しました。

Vue.jsの良いところ

ツールを作っていて感じたVue.jsの良いところを述べます。Angular.jsやReact.jsなどの他のJSフレームワークと比べる意図はありません。
冒頭述べたように、私は普段コードを書かないのですが、そんな自分でも、欲しいものを作れてしまうのがVue.jsのすごいところだと思うので、その辺りを中心に述べます。

日本語情報が多い

2016年にAngular.jsの1系で、Quick Bookmarkとほぼ同じlocalportalというツールを作っていたのですが、その当時は分厚い本が1冊出版されているだけで、初学者が勉強するのはしんどい状況だったので、Udemyか何かで英語のレッスン動画を見ながら、Angular.jsの機能を覚えていた記憶があります。(もちろん今はAngular.jsの日本語情報もたくさんあるのでしょうが、当時は大変だった印象があります。)
Vue.jsは日本語の公式情報もあるし、基礎から学ぶ Vue.jsVue.js入門をはじめとした書籍も充実しているので、同じ機能を様々な解説・サンプルコードを見ながら学習することができ、理解がしやすかったです。

利用者が多く、コミュニティも活発

私は2018〜2019年頃に、秋葉原のWeeybleというコワーキングスペースでVue.jsの書籍の輪読会に参加して勉強することで、Vue.jsを覚えていきました。(当時の資料
この勉強会でVue.jsを勉強していなかったら、このツールは作れていなかったと思うので、この場を提供してくれた方や、Vue.jsを現場で利用してVue.js人口を増やしている方に感謝します。

プログレッシブフレームワークゆえVue.jsの技術習得と機能追加がいい感じに回る

以下は、v0.1.0時点のQuick Bookmarkの画面です。1つの画面に全機能が詰め込んであって、見た目も質素ですが、今と基本的な機能は変わりません。

f:id:sonomirai:20211219232038p:plain
v0.1.0時点のQuick Bookmark
調べたところ、Quick Bookmarkの開発を始めたのは2021年6月27日で、v0.1.0をリリースしたのは2021年7月18日だったので、作り始めて1ヶ月足らずで、最低限自分が必要な機能は実装できていました。
私のような普段コードを書いていない人間が欲しいものを1ヶ月でリリースできるというのはすごいことだと思っていて、これを実現してくれたのがVue.jsのプログレッシブフレームワークという考え方だと思っています。
もともとvue-routerやVuexで何ができるかはざっくり把握していたこともあり、自分が最低限必要とする機能を実装するのにこれらは不要と判断できたので、vue-routerやVuexの勉強はすっ飛ばして、実装に集中できました。
その後ツールを改良しようとした時に、以下の通り段階的にVue.js関連の技術を習得して、機能を追加していくことができました。

  • 1画面1機能に分割したい → vue-routerの導入
  • 見た目をもう少し綺麗にしたい → Vuetifyの導入

次はブックマーク登録をした時に「ブックマークが登録されました」とフラッシュメッセージを出したいと思っていて、その時Vuexが必要らしいので、次はVuexを勉強しようと思っています。
このように段階的に勉強をして、すぐにそれを活かした実践で活かせるので学習意欲が湧くいてくるという点も私にとってはVue.jsの良いところです。

おわりに

この記事ではQuick Bookmarkの紹介、使用しているVue.jsの技術スタックの紹介、私が思うVue.jsの良いところの紹介をしてきました。
Quick Bookmarkをご利用いただき、フィードバックをお寄せいただけると嬉しいです。よろしくお願いします。

チームのアジリティはスキルマップのどこに表れる?

はじめに

安ヶ平です。普段はSIerスクラムマスターとして働いています。
メンバのスキルを星取表の形で可視化するスキルマップ。チーム発足時のメンバのスキルの可視化、離任によるリスクの可視化、学習モチベーションの向上などを目的に作成、運用しているチームは多いのではないでしょうか?
スキルマップの運用について考えていた際、実はスキルマップにチームのアジリティ*1が表れていて、それを認識した上でスキルマップを運用することで、チームのアジリティを向上させることができるのでは?という仮説が浮かんだので、この記事で説明します。
スキルマップ自体の説明は、ryuzeeさんのブログエントリスキルマップ作成のすすめをご覧いただくのが良いと思います。

私なりのスキルマップの作り方

私はスクラムチーム発足時に、インセプションデッキ作成などと共にチームでスキルマップを作成するので、基本的にはPOっぽいスキルやSMっぽいスキルもスキルマップに入れて、POと一緒にスキルマップを作ります。そうすると私のチームのスキルマップは、図のように、DEVっぽいスキル、SMっぽいスキル、POっぽいスキルにゾーンが分かれたスキルマップになります。

f:id:sonomirai:20210802001303p:plain
チーム発足時のスキルマップ例

スキルマップの運用で難しいところ

私はスキルマップを作成した後、ふりかえりの場などを活用して定期的にチームで話し合って、スキルマップを更新しているのですが、このとき難しいと思うことがあります。
それはSMっぽいスキル、POっぽいスキルの更新です。DEVっぽいスキルの部分は、項目自体が細分化されたり(例えばAWSという項目は早い段階で細分化される気がする)、スキル度合いもぐんぐん向上していくはずなので、チームの会話は弾みながら更新できるのですが、SMっぽいスキルやPOっぽいスキルの部分は、ついつい更新をおざなりにしてしまっていました。
理由としては、DEVは複数名いるのに対して、POやSMは基本一人なので、話し合いの中での優先順位を下げてしまっていたというのと、私がスキルマップの主な目的を「DEVのスキル可視化」と捉えていたというのが正直なところです。

チームのアジリティ

唐突に話が変わるのですが、私はチームのアジリティは、メンバがお互いのロールについてどれだけ共通認識を持っているかによって決まると思っています。
DEVがPOに提案しても、POが開発のことをわかっていなかったら、説明に時間がかかります。
POがSMと会話しようにも、SMにPOを支援する度量がないと、バックログ作成が進みません。
SMがDEVにアジャイルマインドを伝えようとしても、DEVが興味なかったら開発は進みません。
チーム発足時に上記の状態だったとすると、それはチームのアジリティが低い状態だと思います。
その後チームで会話を重ねてお互いのロールについて理解することで、チームのアジリティは向上すると思います。

チームのアジリティはスキルマップのどこに表れる?

さてここまでの内容で、「チームのアジリティはスキルマップのどこに表れる?」に対する私の考えがわかったでしょうか。
私は下図の通り「メンバが自分以外のロールのスキルをどれだけ有しているか」にチームのアジリティが表れると思います。

f:id:sonomirai:20210802004600p:plain
他のロールのスキルを有したスキルマップ例

他のロールのスキルについて、高いスキル度合いを有する必要はないと思います。
ただDEVであれば、POがバックログの説明を聞いて、その裏にある業界知識や業務をイメージできる程度のスキルがあるといいし、POであれば、DEVがテストの自動化を訴えてきたときにその優先順位を判断できる程度のスキルがあるといいと思います。

目指したいスキルマップの運用

スキルマップを使って、メンバが他のロールのスキルをどれだけ有しているかを可視化することで、それぞれのロールに対して理解が足りないところは勉強会で補うことができ、結果としてチームのアジリティが向上すると考えているので、今後はこの点をチームメンバに伝えた上で、スクラムチーム一丸となって、改めてスキルマップを運用していきたいと思います。

さいごに

この記事では、スキルマップを見たときに「メンバが他のロールのスキルをどの程度有しているか」を評価することで、チームのアジリティを可視化・向上させることができるのでは?という仮説を説明しました。実践して学びを得たら、また記事にしたいと思います。

*1:この記事において「チームのアジリティ」とは、メンバが何かを提案してから、チームとして合意して具体的なアクションに繋げるまでの期間を指しています。この定義は私の勝手なイメージなで出典はないので、一般的なイメージと異なっていたらすみません。。。なおチームのアジリティという考え方は、広木さんの「2つのDX」とDX Criteriaのお話を聞いていて思いついた考え方です。

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

この記事は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のことはわからないことがわかった笑)

参考サイト