SRE兼スクラムマスターのブログ

チーム開発が好きなエンジニアブログです。検証した技術やチームの取り組みを書いていきます。

モブプログラミング を2年間続けて気づいたこと

モブプログラミングを始めてから2年ほど立つが、この2年間の間でチームが3回ほど変わっている。 チームの形成期から機能期まで何度か経験したおかげで、 その時々でモブプログラミングを行っている経緯が違うことに気づいたので、まとめておこうと思う。

モブプログラミングとは

簡単にまとめると「チーム全員でペアプロする」みたいなこと 2014年にWoody Zuill氏がAgile Allianceで発表されたMob Programming A Whole Team Approachが原著になる。

www.agilealliance.org

環境

  • チーム規模:4~6人
  • 場所:比較的大きなモニターがある部屋、スペース
  • PC:作業用のPC1台、各自調査用のPC
  • 内容:要件定義、設計、開発(TDD)、ドキュメント作成、バグ修正など
  • ツール:

Mobster

モブプロ用のタイマー。(ペアプロMTGでも効果あり) github.com 一部動作しないPCもあったのでその場合は下記のサイトを利用するのもおすすめ。 agility.jahed.dev

Visual Studio Live Share

VSCodeで複数人でコードの編集・デバッグが行える拡張機能。 複数人で同時にファイルを編集できる。ファイルの移動、プロジェクト内検索も可能 ホストマシンのローカルサーバーをシェアし、ゲストマシンからブラウザでアクセスすることができる。 ホストマシンのターミナルをシェアし、ゲストがコマンドを実行することができる。

visualstudio.microsoft.com

モブプログラミングの経緯と成果

ここではチームの成長に伴う、モブプロを行った経緯とそのときの結果をまとめていく 少し特殊な条件として、個人で行っていたプロダクトが人数が増えてチームになっているので 初めからナレッジが多いメンバーがいる。

経緯

チーム形成期

  • オンボーディング
  • メンバー間のプロダクトに対するナレッジ差が激しい

チーム混乱期

  • コードレビューやレビューの取込みにやたら時間がかかる
    • いつまでもマージされないプルリクエス
  • チーム形成期にふわっと決めたルールにひずみが生まれ始めた
    • ルールの理解がメンバーによってマチマチ

チーム統一期

  • プロダクトスキルやナレッジが偏ることでタスク担当者に偏りがでる
    • バス因子の増加

チーム機能期

  • 設計の背景や意図を伝えるのに時間がかかる
    • ドキュメントを作成してみたが作成に時間がかかり、かつ保守が大変
  • 開発チームで決定したことを顧客に合意を得るまでに時間がかかる
    • プロセスタイムは短いけど、リードタイムがやたら長い

成果

チーム形成期

  • オンボーディングに必要な形式知を作成できた
    • オンボーディング対象の人と一緒に作るため一方的なドキュメントではなくなった

チーム混乱期

  • コードレビューの観点を統一出来るようになった

    • 指摘事項もその場で全員で修正するのでそのままマージされる
    • プルリクエストが溜まらない
  • 暗黙知のすり合わせが出来るようになった

    • 必要に応じて暗黙知形式知に変換できるようになった
      • 全員で作成するドキュメントなので後々も保守される

チーム統一期

  • スキル共有することで相互理解が深まる

    • 有識者:スキル共有することで理解を深める
    • 初心者:スキル共有され且つ実際に手を動かしていくので理解を深める
  • 保守体制に心理的安全性が生まれた

    • この機能で問題が起こったら○○さん!状態から脱出できた

チーム機能期

  • PdMとのコラボレーションにより共通言語が出来、プロダクトのブレが少なくなった
    • 都度、確認および決定が出来るのでリードタイムが短くなり素早く価値を提供できるようになった

まとめ

2チームで1年ずつモブプロに取り組んだが、ふりかえってみると その時々でモブプロを導入している経緯は概ね同じようなものだと分かった。 成果としても導入する経緯に対して課題を解決出来ていることが多いので非常に効果的だと感じる。

モブプログラミングの課題とカイゼン

モブプログラミングの経緯と成果の内容だけ見ると モブプロ最高とかモブプロやろう!!みたいな感じになるかもしれないが、もちろん全て順調に進んだわけではない。 ここでは、私たちのチームが失敗したこととカイゼン内容についてまとめる。

生産性が低いと指摘される

課題

これは多くのモブプロ実践者の方が通過するであろう課題で、私は「生産性おじさん」問題と呼んでいる。 管理する人から見れば、シングルスレッドでタスクを行うよりマルチスレッドで行う方が 効率的だし、生産性が高いと指摘された。ちなみに私たちのチームでは、チームメンバーからも同様の声が上がった。

やったこと

