アラート検知型デイリースクラムに移行した話

こんにちは。Groovesエンジニアリングマネージャーのloasnirです。 Groovesにはいくつかの開発組織がありますが、本日はスクラム開発を実践し、私がスクラムマスターを務めているForkwellの開発組織について、日々の検査の場であるデイリースクラムを改善した話をしてみようと思います。

まずスクラム開発を実践している方には馴染みのある話かと思いますが、スクラムガイドによると、スクラムは意図的に不完全なものであるとされています。以下に2020年版のスクラムガイド(日本語)の「スクラムの定義」から抜粋してみます。

スクラムはシンプルである。まずはそのままの状態で試してほしい。そして、スクラムの哲学、理論、構造が、ゴールを達成し、価値を⽣み出すかどうかを判断してほしい。スクラムフレームワークは意図的に不完全なものであり、スクラムの理論を実現するために必要な部分のみが定義されている。スクラムは実践する⼈たちの集合知で構築されている。スクラムのルールは詳細な指⽰を提供するものではなく、実践者の関係性や相互作⽤をガイドするものである。

スクラムガイトとは文字通りガイドラインであって、実践するチームの内情に合わせて肉付け(アレンジ)をしていくことが許容されているんですね。

さて、今回の本筋であるデイリースクラムですが、その役割は大きく4つあります。

  • コミュニケーションを改善する
  • 障害物を特定する
  • 迅速な意思決定をする
  • その結果、他の会議を不要にする

この4つの役割が果たされている限り、アレンジをする必要はありません。 後に説明しますが、私たちのチームではほとんどの項目に課題が見つかったため、デイリースクラムを改善しようという流れになりました。

デイリースクラムとForkwell開発の歩み

Forkwellの開発は2012年から続けられていますが、紆余曲折あって2021年1月からメンバーを再編して再始動しました。それ以前からスクラム開発は取り入れられていましたが、再出発を機に、まずは純粋なスクラムの形でやってみる運びとなりました。守破離でいう「守」を実践しようという話です。この時は、すでにスクラムガイド2020年版が発表されていましたが、理解が十分ではなかったため2017年版を基準として採用しました。その後2020年版へ移行していくのですが、本筋からは外れるため割愛します。

また、弊社は多様性のある働き方を実践するため、コロナウィルスが世界的な流行となった2020年よりも以前から、リモートワークを推進しています。Forkwellのスクラムチームもこの流れを踏襲しており、すべてのスクラムイベントをオンラインで実施しています。これを実践するために、いくつかのオンラインサービスを利用することにしています。以下に代表的なものをピックアップしてご紹介します。

これらを利用した初期のデイリースクラムが、どんな感じで進行していたのかを見てみましょう。

アジェンダ

  1. アイスブレイク
  2. 確認パート on JIRA
    1. スプリントゴールの確認
    2. バーンダウンチャートの確認
  3. 検査パート on Googleドキュメント
    1. 開発チームがスプリントゴールを達成するために、私が昨日やったことは何か?
    2. 開発チームがスプリントゴールを達成するために、私が今日やることは何か?
    3. 私や開発チームがスプリントゴールを達成する上で、障害となる物を目撃したか?
  4. 共有パート

これらを毎朝実施し、Googleドキュメントに記録していくスタイルを採用していました。 運用していく中で検査パートの会場がMiroへ移行され、俯瞰的に状態を検査できるようにするなど、細かいチューニングは行われていました。大筋はこの形で2021年9月まで続きました。

Miroでの記録はこんな感じです。

f:id:grooves:20211112173455p:plain
デイリースクラムの様子

課題の発見と対処

スクラム開発にはスプリントレトロスペクティブというイベントがあります。これは「品質と効果を⾼める⽅法を計画する」という目的を持ったイベントで、私たちはKPTという手法をこのイベントに導入しています。KPTではスプリントで起こった事実をKeepとProblemに分類し、次のスプリントで実施するTryを考えるのですが、デイリースクラムについて以下のようなProblemが提起されました。

  • アラートの発覚がスプリント後半になり、挽回できない。
  • 1人1人の確認に時間がかかり、タイムボックスを超過することがままある。
  • 検査パートが作業報告になっている。

これらを解決するために、Tryを考えるパートでは以下のようなやりとりが交わされてました。

  • 作業報告になりがちなのは問題?
    • 終わったことを知ってもできる事はないし、その時間がムダなのでは。
    • デイリースクラムの目的は状態検査なので、順調かそうでないかだけで良いはず。
  • 各々がアラートを自己申告するという方法について
    • メンバーが十分に自走できている場合
      • それで良い
    • メンバーが自走できない場合、つまり自分でアラートを上げられない場合
      • キャッチアップする仕組みが別途必要
  • 最終日はレビューとフィードバック対応で終わる段取りが良い
  • キャッチアップする仕組み
    • ScMの方で検討するが、全体を俯瞰して粗探しできるとよいか?

これを受けて、それぞれに対処を行います。

まずは検査パートをアラート自己申告制に変更しました。これはデイリースクラムの検査パート中で「アラートがある人はいますか?」という問いかけを行う方法です。これによって、各々の確認のための時間を削減でき、タイムボックス内で完了できるようになりました。加えて、作業報告になりがちという問題にも対処できました。

次に、潜在的なアラートを検出する手法についてですが、これは2つの手段を用いることとしました。 1つ目は全体を俯瞰するためのダッシュボードです。JIRAでは利用者が自由にカスタマイズできるダッシュボードが提供されているため、こちらを利用して全体を俯瞰できるようにしました。

f:id:grooves:20211108181434p:plain
ダッシュボード

2つ目は、スプリントのある時点において各種の値がどういう状態になるのが適切なのか?の定義です。現時点ではあまり厳密には決めていませんが、おおよそ以下の様な取り決めにしてあります。前提として、スプリントの長さは2週間です。

  • 2日目
    • レビュー詰まってる場合は優先的に見よう
  • 4日目
    • レビュー詰まってる場合は優先的に見よう
    • 大きめのタスクはプランニングを確認しよう
  • 6日目
    • 大きめのタスクはプランニングを確認しよう
  • 7日目
    • レビュー詰まってる場合は優先的に見よう
    • 終わりそうにない課題はPOと相談しよう
  • 8日目
    • 今日中に、すべてレビュー中に持っていけるかを確認しよう
  • 9日目(最終日)
    • スプリントレビューの準備をしよう

最終的なアジェンダは以下の通りです。

アジェンダ

  1. Miroを更新しながらアイスブレイク
  2. 確認パート on JIRA
    1. スプリントゴールの確認
    2. バーンダウンチャートの確認
  3. 検査パート on Miro
    1. アラート自己申告
    2. ダッシュボードで潜在的な問題を検出
  4. 共有パート

効果

いくつかありますが、もっとも効果を実感できている部分はベロシティです。グラフからはちょっと分かりにくいですが、スプリント中盤以降の安定感が増していて、達成見込みが早い段階で立てられるようになりました。このおかげで、スプリント最終日は心穏やかに過ごせる。

f:id:grooves:20211112173240p:plain
ベロシティとチームストレングス

このグラフについての補足

  • チームストレングスは直近5スプリントのコミット数の平均値。
  • 8/13スプリントのコミット数が突出していますが、これは7/30スプリントでギリギリ達成できなかった分が積まれているから。
  • 8/27スプリントでコミット数が減少しているのは、メンバーが長期休暇*1に入り、一時的に離脱したため。

また、当初期待されていたタイムボックスを守るという部分についても達成できており、かつ短くなった時間の中で十分な検査が実施できています。

最後に

