社員情報の可視化サービスを内製開発した話。開発スタイルと開発技術、学びとしてふりかえり #devio2020

組織拡大に伴い社員数が急増してきて、どんな人がいるのか分からなくなってきたので、社員情報の可視化サービスを内製開発した話です。開発スタイルと開発技術、学びとしてふりかえりを紹介しています。
2020.06.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。shoitoです。

Developers.IO 2020 CONNECTが開催中でして、6/26に「社員情報の可視化サービスを内製開発した話」というセッションの動画を公開しました。

※2020/07に事業開発部へ異動しているので、その前のチームの話です。

セッション概要

組織拡大に伴い社員数が急増してきて、どんな人がいるのか分からなくなってきたので、社員情報の可視化サービスを内製開発した話です。
開発スタイルと開発技術、それを通して学びとしてふりかえりを紹介しています。

動画

  • 01:58 Voyagerの概要
  • 04:40 開発スタイルの話 - チーム構成やルール、ドキュメント
  • 13:00 開発技術の話 - 技術スタック、アーキテクチャ
  • 18:05 ふりかえり - 意識したこと、TRYしたこと、失敗したこと
  • 23:02 おわりに

スライド

セッション文字起こし

お忙しい方向けにセッションの内容を文字起こししたものを載せておきます。

アジェンダ

まず「Voyagerとは」で開発背景やどんなサービスなのか簡単に紹介し、「開発スタイルの話 」ではチーム構成やどんなルールで開発をしていたのかを紹介します。
「開発技術の話」では技術スタックやアーキテクチャを紹介し、「ふりかえり」ではこれまでの開発で意識してきたことやTRYしたこと、失敗したことを紹介し、「おわりに」という流れで進めます。

Voyagerの概要

Voyager?は、役職や立場、働く場所に関わらず、同僚の強みや個性をわかりやすく可視化して、目的に応じた仲間を見つけやすくすることでコミュニ ケーションを活性化させるサービスです。
なお、Voyagerは開発コードネームであって、プロダクト名ではありません。

開発の背景

クラスメソッドは、毎月10名前後ずつ社員が増加し、事業の幅が広がり組織の数が増え、さらに沖縄、インド、タイなど国内外拠点も増えてきました。
クラスメソッドでは、業務の効率化や家庭の事情によるリモートワークが新型コロナ以前から認められていました。

そのような状況の中、課題感も抱えておりました。
在宅勤務が増えて、同じ空間にいれば発生する偶然の出会いのようなものが減ってしまい、同僚や先輩との接点が薄くなった。
社員数の増加に伴い、知らない同僚も増え、チームに必要なスキルを誰が持っているかわからない。
中途や新卒で入社したものの、同僚がどんな人たちなのか分からない。
というようなものが課題の一部として挙げられます。

以前はこのような課題に対して、Confluenceの社内Wikiで社員プロフィールが管理されていました。こちらは入社時に自分で所属部署のページにプロフィールを書くルールでした。
しかし、同僚を興味のあるキーワードで探したり、最近入社した人を探したり、共通の趣味で探したりといったようなことをするには、専用のツールではなかったため満足のいく状態ではありませんでした。

現在のVoyagerを紹介

こちらはVoyagerの社員一覧ページです。
同僚を所属や趣味、所有資格、タグなど様々な属性で探せて、今月入社したばかりの同僚にどんな人がいるのか確認して、入社後のフォローをしたりします。

個々人のプロフィールページでは、一覧には見えていない自己紹介や興味関心などさらに詳細な情報を確認します。

次に、これは弊社独特の文化なのですが、AWS認定資格の全取得をしている社員やそれを目指している社員が多くいるので、AWS認定資格 9冠 のように取得数をアピールする仕組みがあります。

開発スタイルの話

チーム構成やどんなやり方で開発をしていたのか紹介します。

Voyagerの開発チームは、当初、このように4名のチームで、他のプロジェクトと兼務のあるメンバーが各ロールにいました。なお、メンバーは東京、東京だけど在宅、札幌と分散していました。
開発が進んでいくと、有志で富山のメンバーが週1日、Voyagerの開発に加わってくれて、さらに、福島のメンバーが週2日加わる形となりました。

開発スタイルのベースはスクラム開発です。
タイムボックスは2週間として、一定期間ごとにサイクルを回し改善していくリズムを設けています。
先程紹介したように元々拠点が分散していること、また最近は新型コロナウィルスの感染予防のため在宅勤務であり、イベントは全てGoogle Meetを使いオンラインで実施しています。
チームイベントとしては、当初、朝会、スプリントプランニング、ふりかえり、リファインメント、スプリントレビュー、デイリーDevチーム勉強会を実施していました。