私たちのチームでは実際にモブプロとソロプロの「開発時間」と「テストによる手戻り」と「デリバリー後の保守工数」を指標として 数スプリントデータを取って比較した。結果として、「テストによる手戻り」と「デリバリー後の保守工数」でモブプロがソロプロでやるときに比べて 格段に低くなっているとわかったので、総合的に見て有用であること証明してモブプロを理解してもらった。

ただ漠然とモブプロしていた

課題

モブプロに慣れてきて、形骸化してしまう状態のときにぶつかった課題である。 PdMにも認めてもらいモブプロのやり方も慣れたが故に、その作業に対して本当にモブプロが必要かどうかを 考えずに漠然をモブプロをしている状態だった。 この状態に陥った時はモブプロ本来の良さであるスループットの速度も落ちて全員で悶々と悩んで1日消費してしまうこともあった。

やったこと

この問題に対しては自分たちのモブプロについてしっかりふりかえってみた。 モブプロに対して理解していない部分が多いことが分かり、チームでモブプロについて学習しなおした。 学習の中で自分たちのモブプロルールを作成した結果、しっかり目的意識をもって作業し成果を出せるようになった。

参考までに自分たちのモブプロルールを載せておく

  • 1日の上限時間

    • モブプログラミングによるコーディング: 2h ※コーディング作業に限る
  • 人数上限

    • モブプログラミングによるコーディング: 3名 ※コーディング作業に限る
  • フロー

    • 目標を決める
    • タスクの全体像のすり合わせ
    • mobsterを使って交代する
    • ふりかえり - 15 min
    • その後の作業分担
  • 組み合わせ

    • スキルシートを作って、チームの状態を可視化しておくこと
    • 熟練者 : 熟練者

      • 品質を向上させたい
        • コーディングの書き方
        • テストケースの提案
      • 心理的に安全になりたい
    • 初心者 : 熟練者

      • 情報共有/ノウハウ伝授
        • コーディングの暗黙知を共有
        • 知識を共有してオーナーシップを持ってほしい
          • 責任感を持ってもらう
      • ノウハウを伝授される側は知識が疎い分野に対して教えを請いたい
      • やったことがないタスク
        • オンボーディング

ちなみに、上記のルールはあくまで自分達のリズムで仕事をするために 最適だと思っているルールなので何が正解などは特にないと思う。 かつ、チームの成熟度が上がると自然の応用できるようになるので あくまで目安程度のものとして考えた方が良いかもしれない。

メンバーのスケジュール調整が大変だった

課題

これは環境特有の問題な気もするが、ぶつかるチームもあると思うので書いておく。 私たちのチームではメンバーが複数のプロジェクトにアサインされているケースが多く全員が100%集中できる状態ではなかった。 本来であれば、プロジェクトを減らすなど対応を取りたいところだが、重要なプロジェクトもあるのでそれが出来なかった。 その場合、各プロジェクトの定例MTGなどがバラバラなため、関係者を集めるのが非常に困難な状態になっていた。

やったこと

自分たちのモブプロルールでも書いたが、スプリント毎に当プロジェクトに避ける割合が低いメンバーは 一時的に他プロジェクトに集中してもらう方法を採用した。つまりスプリント毎にキャパシティを変更したのである。 これにより、特定の作業に集中できるのでスケジュールも合わせやすく、調整コストが軽減できた。

リモートが多いとシンドイ

課題

これも環境特有の問題な気もする。 チームメンバーが在宅ワークをしていることも多く、同じ部屋で同じPCを使って行うというのが難しかった。 物理的に同じPCを使うのも困難だし、同じ部屋で参加しているメンバーに対して温度差があると感じた。

やったこと

リモートが多い問題については2つのカイゼン策をとった。 1つめはツールの力を活用することだ。私たちのチームでは「Visual Studio Live Share」を使って物理的な問題を解決した。

Visual Studio Live Share

VSCodeで複数人でコードの編集・デバッグが行える拡張機能。 複数人で同時にファイルを編集できる。ファイルの移動、プロジェクト内検索も可能 ホストマシンのローカルサーバーをシェアし、ゲストマシンからブラウザでアクセスすることができる。 ホストマシンのターミナルをシェアし、ゲストがコマンドを実行することができる。

visualstudio.microsoft.com

2つめは、リモートのドライバー率を高くしたことだ。 そうすることで、参加率が高くなって疑問を発言しやすくなって 同じ部屋で参加しているメンバーとの温度感をそろえていくようにした。

めっちゃ疲れる

課題

1日みんなでモブプロするとめっちゃ疲れる。 ずっと考えているし、喋っていることが多いので1人でやるときより遥かに疲れる。

やったこと

疲れる問題に関しては、疲れる原因を考えるとコーディングを挙げるメンバーが多かったので モブプロルールで示したように1日の上限を設けることで自然と解決できた。 集中出来ると感じる時間は人によって違うので回数をこなしてチームの最適な形を探すと良いかもしれない。

まとめ