今回は、Forkwellの開発組織におけるデイリースクラム改善の話をさせていただきました。スクラムはチームによって適するやり方が異なります。私たちの改善方法が合わない場面というのも往々にしてあるかと思いますが、改善事例の1つとして認識いただけると幸いです。

最後になりますが、私たちGroovesは一緒にサービスを良くしていってくれる仲間を絶賛募集中です。Forkwellの開発組織へ配属になった暁には、この改善の続きを私たちと一緒にやってみませんか?興味を持っていただけた方は、是非弊社の求人をご確認ください。

*1:弊社には一定の条件を満たすと長期休暇を取得できる福利厚生制度があります。詳しくは弊社求人情報をご覧ください。

インフラの改善、後回しになってませんか? プロダクト開発のスピードに置いていかれたインフラを「ちゃんとする」ためにやったこと

こんにちは。grooves エンジニアの福井(@bary822)です。今日はインフラ負債の解消についてお話したいと思います。

プロダクトがローンチしたばかりの頃はとにかく新機能開発を優先することがほとんどかと思いますが、ユーザー数がそれなりに増えて障害発生時の影響が大きくなると信頼性を担保することも重要になってきます。

しかし、これまで機能開発をメインに行なってきた開発者にいきなり「信頼性だ!」と言っても何をしてよいかわからないこともあるでしょう。

信頼性を向上させるための施策は主にインフラレイヤーで行われることが多いですが、groovesはいわゆる「Railsフルスタック」のエンジニアを中心に採用してきた経緯があり、インフラは初期構成から大きく改善されないまま数年が経過していました。この間、AWSなどのインフラ系クラウドサービスには新サービスが続々と誕生したり、様々なサポートが追加されたりしてそれを活かさないだけで機会損失が発生してしまうという状態が継続していました。

この課題はgroovesが開発する Crowd Agent, Forkwell という2つのサービスで共通して存在するものであり、それぞれを個別のチームで解決するというよりは画一のソリューションを両者に適用していったほうが効率が良さそうに思えました。

そこで私はこれまで溜まったインフラ負債の解消と、これから負債が溜まらないように体制を確立することを目的とした専門組織「クラウド推進室」の立ち上げを行うことにしました。

このエントリーでは実際に立ち上げの際に行ったことやこれまでの施策とその成果についてお話します。同じような課題を抱えているけど、どうやって解決していったらよいか悩んでいる方に向けて解決のヒントとなれば嬉しいです。

課題スコープの定義

一番最初に行ったのは数多く存在するインフラにまつわる課題の中で、新しく立ち上げるチームが解決すべきものを抽出することでした。大量の課題を見境なく全て解決しようとすると本当に解決すべき課題にフォーカスできなかったり、解決する価値があまりない課題に大量のリソースを投下してしまう恐れがあります。

当初、溜まったインフラ負債によって「モダンなインフラ」では発生しないような運用コストがかかっていることや、不十分な監視基盤によって障害対応に時間がかかってしまう、現状を正しく把握できないと言った問題を課題スコープの中心と据えることを考えました。しかし、ここで踏みとどまります。

理由は、現状の課題を解決するだけではまた新たな負債が溜まり同じことを繰り返すと思ったからです。それよりも日々の開発の中で適切にインフラを新しくしたり、新機能の設計段階から適切なインフラ構成を行えるようし、持続可能な形でインフラ負債が溜まらないようにする仕組みを構築すべきだと考えなおしました。

そこで大方針として解決する課題のスコープを (1) インフラ負債の解消 (2) インフラ負債が溜まってしまう体制の改善 とすることにしました。具体的には以下の4つです。

  1. 不十分でレガシーなインフラ構成、監視基盤による弊害 - (1)
  2. ナレッジの分散 - (2)
  3. インフラスキルの偏在、属人化 - (2)
  4. インフラ領域への投資妥当性判断を行いづらい - (2)

まずは旧式のインフラ構成によって不必要なメンテナンスコストがかかっている問題や、十分な監視が行えず信頼性が担保しづらい、デバッグに時間がかかってしまっている問題を解決します。

また、各サービスでこれまで培われてきたノウハウや業界のベストプラクティスなどの知識を集結し、それを開発者全員に教育することで日頃の開発活動の一環としてインフラのアップデートを行える状態にする。また、そのための工数を合理的に捻出するためにプロダクトマネージャーがインフラ領域への投資判断をできるような仕組みを構築するというものです。

ソリューション検討

次に前述の課題を具体的にどうやって解決するかを考えていきます。解決したい課題の本質はあくまでも「負債が溜まらないような体制の確立」であるため、短期的な解決だけにならないように気をつける必要があります。

何度も議論を重ね、私のチームでは以下の4つを軸にソリューションを展開することにしました。

モダンなインフラ構成にリプレイス

従来のEC2を中心としたインフラで構成されていたアプリケーションの各種サブコンポーネントやデータパイプラインをできるだけフルマネージドなインフラサービスに移行することでメンテナンスコストの削減や高可用性の担保を目的とするものです。

メインで担当していたメンバーの退職やチーム体制の変化によって発生するコンポーネントの引き継ぎに発生するコストの増大や、開発・運用を行うための知識やノウハウが属人化している状態が長らく問題視されていたため、できるだけ自分たちで管理する領域を小さくしていくことでこれを解決しようとしました。

コード化された監視パッケージの提供

これまでサービスごとに個別、かつ無秩序に実装されてきた監視・アラートをコード化し、サービス横断で利用できるような形で提供します。

具体的にはDatadog MonitorをTerraformでコード化し、監視のテーマごとに1つのレポジトリに切り出して管理します。このレポジトリは複数のサービスで利用できるように適度に抽象化監視パッケージを提供します。

また、サービスに大きな影響があるようなエラーが発生した時にその原因を早く見つけ出すことができるように各種メトリクスを1つの画面にまとめたDatadog Dashboardも同様に1つのレポジトリに切り出します。

groovesが展開するサービスはいずれもWebサービス、かつ人材ドメインに特化したものであるため、見るべきメトリクスやアラートを上げるべきしきい値は共通しています。共通のパッケージとして提供するメリットが大きいことは明らかでした。

SLOの策定、エラーバジェットの運用開始

開発チームがインフラ領域の改善を継続的に行うためには、プロダクトマネージャーと開発者が共通の指標を元に開発リソースを投下すべきかどうかを判断できるようにする必要があると考えました。

SLOはまさにこのために機能します。

f:id:grooves:20211101141519j:plain

エラーが起こりづらいアーキテクチャへの作り変えや、コードレベルでのリファクタリング、パフォーマンス改善など、開発者が手を付けたくてもそのきっかけがなくて中々行動に移せない信頼性向上のための改善を行うための工数を確保するためには、SLOやエラーバジェットなどSREのプラクティスを導入すべきだと判断しました。

インフラ知識、トレーニングの提供

これはまさに専門性の高いチームが価値を発揮するソリューションです。

AWSやDatadogなど、各種インフラサービスの専門知識を豊富に備えたメンバーからアーキテクチャのコンサルティングを受けたり、ハンズオン形式のトレーニングを中心に開発者自身のインフラスキルを向上を図ります。

最終的には各開発チーム内で自然とインフラスキルの平滑化が進み、メンバー間のスキル差が小さくなることでコンテキストを共有し、品質の安定化や説明コストの最小化を狙っています。

説得のための材料集め

ここまで来れば新チームが行う活動が日々の業務レベルでかなり明確になってきています。自分の中では成果が出ることの確信が持ててきていますが、組織で働いている以上ステークホルダーの承認を得る必要があるでしょう。

