以下の内容はhttps://www.yasuhisay.info/entry/2025/08/01/085646より取得しました。


Analytics Engineerのためのプロダクトコードのコードリーディング with LLM Agent

社内のデータ基盤チームのメンバー向けの勉強会で発表した内容を放流します*1。「Analytics Engineerのための」とは付いているものの、実際の勉強会には社内の様々な職種の方も参加してくれて、かつ以下のように業務にも役に立ったという声もあるので、割と有益な内容なんじゃないかなと思っています。

勉強会当日の様子

デザイナの方がフロント周りのコードリーディングで役に立った例:

デザイナの例

SWEで馴染が薄いリポジトリの問い合わせ調査に役に立った例:

SWEの例

また、以下のXのSpaceで同じようなことを話しているので、そちらもよかったら聞いてみてください。

概要

  • 仕事をしていると、プロダクトの機能や仕様について知りたくなることは少なくありません
  • SWEに聞けばよい...というのはそれはそうだけど、全てを聞くのは難しいでしょう
  • この発表では、プロダクト側のコード(サーバーサイドやクライアントサイドなどのリポジトリを想定)を書いたことがない人が助手席にLLM Agentを置いた状態でプロダクトの仕様などをコードリーディングする方法の一案を紹介します
    • データ基盤チーム向けを想定しているので、タイトルにAnalytics Engineerと付けていますが、アナリスト / PdM / QAなど色んな職種の人に役に立つ内容にできるといいかなーと思っています
  • 逆にSWE以外の人がこういったコードリーディングすることを前提にSWEがどういったことを意識すべき(とid:syou6162が思っているか)についても話そうかなと思っています

この勉強会をやろうと思った背景

  • Analytics Engineerの主戦場は主にSQL(最近だと特にdbt)が多い
  • SQLはゴリゴリ書けることが前提、しかし仕事をしていく上でそれだけでは足りないことも多い
  • データソースの仕様をいかに抑えに行けるかはAnalytics Engineerとしてのレベルを上げていくためには必要*2
    • データ(結果)としてそうなっているのか、仕様としてそれが担保されているのかの違いは大きい
    • 例: ある列にNULLが一個もなかったとして、NULLが入らない仕様であるとは限らない
      • たまたままだNULLのデータがきてないだけかもしれない
      • 仕様やソースコードを見に行けば、それが型として分かる。型は雄弁
      • 例: String? entryIdだったら、NULLが入り得る
  • データソースの仕様を抑えに行く手段はいくつもある
    • SWEに仕様を聞く
      • 一番正確(なはず)
      • ぱっと聞きにいけるくらいの関係性になっておけると安心
      • いつも聞いてるとさすがに申し訳ない
    • プロダクトの仕様書
      • 自然言語で書いてあって分かりやすい
      • コードレベルの詳細まで書いてあるわけじゃない
      • たまに更新漏れがあるかもしれない
    • Slack
      • 意外と重要な情報源
      • 検索ワードや重要な会話が落ちているチャンネルを押さえておくと便利
      • 「こんな事例あったなぁ...」というのはSave for laterしまくっておく
  • そして、ソースコードを自分で読むという手段がある
    • ...とはいえ、腕力 / 気合 / 気力がそれなりに必要だし、SWE出身じゃないとこれまではオススメしにくかった
    • 理由: 知らないといけない前提知識がそれなりにあり、それらの学習コストがペイするまでにはそれなりに時間が必要になってしまうため
    • しかし、この半年くらいで状況は大きく変わってきた。LLMの強烈な進化
      • コードを書くことをアシスタントしてもくれるが、コードリーディングにも役に立つ
    • 例: VSCode Copilot / Cline / Cursor / Claude Code / DeepWiki / Devin search

コードリーディングの具体例

具体的なコードベースやAgentの回答を公開することはできませんが、少しぼやかしつつも大まかな雰囲気が分かるレベルでコードリーディングの具体例を載せていきます。

Enumの値の同定