様々な場面でみんながぶつかると思う課題を挙げてみたが、参考になればと思う。 私たちのチームでもまだまだ課題が多いが日々の振り返りによって徐々にカイゼンされているので 今後も何かあれば追記してきたい。。

総括

2年間続けてきたが、やっぱりモブプロは良いと思った。 数値的に考えるとリードタイムが短くなるとか、ムダな部分がなくなるなどいろんな効果があるのだが 個人的には、失敗する作業を経験してそこから成功体験になるまでのプロセスをチーム全員で 経験できることが一番大切だと感じた。 チームで成功体験できることで一体感が増すし、貢献できる部分が増えてくると メンバーのモチベーション向上にも繋がるので、これからモブプロをやってみようと思う人は是非チャレンジしてみてほしいと思う。

参考

モブプロを学習するうえで参考にした資料です

speakerdeck.com

安西剛さんの「1 on 1コーチング体験」を受けてきた話:やり方とあり方

先日、安西剛(@tsuyok)さんによる「1on1コーチング体験」を受けてきた。 以前からTwitterは一方的にフォローさせていただいたので、今回の募集を見たときから気になっており 思い切って応募した。

今回はコーチング体験の流れや感想などをブログに書いていきたい。 www.tsuyok.work

なぜコーチングを受けたのか

なぜ 1 on 1 のコーチングを受けたかというと 自分の場合は2つ理由があった。

  • 1つ目

自分自身が1 on 1を体験してみたかったから。 リーダーとしてメンバーへの成長を促すため、1 on 1を行っているが 自分自身これまで1 on 1を受けたことが1度もないので、実際に体験してみたかった。 やり方は書籍ベース、どう感じるかはメンバーからのフィードバックのみだったので 1 on 1を受けることで新しい気づきがメンバーと行うときの参考になればと思っていた。

  • 2つ目

三者としての意見を聞いてみたかったから。 所属している組織では自分のやっていることに対してディスカッションする人が少なく、 フィードバックをもらうことが少ないのでこの機会を是非活用したいと思った。

学び

状態の可視化・整理・決定

今回の1 on 1 は自由なテーマで話をした場なので、日ごろ自分が抱えている課題やモヤモヤについて話をした。

印象として残っているのは、事象について多角的に考える時間を持てたことである。 ふんわりアイディアが見えているものもあったが、今一度、別の視点から考え直すことで アイディアが他と比べてどうなのか?自分の本当にやりたいことに対して矛盾していないか?を明確にできた。 また、アイディアに対して自分で「決定」することも重要だということを学べた。

やり方とあり方

最も印象に残ったものとして「やり方」と「あり方」の話だ。 なぜコーチングを受けたのかでも理由に挙げているように 1 on 1を受けることで ノウハウを学びたいと考えていた。 ふりかえってみると、その時点では比較的「やり方」の部分に固執していたように感じる。 安西さんとお話をして「やり方」以上に「あり方」が大切ということを学べた。 「あり方」自体、意識して向き合うことがあまりなかったので説明に語弊があるかもしれないが 「あり方」とは、「自分がどうあるか?」である。 例えば1 on 1で成長を促したい場合に自分が成長しているか?について考えることである。 この話でもう一つ印象に残っていたキーワードとして「相手は自分のカガミ」というものがあった。 これはまさに「あり方」を表した言葉だと思う。自分が変わらないと、相手も変わらないし 成長させたい場合は、まず自分が成長することが大切ということだ。 「あり方」をおざなりにするといくら「やり方」を突き詰めても相手に伝わらないので自分の「あり方」について意識したい。

最後に

この記事では、1 on 1体験での「学び」の部分に絞ってふりかえりを書いた。 学びの内容をふりかえっていてコーチングは、感情を大切にすることの確認が出来て非常に有意義だった。 そして感情という非常に抽象度が高いものになっていくに中で、コーチングについてしっかり学習していくと楽しそうだというポジティブな気持ちになれた。

ちなみに当日の 1 on 1では、記事の内容以外にもお話をさせて頂いた。その中にはアジャイルやDDDを導入した話があり 自分が取り組んでいることを、既に経験された話なのでとても勇気づけられた。

普段このような分野で人と話す機会がないので 貴重な体験をさせていただきありがとうございました。

1 on 1参考資料

speakerdeck.com

Feature Toggleについて整理してみました

はじめに

みなさんの現場はデリバリーチームとオンコールチームに分かれていますでしょうか?

分かれている現場ではリリースのタイミングは調整が出来ていますか?

我々のチームはデリバリーチームとオンコールチームに分かれているのですが、テスト環境などの関係上 リリースのタイミングの調整に時間がかかりがちで、そのたびにmaster branchのコンフリクトに悩まされてしまったり merge待ちなどが発生してデリバリーのリードタイムが伸びてしまうことがあります。

そこで今回は本番コードに潜在的にプロダクトのコードを埋め込んでも 影響が出ない仕組みが実現できる「Feature Toggles」について調べてみたので整理してみようと思います。 ※この記事ではFeature Togglesの具体的な実装については記載しません