多くの意思決定者が欲しい情報は、(1) どんな成果が出るか (2) それにはどのくらいのコストがかかるか ということだと思います。いわゆるコストパフォーマンスというやつですね。

今回の場合は得られる成果が主に信頼性向上ですので、過去発生した大きなエラーで損失した金額を計算して、どのくらい減少しそうか試算してみると良いでしょう。

また、開発チームがモダンなインフラサービスを活用できるようになることで実装工数が小さくなったり、メンテナンスコストの減少も見込まれます。

コストに関しては人件費とほとんど同義です。どのくらいの期間で上記成果を上げられるかをざっくりのタイムラインにまとめました。もちろん、タイムライン通りに計画が進まないリスクがあることや、タイムライン上の具体的なマイルストーンが変更されることも合わせて説明します。

私の場合、このエントリーに書いた情報を1つのドキュメントにまとめて「マスタープラン」として意思決定者に提出、説明することで承認をもらいました。

まとめ

専任のインフラチームを持たない組織では開発チームが継続的にインフラ領域の改善を行う難しく、それが故にいざとなると何から手を付けてよいか分からないことも多いのではないでしょうか。

私達は「クラウド推進室」という専門組織によって持続可能な方法で開発チーム自身が適切にインフラを管理できる状態をつくることが望ましいと考え、その実現に向けて活動しています。

余談になりますがクラウド推進室では課題選定から実装までの活動を非常にユニークなプロセスを使って行っています。詳しくは別のエントリーにまとめていますので、こちらもぜひ併せてご一読ください。

tech.grooves.com

groovesでは開発エンジニアを筆頭に、多くのポジションで一緒に働く仲間を募集しています。リモートワーク制度、フレックス制度を採用しているので仕事とプライベートを両立した働き方が可能です。沖縄、北海道、長野など首都圏以外から働くメンバーも多数在籍しています。

開発チームに関しては2017年頃からフルリモートを前提とした組織体制を構築しているため、リモートならではの様々な課題に向き合い、乗り越えてきた歴史があります。リモートで働きたいけれど実際やってみるのはちょっと不安がある、開発以外の他のメンバーの理解が得られるか心配、自分がリモートで成果を出せるかイマイチ自信がない、という方こそぜひお気軽にエントリーしていただけると嬉しいです。

jobs.forkwell.com

Basecamp社のプロダクト開発メソッド「Shape Up」を6ヶ月実践した振り返り

こんにちは。grooves エンジニアの福井(@bary822)です。

突然ですがみなさんはスクラム以外でソフトウェア開発を行ったことはありますか? 私はありませんでした。

私が社会人としてお金を頂きながらコードを書き始めた2014年頃、スクラムは当時としては画期的な概念をソフトウェア開発に持ち込んだ革新的な存在であり、それを採用しているのはいわゆる「イケてる開発チーム」でありました。そして私は幸運にもこのイケてるチームでソフトウェアエンジニアとしてのキャリアをスタートした一人だったのです。

それから7年という、この業界では長いとされる年月が過ぎてスクラムは大衆化しました。私の感覚ではWeb界隈の自社開発企業ではデファクトスタンダードになっていると思います。

実際、Forkwell Jobsで「スクラム」と検索すると300件以上の求人がヒットします。組織の実情や置かれている環境によってその形は様々かと思いますが、スクラムは多くの開発チームに支持されているようです。

もし私が新しい開発チームを立ち上げるとしたら、何の疑いもなくスクラムを採用していたでしょう。なぜなら私はそれしか知らなかったからです。何も整備されていないチームに経験していない新しい開発手法を取り入れるのはリスクが高すぎるため、合理的な判断とは言えないでしょう。

そんな中、今年の1月に出会ったのが「Shape Up」でした。

Shape Up

Shape UpはBasecamp社で実践されているプロダクト開発手法です。

同社が15年以上のプロダクト開発から得た経験や、上手く機能したプラクティスを抽出して開発プロセスとして整理したもので、アジャイルでもスクラムでもない独自の思想、概念が数多く散りばめられてます。

Basecamp社といえばRuby on Railsの作者であるDHHが共同創業者であることで知られているだけでなく、米国内のおいてはそのユニークな経営方針や働き方が話題に上がることも多く、オピニオンリーダー的な側面も持っています。

かく言う私も同社のファンであり、特にPodcastシリーズのREWORKは毎回欠かさず聞いていました。

そんな中、あるエピソードでShape Upを一般に公開することにした、という発表がありました。しかもWeb版は無料で読めるとのことで、早速流し読みしてみるとなんだか良さげです。スクラム開発にどこか窮屈さを感じていた当時の私に一つの答えを与えてくれるような内容が盛り沢山です。これはじっくり読みたい! と思い、有料の書籍版を購入して読み進めることにしました。

shape-up-book-photo
読み返したい本は紙で持っておきたい派です

特徴

詳しい内容はぜひ原書で読んでいただきたいので、ここではShape Upにおける特に重要な用語と開発の進め方を簡単に紹介していきます。

Shaping

shaping-overview Shapingはいわゆるプランニングのフェーズで、「何を作るか」を言語化して形作っていきます。

プロダクトの戦略や中長期的な目標をベースとしたあるべき姿と現実とのギャップを抽出し、それを埋めるために必要なピースを適切なスコープで形作るようなイメージです。

ここで最も重要なのはソリューションを適度な抽象度で記述することです。

原書によると"Wireframes are too concrete. Words are too abstract."とのことです。つまり、ワイヤーフレームまで細かく落とし込むとエンジニアが仕様を調整したり、デザイナーが創造性を発揮できる余地がない。また、言葉だけで作りたいものを伝えようとすると十分な情報が伝わらず、思っていたものとは異なる成果物が出来上がってしまう。ということです。

(Basecamp社でShapingを行うのはいわゆるプロダクトマネージャーや時には共同創業者のJason Fried自身が担当することもあるそうです。)

原書にはBasecampのカレンダー機能を例として実際にShapingが行われる様子が細かく記載されています。ぜひご覧になってみてください。

Appetite

AppetiteはShapingを行う時に考慮すべき項目の一つです。直訳すると「食欲」ですが、個人的な意訳は「希望工数」としています。

通常スクラムなどアジャイルベースの開発プロセスでは、課題選定 -> ソリューション -> 見積もり という順番で「この課題を解決するにはこれくらい工数がかかる」という観点から優先度をつける際に考慮することが一般的です。

しかし、Appetiteはこれと逆の発想です。つまり、 課題選定 -> 解決にふさわしい工数上限(希望工数) -> ソリューション という流れでプランニングが進行します。

希望工数の根拠を示すのは簡単なことではありませんが、例えばその課題解決によって削減される工数や防止できる機会損失額などを引き合いに出してROIを意識したものにすると説得力があるものとなりやすいです。

原書ではAppetiteを考える際に、1~2人の開発者が1~2週間でリリースできる「Small Batch」と1チームが6週間を費やす「Big Batch」のどちらかのサイズに当てはめるて考えることが一般的であるとのことでした。

Pitch

Shapingで考案したソリューションや算出したAppetite、その他の要素をまとめて1つのドキュメントとしてまとめたものがPitchです。

Pitchのフォーマットは定められていませんが、以下の要素を含むものだとされています。

  1. Problem (解決したい課題)
  2. Appetite (希望工数)
  3. Solution (どのように課題を解決するか)
  4. Rabbit Hole (リスク回避のために考慮すべきこと)
  5. No-gos (やらないこと)

実際に見てもらうのが一番イメージしやすいかと思いますので、Basecamp社が公開しているものをいくつか掲載しておきます。