プロジェクトがある程度進んでからは、リファインメントとスプリントレビューは、朝会やスプリントプランニングの時間に集約されて、個別のイベントとしてはなくなりました。
デイリーDevチーム勉強会は、朝会枠の残り時間を使って行う読書会や技術共有会です。
テーマとしては、リーンスタートアップ、Elasticsearch、マイクロサービス、CDK、AWSなどを扱ってきました。

開発フェーズ

開発フェーズは立ち上げフェーズ、MVP開発フェーズ、社内ドッグフーディングフェーズと、現在3フェーズ目というところです。

紹介したフェーズのうちの一つ、立ち上げフェーズで定義したものを3つの観点に分けて紹介します。
プロダクト、チーム、開発の観点に分け、チームメンバー全員で話し合い決めました。

プロダクト観点

プロダクト観点では、対象とする課題とターゲット、想定する解決策、プロダクトが持つべき特徴などを言語化し、どう作り上げていくのかを計画立案、そして、プロダクトが定量的にどうあれば健康なのか計り方としてフェーズ毎のKPIを定義しました。

次に、具体的にどのような手法やフレームワークを用いたのか紹介します。
まず、プロダクトが対象とする課題とターゲット、その解決策などはリーンキャンバスを作成しました。
スライドは実際にVoyager作成したリーンキャンバスの一部です。

リーンキャンバスは、ビジネスモデルを考案するときに便利なツールです。
作成にあたって、必要な項目は「課題」「顧客セグメント」「独自の価値提案」「解決策」「チャネル」「収益の流れ」「コスト構造」「主要指標」「圧倒的な優位性」といった9つで、これらの項目を1枚のシートに整理し、モデルに漏れや矛盾がないか検討します。

私も含めエンジニアは課題と解決策となる機能を中心に考えてしまうことが多いかもしれませんので、そもそもビジネスとして成立するアイデアなのかどうか考える上では良いツールだと思います。

次に、プロジェクトの全体像を表すインセプションデッキを作りました。
プロジェクトの目的、プロダクトは何なのか、何ではないのか、やること、やらないこと、方向性などをチームメンバーで整理し、共通認識としています。
スライドは、実際のインセプションデッキをGitHubのWikiにまとめたものです。

ユーザーストーリーマッピングは、ユーザーがどんな流れでプロダクトを使うのか、またユーザーに提供したい体験(ストーリー)を優先順位を考慮して並べ、MVPやその後のリリースでどのストーリーをリリースするのか計画の共通理解を得られる手法です。

縦横2軸で構成されていて、横軸は時系列にユーザーのアクティビティを並べていき、縦軸は各アクティビティでユーザーに提供したい体験(ストーリー)を優先順位順に並べていきます。
MVP, Dogfoodingの各フェーズでどのストーリーを実現するか絞り込むのに便利でした。

共通語彙ですが、チーム内でプロダクトで扱う用語に齟齬のないように用語辞書を作成しています。
こちらはGitHub Wikiに整理していて、随時アップデートされてます。
英語、日本語、補足説明と設けていて、コードでも英語の用語を利用するようにしています。
例えば、email, mail, mail addressのようなブレを防止します。

MVP, Dogfooding, …とフェーズが進むのに合わせて、各フェーズのリリース判断基準、撤退判断基準を定量的に計れるようなKPI定義です。
先のフェーズについては未確定な部分が多いので具体的な数値は定義できていません。

チーム観点

チーム観点は、チームとして協働するための約束事、進捗に齟齬が発生しないようにタスクはどうなったら完了とするのか、朝会、プランニング、ふりかえりなどのチームイベントはどんな目的で時間枠はどれくらいなのかなど定義しました。

チームで協働する上で、チームの暗黙のルールを減らすため、Working Agreementをチームみんなで定義しています。
スライドは実際のWorking Agreementの一部です。
例えば、「家族や自身を優先して、予定は無理せずリスケ・欠席の連絡をする」や「レビュワーにアサインされたPull Requestに対しては、早めにフィードバックしチーム全体の進捗を優先する」「ソースコードのマージはレビュアーが行う」など大小あり、ふりかえりの際に見直しアップデートしています。

毎日カンバンを見ながら朝会をしますが、そこでタスク完了の認識齟齬を防ぐために、ストーリー、スプリント、ステージングリリースなどの完了条件を定義しています。
例えば、プルリクエストを作るだけでなく、レビュー、マージがされているのがストーリーの完了の定義だよね、といった定義をしています。
プルリクエストを作って、手離れしたつもりになり「実は完了していませんでした」という認識齟齬を防ぎます。

朝会やスプリントプランニング、ふりかえりなどのチームイベント、それぞれについて、実施の目的、内容、参加者、頻度、時間などを明確にしています。
チーム外のメンバーが見たとき、新たにチームに参加したときに、なぜこのイベントをこれだけのコストをかけて実施しているのか曖昧なままということをなくしています。