Feature Togglesとは

Feature Togglesは別名:Feature Flagとも呼ばれており、チームがコードを変更することなくシステムの振る舞いを変更することができる仕組みであり、さまざまな用途が存在しているようです。 ちなみに私が初めてFeature Togglesを知ったのは Martin Fowlerのblog記事でした。 今回の記事もこちらで記載されている情報やFeature Togglesを実現するProductの内容を自分なりに噛み砕いて整理しています。 martinfowler.com

Togglesを実装したり、管理したりする場合、数が増えていくと複雑になる傾向があるので カテゴリ分けを考えることは重要であり、複雑性をコントロールをする事が推奨されています。

トグルのカテゴリ分け

調べてみるとFeature Togglesにはいくつかカテゴリがあり、自分達の課題にある内容も Feature Togglesのカテゴリの中に存在していました。

Release Toggles

継続的デリバリーを実践するチームのためにトランクベースの開発を可能にするために使用される機能フラグです。Release Togglesを使用すると 進行中の機能をmaster branchなどにmerge出来るようにし、いつでも本番環境に展開出来るようになります。

https://martinfowler.com/articles/feature-toggles/chart-1.png

Release Togglesは、一般的に1週間から2週間以上にわたっては存在しないことが推奨されています。 ただし、プロダクト中心のトグルについては長期間埋め込まれていることもあります。 Release Togglesを用いたトグル戦略は非常に静的で、トグルコンフィグレーションの変更して新しいリリースをトグルで展開することの決定は、大抵受入れ易いものになります。

Experiment Toggles

A/Bテストやカナリアテストを実現するために使用されます。 仮説検証のプロダクトや非機能要件の実装を一部のユーザーにのみ公開して動作を追跡することで、効果を比較できます。 この手法は、通常、データ駆動型の最適化に使用されます。 また、この手法を採用する場合はシステム監視の仕組みやユーザーインタビューのようなデータを収集する術をあらかじめ用意していることが望ましいです。

https://martinfowler.com/articles/feature-toggles/chart-2.png

Experiment Togglesは、統計的に有意なデータを収集するために十分な期間の同じ構成を維持する必要があります。 実験の内容にもよって、一般的に時間や週単位が推奨されています。また、システムに変更を加えてしまうと実験の結果が無効になるリスクが存在するので、これ以上長く期間を設定することは有用ではありません。

Ops Toggles

システムの動作の運用面を制御するために使用されます。 パフォーマンスへの影響が不明確な新機能をロールアウトする際にOps Togglesを導入して、Opsチームが必要に応じて本番環境でその機能を迅速に無効化または低下できるようにします。 この仕組みを導入することによってシステム障害時のMTTRが向上すると考えられます。 ※MTTRは障害から回復するまでの平均時間なので、トグルをoffにしたときに「回復した」と定義して良いか、少し迷っています…

Ops Togglesは短い期間でしか存在しておらず、新機能の運用面で安定したらフラグを廃止します。 個人的にはOps作業のボリュームからOps Togglesの上限を設けて、カンバン開発のWIP制御と連動するとDevOpsが良い感じになりそうな予感がします。

ちなみに、Ops Togglesのテクニックとして システムが異常に高い負荷に耐えている場合、Opsチームが重要でないシステム機能を正常値に低下させることができる例外的に長寿命の「Kill Switches」という概念が存在しているようです。 例えば、システムに高負荷がかかっている場合は、機能的には重要ではないが表示コストがかかる項目を一時的にoffするといったイメージです。 これらのOps Togglesを長寿命で管理して手動切り替えられるで管理される「Circuit Breaker」として利用することもあります。

https://martinfowler.com/articles/feature-toggles/chart-3.png

Permissioning Toggles

特定のユーザのみ機能を変えたり、プロダクトのエクスペリエンスを変えたりするのに使われます。 個人的には、Experiment Togglesとの違いはプロダクトとして完成しているかしていないかだと捉えました。 Experiment Togglesはプロダクトが正しいものなのかを実験するためのもの、Permissioning Togglesは正しいものと判断できた機能を 特定のユーザーに提供する仕組みだと思います。

https://martinfowler.com/articles/feature-toggles/chart-4.png

公開する機能を管理する方法として使う場合には、Permissioning Togglesは、ほかのカテゴリの機能トグルに比べてとても長期間生存するものになります。 切り替えは、いつもリクエスト毎になるので、このトグルは非常に動的なものである必要があります。

トグルの管理

トグルのカテゴリについて紹介しましたので、ここでは各トグルの管理方法について整理します。 トグルはカテゴリ毎に、静的/動的および長期間/短期間の2軸で考えることが出来ます。

静的トグルと動的トグル

https://martinfowler.com/articles/feature-toggles/chart-6.png