Pitchを書くにあたって、時には開発者に実現可能性をヒアリングしたり、関係者間で議論を重ねることもあるそうです。このような作業を繰り返すことで質の高いドキュメントが出来上がります。

Betting Table

betting-overview

Pitchを持ち寄って次の開発サイクルで実際にどれにGoを出すのかを決定するミーティングがBetting Tableです。

(Basecamp社では1サイクル = 6週間 で回しています)

参加者はCEOやCTOなど経営幹部クラスやシニアプログラマ、プロダクトチームのリーダー格など、チームを代表するメンバーで構成されます。

CxOクラスの人は得てして時間が取れないことが多いものですが、内容が洗練されたPitchを参加者全員が事前に読んでおくことが参加条件となっているため、Betting Tableは通常 1〜2時間程度で終わるとのことです。

ちなみに"Bet"というワードが選ばれた背景として、(1) 投資にはリスクが伴うこと (2) 関係者全員がそれにコミットすること という意味が込められているそうです。

採用されなかったPitchは担当者個人が持ち帰り、次のBetting Tableまでに内容をより魅力的にしたり、計画を変更するなどします。

Building

building-overview

実際に手を動かしてソリューションを現実のものにしていくのがBuildingです。

Pitchにある「丁度いい抽象度」のソリューション案を実装可能な開発タスクに分解し、それを自らの手で実装していくのが開発者の責任です。個別に分解された細かいタスクを開発者にアサインするのではなく、開発者自身で設計から実装まで責任を持って行うことで "Code Monkey" になるのを避けるべきだと言及されています。

タスクはTo-doリストとHill Chartと呼ばれるユニークな曲線グラフを使って進捗を可視化することになっていますが、この詳細については説明が長くなってしまいますので原書でご確認ください。

Cool-down

6週間のBuildingが終わると、2週間のCool-down期間に入ります。

開発者、デザイナーはこの期間の時間を基本的に自由に使うことができます

Building期間中に生まれたり前から気になっていたバグを直したり、なにか新しい技術を試す、次に何をやるべきかを考えるなど、日常の開発からは一歩離れて全体を見直したり、一息ついて次の開発サイクルに備える期間とされています。

試してみた

前置きが長くなってしまいました。いよいよ私のチームでShape Upを採用するにあたってアレンジを加えた点や、やってみて得た気づきを共有していきます。

前提として私のチームは「クラウド推進室」という、主にインフラレイヤーに責任を持つものであり、ユーザーの目に見える機能を開発するチームではない点にご留意ください。(このチームが誕生した経緯は別のエントリーでまた詳しく共有したいと思います)

6週間は長すぎる

Basecamp社ではBuildingに6週間という時間を使っていますが、私達にとってはこれが長すぎました。6週間を使って作るべきものを計画するのはインフラを構築・改善するチームにとって適切なスコープで課題を切り出すのに大変苦労しました。つまり、「6週間を使ってでも作るべきもの」を探すことができなかったのです。

また、Cool-down期間を加えると8週間という時間は変化の激しいベンチャー企業にとってはアジリティの不足感が否めませんでした。アプリケーション開発と比べるとその程度は落ちるものの、8週間の間に注力すべき領域が変わったり、リリース期限に厳格な機能リリースに関連したインフラ構築依頼がアプリケーション開発チームから飛んでくることも多々あります。

現在のところ私のチームでは3週間をBuilding期間とすることで、Shapingにおいて十分な価値を提供する課題を、手に収まるサイズのスコープで切り出せるようになりました。

また、原書にもある「価値のある仕事をするために十分長く、最初から期限を意識できるほど十分に短い」期間として機能しているように感じます。

PM不在のチームでは誰がShapingを行うのか

Shape Upの一連のフローはどうやらShapingを行う人(PM)とBuildingを行う人(プログラマ、デザイナー)の分担が明確に行われている前提であるようです。つまり、ShapingとBuilding(Cool-down)が並行して走っているイメージです。

これに対し、私のチームでは専任のPMが存在しません。開発者自身が課題を発見してそれをどのように解決するかを計画することから、実際にそれを実装・リリースするまでを広く担当することになっています。

Shape Upを私のチームに適用するために、ShapingをCool-down期間中に行うこととしました。Cool-downの本来の目的である開発者の自由を尊重した活動を行う機会が減る懸念はありましたが、チームで合意の上やってみることにしました。

また、Buildingを6週間 -> 3週間に短縮したことで本来は1週間となるCool-down期間ですが、これを2週間に延長することでバランスを取ることにしました。

今のところ 2週間のShaping + Cool-down -> 3週間のBuilding をシーケンシャルに行うフローが質の高い課題選定を行いつつ、持続可能な開発を行うことができる組み合わせとして機能しているように感じます。

他チームからの要望

私のチームがインフラレイヤーを担当している都合上、アプリケーション開発チームからの要望に答えることは避けては通れない道です。新機能のためにAWSサービスを使ってサーバーレスに実装したい、MVPのために捨てやすいインフラを構築してほしいなど、その種類は多岐にわたります。

これが一番やっかいなのは、Bettingにて優先度を決める場面です。

自チームからのPitch(施策)は基本的に自チームの目標を達成に寄与するかどうか軸として優先度を決定することができます。これに対して他チームからの要望は他チームの目標を達成するために存在します。それぞれが独自の目的を持っているため、自チームと他チームの施策の優先度を並べて評価することはできません

この問題に対する私達の解は「あらかじめ他チームからの要望に対する工数を分配しておくこと」でした。

Bettingに先立って、Buildingで使える工数を自チーム、他チームに分けてあらかじめ提示しておきます。現在のところ 自チーム:他チーム = 7:3 の割合で工数を分配しています。

事業部としての優先度や環境の変化によってこの割合は変化させることを前提としていますが、今のところこの割合で運用してみて目立った問題は発生していません。

スクラムとの比較

ここまではShape Upでの開発の流れと、私のチームに適用する時にアレンジした点をお伝えしました。ここでは少し視点を変えて慣れ親しんだスクラムとの主な違いを紹介します。

(ちなみに私自身はスクラムよりもShape Upが好きです。かなりバイアスのかかった比較となっていますので、あらかじめご了承ください)

バックログ

スクラムが中央集約型バックログなのに対し、Shape Upでは分散型バックログと言えるタスク管理を行っています。

Betting Tableにて採用されなかったPitchはその著者に返されます。著者はそれをブラッシュアップしてより魅力的なPitchにしたり、スコープを小さくする代わりに希望工数を減らしたりして次のBetting Tableで採用されやすくする準備を行います。もちろん、次のBetting Tableまでに状況が変わって取り組む価値が無いと判断した場合はBetting Tableに持ち込まれることはありません。

個人的にはこの仕組みが大変気に入っています。スクラムでよくありがちな「とりあえずタスク化しておこう」で高く積み上がっていくバックログを見て永遠に終わりがないような感覚に陥ることも無いですし、何よりバックログをメンテナンスするコストがかかりません。

私のチームのように少人数でありながらも価値の高い成果物を提供し続けるためには、課題選定 -> 実装・リリース のサイクルを打率よく回すことが求められますが、Shape Upはまさにこれに適していると考えます。

見積もり

先にも少し触れましたが、Shape Upでは「この課題を解決するのにどのくらいの工数をかけられるか」という視点でタスクに対する工数割り当てを決定します。スクラムでは往々にして「開発チームから出た見積もりが大きすぎたからスコープ調整しましょう」という会話がなされ、PM - 開発チーム間でどこまでなら現実的に投資可能な工数で実現できるかというコミュニケーションが頻繁に発生します。

