TECH PLAY

Findy/ファインディ

Findy/ファインディ の技術ブログ

193

こんにちは。 Findy Freelance の開発チームでエンジニアをしている 2bo です。 この記事では私が開発生産性を上げるために開発をする前に考えていることについて書きます。 ここで「開発をする前」というのは次のようなタイミングを指します。 PdMなどから新規施策の仕様について相談を受けたとき 起票された開発Issueを最初に確認するとき 自分がIssueを作成するとき なぜこのタイミングで考えるかというと、開発を進める上での方向性を間違える可能性を減らし後から軌道修正をしやすくするためです。 なおこの記事においては、開発生産性を「開発成果物の提供価値を投入リソースで割ったもの」とします。 いくら頑張って開発をしても、そもそもやるべきことの方向性を大きく間違えると提供価値が0に近づくため開発生産性が低下します。 特に開発が高速なチームで方向性を誤ると高速に間違った方向へ進んでしまうことになります。 そのような事態を避け、提供価値を少しでも上げるために考えていることを記します。 なぜ、いつ、だれがつかうか? 開発する必要があるか?しなくて済む方法はないか? シンプルにできないか? リリースを分割できないか? 実例の紹介 プロジェクトの概要 請求フローの理解 設計の見直しによるシンプル化 スコープの決定とリリースの分割 終わりに なぜ、いつ、だれがつかうか? 大前提にはなるのですが、まずは以下を考えます。 なぜ:なぜその機能が必要なのか?ユーザーはなぜこの機能をつかうのか? いつ:いつその機能を使うのか?そのときユーザーはどういう状況にいるのか? だれ:どういう属性のユーザーか?ユーザーが社内にいる場合、どの部署/役割の人か? これらの情報はありがたいことに PdM から普段提供してもらえています。しかしながら自分でも考えるようにしています。 エンジニアの視点からも考えることで、それを実現するための別の形の機能やアプローチが良いのではないかと提案できることがあります。 たとえ提案が採用されなかったとしても現行案の妥当性を確認できるため、方向性を間違える可能性を減らすことができると考えています。 開発する必要があるか?しなくて済む方法はないか? 提供価値を極力変えないまま、投入リソースを減らせるアプローチがないか次のことを考えます。 既に同じ機能が存在するか、または全く同じではないものの実質的に同じ提供価値を持つ機能があるか? 既存の機能を利用、または組み合わせて実現できるか? 外部サービスやライブラリをつかうことで実現できるか? 例えば、画面Aで情報の表示追加を要望された際、その情報をすでに表示している画面Bがあるため、画面Aへの直接追加ではなく、画面Bへのリンクを設けるだけで十分というケースがあったりします。 このように要望機能そのままでなくても必要十分をみたせば問題ないというケースでは、開発リソースを減らせることがあります。 シンプルにできないか? 機能が複雑になるとその後のメンテナンスや改修の工数が増加したり、作り直しが発生したりしてトータルで見ると生産性が落ちるということが起きがちです。 そのため次のことを考えます。 複数の関連性のない異なる目的を担う機能になっていないか? その場凌ぎでワークフローや処理の分岐を増やすことになっていないか、またはそれらを極力減らして開発できないか? 過度に自動化、抽象化することでなにをしているかわからなくなったり、イレギュラーケースに対応しづらくなっていないか? 私は過去にシンプルさよりもリードタイムを優先して機能追加をしたことがあります。その時は本来異なる目的をもつ既存機能に付け足す形で機能追加をしました。 最初のリリースまでのリードタイムは短縮できましたが、処理の分岐とデータのパターンが増えてメンテナンスとデータ集計がしづらくなり、結局は一から作り直すことになりました。 トータルで考えると最初からシンプルに別の機能として設計/開発をしたほうがよかったと考えています。その反省も踏まえての内容になります。 ただし、特にベンチャー企業においてはどうしてもリリースまでのリードタイムを短くしなければならない状況もあると思います。 そのため完全に否定できることでもないですが、単にそのほうが楽だからという理由ではやらない方がよいと考えています。 リリースを分割できないか? ユーザーへの価値提供を考えて立案された施策や機能が、本当に有効かどうかは実際に提供してみないとわかりません。 また、大きな施策の場合は必須なものと必須ではないがあれば嬉しいというものが混在しがちだと考えています。 それらすべての内容をつくってからリリースする場合、期待通りの結果が得られなかったときに投入した開発リソースを無駄にしてしまう可能性があります。 これを避けるため、今回の開発で一番実現したいことはなにか?を考えて、もっとも重要なものから段階的にリリースすることを考えます。 いわゆるMVP(Minimum Viable Product)を開発ごとに考えるようなイメージです。 次のメリットがあると考えています。 ユーザーに素早く価値提供ができる 効果やユーザーのフィードバックを早く得られる 結果が素早く得られるため、軌道修正や撤退の判断が早期にできる リリースあたり開発ボリュームを減らせるため見積もりのブレを減らせる エンジニアのモチベーションの観点からも、早期にリリースすることで開発者のモチベーション向上につながりやすく、すべて作り込んで無駄になった場合のモチベーション低下も回避しやすいと考えています。 実例の紹介 ここからはこれまで紹介した考え方を実際に活かした「請求フローのシステム化」プロジェクトの事例を紹介します。 プロジェクトの概要 Findy Freelanceではユーザーの稼働後サポートとして請求書の作成代行と業務委託報酬の代理徴収を行っています。 そのため、ユーザー個々の稼働状況を確認し、内容に応じて請求書を作成して企業に送信する必要があります。 これらの作業の多くは手作業で行われていました。サービス利用者の拡大に伴い運用の限界が見えたため、請求フローをシステム化するプロジェクトが立ち上がりました。 請求フローの理解 私は開発リーダーとしてプロジェクトを途中から引き継ぎました。その時点で請求業務のドメイン知識がほとんどありませんでした。そのためPdMにヒアリングしながら請求フローの図を作成し、どの役割の人がどのタイミングで何をするのかを把握しました。つまり「なぜ、いつ、だれが?」の観点を確認しました。 情報を整理することでエンジニアユーザー、企業担当者、社内の営業担当者および経理など多くのステークホルダーが関与しているとわかりました。以後の開発で各々の視点を意識でき、先を見据えながら起案時よりもさらに価値のある仕様に繋げることができました。 設計の見直しによるシンプル化 次に、設計の見直しを行いました。プロジェクト引き継ぎ前は、手作業で管理されていた情報をそのままデータベースに移す形で設計が進んでいました。 例として、Findy Freelanceの契約スキーム上「企業とファインディ間の契約条件」と「ユーザーと企業間の契約条件」の2種類の契約情報が必要です。 当初はこれらを1つのテーブルで管理する設計でしたが、本来は別の情報であり、それぞれの契約変更のタイミングも異なるため、別のテーブルで管理することにしました。 これによりテーブルとモデルクラスの役割が明確になり、シンプルになりました。 また、2種類の契約情報がそれぞれいつ変更されたのかも管理できるようになりました。 設計の見直しには時間がかかりましたが、その後の改修や運用コストを考慮すると、見直して良かったと考えています。 スコープの決定とリリースの分割 プロジェクト引き継ぎ時、システム化に必須な機能と便利な機能がIssueに混在していました。 せっかくシステム化するならと多くの要望が積み上がっていましたが、スコープが不明確でした。 そのため、PdMを中心に関係者と協議してスコープを決めました。 早期の運用開始を目指し、必須機能のみを最初にリリースしました。例えば、次の機能は最初のリリースから除外しました。 社内管理画面の利便性向上 ダッシュボードの作成(初回リリースではBigQueryからのデータ参照で代替) ユーザーがログインページから報告した稼働時間の確認(報告時にユーザーへメール送信しているため) これらの機能は実運用後に必要性を再検討することにしました。スコープを決定し、リリースを分けることで運用開始までのリードタイムを短縮しました。 また、実運用をしたことで発覚した必要となる機能や改修があり、最初からすべて作りこまなくてよかったと考えています。 終わりに 以上が開発をする前に私が考えていることとその実例です。誰かの参考になれば幸いです。 ここに書いてあるようなことは普段から考えているという方も多いのではと思います。 読んでくださった方々が開発に際して考えていることなど是非コメントをいただけると嬉しいです。 また、ファインディではエンジニア領域のプロダクトの開発をするため、開発エンジニアが提供価値を考えるにあたり自然とユーザーの視点にたって考えることがしやすい環境であると感じています。 エンジニアへの価値提供に少しでも興味を持っていただけた方は、ぜひカジュアル面談のお申し込みをお待ちしております。 ファインディの採用情報はこちら↓ herp.careers また、ファインディの開発メンバーが登壇するイベントを4/24(水)12:00~13:00で実施します! 開発生産性や開発のパフォーマンス向上にご興味ある方はconnpassページより是非お申し込みください! developer-productivity-engineering.connpass.com
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 先日、弊社から Findy Tools がリリースされました。 今回は、そのFindy Toolsがどのようにして開発されたのか、開発の背景や工夫点などを紹介していきます。 それでは見ていきましょう! Findy Toolsの概要 紹介 Findy Tools は開発ツールに特化したレビューサイトです。第三者の視点で実際にツールの選定をした企業の生の声を集めることで、ツール選定に関する不安を解消し、導入検討に必要な情報を提供します。 「Findy Tools」を開発ツールの導入検討をしているユーザーが利用すると、実際にツール選定をした大手企業やメガベンチャー企業の技術責任者やエンジニアによるレビューを集めることができ、導入検討がスムーズになります。 また、開発ツールを掲載するベンダーには、実際の利用企業の声を活かしたコミュニティマーケティングによる新規顧客の獲得や、認知向上をご期待いただけます。 システム構成 システム構成は次の通りになっています。 Ruby on Rails React Next.js App Router bulma GraphQL AWS S3 CloudFront Aurora Fargate 上で挙げた構成に特に強いこだわりはなく、既存資産の流用をしやすかったことと、リプレイスや変更しやすいという理由でこの構成になっています。 APIとフロントエンドを疎結合で設計し、どちらか一方を作り直しやすくしたり、GraphQLを用いることでqueryそのものを変更することなく、呼び出し先のエンドポイントを切り替えることでアプリケーションの振る舞いを変えずにAPIを切り替えることができるような構成にしています。 開発 スケジュールとリソース 今回の開発はα版、β版と2回に分けて段階的にリリースしました。 α版は2023年9月から2023年10月で開発し2023年11月上旬にリリース、β版は2023年11月から2024年1月まで開発し、2024年1月下旬くらいにリリースしています。 開発リソースはα版は1人、β版は2024年に入ったあたりから2人で、それに加えてインフラ担当1人で開発をしました。 基本的にβ版リリースまではアプリケーション側の1人で開発していました。 新規サービスが当たるかどうかは実際に世に出してみないとわからないので、「最小限のリソースで最速でリリースする」という方針でした。 開発のポイント 既存資産を活用 最小限のリソースで、最速でリリースするという方針だったので、まず「全てを1から作る」という選択肢は可能な限り避けました。 幸い弊社には既に運用されてるシステムがあり、そこからの流用を決めました。 具体的には次の内容を流用しました。 アプリケーションの実行基盤まわりの共通コード フレームワークの各種設定ファイルや設計思想 デプロイやCIのワークフローのコード 共通コードや各種設定ファイル、設計思想は既存の各サービスでほとんどが統一されており、コピペして少しいじったらすぐに使えるような状況に整備されています。 またデプロイやCIまわりは全てGitHub Actionsに統一されており、こちらもワークフローのファイルをコピペして少しいじるだけですぐに使えるようになっています。 これらの既存資産を流用することで、コードを書き、テストで守り、動作環境にデプロイし、最低限動くものを確認できる環境をすぐにセットアップできました。 ゼロからモノを作るうえで動くものを用意することは非常に重要です。動くものをメンバーと共有して確認することで、認識の齟齬を防ぎ、余計な修正作業を減らすことが出来ます。 データ投入を簡略化 データ投入は開発の中でも時間を取られる作業の1つです。 レビュワーの方から頂いたレビューデータや、各種マスターデータをデータベースに投入する必要があります。 α版の時点ではデータ投入を簡略化するために、全てのデータをseedで投入することにしました。 本来であればデータ投入用の管理画面を作るのがベストなのですが、α版のリリース前に1人で開発してる状況で管理画面を作るようなリソースはありませんでした。 機能の取捨選択 初期リリースの目的は多くのユーザーを獲得することではなく、「サービスが受け入れられるかどうかを可能な限り早い段階で判断する」ことにあります。 そのため、「サービスが受け入れられるかどうかの判断に必要のない機能」を初期リリースのスコープから外しました。 具体例を挙げると、β版リリースまでは画像アップロードの機能を外しました。 レビューデータやアバター画像などをアップロード出来るようにしたかったのですが、画像アップロードを実現しようとすると、色々と考えないといけないことがあります。 画像のアップロード先はどうするのか?削除は許可するのか?画像サイズはどこまで許すのか?などなど色々出てきます。 今回は画像のアップロードを許可せず、運営チームが用意した画像をS3に直接アップロードして、そこへのパスをseedに直接書くことで画像ファイルの管理を単純、簡略化しました。 この機能を簡略化するだけだと良くて1,2日程度の開発工数削減に留まると思います。しかし、このような取捨選択をいくつかすることによって、結果的に半月や1ヶ月程度の工数削減に繋がりました。 この機能を削減して大量に工数削減、といったものではなく、ミニマムな削減の意思決定を大量に行うことによって実現しているのです。 テストコード 色々な取捨選択の意思決定の中で、テストコードだけは切らずに必ず用意していました。 「時間が無いからテストを書かないのではなく、テストを書かないから時間が無い」というのは事実で、結果的にテストが守ってくれているおかげで、余計なことに時間を取られずにやりたいことに集中できるのです。 テストコードのお陰で、α版リリース以降に本番環境で発生した不具合、障害は記憶しているだけですが片手で数えられる程度でした。 管理画面を内製 α版のリリースにより、「このサービスが世に受け入れられる」ことを確認できたため、β版のリリースに向けて着手しました。 α版からβ版に向けて何を実現させるのかを検討している間、開発するものがなくて時間を持て余していたので管理画面を内製で実装することにしました。 各種マスターデータやレビュワーの方から頂いたレビューデータなど、運営で管理したいデータは多数あります。 それらの変更のたびにseedの再実行、データの変更を依頼するようなフローにしてしまうと、エンジニアが機能追加の作業に集中できなくなってしまいます。 β版リリースからはエンジニアを介さずにデータの追加、変更を運営メンバーだけで完結出来るようにしました。 管理画面の画面数は25個程度で、APIとフロントエンド込みで1人で2、3週間程度で開発しました。 管理画面はSSRが必要ないので純粋なReactのSPAで、CSSフレームワークに Bulma を採用しました。 管理画面を用意できたことによって、β版以降の開発時に運営メンバーからのデータ管理周りの依頼が無くなるので、開発作業に集中できるようになりました。 反省点 Findy Toolsの開発では、チャレンジ枠としてNext.jsのApp Routerを採用しました。 既存プロダクトに用いられているPages Routerからの移行を検証する狙いもありましたが、今回は上手くいかなかったと反省しています。 誤解を与えないように言うと、Next.jsのApp Router自体は悪いものではありません。 何が上手くいかなかったかというと、既存資産の流用をした結果、利用していたライブラリがApp Routerに対応出来ておらず、想定していた以上の工数を取られてしまったことです。 弊社ではApp Routerを初めて採用したケースであり、社内にノウハウが蓄積していなかったため、問題解決に時間がかかってしまいました。 今後、他サービスでのApp Routerの採用時に今回のノウハウを活用できるようになったと思いますが、今回のような開発スピードを優先されるケースで採用するべきではなかったかなと思います。 まとめ いかがでしたでしょうか? 新規サービスの開発時にはリソースやスケジュールに大きな制約が課せられます。そのような状況下でやるべきこと、やるべきではないことの取捨選択の意思決定が非常に重要になってきます。 半年近く1人で開発をしてきた Findy Tools ですが、みなさまのおかげもありサービスが順調に成長しており、今では開発に着手しているエンジニアの人数を増やすことができました。 今後もFindy Toolsをより良いサービスにしていくために、引き続き開発を進めていきます。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
Findy Team+でフロントエンドエンジニアをしている 川村( @peijun333 )です。 Findy では、フロントエンドのコード品質と安定性を確保するために Jest などのテストフレームワークを積極的に活用しています。通常、Jest は CLI から実行してテスト結果をコンソールで確認しますが、コマンドを用意する手間や、テスト経過のデバッグのために都度 console.log などでその内容を確認しなければならずとても不便です。 そこで、今回はテストの自動化とリアルタイムなフィードバックを提供する JavaScript の統合テストツールである Wallaby.js を紹介します。Wallaby.js を導入することで、開発効率の向上が期待できます。 Wallaby.js とは? 前提条件 VS Code でテストの修正 Wallaby.js はリファクタリングに強い スナップショット の更新 ユニットテストにおけるデバッグ機能の紹介 Wallaby.js を使ってみて 最後に Wallaby.js とは? Wallaby.js is an integrated continuous testing tool for JavaScript. It runs your tests immediately as you change your code (you don’t even have to save the file) and displays various results (including the code coverage, error and console messages) right inside your code editor, next to your code. Wallaby.js is great for doing JavaScript TDD (Test-driven development) or BDD (Behavior Driven Development), but it works great for other approaches as well. 公式ドキュメントより Introduction: What is Wallaby.js? Wallaby.js は JavaScript の統合テストツールで、次のような機能があります。 リアルタイムなフィードバック Wallaby.js は、テストの実行に手動のステップが不要なため、コードを変更するとリアルタイムで結果をフィードバックしてくれます。 エディタ内でのテスト結果表示 Wallaby.js は、コードエディター内にテスト結果を表示してくれます。エラーやカバレッジ情報などが、コードの隣に直接表示されるため、エディタから離れることなく、テスト結果を確認できます。 デバッグ機能 Value Explorer を使用することで、任意の場所で値を調査し、呼び出し元のコールスタックを確認できます。また、コンソールログをエディタ上に表示する機能も備えており、デバッグプロセスをスムーズにします。 また、サポートしているコードエディタとテストフレームワークが 豊富 で導入がとても容易です。 Wallaby.js は OSS 開発では無料で利用できますが、商用利用の場合は 有料 です。ファインディではフロントエンドを開発するメンバーにアカウントを発行しています。 前提条件 ここから実例を交えて機能を紹介します。実例に使った動作環境は以下の通りです。 VS Code VS Code 上に Wallaby.js の拡張機能 をインストールする必要があります VS Code 以外のコードエディタ もサポートされていますが今回は VS Code を使った紹介になります React version 18.2.0 Jest version 29.6.1 React Testing Library version 14.0.0 Wallaby.js の導入に関する詳細な手順や設定方法については、 公式ドキュメント を参照してください。 VS Code でテストの修正 Wallaby.js は サポートされているエディタ 上で動作します。今回は VS Code で普段テストを書いている様子を紹介します。 以下は、GraphQL を用いてユーザーデータを正しく取得できているか確認するテストの例です。 + expect(result.current.users).toStrictEqual([{ id: '1', name: 'name' }]); - expect(result.current.users).toStrictEqual([{ id: 1, name: 'name' }]); id が number 値ではなく string の '1' であるべきなのですが、上記動画の例では誤った結果を書いています。 Wallaby.js ではこのようにテスト結果がコードエディタ上(VS Code の例)にリアルタイムに反映されます。 予想される結果と実際の結果が異なる場合、赤色のテキストでエラー文が表示されます。そこにカーソルを合わせることで、具体的に差分内容を VS Code 上で確認できます。 - Expected - 1 + Received + 1 Array [ Object { - "id": 1, + "id": "1", "name": "name", }, ] また、VS Code 上では左側の余白に四角のテストカバレッジインジゲーターが 赤色 から 緑色 に変わった様子が確認できたかと思います。これにより視覚的にテストのカバレッジを確認できます。 詳細: Editor Code Coverage Indicators この機能のメリットは、エディタ上でテストの操作が完結でき、さらにリアルタイムに優れている点です。テストの実行や結果、失敗時のエラー原因の迅速な特定、ナビゲーション、差分ビューなど、すべてをエディタ上で行うことができます。 Wallaby.js はリファクタリングに強い 特にリファクタリングでは、 Wallaby.js の機能の 1 つである「リアルタイムにテスト結果がフィードバックされる機能」が発揮されます。 以下は ユーザーデータから空の name を取り除けることを確認するテストの例です。 テスト結果と関数のインターフェイスはそのままで、ロジックのみをリファクタリングしています。こちらの例のように、リアルタイムにテストが失敗し、リファクタリング後ファイルを保存せずともテストが成功しました。 このようにリアルタイムにテストが落ちてくれるので、関数の影響範囲がわかりやすく、テスト結果からすぐにフィードバックされることで効率よくリファクタリングが可能です。 スナップショット の更新 次にスナップショットテストの更新について紹介します。スナップショットテストとは、UI が予期せず変更されていないかを確かめるテストです。Findy Team+では @testing-library/react を使い コンポーネントのスナップショットを撮影し、必要に応じて差分を更新しています。 はじめに Wallaby.js を使わずに Jest のスナップショット を更新する手順をみてみましょう。 次の例は title と description を表示するコンポーネントのスナップショットテストです。 import { render } from "@testing-library/react" ; import { TestComponent } from "./test.component" ; const props = { title: "title" , description: "description" , } ; describe ( "TestComponent" , () => { it ( "表示確認" , () => { const { asFragment } = render ( < TestComponent { ...props } /> ); expect ( asFragment ()) .toMatchSnapshot (); } ); } ); 実装コード type Props = { title: string ; description: string ; } ; export const TestComponent = ( { title , description } : Props ) => { return ( <> < div > { title } </ div > < div > { description } </ div > </> ); } ; @testing-library/react の render 関数を使いスナップショットを撮影しています。このテストを初めて実行すると次のようなスナップショットファイルが作成されます。 // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`TestComponent 表示確認 1`] = ` <DocumentFragment> <div> title </div> <div> description </div> </DocumentFragment> `; 仕様の変更により、description を表示するタグを <span> タグに変更してみます。 - <div>{description}</div> + <span>{description}</span> そしてテストを再度実行すると UI の差分によりテストが失敗します。 ● TestComponent › 表示確認 expect ( received ) .toMatchSnapshot () Snapshot name: `TestComponent 表示確認 1` - Snapshot - 2 + Received + 2 < DocumentFragment > < div > title </ div > - < div > + < span > description - </ div > + </ span > </ DocumentFragment > 12 | const { asFragment } = render( < TestComponent { ...props } /> ); 13 | > 14 | expect(asFragment()).toMatchSnapshot(); | ^ 15 | }); 16 | }); 17 | › 1 snapshot failed. 今回は description を表示するタグは div ではなく span タグが正しいのでスナップショットを更新する必要があります。 Jest でスナップショットを更新するには --updateSnapshot や -u オプションを使い更新します。 (または ウォッチモードで対話的に更新) 以上の手順を踏むことでスナップショットの更新が完了します。 今回は 1 ファイルのみの修正で変更差分も軽微なものですが、複数のテストが失敗した場合、目的のテストを見つける手間と時間がかかります。また、エディタからターミナルに移動しコマンドを実行する必要があるため、コンテキストを切り替える必要があり、多くの時間が消費されます。 次に Wallaby.js を使ったスナップショットの更新をみてみましょう。 エラーにカーソルを合わせ、差分を確認した後、右上のカメラアイコンをクリックしただけです。 失敗したテストをエディタで確認し、スナップショットを直接更新するだけなので、目的のテストを見つける手間も時間もかかりません。 ユニットテストにおけるデバッグ機能の紹介 Wallaby.js には Value Explorer という機能があります。これを活用することで、デバッグ作業を効率化でき手動でのログ出力作業を大幅に削減できます。 また、テスト実行ログに記録されている値に対して、呼び出し元(実装コード)の Call Stack を調べることもできます。 Value Explorer を使用することで、標準出力をコードに仕込まずともデバッグ作業を可能にしますが、使い慣れている console.log を使ったデバッグも Wallaby.js は対応しています。エディタ上にログの結果を表示できるため、コードとログを同時に確認しながらデバッグ作業を行うことができます。 Wallaby.js は多様なログの確認方法があり、当記事では紹介しきれないので気になる方はチェックしてみてください。 Introduction: Advanced Logging Wallaby.js を使ってみて Wallaby.js を使ってみて特にリアルタイムにテスト結果がフィードバックされる点はとても便利だと感じました。Wallaby.js を導入する前はファイル単位やテストケース単位で、テストを実行させる必要があり時間がかかっていましたが、リアルタイムにテスト結果を反映してくれるので実装に集中して開発を進めることができます。リファクタリングでは、リファクタリングの前後でインターフェイスが保たれているかをエディタ上のテストカバレッジインジゲーターから確認できる点は Wallaby.js の強みだと感じました。 FAIL PASS また、 Smart Start という機能により、コードの変更により影響を受けた箇所のみ自動的にテストが実行されるので、とても高速にストレスフリーで動作してくれます。Findy Team+のように大規模なプロジェクトでも高速に動作してくれるのは非常に強みだと思います。 最後に 今回の記事では、JavaScript の統合テストツールである Wallaby.js について紹介しました。 Wallaby.js の導入により、開発プロセスの効率化やコードの品質・安定性の向上が期待できます。是非、Wallaby.js を活用して、よりスムーズなフロントエンド開発を実現してみてください。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは、あるいはこんばんは。 @gessy0129 です。 このたび、ファインディに入社しましたので、入社エントリーをさせていただきます。 お時間のあるときにご覧いただければと思います。 ファインディに対する想いと気持ち 改めて、この度、ファインディ株式会社に正式に参加することとなりました。 パチパチパチパチ 昨年からいくつかのnote記事を執筆させていただいたところでございますが、それに絡めつつ、今回の気持ちを綴りたいと思います。 参考記事: ANDPADを退任しました|げっしー 2024年目標と決意と挑戦と|げっしー 相変わらず、自身の掲げるミッションは、 半径数メートルから幸せの連鎖を生み出す という事だと思っています。 過去の在籍企業で、VPoEや開発本部長として長い間勤務をしてきました。 その中で、ものづくりに集中しているエンジニアたちを支えていく事というのは相当なやりがいでした。 エンジニアたちが幸せに業務出来る環境を整え、それが連鎖していくようにすること。 これはとても楽しかったです。 ※ もちろんVPoE としての業務はこれだけではないです。 この領域を更に深め、挑戦するエンジニアを応援していきたいという思いが強まりました。 そして、その想いが高まった時、多くの選択肢の中からファインディと出会いました。 ファインディのミッション、ビジョン、バリューに共感し、これは非常に大きな出会いであると感じております。 エンジニアの可能性を拡げ、スタートアップのエコシステムに貢献できることを願っています。 やろうとしてること ファインディは色んな事業を展開してます。 エンジニアの転職を支える転職事業 フリーランスエンジニアを支えるフリーランス事業 国内外のエンジニアと企業をつなげるグローバル事業 活躍するエンジニアを支えるTeam+事業 技術選定や意思決定をサポートするTools事業 などなどがあります。 これらの事業がすべて、挑戦するエンジニアのプラットフォームを作り上げ、エンジニアの可能性を広げることにつながると考えております。 そして、CEOの山田さんやCTOの佐藤さんが、この領域で挑戦しようとしていることに感銘を受けております。 ここで、素晴らしいメンバーと共に、挑戦するエンジニアが必要とするサービスを積極的に提供していきたいと思っております。 しかし、まだまだファインディ自体が、挑戦するエンジニア、挑戦したいエンジニアに積極的に選ばれる状況にあるとは言えないのではないかと考えております。 これは、ファインディにとっても僕にとってもさらなる 伸び代 だと思っております。 「ファインディに相談すればなんとかなる」という状況を作り上げることができればと考えております。 最後に ファインディの対外活動にも積極的に参加していく予定でございます。 その際は、皆様、よろしくお願いいたします! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
Findyでエンジニアをしている松村( @shakemurasan )です。 以前、弊社の栁沢が「RailsのCIのテスト実行時間を10分から5分に高速化した話」という記事を投稿しました。 tech.findy.co.jp 本記事ではその少し前のお話、そもそもRSpecの実行時間自体にまだまだあった伸びしろ、特にFactory周りの問題をTestProfというgemを活用して解消していった話となります。 当時のRSpecの実行時間状況 TestProfとは TestProfでの分析結果 改善1. 関連したレコードを複数件作成しているFactoryを1レコードに減らす 改善2. テストで必要最小限なレコードのみを作成する RSpecの実行時間の改善結果 考察 当時のRSpecの実行時間状況 これまでにもテスト実行時間の短縮のための取り組み(CI側でのマシンの並列起動および並列実行)はしており、そこまでストレスのある環境ではありませんでした。異様に実行時間を要しているテストが存在することはメンバー間で認識しており、何となく原因のアタリはついていたものの、並列実行導入で快適な環境が得られていたので、テスト軽量化の優先度が落ちている状況でした。 しかし、じわじわとテスト実行時間は伸びていき、並列実行の導入当初は10分程度だったものが、15分を超えるケースが目立つようになってきました。いよいよテスト軽量化に着手しようかという話になり、実際に対応していくことになったのでした。 更に並列化を推進しようという案もその時点であったのですが、そもそも前述の「異様に実行時間を要しているテスト」が原因でマシンごとのテスト実行完了時間に度し難いバラツキが生じており、まずはここを解決しなければならないよねとなりました。 TestProfとは テスト軽量化にあたって、まずは何となくアタリをつけていたところに本当に原因があるのか測定することにしました。解析/測定に際し、TestProfが使えそうということは様々な記事、他企業様のテックブログ事例から知っていたので、これを採用することにしました。 github.com TestProfには様々な機能があるのですが、アタリをつけていたのはテストデータ生成周りだったため、FactoryProfというFactory周りの解析機能を使っています。FactoryProfを用いることで、Factory別の 総呼び出し回数 / 総実行時間 / 1回あたりの実行時間 あたりをレポーティングでき、この機能を用いて改善に着手しました。 ※ この後の章で登場するファイル名、Model、Factoryは仮名に置き換えていますが、数値は実際のものを掲載しています TestProfでの分析結果 まず大前提、時間がかかっているテストケースの状況を見てみます。 spec Before After Reduce Worst1 78.37s ??? ??? Worst2 75.71s ??? ??? Worst3 48.76s ??? ??? Worst4 48.16s ??? ??? Worst5 88.01s ??? ??? Total of worst 339.01s ??? ??? 実にテストケース5本で5分39秒を越えている状況で、これはちょっと辛いな.... というのがわかります。ここから、一番重たいテストケースのみを指定してFactoryProfの解析をかけてみます。 FPROF=1 bin/rspec spec/models/worst_spec.rb:2244 すると次のようなレポートが得られます。 [TEST PROF INFO] Factories usage Total: 1586 Total top-level: 8 Total time: 01:32.432 (out of 01:59.446) Total uniq factories: 12 total top-level total time time per call top-level time name 309 0 80.7570s 0.2613s 0.0000s full_item 103 0 0.8972s 0.0087s 0.0000s shop_user 103 0 90.3245s 0.8769s 0.0000s item_like 103 0 88.4511s 0.8587s 0.0000s shop ... ... ... この結果を見ると、 item_like shop が呼び出し回数と1回あたりの実行時間あたりが1s弱と長いことがわかります。ここから段階的に改善の手を打っていきます。 改善1. 関連したレコードを複数件作成しているFactoryを1レコードに減らす そこで実際のコードを読んでFactory間の依存関係を見てみると次のような状況でした。 item_like -- create --> shop ┬-- create --> full_item ├-- create --> full_item └-- create --> full_item テストの要件は割愛させていただくのですが、テストを実行するうえで full_item は3件も必要なく、最低1件はshopにぶら下がっていれば十分という状況でした。 item_like というのはここ以外でも結構色々なところで使われているFactoryで、ほとんどのテストは最低1件のshopがぶら下がっていれば問題ない状況でした。 そこで、 item_like のFactoryを修正して full_item を1件だけに限定して再解析したところ、次のような結果が得られました。 [TEST PROF INFO] Factories usage Total: 659 Total top-level: 8 Total time: 00:36.813 (out of 01:14.075) Total uniq factories: 11 total top-level total time time per call top-level time name 103 0 32.7865s 0.3183s 0.0000s shop 103 0 27.1212s 0.2633s 0.0000s full_item 103 0 0.8971s 0.0087s 0.0000s shop_user 103 0 34.5748s 0.3357s 0.0000s item_like ... ... ... 単純に full_item の生成回数が1/3に減り、それに比例して実行時間も約1/3に圧縮できました。 改善2. テストで必要最小限なレコードのみを作成する 別の重たいテストも解析していくと、共通して同じ問題が見えてきます。 [TEST PROF INFO] Factories usage Total: 3157 Total top-level: 582 Total time: 02:05.161 (out of 04:30.214) Total uniq factories: 48 total top-level total time time per call top-level time name 322 6 6.2221s 0.0193s 0.1149s user_profile 276 70 74.0465s 0.2683s 5.2776s shop 230 0 63.5779s 0.2764s 0.0000s full_item ... ... ... 次に着目したのは、 full_item の実行時間の長さです。1回あたり 0.2764s ということでそんなに長く感じないかもしれませんが、呼び出し回数が非常に多く、塵も積もればこのテストでは230回呼ばれて 63.5779s は無視できない実行時間になっています。 またまたコードを読んでみると、 full_item は関連するデータを全部盛りで作る.... というFactoryになっていました。 item というモデル自体、システムの中でコアなドメインのモデルとなっており、非常に多くの関連を持ちうるものなのでした。しかし、大部分のテストにおいてはそこまで完全な状態の item は要らないという状況でした。 そこで、 shop 生成時のデフォルトは full_item ではなく item というスリムなFactoryを使うように切り替え、再度解析をしてみることにしました。 [TEST PROF INFO] Factories usage Total: 2697 Total top-level: 582 Total time: 01:06.857 (out of 02:53.458) Total uniq factories: 47 total top-level total time time per call top-level time name 322 6 4.7178s 0.0147s 0.0844s user_profile 276 70 29.5793s 0.1072s 4.0465s shop 230 0 10.8307s 0.0471s 0.0000s item 結果、1回あたり 0.2764s かかっていた full_item から、 0.0471s で済む item に取り変わったことで、このテストの実行時間は半分にまで圧縮できるようになりました。 RSpecの実行時間の改善結果 他にもTestProfを用いて細かな改善は入れていき、最終的にワースト5のテスト実行時間は次のように変化しました。 spec Before After Reduce Reduce Rate Worst1 78.37s 17.55s -60.82s -77.6% Worst2 75.71s 15.73s -59.97s -79.22% Worst3 48.76s 8.28s -40.48s -83.01% Worst4 48.16s 7.84s -40.31s -83.72% Worst5 88.01s 18.1s -69.9s -79.43% Total of worst 339.01s 67.5s -271.51s -80.08% 339.01s から 67.5s に圧縮され、この最悪値だったテスト5本に限定して言うと、実行時間を8割以上削減できました。さらに上記のテスト以外でも今回改善したFactoryは使われているわけですから、テストの総実行時間にも効いてくるわけです。 考察 今回、TestProfを用いて、何となく重たいんだろうと思っていたところが想定以上に無駄なことをしていたことがわかりました。 「とりあえずデフォルトで全部入りのテストデータ作っておくか!」というのは、ともすればやりがちですし、歴史の長いコードベースだと気づきにくいように感じました。 「推測するな、計測せよ」という言葉がありますが、実際に計測して打ち手をピンポイントに打っていくことで、着実に改善している感覚を得られて周囲にも説明しやすかったのも学びです。 また、今回Factoryの挙動を大胆に変更することで実行時間削減を実現していますが、これは常日頃みんながテストコードをかなり手厚く書いていてくれたおかげというのが大きいです。システムが壊れないことを担保するため、不安と戦うために我々はテストを書くわけですが、テスト自体のリファクタリングにもテストコードが有効であるということは学びになりました。 ファインディは積極的にエンジニアを採用しています。CI/CDを始め、Four Keys、開発生産性、技術トレンド、転職市場など興味のある方は、お気軽にカジュアル面談を受けてみてください :) ファインディの採用情報はこちら↓ herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 Findy 社の Tech Blog を開設して 1 ヶ月程度が経とうとしています。 このブログを通して弊社の技術情報だけでなく社内のエンジニアのことをもっと知ってほしいと考えた結果、今回から 自慢の作業環境を大公開 と題して、社内のエンジニアの作業環境と、そこに対する考え方、思いなどを発信していく事になりました。 弊社のオフィスは東京にありますが、北は北海道、南は福岡まで遠隔地からのフルリモートで JOIN しているエンジニアが多数在籍しております。 エンジニアの多くが各自の自宅から作業しており、きっと自分にとっての最高の環境を整えているはずです! それでは、弊社エンジニア達の自慢の作業環境を見ていきましょう! 作業環境を大公開 戸田 というわけで初回は福岡から JOIN している Tech Lead の戸田の作業環境から紹介させてもらいます。 作業スペースの全体像はこんな感じです 基本的には DELLの32 インチの 4K モニタ を使い、クラムシェルモードで作業をしています。 スピーカー はモニタのアーム部分に接続しており、イヤホンを繋げてボタン一個で出力切り替えが可能なので、普段はスピーカーを使い静かにしたい時はイヤホンを使う。ということが簡単に切替可能です。 Web カメラ と マイク は別途購入して外付けで利用しています。リモートでの作業がメインとなるため、映像、音声環境は最低限のマナーと思い投資しました。 デスクは bauhutte というメーカーの 昇降デスク を使っています。 この昇降デスクは電動でボタン一つで高さを自由に変更でき、横幅も奥行きも大きいので色々な作業シーンに合わせて利用することが出来るので非常におすすめです。 そして安心と信頼のバグ退散お守り。CI を通すときや重要なリリースの前に祈りを捧げます。 手元周りはこんな感じ キーボードは HHKB Professional HYBRID Type-S を使っています。 今まで色々なキーボードを試しました。その結果、個人的に作業終了後の手元の疲れを一番小さく感じたのはこのキーボードでした。 特殊なキー配列ですが、慣れたらコードを書いたりコマンドラインを叩いたりしやすいキーボードだと思います。 マウスは Apple の Magic Trackpad を使っています。マウスに対する拘りはなくて、正直 Mac のショートカットアクションが使えれば何でもいいです。早くマルチペアリングに対応して欲しいです。 また、変わり種としては指の筋トレ用具を手元に置いてます。 事の発端は格ゲーをしてた時に思っていたより指が動かなくて、「人類は薬指と小指を思ってるより使ってないな?」と感じ、この二本の指を鍛えるために買いました。 リモート会議中とか、コードを考えてる時とかずっとこれで指を鍛えてます。これで鍛えだしてから薬指と小指がスムーズに動くようになり、キーボードのタイピングが今までよりもスムーズになった気がします。 作業用 BGM は HomePod mini と Apple Music の合わせ技を使っています。 iPad を HomePod mini とペアリングさせて、サブスクには新曲やサントラがどんどん追加されます。 作業スペースの横には趣味のプラモ作成スペースを、後ろには本棚とプラモケースと積みプラ。 自分の好きなものに囲まれているというのは、毎日1人で黙々と作業する環境としては想像以上に重要だと思います。 毎日部屋に籠もって1人で作業しているので、五感に入るもので飽きが来ない環境を作ることが大事だと思います。 熊野 青森からフルリモートの熊野( @shoota )です。 フルリモートは 2017 年夏からで 7 年目になります。 まずはメインのデスクから。 自宅に備え付けのデスク MacBook Pro 16” をノート用スタンドに載せ、デュアルディスプレイで作業をしています。 MacBook ディスプレイは基本的には Slack 専用で、ほぼすべての作業は 外部ディスプレイ + 仮想デスクトップでこなしています。 外部ディスプレイは DELL の 4K ハブモニター に仕事用の MBP と個人用の Mac mini を繋いでいて、画面を切り替えると接続しているキーボードも自動で切り替わるのが気に入っています。 デスクライトを Amazon Alexa に接続し、デスク左側の Amazon Echo から音声操作できるようにしています。デスクから離れたあとにライトの消し忘れに気づくので、遠くからでも声でライトのオンオフができるのが便利です。 Echo は Spotify などの音楽再生をしたり、他の家電の操作にも使っています。 デスク右側は Anker の無接地タイプの充電器 で iPhone のスタンバイ表示をしています。 その隣には iPad mini をおいていて、ちょっとしたメモをしたり、作業をしながらオンラインイベントを見たりするときに使っています。 全体的に黒で統一するのが好きで、トラックパッド だけが白なのでそろそろ黒の方に買い替えちゃおうかなと思っています。 キーボードは Keychron の分離式キーボード Keychron Q11 QMK Custom Mechanical Keyboard 、ポイントデバイスは Magic Trackpad2 です。 分離式キーボード 肩こりがひどくなりやすいので分離式キーボードをずっと使っていますが、Q11 はキースイッチごと交換したりキーマップのカスタマイズが簡単で、多機能なのでかなり気に入っているキーボードです。 いまは赤軸スイッチと標準仕様のキーキャップなので、そろそろキーキャップを変えたいな〜と思っているところです。 またフルリモートとしてはビデオ通話の品質を大事にしたい&自宅では子どもたちの声などの環境音が混ざりやすいので、自分も音響はしっかりと用意しています。 マイクは指向性の Yeti Nano で自分の声だけが入るようにスタンド設置しています。 Yeti 以前はヘッドセットを使っていましたが、いずれも「物理スイッチでミュートできる」ことがこだわりです。 急にくしゃみしたいときにソフトウェアミュートは間に合わないので 逆に出力側は周りの音が聞こえないと不便なので、オープンイヤータイプを愛用していて、いまは shokz の OPENFIT を使っています。 指向性マイク 最後にデスクの後ろに DIY で作ったコミック棚があるので、自慢がてらに紹介したいと思います。 自分が好きなものや集めたものに囲まれて仕事をするのが好きなので、コミック(たぶん 800 冊くらいあります。もう数え切れません。)やゲームグッズ、お気に入りのウイスキーをおいています。 安全率を含めた荷重計算をして設計図をつくり、部材の切り出しから組立て、取り付けまでひとりでやりました。 だいたい 2 万円強くらいですべて揃い、先日の震度 5 以上の地震でも コミックは 1 冊も落ちませんでした。 2023 年下半期の総会、 Fine-day で MVP を受賞 したときのトロフィーも飾っています。 DIY本棚とMVPトロフィー 仕事場でありながら自分らしさを出しつつ、仕事における自分なりの「快適性 / 合理性」を求めたデスクに仕上がっていると思っています。 主計(かずえ) 福岡からリモートでフロントエンドの開発をしている主計( @nesskazu )です。 デスクの全体像はこのような感じです。 デスク全体 4k ディスプレイを 2 枚配置しコーディングしながらデバッグできるようにしています。 ミーティング時にドキュメント等を参照できるのも便利です。 サブモニターはデバッグしやすく、web等の閲覧性が良いため縦配置にしています。 コーディングとデバッグの画面配置 Thunderbolt ケーブルで会社支給 PC と私用 PC で全ての機器の接続が切り替わるようにしています。 ドッキングステーションには CalDigit TS3 Plus Dock を使用しています。 Thunderboltケーブル1本でPC切替 ドッキングステーション キーボードは静電容量無接点方式やメカニカルなどいろいろ試してきましたが、 自分はキーストロークの深いキーボードは苦手(疲れる&タイプミス多い)なことがわかったのでキーストロークが浅いキーボードを使っています。 MX Keys mini がお気に入りでしたが、途中からチャタリングが発生したり Touch ID が欲しかったので現在は Apple Magic Keyboard を愛用しています。 また、切り替えや充電の手間をなくすため有線で接続しています。 Apple Magic Keyboard リモートワークということもありミーティングが相手と自分双方にとって快適なものになるように構築しています。 マイクは周囲の音を拾いにくいダイナミックマイク(SHURE MV7)を採用しています。 カメラはなるべく目線の高さに合うようにディスプレイ間のスピーカーの上に設置しています。 マイクとカメラ ミーティングや BGM の音は OWNDAYS の HUAWEI Eyewear で聞いています。 普段メガネ付けている人であればメガネが変えるだけでスピーカーが着いてくるので便利です。 ミーティングのたびにイヤホンを装着したりする必要がなくなります。最近電池持ちが悪く昼休みに充電する必要があるため Eyewear2 の購入検討中です。 Eyewear を使い初めてから休みの日にしかコンタクトを使わなくなりました。 Eyewear 我が家でもバグ退散のお守りが後ろから見守ってくれています! バグ退散お守り このように仕事をするうえで不便な点を排除し、快適に作業等ができるように意識してデスクを構築しています。 まとめ いかがでしたでしょうか? 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。こんばんは。 開発生産性の可視化・分析をサポートする Findy Team+ のフロントエンド リードをしている @shoota です。 Findy Team+はエンジニア組織の開発生産性を可視化し、開発チームやエンジニアリングメンバーのパフォーマンスを最大化するための支援をしています。 そして(当然のことながら)Findy Team+ を作っている自分たちも、チームや個人でドッグフーディングをして、チームや自分自身の働き方やエンジニアリング組織の健康チェックをしています。 今回はそんな Findy Team+の開発チームのうち、フロントエンドチームがどのような開発環境・開発インフラで働いているかの概要をご紹介したいと思います。 フロントエンド技術スタックとCI高速化 技術スタック まずはじめにフロントエンドの技術スタックを簡単に紹介します。一般的なSPA構築の技術スタックを採用しており、それほど特別なものではないことをご理解いただけると思います。 React React Router Redux TypeScript GraphQL Apollo Client GraphQL Codegen Emotion Storybook Testing Jest @testing-library/{react,jest-dom,user-event} reg-suit Linter / Formatter ESLint Stylelint Prettier ここまではいわゆる一般的なSPAの構成ですが、Findy のフロントエンドはモノレポ管理ツールである Nx を利用することで高速化を図っています。 Nxの機能詳細についての説明はここでは省略しますが、トップページに「Smart Monorepos・Fast CI」とある通り、CIの高速化が簡単に管理できるところが最大の特徴と恩恵だと思っています。 NxでCIを高速化する Nxは内部に複数のプロジェクトを持つことができ、且つ、それらの依存関係を自動で解析します。 この「プロジェクトの依存関係」をもとに、プルリクエストでの「変更されたプロジェクト」と、その「変更部分が依存しているプロジェクト」のみのテストを実行する手段を提供しています。 これによって開発者が開発しているものに関係のない部分は省略されるためCIが高速化します。 それ以外の変更についてもNx Cloudにキャッシュが残っていればその結果を採用してテスト等をパスさせ、CIが高速に完了します。 CIの実行結果を載せてみました。 GitHub Actionsの様子 共通のhooksを修正してる3段目のプルリクエストではほぼ全てのテストを実行(そして新たにキャッシュ)しているため、20分以上のテスト時間がかかっています。 一方でその他をみてみると、新しい画面などの通常開発の場合は変更内容がプロジェクト内で完結しているので、CIの実行時間は数分で終わっています。 また単にCIが高速化される以外にも、Nxは開発生産性の向上に寄与してくれます。 それは 「プルリクエストはできるだけ小さく作ろう」という開発文化を「CI時間」という数値で可視化 してくれることです。 前述の通りプルリクエストの変更の依存関係が小さいほどCIは早く終わりますので、逆にプルリクエストが広範な範囲で大きくなってしまうほどCI時間が長くなります。 プルリクエストの粒度が大きいと、1) CIが遅くなり、2) レビュー依頼するまでの時間が空いて忘れがちになり、3) レビュー量も多くて時間がかかるという悪循環に陥ります。 そこでプルリクエストを作る側はどうにかこれを避けようとする力学が働き、CIが高速であれば作業内容に集中し、レビュー指摘の反応や修正も楽になっていくのです。 プルリクエスト / レビューに反応する 前述の通りNxの依存管理を基盤としてCIを高速化していますが、Findy ではレビュー依頼やレビューコメントなどGitHubでのやり取りをSlackに移植してコミュニケーションのトリガーを通知しています。 実際のSlackの画面はお見せできませんが、以下のようなタイミングでSlackに状況が実況され、レビュー依頼が来た場合は通知もされます。 プルリクエストを作った時 プルリクエストにコメントされた時 プルリクエストがApproveされた時 プルリクエストをマージ(クローズ)した時 またGitHub標準のSlackアラート機能も併用していて、レビュワーにアサインされたままのプルリクエストがあれば1時間ごとに通知されます。 これによって「レビュー依頼に気づかなかった」状況を減らし、レビューが放置ぎみのときには「なにか事情があるのかな?作業に入れない状況かな?」と察したり、レビュワーを変更するなどの対処もできます。 このSlack Appは弊社テックリードの github-to-slack-notification をベースに構築されています。 Findy謹製のSlack通知App プルリクエストを分類する Findy Team+ は、開発メンバー、開発チーム、リポジトリ、プルリクエストのラベル、日時やカレンダー情報などの複数の条件をディメンションとして、個人やチームのリードタイムやアクション数などのパフォーマンスを計測できます。 プルリクエストは機能開発やリファクタリング、バグ修正、ドキュメンテーションなど内容が様々になってしまうため、パフォーマンスがどのような部分で発揮されているかを分類するのは非常に困難ですが、Team+ではプルリクエストのラベルを利用して一定の分類ができるようにしています。 しかし一方で、「プルリクエストにラベルをつけておく」という作業を定常的に、すべてのエンジニアが、漏れなく、間違いなく、実施していくのはプルリクエストの分類以上に困難なことでしょう。 Slackを見返すと入社3日目の自分がいきなり本質をついています。 ラベル運用について気づくshoota そう思っていたときが私にもありました。 Findy Team+のフロントエンドのプルリクエストは自動でラベルをつけています。 そもそもgit上の全てのコミットは Conventional Commits に則るよう、 commit lint で制約を設けています。 そしてプルリクエストのタイトルもConventional Commitsの形式にするようにルール化しているので、プルリクエストのタイトルにはこれらの接頭句が必ずあり、これを検知してGitHub Actionsで分類、対応するものにラベルをつけるようにしてます。 プルリクエストの種類は、タイトルから自動で分類させておく デプロイする 小さなプルリクエストが無事にマージされたら、デプロイしていきます。Team+ フロントエンドは、GitHub Actionsの schedule cronを利用して一日に2回定期デプロイをしています。 gitはgit-flowをベースにした運用をしつつ、プルリクエストテンプレートにリリース時に必要な確認項目を入力する欄を設け、リリース時にはこの確認項目を自動生成するようになっています。 まずはgitの運用フローを簡単に図式化してみました。 ブランチ運用 ※ の部分はリリース用プルリクエストのcommit hashをmasterからdevelopへ移動するための操作で、基本的には差分は発生しないものです developブランチを定時間でリリース用ブランチに派生して、ステージングにデプロイします。 このときの主なチェック項目として、 バックエンドで先行するプルリクエストがないか(ある場合はそのプルリクエストのリンク) APIレスポンスの変化やエラーハンドリング、後方互換性など、開発者のみが確認できる確認項目がないか 実装機能と想定仕様の合致など、機能リリースのためのQAが必要でないか をプルリクエストテンプレートで記載するようにしており、リリースプルリクエストにはこれらすべてを列挙して簡易的なリリース判定を行っています。 まとめ 今回は Findy Team+ の開発フローに焦点をあてていくつかの要素をご紹介しました。 これ以外にもさまざまなツールやサービスを利用して品質とスピードを両立させるための開発基盤を持っていますが、ひとことではお伝えしにくいものもあるので、それぞれより詳細な記事でご紹介して行ければと思います。 スピードを意識したフロントエンド領域の開発環境として高いレベルで整備し、可視化して改善するように心がけています。 自分の開発能力、スピードをフルに発揮したいという方は、ぜひ下の採用情報もごらんください。 herp.careers
こんにちは、ファインディ株式会社で機械学習エンジニアをしていますsasanoshouta( @Edyyyyon )です。この記事は、言語処理学会第30回年次大会(NLP2024)に社で初めてプラチナスポンサーとして参加してきましたので、その参加報告になります。 NLP2024とは? 言語処理学会第30回年次大会(NLP2024)は,2024年3月11~15日の期間,5日間の日程で開催いたします.チュートリアルは3月11日午後1時に開始,本会議は3月11日午後4時半から14日午後7時までの4日間です.現在,現地とオンラインのハイブリッド開催の形態で準備を進めています.現地とオンラインの両方から参加し,発表・聴講・議論をすることができます. *1 大会概要は引用文の通りで、今年は神戸ポートアイランドの神戸国際会議場で開催されました。 参加の背景 今回初参加となりますが、スポンサーするに至った背景は以下の通りです。 機械学習、データサイエンスを初めとするデータ系職種・界隈への認知拡大や打ち手が足りておらず、その足がかりとしてのスポンサード ファインディでもデータ系職種を絶賛募集しているが、そもそも機械学習やデータサイエンスにも取り組んでいる会社であるとの認知が広げきれていないので、「何を?なぜ?どのように取り組んでいるのか?」を知って頂きたい 「エンジニア開発を支援する企業」であることをアピールできている一方で、実は内部でデータ活用・機械学習を使っている事の認知を広げられていない背景があり、まずは知って頂きたいと言う事で、今回スポンサーとして参加してきました。 会場の雰囲気 前述の通り、弊社ではNLP2024を含む学会への参加経験が全くなかったので、過去のNLP202X年度の雰囲気や、他社さんの過去参加記事を参考に準備を進めていました。また、私自身や今回同行したメンバーの中にも学会参加経験者が数名いた事もあり、普段弊社が参加するカンファレンスイベントなどよりも少しかっちりとした準備を進めていました。いざ当日会場に着いてみると想像していたよりもラフに参加できそうな雰囲気でした。(筆者が最後に参加していた頃の学会がX年前で、真面目な雰囲気の印象があった為か、時が流れて参加しやすい雰囲気になっているのは驚きました。) ポスターセッションの雰囲気 弊社スポンサーブース こちらの画像の、掲示スペースが少しもの寂しげなブースがファインディのスポンサーブースになります。ポスターの用意が間に合わなかった為、苦肉の策として弊社のデータ系職種採用資料を印刷して掲示していました。 弊社スポンサーブースの雰囲気 どうしてこんなに寂しくなってしまったのかと言うと、もともと筆者がポスター準備担当だったんですが、直前の体調不良により作業を進める事ができず、敢えなく準備期間が過ぎ去ってしまった為でした。しかたない側面はありますが、沢山の方とお話できたので伸びしろと捉えて次回参加時こそは掲示物を作って参加したいと思います。 スポンサーブースでお話したこと 今回は、弊社データソリューションチームの採用資料から、機械学習による取り組み事例をいくつか持参し、モニターに投影しながらこられた方に弊社のデータ活用先とその実現方法について紹介をさせていただきました。また、言語処理学会と言う事もあり、実際に社内でも検討しているNLPも取り入れた今後の方向性も反映したものになっています。採用資料から2つ抜粋して簡単に紹介します。 1つ目は「LLMを用いたキャリアサマリの作成」です。👇 LLMを用いたキャリアサマリの作成 1年ほど前の取り組みになりますが、OpenAI API公開後に活用施策第1弾と言う事で、1週間でのリリースを目標に作成した機能になります。 職務経歴書などの情報を入力すると、それを要約して二つ名をつけてくれると言った機能でした。 私の場合は、「AIの魔術師」「AIのキラーコンサルタント」と言う名前をつけてくれました。 2つ目は「行動ログを活用した転職意欲や志向の検知」です。👇 行動ログを活用した転職意欲や志向の検知 こちらの機械学習モデルは、転職意欲が高いにも関わらず、プロフィール上転職意欲が低いままになってしまっている方向けの機能としても使うことができますが、どちらかといえば 転職活動の意欲がないのにスカウトが送られてくる 事での煩わしさを軽減する防御の役割を持った機能として運用しているものになります。 プロフィールのステータスは転職意欲が高いままになっているが、実際には 転職活動が完了したままステータスを変更するのを忘れてしまっている というケースがあったりします。 そうした方に、スカウトを追撃してしまうと転職サービスとしての不信感に繋がりかねないので、事前に予防できるものは出来る限り予防するようにしています。 ブースに立ってみて 当初想定していたよりも多くの方がブースに来てくださり、筆者もブースに立って意見交換をさせて頂きました。ブースに聞きに来て頂いた皆様ありがとうございました。 ファインディ自体が「 エンジニアに特化した中途転職サービスを中心に事業を展開している 」事と、学会に参加されている方々の属性が、 機械学習・データサイエンスを生業とされている社会人参加の方 大学・大学院大学から学生参加の方 の2属性の方々がメインであった事と相まって、「 ファインディ株式会社 」と「 何をしている会社か? 」の知名度にはかなりの伸び代を感じました。一方で、完全アウェーだった訳でもなく、「 スキル偏差値の会社 」として認知いただいている方が多かったです。データ界隈での機能とサービス・会社名の繋ぎ込みにまだまだ課題を残しつつも、機械学習・データサイエンスの界隈にも一定取り組みが届けられている事を感じられました。 個人的な聴講セッションの感想 スポンサーとしてブースに立つ傍ら、いち聴講者としてセッションをいくつか聞いたり他社スポンサーさんの企業ブースにお邪魔してお話を伺わせていただいたりしたので、メモベースにはなりますが個人的な感想を書き連ねておきます👇 オーラル・ポスターセッションそれぞれに共通して言えたのは、大前提 LLMに関する研究発表である 事がほとんどでした。 だからと言って、 OpenAI API をそのまま使って研究をしていたり、サービス実装してコア機能としている企業さんや研究もほとんどないような印象でした。 リクルートさん、サイバーエージェントさんなどのテキストデータを潤沢に持ち合わせており計算資源も豊富な企業でも、一部プロセスに取り入れられているとお聞きしました。 社内向けに、全社の業務効率化を目的としてRAGや文章埋め込み(embedding)を使い、LLMの弱点であるhallucinationを低減した仕組みを取り入れたお問い合わせbotを実装・運用している。 様々お話を伺った所、現在のLLM界隈のトレンドでは、お問い合わせbotのような活用がトレンドとなっていそうで(個人の見解)、このような流れはしばらく続きそうな雰囲気を感じた。 一方で、勢いが若干失速した感はありましたが、 自社専用のLLMをスクラッチで開発する という企業さんのお話もいくつか伺えました。 「ChatGPTとかClaude3とか低価格で高性能なAIが出てるし、今後もその流れは変わらないはずなのになぜ?」 と思い、お話を聞きいてみました。 自社でLLMを作っておく事で、GAFAMOが提供するLLMの規約が変わった時のリスクヘッジになる との方針で、研究をやめていないとの事。 どの企業さんにも共通していたのは、1つ自社のLLMを作れておくと用途に合わせて柔軟にカスタマイズができる点も、内製化のメリットの1つとの事でした。 為になったセッション 全てのセッションが興味深く考えさせられたり、明日使えるものたちが多数でしたが、個人的に1番勉強になったセッションを共有します。全体の発表スケジュールは こちら から。 文章のチャンクに基づく知識グラフを活用したRAG(産総研さん) 元論文は こちら から RAGを使ってLLMの回答精度を高める為の取り組みはいくつもありますが、LLMに与えられるクエリにcontextを付与する為に知識グラフをDBとして構築しておき、知識グラフからの情報検索プロセスをRAGに組み込む、と言うものでした。弊社でもRAGを用いた質問回答botを作って運用したりしており、オーソドックスに類似度計算した上位N件から回答を作成すると言うシンプルな構成を取ったりしています。こちらの研究にある通り「クエリの文脈はすべて類似度で測れるとは限らない」と言う事を痛感しているので、こちらの研究を参考にしてみたいと思いました。 参加してみての感想 初めて言語処理学会にスポンサーとして参加してみて、やはりデータ系職種・界隈での認知拡大の伸び代がある事を強く実感しました。 その理由はいくつかあると思いますが、これまで今回のようにデータ系職種の方が集まる学会やカンファレンスに積極的に参加していけてなかった所が大きいと感じました。 もちろんこれだけではなく、社内でもデータを活用した取り組みは沢山動いたりこれから始まったりしている最中なので、そうした取り組みをもっと積極的に発信する事で、より多くの方にファインディを知って頂きたいなと思います。 いち参加者としても、短い期間でまとまった数のNLPに関する研究発表を自分の五感で感じる機会は中々なかったですし、多種多様な取り組みや企業さんとお話できてとても良い刺激になりました。すぐに試せそうなノウハウを沢山得ることもできましたし、忘れないうちに現在の取り組みの参考にさせていただこうと思いました。 今後は、言語処理学会をはじめ学会へのスポンサー、ポスター発表などにも力を入れていきますので、どこかで見かけた際は何卒よろしくお願いいたします。 さいごに ファインディでは、機械学習エンジニア・データサイエンティスト・データアナリストを絶賛採用中です。以下のページから応募頂けますので、興味のある方は是非カジュアル面談などでお話しましょう。 findy-code.io findy-code.io *1 : ※ NLP2024公式ページ より抜粋
1. はじめに Findyでデータエンジニアとして働いている ひらき( hiracky16 )です。 この記事ではFindyで取り組んでいるデータ基盤について紹介します。 Findyでは2023年からデータエンジニアを採用し本格的にデータ基盤構築に着手しています。 これまではBigQuery(Google Cloud)を中心としたデータ蓄積・利活用をしていました。 今後もっとデータ分析、機械学習などのデータ利用を加速するためにデータマネジメントが不可欠だと考えており、データエンジニアを採用しています。 まだ1人目のデータエンジニアがジョインしてから半年間くらいの取り組みですが、現時点のアーキテクチャや技術スタック、伸びしろや展望などを記します。 1. はじめに 2. これまでのデータ基盤の伸びしろ 3. 現状のデータ基盤アーキテクチャ 3.1. 本番環境のIaC化と開発環境の準備 3.2. データロード系のツール刷新 3.3dbtからDataformへの変更 3.4. データを4層で管理 4. 今後やりたいこと 4.1. 全体を統括するオーケストレーションツールの導入 4.2. データ基盤の利用者拡大に向けたルールと権限 4.3. 複数部門またいだデータ基盤の設計、構築 5. 終わりに 2. これまでのデータ基盤の伸びしろ 僕が入社する前のアーキテクチャがこんな感じです。 プロダクトのRDSからEmbulkを使って1日1回必要なデータをBigQueryへ転送していました。 プロダクトのデータだけでなくGAイベントデータを蓄積していました。 昨年からTransformのツールにdbtを導入しており定期的に実行されるクエリを徐々にdbtへ移行している状態でした。 データ利用で言うと定期的に見るべき数値はLooker Studioで可視化したり、GASからBigQueryへクエリ発行してスプレッドシートで表示しています。 また別Google Cloudプロジェクトにある機械学習用のデータセットにコピーもされていました。 上記を踏まえて現場の課題感やアーキテクチャ図を見ての客観的な伸びしろをまとめてみました。 Embulkなどデータロード系のジョブが失敗した場合のリカバリに負荷がかかっている dbtを使ったクエリが増えない スプレッドシートとGASで実行しているクエリの正確性が担保できていない データソースの変更に対する影響範囲が見積もれない(データリネージが追えない) データ基盤と機械学習用の検証環境がないため新規開発やアップデートにハードルがある 機械学習のプロジェクトとデータ基盤のプロジェクトが別になっておりデータ鮮度が異なる 3. 現状のデータ基盤アーキテクチャ 3.1. 本番環境のIaC化と開発環境の準備 まず取り掛かったのが本番環境のIaC化でした。 上記に示したアーキテクチャ図を書く前に本番環境の主要なリソースをTerraformにインポートしてコード管理できるようにしました。 その過程で不要なリソースを整理でき、本当に必要なものだけを見極めることができます。 おまけにコスト削減にも繋がります。 一通りTerraformへの書き起こしが完了したら、あとは開発環境のGoogle Cloudプロジェクトを作りTerraformを適用するだけです。 データに関しては1日1回、Data Transferでデータセットごとコピーしています。 開発環境に本番環境相当のデータとGoogle Cloudリソースが揃ったので、後に紹介するDataformを使った定期実行クエリの開発を増やしています。 これによって本番環境にて検証用テーブルができたり、間違えてテーブルを消してしまうなどの問題を減らせたと思います。 3.2. データロード系のツール刷新 データを取り込むツールとして trocco と Datastream を採用しました。 troccoはもともと別チームで管理しているものに相乗りさせてもらう形で使っています。 MAツールや他のクラウドサービスといった様々なデータソースに対応可能なため重宝しています。 またロードだけでなくReverse ETLにも役立っており、作ったデータマートを別サービスに読み込んで活用しています。 DatastreamはCDCのサービスでサーバレスなので運用に手間がかからない点でEmbulkの代わりに採用しました。 一方でリアルタイムにソースが変わるため集計のたびに数値が変化するため、問題発生時の原因調査が困難になりました。 現状運用上でカバーできていますが、再現性と説明の容易さを向上させるべく集計に使ったデータを別で持つべきか悩んでいるところです。 またスプレッドシート上で管理しているマスタデータにも対応すべくBigQueryの外部テーブルとして扱っています。 3.3dbtからDataformへの変更 データ変換のためのツールをdbtから Dataform へ変更しました。 dbtはDataformに比べて開発が活発で、ライブラリが充実しているため採用しました。 この前提でdbtにクエリや知識を集約させるべくBigQueryのユーザーを巻き込み利用を促していましたが、なかなかモデル(テーブル)の数が増えませんでした。 理由として2つのハードルがありました。 1つ目がBigQueryでクエリを記述後エディタを開き、dbt 用に書き足す一手間かかってしまうことが大きなハードルになっていること。 2つ目はdbt側の制約(主にモデル名の一意制約)やデータ基盤側の設計から定めたルールが気軽にコミットしづらい状況を作ってしまいました。 これらのハードルをクリアすべくDataformの利用を検討しました。 Dataformはブラウザで完結しBigQueryのメニューにあるため多少ツール間の移動コスト軽減されます。 かつDataformにはモデル名の一意制約がなくBigQueryと同様にデータセット間で被らなければ同名のモデルがプロジェクトに複数存在しても問題ありません。 導入した結果、モデル数はdbtプロジェクトに比べて3倍ほどできており、実際に使いやすいという声もあるので一定成功だったのかなと思っています。 Dataformからdbtへ乗り換えた話は見聞きしたことがありますが、dbtからDataformへのケースは見たことないので一定期間経ったらまた振り返りの記事を書こうと思います。 3.4. データを4層で管理 参考にしたのはdbtのベスプラの1つである「How we structure our dbt projects」です。 dbtをツールとしては不採用にしましたが、考え方は利用させてもらっています。 🙏 docs.getdbt.com 当初3層(lake/warehouse/mart)で作ろうとしていましたが、データソースに対して直接クエリしようとするとBigQuery上で不都合なことがありました。 例えばDatastreamで転送してきた日時のデータがすべてDATETIME型になってしまい、TimeZone を考慮した計算ができませんでした。 毎回TIMESTAMP型に変換する処理をwarehouse層に書かせるのも厳しいのでstaging層を設けて型変換などの簡単な変換をすることにしました。 4. 今後やりたいこと 4.1. 全体を統括するオーケストレーションツールの導入 現在、データ抽出と読み込みはtroccoやDatastreamで行われますが、Dataformによる変換はその読み込みが終わった頃を見計らって実行しています。 もしtroccoによるデータロードが失敗した際にDataformによる変換が実行されてしまうので、データを閲覧する方が古いデータを見てしまう可能性があります。 また現状troccoやDataformそれぞれでエラー検知の仕組みを備えており、日常業務の監視に一定コストがかかっています。 データの抽出から提供までの流れを効率的に管理・監視し、運用コストをかけずに行うためにもオーケストレーションツールの導入が今後必要です。 4.2. データ基盤の利用者拡大に向けたルールと権限 せっかく作ったのでもっと新しいデータ基盤を使ってもらいたいのですが、ルールがないとせっかくの設計が腐敗してしまいます。 例えばGASから直接クエリを発行することはSQLの内容がGASに閉じてしまいメンテができなくなってしまうので新環境では禁止していきたいと考えています。 4層のアーキテクチャも開発上意識しなくてはならないルールなので、なぜ必要なのか理由とともに作るつもりです。 また、適切な権限や公開範囲の設定も必要です。 どのチームがどの範囲のデータセットを扱うことができるか整理しないと予期せぬ変更をしてしまうなどの事故につながってしまいます。 皆が安心して使えるデータ基盤にするためにも適切な権限設定やルール作りが急務だと考えています。 4.3. 複数部門またいだデータ基盤の設計、構築 最後に壮大な話をして終わりたいですが、複数部門でのデータ基盤運用を今後やってみたいと考えています。 実は今まで説明してきたのは弊社の一事業部内での話で弊チームでは他事業部とはあまりまだ関われていない状況です。 エンジニア領域の事業をやっており事業部間のドメインは近いのでデータ文脈でコラボレートできることはあると考えています。 また事業部別で使われるマスタも数々存在しており共通化すると横断してデータ利用できる土壌が整うと考えています。 そのためには複数事業部のデータ基盤を管理するための設計、ルールと開発・運用を担当するデータエンジニアが圧倒的に足りていません。 5. 終わりに 以上がここ半年間で整いつつあるファインディのデータ基盤アーキテクチャと技術スタックの紹介でした。 やりたいことにも挙げましたが、データの攻守においてエンジニアが足りていない状況です。 エンジニアのためのデータプラットフォームを作るためにも、少しでも興味が湧いた方はカジュアル面談お待ちしております。🙏 herp.careers
こんにちは。 FindyでTech Leadをやらせてもらってる戸田です。 昨年(2023年)、 Findy Team+ にて、4名で3ヶ月ほどかけて大規模なフロントエンドの設計刷新を行いました。 Findy Team+はエンジニア組織のパフォーマンス向上を支援するSaaSサービスで、2020年から開発がスタートしました。 3年以上の間、機能開発を行ってサービスを伸ばしてきましたが、同時に様々な課題も生じていました。 今回はそこに至るまでの経緯と、実際に行ったことを紹介します。 なぜフロントエンドの設計刷新を決断したのか 当時、自分は他のプロダクトの開発チームでコードを書いていたのですが、ある日Findy Team+の開発チームへ異動することになりました。 異動後に2週間ほどFindy Team+のフロントエンドの開発をしたのですが、あることに気づきます。 コード設計が思ったより複雑かもしれない 異動前後で理解のしやすさやプルリクを上げるまでの時間に差があるように感じたので、Findy Team+での自分の生産性の数値を比較してみることにしました。 すると、異動前と比べて自分のアウトプットの量が半分以下まで下がっていることが明らかになりました。 感覚値と実際の生産性の数値が一致したため、どこかしらに何か問題があるのでは?という仮説を立てました。 異動前後での変化を洗い出してみた結果、コードの設計に問題がある高いことを突き止めました。 しかし、コードの設計を刷新しようにも、そこには大きなコストと時間が掛かります。 その大きなコストを、異動前後の生産性低下の感覚値だけで周りの人間を納得させることは不可能です。 そこで、今のコードの設計の問題点を洗い出して、何がどう問題で生産性が低いのか具体的な洗い出しに着手しました。 問題点の洗い出し 過度な共通化 まず全体的に過度な共通化が行われていました。 例を上げると、グラフやテーブルに数値を表示する際に表示するcomponent内で、データ取得も同時に行っていました。 こうなってしまった場合、グラフやテーブルの見た目は同じだけど表示するデータが異なる場合に対応できなくなります。 このような複数責任を持ったコンポーネントが幾つも存在していたため、コードリーディングやデータの流れを追うことが非常に困難になっていました。 データの取得と描画は責務が異なる処理なので分けて実装するべきでした。 処理に一貫性がない APIの呼び出しに関するルールが存在しておらず、複数個所から色々なタイミングで呼び出されており、データの流れを追うことが非常に困難になっていました。 前述した過度な共通化がこの問題を引き起こしており、1つのcomponent内で全てのことを処理しようとしていました。 データ取得と描画が密結合で実装されているので、この部分は共通化してるのでcomponent内でデータ取得して描画してるけど、この部分は共通化してないからデータをprops経由で貰ってきてる。といったような状況が多発していました。 これにより、どこからデータを取ってきているのか探しに行く作業が多発し、コードリーディングに必要以上の時間を取られているような状況でした。 テストコードを書きにくい 過度な共通化によりデータの取得と描画が同時に行われていたため、責務の分担がほとんどできていない状況でした。 そのため、テストコードを書きにくい状況にも陥っていました。 描画に専任するべきcomponentの中でデータ取得もしているせいで、データ取得部分のモックを用意しなければテストができず、テストコードが必要以上に肥大化していました。 設計刷新に対する認識合わせと合意形成 メンバーとの認識合わせ Tech LeadやCTOが「やってほしい」と言って作業してもらうことは比較的簡単ですが、自分たちで「やる」と決意してやることは価値が大きく違います。 ある程度の問題点を洗い出すことが出来たので、これを元にメンバーと意見交換をすることにしました。 この時メンバー全員を一同に集めて話すのではなく、メンバー1人ずつ時間を取って話をすることを決めました。 メンバー全員を一同に介してこの手の話をすると、声が大きいメンバーの意見が反映されがちだと考えたからです。 真に自分たちで「やる」と決意して貰いたかったので、1人ずつ時間を取って本音を聞くことにしました。 フロントエンドのメンバー全員と1on1で話を聞いてみた結果、現行の設計に対する意見と感覚値がほぼ一致していました。 ずっとリファクタを入れたかったけど、この規模まで来るとリファクタ自体に時間が掛かりすぎてしまう 機能追加に時間を取れなくなってしまうので、リファクタをやりたくても言い出せなかった 今の設計の状態のまま、更に開発スピードを上げていくのは難しい これから先の開発スピードを更に加速するためにも、フロントエンドの設計刷新は必要不可欠であるとチーム全体で結論が出ました。 経営陣との合意形成 そこで経営陣やPdMのメンバーと、設計刷新に対する合意形成を作りに行きました。 全体的に作り直す必要があるため、新規開発を可能な限りストップして、一定期間を作り直しに集中する必要があります。 これに関しては大きな反対意見が出ることもなく、比較的スムーズに了承を得ることが可能でした。 議論したのは、どのくらいの期間を新規開発ストップするかどうかくらいです。 なぜ大きな反対意見が出なかったかと言うと、 以前にも同様のシステムの設計刷新 を行ったことがあり、それに対する成功体験が大きかったためです。 確かに大きなコストは掛かりますが、比較的早い段階でそのコストを回収できたという成功体験があり、リファクタや設計刷新に対する抵抗感が比較的低い点は弊社の良い点です。 過去の成功体験と現在の状況を比較し、掛かるコストと回収期間を提示できたため、比較的スムーズに了承を得ることが可能になりました。 着手前の準備 新設計の方針を固める 新設計の基本方針として、多少冗長となっても構わないので共通化を最小限に留めることとしました。 最初から共通化して実装するのではなく、実装後に共通化するべきかどうかを議論し、その議論が通ったものだけ後から共通化対応することにしました。 また、コードの責務を明確にし、必要以上のことを1つのファイル内で実行しないことを徹底しました。 更にcomponentとロジックを分離することを基本とし、依存関係を単方向にさせました。 データ取得と描画の処理を明確に分け、描画に必要なデータは全てpropsリレーで受け取ることを義務付けました。 propsリレーが長くなるとツラくなる可能性もありますが、責務が混在してテストコードを書きづらくなることと比べたらマシという判断です。 小さな画面を新設計で1つだけ作り直してみる 新設計の方針がある程度見えてきたタイミングで、簡単な画面を1つだけ作り直して、メンバーに方針を展開することにしました。 方針を文字や口頭で説明するよりも、実際のコードを見てコメントベースで説明する方が理解しやすいからです。 そこから新設計に対する意見をメンバーから貰い、1ヶ月程度で方針が固まりました。 実際の作り直しの流れを決める 実際に本番環境が動いており、多数のクライアントが利用している状況だったので、次の3つを大原則に掲げました。 現状の機能を維持する 現状のスタイルを維持する 安全に移行する ページ単位で作り直しを進め、APIは既に利用しているものを使い回すことを決定しました。 作り直しの流れ 基本的な作り直しの流れは次の通りになります。 同じ画面を別URLで実装 既存画面のコードに手を加えるのは基本NG 一時的に同じ画面が異なるURLで公開される 既存画面と異なるコードで実装しているので、Pullrequestをガンガンmergeできる 新設計での実装が完了後、本番環境で動作確認を行う 動作確認がOKであれば旧設計のURLのルーティングを新設計の画面に向ける 新画面で何かしら不具合が発生した場合は、ルーティングを戻すことですぐに切り戻しが可能 一定期間様子を見て、問題なさそうなら旧実装のコードを全削除 この流れにより、旧実装の画面のことを気にすることなく新設計のPullrequestをmergeすることが可能になり、問題が発生しても切り戻しが容易になります。 振り返り 結果として新設計のコードへの移行完了後のチーム全体の生産性が、前年比で2.5倍程度まで上がりました。 作り直しやリファクタ、設計刷新を提案する前に、まず感覚値と実際の数値を見比べ、メンバーと認識合わせをすることが重要です。 また、経営陣を始めとした決裁権がある人間を納得させるために数字は必要不可欠です。 成功体験があれば次の提案は思った以上にスムーズに進みますが、一番最初の成功体験を作ることは非常に難しいものです。 小さくてもいいので数字を出し、小さな成功体験を多く詰むことが重要です。 まとめ いかがでしたでしょうか? リファクタや作り直し、設計刷新を検討している方の参考になれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから↓ herp.careers
こんにちは、ファインディで Findy Team+ (以下Team+)を開発しているEND( @aiandrox )です。 私が入社したのが2023年2月だったのですが、気がついたら1年間が過ぎていました。 せっかくなので、自分がこの1年でやったこと、感じたことを通してファインディの開発組織について知っていただけたらと思います。 1年でやったこと Team+の画面ベースで振り返る 入社から1年1ヶ月(2023/2/1~2024/2/29)のアウトプットについては以下のようになっています。 プルリク作成数:1229件(4.8件/日) コミットからオープンまでの平均時間:4.2h オープンからマージまでの平均時間:10.3h アウトプット量自体は、エンジニアの中では多めの部類だと思います。ただ、画像上部のアクティビティの推移を見るとわかる通り、とてもばらつきがあります。 開発の他にも下記業務を担当しているのと、外部連携サービスのAPI調査やQAなどのプルリクエストを伴わないタスクもあるためです。 問い合わせ対応 アラート調査 障害対応 リードタイムに関しては以下のようになっています。 外れ値の影響を受けていますが、それ以外の箇所では入社当初より現在の方がリードタイムが減少しています。現在は、開発に集中しているときのリードタイムはある程度安定するようになりました。 日頃から開発のパフォーマンスを上げるために意識したのは以下の点です。 事前に設計レビューやタスクを見てもらうようにする descriptionでタスクの流れを書いておく レビュー後のリードタイムを短縮する 事前に設計レビューやタスクを見てもらうようにする 設計に関しては、イシュー内で確認することもあれば、事前にDraftプルリクを作成してレビューしてもらったりします。 これによって、手戻りを減らすことができました。また、事前に見てもらうことでレビュアーの負荷を下げることもできました。 descriptionでタスクの流れを書いておく プルリクを細分化する関係上、descriptionを書く手間が増えます。レビュアーの負荷と自分の手間の間を取った結果、自分はよくこのフォーマットを使っています。 タスク1 ↓ タスク2 ←イマココ ↓ タスク3 レビュー後のリードタイムを短縮する 基本的には、ファインディのエンジニアはレビュー依頼からレビューまでが爆速です。しかし、入社当初は自分がレビューを受けてから再レビュー依頼をするまでに時間がかかっていました。そのため、レビューされたときに別のプルリクで作業をしていたとしても、レビューへの対応を優先するようにしました。 また、プルリクをすぐにマージする必要がなかったとしても、レビュアーのカレンダーの予定を見てレビュー依頼を個別でメンションするようにしました。 ファインディでは爆速レビューis正義の価値観があるので、圧はあまりない……はず。 プロジェクトベースで振り返る この1年で、主に以下のプロジェクトに関わりました。どれもTeam+の根幹の機能で、アーキテクチャの理解が深まりました。また、後半はプロジェクトのリードに挑戦できました。 プルリクのレビューロジックの変更 多言語化対応 のバックエンド全般とフロントエンド少し GitHub連携をOAuth AppからGitHub Appに移行 Bitbucket Cloud連携 のバックエンド 振り返ってみると、この1年は連携処理をメインで開発していたようです。 プロジェクトの中で、サービスに応じてどういうアーキテクチャにするかだとか、既存の設計だと無理がある箇所なども改修しつつ進められています。設計をどうするか考えるのは自分も好きなので、そういったことを任せていただき、壁打ちや相談させてもらえるのがとてもいい経験になりました。そして、すでに若干設計のつらみを感じています。これを次に活かすのだ……。 また、プロジェクトの進め方についても学びがありました。Team+では、大きめの開発は、PdMが企画を行う→エンジニアとすり合わせつつ仕様をまとめる→開発→QA→リリースという流れになっています。 そのため、調査段階からPdMと認識のすり合わせを行いつつ、開発着手後に出てきた懸念点などは適宜PdMに共有するようにしました。また、QAでも開発者QAとQAチームによるQAをどう担当していくかなどを調整するようにしました。結果として、それぞれのプロジェクトに反省点はあるものの、都度リカバリーできるような開発体制にはできました。 イベント参加 特に記憶に残っているのは以下のイベントです。今までは小規模のオフラインイベントに入ったことがあるものの、大規模なカンファレンスには参加したことがなかったです。 ファインディでは、エンジニア系イベントへのスポンサーや積極的に自社イベントを開催しているので、運営を手伝いつつ参加する機会やLTなど登壇させていただく機会を得やすいです。 RubyKaigi 2023 RubyKaigiはずっと気になっていたのですが、有給を取るのはハードルが高く、2023年に初めて参加しました。思っていたよりも技術的なハードルは低く、わからないとわかるの間を楽しめました。また、カンファレンス中のイベントも多く、たくさん交流ができたのが貴重な経験となりました。2024も行くので、出会った方はよろしくお願いします。 また、 After RubyKaigi で初めてのLTをしました。初参加のパッションでやりましたが、次回は技術的なことを試してみた、みたいなのをやりたいです。 開発生産性カンファレンス 2023年、ファインディでは2回の開発生産性カンファレンスを主催しました。私はTeam+を開発しているのもあり、ドメイン理解を深めるために参加しました。特に役割もなく、一参加者として楽しませていただきました。 dev-productivity-con.findy-code.io こちらのカンファレンスは、開発生産性に関する理論的なセッションが多かったです。書籍などでなんとなく頭にあることがつながったり、今まで友人のエンジニアに聞かれたことについての転換的な話もあり、「そういう考え方があるのか」と気付きを得たりしました。 特に、SLIを決めることで許容可能な不具合の量(エラーバジェット)が決まるので、それは通常の運用の障害ダウンタイムとして使ってもいいし、挑戦的な取り組みによってのダウンタイムとして使ってもいいという考え方が目から鱗でした。 findy.connpass.com こちらのイベントでは、具体的な取り組みを中心に聞きました。全社的に文化を根付かせるためにどうするか、といった啓蒙活動の取り組みが印象に残っています。 経営層・ビジネス部門への理解促進を促し、ステークホルダーを巻き込みつつ成果を出して価値を示すことを積み重ねていました。取り組みを泥臭くやっていくしかない中で、Team+は成果・価値を示すためのツールとして使われていることを感じました。 その他オフラインイベント ファインディ主催のイベントを中心に、さまざまなオフラインイベントに参加しました。ホームなので安心感があり、気軽に行きやすかったです。 オフラインイベントのいいところは、オンラインでは話しづらい内容を聞けることと後半の交流だと思っています。イベントを通して、いろんなエンジニアの方と話すことができました。その中では、Team+を使っているエンジニアの方もおり、生の声を聞けたのがよかったです。機能の要望だったり、Team+への感謝などをいただけて、日頃の開発のモチベーションになりました。 1年で変わったこと 組織の拡大 入社時は社員数も120人くらいでしたが、現在は200人を超えました。エンジニアも増えて、今年からTeam+のエンジニアは2チーム体制になりました。チーム編成としては、外部サービス連携に注力するチームとその他の機能を開発するチームです。 qiita.com また、Bizサイドの人数が増えていくに従って事業全体の勢いを感じています。メンバーがどんどん入社し、爆速オンボーディングですぐに立ち上がっていて本当に尊敬です。 そして、自分が作っているプロダクトの価値をたくさんの人に知ってもらえているのが純粋に嬉しいです。 組織の拡大に伴って課題も生まれた 単純に人数も増え、開発チームとしてできることも増えました。その中で、チームの構成や、プロジェクトの進め方については手探りの状態です。 現在、チームリーダーを中心に、いろんなやり方を試しつつよさそうなやり方を探っています。改善サイクルを回していきながら、その時々に適したチーム・開発体制で進めていけるようにしたいです。そのためにも、自分の視点からもたくさんアイデアを出していきたいです。 その他には、以下のような課題も出てきました。これは現在時間を取って対応しているところです。 Bizサイドの増加に伴い、エンジニアへのプロダクトに対する技術的な質問が増加 ドキュメントの不足 / 更新されてない 1年で変わらないこと 根本的な社風は変わっていないです。 前向き・誠実・チームワーク・スピード・No.1 のバリュー通り、自分自身がやりたいと言ったことはどんどんチャレンジさせてもらえています。 他のメンバーにサポートしていただきながら、GitHub App, Bitbucket連携をリードできた 自分主導で連携周りの設計の刷新やGitHub ActionsによるOps改善にチャレンジできた 「ISUCONに出てみたい」と1on1で言ってみたところ、社内の有志チームで出場できた( レポ記事 ) 今後の1年に向けて 基本的には、爆速開発しながらプロダクトを成長させるのが一番の目標です。そのためにも、自分自身も成長したいと思っています。 自分ができる幅を広げていきたい これは技術についてもそうだし、技術以外についてもです。ありがたいことに新しいことに挑戦することを歓迎されている組織なので、さまざまな挑戦をしていきたいです。技術的には、設計周りの引き出しを増やすこと、インフラやフロントエンドのタスクをもっとこなせるようになるのを目標にしています。 組織の拡大に伴って生まれてきた課題の解消もやりたい 開発生産性を高めるプロダクトを作っているからこそ、うちのチームは生産性が高いぞ!と胸を張って言える状態でいたいです。 他のメンバーはメインのプロジェクトを進めつつ課題解消の取り組みもしているので、自分もそんな風に動けるようになるのが目標です。現状は、プロジェクトがあるとそっちでいっぱいになっているのでさらなるレベルアップを目指します。 発信も頑張りたい 自分がやったことやそのときに考えたことを残しておきたい気持ちがあります。結果として、ファインディのことを知ってもらうことにもつながるので、三方Winにしたいです。 この記事もそうですが、テックブログを活用していろいろなことを発信していけたらいいなと思っています。なので、こんなことが気になるといったものがあればご意見いただけるとありがたいです。 最後に 現在、ファインディでは一緒に働くメンバーを募集中です! 興味を持った方は、ぜひカジュアル面談で話を聞きに来てください! 採用情報はこちら↓ herp.careers
FindyでEMをしている栁沢( @nipe0324a )です。 今回は、FindyのとあるRailsのCIのテスト実行時間を10分から5分に高速化した話をご紹介します。 「CIのテスト実行時間が遅い...」 「CIの実行時間を短くしたい!!」 と感じている方はぜひご覧くださいませ。 Findyでは2024年2月現在、1人あたり1日4プルリクを平均で作っています。静的解析や自動テストなどを即時に行うCI環境がないとスピード感のある開発ができなくなるため、CIを高速で回しタスクを完了させる必要があります。機能も増え、テストケースも拡充したことでCIの高速化が求められるようになりました。 また、個人的には、CIは遅くても10分、理想は5分以内で終わるのを1つの目安にしています。これぐらいのスピード感でCIが完了すると、「プルリク作ってレビュー依頼する」、「レビューコメントもらって対応する」といったことがサクサクできます! 1. CIテスト実行時間の高速化の結果 2. テスト実行時間の高速化の前提条件 3. 今回のテスト実行時間の高速化で実施したこと 3.1. 不要なカバレッジレポートの作成をなくす 3.2. テスト実行の並列度を高める 3.3. テスト実行時間の偏りを減らす 4. 最後にGitHub Actionsのコストについて 5. CIテスト実行時間の高速化のまとめ 1. CIテスト実行時間の高速化の結果 最初にテスト実行時間の高速化の結果を紹介します。 弊社では、ソースコードをGitHubで管理しているので、CIツールももれなくGitHub Actionsを使っています。 GitHub Actionsの「並列化の促進」や「テスト実行の偏り」を減らすことで、CIのテスト実行時間を約2分の1にしました。 対応前:約10分 対応後:約5分 また、費用対効果もよかったと考えています。 月間のGitHub Actionsのコストが2万円ぐらい増加 1ヶ月あたりのCI待ち時間が約7日分減る 2. テスト実行時間の高速化の前提条件 そもそも既存でも、CI上のテストは、「5台のマシン」かつ「1マシンあたり4コア」と20並列でテストを実行していました。 テストを20並列で実行するために、GitHub Actionsのワークフローで次のようなテクニックを使っていました。 5台の複数マシンでテスト実行 GitHub Actionsのmatrixを使い5台のマシンを動かす 対象のテストファイルを5台のマシンに分散させる簡易なshellスクリプトを使う 4コアでテスト実行 4コアのUbuntu Runnerを利用する(参考: より大きなランナーの概要 ) parallel_tests を使ってCPUコア数の並列度でテスト実行できるようにする このような対応をしてもプロジェクト規模の拡大とともにCIのテスト実行時間が遅くなってきたので、さらなる改善を実施しました。 3. 今回のテスト実行時間の高速化で実施したこと 今回のテスト実行時間の高速化にあたり、具体的には次の3つを実施しました。 不要なカバレッジレポートの作成をなくす テスト実行の並列度を高める テスト実行時間の偏りを減らす それぞれ効果があったのですが、「テスト実行時間の偏りを減らす」が他の対応との相乗効果をうみだし、テスト実行時間を大きく減らすことができました。 3.1. 不要なカバレッジレポートの作成をなくす 対応前のテストのワークフローを見ると、テスト実行後に「Post coverage report」というジョブでカバレッジレポートをプルリクにコメントしていました。 これは、自動テストを拡充するときに使われていたのですが、既にテストカバレッジは90%以上になっているためほぼ必要ないためリリースプルリク以外では実行しないようにしました。 これで、テストの実行時間が30秒ぐらい早くなりました。 3.2. テスト実行の並列度を高める 次に、マシン台数を5台から10台に変更することで、並列度を20から40と2倍に高めました。 マシン台数の増加は既存で仕組みが揃っていたので、変更は次のように実施できました。 # .github/workflows/test.yml strategy: fail-fast: false matrix: - ci_node_total: [5] - ci_node_index: [0, 1, 2, 3, 4] + ci_node_total: [10] + ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] steps: # 省略 - name: Run tests env: CI_NODE_TOTAL: ${{ matrix.ci_node_total }} CI_NODE_INDEX: ${{ matrix.ci_node_index }} run: | TEST_FILES="$(find ./spec -type f -name "*_spec.rb" | xargs ./scripts/ci/rspec_split_files.sh)" bundle exec parallel_rspec -- --format progress --color -- $TEST_FILES これでテスト実行時間が2-3分ほど早くなり、6-7分ぐらいになりました。 3.3. テスト実行時間の偏りを減らす 最後に、テスト実行時間の偏りを減らす取り組みをしました。 テストの並列度を2倍にしたのに、いまいちテスト実行時間が早くなりませんでした。そのため、どこがボトルネックになっていそうか調べてみると、テスト実行時間の偏りがボトルネックになっていそうでした。 以下の例ですと、「 Test (10, 8) 」が2m25sなのに比べて、「 Test (10,3) 」が5m30sとなっており、テスト実行時間の差が最大3分ほどあります。 さらに、詳細をみていくと、「マシンごとのテスト実行時間の偏り」と「マシン内のコアごとのテスト実行時間の偏り」の両方が発生していました。そのため、次の対応をしてテスト実行時間の偏りを減らしました。 マシンごとのテスト実行時間の偏りの対応 マシンへのテストファイルの振り分けをファイル名からテストファイルのサイズ順に変更 「ファイルサイズ ≒ テスト実行時間」と考えて、時間がかかるテストファイルを偏らないように変更 コアごとのテスト実行時間の偏りの対応 マシン内でコアごとにテストファイルが割り当てられて実行されていたので、時間がかかるテストファイルを割り当てられていたコアの実行時間がかかっていた ファイル単位からチャンク単位でテストを実行するために、 parallel_tests を parallel_split_test に置き換え(※parallel_testsと作者同じ) # .github/workflows/test.yml - name: Run tests env: CI_NODE_TOTAL: ${{ matrix.ci_node_total }} CI_NODE_INDEX: ${{ matrix.ci_node_index }} run: | - TEST_FILES="$(find ./spec -type f -name "*_spec.rb" | xargs ./scripts/ci/rspec_split_files.sh)" + TEST_FILES="$(find ./spec -type f -name "*_spec.rb" -exec ls -l {} + | sort -n -k 5 | awk '{print $9}' | xargs ./scripts/ci/rspec_split_files.sh)" echo $TEST_FILES - bundle exec parallel_rspec -- --format progress --color -- $TEST_FILES + bundle exec parallel_split_test $TEST_FILES --format progress --color これでマシンとコアのそれぞれでテスト実行時間の偏りが減少し、5分以内にテストが完了するようになりました。 4. 最後にGitHub Actionsのコストについて 並列度を2倍に増やしましたが、コストはそこまで高くなっていません。 GitHub Actionsの料金は「OS x vCPU数 x 分あたりの料金」で課金されます(参考: GitHub Actionsの課金について )。今回は、並列度を2倍に増やしましたが、Billable timeは30分前半から40分ぐらいと1.2〜1.3倍ぐらいなので、コストも1.2〜1.3倍ぐらいの増加になっています。 1ヶ月単位だと、「 ざっくり2万円ぐらいのコスト増加(※1)になりますが、CI待ち時間が7日分ぐらい削減(※2) 」できました。必ずしもCI待ち時間がムダではないですが、エンジニアの人件費を考えると費用対効果は高いのではと考えています。 ※1. 4coreの分あたりの料金 $0.016 x (変更後のBillable time 40分 - 変更前のBillable time30分) x 月間CIテスト実行回数 700回 x 為替150円 ※2. 待ち時間の削減時間 5分 x 月間CIテスト実行回数 700回 ÷ (60分 x 営業時間 8時間) 5. CIテスト実行時間の高速化のまとめ 最後にまとめです。 今回は、FindyのRailsプロジェクトで、CIのテスト実行時間を10分から5分と2分の1に高速化した話をご紹介しました。 具体的には、次のテクニックで高速化を実現しました。 不要なカバレッジレポートの作成をなくす テスト実行の並列度を高める テスト実行時間の偏りを減らす また、費用対効果もよかったと考えています。 月間のGitHub Actionsのコストが2万円ぐらい増加 1ヶ月あたりCI待ち時間が約7日分減る なにか、参考になる内容があれば嬉しいです。 最後に、弊社のエンジニアが次のようなスライドも公開しているので興味があればご覧くださいませ。 speakerdeck.com また、Findyは積極的にエンジニアを採用しています。CI/CDを始め、Four Keys、開発生産性、技術トレンド、転職市場など興味のある方は、お気軽にカジュアル面談を受けてみてください :) Findyの採用情報はこちら↓ herp.careers
こんにちは!Findy CTOの佐藤( @ma3tk )です。 本日からFindyでテックブログを始めることにしました。Findyは「挑戦するエンジニアのプラットフォームをつくる」というビジョンを掲げていますが、昨年様々な方とお話したり面談させていただく中で、Findyの開発組織の良さを伝えきれていないという課題に気づきました。 Findyの開発組織は、カジュアル面談などを通じて知っていただくと「とても面白い」と言っていただけるのですが、その面白さを事前にお伝えできていないことがありました。今回のテックブログスタートがその課題を解決するための一歩になればと思い開始しました。 初回は、大事にしていることと開発ポリシーの観点からFindyの開発組織の紹介をしたいと思います。 Findyの開発組織で一番大事にしていることは5つのバリュー Findyの開発組織は、次の5つのバリューを大事にしています。 Findyの5つのバリューは社内にいるメンバーが必ず意識するものになっています。 例えば、次のような形で意識しています。 前向き…クソコードと呼ばずに「伸びしろ」と呼ぶ。些細な言葉遣いでも前向きな言葉を選ぶことで組織全体の雰囲気を良くする 誠実…顧客に対しての向き合い方はもちろん、社内のメンバー間でのコミュニケーションもサービスに対しても誠実であり続ける チームワーク…個人の成果以上にチームで良い取り組みを行う。チームや職種の垣根を超えて協力し合うことを大事にする スピード…スタートアップだからこそスピード感を持って取り組む。技術にスピードは必要であり、技術の進化に常に追従し続ける No.1…No.2を目指してもNo.1にはなれない。常にNo.1を目指すことで、自分たちの成長を促進する もちろんこれ以外にも様々な観点で5つのバリューを体現することが大事です。 開発ポリシー バリューを体現するだけではなく、僕らFindyの開発組織としての技術に対する考え方もあります。 技術はモダンが当たり前 爆速顧客価値提供 エンジニアがターゲットユーザー 今までこの3つを大事にしながら開発を続けてきました。 ※今後組織の状況などに合わせて変わる可能性もあります。 1. 技術はモダンが当たり前 最近では多くのスタートアップがモダンな技術や環境を構築していることも珍しくはないですが、Findyもなるべく最新の技術に追従しながら開発を進めています。GitHub Copilot、TypeScript、Nx、Ruby on Rails、GraphQL、Terraformなど様々な技術を活用しています(執筆時現在)。 例えば各種ライブラリやフレームワークに関してはほぼすべてのプロダクトで最新バージョンを利用しています。一部最新バージョンに追従できないものは、ライブラリの最新バージョン対応ができていないなどの依存関係ですぐにアップデートが難しいためです。 ただ、多くの場合dependabotを活用し最新のバージョンにアップデートをすぐ実現できる状態にしています。これは、ユニットテストを充実化させ、プロジェクトによってはテストカバレッジ95%強、そしてカバレッジだけではなくテストの内容もバグが発生しにくいような意図を持った守れるテストになっているかどうかを確認しています。 また、CI/CDも整備しており、テストが通らないとマージできないようにしています。これにより、予期せぬバグやデグレなどを検知でき、リリース後のトラブルを大きく減らせています。守れるテストを書き続け、CI/CD環境を整備することで新しいアップデートがあってもテストで守り「これをマージしたらなにが起こるかわからない」という状況を減らす動きができています。 そのため、強気で「(アップデート内容を確認した上で)テストが通っていれば即マージ」ということができる環境になっています。 どんなプログラミング言語、フレームワーク、ライブラリを使うにせよ、最新のバージョンに追従することでセキュリティと開発効率の両方の観点でセキュアかつ高品質な状態を保てています。 2. 爆速顧客価値提供 モダンな技術を活用しているからこそ、僕らが提供する技術は常に爆速で、そして顧客に価値を届けるものであるべきだと考えています。 先ほど述べたように、Findyはテストカバレッジの高さとCI/CD環境が揃っている環境です。顧客に価値を提供してそれが万が一バグを含むものであったとしても、すぐに修正ができる状態です。また、ほぼすべてのプロダクトでフロントエンドとバックエンド両方で毎日リリース作業を行うため、リリース作業の自動化も行えるようにCI/CDを整備してきました。 そして新機能開発や機能改修などの振り返りにおいても、自分たちがFindy Team+を活用し、開発サイクル上の課題がある部分を特定しその問題を対処し解決することで、Findyの開発組織において効率の良い開発スタイルを継続できています。 Findyのプルリク数とリードタイムの変化 例えば2020年1月のFindyの開発組織においては、プルリクを作ってからマージするまでに3〜7日(70時間〜150時間)ほどかかっていましたが、2024年2月現在では、5.2時間と13.4〜28.8倍ほど高速化できています。 Findyの開発者数と一人あたりのプルリク作成数 また、一人あたりのプルリク量も、1日0.7件から4.7件と6.7倍ほど増加しています。開発人員も3.3人から26.6人と8倍の人数規模に増えました。トータルで1日2.8件ほどしか出ていなかったプルリク量も、1日129件と46倍に増加しています。 通常、人数が増えると生産性は低下傾向にあります。コミュニケーションコストが大きくなり、調整コストがかかるためです。しかし、Findyの開発組織は人が増えてもうまく回るようなオンボーディング施策や、コミュニケーションコストを下げるような施策も増やし、開発生産性を高め続けてきました。 その結果、新しい機能を追加するスピード、なにかが起こった時に切り戻すスピードが高い状態を実現でき、顧客価値を追求できるようになりました。また、それだけではなくGitHub Copilotもエンジニア希望者全員に貸与している状況であったり、なるべく開発生産性を高め、エンジニアであってもKPIやKGIなどの結果指標に貢献できるような動き方を常に模索し続けています。 3. エンジニアがターゲットユーザー Findyの開発組織は開発生産性が高い状態だからこそ、「どんな成果を出すべきなのか」を考えることができ、PdMとの連携が取りやすい状況になってきています。 我々Findyは「挑戦するエンジニアのプラットフォームをつくる」というビジョンの元、エンジニアが挑戦しやすい環境をつくり、多くのエンジニアの方にとって横で伴走できるような存在としてあり続けたいと思っています。 エンジニアに向けた事業展開をしているため、エンジニアである自分が欲しいものを生み出せる良さがあり、本当に欲しいものを提案したり議論しながら開発できる環境です。 さらに、プロダクトマネージャー、デザイナーと連携を取るだけではなく、営業メンバーにもフィードバックをしたり、逆にフィードバックしてもらえるいい環境です。営業メンバーもエンジニアのことを知れると対外のエンジニアユーザーに価値提供ができ、結果として自分の成果にも繋がります。エンジニアも単純に言われたものを作るのではなく、顧客が本当に欲しいものはなんなのかを知るようなユーザーインタビューに同席したり、社内の営業メンバーと連携をして顧客の解像度を上げることにもチャレンジしています。 Findyに関わる全てのメンバーがお互いにコミュニケーションを取り続けるメリットが生まれるため、エンジニアとしては真に届くサービス開発をできることが最大の魅力です。 Findyのこれからのエンジニアリングとは? Findyは高効率で常にCI/CD環境とユニットテストを充実させ続け、1人あたりの生産性も上げるような動き方をしてきました。直近でも、効率よく開発ができる環境を求めて入っていただいている方が何名もFindyにジョインしています。これからも人が増えてもずっと効率よく開発ができるように開発生産性を高め続けたくさんのアウトプットを出し、直接的に貢献が難しいKPIや売上などのアウトカムに貢献できる状態を作り挑戦し続けたいと思います。難しいことかもしれませんがそこに挑戦できる組織がFindyにはあります。 Findyは現在5つの事業を展開していますが、これからもさらに多くの事業を通じてエンジニアに価値を提供して、「挑戦するエンジニアのプラットフォームをつくる」ことを実現していきたいと思っています。今後の数年でエンジニア規模も2-3倍になり、新事業の立ち上げ、事業間連携、イネーブリングチームの組成、認証基盤やインフラ基盤の構築など会社・技術的に面白いフェーズに入っていきます。 これから一緒にみんなで最高の開発をしていきたいと思っていますので、興味のある方は是非ご連絡ください! Findyの採用情報はこちら↓ herp.careers おわりに 今回はFindyの開発組織の紹介をしました。 面談や面接、イベントなど含め様々な機会でお会いできることを楽しみにしています!