前提

  • データ基盤チームではデータ活用者向けにenumの値(例: hoge_type)を人間が分かりやすい形にCASE文を使って変換することがよくある、以下のようなSQLが具体例
    case
        payment_method
        when 0
        then 'credit_card'
        when 1
        then 'local_payment'
        when 3
        then 'cash_on_delivery'
        when 4
        then 'invoice'
        else 'other'
    end as payment_method_name,
  • Enumに新しいtypeが追加されると、↑のコードだと全部otherに吸収されていく
    • 分析者「ある時期からotherの割合が急に増えてきている🤔」「otherではなく、その内訳を知りたいよ」となるのは当然の要求
  • Enumが追加されたらデータ基盤チーム側でも知っておける状態にしておきたい
    • dbtのaccepted_valuesというテストを使って、事前に定義した値以外が入ってきてたら気付けるようにしているが、テストを書けていないケースもある
    • 実際にいくつかの事例を見ると、実際に口座振替 / クーポン利用 / ポイント利用などが増えていることに気付いた
  • 余談: こういう細かい仕様のやり取りもData Contractを使うようにしたいですね

やりたいこと

  • やりたいことは2つ
    • Enumの定義元を自分で調査する
    • Enumの値の意味を自分で知ることができる
  • 素朴な疑問: 「GitHubの検索でよくない?」
    • 回答: 出てくる場合はよかったですね、うまくいかないことも結構ありますね
    • GitHubの検索は基本的に文字列のマッチング
    • 同じような文字列は相当色んな場所に出てくる可能性があって、どれが「定義」に相応わしいかを見極めるのはSWE的な知識が必要になる場合がある
      • 例: ここはgRPCでAPIのレスポンス返すところだから「定義」と呼ぶには違う気がする
      • 場所は分かるが、それがよさそうか、全体でどういう立ち位置のものか、などは知識がないと分からない
  • こういった知識をLLM Agentに支えてもらって補っていきたい

簡単な事例

そんなわけでEnumの値の定義はどこかを知るために、まず全体のことを質問しました。特にDBであるFirestoreを重点的に見るようにさせます。

id:syou6162: プロダクトの全体の仕組みをSWEではなくAnalytics Engineerにも分かるように教えてください。APIへのリクエストにはあまり興味がなく、主にFirestoreへの読み書きに関する部分に興味があります。

本筋に入っていきましょう。

id:syou6162: Firestoreのコレクションに対する読み書きを定義しているコードがどこか知りたいです。特にOrder.payment_methodの定義について知りたいです。

コードの定義場所は分かりましたが、その番号に対する意味付けまでは分かりませんでした。より詳細に調査をさせます。

id:syou6162: 結局、Order.payment_methodの値の意味はどこを見れば分かりますか? 0の場合はどういう意味、1の場合はどういう意味というのが知りたいです。コードベースのどのファイルのどの辺に書いてあって、というのが知りたいです。

結果として、どんぴしゃの回答を得ることができました! 漏れていたEnumの値や意味をdbtのyamlファイルに転記することができました。

応用事例: アラート対応の自動化

先ほどの事例は便利は便利ですが、もう一歩頑張って欲しいとも思いました。私が現在所属している株式会社10Xでは、新規事業で新しくデータ基盤を作っており、トイルに近いアラート対応のようなものはClaude Code自身にやって欲しいと思いました。

「そろそろもうやれるんじゃないか...?」と思い、Claude Codeのカスタムスラッシュコマンドに「アラートがきたら、その原因を自分で調べ、その対応策となるPull Request自体を作る」というタスクを書いてみました。具体的には以下の内容をコマンドに記載しています。

  • Datadogのアラートに含まれるCloud LoggingへのURLをカスタムスラッシュコマンドの引数とする
  • gcloud logging readを使って、Cloud Loggingのログを実際に読ませる
    • ログのスキーマを事前に教えておき、典型的な場合についてjqで必要な情報をフィルタ / 加工させる方法を書いておく
  • エラーの内容を特定する
    • 典型的なエラーパターンとしては「プロダクト側のデータソース側の修正によるもの」「データ基盤側の修正によるもの」「インフラの一時的に不調によるもの」などがある
    • それらを具体例を沿えつつ説明しておく
  • 典型例に対して、それぞれ具体的なアクションも記述する
    • 例えば「プロダクト側のデータソース側の修正によるもの」が原因であれば
      • プロダクト側のリポジトリの最近の修正(gh pr list --state merged --limit 20...)の一覧を取得
      • それぞれのPull Request内の修正の中身を確認
      • Pull Request内にNotionのURLがあれば、notion mcpを使って詳細な情報を取得しにいく
    • 原因のPull Requestが分かれば、そこに対応したdbtのyamlファイルやテストの内容を修正する