これに対しShape UpではPitchを書く時点で費用対効果(開発工数 vs 課題解決の価値)を考慮したソリューションを考えます。簡単な作業ではないため最初のうちは希望工数の算出に苦労するかと思いますが、この工程を経ることでオーバーエンジニアリングしてしまったり、逆に解決する価値があまりない課題のために工数を支払ってしまうリスクを低減させることができます。

開発サイクル

スクラムが通常1~2週間のスプリントを回すのに対し、Shape Upではデフォルトで8週間が1サイクルとなります。これは市場への投入スピードが重視されるスタートアップにとって許容できる長さではないかもしれません。

6週間のBuildingが推奨されていますが、私は自分たちのプロダクトが置かれているマーケットの環境や求められるスピード感に応じてアレンジすることも1つの手かと思っています。

また、スクラムの大枠の流れは変えずに期間だけを試しに6週間にしてどのような変化が生じるのかを観察してみるのも良いと思います。

ミーティング

スクラムではスクラムイベントとしてスプリントプランニングやバックロググルーミングを行います。チームによってはそれに追加してバックログをメンテナンスするための何らかの活動を行っているかもしれません。これはバックログのタスクに対して適切な優先度をつけたり、メンバー間で理解のばらつきがない状態を保つためには必要なことですが、同時に実装に費やす工数が減ってしまうこととのトレードオフの関係にあります。実際、私がスクラムで開発していた頃は全体の約50%しか実装に使うことができませんでした。

これに対しShape Upでは定期イベントと呼べるものはBetting Tableだけです。もちろん必要に応じてミーティングを設定することもありますが、それでもBuilding期間中は全体の90%以上の工数を実装に当てることができています。

スクラムは高い透明性を確保することやスプリント期間中に生じた問題を振り返り、改善を積み重ねられるように設計されていることがメリットではあるのですが、「スクラムイベントに割く工数が多すぎてもっと重要なことにフォーカスできていないのではないか」という疑問を抱いていた私にとってShape Upはまさに最低限の工数で最大限の成果をあげるための開発手法であったと言えます。

最後に

いかがだったでしょうか。

今回はShape Upの概要や、私のチームで実際に運用して得た気づき、またチームが置かれた環境に適用させるためにオリジナルからどのようなアレンジを加えたかを紹介しました。

日本国内でShape Upを導入しているチームはまだまだ少ないように思います。もし私達以外にもShape Upを実践している人やこれから試してみたい人がいらっしゃいましたらぜひ意見交換できればと思います。どんな開発を行っているのか、やってみて得られた変化、アレンジした点、導入するに当たって心配している点などお気軽にコメントいただければ幸いです!

また、弊社ではアプリケーション開発エンジニアを募集中です。募集中の求人で配属されるチームではスクラムを採用していますが、groovesはチャレンジに非常に寛容な会社です。私が行ったように実績のない開発手法を導入することも快く受け入れてくれます。ぜひ一緒に働きましょう。

RubyKaigi Takeout 2021 にてプラチナスポンサーでの協賛をします!

RubyKaigi Takeout 2021 いよいよ来週開催ですね。 grooves(グルーヴス)でエンジニアリングマネージャーを担当している吉永です。RubyKaigi Takeout 2021のスポンサーができて嬉しいよ!という記事を書きましたのでご覧ください。

グルーヴスは今回めでたくプラチナスポンサーとして協賛することになりました。私たちは「はたらくヒトと、未来を拓く」というコーポレートビジョンを実現するために、Forkwell(フォークウェル)、Crowd Agent(クラウドエージェント)という2つのサービスをより良くしていこうと開発に取り組んでいます。どちらのサービスもRubyで開発され、長く会社の成長を支えてきました。Rubyがなければグルーヴスはなかった、と言っても過言ではないですね。今回はプラチナスポンサーとして協賛させていただくことで、Rubyへの感謝の気持ちを表現できたことを大変嬉しく思います。

また、スポンサーさせていただくことで、会社のブランディング向上や絶賛募集中のエンジニア採用活動に良い影響がでると良いな、と思っています。今回はプラチナスポンサーということでスポンサー特典の15秒のPR動画を頑張って制作いたしました。用意してくれた弊社のデザイン戦略室のメンバーに大感謝です。良い出来栄えになっているのでイベントに参加された方はぜひご覧ください。

スポンサー特典として、今回はスポンサーチケットを十分な枚数いただくことができました。こういったイベントは日頃Rubyを使って開発しているエンジニアにとって、新しい刺激を得られるまたとないチャンスですので、フル活用させていただく予定です。今回、正社員には業務としてイベントに参加してよく、特にレポート提出の義務も課さず、楽しんでらっしゃい、と送り出しています。残ったチケットは、業務委託として弊社の開発にご協力いただいている方に使っていただくことにしました。

コロナの影響で、このようなイベントの開催も難しい状況が続いています。RubyKaigi Takeout 2021が盛況に終わり、来年また新しい形で開催され、また今回のようにコミュニティをサポートする立場として関われることを願っております。

最後になりますが、弊社ではエンジニアを大絶賛募集しています。興味を持っていただいた方は、ぜひ弊社の求人をご覧いただけると幸いです。

それではRubyKaigi Takeout 2021でお会いいたしましょう!

デザイナーとエンジニアの共通言語を得る輪読会のお話

はじめに

こんにちは、Forkwell 開発チームの tbaba です。最近は暑くなってきたのでドラムを叩くと汗が吹き出てむぎ茶を飲む手が止まりません。

今日は今年の2月くらいからずっと取り組んでいる、「デザイナーとの輪読会」についてお話しようと思います。
弊社には「デザイン戦略室」というチームがありまして、社内のプロダクトやビジュアル、広告のデザインからブランドエクスペリエンスの向上など、様々な制作を横断的に受け持っています。もちろん Forkwell や Crowd Agent などのウェブアプリケーション開発にも関わっております。
そんな彼らが行っている輪読会に、エンジニアである自分が入って何をやっているのか、どんな効果があるのか、をご紹介します。

どうして輪読会をやろうと思ったのか

元々は、デザイナーやカスタマーサクセスチームのみなさんが始めました。
「プロダクトを作っていく上で、エンジニアと会話する際に単語の説明をされてから会話が始まる(「Pumaが・・・あっ、Railsアプリケーションを動かしてるWebアプリサーバーなんですけど・・・」みたいな)、という無駄が発生する」ようなケースも多く、本質的な会話に至るまでに時間がかかることがあったようです。
そこで、エンジニアとの共通言語を増やして、コミュニケーションを取りやすくしたい!という気持ちから、サーバーやWebアプリケーションなどの知識を得るための輪読会を開始した、とのことです。

どうして絡みに行こうと思ったのか

最初はすっごく軽い気持ちで入っていきました。
というのも、元々自分が2020年秋頃から、ゆるゆるとLinuxそのものの再学習を進めておりまして、得た知識を復習したいという気持ちがありました。その目的に対して、輪読会で発言をするというのはとても効率の良い復習方法だと考えたのです。

また、自分の中で今期のテーマとして、「そうやって学習した知識を周りに広めていく」というものがありました。
やっぱり知識は得たなら広めていったほうが自分にとっても周りにとっても良い事だらけです。自分以外に出来る人が増えればそれだけ、チームが成長しますし、周りにとっても出来ることが増えるのはメリットです。

そんなわけで知識を広めていくのに良い機会だと感じたので、「俺も入る〜」とカジュアルに手を上げてみたところ、何やら歓迎されたので、するっと入っていきました。

f:id:harakirisoul:20210707123642j:plain
するっと参加が決まったときのメンションがこちらです。