これまでのスライドでも出てきたようにドキュメントはGitHubのWikiに集約しています。

タスク管理はGitHubのProjects機能のかんばんを用いていて、朝会やスプリントプランニングはこれを全員で見ながら行います。 レーンは「Feedback」「Product Backlog」「Sprint Backlog」「In progress」「Blocking」「In review」「Done」としています。

開発観点

開発観点では、開発する上で必要なツールとしてGitHubやAWSアカウント、Slackチャンネル、Visual Studio Codeなどを準備し、eslintやprettierのルール定義をし、チームで開発ができるように整備しました。
また、想定する技術スタックでプロダクトを実現する上でのリスクを検証しました。

開発技術の話

「開発技術の話 」ですが、ここではVoyagerの技術スタックやアーキテクチャを紹介します。

技術スタック

技術スタックについて、言語は、フロントエンド、バックエンドともにTypeScriptを使っていて、部分的にJavaScriptを使っています。部分的にJavaScriptなのは、デバッグをAuth0のダッシュボードで行うことがあるためです。
TypeScriptを選んだ理由は、型を使って、実装の問題に早めに気付きたい、リファクタリングしやすくしたい、IDEのコードアシストの恩恵を受けたいと考えたためです。

フロントエンドは、Vue.jsのフレームワークであるNuxt.jsを使っています。またUIコンポーネントフレームワークとしてVuetify、UI/UXデザインツールとしてFigmaを使っています。
Nuxt.jsを選んだ理由は、他サービスの開発でも利用していた、学習コストが低かった、フレームワークが提供する規約により複数人でもカオスになりにくいと考えたためです。
StorybookはUIコンポーネントカタログとして導入していたのですが、参照頻度は低くあまり活かせませんでした。

バックエンドは、API Gateway + Lambdaのサーバーレス構成を中心に、各種AWSサービスと、インフラの構築にCDKを使っています。 CDKで可能な限りインフラをコードで管理するようにし、個人の検証環境のような環境も容易に構築できるようにしています。

その他としては、プロジェクト・コード管理でGitHub、コミュニケーション・アラート通知にSlack、IDEとしてVisual Studio Code、認証認可にAuth0を使っています。

アーキテクチャ

Voyagerのアーキテクチャの一部を紹介します。
このような構成を開発環境、ステージング環境、本番環境のそれぞれのAWSアカウント環境に構築しています。

フロントエンドはNuxt.jsで作られたSingle Page Applicationです。
バックエンドAPIはAPI Gateway, Lambda, Auth0, DynamoDB, Amazon Elasticsearch Serviceなどで構築しています。 なお、写真データはS3に格納されていますが、誰でも取得できてしまっては困るため、署名付きCookieを付与したリクエストでなければ、CloudFront経由でS3から画像を取得できないように制限しています。

社員の検索には、Amazon Elasticsearch Serviceを利用していますが、APIからの社員情報の追加・更新などのリクエストはDynamoDBへ書き込まれ、DynamoDB Streamsを使ってLambdaからElasticsearchのインデックスに反映されるという流れになっています。

こちらは先日の坂井の発表で詳細が紹介されていますので、興味を持たれた方は是非動画をご覧いただければと思います。

デプロイはシンプルで、GitHubリポジトリの環境ブランチ(master, staging, productionブランチ)にPull Requestがマージされると各AWSアカウント環境のAmplify Consoleのアプリケーションがフックされ、ユニットテスト、CDKによるインフラ変更適用、フロントエンド、バックエンドのビルド・デプロイが実行されます。

ブランチ戦略

ブランチの話をしましたが、ブランチ戦略としては、GitLab Flowによる環境ブランチを採用しています。

これはmasterからfeatureブランチを作り、featureブランチで開発が終わったらmasterブランチへPull Requestを通じてマージされる点はGitHub Flowと同じですが、stagingブランチ(GitLab Flowではpre-productionブランチと呼びます)やproductionブランチというような、デプロイ環境用のブランチが登場します。
GitHub Flowにデプロイ環境用のブランチが加わった形ですが、各環境へのデプロイ操作がシンプルで、さらにデプロイタイミングに柔軟性を設けられるのが良い点です。

ちなみにPull Requestは最終Reviewerがマージするようにしていて、チームでコードの把握と責任の共有を意識するようにしています。

さらに、ストーリーを実装していて、どうしてもPull Requestが大きくなりそうな場合、まずはfeatureブランチからmasterブランチへ空のcommitでのPull Requestを作ります。
そして、featureブランチからtaskブランチ(と内部で呼んでいるブランチ)を作り、featureブランチに対して小さなPull Requestを作り、レビュー・マージする。というのを繰り返します。
featureブランチに全てのtaskブランチがマージされたら、はじめに作成したfeatureブランチからmasterブランチへのPull Requestをレビューしてマージします。