実際にアラートが鳴った際にこのコマンドを試したところ、根本原因を把握した上で修正Pull Requestを送るところまで自動化することができました。アラート対応としては簡単な部類のものではありましたが、gcloud / ghコマンドやmcpなどをLLM Agentに接続して、適切なコンテキストを与えることの強力さを思い知りました。同じような事例がRebuildでも紹介されていたので、こういった事例はより身近になってくるのだと思います。

もちろん、調査内容や実際に作られるPull Requestが見当違いな場合もあると思います。しかし、プロダクトのコードリーディングに慣れていないAnalytics Engineerからすると、どの辺が怪しい、といった勘所が分かるだけでも嬉しいポイントは結構あるのではないでしょうか。

このカスタムコマンドを書いていた際のもう一つの気付きは、これは人間にとっても非常によいオンボーディングのドキュメントになっている、ということでした。障害対応は慣れている人はサクサクできるものの、慣れていない人にとっては暗黙知になりがちです。こういったLLM Agent向けのドキュメントを整備していくと、新しくチームに入った人にとっても嬉しいものになることが分かったため、こうした活動は今後も続けていきたいと思います。

statusに対する状態遷移

状態遷移図が欲しい背景

  • 問い合わせ調査などで「hoge_statusが3になっていて、操作ができないので調査をお願いします」と聞かれることがあると思います
  • 「その状態に遷移するとしたら、前の状態は何か?」「状態がもう遷移しないterminalの状態はどれか」などが分かると調査が捗ることが多いです

どうやって状態遷移図を手に入れるか

  • そういった背景もあり、状態遷移図が手に入ると嬉しいです
  • 基本的にはそんな便利なものはないことが多いです
    • SWEであれば状態遷移図を書くことは頑張ればできるでしょう
    • しかし、「漏れなく」やってくれ、と言われたら非常に大変で辛い作業です
    • 集中してコードを読んでも2~3時間じゃ洗い出せない、ということも普通にありえます
  • しかし、LLM Agentは疲れを知らないから状態遷移図を書かせてみることはできる、かもしれない
    • と思ってやらせてみたら、できた...!

実例

まず、LLM Agentの基本的な理解度を試すために以下のことを聞きました。

id:syou6162: Order.statusはどういう値を持つことがありえますか? 0はどういう意味、1はどういう意味というのを列挙してください。

無事に各statusの意味を回答できたので、状態遷移について質問しました。「このfactはコードベースのどのファイルのどの行で」というのを出力に含ませると、ハルシネーションを避けられる可能性が高いように思いました。

id:syou6162: Order.statusの取り得る状態遷移を知りたいです。statusの何番から何番に遷移することがあって、それはどういうときなのかを知りたいです。推定ではなく、コードベースを読んだ上で取り得る状態遷移を全て書き出してください。大変だと思うけど、時間をかけて ultrathinkg で見ていってください

さすがにここは回答に時間がかかったので、その間にシャワーを浴びていました。シャワーを浴び終わったら回答が出ていたので、可視化をお願いしました。

id:syou6162: 状態遷移図を見やすく可視化できるように、mermaid形式で出力してください

Claude Codeが解析したあるstatusに対する状態遷移図

それなりに複雑な状態遷移図が出力されましたが、勉強会当日にSWEに合っていそうか質問したところ、出ている分に関しては間違いがなさそうだし、抜けていそうな遷移もぱっとは思い浮かばない、ということでかなり高精度に状態遷移図を出すことができていました。これには正直、かなり衝撃を受けました。

しかし、一つのノードだけ、初期状態以外から始まっているものがあったので、LLM Agentに聞いてみました。

id:syou6162: piyo_status は初期状態からじゃなくていきなり登場してるのはなぜ?

調べてみると、このstatusは

  • 昔は使われていたが、現在はプロダクトの進化により取り得ることがなくなったstatusであった
  • Protocol Buffersの都合上、enumの値を後から消すわけにもいかないため、コード的に残っている
    • しかし、ある状態からこのstatusに遷移するコード自体は消されているため、このような状態遷移図が出力された

ということが分かりました。ハルシネーションを起こしていたわけではなく、コードの実態という意味では真実をきちんと暴けていたのが面白かったし、すごいと感心してしまいました。

店舗の開店 / 閉店の日時の同定

