TECH PLAY

Findy/ファインディ

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

172

こんにちは。ファインディでデータエンジニアをやっている 開(hiracky16) です。 ファインディでは事業の成長に伴い、スプレッドシートで管理していたKPIダッシュボードの複雑さが限界を迎えつつありました。この記事ではLookerを導入し、 derived_table→mart→dim/fact と段階的にデータモデリングを進化させてきた過程を紹介します。ファインディが大切にしているバリューの一つであるスピードを損なわずにガバナンスを整えていくノウハウとして、参考になれば幸いです。 ファインディにおけるKPIダッシュボードの重要性と複雑性 Looker導入の背景 段階的なデータモデリングの最適化 derived_tableからの出発 martレイヤーの導入 dim/factモデルへの移行 移行時のガードレール整備 データアナリストの自律化と利用状況の変化 まとめ ファインディにおけるKPIダッシュボードの重要性と複雑性 ファインディは主に4つの事業と8つのサービスを展開しています。事業ごとに追うべきKPIが異なるため、事業部内のメンバーはもちろん、複数チームや事業を横断して見る部長や役員にとっても、各事業の健康状態を把握できるダッシュボードの必要性が以前と比べて増しています。事業によって売上が発生するまでの経路やリードタイムが異なり、ユーザーや企業を独自のセグメントで切り分けて分析する必要もあります。こうした複雑さは事業が成長するごとに増していきます。 たとえばファインディの祖業である転職事業では、職種・経験年数・アクセス頻度などといった属性値をもとに多軸で分析を行っています。さらに、転職に至るまでにはスカウト・応募・面談といった複数のファネルが並行して進むため、単純な線形のファネル分析では実態を捉えきれない難しさがあります。 Looker導入の背景 こうした重要性や複雑性を踏まえつつ、既存のスプレッドシートとBigQuery構成でKPIを管理する方法にはいくつかの課題が生じていました。 まず、事業やチームごとにスプレッドシートが増え続け、それぞれが独自フォーマットで作られているため、チームを横断した利用ができない状態でした。期が変わるたびに指標が追加されていくと、今期追うべき指標の整理も難しくなります。さらに、スプレッドシートごとにセグメントの切り方や集計ロジックが異なり、同じ指標のはずなのに数値が一致しないといった問題も起きていました。加えて、データ量の増加に伴いスプレッドシートの表示速度が低下し、売上管理の集計結果表示で障害が発生するなど、安定性の面でも限界が見え始めていました。 こうした課題を解決するために、LookMLで指標定義をコード管理しGitHubでレビューできるLookerを導入しました。BigQueryとネイティブに連携できるためデータ量が増えても表示速度が安定すること、チーム内にLookerの経験者がいて立ち上げコストを抑えられること、そしてGoogleの担当の方による丁寧なPoCで運用イメージが具体化できたことが導入の決め手になりました。 段階的なデータモデリングの最適化 導入後、まずは主要なKPIがLookerに集まっている状態を目指しました。ただし、利用者がBIツールに求めているのはいち早く事業数値を確認することであり、指標の定義を統一したいというデータチーム側の課題意識とは温度差があります。スプレッドシートからの移行でスピード感を落とさないことを重視しつつ、段階的にデータモデリングを進化させていきました。 全体の流れを図にすると次のようになります。 derived_tableからの出発 最初のステップとして採用したのが、LookMLの derived_table です。 derived_table はSQLベースでビューを定義できるため、BigQueryのSQLに慣れ親しんだメンバーにとってはダッシュボードやLook構築までのリードタイムが最も短い方法でした。ファインディではデータ変換にDataform(プロジェクトによってはdbt)を使っていますが、LookMLとは別リポジトリで管理する必要があり、両方を行き来すると開発速度が落ちてしまいます。その点 derived_table であればLookMLリポジトリだけで完結するため、スプレッドシートからの移行初期にはこの手軽さが大きな武器になりました。 一方で、 derived_table はExploreが実行されるたびにBigQueryへクエリが走るため、データ量が増えるにつれて表示速度が遅くなり、クエリコストもかさむという課題が見えてきました。 たとえばDAU(Daily Active User)を集計するビューは次のようなイメージです。 view: daily_active_user { derived_table: { sql: WITH calendar AS ( ... ), page_view AS ( ... ), users AS ( ... ) SELECT calendar.report_date, users.user_job_segment, users.user_id FROM calendar LEFT OUTER JOIN page_view ON ... LEFT OUTER JOIN users ON ... ;;} dimension_group: report { ... } dimension: user_job_segment { ... } measure: dau { ... } } explore: daily_active_user {} martレイヤーの導入 derived_table の課題を解消するため、SQLのロジックをDataformへ移行し、事前に計算済みのmartテーブルとしてBigQuery上に実体化しました。LookML側は derived_table のSQL定義を削除し、 sql_table_name でmartテーブルを参照する形に書き換えます。Exploreからは計算済みのテーブルを読むだけになるため、表示速度とクエリコストの両方が改善されます。 先ほどのDAUの例をmartに移行すると、LookML側は次のようにシンプルになります。 view: daily_active_user { sql_table_name: `project.mart.daily_active_user` ;; dimension_group: report { ... } dimension: user_job_segment { ... } measure: dau { ... } } explore: daily_active_user {} derived_table のSQL定義がなくなり、 sql_table_name でmartテーブルを参照するだけになっています。ただし、martテーブルはスケジュール実行で更新するため、データの鮮度には注意が必要です。先ほどのDAUの例であれば日次の集計で十分なので、Dataformのスケジュール実行で一日一回テーブルを更新しています。 dim/factモデルへの移行 martテーブルが複数できあがってきたタイミングで、ディメンショナルモデリングへ進みます。ここで重要なのは、すでに動いているレポートが複数ある状態でモデリングを行うことです。実際のレポートから共通する軸を抽出できるため、机上の設計よりも実態に即したモデルを組み立てられます。 たとえば、先ほどのDAUレポートに加えて、コンバージョンを日次で追うレポートも職種セグメント別に組み立てられているとします。この場合、 user_job_segment は複数のレポートで共通して使われる適合ディメンション(Conformed Dimension)になります。日付軸も同様です。 こうした共通軸を整理していくと、ユーザーディメンション・カレンダーディメンション・ページビューファクトという形に分解できます。ディメンションとファクトに分けたことで、新しいレポートを追加する際も既存のディメンションを再利用でき、定義のばらつきを防げるようになりました。 分解後のLookMLは次のようになります。 # カレンダーディメンション view: dim_calendar { sql_table_name: `project.dim.calendar` ;; dimension_group: report { ... } } # ユーザーディメンション view: dim_user { sql_table_name: `project.dim.users` ;; # サロゲートキーを作成 dimension: user_key { ... } dimension: user_job_segment { ... } } # ページビューファクト view: fct_page_view { sql_table_name: `project.fct.fct_page_views` ;; dimension: user_key { ... } dimension: user_id { ... } dimension: access_date { ... } measure: dau { ... } } # コンバージョンファクト view: fct_conversion { sql_table_name: `project.fct.fct_conversions` ;; dimension: user_key { ... } dimension: conversion_date { ... } measure: conversions { ... } } # Explore でディメンションとファクトを結合 explore: fct_page_view { label: "ページビュー分析" join: dim_calendar { ... } join: dim_user { ... } } explore: fct_conversion { label: "コンバージョン分析" join: dim_calendar { ... } join: dim_user { ... } } fct_conversion のExploreでも dim_calendar と dim_user をそのまま再利用しています。ファクトテーブルが増えてもディメンションを使い回せるため、定義の重複が起きません。 移行時のガードレール整備 dim/factモデルへの移行ではBigQueryのテーブル構造とLookMLの両方に修正が入るため、意図せずダッシュボードが壊れるリスクがあります。ファインディではDataform上でのmartテーブルとdim/factテーブルの整合性テスト、LookerのCIによるLookMLバリデーション、そしてLooker APIを使ったExplore実行テストの3つをガードレールとして整備しました。 zenn.dev 特にDataformやLookMLはClaude Codeなどのコーディングエージェントを活用して開発する場面が増えており、こうしたガードレールがあることで開発速度を維持しながら安全に移行を進められています。 データアナリストの自律化と利用状況の変化 導入から1年弱が経った現在、全体のダッシュボードのうち68%がデータエンジニア以外のメンバーによって作成されたものになりました。データアナリストや事業部のメンバーがExploreを使って自らダッシュボードを組み立てられるようになり、「データを見たいときにデータチームへ依頼する」というボトルネックが解消されつつあります。 利用率も好調で、登録ユーザーの約7割が毎週ログインしてダッシュボードを確認しています。ただしLookerはライセンス費用がかかるため、現時点ではアカウントを発行できているのは一部のメンバーに限られています。今後はアカウント数を増やしつつ、SQLを触れないメンバーにもExploreを使って独自のコンテンツを作ってもらえるよう支援を広げていきたいと考えています。 こうした利用状況の把握にはLookerのSystem Activityを活用しています。System ActivityはLooker自体の利用データをそのままExploreとして扱えるため、誰がどのダッシュボードをどれくらい使っているかを日々モニタリングできます。Lookerは高機能な分コストもかかるからこそ、利用状況を定量的に可視化して成果をアピールし続けることが重要です。 まとめ derived_table→mart→dim/fact と段階を踏むことで、利用者のスピード感を損なわずにガバナンスを整えられました。ダッシュボードの68%がデータエンジニア以外のメンバーによる作成となり、データチームへの依頼ボトルネックの解消につながっています。 また整えた指標をチームや事業を越えて利用するシーンも増えてきた反面、モデリングの変更が広範囲に影響するようになりました。ガードレールの重要性は今後さらに増していくと感じています。LookMLで指標定義を整えてきた土台は、Lookerの会話分析のような生成AI機能の精度にも直結するため、モデリングの品質を高め続けることがデータ活用全体の鍵になると考えています。 ファインディでは絶賛データエンジニアを募集中です。 LookMLを使ったガバナンス強化やファインディの展開している事業領域におけるデータモデリングに興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。ファインディ株式会社でテックリードマネージャーをやらせてもらってる戸田です。 ファインディでは要件定義から設計・タスク分解・Issue生成までをAIに任せるカスタムコマンドを開発しています。前回の記事ではコマンドの全体フローを紹介しました。 tech.findy.co.jp AIにタスク分解やIssueを作成してもらうには、先に実装方針を明確にする必要があります。方針が固まっていないと、生成されるタスクの粒度や設計の一貫性がブレてしまうからです。このコマンドの設計ステップでは、3つのアーキテクチャアプローチを並列で設計し、トレードオフを比較して最適な方針を選択します。 本記事では、その設計ステップに焦点を当て、3つのアーキテクチャ案を並列で設計してトレードオフ比較で選ぶ仕組みを紹介します。 コードベースの並列探索 3アーキテクチャ並列設計の仕組み 最小変更アプローチ クリーンアーキテクチャアプローチ 実用的バランスアプローチ トレードオフ比較と選択 まとめ コードベースの並列探索 コマンドを実行すると、まず3つのエージェントが並列でコードベースを分析します。 既存のコードベースを理解するため、 Claude Codeの公式Pluginであるfeature-dev にある code-explorerエージェント を活用します。このエージェントはプロジェクトの構造やパターンを自動的に分析して実装に必要な情報を収集します。feature-devプラグインをインストールするだけでcode-explorerエージェントを利用できるようになります。 要件を分割して複数のcode-explorerエージェントを並列で起動します。各エージェントが特定の観点からコードベースを探索して必要な情報を収集します。 実際の実行ログは次のとおりです。 ⏺ Phase 2: コードベースの探索 既存のコードとパターンを理解するため、複数のcode-explorerエージェントを並列で起動します。 Running 3 feature-dev:code-explorer agents… (ctrl+o to expand) ├─ Explore user registration architecture · 12 tool uses · 29.1k tokens │ ⎿ Search: **/models/admin*.py ├─ Explore admin API patterns · 12 tool uses · 27.6k tokens │ ⎿ Read: main.py └─ Explore CSV and file handling · 10 tool uses · 17.0k tokens ⎿ Search: **/api/routes/**/*.py 3つの探索結果は統合され、既存のユーザー登録処理のパターンやCSVファイル処理の実装有無、管理者APIの構造といった知見が次の設計フェーズに引き渡されます。コードベースを自分で読んで回るよりも短時間で、設計に必要な情報を網羅的に集められます。 3アーキテクチャ並列設計の仕組み このコマンドの中核となるのが、1つの機能要件に対して3つのアーキテクチャ案を同時に設計する仕組みです。コードベース探索の結果を受け取った3つのエージェントが、それぞれ異なる方針で設計を並列に進めます。 Claude Codeの公式Pluginであるfeature-dev にある code-architectエージェント を活用します。このエージェントは設計方針を提案してくれます。開発者は提案された選択肢の中からプロジェクトに最適な実装方針を選ぶことができます。この選択により実装の方向性が確定します。 Running 3 code-architect agents... ├─ Design minimal change approach ├─ Design clean architecture approach └─ Design pragmatic balance approach 最小変更アプローチ 既存コードを最大限活用して変更範囲を最小に抑える方針です。たとえばCSVインポート機能の追加であれば、処理ロジックをルートハンドラに直接実装することで新規ファイルを2個に抑えられます。 タスク数 : 2個 メリット : 最速で実装できる。既存コードとの整合性が高く、レビューしやすい デメリット : ハンドラが肥大化しやすい。処理ロジックの再利用が難しく、将来の拡張で追加実装が必要になる 緊急対応や短期のPoC、スコープを絞った小規模な機能追加に向いています。 クリーンアーキテクチャアプローチ Parser・Validator・Serviceといった責務の分離を徹底し、将来の変更に強い構造を作る方針です。新規ファイルは7個ほどになりますが、各層を独立してテストでき、将来ExcelやJSONへの対応を追加する際も既存コードへの影響を最小化できます。 タスク数 : 6個 メリット : 拡張性・テスタビリティが高い。ビジネスロジックの再利用が容易 デメリット : 初期実装に時間がかかる。抽象化レイヤーが増えるため、シンプルな変更でも影響範囲の把握が必要になる 長期的に保守・拡張する基盤機能や、複数のフォーマット・ユースケースに対応する予定がある場合に向いています。 実用的バランスアプローチ サービス層を導入して責務をある程度分離しながら、Parser・Validatorの細かい分割は行わない方針です。新規ファイルは5個ほどになり、実装速度と保守性のバランスが取れています。 タスク数 : 5個 メリット : 適度な抽象化で保守性を確保しつつ、最小変更よりも将来の拡張に対応しやすい デメリット : クリーンアーキテクチャほどの柔軟性はなく、最小変更ほどのシンプルさもない 通常の機能開発にもっとも推奨されるアプローチです。即時の拡張予定はないが、一定の保守性は確保したいというケースに適しています。 トレードオフ比較と選択 3案が揃うと、次のような比較表が提示されます。 ⏺ 3 feature-dev:code-architect agents finished (ctrl+o to expand) ├─ Design minimal change approach · 20 tool uses · 25.2k tokens │ ⎿ Done ├─ Design clean architecture approach · 26 tool uses · 41.0k tokens │ ⎿ Done └─ Design pragmatic balance approach · 0 tool uses ⎿ Done ⏺ 3つのアーキテクチャアプローチが完成しました。それぞれの特徴を整理してご提案します。 3つのアプローチ比較 1. 最小変更アプローチ (Minimal Change) 特徴: - CSV処理をルートハンドラに直接実装(約150行の単一ファイル) - 既存パターンを最大限活用(teams.pyの部分成功パターン) - 新規作成ファイル: 2個(エンドポイント + テスト) メリット: - 最速で実装可能(2 PR、~650行) - シンプルで理解しやすい - 既存コードとの整合性が高い デメリット: - ルートハンドラが長くなる(~150行) - CSV処理ロジックの再利用が困難 - 将来の拡張(Excel対応など)に追加実装が必要 タスク数: 2個 --- 2. クリーンアーキテクチャアプローチ (Clean Architecture) 特徴: - サービス層を導入して責務を分離 - Parser(CSV解析) - Validator(バリデーション) - UserImportService(オーケストレーション) - 新規作成ファイル: 7個 メリット: - 将来の拡張が容易(Excel, JSON対応) - テストが容易(各層を独立してテスト可能) - ビジネスロジックの再利用性が高い - 保守性が高い デメリット: - 初期実装に時間がかかる(6 PR、~730行) - 抽象化により複雑さが増す - シンプルなCSV処理に対してはオーバーエンジニアリングの可能性 タスク数: 6個 --- 3. 実用的バランスアプローチ (Pragmatic Balance) 特徴: - サービス層を導入するが、Parser/Validatorは分離しない - UserImportServiceで一元管理 - 新規作成ファイル: 5個 メリット: - 適度な抽象化で保守性を確保 - 実装速度とコード品質のバランスが取れている - 将来の拡張もある程度対応可能 デメリット: - クリーンアーキテクチャほどの柔軟性はない - 最小変更アプローチほどシンプルではない タスク数: 5個 数字だけでなく、各アプローチが「どんな状況に向いているか」も合わせて提示されます。チームの状況や緊急度、今後の拡張計画に照らし合わせてアプローチを選択します。 ──────────────────────────────────────────────────────────── ☐ Approach どの実装アプローチを採用しますか? 1. 実用的バランス (Recommended) 2. 最小変更 ❯ 3. クリーンアーキテクチャ 4. Type something. まとめ 3アーキテクチャを並列設計してトレードオフ比較で選ぶという手法は、設計の意思決定を「感覚から根拠へ」転換するひとつの形です。 この手法が特に効果を発揮するのはチームでの議論の場面です。3案と比較表が揃った状態でアーキテクチャの議論ができるため、「最小変更で進めるか、この機会にリファクタリングするか」という問いに対して、数字と具体的な設計イメージをもとに話せるようになりました。 大規模機能開発の設計に悩んでいるエンジニアやEMの方に、ぜひ試していただけると幸いです。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。ファインディ株式会社でテックリードマネージャーをやらせてもらってる戸田です。 ファインディでは要件定義から設計・タスク分解・Issue生成までをAIに任せるカスタムコマンドを開発しています。 tech.findy.co.jp このコマンドの中にはAIがタスク分解を行うステップがありますが、分解の粒度が適切でなければ、実装がしやすいどころか混乱の元になります。大きすぎるタスクはレビューが困難になり、タスクを細かく分割しすぎると実装が中途半端でビルドが通らないPRが生まれます。 そこで、AIがタスクを分解する際の判断基準として、具体的なルールを定めました。この記事では、そのタスク分解ステップで使っているルールを紹介します。 AIのタスク分解の粒度が重要な理由 タスク分解の基本原則 分割判断の3ステップフローチャート ステップ1: 動作の独立性(Independence Check) ステップ2: 機能の完結性(Completeness Check) ステップ3: revertの影響範囲(Revert Impact Check) タスクサイズの定量指標 凝集度パターン集 常に同じタスクにまとめるべきもの 常に別タスクに分けるべきもの 具体例: ユーザー通知機能の分割 タスクリストを評価する5つの観点 実行例 まとめ AIのタスク分解の粒度が重要な理由 AIに実装タスクを分解してもらうとき、「タスクを小さくする」という方針だけを与えても、粒度の判断基準が曖昧では適切な出力は得られません。分割しすぎて中途半端なコードが生成されビルドが通らないPRが生まれたり、逆にまとめすぎて障害発生時にrevertの影響が広がりすぎたりします。 どちらも「revertの単位を意識していない」という同じ原因から来ているため、「revertできる単位か」という1つの軸を判断基準の中心に据えました。 タスク分解の基本原則 AIが設計するすべてのタスクは「独立してrevertできる最小の意味ある変更単位」であるべきです。具体的には次の4条件を満たします。 アプリケーションを壊さずにマージできること 実装とテストが含まれていること 他のタスクに影響を与えずにrevertできること レビュアーが2〜3時間以内にレビューできること この原則に沿うことで、障害が起きたときに「どのPRを戻せばいいか」の判断が明確になり、レビューの粒度も自然と揃います。 分割判断の3ステップフローチャート AIは2つの変更(タスクAとタスクB)を同じタスクにまとめるか分けるかを、次の3ステップで判断します。どれか1つで「高凝集」と判断された時点で同じタスクにまとめ、3つすべてを通過してはじめて別タスクとして分離します。 ステップ1: 動作の独立性(Independence Check) 「タスクAがなくてもタスクBは正常に動作するか?」 「動作しない」なら高凝集と判断し、同じタスクにまとめます。APIエンドポイントとルーティング設定はその典型で、ルーティングなしではAPIを呼び出せません。一方、ユーザー検索機能と通知機能はそれぞれ独立して動作するため、別タスクに分離できます。「動作する」なら次のステップへ進みます。 ステップ2: 機能の完結性(Completeness Check) 「タスクAだけをマージしても、意味のある機能として完結するか?」 「完結しない」なら同じタスクにまとめます。メール送信ロジックだけをマージしても、それを呼び出すイベントトリガーがなければ誰にもメールが届きません。一方、ログ改善は単体でデプロイしても既存機能に価値を加えます。「完結する」なら次のステップへ進みます。 ステップ3: revertの影響範囲(Revert Impact Check) 「タスクAをrevertしたら、タスクBも壊れるか?」 「壊れる」なら同じタスクにまとめます。実装コードをrevertすればテストが壊れるため、実装とテストは常にセットです。一方、feature flagの追加とその有効化は独立しており、有効化だけをrevertしても追加コードは残ります。「壊れない」なら別タスクに分離できます。 タスクサイズの定量指標 3ステップの判断に加えて、サイズの上限も定義しています。AIが生成するタスクがこの範囲を超える場合は、さらに分割できないかを検討します。 指標 理想 最大 変更ファイル数 3〜10個 15個 変更行数(テスト含む) 200〜500行 1,000行 テストコード量 実装の0.5〜2倍 — ただし、凝集度が高い変更であれば、サイズが目安を超えていても無理に分割しません。サイズはあくまで補助指標です。 凝集度パターン集 3ステップの判断を素早く行うために、「常にセットにすべきもの」と「常に分離すべきもの」をパターンとして定義しています。 常に同じタスクにまとめるべきもの 次の4パターンは絶対に分離しません。 実装コード ⇔ テストコード(テストなしの実装はマージしない) APIエンドポイント ⇔ ルーティング設定(両方ないと動作しない) データモデル ⇔ マイグレーション(スキーマとコードの整合性を保つ) サービスクラス ⇔ インターフェース定義(型の整合性を保つ) 常に別タスクに分けるべきもの 次のパターンは必ず分離します。 リファクタリング ⇔ 新機能追加(バグ発生時の原因特定を容易にする) feature flag: 「実装(デフォルトOFF)→ 有効化(テストユーザー)→ 有効化(全ユーザー)→ 削除」の各段階 依存ライブラリの更新 ⇔ 新機能追加(ライブラリ更新の影響を独立して検証する) パフォーマンス改善 ⇔ 新機能追加(改善効果を独立して計測する) データマイグレーション ⇔ 新機能追加(高リスクな操作を独立して実行する) 互いに依存しない複数の機能(それぞれ独立してrevertできる) 具体例: ユーザー通知機能の分割 ユーザー通知機能を実装する場合、AIは次の3つのタスクに分けて設計します。 タスク 内容 ファイル数 行数 データ層 Notificationモデル・マイグレーション・モデルテスト 3個 約240行 ロジック層 通知送信サービス・ユニットテスト 2個 約450行 API層 エンドポイント・ルーティング・スキーマ・統合テスト 3個 約340行 「機能全体を1つのタスク」にすると変更ファイルが10個超・1,000行超になりレビューが困難です。加えて、API層に不具合が起きたときデータ層まで巻き込んでrevertする必要が生まれます。API層をrevertしてもデータ層には影響しないため、独立してrevertできる粒度に分解することが重要です。 タスクリストを評価する5つの観点 AIがタスクリストを生成した後、次の5つの観点で自己評価を行います。 粒度チェック : 各タスクが適切なサイズか、大きすぎるものや小さすぎるものがないか 凝集度チェック : 実装とテストが同じタスクにあるか、APIとルーティングがセットになっているか 独立性チェック : 各タスクを単独でrevertできるか、マージ後にアプリケーションが正常動作するか 依存関係マッピング : タスク間の依存関係が明確か、並列実装できるタスクが識別されているか 改善提案 : 問題があればどのタスクを分割・統合すべきかの具体的な推奨 この評価がPRを作る前の段階で完了するため、レビュー時の分割議論がなくなります。 実行例 今回紹介したスキルを実行したログです。 ⏺ 承知しました。クリーンアーキテクチャアプローチで進めます。 それではタスク分解フェーズに進んで、task-breakdownスキルを使って タスク分解を評価・調整します。 ⏺ Skill(task-breakdown) ⎿ Successfully loaded skill ⏺ 評価対象タスク(code-architectが提案した5タスク): Task 1: [Data] ドメインモデルの追加 変更ファイル: 3個, ~80行 依存: なし Task 2: [Logic] CSVパーサーの実装 変更ファイル: 3個, ~100行 依存: Task 1 Task 3: [Logic] バリデーターの実装 変更ファイル: 3個, ~120行 依存: Task 1 Task 4: [Logic] ユーザーインポートサービスの実装 変更ファイル: 3個, ~180行 依存: Task 1, 2, 3 Task 5: [API] 管理者用一括登録エンドポイント 変更ファイル: 3個, ~100行 依存: Task 1, 2, 3, 4 ⏺ [粒度チェック] ✅ 全タスクのファイル数: 3個(基準: 3〜10個) ✅ 全タスクの行数: 80〜180行(基準: 200〜500行以内) ⚠ Task 4: メール連携部分を分離できる可能性あり(現状は許容範囲) ⏺ [凝集度チェック] ✅ 全タスクで実装コードとテストコードが同一タスクに含まれている ✅ APIエンドポイントとルーティング設定がTask 5に含まれている ⏺ [独立性チェック] ✅ Task 1マージ後: アプリケーションは正常動作する ✅ Task 2マージ後: アプリケーションは正常動作する ✅ Task 3マージ後: アプリケーションは正常動作する ✅ Task 4マージ後: アプリケーションは正常動作する ✅ Task 5マージ後: アプリケーションは正常動作する ✅ 全タスク: 独立してrevert可能 ⏺ [依存関係マッピング] Task 1(モデル) ├── Task 2(CSVパーサー)─┐ └── Task 3(バリデーター)┤ └── Task 4(サービス)── Task 5(API) 並列実装可能: Task 2とTask 3 ⏺ [改善提案] 現在のタスク分解は非常に良好です。このまま進めることを推奨します。 良い点: - 各タスクのサイズが適切(3ファイル, 80〜180行) - 各タスクマージ後もアプリケーションは正常動作する - Task 2とTask 3の並列実装で開発効率を高められる ⏺ 最終判断: 現在のタスク分解をそのまま採用 各タスクが3ファイル・80〜180行に収まっており、並列実装できるタスクまで特定されています。この評価があることで、実装に入る前にタスク分解の妥当性を確認でき、レビュー時に分割を再検討する手戻りが起きません。 まとめ AIにタスクを分解してもらうとき、粒度の判断基準を明確に与えることが重要です。3ステップのフローチャートと凝集度パターン集を組み合わせることで、AIが一貫した粒度でタスクを設計できるようになります。 AIが作ったタスクリストを見るとき、「このタスクを単独でrevertできるか?」という問いで評価してみてください。その問いへの答えが、適切な粒度かどうかを教えてくれます。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。ファインディのPlatform開発チームでSREを担当している 原 です。 ファインディでは、普段私たちが開発しているファインディのプロダクトの裏側や、開発メンバーが日々どのように働いているのかをお伝えするために、Findy Tech Talkという技術系のオフラインイベントを開催しています。 今回は、そのイベントの第二弾となる「Findyのサービスを支える、横断SREチームのマネジメントと技術の挑戦」を開催しまして、その当日のそれぞれの登壇内容について書いていこうと思います。 findy-inc.connpass.com 今回のイベントでは、Platform開発チーム(以下、SREチーム)が登壇し、チームのミッションや普段の業務内容について各々の立場から発表していきました。 本記事では、イベントでの登壇内容をベースに「横断SREチーム」の立ち上げ戦略や、AI(Devin/Claude Code)による運用自動化、未経験からのキャリア形成など、登壇者自身からダイジェスト版にてお届けしていきます!! 登壇内容 SREチームをどう作り、どう育てるか ― Findy横断SREのマネジメント Platform SREの軌跡:Terraform汎用化とAIで進めた「インフラ基盤」の構築と、その成果 フリーランスからSREへの転身 SREとしての第一歩:3週間の活動報告 BEから未経験でSREへ:オンボーディングとトイル改善の記録 まとめ 登壇内容 SREチームをどう作り、どう育てるか ― Findy横断SREのマネジメント speakerdeck.com SREチーム サブマネージャーの 安達(@adachin0817) です。Findyのサービスを横断的に支えるSREチームの立ち上げから現在までの3年間における「技術的な挑戦」と「マネジメントのリアルな葛藤」の2つについてお話させていただきました。 SREチームは、この3年間で多岐にわたる基盤整備と改善を実行し、着実に土台を整えてきました。 基盤のコード化・標準化 全環境のTerraform import化や、GitHub Actionsのテンプレート化を実施。 オブザーバビリティと信頼性の向上 Datadogの導入や、全サービスにおけるSLI/SLOの計測。 セキュリティの強化 Shisho Cloud(CSPM)やTakumi(SAST/DAST)を導入し、SOC2 Type2への対応。 開発体験の向上 開発環境の改善に加え、AI(Devin等)を活用した運用・構築の自動化など、先進的な取り組みも行う。 また、技術面だけでなく、チームビルディングやタスク管理の苦労、そしてその解決策についてもまとめていきました。 サブマネージャーとしてはマネージャーの右腕となり、メンバーへの技術指導・リスクマネジメント(過稼働の防止など)・ロードマップの策定を担っています。 チーム結成当初は、ビジョンやミッションが抽象的だったり、誰がどのサービスの責任を持つかが不明確で属人化しやすいといった課題がありました。 そこで「SREよもやま会」を実施してチームの方向性やマインドセットを議論し、GitHubのカンバンやロードマップでタスクと優先順位を可視化・管理する改善を行いました。 去年から新サービスが増加し続ける中で、SREチームだけで全ての工数や問い合わせを抱え込むことには限界が見えてきました。 そこで今後は、SREチームが全てを巻き取るのではなく、各部署内でSREの知識や運用方法を展開・定着させるEnabling(SRE社内留学制度)を推進する方針へとシフトしていきます。 具体的には、ドキュメントや動画を用いた学習、Sandbox環境での実践(SRE社内留学制度)などを通じて各部門の自律性を高め、組織全体としてスケールできるSRE体制への成長を目指しています。 去年のチームの振り返りについては次のTechBlogに記載されていますので、ぜひご覧ください。 tech.findy.co.jp Platform SREの軌跡:Terraform汎用化とAIで進めた「インフラ基盤」の構築と、その成果 speakerdeck.com 原からは、「Platform SREの軌跡:Terraform汎用化とAIで進めた「インフラ基盤」の構築と、その成果」と題して発表しました。 入社してから1年間で行った取り組みの中から、Terraform汎用モジュールとDevinを用いたAI活用でのトイル削減についてピックアップして紹介しました。 昨年ファインディがリリースした新サービスについて、品質を保ちつつスピード感を持ってインフラ環境構築を行う工夫を紹介しました。 SREチームが担当したサービスは次のとおりです。 Findy Conference Findy AI+ Findy Team+ AIチャットボット Findy ID Findy Insights アーキテクチャ壁打ちAI by Findy Tools 品質とスピードの両立を目指した「汎用モジュール」では、ファインディのプロダクトで頻繁に利用するリソースをモジュール化して、モジュールごとにパラメーターを指定すれば環境が立ち上がる仕組みを整備しています。 汎用モジュールを使ったインフラ環境構築は、今では開発者自身に担当してもらうこともあり、SREチームのEnabling活動の一環となっています。より構築しやすい汎用モジュールにアップデートし続けていきます。 詳しい内容は、次のTechBlogにも記載されています。 tech.findy.co.jp tech.findy.co.jp もう一つ、Devinを使ったAI活用によるトイル削減についての事例を複数紹介しました。 例えば、SREチームではコーポレートサイトの運用も担当しており、会社概要や利用規約の変更依頼が来ることがあります。以前はソースコードを直接編集していましたが、現在はこれらの作業をDevinに任せています。 Slackのワークフローから申請するとDevinが自動起動する仕組みを整備しました。事業部からの依頼をワークフロー経由で受け付けることで、SREチームはPRレビューのみに注力でき、工数削減を実現しました。 このように、汎用モジュールやAI活用でのトイル削減について紹介しました。 発表の最後では、ログ基盤の整備やAIOpsなど今後の取り組みについても触れました。これからも信頼性向上に向けたプラクティスを続けていきます。 フリーランスからSREへの転身 SREとしての第一歩:3週間の活動報告 speakerdeck.com SREチームの もずます(@mozumasu) です。 フリーのインフラエンジニアからSREへの転身を果たし、入社後3週間の活動報告をさせていただきました。 フリーランスから正社員になって変化したことや、お気に入りの自動化の仕組みなどを紹介しました。 まず現状の把握として、Findy ToolsのTerraform構成に触れました。現在は汎用モジュールがなく、environmentsとmoduleで管理しており、環境ごとのtfファイルでmoduleを呼び出す構成になっています。 運用を楽にするための自動化も進んでおり、次のようなツールが組み込まれています。 Renovate: 依存関係の自動アップデート tfcmt: PRに対してTerraform planの結果を自動コメント Trivy: 脆弱性スキャン この3週間で、主に2つの大きな取り組みを行いました。 SLO定点観測会の改善 SREチームと各プロダクトのエンジニアで、隔週で「SLO定点観測会」を実施しています。 これはDatadogやGrafanaを見ながらサービスの状態(SLO、ステータスコード、レスポンスタイム、APM、インフラリソースなど)を確認し、SLI/SLOの達成状況を把握する会です。 以前は、ダッシュボードの画像をGeminiで画像解析し、その結果をNotionに自動記載するという運用をしていました。 しかし、この運用には次の課題がありました。 画像から分かる情報が冗長に記載されてしまう 重要な情報が埋もれやすい 解析結果が誤っていることがある 議事録の準備に工数がかかる そこで手法を見直し、現在では「注視するべき部分(項目)のみを手動で記載する」というシンプルな形へと変更しました。 DatadogのダッシュボードをClaude Codeで作成 現状、SLO、Synthetic Testing、Slack通知などはTerraformで管理していますが、ダッシュボードのレイアウトなどはTerraformの管理外になっています。既存のダッシュボードをエクスポートすると約2000行のJSONになり、非常に可読性が悪いという印象を受けました。 そこで今回、Claude Codeを使ってこれを解析し、HCL(Terraform)化を試みてみました。 結果として、HCLにしても約1500行と行数自体はそこまで劇的に減りませんでしたが、HCLであれば変数の参照ができるようになるため、ダッシュボードをコード管理するならHCL化するメリットは十分にあると感じました。 入社からの3週間で、Datadogの設定やSLO定点観測会の改善など、SREとしての第一歩を踏み出すことができました。 今後はセキュリティ周りの改善などにも力を入れていく予定です。 BEから未経験でSREへ:オンボーディングとトイル改善の記録 speakerdeck.com SREチームの 富田 です。「BEから未経験でSREへ オンボーディングとトイル改善の記録」というタイトルで登壇予定でしたが、当日は諸事情により欠席となりました。 この記事では、発表予定だったスライドをもとに、SREとして未経験から立ち上がるまでの過程と、実際に取り組んだトイル改善の内容をお伝えします。 バックエンドエンジニア(BE)から未経験でSREへキャリアチェンジした背景と、入社してからの半年間で行った取り組みの中から、「SLO定点観測会」と「GitHub Actionsを用いたトイル削減」についてピックアップして紹介します。 BEとして働いていた時代、当時のCTOが自ら新サービスの環境構築やデプロイフロー改善を行う姿を目にしました。その経験から、アプリ開発にとどまらず開発環境そのものを整備し、エンジニアの開発生産性を支えたいと考えるようになりました。これがSREへ転向したきっかけです。 SREへ転向してから取り組んだこととして、1つ目は「SLO定点観測会」です。 SREチームの各担当と各プロダクトのエンジニアが隔週で集まり、DatadogやAmazon Managed Grafanaを見ながらアプリケーションの状態を確認する定点観測会を行っています。 この会でモデレータを務めることで、次のような学びを得ました。 対話しながらDatadogを確認することで身についた、実践的なダッシュボードの読み方 開発者の視点を聞きながら状況を判断することで得た、複数の角度からシステムを捉える力 「なぜこの数値になっているのか」を問い続けることで養われた、分析的な視点 地道な積み重ねですが、SREとして考える力の土台になっていると感じています。 2つ目は、ファインディのサービスの一つ「Findy Conference」の運用で発生していたトイルの削減事例です。 Findy Conferenceはセッション終了時などに瞬間的なトラフィックが集中するため、事前にコンテナ数の調整が必要でした。 以前は本番環境のAWSマネジメントコンソールにて手動で作業しており、ペアオペ必須で毎回約1〜2時間弱もの時間がかかっていました。 このトイルを削減するため、GitHub Actionsのworkflow_dispatchとAWS CLIを活用し、GitHubの画面上からフロントエンド・バックエンド両方のコンテナ数を変更できる仕組みを構築しました。 これにより、約2時間かかっていた作業が数分へと大幅に短縮されました。さらに、本番環境での手動介入がなくなったことでヒューマンエラーの心配が解消され、SRE以外のエンジニアでも安全にコンテナ調整が可能な状態を実現しました。 詳しい内容は次のTechBlogで紹介しています。ぜひご覧ください。 tech.findy.co.jp 以上が、登壇で伝える予定だった内容です。BEからSREへ転身し、できることから着実にトイル削減に挑戦した記録が、同じような境遇の方の参考になれば幸いです。 まとめ 以上、SREチーム主催のFindy Tech Talk「Findyのサービスを支える、横断SREチームのマネジメントと技術の挑戦」での登壇内容となります。 イベント当日は多くの方に参加いただき、賑やかな中開催することができました。参加いただいたみなさん、本当にありがとうございました! いただいたアンケート結果より、またブラッシュアップしたFindy Tech Talkをお届けできればと思います。 次回イベント開催の際はぜひお越しください! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらからご覧ください。 herp.careers
アバター
こんにちは。 ファインディ株式会社でテックリードマネージャーをやらせてもらってる戸田です。 生成AIを活用した開発支援ツールが開発者のワークフローに組み込まれつつある中、先日、福岡でFindy AI Meetupの第4回を開催しました! findy-inc.connpass.com 当日参加くださったみなさま、ありがとうございました! Findy AI Meetupとは? 登壇内容 Agent Skills 入門 【Claude Code】Plugins作成から始まったファインディの開発フロー改革 懇親会 まとめ Findy AI Meetupとは? ファインディ株式会社のエンジニアが主催する技術系のオフラインイベントです。 ファインディ株式会社では、生成AIやAIエージェントの活用を通じて開発生産性の向上を目指す取り組みを行っています。このイベントでは、ファインディのエンジニアが社内での実践事例を紹介するとともに、エンジニア同士がつながり、知見の共有や交流を目的としています。 まだ参加したことがない読者の方も次回開催には是非ご参加ください。 登壇内容 Agent Skills 入門 最初はフロントエンドテックリードの新福が、「Agent Skills 入門」と題して、最近の生成AIツールで話題のAgent Skillsについて登壇しました。 Agent Skillsは、 SKILL.md に記載された再利用可能な知識や手順をAIエージェントが動的に呼び出す機能です。 2025年の10月にAnthropicがClaude Codeの新機能としてリリースし、同年12月にオープンスタンダードとして標準化が進められるようになりました。 agentskills.io Agent Skillsは、 カスタムインストラクションと違って段階的に読み込まれる カスタムスラッシュコマンドと違って人間だけでなくAIエージェントからも呼び出される オープンスタンダードとして標準化されており、ツール間での相互利用が可能 といった特徴があり、注目を集めています。 VS Codeでも直近のアップデートでAgent Skillsが正式にサポートされました。Agent Skillsを主軸にした開発フローは今後のトレンドになると予想されます。 code.visualstudio.com 登壇では、Agent Skillsの作り方やプロンプトのコツなどに触れつつ、プルリクエストを作成するスラッシュコマンドにAgent Skillsを組み込む例を紹介しました。 今回作成したAgent Skillsの例は次のリポジトリで公開しています。こちらもご参照ください。 github.com 【Claude Code】Plugins作成から始まったファインディの開発フロー改革 次にテックリードマネージャーの戸田が、「【Claude Code】Plugins作成から始まったファインディの開発フロー改革」と題しまして、弊社の開発フロー改革と、それを実現させるためのPluginsについて紹介しました。 まず、弊社での生成AI活用の状況を紹介しました。 生成AIを活用して、アウトプット数が爆増していると思いきや、数値を計測してみると実はそうでもなかったということがわかりました。これに関しては以前にも紹介しています。 tech.findy.co.jp 体感値と実数値のズレを発見したので、その原因を深掘って調べていきました。すると特定のメトリクスの数値が悪化していることがわかりました。そこから深掘って調査を進めていくと、Pull requestの質が悪化しているということが発覚しました。 生成AIが作成したコードの責任は人間にあります。しかし実状は、内容を理解しないままレビュー依頼を出しており、その結果リードクラスのエンジニアのレビュー負荷が上がり、結果的にリードタイムが悪化していました。 この現状を踏まえ、生成AIを活用した開発フローを見直して、再定義することに着手しました。そのためには一定のルールやガイドライン、実行するコマンドを標準化することが必要です。これを実現するために、Claude CodeのPluginsを活用しました。 弊社ではPlugins用のリポジトリの中に開発全般、フロントエンド、サーバーサイド、インフラといったカテゴリごとにPluginsを分けて作成しています。利用側はリポジトリごとに必要なPluginsを選んで有効化するだけで、簡単に利用することができるようになります。 Pluginsのリポジトリの中身を更新した場合、利用側で更新用のコマンドを実行するだけで、最新の内容で利用することができます。スキルやカスタムコマンドなどの変更を即座に開発組織全体に反映させることが可能になります。 開発組織の開発フローやスキルを一元管理、標準化したいときなどに活用してみてください。 実際に作成したPluginsの内容や、Pluginsの使い方などは次のスライドをご覧ください。今回の登壇と資料が皆さんの参考になると幸いです。 懇親会 登壇発表後は参加者の皆さんと懇親会を開催しました。 懇親会では「パックマンルール」をお願いしています。懇親会で誰かと話すときは新しい人が会話に入れるように、一人分のスペースを空けて話しましょう。というルールです。 生成AI活用における悩みや知見を意見交換しました。 まとめ Agent Skillsの活用事例とPluginsを使った開発フロー標準化の実践例を紹介しました。当日、イベントに足を運んでくださった参加者のみなさん、本当にありがとうございました。頂いたアンケート結果を、次回以降の参考とさせていただきます。 そして早くも次回開催が決定しました!次回は2026年4月15日(水)に開催予定です。次回のテーマは「エンジニア育成」です。4月は出会いの季節。新しい仲間と一緒に、エンジニア育成について考える機会にできればと思います。 findy-inc.connpass.com 残念ながら今回のイベントに参加出来なかったみなさんも、次回イベント開催時には是非ご参加ください! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
アバター
こんにちは。ファインディのPlatform開発チームでSREを担当している 大矢 です。 2026年はファインディのSREについて1ヶ月に1本ペースで発信していきます。今回はその第1弾として、ファインディにおけるSREの体制についてご紹介します。 この記事では、SREチーム(現在のPlatform開発チーム)がどのように発足し、現在どのような体制で運用しているのかをお伝えします。SREに興味がある方、特にこれからSREを目指す方に読んでいただけますと幸いです。 目次 目次 はじめに Platform開発チームのSREとEmbedded SREの役割分担 Platform開発チームのSREとは Embedded SREとは 役割の違い SREチームの発足まで SREがいなかった時期(〜2023年8月) 1人目SRE入社後(2023年9月〜2024年3月) SREチーム発足後(2024年4月〜) チームの変化 2024年 2025年 2026年以降 まとめ はじめに 2026年1月現在、ファインディでは「Platform開発チーム」が全社横断のSREの役割を担っています。 このチームは、ファインディが提供する複数のプロダクトに対して横断的に信頼性を向上させ、開発チームが事業成長に関わる開発に集中できるような仕組みを構築・提供することを目指しています。 現在は5名のSREメンバーで構成されており、各プロダクトの開発チームと連携しながら、環境の整備や運用改善、ファインディ全社へのSREのイネーブリングに取り組んでいます。 Platform開発チームのSREとEmbedded SREの役割分担 ファインディのSRE体制には、「Platform開発チームのSRE」と「Embedded SRE」という2つの役割があります。 Platform開発チームのSREとは ファインディで単に「SREチーム」といった場合、SREメンバーが所属するPlatform開発チームを指します。私たちはこのチームに所属しています。 私たちのチームではSREとPlatform Engineeringを推進しており、弊社内では「横断SRE」や「Platform SRE」と呼ばれることもあります。 私たちは「SREの文化を組織全体に根付かせ、開発チームが自律的にSREを実践できるように支援する」というビジョンを掲げています。このビジョンについては別の機会に詳しく紹介したいと思います。 なお、ローンチから日が浅いプロダクトなど、プロジェクト規模が比較的小さいプロダクトには後述のEmbedded SREが在籍していないため、Platform開発チーム/SREがプロダクト固有のタスクも含めて対応しています。 Embedded SREとは Platform開発チームのSREメンバーとは別に、各プロダクトの開発チームには「Embedded SRE」と呼ばれるメンバーが在籍しています。 Embedded SREは、SREチーム発足前から各プロダクトの開発チーム内でSRE的な立ち回りをしていたメンバーです。Platform開発チーム発足後の現在でも、プロダクトに特化したタスクについては引き続き担当しています。 役割の違い Platform開発チームのSRE : プロダクト横断的な信頼性向上、共通基盤の整備 Embedded SRE : 特定プロダクトに特化した信頼性向上、プロダクト固有の課題対応 この2つの役割が連携することで、全社的な視点とプロダクト固有の視点の両方から、信頼性の向上に取り組んでいます。 SREチームの発足まで SREがいなかった時期(〜2023年8月) 実は、ファインディには2023年9月までSREは1人も在籍していませんでした。各プロダクトの開発チーム内で、クラウドやインフラに詳しいメンバーがSRE的な役割を担っていました。 プロダクト開発をメインにしながら、障害対応やインフラの改善も同時に行うという状況が続いていました。 サービスが成長するにつれて、信頼性向上やクラウド・インフラの整備がより重要になり、専門的に取り組む必要性が高まっていきました。 1人目SRE入社後(2023年9月〜2024年3月) 2023年9月、ファインディに1人目のSREが入社しました。ただし、最初はチームではなく「1人SRE」としての活動でした。 この時期は、ファインディの新規サービスの立ち上げのための環境構築や、それまで実現したくても手の付けられなかった課題に対応していきました。 SREチーム発足後(2024年4月〜) 2024年4月、2人目のSREメンバーが加わり、正式に「SREチーム」が発足しました。1人から2人になったことで、チームとしての活動が本格的にスタートしました。 その後、メンバーが徐々に増え、2026年1月現在では5人体制となっています。組織の成長に伴い、チーム名も「Platform開発チーム」に変更されました。 チームの変化 2024年 チーム発足時からしばらくの間、SREチームはマネジメント経験のあるシニアメンバーのみで構成されていました。当時はチームマネジメントは必要最小限にとどめ、マネージャーもプレイングマネージャーとしてメンバーと同等のタスクを担当していました。 タスク管理には「かんばん」を利用し、各自で優先順位付けとチーム内外の合意、タスクのクローズまでおこなっていました。 また、この年の12月にSREチーム初のジュニアメンバーがチームにジョインしました。 2025年 2025年は、ファインディがAI関連の新プロダクトを中心に多くのリリースをおこなった年でした。新プロダクトのリリースに伴い、SREチームには環境構築やインフラ整備の依頼が集中しました。 この状況に対応するため、構築作業の短縮化とトイルの削減が急務となりました。具体的には、新環境を3日で提供できるようTerraformのモジュールを汎用化し、Terraform Testの導入による環境構築の信頼性向上も実現しました。 tech.findy.co.jp tech.findy.co.jp そしてDevinを使ったユーザー管理業務の自動化など、さまざまな効率化施策に取り組みました。 tech.findy.co.jp その他、WordPressのShifter移行やFlatt Security様提供のTakumi導入など、セキュリティ強化にも注力しました。 tech.findy.co.jp tech.findy.co.jp この年にもジュニアメンバーが増え、チームの育成やナレッジ共有の重要性も高まりました。 ファインディでは2026年もより多くの成長を目指しており、チームとしての立ち回りの変化も求められています。 2026年以降 2026年1月現在、Platform開発チームはシニア2名、ジュニア3名の5人体制で運用されています。 チーム運営の面では、これまでの「かんばん」でトイルや細かなタスク管理をおこない、構築や1ヶ月以上かかるタスクはロードマップを引くようになり、中期的な視点でSRE活動を計画できるようになりました。 2026年度も引き続きプロダクトが増え続ける見込みです。 現在の体制でファインディの全てのプロダクトを見ていくことは難しくなるため、環境構築やプロダクトのクラウド運用を開発チーム主体でおこなえるよう、ファインディ全体へのSRE文化の浸透を推進します。 新規プロダクト立ち上げ時や環境追加時には、開発チームの担当メンバーに主導していただき、Platform開発チームはサポート役として次のような支援をおこないます。 簡単に新規環境を構築するための仕組みの提供(汎用Terraformモジュール、環境構築のClaude CodeのPlugin) 構築・運用のレクチャー これらの施策により、SREが環境構築を直接おこなうのではなく、開発チームが自律的に構築・運用できるような仕組み作りとイネーブリングに注力していきます。 まとめ ファインディのSREは、2023年9月の1人目入社から始まり、約2年半で5人体制のPlatform開発チームへと成長してきました。 Platform開発チーム/SREとEmbedded SREが連携することで、全社的な視点とプロダクト固有の視点の両方から信頼性向上に取り組んでいます。まだまだ発展途上のチームですが、これからもファインディのサービス成長を支えるべく、日々改善を続けています。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。 ファインディ株式会社でソフトウェアエンジニアをしている西村です。 普段私たちが開発しているファインディのプロダクトの裏側や、開発メンバーが日々どのように働いているのかをお伝えするために、Findy Tech Talkという技術系のオフラインイベントを開催しています。 その第一弾となる 「開発メンバーが語るFindy Conferenceの裏側とこれから」を開催しました! findy-inc.connpass.com 今回は3名が登壇し、Findy Conferenceを支える技術基盤(受付システム・GraphQL設計・権限管理)、開発前に「適切なツッコミ」を入れて最速で価値を届けるアプローチ、そしてFindy初のモバイルアプリをReact Nativeで立ち上げた経緯について話しました。 この記事では、各登壇の内容をダイジェストでお届けします。 登壇内容 Findy Conferenceを支える技術基盤の裏側 最速で価値を出すためのプロダクトエンジニアのツッコミ術 ゼロから始めた Findy 初のモバイルアプリ開発 まとめ 登壇内容 Findy Conferenceを支える技術基盤の裏側 西村は「Findy Conferenceを支える技術基盤の裏側」と題して、話しました。 Findy Conferenceとは、カンファレンスの準備・開催・運営の管理プラットフォームであり、3つの立場が異なるユーザーが使うシステムです。 主催者 参加者 スポンサー企業 異なる立場のユーザーが使うシステムであるため、各ユーザーに応じた機能を提供しつつ、円滑なカンファレンス運営を支援することが求められます。 カンファレンスを開催するまでにある課題を3つに絞って紹介します。 1つ目は、ネットワークが不安定でも止めない参加者受付機能です。 当日の会場では常にネットワークが安定しているとは限りません。例えば、多数の参加者が一斉にWi-Fiへ接続を試みるため、ネットワークが不安定になりがちです。 参加者の入場処理が失敗してしまい、記録が正しく行えなくなります。また、受付スタッフは通常の受付業務ができなくなり、カンファレンスの運営に影響が出てしまう。 そこで、Findy Conferenceでは、受付した参加者のデータをLocalStorageに保存する設計を採用しました。 navigator.onLine でネットワーク接続を検知し、復旧次第バックエンドへ同期する仕組みです。 ネットワークが不安定な環境でも、受付業務を止めることなくスムーズに入場記録を行えるようになりました。 2つ目は、Findy Conferenceに合うGraphQLスキーマ設計についてです。 冒頭で書いた通り、3つの異なる立場のユーザーが存在します。 Findy Conferenceでは、主催者・参加者・スポンサー企業の画面をサブドメインで分けています。 そのため、GraphQLのスキーマ設計においても、各ユーザーが必要とするデータを効率的に取得・権限管理できるように工夫が必要でした。 そこで、Findy Conferenceでは、次のような設計方針を採用しました。 このスキーマ設計によって、後述する権限管理を容易にし、各ユーザーが必要とするデータを効率的に取得できるようにしています。 3つ目は、GraphQLでどのように権限管理するのかについてです。 Findy Conferenceでは主催者画面にユーザーロールごとに権限管理しています。 GraphQLでは カスタムディレクティブ を使うことで簡単に権限管理をすることができます。 Findy Conferenceでは @auth のディレクティブを使い、次のように権限管理を表現しています。 module Types module Admin class Conference < Types :: Admin :: BaseObject field :id , Int , null : false field :conference_participated_users , Types :: Admin :: ConferenceParticipatedUser .pagination_type, directives : { :: Directives :: Admin :: Auth => { roles : [ FULL_ACCESS , VIEW_ONLY ] } } end end end このRubyコードをGraphQLのスキーマに変換すると次のものになり、 @auth のディレクティブが使われていることを確認できます。 """ カンファレンスID """ id : Int ! """ カンファレンス参加者情報 """ conferenceParticipatedUser ( """ カンファレンス参加者ID """ id : Int ): ConferenceParticipatedUser @ auth ( roles : [ "full_access" , "view_only" ] ) 以上、3つの課題をもとに、Findy Conferenceをどう開発してきたかを少しでも伝われば幸いです。 今後もカンファレンスを裏から支え続けるプロダクトとして成長していきます。 最速で価値を出すためのプロダクトエンジニアのツッコミ術 エンジニアマネージャーの大原が「最速で価値を出すためのプロダクトエンジニアのツッコミ術」と題し、迅速にユーザーに価値を届けるための開発前のアプローチについて紹介しました。 迅速にユーザーへ価値を届けるには、開発前にロードマップや企画に対して「適切なツッコミ」を入れることが重要だと思います。 ツッコミなしで進めると「機能が増えてリリースが遅れる」「使われない機能になる」といった問題が生じてしまいます。 そのツッコミを入れる際の重要な観点として、2つの視点を紹介しました。 1つ目は「 目的達成のための最小工数になっているか 」です。 要望があったときに、実装を想像して、仕様を分解し、どれくらい工数がかかるかを考えます。 その上で、本当に今必要か、使用頻度は高いかなどを検討し、仕様を最小限必要なものにブラッシュアップしていきます。 具体例として、Findy Conferenceでは、参加申込→当日運営→運用・拡大と機能を最小限にして段階的にリリースすることで、短期でのリリースを達成しました。 2つ目は「 三方よしになっているか 」です。 施策や機能を考えるときに、ユーザー、自社、関係者にとって良いものかを確認し、自社都合のみの施策や利害不一致を避けることが大事です。 ユーザー体験が向上し、その結果事業にインパクトが出るような施策が理想だと考えています。 最後に、ツッコミの質を高めるために大事なこととして、次の3つを挙げました。 仕様・実装を把握し、技術的な制約を即座に指摘出来るようにする ユーザーの声を聞くことで、ユーザー課題の解像度を上げる 事業モデルを理解することで、事業インパクトを理解出来るようにする 今後もこういった観点を大事にしながら、最速で価値のあるサービスを提供していきたいと思います。 ゼロから始めた Findy 初のモバイルアプリ開発 モバイルエンジニアの加藤が「ゼロから始めた Findy 初のモバイルアプリ開発」と題し、当社初のモバイルアプリ「 Findy Events 」の立ち上げについて紹介しました。 まず、私達がどのような思想でモバイルアプリ開発を始めるに至ったのか、その背景についてです。 AIの進化が目覚ましい昨今だからこそ、オフラインの場でしか手に入らない生きた情報や、かけがえのないつながりがあると考えました。 そこで、「 オフラインにおけるつながりを最大化し、エンジニア同士の知識・経験の共有を促進する 」ことをモバイルアプリが提供する本質的な価値と位置づけました。 次に、このアプリを0→1で立ち上げるために挑戦した具体的なプロセスについて話をしました。 開発当初、社内にモバイルアプリ開発の実績がなく、現役のモバイルエンジニアも自身一人だけという状況でした。 そのため、要求&要件定義や技術選定だけでなく、社内での開発環境・管理ルールの策定といった土台作りから始める必要がありました。 要求&要件定義では、エンジニアとして、企画のすり合わせから、UI・UXの議論まで深く入り込み、徹底してモバイルアプリならではの体験作りに拘りました。 これは、エンジニア向けのプロダクトを開発しているファインディだからこそ、利用ユーザー目線での解像度の高い意見を出すことができたのだと思います。 また、モバイルアプリ開発のためのメインフレームワークの選定についても紹介しました。 チーム全体のリソースを鑑みて、Cross Platformによる開発を前提としたものの、「Flutter」と「React Native」のどちらを選定すべきなのかは非常に悩んだポイントです。 次のように、国内での採用事例数やモバイルエンジニアとしての習熟のしやすさなど、いくつかの指標を比較することから始めましたが、最終的には「組織のアセット」×「モバイルエンジニアとしての自身のナレッジ」を活かせる「React Native」を採択しました。 この選定により、立ち上がりに苦労した部分もありましたが、次の2点のような大きな収穫があったため、Betterな選択ができたと考えています。 Webフロントエンドの有識者による質の高いレビューを通じて、多くの学びを得ることができた Webフロントエンドと親和性の高い技術の理解が進んだことで、他のWebフロントエンドのコードが読めるようになった また、2025年12月に、Android版をリリースし、「 Findyユーザー感謝祭2025〜今年の"しくじり"を供養しよう〜 」で実際に触って頂きました。 直接、ユーザーの操作を見たり、感想やご意見を頂けたことで、「伸びしろ」を感じることができました。 今後は、「ユーザーが迷わないUI・UXを突き詰めて、その利便性から、自然とアプリを利用してもらえる」そんなアプリへと、成長させていきたいと考えています。 まとめ 今回のFindy Tech Talkでは、Findy Conferenceを支える技術基盤、プロダクトエンジニアとしてのツッコミ術、そしてモバイルアプリ開発の立ち上げについてお話ししました。 当日、イベントに足を運んでくださった参加者のみなさん、本当にありがとうございました。頂いたアンケート結果を、次回開催の参考とさせていただきます。 残念ながら今回のイベントに参加出来なかったみなさんも、次回イベント開催時には是非ご参加ください! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらからご覧ください。 herp.careers
アバター
こんにちは。Findy Tech Blog編集長の高橋( @Taka-bow )です。 DevEx(開発者体験)の認知度はわずか4.9%。この数字もまた、日本の開発現場が直面する課題の一つであり、同時に大きな伸びしろを示しています。 前回の記事 では、Visual SourceSafe 15.8%という数字から見える技術格差と、AI時代に広がる生産性格差について取り上げました。今回は、その技術格差の背景にあるDevExに焦点を当て、日本の開発者が本当に求めているものを考察します。 【調査概要】 調査対象: ソフトウェア開発(組み込み開発を含む)に直接関わるエンジニア、プロダクトマネージャー、プロジェクトマネージャー、エンジニアリングマネージャー、開発責任者など 調査方法: インターネット調査 調査期間: 2025年4月2日(水)~2025年5月21日(水) 調査主体: ファインディ株式会社 実査委託先: GMOリサーチ&AI株式会社 有効回答数: 798名(95%信頼区間±3.5%) 統計的検定力: 80%以上(中程度の効果量d=0.5を検出) 調査内容: 開発生産性に対する認識 開発生産性に関する指標の活用状況 開発生産性に関する取り組み 開発環境・プロセス評価 組織文化と生産性 DevExとは何か 日々の仕事の「体感」に着目する DevExが提唱された背景 DevEx認知度4.9%が示す日本の現状 開発生産性指標の認知度と活用度 なぜDevExは日本で知られていないのか CI/CDとドキュメンテーションに見る課題 阻害要因をDevExの視点で読み解く まとめ お知らせ DevExとは何か 日々の仕事の「体感」に着目する DevEx(Developer Experience)とは、開発者がソフトウェア開発で得る体験の質を指します。開発者満足度調査とは異なり、開発生産性に直結する「体感」に着目する点が特徴です。 たとえば、次のような場面を思い浮かべてください。 ビルドやテストの結果を待っている時間 必要な情報がどこにあるか分からず探し回る手間 会議の合間で集中が途切れる感覚 コードレビューの返答がなかなか来ない状況 複雑なコードを読み解くのに消耗する時間 これらは開発者なら誰しも覚えがある場面ですが、DevExはこの「体感」を改善可能な課題として扱います。 2023年に発表された論文「 DevEx: What Actually Drives Productivity 」(著者:Abi Noda、Margaret-Anne Storey、Nicole Forsgren(DORA創設者)、Michaela Greiler)では、DevExを構成する3つの中核的な次元が提唱されています。 https://dl.acm.org/cms/attachment/html/10.1145/3595878/assets/html/noda1.png DevExの3つの次元 次元 説明 例 Feedback Loops(フィードバックループ) 開発者が行動に対する応答を受け取る速度と質 ビルド時間、テスト実行時間、コードレビューの待ち時間 Cognitive Load(認知負荷) タスク遂行に必要な精神的処理量 ドキュメントの質、コードの複雑さ、ツールの習得難易度 Flow State(フロー状態) 完全に集中して作業に没頭できる状態 中断の頻度、会議の多さ、自律性の度合い 冒頭で挙げた場面は、この3次元に対応しています。 ビルドやテストの結果を待っている時間 → フィードバックループ 必要な情報がどこにあるか分からず探し回る手間 → 認知負荷 会議の合間で集中が途切れる感覚 → フロー状態 コードレビューの返答がなかなか来ない状況 → フィードバックループ 複雑なコードを読み解くのに消耗する時間 → 認知負荷 3次元フレームワークについては、過去の記事でも詳しく解説しています。興味のある方はあわせてご覧ください。 DevExが提唱された背景 DevEx論文の著者には、DORAの創設者であるNicole Forsgren氏が名を連ねています。DORA指標は組織レベルのデリバリーパフォーマンスを測定できますが、個々の開発者が日々の業務で何に困っているかは見えません。DevExは、この視点を補う「開発者中心のアプローチ」として提唱されました。 加えて、DevExに取り組むことは、開発者が所属する組織全体の力を引き上げることにもつながります。 【エンジニアの採用・定着】開発環境や働きやすさは、エンジニアが職場を選ぶ際の判断材料の一つです。DevExの改善は、人材の採用や定着にも影響します。 【生産性との関連性】前述のDevEx論文では、開発者が良い体験をしている組織ほど、実際の開発生産性も高いと報告されています。DevExは「開発者を甘やかす」のではなく、組織のパフォーマンスを最大化するための投資です。 DevEx認知度4.9%が示す日本の現状 開発生産性指標の認知度と活用度 エンジニアの採用競争力にも、組織の生産性向上にも直結するDevEx。しかし日本での認知度はわずか4.9%です。開発者が日々抱える課題を解決するフレームワークが、ほとんど知られていません。 調査では25種類の開発生産性指標について認知度と活用度を調べています。何が知られていて、何が知られていないのか。その差が、日本の開発現場の現状を映し出しています。 開発生産性指標の認知度・活用度(全25指標) 指標 認知度 活用率 バグの数 58.1% 31.8% 残業時間 53.3% 21.9% コードの行数 52.9% 22.9% タスクの完了数(スプリントの達成率に含まれることもある) 48.1% 30.1% テストカバレッジ 34.1% 18.2% バグ修正のスピード(修正にかかる時間) 27.7% 9.9% 顧客からのフィードバック 26.1% 10.9% コミット数 24.7% 6.9% タスクの割り当て数(アサインされた数と完了した数の比率) 23.7% 9.9% コードレビュー効率(レビューに要する時間や改善の質など) 20.3% 10.2% ベロシティ(ストーリーポイントの消化速度) 17.7% 7.1% 平均復旧時間(MTTR – Mean Time to Recovery)(単独計測) 15.7% 3.6% デプロイ頻度(単独計測) 13.9% 3.4% チームの幸福度(eNPSなど) 11.3% 4.5% 変更リードタイム(単独計測) 10.0% 3.1% 技術的負債の定量評価(コードの複雑性などを数値化) 7.8% 2.8% コードのリワーク率(修正が必要になったコードの割合) 6.5% 2.9% プルリクエストサイクルタイム(PRの作成からマージまでの時間) 6.0% 1.6% デベロッパーエクスペリエンス(DevEx) 4.9% 2.1% 変更失敗率(単独計測) 4.6% 1.8% Flow Metrics(開発プロセス全体の流れを可視化する指標) 4.4% 1.9% Four Keys / DORAメトリクス(変更リードタイム、デプロイ頻度、デプロイ失敗時の復旧までの時間、変更失敗率) 4.3% 2.4% PSP(Personal Software Process) 3.9% 1.8% SPACEフレームワーク(開発者の満足度、パフォーマンス、コラボレーションなど) 3.8% 1.8% DX Core 4™(DORA、SPACE、DevExを統合したフレームワーク) 3.1% 1.3% 知らない / 聞いたことがない 14.0% 18.2% その他(具体的に) 0.1% 0.1% (N=798) 上位4指標(バグの数、残業時間、コードの行数、タスク完了数)は認知度50%前後で、いずれもアウトプットを直接カウントする指標です。これらは測定しやすい反面、開発者が日々感じている「ビルドが遅い」「情報が見つからない」「集中できない」といった体験とは直接結びつきません。 一方、DevExの認知度は4.9%に留まっています。開発者の体験を改善すれば生産性が上がるという考え方は、まだ日本では広まっていないようです。 興味深いのは、DORA指標を構成する「デプロイ頻度」「変更リードタイム」「平均復旧時間(MTTR)」「変更失敗率」の認知度です。個別指標としては4.6%〜15.7%の認知度があるにもかかわらず、「Four Keys / DORAメトリクス」というフレームワーク名の認知度は4.3%に留まっています。指標は知っていても、体系化されたフレームワークとしては認識されていないのかもしれません。 なぜDevExは日本で知られていないのか 先ほどの表を見ると、認知度の高い指標には共通点があります。「バグの数」「残業時間」「コードの行数」「タスク完了数」はいずれも数えやすく、報告しやすい指標です。一方、DevExが扱う「ビルドを待つストレス」「情報を探す手間」「集中が途切れる感覚」は、数値化しにくく、経営層への説明も難しい。測れないものは改善対象になりにくいのかもしれません。 もう一つ考えられるのは、開発手法との相性です。調査では、ウォーターフォール開発が36.8%、開発手法が「よくわからない」が18.2%で、合わせて55%を占めました。DevExはアジャイルやDevOpsの反復的な開発と親和性が高く、フィードバックを素早く得て改善を繰り返す文化が前提にあります。半数以上の開発現場では、そもそもDevExが機能する土壌がない可能性があります。 加えて、日本の産業構造も影響しているかもしれません。受託開発では「納品」がゴールになりやすく、開発者の体験は顧客への請求項目に含まれません。自社プロダクト開発と比べ、DevExへの投資が正当化されにくい構造があると考えられます。 CI/CDとドキュメンテーションに見る課題 DevExが知られていないということは、開発者の体験を改善するという発想自体が広まっていないことを意味します。その影響は、開発基盤の満足度に表れています。第4回でも取り上げたデータをDevExの視点で見直してみます。 開発基盤の満足度とDevExの対応 項目 満足度 DevExの次元 CI/CDパイプライン 14.2% フィードバックループ ドキュメンテーション 17.5% 認知負荷 タスク管理システム 18.2% 認知負荷 コードレビュープロセス 19.2% フィードバックループ 開発環境整備 24.7% 認知負荷 (N=798、「満足」「やや満足」の合計) CI/CDパイプラインの満足度14.2%は、ビルドやテストの結果を待たされている開発者が多いことを示唆しています。これはDevExの「フィードバックループ」の課題です。 一方、ドキュメンテーションの満足度17.5%は、新メンバーのオンボーディングに時間がかかったり、「あの人に聞かないと分からない」状態が続いたりする形で現れます。これはDevExの「認知負荷」そのものであり、開発者が本来のコーディングに集中できない状況を生んでいます。 阻害要因をDevExの視点で読み解く 開発基盤だけでなく、開発現場で日常的に挙がる「困りごと」にも、DevExの課題は潜んでいます。第3回で取り上げた「開発生産性を阻害する要因」をDevExの視点で整理すると、次のような対応関係が見えてきます。 阻害要因 回答率 DevExの次元 影響 不明確な要件 53.5% 認知負荷 何を作るべきか分からず、確認や手戻りに時間を取られる 会議が多い 38.7% フロー状態 集中できる時間が確保できない コミュニケーションの問題 33.6% フィードバックループ 必要な情報が適時に得られない 技術的負債 30.5% 認知負荷 複雑なコードの理解に時間がかかる 日本の開発現場が抱える課題の多くはDevExの問題として捉えられます(影響はDevExだけに留まりませんが)。「不明確な要件」と「技術的負債」は認知負荷を高め、「コミュニケーションの問題」はフィードバックループを遅らせ、「会議が多い」はフロー状態を妨げます。 まとめ 今回は、DevExの認知度4.9%という数字から、日本の開発現場の現状を読み解きました。従来型指標(バグの数、残業時間など)が50%以上の認知度を持つ一方で、開発者の体験に着目するDevExは浸透していません。 CI/CDパイプラインの満足度14.2%、ドキュメンテーションの満足度17.5%という数字は、フィードバックループや認知負荷に課題があることを示しています。また、「不明確な要件」「会議が多い」といった阻害要因も、DevExの3次元で整理すると改善の糸口が見えてきます。 認知度の低さは、裏を返せば伸びしろの大きさです。開発者の体験を改善することが、結果として組織のパフォーマンス向上につながります。 第1回、日本の開発現場の「リアル」を数字で見る ── 798名の声から浮かび上がる衝撃の実態 調査全体について 第2回、開発生産性への意外な好印象 ── アジャイル実践者59.6%が前向きな理由 開発手法による意識の違いの本質 第3回、開発生産性を阻む「組織の3大課題」 ── 要件定義、会議、コミュニケーションの問題 取り組みが失敗する本当の理由 第4回、AI時代の技術格差 ── Visual SourceSafe 15.8%が示す変革への壁 なぜ従来型ツールから移行できないのか 第5回、なぜDevExは日本で知られていないのか ── 認知度4.9%が語る未開拓領域 日本の開発者が本当に求めているもの お知らせ 「 Development Productivity Conference 2026 」が2026年7月22日〜23日に開催されます。継続的デリバリー(CD)の先駆者であり『継続的デリバリーのソフトウェア工学』著者のDave Farley氏が初来日。日本からはテスト駆動開発の第一人者・和田卓人氏が登壇します。 prtimes.jp ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
はじめに こんにちは、ファインディのPlatform開発チームでSREを担当している原( こうじゅん )です。 2025年は、ファインディにとって新規サービスリリースが相次ぐ年でした。 Platform開発チーム(以降、SREチーム)では、この1年間で6つのサービスのインフラ環境を構築してきました。 スピード感を持った環境構築を実現するために、私たちがどのような工夫を行ったのか、今回はTerraformの汎用モジュールを活用した取り組みについてお話しします。 はじめに 2025年、6つのサービスをリリース スピード感のある環境構築で直面した課題 Terraformでの汎用モジュールの導入 Network、Container、Databaseなど、様々なパッケージを整備 モジュールごとにパラメーターを指定すれば環境が立ち上がる仕組み 汎用モジュールで解決した課題 Terraformのplanは成功するけどApplyはコケる問題 まとめ 2025年、6つのサービスをリリース 2025年、SREチームでは次のサービスのインフラ環境を構築しました。 Findy Conference Findy AI+ Findy Team+ AIチャットボット Findy ID Findy Insights アーキテクチャ壁打ちAI by Findy Tools これらのサービスは、それぞれStaging環境やProduction環境といった複数の環境が必要であり、SREチームとしては短期間で多数の環境構築を実施する必要がありました。 スピード感のある環境構築で直面した課題 新規サービスのリリースラッシュの中で、私たちは次のような課題に直面しました。 サービス開発はスピード感を持って行われており、インフラ環境の構築にも「2週間でStaging環境とProduction環境を用意してほしい」といった依頼も珍しくありません。サービスリリースのタイミングが重なると、複数の環境構築依頼が同時に舞い込むこともあります。 SREチームは環境構築だけに専念できるわけではなく、既存サービスの運用改善、障害対応、セキュリティ対応なども並行して進める必要があります。 2025年当時、SREチームのメンバーは4名でした。この人数で、これだけのサービスリリースに対応するのは容易ではありませんでした。 Terraformでの汎用モジュールの導入 これらの課題を解決するために、ファインディのプロダクトで頻繁に利用するAWSリソース(ECS、ALB、RDS、VPCなど)を、再利用可能なTerraformモジュールとして整備しました。 これらを「汎用モジュール」と呼んでいます。 汎用モジュールの目的は、次の2点です。 スピード: 環境構築にかかる時間を大幅に短縮する 品質: 標準化されたモジュールを使うことで、設定ミスを減らし、品質を担保する 汎用モジュールは、HCP Terraform(旧Terraform Cloud)のプライベートレジストリに登録しています。これにより、チーム内で簡単にモジュールを共有・再利用できるようになりました。 Network、Container、Databaseなど、様々なパッケージを整備 汎用モジュールは、リソースの機能ごとにパッケージを分けて整備しています。 例えば次のようなカテゴリーに分けています。 Network: VPC、サブネット、ルートテーブル、NATゲートウェイなど Container: ECS、Fargate、ALB、タスク定義など Database: RDS、Aurora、パラメータグループなど その他、必要に応じてモジュールを追加 モジュールごとにパラメーターを指定すれば環境が立ち上がる仕組み 汎用モジュールを使えば、必要なパラメーター(プロジェクト名、環境名、リソースサイズなど)を指定するだけで、標準化された環境が立ち上がります。 例えば、次のようなイメージです。 module "database" { source = "app.terraform.io/Findy/findy-XXXX-platform/aws//modules/database" version = "X.XX" environment = "staging" engine_type = "postgresql" db_parameter_group_name = "sre-staging" instance_class = "db.t4g.medium" number_of_instances = 2 preferred_backup_window = "20:05-20:35" service_name = "sre-sandbox" } このように、モジュールを組み合わせることで、複雑なインフラ環境を短時間で構築できます。 汎用モジュールで解決した課題 汎用モジュールの導入により、品質が担保されてスピード感のある構築が可能になりました。 汎用モジュールを使うことで、モジュール内の構成ならProduction環境とStaging環境を含めても最短3日で完了できるようになりました。 またパラメーターを指定するだけで環境が立ち上がるので、新しいメンバーでもすぐに戦力になれる仕組みを作ることができました。 Terraformのplanは成功するけどApplyはコケる問題 汎用モジュールの導入で大きな成果が得られた一方、汎用モジュールから呼び出した構成でTerraformのplanは成功するけどApplyはコケるという問題も発生しました。 この問題は、構築スピードの低下につながるため、Terraform Testを導入して対処しました。 詳細については、次の記事で詳しく紹介していますので、ぜひご覧ください。 tech.findy.co.jp まとめ 2025年、SREチームは多数のインフラ環境を構築しました。その裏側で、Terraformの汎用モジュールを活用することで、スピード感と品質を両立した環境構築を実現しました。 汎用モジュールの導入により、SREチームの環境構築はスピードアップしましたが、まだまだ改善の余地があります。 現在は、SREチームが主体となってインフラ環境を構築していますが、今後は開発チームが主体となって容易にインフラ構築できるPlatformを作りたいと考えています。 これにより、開発チームがより自律的にサービスをリリースできるようになり、SREチームはより注力すべきタスクに集中できるようになります。いわゆるPlatform Engineeringの取り組みを進めていきます。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。Findy Tech Blog編集長の高橋( @Taka-bow )です。 2012年にサポート終了したVisual SourceSafeが、いまだに利用率2位。この調査結果に私はとても驚きました。 前回の記事 では、開発生産性を阻む「組織の3大課題」として、要件定義、会議、コミュニケーションの問題を取り上げました。今回は、それらと深く関わる技術環境の世代差と、AI時代における影響を考えます。 【調査概要】 調査対象: ソフトウェア開発(組み込み開発を含む)に直接関わるエンジニア、プロダクトマネージャー、プロジェクトマネージャー、エンジニアリングマネージャー、開発責任者など 調査方法: インターネット調査 調査期間: 2025年4月2日(水)~2025年5月21日(水) 調査主体: ファインディ株式会社 実査委託先: GMOリサーチ&AI株式会社 有効回答数: 798名(95%信頼区間±3.5%) 統計的検定力: 80%以上(中程度の効果量d=0.5を検出) 調査内容: 開発生産性に対する認識 開発生産性に関する指標の活用状況 開発生産性に関する取り組み 開発環境・プロセス評価 組織文化と生産性 ソースコード管理ツールの利用状況 意外と多かったVisual SourceSafe AI時代に広がるソースコード管理ツールの影響 AI開発支援ツールとGit連携 ツールの差がAI活用の差になる CI/CDパイプラインへの低い満足度 なぜ従来型ツールから移行しないのか 開発プロセスの認識の課題 まとめ お知らせ ソースコード管理ツールの利用状況 意外と多かったVisual SourceSafe 今回の調査で、ソースコード管理ツールの利用状況を調べてみたのですが、私はVisual SourceSafeをアンケート回答の選択肢に入れるかどうか、最後まで悩みました。さすがにもう使われていないだろうと思い込んでいたからです。 それは、大きな間違いでした。 ソースコード管理ツールの利用状況 順位 ツール名 利用率 回答者数 備考 1位 GitHub 30.5% 243名 Gitベース 2位 Visual SourceSafe 15.8% 126名 2012年サポート終了 3位 Subversion 13.7% 109名 集中型VCS 4位 Azure DevOps (Repos) 8.4% 67名 Gitベース 5位 GitLab 8.0% 64名 Gitベース 6位 CVS 3.6% 29名 2008年開発終了 7位 TFVC 2.4% 19名 従来型 8位 Bitbucket 1.8% 14名 Gitベース 9位 Gitea 1.6% 13名 Gitベース 9位 SourceForge 1.6% 13名 ホスティング 11位 Perforce (Helix Core) 1.3% 10名 大規模向け 12位 Mercurial 0.4% 3名 分散型VCS - その他 11.0% 88名 - (N=798、単一回答) GitHubが1位であることは予想通りでしたが、Visual SourceSafeが2位に入っていたのです。 Subversion(13.7%)、CVS(3.6%)を加えると、約3割の組織が従来型のバージョン管理システムを使用しています。 AI時代に広がるソースコード管理ツールの影響 AI開発支援ツールとGit連携 2023年以降、AI開発支援ツールが急速に普及しました。 GitHub Copilot、Cursor、Claude Code、Devin、Clineなど、いずれもGitベースのワークフローを前提に設計されています。そのため、従来型ツールの環境ではこれらのツールを十分に活用できません。 AIがコードベース全体を把握できず、提案の精度が下がる(リポジトリ連携機能) 変更履歴や差分を活用したコード生成ができない(diff/commit統合) コードレビューやタスク管理の自動化が使えない(PR自動作成、イシュー管理) DevinやClineなどAIエージェント系ツールは、コード補完にとどまらず、プルリクエスト作成、コードレビュー、イシュー管理まで自動化します。これらはGitHub/GitLabのAPIを前提としているため、旧来のバージョン管理では活用できません。 このツール環境の差は、どのような影響をもたらすのでしょうか。 ツールの差がAI活用の差になる GitHub社の調査によると、Copilot利用者は特定のタスク(HTTPサーバー実装)において、非利用者より 55%速く完了した と報告されています。日常業務すべてで同じ効果が出るとは限りませんが、無視できない差です。 Visual SourceSafe(15.8%)とSubversion(13.7%)を合わせると約3割の組織が、こうしたAI開発支援ツールを十分に活用できない環境にあります。このようなツール環境の違いが、将来の生産性格差につながっていく可能性があります。 つまり、AI活用の有無が開発速度に影響する可能性があります。 CI/CDパイプラインへの低い満足度 次のグラフは、満足度が50%を下回った項目を抜粋したものです。 開発基盤の満足度(全7項目が50%未満、ワースト順) 項目 満足度 CI/CDパイプライン 14.2% ドキュメンテーション 17.5% タスク管理システム 18.2% コードレビュープロセス 19.2% 開発環境整備 24.7% チーム内意思決定 34.1% チーム内コミュニケーション 37.1% (N=798) CI/CDパイプラインの満足度はわずか14.2%で、最も低い結果となりました。 この低さは、ソースコード管理ツールの選択と無関係ではないと思います。現在主流のCI/CDツールはGitベースのバージョン管理を前提としており、Visual SourceSafeやSubversionとシームレスに連携することが難しいからです。 なぜ従来型ツールから移行しないのか 従来型ツールを使い続ける組織には、それぞれの事情があると考えられます。 基幹システムや業務システムとの連携が従来型ツール前提で構築されている 過去の履歴データ、ワークフロー、ビルドスクリプト等の移行に膨大な工数がかかる 長年使い続けたツールに習熟したメンバーが多く、再教育コストが高い 「動いているものは触るな」という保守的な判断が優先される ウォーターフォール型ではリリース頻度が低く、Gitベースのワークフローの恩恵を感じにくい 大規模組織ほど、これらの要因が重なり移行が難しくなります。 とはいえ、全面移行にはリスクが伴います。履歴データの損失、一時的な生産性低下、デリバリー遅延、メンバーの抵抗などです。一方で、現状維持にも見えないコストがあります。セキュリティリスクの増大、新しい技術との統合困難、採用市場での不利など、これらは時間とともに大きくなっていきます。 具体的な移行のロードマップは、最終回(第8回)で取り上げます。 開発プロセスの認識の課題 ソースコード管理ツールの選択は、組織の開発プロセスに対する認識とも関連しています。調査からは、開発プロセスの認識にも課題が見えてきます。 開発フレームワークの認識状況 開発フレームワーク 回答率 回答者数 ウォーターフォール 36.8% 294名 よくわからない 18.2% 145名 ウォーターフォールとアジャイルのハイブリッド 13.2% 105名 【アジャイル開発】決まったフレームワークはない 13.2% 105名 【アジャイル開発】スクラム 6.8% 54名 【アジャイル開発】XPのプロセス 3.8% 30名 【アジャイル開発】大規模スクラム:LeSS 2.4% 19名 【アジャイル開発】大規模スクラム:SAFe 1.3% 10名 【アジャイル開発】大規模スクラム:Nexus 1.3% 10名 【アジャイル開発】大規模スクラム:Scrum@Scale 0.8% 6名 【アジャイル開発】大規模スクラム:その他 0.8% 6名 リーン 0.4% 3名 カンバン 0.3% 2名 その他 1.0% 8名 (N=798) なんと、約5人に1人(18.2%)が自分の組織がどんな開発フレームワークを使っているか「よくわからない」と回答しています。 開発フレームワークを十分に理解できていないということは、 なぜそのプロセスで開発しているのか どのような改善が可能なのか 自分の役割がプロセス全体のどこに位置するのか こうしたことが把握しづらくなります。 この問題は、第3回で取り上げた「不明確な要件」の問題とも関連しています。開発プロセスが明文化・共有されていない組織では、要件定義も曖昧になりがちだと思われます。 まとめ 798名の調査から見えてきたのは、日本の開発現場における技術環境の世代差です。Visual SourceSafeが15.8%、Subversionが13.7%と、約3割の組織が従来型ツールを使い続けています。CI/CDパイプラインの満足度は14.2%にとどまり、18.2%は自組織の開発手法を「よくわからない」と答えました。 AI時代において、このツール環境の差はさらに広がっていくでしょう。最新のAI開発支援ツールはGitベースのワークフローを前提としているからです。ただし、ツールを入れ替えるだけでは解決しません。技術基盤の刷新と組織文化の変革、両方が必要です。 次回は「 なぜDevExは日本で知られていないのか ── 認知度4.9%が語る未開拓領域 」をお届けします。 第1回、日本の開発現場の「リアル」を数字で見る ── 798名の声から浮かび上がる衝撃の実態 調査全体について 第2回、開発生産性への意外な好印象 ── アジャイル実践者59.6%が前向きな理由 開発手法による意識の違いの本質 第3回、開発生産性を阻む「組織の3大課題」 ── 要件定義、会議、コミュニケーションの問題 取り組みが失敗する本当の理由 第4回、AI時代の技術格差 ── Visual SourceSafe 15.8%が示す変革への壁 なぜ従来型ツールから移行できないのか 第5回、なぜDevExは日本で知られていないのか ── 認知度4.9%が語る未開拓領域 日本の開発者が本当に求めているもの お知らせ 「 Development Productivity Conference 2026 」が2026年7月22日〜23日に開催されます。継続的デリバリー(CD)の先駆者であり『継続的デリバリーのソフトウェア工学』著者のDave Farley氏が初来日。日本からはテスト駆動開発の第一人者・和田卓人氏が登壇します。 prtimes.jp ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。 ファインディ株式会社でテックリードマネージャーをやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやClaude Codeなど生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 2025年はSpec Driven DevelopmentやAI-DLCなどといった新しい開発手法が注目を集める年になりました。 ファインディでも新しい開発手法への取り組みを進めており、その一環として要件定義、設計、タスク分解、Issue作成までのフローを自動化しました。 そこで今回は、自動化したフローの内容と仕組みを実現したカスタムコマンドについて紹介します。 それでは見ていきましょう! 背景と課題 既存の開発手法の検討 解決策: AIフレンドリーなIssue カスタムコマンドの仕組み 概要とフロー ステップ1: 要件の理解 ステップ2: コードベースの探索 ステップ3: 要件の明確化 ステップ4: 設計 ステップ5: タスク分解 ステップ6: Issue作成 カスタムコマンド作成のコツ まとめ 採用情報 背景と課題 機能追加の要件から、設計、タスク分解、Issue作成までを行う必要があります。これらを生成AIに任せたいところですが、必要とされる事前知識が多くハードルが高いという課題がありました。 システム全体を把握できていないと適切な設計が難しいケースもあります。また、生成AIに対して効果的な依頼を作成するには明確で簡潔なステップ構造にすることが重要です。 つまり明確な要件を定義して、 生成AIが正しい方法と手順を理解して実行できる ように、 設計図や指示書をAIフレンドリーな形で用意する必要があった のです。 既存の開発手法の検討 2025年はSpec Driven DevelopmentやKiroといった新しい開発手法が注目を集めました。これらは要件定義から実装まで一貫した自動化を目指すアプローチです。 私たちもこれらの手法を検討しましたが、タスク分解とPull requestの粒度に対する考え方に課題を感じました。 Spec Driven Developmentでは、システム全体の仕様を詳細に定義してから実装に進みます。これは大規模な機能開発や新規プロジェクトでは有効ですが、仕様の粒度やSpec/Taskの部分が大きくなりがちです。その結果、実装を進めると大きな変更を含むPull requestが作られることになり、コードレビューの負担が増大する傾向があります。 どちらにも利点がありますが、私たちはレビューの品質とチーム全体の開発速度を重視して、 タスク分解と粒度に重点を置いたアプローチが必要 だと考えました。 解決策: AIフレンドリーなIssue この課題を解決するため、 システムの現状を把握して、必要な要件をタスク分解してIssueに切り出すカスタムコマンド を構築しました。 重要なのは、 Pull requestとタスクの粒度を維持しつつ、生成AIが理解しやすく精度の高いIssueを自動生成する ことです。この一連の流れをカスタムコマンドで自動化しました。 Issueが作成されたら、その内容や手順が正しいのかどうかチェックして、問題なければ そのまま生成AIに渡して実装を進めてもらう ようになります。 カスタムコマンドの仕組み 概要とフロー 今回紹介するカスタムコマンドは要件とコードベースを元に、要件の明確化、設計、タスク分解、Issue作成までを自動化します。 特徴的なのはインタラクティブな形式を採用している点です。曖昧な部分や不明点があれば、その都度生成AIが質問を投げかけてきます。人間は質問に答えながら生成AIとの対話を通じて要件を明確化していきます。 このプロセスを経て、生成AIが設計を行い、タスク分解を実施し、最終的にGitHubのIssueを自動で作成します。人間が行うのは作成されたIssueのレビューだけです。 Issueのレビューが完了したら、そのIssueをそのまま生成AIに渡して実装を進めてもらいます。Pull requestの粒度を意識した形でIssueが作成されるため、後続のコードレビューの負担も軽減されます。 このカスタムコマンドの全体フローは次のようなイメージです。 これら全てのフローを実行するために必要なカスタムコマンドやSkill、Sub Agentを社内Pluginとして開発組織全体に展開しています。 ステップ1: 要件の理解 まずは実現したい要件を生成AIが理解するところから始めます。このステップのフローは次のようなイメージです。 カスタムコマンドを実行して実現したい要件をパラメータ経由で伝えます。この段階では要件がある程度曖昧でも問題ありません。 ❯ /plugin:feature-breakdown 複数ユーザーの新規登録を一括で実行する機能を追加したい ⏺ I'll help you break down the bulk user registration feature into implementation tasks and create GitHub issues. Let me start by creating a TODO list for all phases. ⏺ Phase 1: 要件の理解 初期リクエスト: 複数ユーザーの新規登録を一括で実行する機能を追加したい 要件の中に曖昧な内容があれば生成AIが確認のための質問を投げかけてきます。対話を通じて徐々に要件を明確にしていきます。 今回は追加したい機能を具体的にするために生成AIから幾つかの質問が投げかけられました。解答を選択式にすることで、スムーズに要件を明確化できます。 この機能について、以下の点を明確にさせてください。 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ← ☐ 対象ユーザー ☐ 入力形式 ☐ 認証フロー ☐ エラー処理 ✔ Submit → この一括登録機能は誰が使うことを想定していますか? ❯ 1. 管理者(AdminUser)のみが使用 管理画面から管理者が実行する機能として実装。一般ユーザーは使用できない。 2. 組織の管理者(Org内の特定ロール) 組織内の権限を持つユーザーが自組織のメンバーを一括登録できる。 3. 一般ユーザーも使用可能 全ユーザーが利用可能な機能として実装。 4. Type something. 解答を選択式にするためにClaude CodeのToolの AskUserQuestion を利用するようにプロンプトに明記すると便利です。 AskUserQuestion は情報を収集または曖昧さを明確にするために、ユーザーに複数選択肢の質問をします。 一通りの質問に回答すると生成AIが要件を整理してくれます。ここまでの選択で要件を理解することができました。認識にズレがなければこのまま次のステップに進みます。何かしらに誤りがあった場合、この段階で軌道修正もできます。 ⏺ User answered Claude's questions: ⎿ · この一括登録機能は誰が使うことを想定していますか? → 管理者(AdminUser)のみが使用 · ユーザーデータの入力形式はどのようなものを想定していますか? → CSV/TSVファイルのアップロード · 登録時のユーザー認証フローはどうしますか? → 確認メール送信(既存フロー準拠) · 登録処理中のエラーハンドリングはどうしますか? → 部分成功を許可 ⏺ ありがとうございます。要件を整理します。 ⏺ 理解した要件 機能: 複数ユーザーの新規登録を一括で実行する機能 要件の詳細: - 対象ユーザー: 管理者(AdminUser)のみが使用可能 - 入力形式: CSV/TSVファイルのアップロード(email, name, org_id等のカラム) - 認証フロー: 確認メール送信(既存の単一ユーザー登録フローと同じ) - エラー処理: 部分成功を許可(成功したユーザーは登録、失敗したユーザーはエラーレポートで返す) ステップ2: コードベースの探索 次に、要件を実現させるために既存のコードベースがどうなっているのかを理解する必要があります。 次のようなフローでコードベースを探索していきます。 既存のコードベースを理解するため、 Claude Codeの公式Pluginであるfeature-dev にある code-explorerエージェント を活用します。このエージェントはプロジェクトの構造やパターンを自動的に分析して実装に必要な情報を収集します。feature-devプラグインをインストールするだけでcode-explorerエージェントを利用できるようになります。 要件を分割して複数のcode-explorerエージェントを並列で起動します。各エージェントが特定の観点からコードベースを探索して必要な情報を収集します。 ⏺ Phase 2: コードベースの探索 既存のコードとパターンを理解するため、複数のcode-explorerエージェントを並列で起動します。 Running 3 feature-dev:code-explorer agents… (ctrl+o to expand) ├─ Explore user registration architecture · 12 tool uses · 29.1k tokens │ ⎿ Search: **/models/admin*.py ├─ Explore admin API patterns · 12 tool uses · 27.6k tokens │ ⎿ Read: main.py └─ Explore CSV and file handling · 10 tool uses · 17.0k tokens ⎿ Search: **/api/routes/**/*.py ctrl+b to run in background ⏺ Excellent! Now let me read the critical files identified by the code-explorer agents to deepen my understanding. ⏺ Read(src/api/routes/user/users.py) ⎿ Read 60 lines ⏺ Read(src/api/routes/user/users.py) ⎿ Read 60 lines ⏺ Read(src/api/routes/admin/orgs.py) ⎿ Read 70 lines ⏺ Read(src/api/routes/user/orgs/teams.py) ⎿ Read 60 lines ⏺ Read(src/services/email/email_service.py) ⎿ Read 132 lines 今回は複数のユーザー登録を一括で実行する機能を追加したいので、既存のユーザー登録処理や管理者用APIのパターン、CSVファイルの取り扱い方法などを中心にコードベースを探索しているようです。 要件を実現させるために必要なコードベースの情報が揃ったようなので、次のステップに進みます。 ステップ3: 要件の明確化 次は入力した要件とコードベースの情報を元に、要件を更に明確化していきます。 既存コードと要件を精査して曖昧な内容が残っていれば、追加で質問が投げかけられます。対話を繰り返すことで実装に必要な情報を揃えていきます。 ⏺ Phase 3: 明確化のための質問 コードベースの調査結果から、以下の点について確認させてください。 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ☐ CSV Columns CSVファイルにはどのような情報を含めますか? ❯ 1. 必須情報:メール、名前、ロール (Recommended) email, first_name, last_name, roleの4カラム。GitHubアカウントはオプション 2. 必須情報:メールと名前のみ email, first_name, last_nameの3カラム。ロールはデフォルトでmember 3. メールアドレスのみ emailの1カラムだけ。他の情報は後から追加 4. Type something. このステップではエラーハンドリングやエッジケースなど、細かい点についての要件を明確化します。 ⏺ Phase 3: 明確化のための質問 コードベースの調査結果から、以下の点について確認させてください。 ⏺ User answered Claude's questions: ⎿ · CSVファイルにはどのような情報を含めますか? → 必須情報:メール、名前、ロール (Recommended) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ☐ Duplicate Emails 既存ユーザー(同じメールアドレス)がいた場合、どう処理しますか? ❯ 1. スキップして結果に記録 (Recommended) 既存ユーザーは登録せず、skipped_emailsリストとして返す 2. エラーとして返す 既存ユーザーがいたらエラー情報を返し、その行を登録しない 3. 情報を更新する 既存ユーザーの名前やロールをCSVの値で更新 4. Type something. ここまでで要件と既存コードの変更内容が明確化されました。次のステップで設計に進みます。 ステップ4: 設計 設計フェーズでは、 Claude Codeの公式Pluginであるfeature-dev にある code-architectエージェント を活用します。 このエージェントは設計方針を提案してくれます。開発者は提案された選択肢の中からプロジェクトに最適な実装方針を選ぶことができます。この選択により実装の方向性が確定します。 設計に関するフローは次のようなイメージになります。 今回は最小構成、クリーンアーキテクチャ、実用的バランスの3つのアプローチでcode-architectエージェントを並行稼働して最適な設計方針を提案してもらいました。 ⏺ Phase 4: アーキテクチャ設計 それでは、3つの異なるアプローチでアーキテクチャ設計を行います。 ⏺ Running 3 feature-dev:code-architect agents… (ctrl+o to expand) ├─ Design minimal change approach · 3 tool uses · 10.1k tokens │ ⎿ Search: send_invite_user_email ├─ Design clean architecture approach · 4 tool uses · 10.1k tokens │ ⎿ Search: src/services/**/*.py └─ Design pragmatic balance approach · 0 tool uses ⎿ Initializing… ctrl+b to run in background ⏺ 3 feature-dev:code-architect agents finished (ctrl+o to expand) ├─ Design minimal change approach · 20 tool uses · 25.2k tokens │ ⎿ Done ├─ Design clean architecture approach · 26 tool uses · 41.0k tokens │ ⎿ Done └─ Design pragmatic balance approach · 0 tool uses ⎿ Done ⏺ Perfect! Now I have three comprehensive architecture designs. Let me present them to the user for selection. ⏺ 3つのアーキテクチャアプローチが完成しました。それぞれの特徴を整理してご提案します。 3つのアプローチ比較 1. 最小変更アプローチ (Minimal Change) 特徴: - CSV処理をルートハンドラに直接実装(約150行の単一ファイル) - 既存パターンを最大限活用(teams.pyの部分成功パターン) - 新規作成ファイル: 2個(エンドポイント + テスト) メリット: - 最速で実装可能(2 PR、~650行) - シンプルで理解しやすい - 既存コードとの整合性が高い デメリット: - ルートハンドラが長くなる(~150行) - CSV処理ロジックの再利用が困難 - 将来の拡張(Excel対応など)に追加実装が必要 タスク数: 2個 --- 2. クリーンアーキテクチャアプローチ (Clean Architecture) 特徴: - サービス層を導入して責務を分離 - Parser(CSV解析) - Validator(バリデーション) - UserImportService(オーケストレーション) - 新規作成ファイル: 7個 メリット: - 将来の拡張が容易(Excel, JSON対応) - テストが容易(各層を独立してテスト可能) - ビジネスロジックの再利用性が高い - 保守性が高い デメリット: - 初期実装に時間がかかる(6 PR、~730行) - 抽象化により複雑さが増す - シンプルなCSV処理に対してはオーバーエンジニアリングの可能性 タスク数: 6個 --- 3. 実用的バランスアプローチ (Pragmatic Balance) 特徴: - サービス層を導入するが、Parser/Validatorは分離しない - UserImportServiceで一元管理 - 新規作成ファイル: 5個 メリット: - 適度な抽象化で保守性を確保 - 実装速度とコード品質のバランスが取れている - 将来の拡張もある程度対応可能 デメリット: - クリーンアーキテクチャほどの柔軟性はない - 最小変更アプローチほどシンプルではない タスク数: 5個 --- ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ☐ Approach どの実装アプローチを採用しますか? 1. 実用的バランス (Recommended) 開発速度と品質のバランス。サービス層を導入しつつもシンプルさを維持。タスク数: 5個 2. 最小変更 最速で実装。ルートハンドラに直接実装。既存パターンを最大限活用。タスク数: 2個 ❯ 3. クリーンアーキテクチャ 保守性と拡張性を重視。Parser/Validatorを分離し、将来の複数フォーマット対応を考慮。タスク数: 6個 4. Type something. 様々な設計方針ごとにメリット、デメリットなどが提示されます。要件やプロジェクトの方針にもよりますが、今回はクリーンアーキテクチャを選択します。設計方針が決まったので次のタスク分解のステップに進みます。 ステップ5: タスク分解 確定した設計方針を元に実装に必要なタスクを洗い出して分解します。 今回のカスタムコマンドで特に重要なのは、Pull requestやIssueの粒度を考慮することです。今回のカスタムコマンドの調整により、レビューしやすく適切な粒度でマージしやすい最適な粒度に分解してくれます。 Pull requestやIssueの粒度に関するガイドラインはSkillに切り出しています。 Sub AgentやSkillに切り出すことにより、タスク分解の品質を継続的に改善できるだけでなく、カスタムコマンドの一連の流れのコンテキストを適切に管理できるようになります。 今回はクリーンアーキテクチャを選択しており、最初に各種共通処理の作成とリファクタを行い、その後にAPIを追加するというタスクの分け方になっているようです。 ⏺ 承知しました。クリーンアーキテクチャアプローチで進めます。 それでは Phase 5 に進んで、task-breakdown Skillを使ってタスク分解を評価・調整します。 ⏺ Skill(task-breakdown) ⎿ Successfully loaded skill ⏺ Task Breakdown Skillがロードされました。それでは、Phase 4で得たクリーンアーキテクチャアプローチのタスク分解を評価します。 code-architectが提案したタスク分解 以下は、クリーンアーキテクチャアプローチで提案された6つのタスクです: Task 1: [Data] ドメインモデルの追加 - 変更ファイル: - CREATE: src/services/user_import/models.py - CREATE: src/services/user_import/__init__.py - CREATE: tests/services/user_import/test_models.py - 概要: ImportRow, ValidationError, CreatedUser, ImportResult モデルを作成 - 依存関係: なし Task 2: [Logic] CSVパーサーの実装 - 変更ファイル: - CREATE: src/services/user_import/parser.py - MODIFY: src/services/user_import/__init__.py - CREATE: tests/services/user_import/test_parser.py - 概要: CSVParserインターフェースとDefaultCSVParserを実装 - 依存関係: Task 1(ImportRowモデルが必要) Task 3: [Logic] バリデーターの実装 - 変更ファイル: - CREATE: src/services/user_import/validator.py - MODIFY: src/services/user_import/__init__.py - CREATE: tests/services/user_import/test_validator.py - 概要: UserDataValidator(ビジネスルール検証)を実装 - 依存関係: Task 1(ImportRow, ValidationErrorモデルが必要) Task 4: [Logic] ユーザーインポートサービスの実装 - 変更ファイル: - CREATE: src/services/user_import/user_import_service.py - MODIFY: src/services/user_import/__init__.py - CREATE: tests/services/user_import/test_user_import_service.py - 概要: UserImportService(オーケストレーション層)とメール連携 - 依存関係: Task 1, 2, 3(すべてのコンポーネントが必要) Task 5: [API] 管理者用一括登録エンドポイント - 変更ファイル: - CREATE: src/api/routes/admin/user_import.py - MODIFY: main.py - CREATE: tests/api/routes/admin/test_user_import.py - 概要: POST /api/v1/admin/users/import エンドポイントの実装 - 依存関係: Task 1, 2, 3, 4(サービス層全体が必要) --- Task Breakdown Skillによる評価 1. タスクの粒度チェック Task 1: ドメインモデル - ファイル数: 3個 ✅ (理想的) - 行数: ~80行 ✅ (適切) - 評価: 適切なサイズ Task 2: CSVパーサー - ファイル数: 3個 ✅ (理想的) - 行数: ~100行 ✅ (適切) - 評価: 適切なサイズ Task 3: バリデーター - ファイル数: 3個 ✅ (理想的) - 行数: ~120行 ✅ (適切) - 評価: 適切なサイズ Task 4: ユーザーインポートサービス - ファイル数: 3個 ✅ (理想的) - 行数: ~180行 ✅ (適切) - 評価: 許容範囲だが、メール連携部分を分離できる可能性あり Task 5: APIエンドポイント - ファイル数: 3個 ✅ (理想的) - 行数: ~100行 ✅ (適切) - 評価: 適切なサイズ 2. 密結合の識別 ✅ 密結合が適切に保たれているもの: - Task 1: モデル定義 + テスト (実装とテストが同一PR) - Task 2: Parser実装 + テスト (実装とテストが同一PR) - Task 3: Validator実装 + テスト (実装とテストが同一PR) - Task 4: Service実装 + テスト (実装とテストが同一PR) - Task 5: APIエンドポイント + ルーティング + テスト (API完全性が保たれている) ❌ 潜在的な密結合の問題: なし 3. 独立性の検証 独立してrevertできるか? - Task 1: ✅ 他のタスクに影響なし(モデルのみ) - Task 2: ✅ Task 1に依存するが、独立して削除可能 - Task 3: ✅ Task 1に依存するが、独立して削除可能 - Task 4: ⚠️ Task 2, 3に依存するため、revert時は順序が重要 - Task 5: ✅ Task 4に依存するが、独立して削除可能(ルーター登録を削除するだけ) 各PRマージ後、アプリケーションは正常動作するか? - Task 1マージ後: ✅ モデルのみ追加、既存機能に影響なし - Task 2マージ後: ✅ パーサーのみ追加、既存機能に影響なし - Task 3マージ後: ✅ バリデーターのみ追加、既存機能に影響なし - Task 4マージ後: ✅ サービス層のみ追加、APIエンドポイントがないため既存機能に影響なし - Task 5マージ後: ✅ 新規エンドポイント追加、既存機能に影響なし 4. 依存関係の整理 Task 1 (モデル) ├── Task 2 (Parser) ← Task 1に依存 └── Task 3 (Validator) ← Task 1に依存 └── Task 4 (Service) ← Task 2, 3に依存 └── Task 5 (API) ← Task 4に依存 並列実装可能なタスク: - Task 2とTask 3は並列実装可能(どちらもTask 1にのみ依存) 5. 推奨事項 現在のタスク分解は非常に良好です。以下の理由から、このまま進めることを推奨します: 良い点: 1. ✅ 各タスクのサイズが適切(3-10ファイル、100-200行) 2. ✅ 実装とテストが密結合として同一PRに含まれている 3. ✅ 各タスクが独立してrevert可能 4. ✅ 依存関係が明確で、並列実装の余地もある 5. ✅ 各PRマージ後もアプリケーションは正常動作する 最終判断: 現在のタスク分解をそのまま採用 --- ここまでで要件を正しい方法と手順で実現するために必要な準備が整いました。最後のステップをこれらを元にIssueを作成していきます。 ステップ6: Issue作成 最後のステップで、分解したタスクを元にGitHubのIssueを自動で作成します。 作成前には確認ステップを踏み、認識がズレていないか最終チェックを行います。問題がなければ、そのままIssueを作成してSub Issueの紐付けとrelationshipの設定まで完了させます。 これにより親Issueと子Issueが適切に構造化された状態で、すぐに実装に取り掛かれるようになります。 GitHubのIssueを作成する処理もSub Agentに切り出しています。Issueを作成するために必要な情報量が多く、すぐにコンテキストが肥大化してしまうからです。 そのためIssue作成専用のSub Agentを用意して必要な情報だけ渡してIssueを作成する形にしています。 ⏺ Phase 7: GitHub Issueの作成 github-issue-creator agentを起動してGitHub issueを作成します。 ⏺ plugin:github-issue-creator(Create GitHub issues) ⎿ Done (25 tool uses · 117.1k tokens · 8m 35s) ⏺ ✅ Feature Breakdown 完了! GitHub Issueの作成が完了しました。以下が作成されたIssueです。 📋 親Issue #1 - Feature: 複数ユーザーの一括登録機能 https://github.com/Findy/Example/issues/1 📦 子Issue(実装タスク) 1. #2 - [Data] ドメインモデルの追加 + テスト https://github.com/Findy/Example/issues/2 依存関係: なし 2. #3 - [Logic] CSVパーサーの実装 + テスト https://github.com/Findy/Example/issues/3 依存関係: #2 3. #4 - [Logic] バリデーターの実装 + テスト https://github.com/Findy/Example/issues/4 依存関係: #2 4. #5 - [Logic] ユーザーインポートサービスの実装 + テスト https://github.com/Findy/Example/issues/5 依存関係: #2, #3, #4 5. #6 - [API] 管理者用一括登録エンドポイント + テスト https://github.com/Findy/Example/issues/6 依存関係: #5 --- 📊 Issue構造 📋 #1 Feature: 複数ユーザーの一括登録機能 ├── 📦 #2 [Data] ドメインモデルの追加 + テスト │ ├── ⚙️ #3 [Logic] CSVパーサーの実装 + テスト │ └── ⚙️ #4 [Logic] バリデーターの実装 + テスト │ └── ⚙️ #5 [Logic] ユーザーインポートサービスの実装 + テスト │ └── 🔌 #6 [API] 管理者用一括登録エンドポイント + テスト --- 🎯 次のステップ 1. 実装開始: #2から順番に実装してください 2. 並列実装可能: #3と#4は#2完了後、並列で実装可能です 3. 進捗管理: 親Issue #1で全体の進捗を確認できます 4. PRの作成: 各Issueごとに1つのPRを作成してください --- 📝 設計サマリー 採用アーキテクチャ: クリーンアーキテクチャ - Parser層(CSV解析) - Validator層(ビジネスルール検証) - Service層(オーケストレーション) - API層(HTTPハンドリング) 主な技術要素: - CSVパース: Python標準ライブラリ csv.DictReader - バリデーション: Pydantic + カスタムロジック - トランザクション: ユーザー単位のコミット - メール送信: 既存のEmailService再利用 - エラー処理: 部分成功パターン 受入基準: - テストカバレッジ90%以上 - 各PRは3-10ファイル、200-500行の変更 - すべてのPRは独立してrevert可能 Feature Breakdown コマンドの全フェーズが完了しました! これで要件の策定から適切な粒度でのIssue作成までの一連の流れが完了しました。Issueの内容をチームでレビューして、実装を生成AIに任せましょう。適切な粒度でタスクが分解されているので、Pull requestの粒度も適切になり、レビューの負担が大幅に軽減されます。 カスタムコマンド作成のコツ 様々な開発タスクを効率化するためには必要な情報を用意する必要があります。その結果、コンテキストが肥大化してしまい精度が一気に落ちてしまうことがよくあります。 まずは一通りの流れをカスタムコマンドで作成して、内容やスコープに応じてSkillやSub Agentに切り出していくのが良いです。特定の知識やガイドラインなどはSkillに切り出しましょう。メインのコンテキストには不要で結果のみ必要な情報を扱う場合はSub Agentに切り出すのが良いです。 いかにしてコンテキストを最小限に保つかがコツです。 カスタムコマンドに限らず、 コンテキストが肥大化すると生成AIの精度は一気に落ちてしまいます。 必要な情報だけを適切に渡して維持し続けることが、生成AIを活用する上で非常に重要です。 まとめ 今回紹介したカスタムコマンドは、誰でも高品質で適切な粒度のAIフレンドリーなIssueを作成できるようにするものです。 生成AIを活用した開発では、生成AIが理解しやすい形で要件と設計を伝えることが重要です。要件定義から設計、タスク分解、Issue作成までのフローを自動化することで、開発者はより本質的な開発業務に集中できるようになります。生成AIとの協業による開発スタイルは、今後ますます重要になっていくでしょう。 最後になりますが、このたび 2026年2月18日(水)にFindy AI Meetup in Fukuoka #4の開催が決定 しました! findy-inc.connpass.com 会場へのアクセスは天神駅から徒歩3分となっています。またTVCM公開記念ノベルティや、イベント後半には懇親タイムもご用意しています。 申込みの先着順となっておりますので、気になっている方は早めにお申し込みいただくことをおすすめします。生成AIの活用事例に興味のある方は奮ってご参加ください! みなさんにお会いできることを楽しみにしています! 採用情報 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから。 herp.careers
アバター
こんにちは。 ファインディ株式会社でテックリードマネージャーをやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやClaude Codeなど生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 弊社でも例に漏れず、生成AIを活用して開発効率の向上に取り組んでいます。その中でFindy Team+で開発組織の生産性をチェックしていたところ、Pull requestの質が落ちているのでは?という仮説が浮かび上がりました。 今回は仮説が浮かんできた経緯と、その対策として導入したセルフレビューの仕組みについて紹介します。 それでは見ていきましょう! 思っていたよりPull requestの数が増えていなかった 理解しないままレビュー依頼を出していた AIでセルフレビューを支援する仕組みを導入 まとめ 思っていたよりPull requestの数が増えていなかった 稼働人数は昨年比で1.5倍程度増えており、それと比例する形でPull requestの作成数も単純に1.5倍に増えていました。この図から、人数の増加とPull request作成数が概ね比例していることが分かります。 しかし、1人あたりのPull requestの作成数は、昨年とほぼ変わらずでした。この図を見ると、人数が増えても1人あたりのPull request作成数はほぼフラットであることが分かります。 生成AIにPull requestを作成してもらうのであれば、1人あたりの作成数も伸びて、増えた人数以上に総数も伸びるはずでは?ここが疑問ポイントでした。 Pull requestの数が多ければ必ずしも良いわけではありませんが、AIを導入しても1人あたりの数値が伸びていないということは、どこかしらに問題があるはずです。 Pull requestの作成数だけでは判断することが出来ないので、他の数値に目を向けてみました。すると、各種リードタイムが昨年比で悪化していることがわかりました。 その中でも私が特に目を付けたのが「レビューからApproveまでの平均時間」です。この数値が昨年比で平均約20分近くも伸びていたのです。 更に「平均コメント数」と「平均レビュー数」にも目を付けました。こちらも昨年比で30%近くも増えていたのです。 これらの数値の変化から、1つの仮説が浮かび上がりました。それは「レビューで指摘された内容の対応で各種リードタイムが伸びており、マージまでの時間が伸びて結果的にPull requestの作成数が伸びていないのでは?」ということです。 この仮説を一言で言うと、「作成されているPull requestの質が落ちているのでは?」と言い換えることもできます。仮説を整理できたので、その仮説が正しいのかどうかを検証することにしました。 理解しないままレビュー依頼を出していた AIが作成したPull requestを幾つか確認してみたところ、確かにセルフレビューである程度防げるような指摘が多く見受けられました。 例えばAIが次のようなテストコードを追加しているシーンがありました。 import { render, screen } from '@testing-library/react' ; it ( 'should render with isHiddenTitle' , () => { render(< HogeComponent isHiddenTitle />); expect ( screen .queryByText( "Title" )).not.toBeInTheDocument(); } ); 一見特に問題なさそうなテストコードですが、仮にテキストが常に非表示になっている状態だった場合、このテストコードは常に成功してしまいます。つまり、テストコードとしての意味を成していないのです。 特定の条件下で「表示されないこと」を守りたいのあれば、その条件下以外で「表示される」ことも同時に守る必要があります。この変更に対してはリードクラスのエンジニアからレビューで指摘が入り、次のようなテストコードになりました。 import { render, screen } from '@testing-library/react' ; it ( 'should render' , () => { render(< HogeComponent />); expect ( screen .getByText( "Title" )).toBeInTheDocument(); } ); it ( 'should render with isHiddenTitle' , () => { render(< HogeComponent isHiddenTitle />); expect ( screen .queryByText( "Title" )).not.toBeInTheDocument(); } ); このテストコードで文言が表示されること、特定の条件下のみで表示されないことの両方を守ることができるようになりました。 このように、AIが出力したコードを依頼主が理解しないままレビュー依頼を出しているケースが少なからず見受けられました。そしてそれらをレビューするリードクラスのエンジニアのレビュー負担が上がっており、結果的にマージまでのリードタイムが伸びている。という状態に陥っていたのです。 これらの多くは難しい問題点ではなく、セルフレビューの時点で気づくことが出来るような内容が大半でした。 AIが出力したコードの責任は人間にあります。 レビュー依頼を出す前に、まずセルフレビューをして、早い段階で問題点に気付けるように仕組みを作ることにしました。 AIでセルフレビューを支援する仕組みを導入 自動でレビューをしてくれるサービスも利用したのですが、汎用的な内容でのレビューなのでドメイン知識や個人の癖などを考慮出来ておらず、指摘内容としても薄いものが多く、レビュー依頼する前のセルフチェックという意味合いでは不十分でした。 そこで、自分自身にカスタマイズされたセルフレビューのチェックリストを作成する仕組みを内製することにしました。 流れとしてはこうです。 まず直近数カ月で自分が作ったPull requestの一覧を取得します。そのPull requestに対して作成されたレビューコメントを全て取得します。それらレビューコメントの全てをLLMに渡して、どういう内容や傾向で自分自身が指摘されているのかを分析後にチェックリストを作成します。 作成されたチェックリストに沿って、Claude Codeにセルフレビューしてもらいます。 一連の流れはこのようになります。 このシーケンス図から、チェックリストの生成からセルフレビュー、修正の反映までが一連のフローとして自動化されていることが読み取れます。 この一連の流れを全て自動で行うカスタムコマンドを作成し、Pluginsに入れて社内に展開しました。 チェックリストを更新するカスタムコマンドと、そのチェックリストを使ってセルフレビューを実行するカスタムコマンドは分けています。チェックリストは定期的に更新すれば良いので、セルフレビューの度に更新する必要はないからです。 まずチェックリストを作成するコマンドを実行して、次のようなファイルが出力されます。 # Self-Review Checklist for hoge このチェックリストは、過去3ヶ月間(2025年9月30日〜2025年11月26日)にマージされたPRとレビューコメントを分析して作成されました。 ## 🧪 テストコード ### アサーションの品質 - [ ] ` toEqual ` の代わりに ` toStrictEqual ` を使用しているか - より厳密な型チェックのため - [ ] テストケースは実装の意図を正確に検証しているか - [ ] スナップショットテストは適切に使用されているか ### テストの網羅性 - [ ] 主要な機能パスはすべてカバーされているか - [ ] エラーハンドリングのテストは含まれているか - [ ] エッジケースを考慮しているか ## 🎨 UI/UX 設計 ### アクセシビリティ - [ ] aria-label は適切に設定されているか - [ ] キーボード操作に対応しているか - [ ] カラーコントラストは十分か ## 🎯 コミットメッセージ ### Conventional Commits - [ ] プロジェクトのコミットメッセージ規約に従っているか - [ ] 適切な type を使用しているか(feat, fix, refactor, chore, etc.) - [ ] scope は正しく指定されているか --- **最終更新日**: 2025-11-28 **分析期間**: 2025-09-30 〜 2025-11-26 次にセルフレビューのコマンドを実行します。出力されたチェックリストの内容に沿って、変更箇所をレビューしてもらいます。実際の出力例は次のようになります。 > 変更箇所に対して、`self-review-check-list.md` の内容を元にレビューしてください ⏺ 変更箇所をレビューするために、まず self-review-check-list.md の内容を確認します。 ⏺ Search(pattern: "**/self-review-check-list.md") ⎿ Found 1 file (ctrl+o to expand) ⏺ Read(self-review-check-list.md) ⎿ Read 33 lines ⏺ Read(packages/feature-server/src/clients/github/github-client.spec.ts) ⎿ Read 863 lines ⏺ self-review-check-list.md の内容に基づいて、変更ファイルのレビューを実施しました。 レビュー結果 ✅ コード品質 命名の明確さ - 関数名や変数名が実際の動作を正確に表現しています - ドメイン用語(GitHub API関連)を正しく使用しています ✅ テストコード テストの網羅性 - 各関数に対して以下のテストケースを網羅しています: - すべてのパラメータを指定した成功ケース - 必須パラメータのみの成功ケース - エラーケース - toStrictEqual を使用してオブジェクト全体の検証を適切に行っています テスト依存関係 - 不要なテスト依存関係は追加されていません - プロジェクト標準のテストライブラリのみを使用しています ✅ プロジェクト固有のルール - TypeScript Deep Dive のスタイルガイドに従っています - ファイル名がケバブケース(github-client.spec.ts)になっています ⚠️ 改善提案 テストアサーションの統一性 packages/feature-server/src/clients/github/github-client.spec.ts:307 expect(response.data).toEqual(mockData); 他のテストケースでは toStrictEqual を使用していますが、ここだけ toEqual を使用しています。toStrictEqual に変更することを推奨します: expect(response.data).toStrictEqual(mockData); toStrictEqual は toEqual よりも厳密なチェック(undefined プロパティも検証)を行うため、より堅牢なテストになります。 --- 全体的に非常に高品質なテストコードです。上記の1点のみ修正すれば、チェックリストのすべての項目を満たしま す。 テストコードを変更した場合のセルフレビュー例ですが、コード品質やテストコード、プロジェクト固有のルールに関しては基本的にクリアしていましたが、改善提案として1点のみ指摘がありました。 このレビュー結果を元に、修正も自動で行ってもらいましょう。続いてプロンプトを実行します。 > レビュー結果を元に、変更箇所を修正してください ⏺ レビュー結果に基づいて修正します。 ⏺ Update(packages/feature-server/src/clients/github/github-client.spec.ts) ⎿ Updated packages/feature-server/src/clients/github/github-client.spec.ts with 1 addition and 1 removal 304 } 305 ); 306 expect(response.status).toBe(HttpStatusCode.OK); 307 - expect(response.data).toEqual(mockData); 307 + expect(response.data).toStrictEqual(mockData); 308 }); 309 310 it('fetch data with only required params', async () => { ⏺ 修正が完了しました。 修正内容 packages/feature-server/src/clients/github/github-client.spec.ts:307 変更前: expect(response.data).toEqual(mockData); 変更後: expect(response.data).toStrictEqual(mockData); この修正により、テストアサーションが統一され、すべてのテストケースで toStrictEqual を使用するようになりました。toStrictEqual は toEqual よりも厳密なチェック(undefined プロパティも検証)を行うため、より堅牢なテストになります。 これで self-review-check-list.md のすべての項目を満たすコードになりました。 この仕組みにより、定期的にチェックリストのファイルを更新することによって、セルフレビューの精度を上げ続けることが可能となります。 まとめ 今回はジュニアエンジニアがAIを使ってPull requestを作成した場合に、セルフレビューでのチェックが甘くなり、レビュワーの負担が上がっているといったケースでした。 「AIに使われる」のではなく、「AIを使う」ためにも、AIが出力したコードを理解することが必要不可欠です。AIが出力したコードの責任は人間にあります。自分自身の責任を果たす意味でも、生成AI時代のセルフレビューが持つ意味合いは、これまで以上に重要になってくるでしょう。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
アバター
こんにちは。 ファインディ株式会社でFindy AI+の開発をしているdanです。 Findy AI+ではLLMを活用した分析機能を提供しています。 分析対象は個人・チーム・組織と幅広く、データ量に応じて分析に時間がかかることがあります。分析が完了するまで画面に何も表示されないと、ユーザーは処理が進んでいるのか分からず、待ち時間が長く感じられてしまいます。 この課題を解消するため、LLM分析結果の表示にストリーミング出力を導入しました。 今回は、実装内容とどの程度待ち時間が改善されたのかについてお話しします。 Findy AI+とは ストリーミング対応前は何が問題だった? 当初の設計 分析結果を見るのにどのくらいの時間を要していたのか どのように対応を進めたか ストリーミング対応の設計 肝となる実装の全体像 LangChainの astream() メソッド FastAPIでのストリーミング実装 ストリーミングレスポンスの生成 SSE(Server-Sent Events)の仕組み フロントエンドでの受信処理 ストリーミング対応後に得られた効果 おわりに Findy AI+とは Findy AI+ は、GitHub連携やプロンプト指示を通じて生成AIアクティビティを可視化し、生成AIの利活用向上を支援するサービスです。 人と生成AIの協働を後押しし、開発組織の変革をサポートします。 Claude Code、GitHub Copilot、Codex、Devinなど様々なAIツールの利活用を横断的に分析しており、分析基盤にはLangChainを採用しています。また、日報やチーム分析などの機能でもLLMを活用しています。 LLM分析に使用するプロンプト調整についても記事を公開していますので、よかったらご覧ください。 tech.findy.co.jp ストリーミング対応前は何が問題だった? 当初の設計 分析結果を見るのにどのくらいの時間を要していたのか 冒頭で述べた通り、Findy AI+では個人・チーム・組織と幅広いデータを分析対象としています。 分析に必要なデータ作成のAPIを例にあげます。 @ router.post ( "/api/v1/hoge" ) def create_hoge ( request: CreateHogeRequest, db: Session = Depends(get_db), ): # 1. データ取得 hoge = get_hoge(db, request.hoge_id) # 2. LLM呼び出し(全レスポンス待ち) client = Anthropic(api_key= "xxx" ) message = client.messages.create( model= "claude-sonnet-4-20250514" , max_tokens= 4096 , messages=[{ "role" : "user" , "content" : f "分析して: {hoge.content}" }], ) analysis_result = message.content[ 0 ].text # 3. 分析結果保存 save_analysis(db, hoge.id, analysis_result) # 4. レスポンス返却 return { "id" : hoge.id, "analysis" : analysis_result} やっていることは次の2つです。 LLM分析を行い完了後に分析結果を保存 フロントへデータを返す APIを呼び出してみると平均して30~40秒ほど時間がかかっていることが分かりました。 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7341 100 6673 100 668 193 19 0:00:35 0:00:34 0:00:01 2059 実行してから分析結果を見るのに30~40秒程度かかるほど、遅すぎて使いものにならない状態でした。 どのように対応を進めたか ストリーミング対応の設計 新たに作成したストリーミングのAPIは下記の通りです。 肝となる実装の全体像 ストリーミング対応したサンプルコードは下記になります。 @ router.post ( "/api/v1/hoge/analysis/streaming" ) async def create_hoge_analysis_streaming ( request: AnalysisRequest, db: Session = Depends(get_db), ): # 1. データ取得 hoge = get_hoge(db, request.hoge_id) # 2. LangChainエージェント作成 agent = ChatAnthropic( model= "claude-sonnet-4-20250514" , anthropic_api_key= "xxx" , max_tokens= 4096 , ) # 3. StreamingResponse返却 return StreamingResponse( generate_streaming_response(agent, hoge, db), media_type= "text/event-stream" , ) async def generate_streaming_response ( agent: ChatAnthropic, hoge: Hoge, db: Session, ) -> AsyncGenerator[ str , None ]: """SSE形式でストリーミングレスポンスを生成""" accumulated_content = "" messages = [HumanMessage(content=f "分析して: {hoge.content}" )] # チャンクごとに送信 async for chunk in agent.astream(messages): if chunk.content: accumulated_content += chunk.content data = json.dumps({ "type" : "content" , "content" : chunk.content}) yield f "data: {data} \n\n " # 完了後にDB保存 save_analysis(db, hoge.id, accumulated_content) # 完了イベント送信 data = json.dumps({ "type" : "complete" , "content" : accumulated_content}) yield f "data: {data} \n\n " やっていることは次の2つです。 分析結果がチャンクで返ってくるので、そのままフロントに渡す 分析完了後に分析結果を保存・フロントに返す どのように分析結果をチャンク(断片したテキスト)形式で受け取るのかについて説明します。 これは、LangChainのストリーミングメソッドを使用することで実現可能です。 LangChainの astream() メソッド async for chunk in agent.astream(messages): print (chunk.content) # "Find" → "y AI+" → "AI利活用" のように少しずつ届く astream() は非同期ジェネレータを返し、LLM APIからのレスポンスをチャンク単位で受信できます。 通常の invoke() との違いは全文が返らないことです。 # invoke(): 全文が返るまで待つ result = agent.invoke(messages) # 数秒〜数十秒ブロック # astream(): チャンクごとに即座に処理できる async for chunk in agent.astream(messages): # 即座に開始 process(chunk.content) FastAPIでのストリーミング実装 @ router.post ( "/api/v1/hoge/analysis/streaming" ) async def create_hoge_analysis_streaming (request: AnalysisRequest): hoge = get_hoge(request.hoge_id) agent = ChatAnthropic(model= "claude-sonnet-4-20250514" , ...) return StreamingResponse( generate_streaming_response(agent, hoge), media_type= "text/event-stream" , ) StreamingResponse に非同期ジェネレータを渡すことで、yield するたびにクライアントへデータが送信されます。 ストリーミングレスポンスの生成 async def generate_streaming_response (agent, hoge) -> AsyncGenerator[ str , None ]: accumulated_content = "" messages = [HumanMessage(content=f "分析して: {hoge.content}" )] # チャンクごとにフロントへ送信 async for chunk in agent.astream(messages): if chunk.content: accumulated_content += chunk.content data = json.dumps({ "type" : "content" , "content" : chunk.content}) yield f "data: {data} \n\n " # 完了後にDB保存 & 完了イベント送信 save_analysis(hoge.id, accumulated_content) data = json.dumps({ "type" : "complete" , "content" : accumulated_content}) yield f "data: {data} \n\n " accumulated_content で全文を蓄積しDB保存の準備を行います yield f"data: {data}\n\n" でSSE形式でフロントへ送信することでストリーミング対応を行います SSE(Server-Sent Events)の仕組み StreamingResponse で media_type="text/event-stream" を指定することで、SSE形式でデータを送信できます。 SSEでは data: {JSON}\n\n という形式でイベントを送信します。クライアントはこのイベントを受信するたびに画面を更新できるため、LLMの出力をリアルタイムで表示できます。 data: {"type": "content", "content": "Findy "}\n\n data: {"type": "content", "content": "AI+では"}\n\n data: {"type": "content", "content": "..."}\n\n data: {"type": "complete", "content": "Findy AI+では..."}\n\n フロントエンドでの受信処理 フロントエンドでは fetch の ReadableStream を使ってストリーミングデータを受信します。 const response = await fetch ( '/api/v1/hoge/analysis/streaming' , { method : 'POST' , body : JSON . stringify ( { hoge_id : 123 } ), } ); const reader = response. body .getReader(); const decoder = new TextDecoder (); while ( true ) { const { done , value } = await reader.read(); if (done) break ; const chunk = decoder. decode (value); // "data: {...}\n\n" 形式のイベントをパース const events = chunk. split ( ' \n\n ' ). filter ( e => e. startsWith ( 'data: ' )); for ( const event of events) { const data = JSON . parse (event. replace ( 'data: ' , '' )); if (data. type === 'content' ) { // チャンクを画面に追加表示 appendText(data.content); } else if (data. type === 'complete' ) { // 完了処理 } } } このように、サーバー側でチャンクを yield するたびにフロントエンドで受信・表示することで、ユーザーは分析結果をリアルタイムで確認できます。 ストリーミング対応後に得られた効果 画面遷移から3秒程度で読み始めることができるので非常に使い勝手が良くなりました。 おわりに ストリーミング対応をしたことで分析に使用するデータ量が多くても逐一分析結果が表示されるようになりました。 LangChainを使用したストリーミング対応について少しでも参考になれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらからご応募ください。 herp.careers
アバター
こんにちは、Findy Freelanceでフロントエンドエンジニアをしている主計(かずえ)です。 この記事は、 ファインディエンジニア #3 Advent Calendar 2025 の25日目の記事です。 adventar.org Dependabotが作成するPRの対応、皆さんはどのように運用していますか?依存パッケージの更新は地味ながら継続的に発生する作業で、特に少人数チームでは対応工数の比率が無視できません。 この記事では、私たちのチームがDependabot PR対応を手動運用からDevin、そしてClaude Code Actionへと段階的に改善してきた過程を紹介します。それぞれのアプローチで得られた知見と、最終的にClaude Code Actionに落ち着いた理由をお伝えします。 Dependabot PRの対応フローを効率化したい方、AIツールを活用したコードレビューの自動化に興味がある方の参考になれば幸いです。2025年の変遷を書いているのでDependabot PRのAIレビューをこれから実施したい場合はClaude Code Actionのセクションを中心に見ていただければと思います。 手動時代 フロー 課題 Devinへ移行 Playbookとは SlackからPlaybookを呼び出して実行 承認時 非承認時 良かった点 運用していく中で見えてきたこと Claude Code Actionへ移行 bot作成PRでは動作しないためClaude Code Base Actionを利用 allowed_botsでClaude Code Actionへ移行 各CI完了後にレビューを実施 現在のフロー 承認時 非承認時 効果 注意点 ANTHROPIC_API_KEYはDependabot用のSecretに設定 WebFetchの不安定さ まとめ 手動時代 フロー Dependabot PRへの対応は、次のような流れで行っていました。 Dependabotが作成したPRを確認する CIの実行結果を待ち、成功・失敗を確認する 更新されたパッケージのリリースノートを確認し、Breaking Changesがないか調べる CIが失敗している場合は原因を調査し、必要に応じてコードを修正する 問題がなければレビューを行う マージする 一見シンプルなフローですが、実際に運用してみると様々な課題があります。 課題 まず、コンテキストスイッチのコストが大きいという問題がありました。Dependabot PRを順番にマージしていくと、他のPRとコンフリクトが発生してrebaseが必要になります。CIの実行を待っている間に別の作業を始め、CIが完了したら戻ってきて次のPRを処理する、という流れで作業が細切れになりがちでした。 リリースノートの確認も手間のかかる作業でした。Breaking Changesは基本的にCIが失敗するので気付けますが、稀にruntimeで問題が発覚することがあります。そのため、念のためリリースノートを確認してからマージするようにしていました。 また、人によってマージの判断基準にズレがあるという問題もありました。あるメンバーはCIが通っていればすぐにマージし、別のメンバーはリリースノートを細かく確認してからマージするといった具合です。リリースノートを確認するというルールは作れば防げますが、どれくらい詳細に確認するかなど個人の感覚に依存してしまいます。 少人数チームでは、こうした定型作業の工数比率が相対的に高くなります。週に数時間をDependabot PR対応に費やしていると、本来注力すべき開発作業に割ける時間が減ってしまいます。 Devinへ移行 こうした課題を解決するため、導入済みだったDevinのPlaybookをDependabot PRのレビューに活用してみることにしました。 Playbookとは DevinにはPlaybookという機能があります。これは繰り返し行うタスクの手順を定義しておき、再利用できる仕組みです。「Dependabot PRをレビューする」というPlaybookを作成しておけば、毎回同じ手順でレビューを実行できます。 次のような形でPlaybookに記載して繰り返し利用しておりました。 SlackからPlaybookを呼び出して実行 DevinはSlackと連携できるため、Slackから直接Playbookを呼び出すことができます。 「@Devin playbook:!hoge」とメンションするだけで、定義したPlaybookが実行される仕組みです。 レビューが実施されると各PRにコメントを残してくれます。 承認時 非承認時 良かった点 Devinを導入して良かった点は、1つのアクションで各PRのレビュー依頼が完結することでした。Slackでメンションするだけでレビューが始まるため、Devinの作業が完了した後は、各PRについたレビューを確認し、マージするだけで済むようになりました。 運用していく中で見えてきたこと 複数のDependabot PRが同時に作成された場合、一部のPRが漏れてしまうケースがありました。また、すでにレビュー済みのPRを再度レビューしてしまうこともありました。 これらはDevin自体の問題ではなく、1回の依頼で複数PRをまとめて処理させていた運用方法に起因する課題でした。DevinにはAPIが提供されているため、GitHub ActionsからPRごとにDevin APIを呼び出す仕組みを作れば解決できる課題と考えました。 Claude Code Actionへ移行 GitHub ActionsからDevin APIを呼び出す仕組みの構築を検討していたところ、Claude Code Actionがリリースされました。 Claude Code Actionは、名前の通りGitHub Actions上でClaude Codeを実行できるActionです。PRの作成やコメントをトリガーにして、自動でコードレビューやタスクの実行ができます。 PRごとにワークフローが実行されるため、「このPRに対してレビューを行う」というスコープが明確になります。公式のGitHub Actionとして提供されていることと、AIモデルを選択できることが決め手となり、Claude Code Actionへ移行することとしました。 bot作成PRでは動作しないためClaude Code Base Actionを利用 導入当初、Claude Code ActionにはDependabotのようなbotが作成したPRでは実行できないという制約がありました。 この制約を回避するため、Claude Code Base Actionを利用することにしました。Base Actionはbot作成のPRでも動作させることができ、機能的にもClaude Code Actionと同等のことができます。 allowed_botsでClaude Code Actionへ移行 その後、Claude Code Actionに allowed_bots オプションが追加されました。これにより、Dependabotが作成したPRでもClaude Code Actionを実行できるようになりました。 Claude Code Base Actionからの移行を行った理由は、機能的な差はほとんどないものの、他のCIワークフローとの一貫性を保つためでした。チーム内で複数のActionを使い分けるよりも、統一した方がメンテナンス性が高くなります。 各CI完了後にレビューを実施 Claude Code Base Actionのワークフローはlint、test、typecheckなどのCIジョブが完了した後にClaude Code Base Actionを実行するようにしました。そうすることで、CIの結果を踏まえたレビューができます。 CIの流れは次のようなイメージです。 jobs: test: ...(省略)... lint: ...(省略)... typecheck: ...(省略)... claude-review-for-dependabot-pr: name: Claude Review for Dependabot PR # `always()`を指定しCIが失敗しても実行 if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && always() }} # 各CIの結果が欲しいので終了してから実行 needs: [test, lint, typecheck] ...(省略)... steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Claude Review for Dependabot PR uses: anthropics/claude-code-action@f0c8eb29807907de7f5412d04afceb5e24817127 # v1.0.23 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} github_token: ${{ github.token }} show_full_output: false #デバッグしたいときはshow_full_outputをtrueにして確認 allowed_bots: dependabot claude_args: | --allowedTools "View,GlobTool,GrepTool,BatchTool,Bash(gh auth status),Bash(gh pr view:*),Bash(gh run list:*),Bash(gh pr comment:*),Bash(gh pr review:*),Bash(gh pr diff:*),Bash(gh pr checks:*),Bash(gh run view:*),Bash(gh release view:*),Bash(git log:*),Bash(git status:*),Bash(git diff:*)" --model claude-opus-4-5-20251101 prompt: | (プロンプト例は下記に記載) プロンプト例 ## 命令 CI実行中のDependabotのプルリクエスト #${{ github.event.pull_request.number }} を評価しマージして問題ないか判断してください ## 手順 1. プルリクエストを確認(gh pr view ${{ github.event.pull_request.number }}) 2. package.jsonとpackage-lock.jsonの差分を確認 3. バージョン差分から公式リリースノートとGitHubのリリースを確認しライブラリの変更内容を把握(gh release view) 4. test, lint, typecheckの実行結果を確認(gh pr checks ${{ github.event.pull_request.number }}) 5. test, lint, typecheckが失敗していた場合、ログを確認(gh run view) 6. 既存コードや他ライブラリのバージョンとの整合性を確認 7. 変更内容を評価しフォーマットに沿ってプルリクエストにレビューコメント(日本語)を1件投稿 ## フォーマット ``` # {ライブラリ名} x.x.x -> x.x.x ## 評価結果 ✅ 承認 / ⚠️ 確認が必要 / ❌ 要対応 / etc... ## ライブラリの変更内容 - 変更内容1 - 変更内容2 ## リスク、注意事項 - リスク1 - リスク2 ## 必要な対応 - 対応1 - 対応2 ``` ## 注意事項 - 承認する場合:`gh pr review {プルリクエスト番号} --approve --body "{BODY}"` - 承認しない場合:`gh pr comment {プルリクエスト番号} --body "{BODY}"` - 実行時に足りない権限があった場合はコメント ## 追加確認項目 - Breaking Changesの有無 - セキュリティ脆弱性の修正状況 - 他の依存関係への影響 他のCIジョブの完了を待ってからActionを実行することで、CIが失敗している場合は「なぜ失敗したか」の分析をさせることができます。失敗ログから原因を特定し、次に取るべきアクションをPRコメントとして残すことができます。 対応すべきことがわかれば対応時の工数感がわかりすぐ取り掛かるかタスクとして積んでおくかの判断がしやすいです。 現在のフロー DependabotがPRを作成する lint、test、typecheckのCIジョブが実行される CIジョブ完了後、Claude Code Actionが実行される Claude Code Actionが更新内容の要約、リリースノートの重要ポイント、CI失敗時の原因分析と修正提案をPRコメントとして残す 人間がコメントを確認し、最終判断を行う 問題なければマージする 人間が行う作業は「Claude Code Actionのコメントを確認して最終判断する」ことに集中できるようになりました。 承認時 非承認時 効果 この改善により、Dependabot PR対応にかかる工数が週あたり約30分〜1時間削減されました。 削減される主な内訳としては、リリース内容の確認と対応要否の調査にかかる時間です。 必要な対応が出力されるのですぐ対応するかタスクとして積むかの判断がしやすくなったのは良かったと感じます。 また、レビューの観点がプロンプトで統一されているため、属人性が低下しました。誰が対応しても同じ基準でレビューが行われます。 コンテキストスイッチのコストも低下しました。コンフリクトしたPRは自動でrebaseと再レビューがされるため、自分の切りがいいタイミングでマージするだけで済むようになりました。 注意点 ANTHROPIC_API_KEYはDependabot用のSecretに設定 ANTHROPIC_API_KEY はGitHub ActionsのSecretsだけでなく、Dependabot側のSecretsにも設定する必要があります。Dependabotが作成したPRでは、通常のRepository Secretsにアクセスできないためです。 設定場所は https://github.com/{Org}/{Repo}/settings/secrets/dependabot です。これを忘れると、Dependabot PRでClaude Code Actionが動作しません。 WebFetchの不安定さ 当初、リリースノートの取得にWebFetch機能を使っていましたが、フリーズすることがありました。(2025年11月ごろ) 対策として、外部情報の取得は gh コマンドを使う方針に変更しました。GitHub CLIを使ってリリース情報を取得する方が安定性と再現性が高く、トラブルが減りました。 Claude Code側でWebFetchがフリーズするissueがいくつかあります。 show_full_output を有効化してもログが表示されないため直接的な原因は掴めていませんが、現状では gh コマンドで必要な情報は取得できているので allowedTools から WebFetch は一時的に除外しています。 github.com まとめ Dependabot PR対応を手動運用からDevin、そしてClaude Code Actionへと改善してきた過程を紹介しました。 定期的に発生する作業は自動化すると効果が大きいです。特にDependabot PRのような「PRごとに自動でトリガーされる」タイプのタスクには、GitHub Actionsと連携するClaude Code Actionが適していました。 今後の課題としては、Claude Code ActionがApproveしたPRを自動マージする仕組みの導入を検討しています。現在nxを利用したモノレポで運用しており、ユニットテストやVRTは各アプリで整備できています。ただし、管理画面など一部のアプリではE2Eテストが未整備のため、まだ自動マージには踏み切れていません。E2Eテストを拡充し、自動マージしても安全という確信を持てる体制を整えていきたいと考えています。 上記のように、AIのガードレール整備が重要なのでテスト等をしっかりやっていくことは今後さらに重要になってくると再認識しました。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
この記事は「 ファインディエンジニア #1 Advent Calendar 2025 」の24日目の記事です。 沢山のアドベントカレンダー記事が執筆されていますので、年末のお供に是非読んでみてください。 adventar.org はじめに ソフトウェアエンジニアの 土屋(@shunsock) です。私の所属するデータソリューションチームでは、ファインディ全体のデータ活用を推進するためのデータ基盤を構築しています。 今回、我々はデータ基盤のRDSとBigQueryのテーブル同期システム (EL Pipeline) のリプレースを行い、 DuckDBを本番導入 しました。本稿では、活用に至った経緯と実際に組みこむにあたる課題、および成果を紹介します。 はじめに ファインディにおけるテーブル同期システムの立ち位置 リプレイスの背景 補足 技術選定 Datastream DuckDB Datastream, DuckDB両採用の理由 システム設計 概要 CLIを挟む理由 GitHub Actionsからの起動にした理由 複数のRDSを転送する 開発運用と成果 開発・運用してみた感想 可読性と拡張性が高い とはいえまだまだ新興のソフトウェア まとめ ファインディにおけるテーブル同期システムの立ち位置 ファインディでは、ウェブアプリケーションをAWS上のECSとRDS、データ基盤をGoogle CloudのBigQueryで作成しています。 このような構成を取っているため、AWSのRDSとGoogle CloudのBigQueryを同期してテーブルを最新にする必要があります。 次の図は、Findy Tools事業部における、現在のデータフローの概念図です。AWS上に存在するRDSのデータをBigQueryに転送していることが分かります。 リプレイスの背景 弊社では従来、OSSのEL(Extract Load) ツール  Embulk  をECSに載せて長期間運用していました。弊社で利用しているRDBMSやデータウェアハウスに対応している他、社内に知見を持った方が在籍しているためです。 しかし、近年では、 Embulkのエコシステムのレガシー化や 長期的なメンテナが不足 が課題 となっています。特に、 将来のメンテナンスが不透明な点は、セキュリティインシデントに繋がりかねない ため危惧していました。 また、 Embulkの起動の遅さも課題 にしていました。我々はBigQueryプラグインなどを利用していたため、JVM上でさらにJRuby VMを立ちあげます。このような構成は テーブル同期の遅さに繋がり、ECSの課金額を増やす要因 となっていました。 このように、システムを堅牢にすることと処理スピード向上による料金のコストダウンが今回のプロジェクトの目的でした。 補足 Embulkのメンテナーの方も 「オープンソース・プロジェクトのたたみ方」 というブログ記事で脆弱性について次のように述べています。 おそらくいくつかの攻撃は既に成功していて、私たちのソフトウェア・サプライチェーンには、悪意のあるコードがとっくに入り込んでいる、と認識しておくべきでしょう。 技術選定 Datastream, Spark, その他 ELTツールなど、複数の移行先候補がありました。その中で、データ規模に応じて次の2つから選定することにしました。 Datastream: ニアリアルタイムでの更新が欲しい場合や大規模データの場合 DuckDB: 小規模データの場合 Datastream Datastream は Google Cloudが提供するサーバーレスのCDC (Change Data Capture), Replicationツールです。 CDCは、あるソースのシステムを監視し、そのシステムに対する操作をニアリアルタイムで、ターゲットとなるシステムに反映する仕組みのことです。これによりAWSのRDSに対する変更を即座にBigQueryに反映可能です。 DuckDB DuckDB は高速なアナリティカルデータベースです。s3などのストレージサービスに出力されたログ分析やファイルフォーマットの変換、wasmによるフロントエンドでの活用など広い用途で活用されています。 接続先や出力フォーマットが非常に豊富な他、C++製のマルチスレッドランタイムにより、高速に動作する点が魅力です。 次の写真はDuckDBのPoC時に行なったベンチマークです。小さなテーブルで転送を試したところ、 1.5倍程度の高速でした 。 ソフトウェア名称 平均 標準偏差 最速 最遅 Embulk 253秒 8秒 242秒 261秒 DuckBD 176秒 30秒 137秒 209秒 補足: 実際にパフォーマンステストを行ったときの様子 Datastream, DuckDB両採用の理由 今回のリプレイスでは、コスト最適化を軸に Datastream と DuckDB の2種類のアプローチを使い分ける構成を採用しました。 DatastreamはフルマネージドでサーバーレスなCDCサービスと強力です。一方で、ニアリアルタイム性が不要な小規模データに対しては機能過多となり、費用面でも割高になります。そこで、リアルタイム性を求めない領域では、より軽量でシンプルに扱えるDuckDBを使って同期を行う方針を取りました。 本記事の以降では、上記のうち、DuckDBによってどのようにテーブル同期システムを構築したか、開発運用で見えた知見を説明します。 システム設計 概要 次の画像は我々のDuckDBによるテーブル同期システムの概念図です。 次のように各種ソフトウェアが起動します。 GitHub Actionsの on_schedule でワークフローが起動 ワークフローがECS Fartate Taskを起動 Fargate Taskがコンテナランタイムを起動 コンテナランタイムの中でCLIアプリケーションが起動 CLIアプリケーションが引数と設定ファイルからSQLを生成 CLIアプリケーションがDuckDBでSQLを実行 CLIを挟む理由 DuckDBを直接起動しない理由は、1回の実行で1テーブルずつ送信できるようにするためと、SQLを直接書かずに設定ファイルをインターフェースにするためです。 実際のユーザーの入力インターフェースは次のようなYAMLです。 dataset_id : lake... table_name : table_name select_statement : "hoge, fuga, ..." GitHub Actionsからの起動にした理由 元々のワークフローはEventBridge Schedulerだったのですが、システム障害時にEventBridgeのcronを変更するなど運用負荷が重い状態でした。 DispatcherをGitHub Actionsにすることでボタン操作だけで検証可能にしました。 また、1テーブルずつの送信にしたので、ステージング環境での動作検証も簡単かつ軽量です。ユーザーは次のようなWorkflow Dispatchを起動するだけで動作検証が完了します。 複数のRDSを転送する 現在のFindy Tools事業部のワークフローを見ると分かる通り、複数のRDSを転送する必要がありました。そこで開発用スクリプトを汎用化して動的なビルドやawsコマンドの発火をしています。 開発運用と成果 開発は、私1人で1か月弱でしました。最初の1プロジェクトこそ時間がかかったものの、モノレポ構成にしたおかげで 従来1か月かかった新規データソースの追加が1週間程度になりました。 処理速度については、直列稼動から並列稼動へ変更となったため単純な比較は難しいのですが、 1テーブルあたり約30秒から約10秒に短縮 できました。 すでに他のメンバーからもプルリクエストが届いており、社内でも手応えのある反応を得ています。 開発・運用してみた感想 可読性と拡張性が高い 今回作成したCLIでは次のようなSQLを生成しています。高い拡張性や可読性が良いと改めて感じました。 INSTALL mysql; LOAD mysql; ATTACH '' AS mysqldb ( TYPE mysql); -- 環境変数から取ってくる CREATE TABLE users AS SELECT * FROM mysqldb.table_name; INSTALL bigquery FROM community; LOAD bigquery; ATTACH '' as bq ( TYPE bigquery); DROP TABLE IF EXISTS bq.lake__system_name.table_name; CREATE TABLE bq.lake__system_name.table_name AS SELECT * FROM table_name; DROP TABLE table_name; 拡張についても、次のCore Extensionsの他にCommunity Extensionsがあります。DB以外にもSpreadSheetなど幅広いツールが対応しているので、興味を持った方は確認してみると良いと思います。 duckdb.org とはいえまだまだ新興のソフトウェア DuckDBは新興のソフトウェアということもあり、普通にバグがあったりします。例えば次のIssueは、私がDuckDBのMySQLのプラグインのATTACH句に存在したバグを報告したものです。(既に解決済みです) github.com また、拡張によっては、サポートしているOSが限られていることがあります。私が作成した時期では、BigQuery拡張でarm64 linuxがサポートされておらず、Fargateをamd64で立てていました。なお、こちらも現在は対応しているようです。 github.com まとめ 今回の取り組みで、我々の テーブル同期システムはより高速、堅牢になりました。 さらに、ユーザーインターフェースが洗練され、 チームメンバーの利用しやすいソフトウェアとなりました。 データソリューションチームでは一緒に事業部横断データ基盤を作る仲間を募集しています。気になる方は是非次のフォームからカジュアル面談に応募してみてください!! herp.careers
アバター
こんにちは。 2025 年 9 月にファインディに入社し、 Platform 開発チームで SRE を担当している富田( @Cooking_ENG )です。 この記事は、 ファインディエンジニア #2 Advent Calendar 2025 の 23 日目の記事になります。 adventar.org 今回は、ファインディのサービスの1つである「 Findy Conference 」の インフラ環境の運用トイル を改善した話を紹介します。 Findy Conference とは Findy Conference とは、テックカンファレンスに特化したプラットフォームサービスです。 国内外のカンファレンスに関する情報・体験を一元化し、主催者・参加者・スポンサーをつなぐことで、テックカンファレンスの体験を最大化することを目指します。 参加者は関心のあるイベント情報や CFP(発表募集)、イベントのタイムテーブルを見逃さずに把握でき、主催者は集客や受付管理、データ活用といった運営にかかるコスト・工数を最小化できるようになります。 conference.findy-code.io Findy Conference のトラフィックの特徴 Findy Conference のトラフィックには、一般的な Web サービスとは異なる、カンファレンス特有の 瞬間的なスパイク が多く発生するという特徴があります。 特にスパイクが起こりやすいタイミングは次の 2 点でした。 受付が始まったタイミング セッションの始まりと終わりのタイミング このうち、特に負荷が高かったのが セッションの始まりと終わりのタイミング です。 原因は次のような、 オンライン配信におけるカンファレンス参加者の方々の動き によって起こるものでした。 セッション中は参加者の方々は配信セッションを視聴しているため、Findy Conference のポータルサイトなどにアクセスすることは少ない。 セッションが終了するタイミングで、次のセッションの配信場所やチャンネル切り替えを行うため、セッションを視聴していた方々が一斉に Findy Conference のポータルサイトにアクセス。 その結果、一気にアクセスが集中し、スパイクが発生! この一連の流れにより、インフラに瞬間的な高負荷がかかっていました。 オートスケールが発動しない Findy Conference の環境は Amazon ECS と AWS Fargate (以降 ECS/Fargate) を使って構築しています。 ECS/Fargate であれば、オートスケールが発動するのではないか?という疑問を持つ方もいらっしゃると思います。実際に、Findy Conference の環境でも、CPU 使用率が設定している閾値を超えたらオートスケールが発動するように設定していました。 しかし、実際の運用では CPU 使用率が設定している閾値を超えてもオートスケールが発動せず、高負荷時にユーザー体験を維持できないリスクが生じていました。 オートスケールが発動しなかった原因は「アクセス集中が瞬間的すぎる」という点にありました。 短時間の高トラフィック・スパイクにより、オートスケールが発動に必要な時間を満たせず、新しいコンテナが立ち上がる前に CPU 使用率が下がってしまう Fargate の起動が少し遅いという特性も影響 結果として、カンファレンス中に上記のような瞬間的な高負荷がかかっても、 コンテナ数はスケールせず終わってしまう という状況でした。 (参考までに、こちらは過去のオブザーバビリティカンファレンスでの CPU グラフです。同時刻にオートスケールが発動していないことがわかります。) これまでのカンファレンス開催時の SRE の対応 上記の問題を回避するため、以前は「カンファレンス開催前に、Platform 開発チーム SRE メンバー(以降、SRE チーム)が AWS の Production 環境に入り、手動でコンテナ数を増やし、カンファレンス終了後にコンテナ数を元に戻す」という対応をしていました。 スパイク時の対策としては、当時はコンテナ台数を増やす以外に現実的な選択肢がなく、人手によるスケール対応に頼らざるを得ない状況でした。 この手動オペレーションは、次のようなトイルを生み出していました。 カンファレンス運営の方との連携が必須: カンファレンスが開催される日程共有の段階でコミュニケーションミスが発生した場合、急いで対応する必要がある。 ペアオペ作業のため 2 人分の工数が発生する: Production 環境で作業をするセンシティブな作業のため、ペアオペが必須となり、2 人分の時間が取られる。 複数環境の調整: フロントエンドとバックエンドなど、複数の環境で調整が必要なため、作業量、作業時間が多くなる。 オペレーション・リスク: そもそも Production 環境を手作業で触るので、作業ミスが発生するリスクがある。 実際、最近開催されたアーキテクチャカンファレンスでは、関連する複数環境のコンテナ調整に 2 時間近く要してしまいました。 カンファレンスが開催されるたびに、この手動作業の負荷が大きいと考え、トイルを抜本的に改善する必要があると判断しました。 GitHub Actions の workflow と AWS CLI で自動化 このトイルを撲滅すべく SRE 以外でも素早くコンテナ調整をできるようにするために、今回は AWS CLI と GitHub Actions の workflow_dispatch を組み合わせて、Production のマネジメントコンソールに入らなくても GitHub 上からコンテナ数を調整できるようにしました。 これにより、必要な権限を持ったユーザーが、安全かつ簡単にコンテナ調整を行えるようになりました。 コードの全体像 以下が、コンテナ数をスケールさせるための GitHub Actions のワークフロー全体像です。 scale-containers.yml name : Scale Containers run-name : Conference Scale Containers to ${{ github.event.inputs.container_count }} in ${{ github.event.inputs.environment }} on : workflow_dispatch : inputs : environment : type : environment required : true default : staging container_count : description : "containers_count" type : choice required : true options : - xx - yy - zz permissions : id-token : write contents : read jobs : scale-containers : runs-on : ubuntu-slim environment : ${{ github.event.inputs.environment }} steps : - uses : actions/checkout@v5 with : fetch-depth : 0 token : ${{ secrets.GITHUB_TOKEN }} - name : Configure AWS credentials uses : aws-actions/configure-aws-credentials@v5 with : role-to-assume : ${{ secrets.AWS_ROLE_ARN }} aws-region : ap-northeast-1 - name : Scale Backend ECS containers run : | CLUSTER_NAME="backend-${{ github.event.inputs.environment }} " SERVICE_NAME=" backend-${{ github.event.inputs.environment }} " echo "🔄 Scaling Backend containers to ${{ github.event.inputs.container_count }}" # 1. ECSサービスのDesired Countを更新 aws ecs update-service \ --cluster "$CLUSTER_NAME" \ --service "$SERVICE_NAME" \ --desired-count ${{ github.event.inputs.container_count }} # 2. オートスケールの最小キャパシティもワークフローでの設定値に合わせる aws application-autoscaling register-scalable-target \ --service-namespace ecs \ --scalable-dimension ecs:service:DesiredCount \ --resource-id "service/$CLUSTER_NAME/$SERVICE_NAME" \ --min-capacity ${{ github.event.inputs.container_count }} \ --max-capacity [ xx ] echo "✅ Backend containers scaled successfully" - name : Scale Frontend ECS containers run : | CLUSTER_NAME="frontend-${{ github.event.inputs.environment }} " SERVICE_NAME=" frontend-${{ github.event.inputs.environment }} " echo "🔄 Scaling Frontend containers to ${{ github.event.inputs.container_count }}" aws ecs update-service \ --cluster "$CLUSTER_NAME" \ --service "$SERVICE_NAME" \ --desired-count ${{ github.event.inputs.container_count }} aws application-autoscaling register-scalable-target \ --service-namespace ecs \ --scalable-dimension ecs:service:DesiredCount \ --resource-id "service/$CLUSTER_NAME/$SERVICE_NAME" \ --min-capacity ${{ github.event.inputs.container_count }} \ --max-capacity [ xx ] echo "✅ Frontend containers scaled successfully" ※実際のワークフローの画面です。 ワークフローの実装ポイント workflow_dispatch による手動実行 inputs で environment(環境名)と container_count(コンテナ数)を入力値として受け付けます。 container_count は choice にすることで、設定可能な値に制限を設け、誤入力を防いでいます。 コンテナ数と同時に最小コンテナ数の設定値も合わせる aws application-autoscaling register-scalable-target を実行し、オートスケールの --min-capacity もワークフローでの設定値に合わせるようにしています。この設定はコンテナ数を増やしても、オートスケールが最小キャパシティまでコンテナ数を減らしてしまう可能性を防ぐためです。 本ワークフローの導入により、Findy Conference のコンテナ調整は、誰でも GitHub Actions の画面から数クリックで実行できるようになり、SRE チームの負荷が軽減されました。また、既にカンファレンス開催に関わる複数の環境全てに横展開を完了しています。 この改善によって、SRE チームが約 2 時間かけて行っていたペアオペ作業は解消されました。 加えて、手動オペレーションのリスクも排除され、 必要な権限を持った開発者やカンファレンス担当者が安全にコンテナ調整を行える運用体制 を整えることができました。 おわりに 今回は Findy Conference のスパイクの起こりやすいトラフィック課題に対して、GitHub Actions と AWS CLI を用いて運用オペレーションを自動化・トイル削減した事例をご紹介しました。 トイル削減は SRE の永遠のテーマですが、エンジニアが気持ちよく開発に取り組める環境づくりや、安心して運用できる体制に繋がるため、これからも積極的に進めていきたいと思います。 最後までお読みいただきありがとうございました! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。 ファインディ株式会社でFindy AI+の開発をしているdanです。 今回は、プロンプトにどのようなデータや指示内容を与えるとLLMが誤った出力をしやすいのかについてお話しします。 プロンプトには何を書くべきで、何を書かないべきなのか。また、LLMに渡すデータはどのような形であるべきなのか。私自身が経験した実際の例をあげて解消までのアプローチ方法をご紹介します。 分析の精度をあげるにはここで紹介する内容では不十分ですが、入門編として参考になれば幸いです。 この記事はファインディエンジニア #3 Advent Calendar 2025 23日目の記事です。今月から、たくさんのアドベントカレンダー記事が執筆される予定ですので、ぜひ読んでみてください。 adventar.org Findy AI+とは 誤解していたプロンプト調整 良くない手法1: システムプロンプトにUTCから日本時間に変換する指示を与える 良くない手法2: 分析に使用するデータを加工する指示をシステムプロンプトに与える あるべき手法 システムプロンプトはどのような振る舞いで分析をしてほしいのかを書く 分析に使用するデータを加工してからLLMに渡す おわりに Findy AI+とは Findy AI+ は、GitHub連携やプロンプト指示を通じて生成AIアクティビティを可視化し、生成AIの利活用向上を支援するサービスです。 人と生成AIの協働を後押しし、開発組織の変革をサポートします。 Claude Code、GitHub Copilot、Codex、Devinなど様々なAIツールの利活用を横断的に分析しており、分析基盤にはLangChainを採用しています。また、日報やチーム分析などの機能でもLLMを活用しています。 こうした特性から、Findy AI+ では「何をどう分析するか」を定義するためのプロンプトが、サービスの価値を左右する重要な要素となります。 誤解していたプロンプト調整 良くない手法1: システムプロンプトにUTCから日本時間に変換する指示を与える 初期のシステムプロンプトは次の通りです。 # System Prompt ## Overview You are expert of developer experience and developer productivity. Your Timezone is Asia/Tokyo (UTC+9). Your Language is Japanese. The Timezone for the creation datetime of the Pull request is UTC. 上記はすごくシンプルなシステムプロンプトです。 このコードでは次のことを書いています。 LLMがどのような役割を担うのか タイムゾーンはどこを使用するのか どの言語で出力するのか プルリクエストの作成日時がUTCであること このシステムプロンプトを使用してプロダクトから分析ツールを実行すると次のような出力結果になりました。 システムプロンプトには使用してほしいタイムゾーンがUTC+9(日本時間)であることと、LLM分析に使用するデータはUTCであることを明記しています。 その結果、LLMは分析中に与えられたUTCのデータをJSTに変換する推論処理を行う必要があり、意図しない日付のズレが発生しました。 良くない手法2: 分析に使用するデータを加工する指示をシステムプロンプトに与える ユーザーからの自由入力による追加分析を行うと実際とは異なる日時が分析結果として返ってきました。 そのため次のようにシステムプロンプトを調整しました。 # System Prompt ## Overview You are expert of developer experience and developer productivity. ## Current Date Today's date is {current _ date} (YYYY-MM-DD format in UTC timezone). When you see dates in the data provided, interpret them according to this current date. For example, if today is 2025-10-08 and the data shows "2025-10-06 to 2025-10-12", this is the current week, not a future or past week. Your Timezone is Asia/Tokyo (UTC+9). Your Language is Japanese. The Timezone for the creation datetime of the Pull request is UTC. このコードでは次のことを書いています。 LLMがどのような役割を担うのか 現在日時の明記 現在日時は明記されたものを使用し過去を参照しないこと タイムゾーンはどこを使用するのか どの言語で出力するのか プルリクエストの作成日時がUTCであること このシステムプロンプトを使用してPRの分析を行った後、「日曜日に稼働したりしてないよね?」と追加で質問しました。LLMはGitの活動ログから曜日を判定して回答しますが、次のような出力結果になりました。 実際の曜日とLLMが出力した曜日を比較すると、2025年11月17日は月曜日ですが日曜日で出力されてしまっていることが分かります。 システムプロンプトに現在日時の明記と過去を参照しない旨を明記しています。 また期間指定の範囲についても具体的に指示しています。 その結果LLMは現実と過去について言及されている部分で混乱し、誤った推論による出力ミスが起きてしまいました。 あるべき手法 システムプロンプトはどのような振る舞いで分析をしてほしいのかを書く システムプロンプトにデータの加工、時間変換など処理の具体的な内容を書いてしまうと上記で紹介したような誤った推論を誘発してしまう可能性が高いです。 そのため、役割・言語・フォーマットなどシンプルな内容で最低限のみ書くのが良いです。 最終的には次のようなシンプルなシステムプロンプトになりました。 # System Prompt ## Overview You are expert of developer experience and developer productivity. ## Current DateTime Current datetime is {current _ datetime _ jst} ## Important Rules - When data includes weekday information (e.g., "月曜日", "火曜日"), use it as-is. Do NOT recalculate weekdays yourself. Your Language is Japanese. このコードでは次のことを書いています。 LLMがどのような役割を担うのか 現在日時は変換済みのJSTで渡す 渡されたデータをそのまま使うよう指示する どの言語で出力するのか 分析に使用するデータを加工してからLLMに渡す 分析に使用するデータは、システムプロンプトへ渡す前に加工済みのものを用意した方が良いです。 システムプロンプトにUTCからUTC+9(日本時間)の変換をするように書くべきではありません。 LLMに渡すデータは変換済みのデータにしておきましょう。 例えば、PRのデータをLLMに渡す場合を見てみましょう。 GitHubのPR情報をAPIから取得する場合、日時に関するレスポンスはUTCで返ってきます。 次の手順で、LLMに渡すデータを変換し分析を行います。 ・GitHubのAPIから取得したPR作成日時をUTCからUTC+9(日本時間)に変換する def format_datetime_jst (pr_utc_datetime: str ) -> str : # UTCの日時文字列をJSTに変換 utc_dt = datetime.fromisoformat(pr_utc_datetime.replace( "Z" , "+00:00" )) jst_dt = utc_dt.astimezone(JST) # 曜日も付与してフォーマット weekday_jp = WEEKDAYS_JP[jst_dt.weekday()] return jst_dt.strftime(f "%Y/%m/%d ({weekday_jp}) %H:%M:%S UTC+9" ) # 実行例 format_datetime_jst( "2025-11-17T08:53:32Z" ) # => "2025/11/17 (月曜日) 17:53:32 UTC+9" ・変換したデータを分析コンテンツに格納する analysis_content = f """ # Pull Request Analysis - PR1 Created: {format_datetime_jst(pr1.get("created_at", ""))} - PR2 Created: {format_datetime_jst(pr2.get("created_at", ""))} - PR3 Created: {format_datetime_jst(pr3.get("created_at", ""))} """ ・分析コンテンツを使用してLLMに分析を依頼する llm.invoke([ # 「システムプロンプトはどのような振る舞いで分析をしてほしいのかを書く」で紹介したシステムプロンプト { "role" : "system" , "content" : system_prompt}, { "role" : "user" , "content" : analysis_content} ]) このように変換済みのデータをLLMに渡すことで、LLMが日時の計算や曜日の判定を行う必要がなくなり、誤った出力を防ぐことができます。 おわりに 今回は、LLMにデータ加工や時間変換を任せると誤った推論を誘発しやすいことをご紹介しました。システムプロンプトには役割や出力形式などシンプルな指示のみを書き、データはあらかじめ加工してから渡すことで、分析精度を向上させることができます。 プロンプトの書き方ひとつでLLMの出力は大きく変わります。この記事が、皆さんのLLM活用の参考になれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらからご応募ください。 herp.careers
アバター
こんにちは。ファインディのTeam+開発部でエンジニアをしている古田(ryu-furuta)です。 この記事は、 ファインディエンジニア #2 Advent Calendar 2025 の22日目の記事です。 はじめに 2025年下期、私は「DevとOpsを融合する」というミッションを掲げ、問い合わせやアラートといった運用業務の改善にAIをいくつか活用していきました。 この記事では、Claude Code GitHub ActionsやNotion MCPを使った運用業務改善の具体的な実装方法を紹介します。 また、効率化を実現した先に見えてきた「次にやるべきこと」についても共有します。 AIを活用した運用改善を検討している方や、改善施策を打っても成果が出ないと悩んでいる方に読んでいただけると幸いです。 はじめに 問い合わせやアラートに生じていた課題 Claude Code GitHub Actionsでアラートの初期調査コストを削減 Notionのデータベースで問い合わせのチケット管理とデータ蓄積 Notion MCPを使って過去事例の検索と自動調査 取り組みの成果 今後の取り組み:根本原因の特定と改善の仕組みづくり まとめ 問い合わせやアラートに生じていた課題 私が携わる Findy Team+ はエンジニア増加による開発チームの細分化・多数の機能リリース・連携するサービスの増加といった変化の中にあります。これにより、問い合わせやアラートなどの機能開発以外の運用業務でも複数の課題が生じていました。 問い合わせ/アラートの数が増加して機能開発のボトルネックになっている 問い合わせ/アラートに関連した機能・実装のコンテキストを知らないため調査コストが高い 問い合わせのやりとりは Slack のスレッドで行っているためステータスが分かりにくい 問い合わせのデータが蓄積されないため対策や将来の改善に活かせない こういった課題を解消すべくAIやツールを活用した改善をこの2025年下期で取り組みました。 Claude Code GitHub Actionsでアラートの初期調査コストを削減 アラート通知はこのようにSentryを経由してSlackへ通知されます。 これだけを見てもどういったエラーでどこで発生したのか分かりません。 そのため従来はSentryのイシュー詳細に遷移し、スタックトレースを確認したり、そこからエディタで関連コードを調査したり、まず 状況把握をするための初期調査コストが高い という問題がありました。 この問題の改善に用いたのが Claude Code GitHub Actions です。 Claude Code GitHub Actionsは、GitHub ActionsのワークフローからClaude Codeを呼び出せる機能です。 SentryからGitHubのイシューを作成したら自動で次のようなプロンプトのコメントをClaudeにメンションします。 このissueのdescriptionに当リポジトリで発生したエラーが記述されています。 このissueのdescriptionにはSentryのissueのIDが記載されています。 mcp__sentry__get_sentry_issueで記載されたIDのissueの詳細情報を取得してください。 mcp__sentry__get_sentry_issueで取得した結果やエラー発生箇所・周辺ファイルを閲覧し、エラーの発生原因の調査結果をissueのコメントに記載してください。 可能であれば修正対応のプルリクエストを作成してください。 プルリクエストを作成する際は次の3ステップで実行してください: - エラーに対する初期の対応案(ドラフト)を作成してください。 - そのドラフトに対して、どこが良くてどこが改善できるかをレビューしてください。 - レビュー結果をふまえて、より良い最終的な対応案を提示してください。 これによってClaude Code GitHub Actionsが起動し、自動でエラー発生箇所の周辺調査や状況整理、うまく噛み合えばClaudeが作ったプルリクエストをマージするだけで対応が完了する時もあります。 ▼実際にClaudeが作成したコメント例 この取り組みによって アラート発生時の初期調査コストを削減 することができました。ケースによっては数時間かかっていた調査が数分で状況把握できるようになり、調査開始までの心理的ハードルも下がっています。 Notionのデータベースで問い合わせのチケット管理とデータ蓄積 前述したようにFindy Team+では数年間に渡ってSlackワークフローでの問い合わせ起票を行ってきました。 問い合わせのコミュニケーションに関してはSlackで過不足無いのですが、複数問い合わせが並行するとやりとりを追うのが大変だったり、現在のタスクの状況が分からなくなる問題が度々発生していました。 また問い合わせはプロダクトの改善に繋がる貴重な情報なのにそのデータが蓄積されずフィードバックループを回すことが出来ない、というのも大きな課題でした。 これを一気に解消したのが Notion のデータベースです。 Slackのワークフローでの問い合わせ起票を全て Notion Form に移行し、フォーム送信と同時に問い合わせの情報がデータベースに蓄積されるようになりました。 またデータベースでもチケット管理を行うようにしました。 対応期限のカラムやいわゆる「To Do」「In Progress」「Done」といった値を持ったステータスのカラムを用意し、 Zapier を使ってリマインドの機構を設けました。 例えば対応期限を超過してもステータスが「Done」になっていない場合、Slackで担当者へリマインド通知を飛ばすといった自動化も行いました。 ▼対応期限超過のリマインドメッセージ Notionのデータベースを用いることでステータス管理や情報の蓄積が可能になり、問い合わせが抱えていた複数の課題を一気に解消することができました。 また、データが蓄積されることで次に紹介する取り組みにも繋がりました。 Notion MCPを使って過去事例の検索と自動調査 問い合わせ起票時には起票するメンバーに問い合わせに関連した「画面機能」「連携サービス」「メトリクス」といった情報をデータベースに入力してもらうようにしています。 さらに問い合わせの対応が完了したらLLMに問い合わせのやりとりを要約してもらい、その内容もデータベースに保存しています。 これにより半自動的に問い合わせについての情報を拡充していくことができています。 そしてアプリケーションのリポジトリに次の内容のClaude Codeのスラッシュコマンドを作成しました。 --- description : Notion上の問い合わせDBから類似の問い合わせを検索し、原因を調査する --- - $ARGUMENTSは `collection://***` の問い合わせデータベースの中の問い合わせ(ページ)です。 - notion-fetchを使って $ARGUMENTS の問い合わせ内容を確認してください。 - $ARGUMENTS の問い合わせと類似の過去の問い合わせを `collection://***` のデータベースから検索してください。 - 検索の際は`summary`,`detail`,`tag`の各プロパティから類似の問い合わせを検索してください。 - この検索結果から $ARGUMENTS の問い合わせを当リポジトリのコードから調査してください。 - 最終的に次の結果を出力してください。 1. 類似の問い合わせが見つかったかどうか 2. 類似の問い合わせが見つかった場合、その問い合わせIDと概要(summary) 3. $ARGUMENTS の問い合わせの原因調査結果 このスラッシュコマンドは内部で Notion MCP のtoolを利用しています。 これにより過去の問い合わせ情報というコンテキストを持ちながらClaude Codeがより詳細にコード情報を調査することを可能にしています。 出力サンプルを本記事に掲載したいところですが、あまりにも詳細に情報を出力しすぎてしまうため残念ながらここでの掲載は控えさせていただきます。 ただ私自身何度かこのスラッシュコマンドを問い合わせに実行してみて過去に類似問い合わせがあると問い合わせの要因等をかなり詳細に調査してくれることを確認しています。 また過去に類似問い合わせが無いとしても、問い合わせに関連した周辺処理の概況を説明してくれるので全くコンテキストを把握していない機能の問い合わせの調査コストを軽減できていると感じています。 取り組みの成果 今回紹介した取り組みにより、次のような成果を得ることができました。 問い合わせやアラートの状況が可視化され、分析可能な基盤が整った AIによる初期調査で調査の効率化が実現し、状況把握までの時間を大幅に短縮できた チケット管理によりステータスが明確になり、対応漏れを防げるようになった 一方で、可視化や効率化を行うだけでは問い合わせやアラートの件数自体は減少しませんでした。 機能開発が進み、利用者数も増加している中での自然な傾向でもあります。 可視化や効率化は部分的に対応コストを下げるものであり、それだけでは件数を減らす根本的な解決にはなりません。 今後の取り組み:根本原因の特定と改善の仕組みづくり 蓄積された問い合わせデータやアラート傾向を分析し、頻出する問題の根本原因を特定していきます。 暫定対処ではなく恒久対応を行うことで、問い合わせやアラートの件数自体を減らすことを目指します。 たとえば、問い合わせデータを「画面機能」や「連携サービス」ごとに集計し、特定の領域に問い合わせが集中していないかを可視化します。 集中している領域があればUIの改善やドキュメントの拡充、場合によっては機能自体の見直しを検討します。 また、これまでは改善活動に対する明確な行動指針がなく、暫定対処に留まりがちでした。 今後はインセンティブの設計をしっかり行い、改善活動が継続して実施される仕組みを作ります。 具体的には、来期から私も機能開発チームに合流し、改善対応もミッションの一部として進めていきます。 運用業務の当事者として改善に取り組むことで、フィードバックループを確実に回していきます。 まとめ 2025年下期開始当初、自分は昨今のAIの潮流もあって「AIがあれば運用業務の全てを改善できる!」と意気込んでいました。 実際に取り組んだ結果、AIやツールを活用していくらかの問い合わせやアラート対応の「可視化」と「効率化」を実現しました。 しかしこれらは対応を効率化するものであり、件数を減らす根本解決ではありません。今後は蓄積したデータを活用して恒久対応に繋げ、問い合わせやアラートの根本原因を取り除いていきます。 引き続きAIを活用しつつ、改善活動が継続する仕組みを作りながら本質的な改善に挑戦していきます! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
この記事は、 ファインディエンジニア #3 Advent Calendar 2025 の22日目の記事です。 adventar.org はじめに こんにちは、ファインディのPlatform開発チームでSREを担当している原( こうじゅん )です。 2025年12月に、アメリカ・ラスベガスで開催されたAWS re:Inventに参加してきました。 re:Inventは毎年ラスベガスで開催されるAWSの世界最大のカンファレンスで、世界中からエンジニアが集まります。 この期間中、ラスベガスの街全体がre:Inventの会場となり、最新のAWSアップデート情報のリリースや技術セッションの他、EXPO、re:Playパーティー、5K Raceなど様々なアクティビティが用意されています。 本記事では、技術セッションの内容よりも、会場の雰囲気やサブイベント、現地での過ごし方を中心にお伝えします。 技術セッションの内容を中心とした内容は先日投稿した AWS re:Invent 2025 参加レポート - 参加して感じた、AIOpsの本格的な到来 に記載しているので、ぜひこちらも合わせて御覧ください。 はじめに re:Inventの規模感 - ラスベガスの街が会場に 会場は6つの施設に分散 シャトルバスとモノレールで会場間を移動 多数あるセッションカテゴリ 会場の様子 フリードリンクと軽食 Meal会場でのビュッフェ 厳重なセキュリティチェック EXPO会場 SWAG SPORTS FORUM セッション以外のサブイベント 5K Fun Run re:Play おわりに re:Inventの規模感 - ラスベガスの街が会場に 会場は6つの施設に分散 re:Inventの会場は次の6つに分散しており、それぞれが巨大な施設です。 Encore Wynn The Venetian (メイン会場) Caesars Forum MGM Grand Mandalay Bay 上の地図を見ても縮尺がわかりにくいですが、実際に現地で歩いてみると想像以上の距離があります。 メイン会場であるThe VenetianからMGM Grand付近まで実際に歩いてみると約1時間ほどかかりました。 さらに、各会場内も広大で、イベント全体を通じてかなりの距離を歩くことになります。 シャトルバスとモノレールで会場間を移動 会場間の移動手段は、シャトルバスかモノレールが基本です。 シャトルバスもひっきりなしに運行されており、私は期間中ずっとシャトルバスを利用していました。 街中やホテル内の至るところでre:Inventのバッジを付けた参加者とすれ違います。 まさに「ラスベガスの街全体がre:Invent」という雰囲気でした。 多数あるセッションカテゴリ この複数ある巨大な会場の中で、様々なセッションが同時並行で行われます。セッションの種類は次の通りです。 Keynote : 基調講演 Breakout Session : 技術・事例セッション Workshop : ハンズオン形式 Chalk Talk : 小規模なディスカッション形式 Game Day : チーム対抗の技術チャレンジ セッション数が膨大なため、見たいセッションを探すだけでも一苦労です。 また、移動時間込みでセッションスケジュールを考える必要があります。 re:Invent 2025 MCP Server というイベント情報を調査できるMCPもあり、私はこれを利用してスケジュールを組んでいました。 builder.aws.com Keynoteで発表された新サービスのアップデートに関するセッションは[NEW LAUNCH]という形で新しく登場してきます。 そのため、気になるアップデートがあれば、事前に組んでいたスケジュールから変更したり、柔軟にスケジュールを変えていく必要があります。 私の参加したスケジュールは次の通りです。その他の時間は、会場移動やEXPOへの参加などしていました。 今回は、Keynoteで発表されたDevOpsエージェント関連のワークショップを運よく予約できたこともあり、ObservabilityやAIOps系のセッションが多めの構成になりました。 Scaling observability with generative AI (ARC311) Behind the scenes: How AWS drives operational excellence & reliability (COP415) Amazon ECS observability patterns and design decisions (CNS351-R) Opening Keynote with Matt Garman (KEY001) A deep dive on IAM policy evaluation (SEC402-R1) Best practices for cost optimization with AWS Backup (STG328-R) The Future of Agentic AI is Here (KEY002) Unveiling Amazon ECS workloads with AWS observability and agentic AI (CNS413) [NEW LAUNCH] Resolve and prevent future operational issues with AWS DevOps Agent (DVT337-R1) Infrastructure Innovations (KEY004) A Special Closing Keynote with Dr. Werner Vogels (KEY005) 技術セッションの感想を中心とした内容は先日投稿した AWS re:Invent 2025 参加レポート - 参加して感じた、AIOpsの本格的な到来 に記載しているので、こちらもよろしければ御覧ください。 会場の様子 ここからは、セッション以外の会場の様子やサブイベントについての体験談を書いていきたいと思います。 フリードリンクと軽食 各会場の廊下には、コーヒー、ドリンク、サンドイッチ、ドーナツ、バナナなどの軽食がおいてあり、自由に飲食できます。 特に制限もないため、私はここで簡単に朝食を済ませたり、セッション後にコーヒーを入れてホテルに持ち帰ったりしていました。 Meal会場でのビュッフェ Meal会場ではビュッフェ形式の食事が提供されています。 イベント期間中は軽食とMeal会場の食事が用意されているため、イベント時間中は会場だけで出費なしで食事を賄うことは可能です。 会場や日にちによって出る料理が異なったりしてますが、注意点としてはLunchの時間が11:00 AM ~ 1:00 PMなど食事できる時間が限られていることです。セッションの時間と様子を見てLunchの時間を確保する必要があります。 厳重なセキュリティチェック 各会場の入口には、セキュリティゲートが設置されており、持ち物検査を受ける必要があります。 麻薬検知犬も多く見受けられ、日本のカンファレンスでは体験できない海外イベントならではの厳重さを感じました。 シャトルバスで会場間を移動した際も、別会場の入口でセキュリティチェックを受ける必要があります。 EXPO会場 企業ブース出展会場のEXPOも圧巻の広さでした。 多数の企業が出展しており、Datadogの滑り台やKiroのお化け屋敷など、ユニークな展示もありました。 また、アメリカらしいと感じたのは、ドネーション(寄付)コーナーが設置されているブースで、日本にない文化を感じました。 SWAG EXPO会場や各ブースでSWAG(ノベルティグッズ)が配られており、Tシャツ、ステッカー、ボトルなど様々なグッズを集めることができます。 SWAGもサプライズ的に配布されたりすることがあり、Xで「〇〇でXXが配られた!」などの情報をみて初めて知るものもありました。 SPORTS FORUM SPORTS FORUMは、スポーツとテクノロジーを組み合わせたエンタメエリアです。 F1のタイヤ交換ゲーム、バスケのゲーム、VRなど、多彩なアクティビティが用意されていました。 散策しているだけでも楽しめます。 セッション以外のサブイベント ここからは、re:Inventのサブイベントをご紹介します。 5K Fun Run イベント期間中に開催される5Kmのマラソンイベントです。 参加して完走すればメダルがもらえます。 6:00 AMから開始され朝早いイベントですが、ラスベガスの道路を走れる貴重な機会なので、体力に余裕があればぜひ参加してみてください。 re:Play re:Invent後半、クロージングKeynoteの後に開催される公式パーティーがre:Playです。 DJによるライブパフォーマンスが行われ、会場の雰囲気はもはやカンファレンスというより野外フェスそのもの。 40フィート走や、巨大なロボットアームで廃車を持ち上げて落とすという、ユニークなアクティビティも用意されており、締めのエンジョイできる時間でした。 おわりに 技術セッションで最新のAWSサービスを学べたのはもちろんですが、会場の規模感やサブイベントの充実度、そして海外のエンジニアとの交流が、このイベントの大きな魅力だと感じました。 ワークショップで英語を使って会話したり、海外のエンジニアからファインディについてフィードバックをもらったりと、コミュニケーションを取ろうとした経験は貴重なものでした。 もっと技術的なディスカッションができるようになりたいという想いも強くなり、継続して英語を学習していきたいと思っています。 来年以降re:Inventへの参加を検討している方の参考になれば幸いです。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
この記事は、 ファインディエンジニア #1 Advent Calendar 2025 の21日目の記事です。 adventar.org はじめに こんにちは、ファインディのPlatform開発チームでSREを担当している原( こうじゅん )です。 2025年12月、ラスベガスで開催されたAWS re:Inventに参加してきました。re:InventはAWSが毎年開催する世界最大級のクラウドカンファレンスです。 今年は特にAI Agentを中心とした大きな変化を感じるイベントとなりました。 本記事では、私の体験したセッションを通じて見えてきたインフラ・運用の変化について、AIOps領域に焦点を当てて振り返りを書いていこうと思います。 会場の様子やセッション以外のイベントについてはまた別記事で書いていきます。 はじめに re:Invent 2025 今年の主要テーマの1つであるFrontier Agents AWS DevOps Agentとは ワークショップでの体験 その他の運用・インフラ領域で参考になるセッション Observability × AI 運用の文化とプラクティス インフラ基盤の進化 IAMポリシーの深掘り エンジニアに求められる姿勢 おわりに re:Invent 2025 re:Inventは、ラスベガスの街全体が会場となる巨大なイベントです。 reinvent.awsevents.com 6つの会場で数多くのセッションが同時並行で開催され、世界中のエンジニアが集まります。 会場間の移動だけでも場所によれば徒歩だと約1時間かかることもあり、シャトルバスやモノレールで移動しながら1週間を過ごすことになります。 セッション以外にもEXPO、re:Playと呼ばれるパーティイベント、5k Raceなど様々なアクティビティが用意されており、まさにAWSの祭典という雰囲気でした。 今年の主要テーマの1つであるFrontier Agents 2025年のre:Inventで印象的だったのは、Frontier Agentsと呼ばれるAIエージェントにまつわる発表です。 Keynoteでは、Kiro Autonomous Agent、AWS DevOps Agent、AWS Security Agent、など、フロンティアエージェントと呼ばれるインフラ・運用領域に直接関わるAIエージェントが次々と発表されました。 これらは単なる「補助ツール」ではなく、「チームメイトとして成果を出すことを期待される存在」として位置づけられています。 その中の1つである私が体験してきたAWS DevOps Agentについて軽く触れていきたいと思います。 AWS DevOps Agentとは AWS DevOps Agentは、運用チームの「チームメイト」として次のような役割を担います。 Team Player : アラートやチケットに対応し、Slackなどのコラボレーションチャネルで知見を共有 Telemetry Expert : メトリクス・ログ・トレースを横断的に分析。DatadogやNew Relicとも連携可能 Pipeline Pro : GitHubやGitLabと連携して障害につながる変更を特定し、パイプライン改善を提案 Application Context : アプリ構成やRunbookを理解した上で判断 aws.amazon.com ワークショップでの体験 実際にDevOps Agentを使ったワークショップである [NEW LAUNCH] Resolve and prevent future operational issues with AWS DevOps Agent に参加し、次のような操作を体験しました。 障害発生中のAWSリソースを解析して根本原因を特定 Dynatraceと連携させてオブザーバビリティデータを統合 インシデント対応レポートと改善計画の自動生成 エージェントが「インシデントの根本原因を教えてくれる」だけでなく、「改善計画」まで説明してくれる点は、まさにチームメイトのような動きでした。 まだプレビュー版ではありますが、弊社でオブザーバビリティツールとして使用しているDatadogとの連携もできるのでぜひ取り入れていきたいと思いました。 その他の運用・インフラ領域で参考になるセッション DevOps Agent以外にも、AIOpsに関連する運用・インフラ領域で参考になるセッションがいくつかありました。 Observability × AI Scaling observability with generative AI (ARC311) では、Kiro CLI Agentを用いた自然言語操作によるオブザーバビリティの自動化が紹介されました。 障害が発生している環境に対して、Kiroがカスタムエージェントで解析した内容をもとにLambdaのコードを書き換えたり、リソース設定を変更したりするデモが印象的でした。 Unveiling Amazon ECS workloads with AWS observability and agentic AI (CNS413) では、ECSワークロードに対して生成AIを活用し、オブザーバビリティデータを自動分析するアプローチが紹介されました。 毎週30億タスクが実行され、新規コンテナ顧客の65%がECSを利用しているという事実を紹介してから、AWSのオブザーバビリティツール全体を整理した上で、ECS上でAIOpsエージェントを構築する際のベストプラクティスが紹介されました。 運用の文化とプラクティス Behind the scenes: How AWS drives operational excellence & reliability (COP415) では、AWSがグローバル規模で運用をどのように行っているのかが解説されました。 特に印象的だったのは、次のサイクルを継続的に回している点です。 Readiness : 障害が起きる前の状態づくり(アラーム、ダッシュボード、Runbook、オンコール体制の整備) Observability : ログ・メトリクス・トレースでの計測、SLOドリブンなモニタリング Incident Response : SOP(標準作業手順書)に従った対応、AIOpsによる障害分析 Reviews : 定期的なダッシュボードレビューと改善活動 これらはSREのプラクティスと大きくは変わらないなと思いつつ、改めて運用フローを整理・定義していく重要性を認識しました。 インフラ基盤の進化 Infrastructure Innovations (KEY004) では、Graviton5やLambda Managed Instances、Amazon ConnectのAI対応など、AWSのインフラ技術の進化が語られました。 セキュリティ、可用性、弾力性、コスト、俊敏性といった軸で、どのような思想で設計・進化してきたのかが示されており、基盤レイヤの理解を深めることができました。 IAMポリシーの深掘り A deep dive on IAM policy evaluation (SEC402-R1) では、IAMポリシーの評価ロジックが詳細に解説されました。 権限評価は単一のポリシーだけで決まるのではなく、Organization → Account → Role → Boundary → Session という複数レイヤをすべて通過して決まります。 また、すべてのPrincipalを対象にしたDenyに条件を付けることで、特定のロールだけを例外として許可するIAMポリシーの書き方なども紹介されており、セキュリティ設計の参考になりました。 AIがインフラ領域に組み込まれている中、ガードレールとしてのポリシーの整備も必要だと感じました。 エンジニアに求められる姿勢 また、クロージングKeynoteで、AWS CTOのWerner Vogels氏が語った言葉が印象に残っています。 「AIは自分の仕事を奪うのか?」という問いに対して、CTOは「多分ね……」と答えつつも、本質的な問いはそこではなく、「AIがあなたを時代遅れにするのか?」であると強調していました。 そして、その答えは、「あなたが進化し続ける限り、断じてノーだ」と。 私たちは今、AIによって時代が大きく動いている震源地に立っています。その中で重要なのは、次の姿勢です。 Be Curious: 好奇心を持ち続けること Think in Systems: 複雑なシステム全体を捉える力 Communicate: 良いアイデアを明確に伝える力 Owner: 成果物に対して自ら責任を持つこと Polymath: 多才であり、学び続けること AIはあくまでツールであり、仕事の主体は常に「あなた自身」である。 The work is yours, not the tool's YOUR CURIOSITY + YOUR SKILLS = WORLD-CHANGING このメッセージは、re:Inventの締めとしてとても印象に残りました。 おわりに 4日間のイベントを通して、技術的な知見が広がり、刺激的で濃い時間を過ごすことができました。 2026年は、AIOpsが本格的に実務に組み込まれていく年になると感じ、ファインディのPlatform開発チームでもよりAIOpsを組み込んでいく体制づくりを行っていければと思います。 ファインディでは一緒に働くメンバーを募集中です! よかったら覗いてみてください。 herp.careers
アバター