TECH PLAY

Findy/ファインディ

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

165

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 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の開発組織の紹介をしました。 面談や面接、イベントなど含め様々な機会でお会いできることを楽しみにしています!
アバター