前提および課題感

  • 前提: 店舗(Shopテーブル)に関する情報はfirestoreからBigQueryに日時でexportされており、releasedAt(開店日)やisDeleted(閉店フラグ)といったカラムを持っている
  • 課題感
    • 閉店はフラグであり、いつ閉店したのかの日時の情報がない
    • 店舗は(何らかの事情により)閉店後に開店する場合がある
      • 過去にこういうオペレーションがあったのは確認済み
    • その場合、複数回開店する可能性があるが、releasedAtはスカラー値なので、情報が保持しきれない
    • ある時点での開店していた店舗数を出して欲しいという要望が上がってきている
      • 注文ベースで店舗数をカウントすると、仮に注文がなかった場合の店舗が集計から漏れてしまうことになり、正確な値を出せない
      • 店舗の開店 / 閉店のstatusに対する履歴テーブルに相当するものが欲しい
  • 「どこかに履歴が取れる情報ないんだっけ...」と思って、Claude Codeと会話した

実例

会話するにあたって、Claude Code自体にコードベース全体を眺めさせ、後続の質問に対してスムーズに行くようにしたかったため、以下の質問をしました。この質問を通じて、Claude Code自体の理解度を見ておきたかったという意図もあります。

id:syou6162: 店舗に関する情報はどこで管理されていますか?

releasedAtなど主要なカラムの情報はちゃんと知っててくれているのね」と思いながら次の質問をします。

id:syou6162: 店舗をいつ開けたか、いつ閉店したかという情報はどこで誰が設定できますか? それらの情報はどこに保存されますか?

店舗の開店 / 閉店に関わる主要な画面のことも理解できていそうだし、関連するテーブルのことも理解していたので、いよいよデータ基盤に関するテーブルのことを質問します。

id:syou6162: 店舗イベント履歴はBigQueryではどのテーブルになりますか?

ここで、実はClaude Codeは重要な発見(サブコレクションに含まれている)をしてくれるのですが、BigQuery上には見当らなかったということでid:syou6162はこの時点では気付けずにスルーしてしまいます😭。

id:syou6162: 実際のFirestoreのコレクションを見たけど、 ShopEventというFirestoreのコレクションは存在しなかったよ。どこのことを見て言っていますか? ちなみにあなたにはFirestoreのテーブルを見る権限はないので、実際のテーブルではなくコードベースから推測してください*3

この時の自分の心境としては「またハルシネーションしているのか?factベースでどうなってるか報告させることにしよう」と作戦を切り替えたつもりになっています。

データカタログからテーブル名(ShopEvent)を調べてみるけどないな?どうなってるんだ?と思って、以下の質問をしました。

id:syou6162: gcloud firestore exportを使ってGCSに出力して、GCSからBigQueryのテーブルとして取り込まれているんだけど、サブコレクションはBigQueryにディフォルトだと取り込まれるのかな?

Claude Codeが色々答えてくれますが、id:syou6162にはよく分からなかったので、公式ドキュメントベースで事実を照合させることにしました。

id:syou6162: gcloud firestore exportってそのままサブコレクション指定しても動くの? 公式ドキュメントをよく見てください

サブコレクションでも動きそうな様子ですが、実際に本当に動作するのか判断が付けにくかったため、すでにサブコレクションで動作しているものがあるかを追加で質問します。既存のデータ転送でサブコレクションを実際に動かしているものがない場合、検証を挟む必要もあるので、その意味でも調べさせています。

id:syou6162の質問: FirestoreからBigQueryにエクスポートしている一覧はここにあるんだけど、この中にサブコレクションを実際に指定しているものってあるかな。サブコレクションを指定しても問題ないかを確かめたいんだけど。

「これがサブコレクションだよ」とClaude Codeが案内してくれましたが、まだ確証が得られなかったため、追加で質問をします。

id:syou6162: ちょっとわかんないけど、出してもらった例はどれが大元のコレクションで、どれがそのサブコレクションっていう関係性なの?

この辺りでようやくid:syou6162は事情が掴めてきました。答えとしては

  • 店舗の開店 / 閉店の履歴に対応するレコードは存在するが、サブコレクションに含まれている
  • 大本のコレクションがFirestoreからBigQueryに転送されていたとしても、サブコレクションが転送されるわけではない
  • しかし、サブコレクション個別に対して転送設定を書けばBigQueryに転送できる