Martin Fowlerのblog記事では静的トグルは「Release Toggles」のみとなっています。 Release Togglesの用途は、本番環境に実装途中の機能を統合するための仕組みなので動的に切り替えられる必要がなく 設定ファイル等にon/offを設定すれば良さそうです。

動的トグルは、トグルの切り替えのためにリリースするのは非常にコストがかかる作業になるので 別の仕組みを提供する必要があります。 例を挙げると下記のような方法が考えられます。

  • システムの利用しているユーザーのIDを読み込んでon/offを切り替える切り替える
  • 別システムを利用してDBでトグル情報を管理してダッシュボードからOpsチームがon/offを切り替える
  • システムにアクセスする時のリクエストをオーバーライドして、リクエストパラメーターやHTTP headerに特定の値を埋め込んでon/offを切り替える…etc

短期間トグルと長期間トグル

https://martinfowler.com/articles/feature-toggles/chart-5.png

短期間トグルは、トグル判定を行うコード上にif/elseのようにハードコーディングしても良いと思います。 短期間のため、リリースサイクルの過程でif/elseの記述がなくなると予想されるからです。

function reticulateSplines(){
  if( featureIsEnabled("use-new-SR-algorithm") ){
    return enhancedSplineReticulation();
  }else{
    return oldFashionedSplineReticulation();
  }
}

一方で長期間トグルの場合はif/elseのコードがいつまでも残っているのは保守の観点からも リスクが発生します。blog記事でも保守可能な実装技術を採用する必要があるの述べられています。

実装テクニック

ここから先の記述ではFeature Toggles の切り替え分岐部分をトグルポイント、切り替え判定の値取得部分をトグルルーターと表現します。 トグルポイントはFeature Togglesの数とともにはコードベース全体に増殖する傾向があります。 トグルポイントの実装が増殖した場合は、保守が非常に煩雑になり本番障害へのリスクも増加します。 ここではトグルポイントを実装する際の実装パターンを紹介していきます。

決定点と決定ロジックの分離

Feature Togglesを実装する際の注意点はトグルポイントの処理と決定ロジックの統合をしないことです。 例として下記のコードを紹介を紹介します。

  
  const features = fetchFeatureTogglesFromSomewhere();

  function generateInvoiceEmail(){
    const baseEmail = buildEmailForInvoice(this.invoice);
    if( features.isEnabled("next-gen-ecomm") ){ 
      return addOrderCancellationContentToEmail(baseEmail);
    }else{
      return baseEmail;
    }
  }

if/else時の判定にnext-gen-ecommの値を取得して切り替えているので 一見、シンプルで可読性の高い実装のように見えますが非常に保守が大変になります。 まず、トグルルーターを呼び出すのが、他のメソッドでも必要にあった場合に すべてのメソッドに同様の処理を施す必要があります。 結果的に非常に冗長したコードになり開発時のコストを増加させる危険があります。

そこでトグルルーターを別オブジェクトとして実装します。

  function createFeatureDecisions(features){
    return {
      includeOrderCancellationInEmail(){
        return features.isEnabled("next-gen-ecomm");
      }
      // ... additional decision functions also live here ...
    };
  }

FeatureDecisionsオブジェクトを導入しているので、機能切り替えの決定ロジックの収集ポイントとして機能します。 これによってトグルルーターの保守が簡潔になります。

そして先ほどのトグルポイントの実装は下記のようになります。

  const features = fetchFeatureTogglesFromSomewhere();
  const featureDecisions = createFeatureDecisions(features);

  function generateInvoiceEmail(){
    const baseEmail = buildEmailForInvoice(this.invoice);
    if( featureDecisions.includeOrderCancellationInEmail() ){
      return addOrderCancellationContentToEmail(baseEmail);
    }else{
      return baseEmail;
    }
  }

切り替えの決定が抽象化されているので開発者はその中身をあまり気にせずに実装を続けることが可能になります。

条件の回避

上記で紹介したトグルポイントをif/elseで実装するケースは、短期間トグルには有効なテクニックですが 長期間トグルではアンチパターンとされています。 より保守可能な代替手段は、ある種の戦略パターンを使用してコードを実装することが推奨されています。

  function identityFn(x){ return x; }
  
  function createFeatureAwareFactoryBasedOn(featureDecisions){
    return {
      invoiceEmailler(){
        if( featureDecisions.includeOrderCancellationInEmail() ){
          return createInvoiceEmailler(addOrderCancellationContentToEmail);
        }else{
          return createInvoiceEmailler(identityFn);
        }
      },
  
      // ... other factory methods ...
    };
  }

上記の例ではfactoryパターンを採用した場合の実装になります。 この実装では「featureAwareFactory」というオブジェクトを実装しており その中で、メールの送信に必要なオブジェクトをトグルポイントで作り分けています。

このように実装することによってトグルポイントがコードベースに散りばめられることや コードの修正漏れに対するリスクの軽減になります。