どんな感じで進行しているの?

基本は事前に対象となる箇所を読んで来て、気になったところについて議論をする、というよくある輪読会の形式です。
少し通常のものと違うのが、「 tbaba がオブザーバーとして参加している」という点です。
何をやっているかというと、

  • 読んできてよく分からなかった点をオブザーバーに聞く
  • オブザーバーはこれに対し、「自社ではこうなっている」という風に回答する

ということをやっています。

なぜこの形式を採用しているかというと、元々の目的が「開発者との共通言語を得て、コミュニケーションを取りやすくするため」だからです。

例えば単にサーバーと言っても、「Web サーバー」「アプリケーションサーバー」「メールサーバー」などなど、多岐にわたります。また、「IP アドレスとは」「IPv4 と IPv6 って何が違うの?」という疑問もあるでしょう。

このあたりを、「Forkwell ではこう言う構成になっていて」「Crowd Agent はこういう風になっていて」という説明をはさみつつ説明していっています。自社プロダクトがどうなっているのかを伝えることで、より具体的な理解につながるのです。

何が変わったのか

単なる輪読会に開発者のオブザーバーを入れることでどうなったのか?これが気になるところだと思います。
というわけでアンケートを取ってみました。
まずは「輪読会の理解度」についてです。

f:id:harakirisoul:20210707123017p:plain
輪読会の理解度はどのくらい増したか

参加者が少ないのと、社内のアンケートのため、公正とは言いづらいかも知れませんが、概ね高評価でした。以下のようなコメントも寄せられており、デザイナーが独自に輪読会を行うよりも効率良く学習を進められたのではないかと思います。

  • 具体例を交えて説明していただいているので、イメージしやすくなった。
  • Crowd Agent や Forkwell では実際どのようにサーバーが構築されているのか、実例を聞くことができたので、自分ごと化しやすかったです。
  • 実務につなげていただいたり、実際の開発エンジニアが理解・関わる範囲を教えていただけるので、理解度が上がりました!

一方で、「開発者とのやり取りがやりやすくなったか」という質問も投げかけてみました。結果はこちら。

f:id:harakirisoul:20210707123103p:plain
開発とのやり取りはやりやすくなったか

真ん中(よくわからない)から、右側(やりやすくなった)のあたりに留まっています。
これについては、まだサーバーのお話、つまりアプリケーション開発そのものよりも低レイヤーの話に終始しているためと思われます。今後アプリケーション開発についての輪読会が開催されれば、こちらも数値が変わってくるのではないかと思います。
個別のコメントとしては、好意的なものを頂いています。

  • 「エンジニアのみなさんの意見や質問内容を理解した上でやりとりができ、進めやすかった」
  • 「リファインメント(バックログを整えるミーティング)でのエンジニア同士の会話などに壁を感じにくくなった」

また、今後何を勉強したいかという話についてもアンケートを取ってみたところ、「ウェブアプリケーション」と「データベース」という2つが票を集めていました。やはり、ウェブアプリケーションのプロトタイプを作っていたり、データ集計・分析をしたりする際のことを考えると、この2つの優先度は高くなるのでしょう。

また、変わった点としてとても大きなものがありました。それは、「質問できる」という点です。
自分が加わるまではデザイナーやカスタマーサクセスと言った、普段エンジニアリングそのものには関わらないメンバーのみで輪読会をしていました。そのため、少し込み入った話が出てくると、誰も答えることができず、疑問解消しにくかったのです。
そこにエンジニアが入ってくることで、疑問を疑問のまま残さないで、輪読会の時間内にしっかりと解消することができるようになりました。これが、デザイナーがエンジニアリングを学ぶ輪読会を行う際に、エンジニアが同席する最大のメリットと言えると思います。

もちろん、エンジニアにとっても悪い話ではありません。人に説明するということは、自分がちゃんと理解していなくてはいけません。つまり、復習の機会になります。それに、デザイナーと一緒に学ぶということはそれだけコミュニケーションを多く取るということでもあります。そうやって一緒に学んだ時間は、きっとその後のコミュニケーションにプラスに働くことでしょう。

最後に少し別の話ですが、前半でも書いたように、今年の自分の中のテーマとして「学習した知識を周りに広めていく」というのがありました。これが少しでも広まっていくのがアンケート結果からも実感できたのが、かなり嬉しかったです。

まとめ

世の中のデザイナーの皆様の中には、エンジニアとコミュニケーションをして作る時に、「こいつ何言ってんだ」と思うときがある、という方もいらっしゃることでしょう。
しかし、それは今回の自分たちのように、一緒に学ぶ場を作ったり、歩み寄ったりすることで解消できることがとても多いと思います。
何か困ったことがあったらエンジニアに相談してほしいし、エンジニアも困りごとはデザイナーに相談するような信頼関係を持つことと、お互いがお互いの専門領域について多少なりとも知識を持つことで、円滑にお仕事を行っていけるような関係が持てると、かなり強いチームになれるのではないでしょうか。

正直そんなに深く考えないで始めた取り組みですが、今では「やってよかったし今後も続けたいなぁ」と考えております。

# そういえば、デザイナーがエンジニアに教える輪読会があっても良いかも知れませんね。

最後に

そんな grooves 社では現在、一緒に働いてくれるエンジニアを募集しています。

jobs.forkwell.com

jobs.forkwell.com

もし興味があれば、ぜひ一度ビデオ通話などでお話しをさせてください。

Reactを使うならRecoilも学べば良いと思うって話

こんにちは、 tbaba です。元々 Rubyist として入社していますが、ここ2〜3年はフロントエンド力の向上にも力を注いでおります。

突然ですが、React で状態を管理する時に何を使っていますか?クラスコンポーネントにしてクラスに状態をもたせている、Redux を使って管理している、React Hooks で管理している、などなど色々な選択肢があるかと思います。

そんな中で自分たちのチームは、現在社内向けのアプリケーションにおいて、フロントエンド開発をする際に Recoil という状態管理ライブラリを使うことが多いです。そこで、今日は「なんでそれ使うの」「何が便利なの」みたいな話ができれば良いなと思います。
先に言っておくと、自分のスキルセットとしては「 TypeScript を利用した開発2年目」「React を利用した開発3年目」「基本は Ruby on Rails が得意なバックエンドエンジニア」です。なので React の状態管理について理解の浅い点があるかもしれませんが、ご了承ください。

なぜ Recoil を使うのか

端的に言うと、Redux を使うことに疲れたからです。

Redux は React コンポーネントの状態 (state) を上手く管理するためのフレームワークです。元はデータの状態変化の流れを一本化しようというアーキテクチャの派生としてリリースされて、今では React アプリケーションの状態管理のデファクトスタンダードと言っても過言ではないくらい、様々なプロダクトで利用されていることと思います。

しかし、後述しますが Redux は大きなアプリケーションを作る際には更新処理などを整理してわかりやすく配置することができますが、その特性上複雑であったり、パッと見では理解しづらいところがあります。僕自身、Redux は書けるといえば書けるけど、あまり書きたくないな、と感じてしまいます。特に、よくある「マルチページアプリケーションの画面の一部を React 化する」と言った小規模な開発では使いたくないというのが本音です。

そんな時に React Hooks や Recoil を使うと、驚くほどシンプルにコードを書くことが出来ます。以下、その理由を書いていきます。

理由その1: 状態の持ち方が楽

例えば Recoil では、とある状態を持つときに以下のように設定します。

import React from "react";
import { atom, MutableSnapshot, RecoilRoot, useRecoilValue } from "recoil";