というものでした。

  • ...とそんなやり取りを経て、分析にとって重要なテーブルをClaude Codeと一緒に発見することができ、対象のテーブルは先日BigQueryに取り込まれました🎉🎉🎉
  • 感想: 軽い & ダメ元の気持ちでやってみたけど、実務的にもいい発見ができて結構ビビった
  • 「人間は正解を知っている => LLMにやらせる」だけじゃなくて「LLMを人間が協力して、どうにかできないか一緒に考える」がすでに実用的なフェイズになっている
    • しかも、それが自分にとって馴染がないリポジトリでも機能するようになっている
    • Analytics Engineerにとって、これほど強力な武器はない...!
    • もちろん、Analytics Engineerが持っているデータに対する知識をコンテキストとしてAgentに与えた上でやる、というのが非常に重要
  • もちろん、ハルシネーションもたまに入ったりするので、それらを「ハルシネーションだな」と見分けられる技術力もAnalytics "Engineer"として今後も重要ではあり続けます、頑張ろう

Take Home Message

To: Analytics Engineer

  • Analytics Engineerにとって、データの生成元がどうなっているかの仕様を抑えにいけるのはスキルを上げていく上でも非常に重要
  • 一人だと大変、時間もかかる
  • LLM Agentとならもっとうまく / 早く / 安くやれる可能性がある
    • まだじゃじゃ馬感はあるけど、それでもかなり実用的になってきている
    • 乗りこなし方を覚えると「じゃあ、こういうことできるかも」
  • 一方で、SWEとしての基礎力は高め続けましょう
    • AgentとかAIについても同じ
    • 指示の仕方の適切さ、返ってきた内容を吟味して取捨選択の質が変わってくる

To: SWE

  • プロダクトのリポジトリにPull Requestを出す人以外でもプロダクトのコードはかなり読まれているし、重要な情報である、ということを改めて知っておいて欲しいです
    • Analytics Engineer / Search & ML / Secirity / PdM / そして、LLM Agent
    • また、プロダクトのコードであっても、自分の手垢が付いてないドメインではコードリーディングに時間がかかるということもよくある話だと思います
      • 例: 問い合わせ調査などの際にお届けチームの人が売場のコードを読まないといけない場合などドメインを跨ぐ場合
  • 「全ての職種向けに対してドキュメントを頑張って書いて欲しい」と言いたいのではない
    • それは現実的には難しい、SWE => 全ての職種(N)の構造
  • でも、LLM Agentの登場でそれぞれの職種向けに翻訳をさせること、必要な情報を抽出 / 要約させることが(今日紹介した事例のように)できるようになってきた
  • 情報 / データの生成元であるSWEがここを意識できるか否かで組織の生産性業務効率性がぐっと変わってくると思っている

To: QA / PdM / BizDev / etc

  • 今日紹介したように、これまでSWEに聞かなければ分からなかったことがLLM Agentによってある程度のことであれば分かるようになってきています
  • もちろんまだまだ完全ではありません
    • ハルシネーションを起こす場合もあります、裏を取らないといけない場合などはこれまで通りSWEに聞くのがよいでしょう
  • しかし、自分の理解度や解像度を上げたい、という場合には今日紹介したようなLLM Agentとの会話はかなり役に立つ場合があると思います
    • LLM Agentと会話した状態で情報を整理し、SWEに質問すると質問の精度も高まる、という場合があると思います
  • 「こういうのはもしかしたらLLM Agentに聞いたら分かるかも」というのを少しずつ試してみて欲しいです
    • git cloneして、エディタで聞くだけでもできることはかなりある
  • 試してみた上で「こういう情報を聞いてみたけど、うまくいかなかった」「こういう情報があればLLM Agentは情報を返せるようになるかもしれない」という事例があったら、Slackに是非共有して欲しいです
    • SWEはコードを自分でも読めるため「こういったこともできない」「何があれば分かりそう」は意外と気付かないことも多いので

宣伝: データエンジニアの採用やってます

こういったLLM Agentの力も借りつつ、各プロダクトのデータ基盤開発を一緒にやってくれるデータエンジニアを募集しています! このエントリに関する話やそれ以外の話など、カジュアル面談でお待ちしております!

*1:会社ブログに書くつもりだったけど、気合が足りなかった。お蔵入りするよりマシかなと...

*2:要出典、個人の意見です

*3:LLM Agentにいらぬ操作をされたくなかったので、権限をここでは付与していません




以上の内容はhttps://www.yasuhisay.info/entry/2025/08/01/085646より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14