所感

Feature Togglesの記事について読み込んで整理してみました。 結果としてもともとのissueであったチーム間のコンフリクトやリリースのリードタイムはFeature Togglesを導入することで解決できそうなことが分かりました。 特に私たちのチームでは「Release Toggles」と「Ops Toggles」が有効に機能しそうです。 リリース戦略を考えるうえで強力な手法なのでこれを気にしっかり導入してみようと思います。 また、将来的にはOutcome Deliveryのために「Experiment Toggles」を導入してより「正しいもの」を見つけるための仕組みとして強力な手法になりそうな予感です。

一方、課題として見えたことは 各カテゴリのトグルを単一管理するとOps作業が大変になり運用障害が起こりうること、運用していくうえでダッシュボードのように トグルの状態を可視化できる仕組みが求められる可能性が高いこと、Feature Togglesが単一障害点にならないように設計する必要があることなどなど やることはたくさんありそうな気がしました。

ダッシュボードや堅牢性を担保する場合は、自分たちで実装するのもありですが下記の製品を検証してみようと思います。 launchdarkly.com

簡単に説明するとFeature Togglesを管理してくれる製品です。 java, javascript, node, pytho..etcなどの対応言語が多いこととdatadogなどの監視システムとの親和性も高そうなので期待しています。

参考

今回の記事は基本的に下記のblogを参考にしました。 個人的には非常によくまとめられているので導入が進んでいくにつれて読み直すと気づきも多くなりそうです。 https://martinfowler.com/articles/feature-toggles.html

チームの成長のために「Learning Session」を始めた話

はじめに

皆さんのチームでは、チームの成長のためにどのような取り組みを実施していますか?

私たちのチームでは、メンバーに学習文化をつけて個々のスキル向上を図り、結果的にチームの成長につながると考えていました。 チームはスクラム開発を実施しており、スプリント内のキャパシティに毎日20%の学習時間を計画して メンバーがスキル向上やチームビルディングに充てる時間を確保しています。

時間を確保していると言えば聞こえは良いかもしれませんが、もともと業務時間内での 学習時間確保の文化が存在していたわけではないので、実際はタスクに追われて学習時間を確保できていなかったり チームで必要なスキルではない分野の学習を進めていたり、学習時間を有効に活用できていませんでした。

※チームで必要なスキルではない分野の学習をしてはいけないわけではなく、チームで開発していくにあたって最低限必要なスキルは皆で統一したいという意味です。

これまで取り組んできたことのふりかえり

これまでチームの成長のために取り組んできたプラクティスを紹介します。

ペアプログラミング

設計・開発・テスト・ドキュメントまでプロダクトをデリバリーする一連の流れをメンバーがペア作業で実施しました。 ペア作業で行うことで暗黙知の共有が出来たり、テスト品質が上がるなど効果が表われました。

モブプログラミング

設計・開発・テスト・ドキュメントまでプロダクトをデリバリーする一連の流れをメンバーがモブ作業で実施しました。 ステークホルダーとなるメンバーを招待して、実施することでペアプログラミングを実施していた時の効果に加えて スプリント計画時の手戻りが減るなど、こちらも効果は大きかったです。

ラクティスのふりかえり

  • よかったこと

どちらのプラクティスも効果が大きく、チームではタスクの粒度によって使い分けを行っており プラクティス自体は今後も続けていくことになりました。

スプリントの振り返りでFun/Done/Learnを実施したときに、「Learn」の枠に付箋が少なくなってきた ペア/モブでは、基本的にタスクをこなすことを優先しているので、フレームワークややり方に慣れてくると形骸化しがちという意見もちらほらありました。

Learning Session」を導入してチームで学習時間を確保する

Learning Sessionとは

チームで良い感じに学習することを探していたらこちらの記事が見つかりました。

engineering.linecorp.com

Learning Sessionで注意したこと

  • 紹介した記事に記載はありますが、極力負担がかからないこと

    • 資料は必要であれば作成する
  • 成果物にこだわらないこと

    • 成果物にこだわらず、あくまで学習の一環としてとらえる
  • 楽しくやること

  • お互いに敬意をもって参加すること

    • 批判をせずに、お互いの良い点を見つける

Learning Sessionを続けて変わったこと

  • メンバーがoutputする習慣がついた

    • 自分の得意分野についてコーチングするメンバーが増えた
    • 人生で初めてLTを行ったメンバーも!
  • キャパシティが上がった

    • メンバーのスキルが底上げされたので、コミュニケーションコストが減った

所感

チーム学習という仕組みを導入して1ヶ月たったが、チームの雰囲気が良くなったり 以前より楽しく仕事ができていることが実感できる。 エンジニアの定常業務の中に「学習」があるのは、とても重要で結果的に仕事が早く終わることにつながるという 成功体験をチームで出来たのは非常に良かった!