// Todo の id をインクリメントするやつ
let id = 0;
function getId() {
  return id++;
}

// Todo の型
type Todo = {
  id: number;
  content: string;
  isCompleted: boolean;
};

// Todo の状態の定義
const todosState = atom<Todo[]>({
  key: "state/todos",
  default: [],
});

const Todos = () => {
  const todos = useRecoilValue(todosState);

  const contents = todos.map((todo) => (
    <div key={`todo-${todo.id}`}>{todo.content}</div>
  ));
  return <>{contents}</>;
};

// 初期値のセット
const initialize = ({ set }: MutableSnapshot) => {
  set(todosState, [
    {
      id: getId(),
      content: "ご飯を買ってくる",
      isCompleted: false,
    },
    {
      id: getId(),
      content: "手を洗う",
      isCompleted: false,
    },
  ]);
};

export default function () {
  return (
    <RecoilRoot initializeState={initialize}>
      <Todos />
    </RecoilRoot>
  );
}

# RecoilRoot を置いて、その中で Recoil の関数を呼び出すようにしましょう、とかの基本的なことについては、公式ドキュメントを参考にしていただけると分かりやすいと思います。

keyatom を状態を示す一意の値、 default はデフォルト値です。
つまり、デフォルト値を自由に設定できるのが大変便利な上、 TypeScript で型を指定してあげることで、型保証も簡単に出来ます。

同じことを Redux を利用すると、「 reducer を作って」「 store を作って」「 connect して」など、色々とやることが多いですよね。そういうのはキレイさっぱりスキップできます。
状態の更新ですら、Redux なら「 action を作って」「 import して」「 dispatch に食わせて」「 connect して」といった風にしなきゃいけないところ、Recoil だと「 useSetRecoilState を呼び出す」で終わりです。

理由その2: 初期化がすごく分かりやすい

Redux や Hooks などでも初期化はできます。しかし、そのために Provider に store を食わせたり、そのために初期値のオブジェクトをデフォルト値のオブジェクトと手動でマージしたりとやることが多い印象です。 いちいち reducer 作ったりして大掛かりになるのも面倒くさいですね。

ところが、 Recoil はそれすら簡単です。

import React from ‘react’;
import { RecoilRoot, todosState } from ‘recoil’;
import { Todo } from ‘./models’;
import { todosState } from ‘./modules’;

const initialize = ({ todos }: Todo[]) => ({ set }: MutableSnapshot) => {
  set(todosState, todos);
};

export default function (props) {
  return (
    <RecoilRoot initializeState={initialize(props)}>
      <Todos />
    </RecoilRoot>
  );
}

このように App というルートコンポーネントが持っている初期値を、 RecoilRoot が持つ initializeState に食わせるだけで良いのです。その中では set という関数が使えるため、 atom と初期値を渡してあげればそれだけで状態として保持してくれます。
もちろん、 initializeState 関数の中で非同期で取得し、それを set に渡すことも可能です。

非同期の場合は atom 直ではなく selector を使って状態をセットすることも可能なのですが、それはまた別のときにでも。
そういえば、Redux などでは非同期処理のためにミドルウェアを入れたりしますね。 Recoil の場合は最初から対応しているため、特殊なミドルウェアの導入などは必要ありません。閑話休題。

理由その3: 余計なところで状態を読み込まなくて済む

状態管理、面倒くさいですよね。分かります。いろいろ継ぎ足していったらものすごい大きなオブジェクトが完成して、しかもそれがどっか更新するたびに全部更新されるみたいなことが起こりえます。更新したいのはほんの一部なのに!と思うことがありますね。
Redux だと、大きな reducer を作ってあげたり、複数の reducer を combineReducers を使って名前空間が区切られている一つのオブジェクトにする、といった風に、少し工夫してあげる必要があります。が、それを理解するのはしんどいです。React Hooks の Context API で頑張る、でも良いのですが、結局複数の Context を管理する必要があって煩雑でした。

それに対して Recoil は簡単です。それぞれの状態を atom が持っているので、「Aの状態を知りたかったらAの atom を見に行けば解決!」という風にスッキリさせることが可能なのです。

const todosState = atom<Todo[]>({
  key: 'state/todos',
  default: [],
});

const loadingState = atom<boolean>({
  key: 'state/loading',
  default: false,
});

function ComponentA
  const todos = useRecoilValue(todosState);
  const loading = useRecoilValue(loadingState);

  return (
    <>
      {loading ? <div>Now loading</div> : todos.map((todo) => <div>{todo.content}</div>)}
    </>
  );
}

function ComponentB
  // loadingState は見る必要がないので省いて問題がない
  // ここの todosState は、 ComponentA で見ているものと同じものを見ていることになる
  const todos = useRecoilValue(todosState);

  return <>{todos.map((todo) => <div><input type="checkbox" checked={todo.isCompleted} />ステータス</div>)}</>;
}

値を参照したいだけなら useRecoilValue 、参照と代入をしたければ useRecoilState 、代入のみしたければ useSetRecoilState を利用しましょう。

このように、Recoil は一つのオブジェクトに状態を集約させたり、複数の Context を管理したりする必要がありません。 RecoilRoot コンポーネントの中であれば、自由に呼び出すことができる*1ので、とても便利なのではないでしょうか。

まとめ

以上のように、 Recoil はコンパクトで、状態を管理しやすく、Hooks に慣れていれば使うときにもあまり悩まない大変便利な状態管理ライブラリです。基本コンセプトが「コンポーネント間で共有される状態 (atom) 」と「関数 (selector) 」で、それよりも複雑なことはやろうと思えばできるし用意もある、でも基本この2つでどうにかなるよ、というものなのです。
加えて TypeScript との親和性も非常に高く、ここ最近の Redux に心をやられているという方には大変おすすめとなっております。

ただ、気をつけたほうが良いこともあるので、こちらに書いておきます。

実はまだメジャーリリースがない

この記事を書いている 2021/05/31 現在、最新バージョンが 0.3.1 となっています。つまりまだ大変活発に実装が進んでいる、枯れていないライブラリです。そんな状況なので、いつ API が変わってしまうかもわかりません。
加えて、 description には Recoil is an experimental state management library for React apps. とあります。 experimental です。実験的なライブラリなので、無くなる可能性も考慮しながら作る必要があります。もし無くなってしまったっ場合は自分で保守するという強い意志を持ちましょう。

シンプルで自由度が高いがゆえに気をつけたい

atom を利用することで、シンプルに状態を作ることができるのはここまでで理解していただけたかと思います。
しかし、それゆえにぽんぽん自由に状態を突っ込んでいくと、結局のところ「何がどういう風にデータとして入っているのか」「どう更新処理を入れればよいのか」が分かりづらくなってしまうのは間違いありません。
そういう状態になってしまうのを避けるため、可能な限り型を使って安全に入出力値を定義してあげるのをオススメします。
selector などを使って非同期に処理を行う際も同様です。

とりあえず社内のアプリから、いかがですか?

いきなり本番環境に投入するの怖いとかがあるのでしたら、社内で使うようなちょっとした便利アプリなんかに Recoil を導入してみるのはいかがでしょうか?
触っていて面白いですし、これまでそこそこちゃんと設計してやらなきゃいけなかった React の状態管理がサクサク進むというアハ体験を感じることができますよ!

人を探しています

そんな弊社ですが、実は開発チームを技術面からリードしてくれるようなエンジニアを募集しています。
2つのプロダクトとチームがあって、どちらかに入ってもりもりと開発を進めたり、技術的な検証やアドバイスをしてくれる、そんな方を探しているところです。
もしご興味があれば一度、以下の求人から「話を聞きたい」などでコンタクトを取っていただけると幸いです。
(ちなみに tbaba は採用にも関わっており、もし選考に進んでいただけるとなればご挨拶する機会もあるかと思います。その時はぜひお喋りしましょう)