このようにして、Pull Requestが大きい場合に、Reviewの負担が大きく、Approveまで時間がかかったり、Reviewが甘くなってしまう問題を回避しています。

開発スタイルと開発技術についてふりかえり

「ふりかえり」ではこれまでの開発で意識してきたこと、TRYしたこと、失敗したことを紹介します。

意識したこと

開発する際に意識したことについてですが、一部だけでも結構な数ありました。
ここでは赤枠で囲った3つについて紹介します。

GitHubへの情報の集約ですが、これはソースコード管理、Issue管理、進捗管理、ドキュメント管理などをGitHubの機能を使う形に集約し、GitHubの検索フォームからプロジェクトの全ての情報にアクセスできるようにしたかったためです。
もちろん、各機能毎に、例えばIssue管理はJira、ドキュメント管理はNotionやConfluenceなど専用のツールの方が使い勝手は良いのですが、今回は情報の集約による連携を優先しました。
稀に、GitHubがステータス500を返すようになるとそこで仕事はお終いになります。

次に責任は個人ではなくチームへ、ということで、あまり恐れず、しかし慎重にチームで動くことを意識しました。一例としては、細かいのですがPull Requestは必ずレビューと承認、そしてレビュアーによるマージをするルールとしました。レビュアーはマージボタンを押すアクションをすることで、コード変更を一緒に実施した意識を持つことになります。

15分お悩みルールは、チームメンバーはみんなリモートワークをしているため、ハマってしまっているかどうかお互いに見えません。メンバーが1人で黙々とこなすのも良いのですが、困った事象を抱え込まないように、15分以上悩みそうなら気軽にSlackやGoogle Meetで相談しあいましょうと敢えてWorking Agreementに明文化しました。
これのおかげかSlack上で「ここのところちょっと分からないのでペアプロイイですか?」「このタスク、今ハマってませんか?」のような会話がよくされて、助け合う文化ができています。

TRYしたこと

TRYしたことについては、3つ紹介します。

まず、新加入メンバーのオンボーディングですが、初日にストーリーをアサイン、モブプログラミングによる実装、Pull Request作成、レビュー、デプロイまで実施してもらい、開発チームのイメージを掴み、初日GitHubのコントリビューターに加わり、達成感を味わってもらうということをしました。オンボーディング用のGitHub Issueを作り、一つ一つチェックボックスにチェックを付けていきました。

次に、Visual Studio CodeのLive Shareによるペアプログラミングをオンボーディングや担当者が初めて扱う技術分野の際に行い、1人で抱えず、チームでフォローしあえるようにしました。

非同期&同期のふりかえりは、このようにGitHub Issueでスプリント毎のふりかえりを運用したものです。
クイックレトロスペクティブというふりかえり手法を利用して、スプリント内でのGood/Bad/Idea/Actionをチームのみんなで挙げていきます。

GitHub Issueのコメントにこのように絵文字付きで、各カテゴリのコメントをスプリント期間中いつでも、またふりかえりイベント中に記載して、ひとつひとつ共有&ディスカッションしていきます。
ふりかえりも記録を残す形にし、新たなメンバーが過去にチームがどのような課題感を持っていたのか把握できるようにしています。

失敗したこと

失敗したことは多々ありますが、その中から3つ紹介します。

まず、タスクの分担についてです。
チーム構成でご説明したように週5, 2, 1日の稼働のように分散してしまっていたため、進捗の同期をはかるのが難しかったです。
1つのストーリーをタスク分割し、そのタスクを複数人で分担した際に、週2稼働日のメンバーが着手中の場合、翌稼働日までタスク完了できないことがありました。タスクが全て完了しないとストーリー自体も完了できないため、これはタスクを移譲しても良かったと思ってます。

次にMVP(Minimum Viable Product)ですが、これがMinimumじゃなかったことです。最低限と定義していた機能を実装したのですが、早めのフィードバックを得るためなら、Figmaによるワイヤーとプロトタイプで良かったと思います。

最後にふりかえりですが、ふりかえり用のGitHub Issueを作り、非同期でも日々Issueコメントという形でふりかえりの内容を書けるようにしましたが、それ自体は少なく運用に載せきれていませんでした。

おわりに

Voyagerは、現在、社員のスキルや個性を可視化したところまでで、まだまだMVP + αな状態です。
どんなプロジェクトに関わってきたのか可視化したい、可視化の次には、社員間のコミュニケーションをサポートしたい。
リモートワークでは難しい、社員間の新しい出会いを創出したい。
など、まだやりたいことは山積みされています。

一緒に作っていく仲間が必要なので、是非エントリーをお待ちしています。

クラスメソッド採用サイト
https://careers.classmethod.jp/