学習文化をチームに定着させたい方がいたら是非「Learning Session」を試してみてください!

「ふりかえり読本 実践編」を読みました

XP祭りに参加して念願の「ふりかえり読本」を購入できまして これまでやってきた自分たちのふりかえりをふりかえりながら読んでみました。 ふりかえりを実践してきた人達でも、きっと学びがあると思います。

hurikaeri.booth.pm

ざっくりどんな本なのか

正直、ふりかえりのプラクティスに関しては「アジャイルレトロスペクティブズ」や 「LEADER's KPT」など 様々な書籍があり、そちらを読んでみることお勧めしたい。

本書ではふりかえりを型分けして目的ごとに、プラクティス使い分けるアドバイスやふりかえり本質について焦点を当てていて ふりかえりをもっと上手にやりたい人や初めてやるがどうしたら良いかわからない人に向いていると感じました。 そして何より「ふりかえり」というカイゼン文化を広めたいという著者の思いが詰まっている書籍でした。

面白かった部分として「ふりかえりを8つの型に分ける」部分であり これまであまり意識していなかったが、ふりかえってみると確かに目的別に使い分けており それが言語化されたもの読むとチームの状態に対してより良い方法を選定することにも繋がる。

  • 2章 ふりかえりを拡張する
    • ふりかえりの型
    • 型を使いこなすために
  • 6章 学びを最大化する

読んだ方が良さそうな人

本書にも記載されているが、ふりかえりを初めてみようと考えている人、ふりかえりを実施しているがうまくいっていない人にお勧めしたい書籍だと思いました。

特にふりかえりを実施しているがうまくいっていない人は毎回ふりかえりの前に憂鬱な気持ちになっていないでしょうか?

私もうまくいっていないときは、「ふりかえり、やだなぁ...」と考えていた時期もありましたが、目的を明確にしたり、チームメンバーが参加しやすいアクティビティを取り入れることで 前向きに「ふりかえり」が出来るようになってくると毎週ふりかえりの時間が楽しみで仕方ないです。 楽しく実りのあるふりかえりを実践したい方は是非。

併せて読んだ方が良さそうな本

アジャイル関連の書籍はたくさんあるのですが「ふりかえり」の部分について焦点を当てている書籍です。 併せて読んでおくと理解が深まりやすいと思います。

アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き

アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き

LEADER's KPT

LEADER's KPT

これだけ!  KPT

これだけ! KPT

最後に

アジャイルを組織に浸透させるのは、とても大変で場合によっては大きな抵抗にあう場合もあります。 自分たちの目的は「アジャイル」になることは非常に時間がかかることなので、 まずは立ち止まって分析しカイゼンすることを習慣づけしていくことが大切です。 そういった意味においても「ふりかえり」 は初めの一歩として非常に有効なので今後も継続的に組織に広げていこうと思います。

Fluxを使ってGitOpsを実現する

概要

  • GitOpsという概念は知っているが実現はできていなかった
  • GitOps実践ツールではAgro CD,Flux,Jenkins Xなどが有るけど,GitOps提唱元のFluxを試してみる

モチベーション

  • kubernetesを運用するにあたってmanifestを使って宣言的に運用したい
  • codeと実際の環境差異をなくしたい

GitOpsとは?

Weaveworks社が提唱した,Kubernetesの運用ベストプラクティス

詳しくはGitOpsを参照

Fluxとは?

Kubernetesへのコンテナの展開を自動化するツール

Githubを見ると以下のことが書かれていた

  • gitでシステムの望ましい状態を宣言的に記述できる

  • 宣言出来るものは自動化できる

  • コンテナをpushするのではなくコードをpushするのだ

github.com

詳細はここでは割愛するが 実現できることを簡潔に表現すると kubernetes Clusterの状態とGit管理されているmanifestと同期を取り 変更検知された場合に自動的にclusterを更新してくれるものらしい

事前準備

fluxctlのインストール

brew install fluxctl

Kubernetes Clusterの構築

  • 今回はdocker desktop for windowsを使ってlocal環境にclusterを構築しました。

qiita.com

qiita.com

Flux同期用のリポジトリを作成

flux導入

  • 導入はこちらを参考に進めました

https://docs.fluxcd.io/en/stable/tutorials/get-started.html

基本は手順通りなのだが自分は英語を読むのに時間がかかるので実行したコマンドをメモしておきます

clusterにflux用のnamespaceを作成する

kubectl create ns flux

fluxをinstallする GHUSERはgithubのアカウント名に変更する 今回はgithubを利用しているが他のversion管理ツールを利用している場合は検証が必要そう

export GHUSER="hogehoe"
fluxctl install \
--git-user=${GHUSER} \
--git-email=${GHUSER}@users.noreply.github.com \
--git-url=git@github.com:${GHUSER}/flux-get-started \
--git-paths=namespaces,workloads \
--namespace=flux | kubectl apply -f -