jobs.forkwell.com

jobs.forkwell.com

*1:実装の中身は React Hooks なので、呼び出しの制約は Hooks に準じるのだけ注意です。

リモートワークでも存在感を出すために

はじめに

こんにちは!Crowd Agent 開発チームのmktakuyaです。昨年11月に株式会社groovesに入社し、6名程度のスクラムチームにて主にサーバサイドの開発を担当しています。また、スクラム外でのタスクとしてカスタマーサクセス推進のためのKPI設定やSlackの無駄カスタムレスポンス量産などに従事しています。

f:id:mktakuyax:20210317230338p:plain

無駄カスタムレスポンスの一例

弊社の開発チームメンバーは、北は北海道、南は宮古島まで全国各地に散らばっております。2020年は新型コロナウイルス感染症対策をきっかけとして全国的にリモートワークが広まりましたが、弊社ではその5年前、2015年からリモートワークを本格的に導入してきました。

リモートワークでも存在感を出すために

場所に縛られず自分好みの環境で仕事が出来るリモートワークですが、一方で何も工夫しなかった場合、オフィスワークに比べて他メンバーとのコミュニケーションの総量が減り、社内での存在感を発揮しにくくなるという問題もあります。

オフィスで机を並べて仕事をしていたときにはあった、たまたま廊下ですれ違ったときに生まれる「こないだリリースされた○○機能、めっちゃ評判良かったよ!」「先日の○○の件、一応解決したもののまだこんな問題があるみたいで……。」といった何気ない会話。これらはリモートワーク環境下ではなかなか生まれません。もちろん仕事で必要な会話ならテキストベースなりMTG組むなりで話すべきですが、そこまででもないちょっとした会話からより良いフィードバックが生まれたり、知らず識らずのうちに存在感を発揮できていたものです。

今回はそんなリモートワークの中でも存在感を出し、社内の各ステークホルダーにとって頼れるエンジニアになるため気をつけていることを書いていければと思っています。

Slack キーワード通知を活用する

Slackには、事前にキーワードを設定しておいてそれに引っかかる投稿を通知してくれる機能があります*1。自分の名前やハンドルネームはもちろん、最近リリースした機能についてもキーワードを設定しておくと良いかもしれません。

f:id:mktakuyax:20210329121923p:plain

筆者の通知キーワード一覧

もちろん何かあったらメンションしてもらうのが一番ですが、そこに至る前の軽い問題意識の状態からWatchしておくことによって発見できることもありそうです。あとは、自分達が作った機能がどんな使われ方をしているのかはエンジニアなら把握しておきたいですよね。

ある程度キーワードで絞ってWatchしておくと、実際に相談が来た時に「あぁ、あの話ですよね!」という打ち返しをすることが出来ます。背景説明のコストを省きより本質的な議論に時間を割くことが出来るので、仕事の質も上がりますよね。また、単に名前を呼ばれた時に反応しておくと文字通り存在感を出すことができそうです。

問い合わせ対応のその後をremindでフォローアップする

コードを黙々と書くだけが開発チームの仕事ではありません。その代表例として、各チームからの問い合わせ対応があります。オンサイトでもリモートでも、大体の問い合わせとその対応はチャットベースで行われるかと思います。

オフィスであれば廊下ですれ違った際に「昨日の○○の件、あの後どうなった!?」と自然なフォローアップが可能です。そこから「実はまた別の小さな問題があって……」という話になるかもしれないし、無事に解決してお礼など言われたらそれはそれで嬉しいものです。

が、リモートワークだとそうもいきません。対応が終わり自分の手を離れた問題のことは普通は忘れてしまいますし、廊下ですれ違うなどを通じて思い出すきっかけもありません。

僕の場合は、一度対応が終わった問い合わせのメッセージに対してremindを設定し、後日(ものによって翌日にしたり、「1週間くらい様子見ましょうか」と言ったなら1週間などいろいろ)また通知が来るようにしています。Slackのメッセージにリマインダを設定する方法はこちらをご確認ください。

slack.com

後日のフォローアップをすることで、その対応が良かったのかどうかを確認することが出来ますし、新たな問題があればそれに早く気づくことが出来ます。何も問題が無かった場合でも感謝され良い気持ちになることが出来ますよね。 

対外的なやりとりのタスクを買って出る

問い合わせ対応とも似ている話ですが、対外的なやりとりを必要とする仕事はテキストベース・口頭問わず積極的に取りにいくようにしています。開発チームからBizのみなさんにお願いする事柄を伝えることだったり、なにか決め事をするのにエンジニアのアサインが必要と言われていることだったり、あるいは社外の方とのMTGだったりです。

あまりやりすぎるとコードを書く時間が減ってしまうのでツラいですが、何もやらないと開発チームが「チケットを投げてしばらくすると動くソフトウェアが出来ている謎の組織」になってしまいかねません。

どこかで決まったことに沿って実装をするだけでなく、自ら何かが決まる場に出向くようにすると、存在感を発揮できるだけでなく、開発者の立場から意思決定プロセスに貢献することが出来たり、普段とは違うコンテキストで会話することによって事業を進めるための視点が得られるようになったりします。

リフレクションで感謝の気持ちを伝える

弊社では、その日の業務を振り返り次へつなげる内省の機会を作るため、業務終了時にリフレクションを投稿するようにしています。

これは最近はじめたことなのですが、みなさんのリフレクションを読んでemoji reactionをつけるようにしています。また、MTGや問い合わせ対応等でお世話になった方には、スレッドにて感謝の言葉を書くようにしています。

問い合わせ対応フォローアップの項目でも書きましたが、リモートワーク・テキストベースメインでの仕事をしていると、ちょっとした会話をするチャンスがなかなかありません。かつ、「わざわざ別チームのチャンネルに登場してまで言わなくてもいいか」という気持ちになってしまうところもあります。

そういうときは、リフレクションを書くときに本日のGood Job欄*2で感謝の気持ちを述べたり、その人のスレッドまで行ってお礼を言ったりなどをしています。

f:id:mktakuyax:20210329135355p:plain

リフレクションチャンネルでのやり取りの一例

おわりに

というわけで、リモートワークでも存在感を出すために僕が気をつけていることのうちのいくつかを書き出してみました。

ここまで書いたようなことをやった甲斐もあってか、2020年度下期のMVPを受賞することが出来ました。組織の垣根を超えコラボレーションをすることが出来たからとのことでしたが、これはここまで書いていたようなことを実施出来たからなのかなぁと思っています。

一方で、ここに書いてあることを厳密に全部やると、コード書く時間がなくなるなぁとも思います。月並みな意見ですが要はバランスで、自分の仕事のどこか一部分を改善したいなと思ったタイミングで参考にしていただければ嬉しいなと思っています。

リモートワークで存在感を出せずに悩んでいるエンジニアの方がいらっしゃいましたら、参考にしていただけると幸いです。

 

株式会社groovesでは、求人データベースの「Crowd Agent」と成長し続けるエンジニアを支援するサービス「Forkwell」を開発・運用しています。

どちらのサービスも、リモートワークでプロダクトの価値を高めて頂けるエンジニアを積極採用しています。エントリーお待ちしています!

jobs.forkwell.com

jobs.forkwell.com

*1:Slack 通知を設定する | Slack

*2:弊社のリフレクションのフォーマットにある、誰かへのGood Jobを伝えるコーナー