コマンドを実行するとfluxがデプロイされているか確認します。

kubectl get all -n flux

NAME                             READY   STATUS    RESTARTS   AGE
pod/flux-69f4b44484-t6lrt        1/1     Running   0          178m
pod/memcached-7c45dbdb45-s4m95   1/1     Running   0          178m

NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
service/memcached   ClusterIP   10.97.207.98   <none>        11211/TCP   178m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/flux        1/1     1            1           178m
deployment.apps/memcached   1/1     1            1           178m

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/flux-69f4b44484        1         1         1       178m
replicaset.apps/memcached-7c45dbdb45   1         1         1       178m

Fluxの公開鍵をリポジトリに登録します Clusterの状態をgitと同期するには,公開鍵を使ってGitHubリポジトリに書き込みアクセス権を持つデプロイキーを作成する必要があるようです。 デプロイキーの作成はこちらを参照

fluxctl identity --k8s-fwd-ns flux

ちなみにこの時点で Flux同期用のリポジトリに管理されているmanifestがcluster上にデプロイされていました。 guthubのmanifest抜粋

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
  namespace: demo
  labels:
    app: podinfo
  annotations:
    flux.weave.works/automated: "true"
    flux.weave.works/tag.init: regex:^3.10.*
    flux.weave.works/tag.podinfod: semver:~2.1
spec:
  strategy:
    rollingUpdate:
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
      labels:
        app: podinfo
    spec:
      initContainers:
        - name: init
          image: alpine:3.10
          command:
            - sleep
            - "1"
      containers:
        - name: podinfod
          image: stefanprodan/podinfo:2.1.3
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9898
              name: http
              protocol: TCP
          command:
            - ./podinfo
            - --port=9898
            - --level=info
            - --random-delay=false
            - --random-error=false
          env:
            - name: PODINFO_UI_MESSAGE
              value: "Greetings change pod!"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 9898
          readinessProbe:
            httpGet:
              path: /readyz
              port: 9898
          resources:
            limits:
              cpu: 1000m
              memory: 128Mi
            requests:
              cpu: 10m
              memory: 64Mi
kubectl get pod -n demo
NAME                       READY   STATUS    RESTARTS   AGE
podinfo-5645bc6c54-lmcnk   1/1     Running   0          146m
podinfo-5645bc6c54-tln7j   1/1     Running   0          146m

sampleのServiceはclusterIPなのでportforwadしてブラウザでアクセスしてみます

kubectl port-forward svc/podinfo 8080:9898 -n demo
Forwarding from 127.0.0.1:8080 -> 9898
Forwarding from [::1]:8080 -> 9898

manifestのenvで定義されている「PODINFO_UI_MESSAGE」の値が表示されているっぽい f:id:JunichiMitsunaga:20191003190816p:plain

ここからはmanifestの内容を変更してgithubにpushしてみます PODINFO_UI_MESSAGEの内容を「Hello!!」に変更後,push

          env:
            - name: PODINFO_UI_MESSAGE
              value: "Hello!!"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 9898
          readinessProbe:

Defaultでは5分単位で同期を取るようですがすぐに確認したかったためコマンドを実行します

fluxctl sync --k8s-fwd-ns flux

同期を取った時に監視していると差分検知されて自動的デプロイされたことがわかりました

kubectl get po -n demo -w

NAME                       READY   STATUS    RESTARTS   AGE
podinfo-f55d5f6d9-v4phs    0/1     Pending   0          0s
podinfo-f55d5f6d9-v4phs    0/1     Pending   0          0s
podinfo-f55d5f6d9-v4phs    0/1     Init:0/1   0          0s
podinfo-f55d5f6d9-v4phs    0/1     Init:0/1   0          2s
podinfo-f55d5f6d9-v4phs    0/1     PodInitializing   0          3s
podinfo-f55d5f6d9-v4phs    0/1     Running           0          4s

再度アクセスしてみると表示が「Hello!!」に変わっています f:id:JunichiMitsunaga:20191003191555p:plain

所感

ひとまず動作させることを目的としていたので思っていたより簡単に導入出来て良かったです。 GitOpsはkubernetesを運用していくにあたって非常に強力なプラクティスになると思うので引き続きfluxを掘り下げていこうと思います。

参考

今回は全体的に公式ページを参考にさせて頂きました。 チュートリアルはシンプルでイメージを掴むのに最適だと思います。

https://docs.fluxcd.io/en/stable/index.html

現在はKustomizeを使ってmanifestを管理しているのでゆくゆくはこちらも試してみたいです。

https://docs.fluxcd.io/en/stable/tutorials/get-started-kustomize.html

local環境でのcluster構築はminikubeでも良かったのですがdocker desktopが既にinstallされていたのでそちらを使っています

https://qiita.com/yoichiwo7/items/0b2aaa3a8c26ce8e87fe

https://qiita.com/comefigo/items/f7bc852a63797934d641