こんにちは。データアナリストのtomitaです。 先日、社内のPdM(プロダクトマネージャー)とアナリストが中心となり、当社にとって重要な業界の一つである物流業界に関する勉強会を開催しました。 今回は、その内容と、そこで見えてきた当社の魅力についてご紹介したいと思います! 生成AIを駆使した『AI駆動勉強会』 今回の勉強会で最も特徴的だったのが、生成AIを活用した新しい学習スタイル『AI駆動勉強会』です。 これは、参加者各自がリサーチクエスチョンを設定し、それに対して生成AIを使って調査を行い、アウトプットと深掘りを行うスタイルです。 生成AIを使うことで、これまで何時間もかかっていた情報収集を短縮し、より本質的な議論に時間を割けるようにしました。 勉強会の様子 『AI駆動勉強会』の進め方 リサーチクエスチョンを立てる (5分):各自が知りたいテーマについて具体的な問いを立てます。 AIで調査する (15分):生成AIを使い、設定した問いについて効率的に情報を収集します。 アウトプット&質問深掘り (2分):調査結果を簡潔にまとめ、参加者と共有。疑問点やさらなる深掘りについて議論します。 このセッションを1.5〜2時間で2〜3回繰り返すことで、短時間で多くの学びを得ることができました。 参加者からの声 「リサーチクエスチョンを先に立てることで、集中して学習できた!」 「アウトプットと質問深掘りの時間で、学習内容がより深く定着した」 「AI活用の練度が上がり、効果的なプロンプトなどの知見が共有されたのが良かった」 「他の人のリサーチクエスチョン自体に学びがあり、視野が広がった」 部署を超えたメンバーとの交流 今回の勉強会には、アナリストだけでなく、PdMや元CSM(カスタマーサクセスマネージャー)で物流業界に詳しいメンバーまで、幅広い職種のメンバーが参加しました。 例えば、元CSMのメンバーからは、物流現場でのリアルな課題が共有され、AIによるリサーチだけでは得られない学びがありました。 多角的な視点からの議論は、私たちデータアナリストがデータから導き出したインサイトを、プロダクト改善やビジネス戦略に繋げる上で不可欠です。異なる専門性を持つメンバーと気軽に意見交換できる環境は、当社で働く大きな魅力の一つだと改めて感じました。 リモート参加も可能な柔軟な働き方 今回の勉強会では、多くのメンバーがオフィスに集まりました。私自身は家庭の事情でリモートでの参加でしたが、オフィスにいるメンバーと変わらず、活発な議論ができました。 当社のプロダクト組織では、働き方の柔軟性を担保する観点から、リモートワークOKとなっています。場所や時間にとらわれずに質の高いインプットとアウトプットができるのは、非常にありがたい環境です。 終わりに 今回の物流業界勉強会は、当社のPdMとアナリストが中心となり、生成AIを駆使した独自のスタイルで実施しました。AIで調査を進め、その結果をアウトプット・深掘りすることで効率的に物流業界への理解を深めることができました。 また、部署を超えて様々な職種のメンバーが参加することで、AIだけでは得られない物流現場でのリアルな課題が得られたり、多角的な視点からの議論ができたりしました。 We’re Hiring! 私たちは、ともに働くメンバーを募集しています!! カジュアル面談 も行っていますので、少しでも興味がありましたら、気軽にご連絡ください。
こんにちは、タイミーでPlatform Engineerをしている近藤です。 マージキュー上のエラー通知について GitHubのマージキューは、チームが効率的かつ安全にコードをリリースするために欠かせない仕組みです。特に、大規模なチームや頻繁にコードをデプロイするプロジェクトでは、マージキューがCI/CDプロセスの核となります。しかし、マージキュー上でエラーが発生した際、その通知を迅速に受け取ることが極めて重要です。通知が遅れたり、見落とされたりすると、次のような問題が生じる可能性があります。 リリースの遅延 エラーが発生すると、問題のある変更は差し戻されます。 その結果、後続のPRのベースが変更されるため、マージキュー上でのCI処理を再実行する必要が生じます。 これにより、本来スムーズに進むべきリリースサイクルが停滞し、開発スピードが著しく低下します。 開発者体験(DX)の低下 マージキューでのエラー通知が適切に行われないと、開発者が混乱したり、不要な手戻り作業を強いられたりします。これにより、開発者のモチベーションや生産性の低下を招くことにもなります。 以上の理由から、GitHubのマージキューでエラーが発生した際の通知を確実に行うことは、開発効率を保ち、迅速な問題解決を促すために不可欠です。通知の仕組みを整備し、チーム全体が即座に問題に対処できる環境を整えることが求められます。 エラー通知の課題 単にワークフロー中にエラー通知のジョブを入れるだけでは、先行してマージキューに積まれたPRにCIエラーが発生する内容が含まれている場合、後続の人にも不要なエラー通知が届いてしまいます。これを回避するために、GitHubのconcurrency機能を活用してCIを適切にキャンセルする仕組みを導入しました。 sequenceDiagram autonumber participant DevA as 開発者 A participant DevB as 開発者 B participant Queue as マージキュー participant CI as CI (GitHub Actions) participant Master as master ブランチ DevA->>Queue: PR A をキューに追加 DevB->>Queue: PR B をキューに追加 par Queue->>CI: PR A + master のテスト Queue->>CI: PR B + PR A + master のテスト end CI--x Queue: PR A + master でテストエラー Queue->>DevA: PR A がテストエラーになりました Queue->>DevB: PR B がテストエラーになりました Queue->>Queue: PR B + master の再エンキュー Queue->>CI: PR B + master のテスト CI-->>Queue: PR B のテスト合格 Queue->>Master: PR B を master にマージ PR AとPR Bがマージキューに積まれた状態で、先行するPR Aでエラーが発生すると、PR Bは自動的にPR Aの内容を除外した状態で再度マージキューに入れられます。 この際、マージキューの実行時に作成されるブランチ名は都度変化します。よって単純にブランチ名をキーとした以下の設定では、期待通りに動作しません。 concurrency : group : ${{ github.ref_name }} cancel-in-progress : true そこで、マージキュー上で作成されるブランチ名の規則性を利用します。ブランチ名にはPR番号が含まれているため、ワークフロー内でブランチ名からPR番号を抽出するジョブを追加しました。 最終的に採用したワークフローは以下の通りです。意外と知られていませんが、concurrencyキーワードはジョブレベルでも指定可能です。 name : ci on : push : branches : - '**' - '!master' - '!gh-readonly-queue/**' tags-ignore : - '*' merge_group : permissions : id-token : write contents : read pull-requests : write jobs : concurrency_key : runs-on : ubuntu-latest outputs : key : ${{ steps.extract_pr.outputs.key }} steps : - id : extract_pr name : Extract PR number from branch name shell : bash run : | if [[ $ {{ github.event_name }} == 'merge_group' ]] ; then full_ref="${{ github.ref_name }} " pr_number=$(basename " $full_ref" | cut -d- -f2) echo "key=$pr_number" >> "$GITHUB_OUTPUT" else echo "key=${{ github.ref }}" >> "$GITHUB_OUTPUT" fi ci : needs : concurrency_key concurrency : group : ${{ github.workflow }}-${{ needs.concurrency_key.outputs.key }} cancel-in-progress : true uses : ./.github/workflows/_ci.yml with : skip : ${{ github.event_name != 'merge_group' }} secrets : inherit merge_group_notify : needs : ci if : ${{ failure() && github.event_name == 'merge_group' }} uses : ./.github/workflows/_merge_group_notify.yml with : role_to_assume : arn:aws:iam::012345678901:role/example notification_type : failure secrets : inherit 上記の仕組みを導入することで、先行するPRでテストエラーが発生しても、その影響で後続PRに対して不要なエラー通知が送信されることを防げます。 sequenceDiagram autonumber participant DevA as 開発者 A participant DevB as 開発者 B participant Queue as マージキュー participant CI as CI (GitHub Actions) participant Master as master ブランチ DevA->>Queue: PR A をキューに追加 DevB->>Queue: PR B をキューに追加 par Queue->>CI: PR A + master のテスト Queue->>CI: PR B + PR A + master のテスト end CI--x Queue: PR A + master でテストエラー Queue->>DevA: PR A がテストエラーになりました Queue->>Queue: PR B + master の再エンキュー alt 失敗通知をキャンセル Queue -x DevB: PR B がテストエラーになりました (キャンセル) end Queue->>CI: PR B + master のテスト CI-->>Queue: PR B のテスト合格 Queue->>Master: PR B を master にマージ ただし、PR AとPR Bがほぼ同時にマージキューへ投入された場合など、極めて稀なタイミングによっては、キャンセル処理が間に合わず後続のPRに対して不要なエラー通知が送信されてしまうケースが残ってしまいます。 こうしたエッジケースまで完全に抑制しようとすると、ワークフロー全体の実装が大幅に複雑化し、運用・保守コストも増大してしまう懸念があります。 そのため、今回は「不要な通知の発生を現実的な範囲で最小化しつつ、実装のシンプルさを優先する」という方針を選択しました。 まとめ 本仕組みによって、マージキュー運用時の不要なエラー通知を大幅に削減しつつ、チーム全体の開発効率と安心感を両立できるようになりました。 今後も、より良い開発体験を目指して、現場の実情やフィードバックを取り入れながら、継続的な改善を進めていきます。
こんにちは、タイミーでバックエンドのテックリードをしている新谷 ( @euglena1215 ) です。 GitHubマージキューTIPSシリーズ、前回までに、マージメソッドの制約やCIの高速化といったTIPSを共有してきました。今回は、マージキューのポテンシャルを最大限に引き出すためのパラメータチューニングと、そのために不可欠なキューの状態の可視化について解説します。 デプロイ効率と安定性のトレードオフ マージキューには、その挙動をコントロールするためのいくつかのパラメータが存在します。 Build concurrency :マージキューのCIを同時に実行する並列数。 Minimum/Maximum pull requests to merge :一度のデプロイ(マージ)に含めるPRの最小数と最大数。 これらのパラメータは、効率性と安定性という、二つの相反する要素を調整するために使用します。 効率性(デプロイの速さ) :開発者の待ち時間を短縮するため、PRを迅速にマージすることが求められます。 安定性(変更の分離) :問題発生時の影響範囲を限定し、原因特定を容易にするため、一度にマージする変更は少なくすることが望ましいです。 例えば、 Maximum pull requests to merge を10に設定するとデプロイのスループットは向上しますが、障害発生時には10個のPRの中から原因を特定することが困難になります。逆に1に設定すると、原因特定は容易になりますが、PRが多数待機している場合に待ち時間が増加します。 キューの長さを計測する必要性 この関係を考慮してパラメータを調整するには、「現在のマージキューで待機しているPRがどの程度あるか」というデータが必要です。キューに待機しているPRがなければ設定を変更する必要はありませんが、常に多数のPRが待機している場合は、CIの並列数を増やすなどの対策を検討する必要があります。 しかし、キューの長さや待ち時間といった情報は、GitHubの標準機能では提供されていません。このため、キューの長さを計測し、可視化する仕組みを構築しました。 キューの長さを計測する方法 私たちのチームでは、GitHub Actionsを利用してキューの長さを計測し、Datadogへ送信しています。 その実装で利用している方法を紹介します。 gh コマンドによるキュー長の取得 GitHubマージキューの現在の長さは、GitHubのGraphQL APIを通じて取得できます。 gh コマンドを使えば、これを1行のコマンドで簡単に行えます。 使用するコマンドは以下の通りです。 QUEUE_COUNT=$(gh api graphql -f query=' query { repository(owner: "THIS_IS_ORG_NAME", name: "THIS_IS_REPO_NAME") { mergeQueue(branch: "DEFAULT_BRANCH_NAME") { totalCount: entries { totalCount } } } } ' --jq '.data.repository.mergeQueue.totalCount.totalCount') このコマンドは、GraphQLクエリで必要なデータ ( totalCount ) を指定し、 gh コマンドの --jq フラグでレスポンスから値を直接抽出しています。 このコマンドを、 on.merge_group (PRがマージキューに追加された時)をトリガーにしたGitHub Actionsで実行します。その結果をモニタリングツール(私たちの場合はDatadog)に送信することで、キューの長さを時系列グラフとして可視化できます。 マージキューに入っている Pull Request の数の時系列グラフ このダッシュボードによって「どの時間帯にマージが集中するのか」「現在のパラメータ設定でキューが効率的に処理されているか」といった状況を把握できるようになりました。 データに基づくパラメータ調整の実際 このダッシュボードを2週間運用した結果、私たちのチームでは同時にマージキューに積まれていたPRは最大でも 3件 であることが分かりました。 この実績データに基づき、安定性をさらに高めるため、パラメータを以下のように調整しました。 Maximum pull requests to merge : 変更前 5 → 変更後 3 Build concurrency : 変更前 10 → 変更後 6 一度にマージするPR数を実績値(3件)に合わせ、ビルドの並列数( Build concurrency )をその2倍に設定しました。これにより、リソースを効率的に使いつつ、より安定した運用を目指しました。 まとめ マージキューは導入するだけでも一定の効果がありますが、その効果を高めるには、開発の規模や状況に応じてパラメータを継続的に調整することが重要です。その調整は、勘や感覚ではなく、今回紹介したような可視化されたデータに基づいて行うことが推奨されます。 今回はキューの可視化とパラメータ調整について解説しました。次回以降も、マージキューをより効果的に活用するための情報をお届けします。
こんにちは、タイミーでバックエンドのテックリードをしている新谷 ( @euglena1215 ) です。 このシリーズでは 「モノリスRailsにマージキューを導入してデプロイフローを安定させる」 の続編として、導入時のTIPSを紹介しています。前回は 「GitHubマージキューTIPS:CIの実行を最適化し、障害対応を10分高速化する」 について解説しました。 本記事では、GitHubのマージキュー導入後に発生した、ブランチ保護機能(Ruleset)のbypass list機能との非互換性について解説します。 これまでのコードフリーズ運用 タイミーでは、主に年末年始やGWといった開発者が少ない期間にコードフリーズ期間を設けています。この運用を実現するため、我々はGitHubのRulesetsと、そのbypass list機能を活用していました。 これは非常に便利な機能で、以下のような運用を可能にしています。 通常時: 開発者は自由にマージできる。 コードフリーズ期間中: Rulesetを有効化し、原則マージを禁止する。 緊急時: ただし、bypass listに登録された開発者のみ、チェックボックス一つでこのルールを回避し、緊急の修正をマージできる。 この仕組みで、コードフリーズ期間中の安全性と、緊急時の柔軟な対応を両立していました。 マージキュー導入後に発覚した問題 マージキューを導入し、順調に運用が始まったかのように思えたある日、コードフリーズ期間直前に問題が発覚しました。 bypass listに登録されているにもかかわらず、ルールを回避してマージすることができなくなっていたのです。 コードフリーズ期間中にコードを変更することは基本ありませんが、例えば障害対応で緊急の修正が必要になった際に、これまでのように特定の担当者が即座にマージできなくなる、という影響が考えられます。これは、柔軟な対応を期待していた開発者にとっては意図しない仕様変更でした。 原因と対応 仕様上の非互換性 調査の結果、マージキューとRulesetのbypass機能は併用できないGitHubの仕様であることが分かりました。この件はGitHubの公式Discussionでも報告されています。 ref. https://github.com/orgs/community/discussions/45208 この仕様に対する直接的な解決策は見つからなかったため、bypass listを使用しない運用への変更が必要になりました。 新しい運用への変更 代替案として、以下の運用を構築しました。 コードフリーズ期間中、 常に失敗するCIジョブ をワークフローに追加する。 ただし、このCIジョブはブランチ保護ルールの 必須チェックには設定しない 。 これにより、開発者はCIの警告表示からコードフリーズ期間中であることを認識でき、意図しないマージの抑止につながります。 まとめ GitHubのマージキューは有用な機能ですが、Rulesetのような既存の機能と組み合わせる際には、意図しない動作をしないか注意が必要です。(この記事は2025年7月時点のGitHubの仕様に基づいています。) 私たちのケースでは、導入後にこの問題が判明し、コードフリーズ直前の対応が必要となりました。 マージキューの導入を検討する際は、通常のデプロイフローだけでなく、コードフリーズのような特定の運用条件下でも意図した通りに動作するか、事前に検証することを推奨します。 特に、ご自身のチームが以下の点に当てはまるか、一度確認してみてください。 ブランチ保護(Rulesets)で、特定の担当者やチームにマージの例外(Bypass)を許可しているか? その例外的なマージは、緊急時の対応など、今後も必要な運用か? 私たちのケースでは、導入後にこの問題が判明し、コードフリーズ直前の対応が必要となりました。 さて、次回はマージキューのポテンシャルを最大限に引き出すための「詰まり具合の可視化」と、パラメータチューニングについてご紹介します。
こんにちは、タイミーでバックエンドのテックリードをしている新谷 ( @euglena1215 ) です。 このシリーズでは 「モノリスRailsにマージキューを導入してデプロイフローを安定させる」 の続編として、導入時に工夫した点や直面した課題をTIPS形式で紹介しています。前回の記事では 「GitHubマージキューの制約:マージメソッドが1つに強制される」 について解説しました。 今回は、マージキューの特性を活かして CIの実行方法を最適化し、特に緊急時のデプロイを高速化した 話を紹介したいと思います。 Pull RequestにおけるCIは本当に必須か? マージキューの最も基本的な機能は、エンキューされたPull Request(PR)を 常に最新の master ブランチに取り込んだ状態でCIを実行する ことです。これによりmaster ブランチのCI成功が保証されるため、私たちはまず「master ブランチへのマージ後のCI」を不要と判断しました。 さらに、私たちはもう一歩踏み込んで考えました。 「そもそも、PR上でのCI実行も必須ではなくなったのでは?」 仮にPR単体でCIが失敗したとしても、その変更はマージキューのCIで検知され、キューから自動的に取り除かれます。master ブランチが壊れることはないため、PR作成時のCIはあくまで開発者のための任意実行とし、マージをブロックする「必須チェック」から外せるのではないか、という発想です。 CIを「必須」と「任意」に分ける方法 この「PRでのCIを必須としない」運用を実現するには、一つ技術的な壁がありました。 GitHubの仕様上の壁 GitHubの仕様では、PRの必須チェック(Required Check)とマージキューの必須チェックを分けることができません。マージキューでマージ前にチェックしたいCIはPRでも常に実行する必要があります。 こちらはマージキューへのフィードバックとして挙がっていますが、2025年7月時点では対応されていませんでした。 ref. https://github.com/orgs/community/discussions/46757#discussioncomment-4912738 PRでの必須チェックを外すためにチェックを外すと、マージキューでも必須ではなくなってしまい、CIが実行されないままマージされる問題が生じます。 ワークフロー分割による解決策 そこで我々は、CIのコアロジックを再利用可能なワークフロー( _ci.yml )として切り出し、それを呼び出す2つのワークフローに分割することで、この問題を解決しました。 1. ci.yml(マージキューでの必須CI) これをブランチ保護ルールの必須チェックに設定します。このワークフローは push イベントと merge_group イベントの両方でトリガーされますが、 github.event_name を判定し、 merge_group イベントでない場合は skip: true を渡すことで、CIの実行をスキップします。 これにより、「必須チェックとしては存在するが、PR上では即座に完了(スキップ)し、マージキューでのみ実行される」状態を作り出せます。 # .github/workflows/ci.yml name: ci on: push: branches: - '**' - '!master' merge_group: jobs: ci: # ... uses: ./.github/workflows/_ci.yml with: # merge_group イベントでない場合は true を渡し、ワークフローをスキップさせる skip: ${{ github.event_name != 'merge_group' }} secrets: inherit 2. ci_branch.yml(PRでの任意CI) こちらは必須チェックには設定しません。 push イベントでのみトリガーされ、常に skip: false を渡してCIを実行します。開発者はこのCIの結果を参考にしますが、完了を待たずにエンキューできます。 # .github/workflows/ci_branch.yml name: ci branch on: push: branches: - '**' - '!master' jobs: ci: uses: ./.github/workflows/_ci.yml with: # こちらは常に false を渡し、CIを実行させる skip: false secrets: inherit この構成により、「PR上ではCI実行は必須ではないが、マージキューではCI実行が必須」という状態を実現しました。 実行結果を確認する 挙動を確認するために、実行結果を確認してみましょう。 PR上では、ci.yml と ci_branch.yml が実行されます。必須であるci.ymlはほとんどのステップがskipされているので全体が数秒で確認できます。対して、ci_branch.ymlでは数分かかっていますが、必須ではないので実行途中でもマージキューにエンキューできます。 PR上でのci.ymlの実行結果 PR上でのci_branch.ymlの実行結果 対して、マージキュー上ではci.ymlのみが実行されます。マージキューで実行した場合、ci.ymlはskipされずに実行されるので、CIが失敗しているのにmasterブランチにマージされてしまうといったリスクはありません。 マージキュー上でのci.ymlの実行結果 障害対応のデプロイを10分短縮 この最適化は、特に緊急の修正(Revertなど)をデプロイする際に大きな効果を発揮します。 変更前 featureブランチのCI(10分) + masterマージ後のCI(10分) + デプロイ(5分) = 合計25分 変更後 マージキューのCI(10分) + デプロイ(5分) = 合計15分 結果として、障害発生から復旧までの時間を 10分短縮 できました。 まとめ マージキューはmaster ブランチを安定させるための機能ですが、その特性をうまく利用し、CIの実行方法を工夫することで、デプロイの安定化とデプロイの高速化を両立させることができました。まさに一石二鳥の改善だったと感じています。 次回は、マージキュー導入時に発覚した、GitHubのブランチ保護機能(Ruleset)との思わぬ非互換性について紹介します。
こんにちは、タイミーでバックエンドのテックリードをしている新谷 ( @euglena1215 ) です。 先日公開した記事 「モノリスRailsにマージキューを導入してデプロイフローを安定させる」 では、多くの開発者が関わるモノリスリポジトリのデプロイフローを安定させるために、GitHubのマージキューを導入した事例を紹介しました。 今回からは、導入にあたって直面した課題や、我々の開発プロセスにうまく組み込むために工夫した点などを、TIPSとして何回かに分けて紹介していきます。 シリーズ最初のトピックは、マージキューを導入すると直面するマージメソッドの制約についてです。 開発者の自由がなくなる?マージフローの変化 マージキューを導入すると、開発者のマージ作業のフローが大きく変わります。最も大きな変化は、開発者が直接「Merge」ボタンを押すのではなく、「Merge when ready」ボタンでエンキュー(マージキューに追加)する点です。 エンキューされたPull Requestのマージ作業そのものは、開発者ではなくbotが内部的に自動的に行うようになります。 マージメソッドを指定できない仕様 2025年7月時点でのGitHubマージキューの仕様では、各開発者がエンキュー後のマージメソッドを選ぶことはできません。代わりに、リポジトリの設定として、どのマージメソッド(Merge commit, Squash and merge, Rebase and merge)を使うかを指定しておく必要があります。 結果として、 これまで開発者が個人の好みでマージメソッドを選んでいた運用はできなくなり、全員が同じメソッドを使うことを強制されます。 我々が行った選択とそのプロセス マージキューを導入するにあたり、我々は Merge commit と Squash and merge のどちらに統一するか、という選択を迫られました。 各選択肢の課題の比較 それぞれの設定をデフォルトにした場合に、開発者にどのような影響が出るかを比較検討しました。 Squash and merge を選択した場合の課題: 意図的に複数のコミットに分けているプルリクエストが、マージ時に強制的に1つにまとめられてしまいます。さらに、GitHubのUI上で自動生成されるコミットメッセージは、個々のコミットメッセージを単純に連結したものになり、マージ時にメッセージをきれいに整形することができません。 Merge commit を選択した場合の課題: これまで feature branch 上で作業途中のコミットを細かく積み、マージ時にUI上で1つにまとめていた開発者にとっては、整形前のコミットがそのまま master ブランチの履歴に残ってしまうことになります。 我々の決定:「Merge commit」の採用と運用によるカバー 両者を比較した結果、我々はリポジトリのデフォルト設定として Merge commit の採用を決定しました。 決め手は、 Squash and merge を選択した際の「コミットメッセージが適切に整形できない」という制約の影響が大きいと判断したためです。 その上で、 Merge commit を選択した場合の課題(整形前のコミットが残ってしまう)については、運用でカバーする方針としました。 具体的には、コミットを1つにまとめたい開発者に対し、「マージキューに入れる前に、 feature branch 上で git rebase -i などを使って事前にコミットを整理してもらう」という協力をお願いすることにしました。 この運用により、意図したコミット履歴をそのまま残したいケースと、複数のコミットを1つにまとめてマージしたいケース、その両方に対応できると考えました。 この決定の背景と具体的な運用ルールをドキュメントにまとめ、開発者全員に協力を依頼することで、スムーズな移行を目指しました。 まとめ GitHubのマージキューはデプロイフローを安定させる有用なツールですが、一方で、チームの開発スタイルに影響を与える制約も存在します。特に、マージメソッドが1種類に固定される点は、導入前にチーム内でコンセンサスを取っておくべき重要なポイントです。 この「マージメソッドが強制的に固定される」という仕様は、見落とされがちなポイントだと思いましたので、最初のTIPSとして紹介しました。 次回は、マージキューの特性を活かして、障害対応時のCI待ち時間を短縮した工夫についてご紹介します。
GitHubマージキュー導入時のGitHub Actions CI設定変更 こんにちは、タイミーでPlatform Engineerをしている近藤です。 今回は、GitHubのマージキュー(Merge Queue)に対応するために、GitHub ActionsのCI設定を修正した話を紹介します。 TL;DR GitHubのマージキュー(Merge Queue)を導入する場合、以下の設定が必要です。 Rule Sets(Branch protection rule)で「Require status checks to pass」を有効化 「Merge Queue」の有効化 CIワークフロー(ci.yml)の変更 merge_group イベントの追加 gh-readonly-queue/** ブランチをpushイベントから除外 GitHub Actionsの従来のCIワークフロー まず、従来のCIワークフロー(ci.yml)の設定を振り返ります。元々の設定は以下のようになっていました。 name : ci on : push : branches : - '**' - '!master' tags-ignore : - '*' concurrency : group : ${{ github.workflow }}-${{ github.ref }} cancel-in-progress : true permissions : id-token : write contents : read pull-requests : write jobs : ci : uses : ./.github/workflows/_ci.yml secrets : inherit この設定では、masterブランチ以外のすべてのpushイベントでCIが実行されます。 デプロイまでの従来の流れ タイミーのdeployワークフローはGitHub Flowを採用していたため、以下のような流れになっていました。 PRを作成し、CIが通ることを確認。 PRをmasterブランチにマージ。 マージによってmasterにpushが発生し、デプロイ用ワークフロー(deploy_prod.yml)が実行される。 deploy_prod.yml は次のようになっています。 name : deploy_prod on : push : branches : - master jobs : deploy : runs-on : ubuntu-latest steps : - name : Checkout uses : actions/checkout@v4 # デプロイ処理... GitHubでの設定変更(Rule Sets) マージキューを使うには、GitHubの設定画面から「Rule Sets」(従来はブランチプロテクションルール)を設定します。 多くのケースではすでにステータスチェック必須(Require status checks to pass)の設定がされていると思いますので、その場合は「Merge Queue」を追加でONにするだけです。 GitHub ActionsのCIワークフロー変更 PRからマージキューに積まれた際、 gh-readonly-queue/xxxx というブランチが作成されるため、CIワークフロー(ci.yml)に以下の変更が必要になりました。 name : ci on : push : branches : - '**' - '!master' + - '!gh-readonly-queue/**' tags-ignore : - '*' + merge_group : concurrency : group : ${{ github.workflow }}-${{ github.ref }} cancel-in-progress : true permissions : id-token : write contents : read pull-requests : write jobs : ci : uses : ./.github/workflows/_ci.yml secrets : inherit ポイント merge_group イベントを追加することで、マージキューにエンキューされたときにCIが実行されます。 gh-readonly-queue/** を除外することで、不要な二重実行を防ぎます。 注意点 merge_group イベントは単独で定義できず、必ず他のイベントと一緒に定義する必要があります。 GitHub公式ドキュメント - merge_group The merge_group event cannot be the only event defined in a workflow. 変更が不要なワークフロー デプロイ系ワークフロー(例: deploy_prod.yml )など、masterブランチへのpushのみで動作するワークフローは、マージキュー対応後も変更不要です。 おわりに GitHubのマージキューは導入が比較的簡単ですが、既存のGitHub Actionsにも影響を与えます。本記事を参考に、スムーズにマージキューを導入していただければ幸いです。 最後までお読みいただき、ありがとうございました!
こんにちは、タイミーでバックエンドのテックリードをしている新谷 ( @euglena1215 ) です。 タイミーのバックエンドは、多くの開発者が関わるモノリスなRailsアプリケーションを中心に構成されています。本記事では、このモノリスリポジトリのデプロイフローを安定させるためにGitHubのマージキューを導入した事例を紹介します。 本記事が、masterブランチにマージしたコードでCIが頻繁に失敗し、開発プロセスに影響が出ているチームの参考になれば幸いです。 masterブランチのCIが頻繁に失敗していた タイミーのモノリスRailsリポジトリでは、1日に20件以上のPull Requestがマージされることもあります。多くの開発者が同時に開発を進める中で、ある問題が頻発していました。 それは「他の人の変更がmasterブランチに取り込まれたことに気付かず、古いmasterを元にしたPull Requestをマージしてしまい、結果的にmasterブランチでCIが失敗する」という事象です。 masterブランチでCIが失敗する図 この事象により、開発チームに次のような影響が出ていました。 リリース遅延 masterが一度CIに失敗すると、原因の特定と修正(Revertなど)が終わるまで、誰もデプロイできなくなります。これにより、ユーザーに届けたい価値をタイムリーに届けられない事態が発生していました。 コンテキストスイッチとコミュニケーションコストの増大 masterのCI失敗は、Slackでの全体周知、原因調査の依頼、マージの一時停止呼びかけなど、多くの開発者を巻き込むコミュニケーションを発生させ、チーム全体の生産性を低下させていました。 実際に、2025年のある2ヶ月間を調査したところ、masterブランチでのCI失敗のうち、 最新のmasterを取り込んでいれば防げた可能性が高いものは6件 ありました。この課題を解決するため、我々は解決策の検討を開始しました。 なぜ「マージキュー」だったのか? この問題を解決するにあたり、我々はGitHubマージキューを選択しました。その背景をご説明します。 まず、解決策として考えられる「すべてのPull Requestは、マージ直前に必ず手動で最新のmasterを取り込む」というルール運用は、1日に20件以上もマージされるリポジトリでは現実的ではありませんでした。CIの待ち時間や再レビューのコストを考えると、開発速度の低下は避けられないと判断しました。 一方で、タイミーでは既にGitHub Enterprise Cloudを導入済みでした。そのため、マージキューは追加コストや新たなセキュリティレビューなしに利用できる機能でした。 既存のプラットフォームの機能を活用することは、我々にとって合理的な判断でした。そのため、他のサードパーティツールを比較検討することはせず、マージキューの導入にフォーカスして調査を進めることにしました。 解決策:GitHubマージキューとは? GitHubのマージキューを改めて説明すると「masterブランチにマージされる前に、最新のmasterと合体させた状態でCIを実行し、成功したものだけを自動でマージする仕組み」です。 開発者がPull Requestをマージキューに追加すると、GitHubは内部的に一時的なブランチを作成し、その時点での最新のmasterとPRの変更をマージしてCIを実行します。CIが成功すれば、その変更がmasterにマージされる、という仕組みです。 【重要】GitHub Enterprise Cloudが前提 繰り返しになりますが、GitHubのマージキューはprivateリポジトリで利用する場合、GitHub TeamsプランではなくGitHub Enterprise Cloudプランの契約が必要となります。 詳しくは公式ドキュメントをご覧ください。 docs.github.com まとめ GitHubマージキューを導入したことで、課題であった「古いmasterとの競合によるCI失敗」はなくなり、masterブランチがCIの成功した状態を維持できるようになりました。 この結果は、ただ機能を有効化しただけで得られたものではありません。私たちは、本格導入に先立ち、マージキューをテスト環境で検証しました。その結果、ただ有効化するだけでは我々の開発フローとの互換性を保つのが難しく、いくつかのチューニングが必要なポイントが明らかになりました。 これらのポイントに事前に対処したことが、スムーズな導入の鍵となりました。 次回の記事では、この導入を成功に導いた、具体的な検証内容と、それに基づいて我々が実装したチューニング方法(GitHub Actionsのワークフロー設定など)について、詳しく解説していきたいと思います。 tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp
タイミーでは、Flaky Test がデプロイの妨げになることで開発効率が悪化していました この問題を解決するため、AI エージェント「Devin」を活用し、Flaky Test の検出から修正プルリクエストの作成までを完全に自動化しました 結果、CIは安定し、開発者は本来の業務に集中できるようになったことで、開発体験が向上しました こんにちは!タイミーでバックエンドエンジニアとして働いている 福井 ( bary822 ) です。 皆さんは Flaky Test に悩まされた経験はないでしょうか? タイミーでも、Flaky Test によって CI の信頼性が低下し、開発者の貴重な時間を奪ってしまうという課題を抱えていました。 ある期間においては master ブランチにおけるテスト実行の 4.5% が Flaky Test によって失敗しており、20+回/日 の頻度でデプロイされていることを考えると1日に1名は CI を re-run せざるを得ない状態に陥っていました。 この記事では、根深い Flaky Test 問題を解決するために、Devin を活用して修正プルリクエストの作成を自動化し、CI の安定化と開発体験の向上を実現した取り組みについてご紹介します。 私たちが抱えていた課題 Flaky Test を放置すると開発チーム全体に様々な悪影響を及ぼします。私たちが直面していた主な課題は以下の通りです。 開発効率の悪化 : 問題ないはずの Pull Request の CI が Flaky Test によって失敗すると、開発者は本来不要な原因調査や CI の再実行に時間を費やすことになります。多くの人にとって一定の緊張が発生するデプロイ作業の一環として実行される CI が失敗するというのは精神的にも大きな負担となります。 デプロイの遅延 : master ブランチの CI が失敗すると、デプロイ担当者はそれが Flaky Test によるものかどうかを切り分ける調査を強いられていました。 Flaky Test だった場合は再実行によってその場を凌ぐことが常態化しており、迅速な価値提供の妨げとなっていました。これは、ビジネスの機会損失にも繋がりかねません。 CI における品質保証の機能不全 : テストの成否が不安定なため、master ブランチで既存機能が正しく動作することが保証されているかどうかを正確に判断できなくなります。私たちの場合はその多くが「テストは正しく書かれているが何らかの不安定な要因によって失敗することがある」ケースだったため、実質的な品質の低下はほとんど発生していませんでした。しかし、その反対(本来失敗すべきなのにたまたまパスしてしまう)が発生していたとしても「また Flaky か…」と見逃されてしまいコードの修正が遅れる可能性がありました。 これらの課題を解決し、開発者全員が安心して高速に開発を進められる環境を作るため、私たちは Flaky Test の早期発見と修正を自動化する仕組みの構築に乗り出しました。 解決策:Devin による Flaky Test 修正の完全自動化 私たちは、以下のステップで Flaky Test の特定から修正までを自動化する仕組みを考案しました。 Flaky Test の自動検出 : CI 環境で実行されるテストの実行データを Datadog (Test Optimization)に送信し、Flaky Test を自動で検出する Devin による修正PRの作成 : 新しい Flaky Test が検出されると、それをトリガーに GitHub Actions のワークフローを起動する。ワークフローは、テストファイル名やエラーメッセージなどの情報をプロンプトに含めて API 経由で Devin に渡し、修正プルリクエストの作成を依頼する。 レビューとマージ : Devin によって作成されたプルリクエストは、 CODEOWNERS の設定に基づいて適切なチームに自動でレビューが割り当てられます。チームは、Devin が提案した修正内容を確認し、必要に応じて変更を加え、マージします。 この仕組みの全体像は以下のようになっています。 Flaky Test の発見から修正の「叩き台」作成までを自動化する このフローにより、Flaky Test の発生から修正提案までが完全に自動化され、開発者は Devin が作成した Pull Request をレビューするだけでよくなりました。 もちろん Flaky Test の発見自体が誤検知である可能性もあるため、その場合はチームの判断でクローズします。 また、Devin が誤った原因仮説に基づいた望ましくない修正を提案する場合もあるため、必要なら追加の変更を行ったり、新しい Pull Request を作成したりして柔軟に対応します。 いずれにせよ Flaky な状態が疑われるテストが発見されると、ほとんど同じタイミングで担当するチームがそれを認識し、修正の「叩き台」がすでに作成されている状態を実現することができました。 Devin はどのようにテストを修正するのか? 「Devin が本当に Flaky Test を修正できるのか?」と疑問に思う方もいるかもしれません。 私たちも最初は半信半疑でしたが、Devin は当初の期待を上回るほど的確な修正を提案してくれています。 これは、Devin に渡しているプロンプトの一部です。再現手順の特定や、 Pull Request の体裁、修正の勘所などを細かく指示しています。 レビュアーやラベルなど、Pull Request 上で設定する静的な項目に関しては期待値を宣言的に定義し、CLIコマンドの返り値によってその検証を行うように指示しているのが重要なポイントです。 こうすることで、Devin 自身がセルフチェックを行いやすくして求める出力を安定的に得られるようにしています。 以下の Flaky Test の修正を行い、${レポジトリ名} に Pull Request を作成してください。 # テスト情報 ## テストファイル ${Flaky Test が発生したテストファイル名} ## テストケース ${Flaky Test が発生したテストケース名} ## エラーメッセージ(先頭20行) ${テスト失敗時のエラーメッセージとスタックトレース} ## 実行コマンド ${テストの実行コマンド} (CI環境ではテストファイルを分割して並列実行しているため、どのテストファイルをどの順番、Seed値で実行しているかの情報が必要) ## 問題発生時のコミット ${直前の Commit の SHA} # 作業内容 1. テストコードの修正 2. 修正後、当該テストをローカル環境で5回実行し、全て成功することを確認 - seed値を変えながらテストを実行する時は、1つ以上の他のテストファイルも同時に実行 - 複数のテストファイルに渡ってランダムな順番でテストが実行されるようにしたい 3. 以下の要件を満たす Pull Request をDraftで作成 - タイトル: flaky: (原因と修正内容を簡潔に記載) - コードオーナーの設定に従ってレビューリクエストを送信。コードオーナー不在の場合は ${コードオーナー不在の場合に対応する GitHub Team 名} に送信 4. CIが成功したら、Pull Request を Open に変更 # Pull Request の description に含める情報 - 発生していた問題の概要 - 修正内容とそれによって Flaky が解消されると判断した理由 - Datadog 上のテスト結果ページのURL # 重要な注意事項 ## 制約 - 修正内容は最小限に抑え、テストの意図を変更しないようにしてください。 - 他の spec ファイルで使用されている既存のパターンに合わせた実装を行ってください - 可能な限り修正前に失敗するまで条件を変えながらテストを実行し、失敗したときの実行コマンドなどの再現手順を明記してください。 - テストの失敗を再現するときには並列実行環境下で自然に発生し得る条件を設定してください。特定のデータを手動で作成するなどすることは禁止します。 - テストの修正によって Flaky が解消されると判断した理由を明記してください。 ## 検証コマンド 以下のコマンドで各項目が正しく設定されていることを確認してください: ### PRステータスが Open であることの確認 \`\`\` bash gh api repos/${レポジトリ名}/pulls/{pr _ number} --jq '.state, .draft' # 期待値: "open" と false が表示される \`\`\` ### レビュアーが追加されていることの確認 \`\`\` bash # 変更したファイルにコードオーナーが設定されている場合 gh api repos/${レポジトリ名}/pulls/{pr _ number}/requested _ reviewers # 期待値: teams配列に コードオーナーのTeam名 が含まれる # 変更したファイルにコードオーナーが設定されていない場合 gh api repos/${レポジトリ名}/pulls/{pr _ number}/requested _ reviewers # 期待値: teams配列に "${コードオーナー不在の場合に対応する GitHub Team 名}" が含まれる \`\`\` ### devin-fix-flaky-test ラベルが設定されていることの確認 \`\`\` bash gh api repos/${レポジトリ名}/issues/{pr _ number}/labels # 期待値: name が "devin-fix-flaky-test" のオブジェクトが含まれる \`\`\` # 参考情報 - テストはファイルごとに一定のまとまりで分割されて並列実行されており、ランダムに設定されたSeed値を使って実行順序を制御しています - それぞれの実行環境では独立したデータベースが用意されており、実行環境間でデータが共有されないようにしています このプロンプトに基づき、Devin は様々なパターンの Flaky Test を修正してくれました。 ここでは、その中から代表的な2つの例をご紹介します。 修正例1: バリデーションエラーによる不安定性の解消 開始、終了時間を定義する2つの DateTime 型のカラムによって計算される値に依存するバリデーションのテストにおいて、処理時間とタイミングによっては失敗するケースがありました。 Before: context ' ... ' do before do create( :offering , :just_working ) end end offering はいわゆる「求人」を表現するモデルです。 just_working trait では稼働時間がちょうど6時間になるように設定されています。 trait :just_working do start_at { Time .current.ago( 5 .hours) } end_at { Time .current.since( 1 .hour) } end 労働基準法では6時間を超えると45分以上の休憩が義務付けられます。この場合はギリギリ6時間なので休憩時間が0分でも offering レコードの保存に成功します。 しかし、開始・終了時間( start_at と end_at )はそれが設定されるときの現在時刻に依存しているため、 start_at が設定された後のタイミングでちょうど1秒をまたいでしまうと、 end_at = start_at + 6時間 + 1秒 となってしまうため、休憩時間が設定されていないとバリデーションエラーが発生してしまいます。 ActiveRecord :: RecordInvalid : 労働時間が 6 時間を超えています。法定休憩時間を満たすように休憩時間を設定してください。 After (Devinによる修正): context ' ... ' do before do create( :offering , :just_working , :with_rests ) # :with_rests trait を追加 end end Devinは、 with_rests trait を追加することで、6時間超の労働時間に対して法定休憩時間(45分以上)を自動的に設定するように修正しました。 これにより、バリデーションエラーを回避し、テストが安定して成功するようになりました。 修正例2:FactoryBot のランダムデータ生成による不安定性 FactoryBot で生成されるランダムなデータが、テスト対象のメソッドの条件分岐に影響を与えて Flaky になっていたケースがありました。 Before: describe ' ... ' do let( :client ) { create( :client ) } context ' ... ' do let( :serializer ) { BrandUserSerializer .new(brand_user, client_id : client.id) } let( :brand_user ) { build_stubbed( :brand_user ) } # brand_user に client が紐づく it { expect(serializer.kind).to eq :other } end end このとき BrandUserSerializer#kind メソッドは次のように実装されていました。 def kind if @brand_user .client_id == @client_id :manual else :other end end BrandUserSerializer のインスタンス生成時の第一引数として渡された brand_user に紐づく cliend_id と、第二引数として直接渡された client_id の値を比較し、同一であれば :manual を、そうでなければ :other を返します。 このテストでは異なる値が設定される :other を期待値としていました。しかし、 build_stubbed では ID がランダムに設定されるため、ごく僅かな確率で第二引数として渡された client.id の値と一致することがあります。 この場合 .kind は :manual を返すためテストが失敗してしまいます。 After (Devinによる修正): describe ' ... ' do let( :client ) { create( :client ) } context ' ... ' do let( :serializer ) { BrandUserSerializer .new(brand_user, client_id : client.id) } # 明示的に別の client を作成して確実に異なる client_id が返るようにする let( :other_client ) { create( :client ) } let( :brand_user ) { build_stubbed( :brand_user , client : other_client) } it { expect(serializer.kind).to eq :other } end end Devinは、明示的に other_client を作成し、 brand_user に設定することで、確実に異なる client_id を持つようにしました。 この変更により、serializerの条件分岐で正しく :other が返されるようになり、テストが安定して成功するようになりました。 導入後の成果と今後の展望 これを書いている時点で 3件 の Flaky Test を修正する Pull Request が Devin によって作成されましたが、そのうち 2件 は開発者によって変更が加えられることがなくマージされました。 結果として、CI の成功率は安定し、開発者は Flaky Test による手戻りや不要な調査から解放され、より価値のある機能開発に集中できるようになりました。 Devin が作成した Pull Request を「叩き台」として、チーム内で修正方針を議論したり、追加の変更を加えたりといった、より建設的な活動も生まれていることも重要なポイントです。 今後は、さらにプロンプトを洗練させ、より複雑な Flaky Test にも対応できるように改善を続けていく予定です。また、今回の成功を足がかりに、Flaky Test 修正以外の開発プロセスにも積極的に AI を活用していくことを検討しています。 おわりに 今回は、 Devin を活用して Flaky Test の修正を自動化し、CI の安定化と開発体験の向上を実現した事例をご紹介しました。AI を開発ワークフローに組み込むことで、これまで人間が時間をかけて対応していた退屈な作業をなくし、より創造的な仕事に集中できる環境を作ることができます。 この記事が、同じように Flaky Test に悩む開発者の皆さんにとって、少しでも参考になれば幸いです。 最後までお読みいただき、ありがとうございました!
はじめに こんにちは。タイミーでAndroidエンジニアをしている Hunachi(ふなち) です。 2025年6月25日から26日に開催されたdroidcon NYC 2025に参加してきました。このブログでは、droidcon NYCの雰囲気と、特に印象に残ったセッションについてご紹介します! droidcon NYC 2025の雰囲気 参加者は 700名以上 、セッションは4つのステージで 80以上 と、DroidKaigiとほぼ同規模か少し小さいくらいのイベントでした。 主にアメリカで働くAndroidエンジニアが集まっており、私が話した方々はニューヨーク近郊だけでなく、アメリカ各地から数時間かけて来ている方がほとんどでした。弊社社員を除く日本からの参加者には出会いませんでした。 また、同じ会場で Fluttercon も開催されており、Flutterエンジニアとの交流も楽しめました。 興味のあるセッションを多数聞けたのはもちろんのこと、海外のエンジニアの方々と交流できたのは貴重な経験でした。 英語をスラスラと喋れる訳ではないのですが、他の参加者の方々がとても優しく接してくださり、楽しい時間を過ごせました。Googleの社員の方やスピーカーの方に直接質問できる機会もあり、非常に有意義でした。 一緒にセッションを聞きいたりお話ししたりしてました! ランチの時間でも他の参加者と交流することができました! Day2には、前日に仲良くなった人たちと一緒にセッションを聞いたり、おしゃべりしたりできました。ランチの時間も他の参加者と交流することができ、自分から喋りかけに行けば他の参加者と楽しくコミュニケーションが取れる雰囲気でした 🤝 聞いてきたセッションの一部を紹介します! Panel: The Future of Dependency Injection in Modern Android このパネルディスカッションでは、現代のAndroid開発におけるDI(依存性注入)の未来について議論されていました。 KMP(Kotlin Multiplatform)では「Metro」というDIフレームワークがよく使われる。 DIの原則自体は複雑ではない。我々は問題解決に集中すべきで、DIのことを気にするのは良くない。 サービスロケーターは避けるべきで、依存関係はコンパイル時に解決すべき。 DIフレームワークは早めに導入を決定することが推奨で、移行にはコストがかかるため注意が必要。 CompositionLocal はグローバル変数のように使われることがあり、コンパイル時にエラーにならないためリスクがある。 など、AndroidやKMPの最前線を走っている方々からDIに関するお話を聞くことができて、とても勉強になりました。 Tackling Memory Issues on the Instagram Android App at Scale InstagramのAndroidアプリにおける大規模なメモリ問題への対処法についてのセッションでした。 アプリでユーザーがコンテンツを編集中に落とさないための工夫や、メモリが足りずにアプリがクラッシュする時の調査方法(HPROFファイルを使った調査)の説明がありました。 特に印象的だったのは、メモリについて詳しくなりたいなら「 Runtime.getRuntime() 」や「 /proc/meminfo 」から取得できるデータなど見ると良いという細かなアドバイスがあったことです。大半の普通のAndroidエンジニアは一生触れないだろう内容ですが、前職でメモリと向き合ったことのある私にとってはとても興味が湧く内容でした。 The Future of Android...And How to Prepare For It Androidの未来と、それに向けてどのように準備すべきかについてのパネルディスカッションでした。 AIの進化により、スクリプトだけで開発できる時代が来ており、将来的にはコードの70%がAIによって生成されるだろう。 エンジニアはより複雑な問題を解決するために働くようになってきている。 AIによるポジションの削減などもありますが、逆にAIのおかげで私たちもあらゆる分野で働けるようになるため、ポジティブな側面も多くある。 このようなカンファレンスでいろんな人と問題など色々なことについて話す等、エンジニア同士の交流も重要になってくる。 AIにより学ぶことも前より容易になっている。 一般的な知識(いろんな言語や分野)を身につけることが大切。 といった白熱したトークが行われていました。 弊社でもAIの活用はとても推奨されているのでAIを使った開発が日常になりつつはあるものの、このパネルディスカッションを聞いて、私ももっとAIを活用して今までよりも多くの分野で、より多くの作業量をこなすことができる人材になりたいなと思いました。 Career Office Hours with Stacy Devino Stacy Devino氏によるキャリアに関するオフィスアワーにも行きました。 キャリアを考える上で大切だと言われていたことのうち印象に残ったものは、 経済的に安心できる状況を作る AIでカバーできない範囲など ユニークなスキルを持つ 自分が何を楽しんで、何が得意かを認識する ビジネスプロセスや効率化について学習する レイオフの危機 を感じたら、事前に準備する の5つです。 レイオフが日本よりも身近なアメリカだからこその話も聞けてとても為になりました。 Server Driven UIs: the future of cross-platform rendering architectures サーバー駆動型UI(SDUI)についてのセッションでした。 SDUIはUIのデータをサーバー側に持たせて、動的なUI変更を可能にする仕組みのことなのですが、個人的にとても親しみのある内容でした。 タイミーでも取り入れられると嬉しいなと思いました。 Google社員の方や、スピーカーの方に質問してきた 出発前に社内のAndroidメンバーに聞いてきて欲しいことがあるか意見を聞きました。 そこで出てきた意見や個人的に気になっていたことをGoogle社員の方や、登壇者の方に質問してきました。 社内で質問したいことや気になるセッションを聞いた時のmiroのボード Googleの方に、"Ask Android" Office Hours の時間を使って質問をしました。 「Google的に、Adaptive layoutsを推してると思うけど、時間がないデザイナーが対応したいと思える情報ある?」 「Android用のMCPってどんなのがある?」 等の質問をしました。 Googleの方と2対1(Google社員の方2人、私1人)という贅沢な環境でたっぷり時間を使って質問することができました。また、Google I/Oの動画に出ていた方も数人おり、直接お話しできてとてもワクワクしました。Google社員の方がたくさんいるニューヨークだからこんな状況で質問できたと思うので、droidcon NYCに来た甲斐があったと思える瞬間の一つでした。 また、フリーの時間で、キャリアのセッションをしていたStacyさんという女性の方にキャリアと育児についての質問もさせていただきました。 自分にはまだ子供がいませんが、将来的に必要になるかもしれないアドバイスを多くもらえました。特に「子供を産んだり育てることは想像以上に大変だから金銭面でも時間の面でも余裕を持っておくことがオススメだよ。」「子供との時間、仕事両方大切だけど、その時々で優先順位を決めて行動しなさい。同時に両方を全力でするのは厳しいよ。」という言葉がとても心に響きました。 感想 初めての海外カンファレンスですごく緊張していたのですが、とっても楽しかったです! 私はまだ英語に苦手意識があったのですが、各自見たいセッションも異なるし、弊社メンバーで固まらずに別行動をしよう!となり、Day1の最初以外の大半の時間を別行動していました。このチャレンジのおかげで自分の力だけでも海外の方と仲良くなれるという自信をつけることができてとても嬉しかったです。 また、今回のdroidconはAIの話が多く、AIの影響による良い面や悪い面について考える良い機会にもなりました。上記で紹介していないのですが、Stacyさんのセッションで「AIの出現はComposeの出現と似たようなもので、怖がる必要はない。我々は変化に対応できる。」という話を聞き、ポジティブな意味でもっとAIと仲良くなれるように頑張ろうと思えました。 今回のカンファレンスで学んだことをこれからのキャリアや社内での振る舞いに活かしていきたいです。 関連記事 productpr.timee.co.jp tech.timee.co.jp おまけ 行くまでの準備 英語の勉強をしました。Native Campで会話をする練習をしたり、Duolingoで文法や単語を勉強しました。また、英語のドラマを毎日見て、英語に親しみを覚えるようにしました。 今年もGoogle I/Oの動画でモバイルに関連するものはほぼ全部見ました。去年より英語の勉強をした甲斐があり英語での視聴でもほぼ問題がなかったのでスラスラ見ることができました。 droidcon NYC 2025の自分用のアプリも作りました。作成時にまだ公式アプリがなかったためです。後から出てきたので用無しになりましたが、AIがどれくらい使いやすいのか知れる良い機会になりました。細かいエラーなどは手動で修正しつつ、大部分のコードをAIに書かせるというスタイルだと爆速でアプリが作れることがわかりました。この経験のおかげでdroidconの中で行われていたAIの議論にもよりついて行くことができた気がします! I'll be attending droidcon NYC 2025😻 To save sessions I want to attend, I developed an Android application for personal use. While it's not a polished app, I used Cursor so it only took me about four hours to create. AI is very powerful 🙀 pic.twitter.com/K2QbyoAkV7 — 🍥ふなち🍥 (@_hunachi) June 21, 2025 観光 カンファレンス以外では、ニューヨーク市内で観光も楽しみました。 サブウェイなどのローカルな飲食店や、ローカルなスーパーも色々と行きました。 チャンククッキーが好きなので、色々なお店でクッキーを買って食べたりもしました。 どのお店の店員さんもわからないことも教えてくれたりととても優しく過ごしやすかったです。乗る電車がわからなくなった時も、駅員さんと他の乗客の方々がめちゃくちゃ丁寧に道を教えてくれて感動しました😭 また機会があればニューヨークにもdroidconにも行きたいです!
こんにちは!タイミーでAndroidを主軸にしながらプロダクトエンジニアをしている中川です。 6月25, 26日の2日間、ニューヨークのブルックリンで開催された droidcon 2025 NYCに参加してきました。 今回の参加には、個人的に強い動機がありました。 30歳になる節目に、日本だけでなく世界で自分がエンジニアとしてどの位置にいるのかを確かめたかったのです。 今回このような貴重な機会をいただけたのは、日頃から支えてくださっている社内の関係者の皆さまのご理解とご支援、そして不在の間、現場を支えてくれたチームメンバーのおかげです。心より感謝しています。 タイミーには、世界中で開催されているすべての技術カンファレンスに無制限で参加できる「Kaigi Pass」という制度があり、今回はこの制度を利用してカンファレンスに参加しました。詳しくは以下をご覧ください。 productpr.timee.co.jp 私自身も、入社する前にタイミーのエンジニア組織について調べており、2023年にも現在の同僚が droidcon San Francisco に参加した記事を読み、これらのエンジニアの成長を強く後押ししてくれる制度に魅力を感じ、実際に入社を決める一つの大きな要因となりました。 productpr.timee.co.jp 今回のdroidcon 2025 NYCはニューヨークの Brooklyn Storehouse で開催されました。会場はStorehouseという名の通り倉庫の形をしており、およそ10,000㎡の広大なスペースでセッションごとに仕切りを設けずに開催されました。 カンファレンス会場には高さ5メートルほどの巨大なドロイドくんが設置されており、初めての人でも「ここが droidcon だ」と感じさせてくれる象徴的な存在でした。 しかし、それ以上に存在感を放っていた“見えない 象 ”がいました──それは AIとレイオフ です。 You’re Not an Android Developer Anymore (Keynote) Stacy Devino 全米のみならず世界中からAndroidエンジニアが集まるカンファレンスの初っ端から、いきなり核心を突くタイトルが登場しました。"こういうの待ってたぜ…USA…" とタイトルを見た時から感じていました。 今、アメリカには大きなレイオフの波が来ており、実際にレイオフをされて仕事を探している人が周りにいるかという質問に対し約7割の人が挙手しており、アメリカのIT業界の現状を肌で感じる機会になりました。 セッションではStacyが長年にわたり、さまざまな企業で Android エンジニアとして活躍してきた経験をもとに、これからの時代に生き残るための戦略を語りました。 AIの進化によって、プロダクトマネージャーやデザイナーなどのエンジニア以外の職種でもある程度の機能を作れる環境になってきています。 そして今後、モデルが進化したら誰でもソフトウェアを作れる時代が来るかもしれない──その中で、Androidエンジニア、ソフトウェアエンジニアはどうあるべきか?を問いかけるセッションでした。 セッションの中で語られていた 問題解決にフォーカスすること 自分の専門領域にとらわれず越境をすること 小さな職能横断チームでゴールに向かって動くこと これらはまさに、タイミーにおけるSAチームのプロダクトエンジニアのスタイルと強く重なる部分で、聴いていて非常に共感しました。 docs.google.com "Ask Android" Office Hours Google's Android DevRel team さまざまなセッションの裏で自由にGoogleのAndroid DevRel teamのメンバーになんでも質問をすることができる"Ask Android"にも参加をしました。この会は特にファシリテーターやルールなどはなく、その場にいるGoogleのAndroid DevRel teamのメンバーを捕まえていろんな質問をぶつけることができました。 実際にComposeに注力をしているAlexに話を聞く機会があり、Edge to edge対応やLarge Screen Device, Material Designについてさまざまな話(ここには書けない裏話も含めて)を聞くことができ、貴重な時間になりました。 彼らのようなライブラリを提供する側からすると、逆にアプリケーションを開発するエンジニアがどんなことを考えながらアプリを作っているかに興味があり、お互いに情報交換をする機会にもなりました。 AlexはHandling configuration changes in Composeというタイトルで2日目のセッションにも登壇をしており、この"Ask Android" Office Hoursをきっかけに彼のセッションを聴講したのですが、なんとComposeの動作に関する例で実際にUIがスライド内で動作しており、これはもしや…と思いながら最後まで聞いていると、やはりスライド自体もComposeでできており、Composeを提供している側ならではの、圧倒的な熱量に驚かされました。 https://alex.vanyo.dev/talks/configurationchanges/ Career Office Hours with Stacy Devino 先述したStacyと参加者が円になって座り、キャリアの相談をする会でした。このセッションにはスライドやアジェンダもなく録画もされません。純粋にそれぞれのキャリアの相談をStacyと一緒に考える会でした。 相談の内容はレイオフの波もあり、かなり深刻なものが多かったです。個々人の話であるのであまり詳細には触れないのですが 実際にレイオフにあった マネージャーからICに戻ることに対する葛藤 Native/Flutter/React Nativeなどさまざまなモバイル開発手法に手を出したがどれも深掘りできておらず自信を持てずに悩んでいる 大学でCSを学んだが入学時と卒業時でマーケットが激変していて就職に苦しんでいる など聞いていて胸が苦しくなるような話題が多くありました。そのような困難な相談に対してもStacyの持ち前のポジティブさと、これまでの経験に基づく的確なアドバイスによって40分間のセッションでしたが、参加者はセッション後には前よりは明るい顔になっていくのをその場で感じました。 なぜ「現地に行く」ことが大きな意味を持つのか? この記事の執筆時点では公開されていませんが、今回のdroidconの動画は例年通りであればインターネット上に公開されます。しかしながら実際に足を運ばなければ得られない体験をたくさん経験することができました。 カンファレンスはセッションを聞くだけの場所ではなくコミュニティが存在する場所である 動画が後からアップロードされるカンファレンスでも現地でしか得られない体験が多く存在し、例えば以下のようなものが挙げられます。 現地での出会いをきっかけに、実際に仕事が決まることもある セッション外でスピーカーにさまざまな質問をぶつけることができる 朝早く会場に入ってStacyのような有名なエンジニアを見つけて会場で朝食を食べながら話をすることができる 有名な人を捕まえると自然と人が集まってきて、さまざまな議論が始まったりする セッション後にスピーカーにセッションに関連することも、それ以外の気になることも質問することができる Androidという共通の話題をベースにキャリアだけでなくプライベートについても話をすることができる Jake Whartonと話をして記念写真を撮ることができる 世界中のエンジニアが集まる場で感じたこと 世界と比べても、タイミーのエンジニアたちは十分に戦えていると感じました 有名OSSやJetpackライブラリの開発者など、世界的に活躍しているエンジニアたちは、やはり圧倒的でした jakewharton.com すべてのセッションが上記のJakeのセッションのようなAdvancedな内容ではなく、自分がある程度知っている内容のセッションも一定数あり、自分もいつか、この舞台に立てるかもしれないという希望を持てました 雇用について改めて考え直すきっかけに 今回のカンファレンスを通じて、自分自身のキャリアだけでなく、「雇用」そのものについても考え直す機会になりました。 アメリカの大規模なレイオフの波を目の当たりにし、これまで安定だと思っていた“正社員”という立場も、企業の方針や市況の影響を受けて簡単に変わりうる現実を実感しました。一方で、個人として武器を持ち、どこにいても価値を発揮できる状態でいることの重要性も強く感じました。 タイミーという「働き方」に向き合っている会社で働く自分が、 “雇用とは何か” をアメリカの現地で問い直すというのは、とても象徴的な体験だったように思います。 おまけ 時差ボケを考慮してスケジュールを組ませていただき、カンファレンスのない日は、せっかくニューヨークまで行ったので、観光を楽しむこともできました(もちろん仕事もちゃんとしていました)。 ナイトミュージアムの舞台になったアメリカ自然史博物館 ブロードウェイにてマイケルジャクソンの半生をミュージカルにしたMJ the Musical
こんにちは!タイミーでBackend Engineerをしている @akitoshiga です! 7月3日(木)、7月4日(金)に東京の丸の内で開催された「開発生産性Conference2025」に参加してきました!🙌 dev-productivity-con.findy-code.io 自身は7月3日(木)のDay1に現地参加したので、その時の様子を振り返ってみたいと思います! 当日の様子 関西在住の自分は「Kaigi Pass」という社内制度を利用して参加しました。 「Kaigi Pass」とは、世界中で開催されているすべての技術カンファレンスに無制限で参加できる制度です。 productpr.timee.co.jp 会場はJPタワーホール&カンファレンスという東京駅近くにある会場で行われました。 最初のセッションで基調講演を行ったのはケント・ベック氏でした。 彼のファンである自身は今回聴講できて感無量でした。 Day1 Keynote、Kent Beck @KentBeck 氏 11時からはサイン会も実施します!✒️ #開発生産性con_findy #開発生産性con_findy_A pic.twitter.com/s0COYqZCY2 — 開発生産性Conference/Developer Productivity Engineering (@dpe_findy) 2025年7月3日 その後のサイン会でケント・ベック氏にサインをもらいました! サイン会の場で彼に対する想いと感謝を直接伝えることができて嬉しかったです。 サイン会の後、スポンサーブースを回ってみたのですが、非常に盛況でした。 ブースもたくさんありましたが、それ以上に参加者の多さに圧倒されました。 タイミーのブースもこんな感じで出展していました! \ #開発生産性con_findy ブース紹介✨ / 株式会社タイミー様 @TimeeDev pic.twitter.com/lq9LWwyE8y — 開発生産性Conference/Developer Productivity Engineering (@dpe_findy) 2025年7月3日 また、タイミーからはプラットフォームエンジニアリング部部長の恩田が登壇しました。 参加したセッション 自身が参加したセッションについてもいくつか紹介をしたいと思います。 基調講演:開発生産性測定のトレードオフ 「グッドハートの法則」はもっと悲観的に捉えるべきだった ケント・ベック氏 冒頭で「物事をより良くしようとしてかえって結果が悪くなってしまう」という旨のドイツのことわざを紹介しており、要所要所でこちらに言及しているのが印象的でした。 「グッドハートの法則」とは「指標が目的になった途端それは良い指標ではなくなる」ことを言うそうで、これを提唱した英国の経済学者の名前にちなんで名付けられたそうです。 生産性向上のために指標を設け測定したとしても、開発者にプレッシャーをかけるとその指標を達成することが目的になってしまうと主張していました。 タイトルに「もっと悲観的に捉えるべきだった」とありますが、このような指標の目的化現象は我々の想像以上に起こりやすく、またいろいろなところでそのような場面にケント・ベックは直面していたようです。 実際にこのような事態は誰しもが一度は経験があるのではないでしょうか。 このことについて、開発者にはプレッシャーをかけるのではなく目的意識を共有することが重要だと主張されていました。 また、測定すること自体は良いが、決して目標にしてはならず測定のポイントにも注意が必要だと主張していました。 ケント・ベック氏は「Path of Value」として以下の4つのプロセスを紹介しました Effort コードを書くこと Output 具体的な成果物(画面上のボタンなど) Outcome ユーザーの価値変容 Impact ユーザーの行動変容 1から4に行くほど測定はしづらいが、ユーザーの価値につながるため、測定の判断は先送りにしてなるべく後ろのプロセスで測定することを推奨していました。 最後にグッドハートの法則に対応する形で以下を結論づけました。 Observe later(計測はなるべく遅らせ後ろの段階で行う) Encourage awareness(気づきを奨励する) Avoid pressure(プレッシャーをかけること避ける) Instill purpose(目的意識を共有する) 「グッドハートの法則」に基づくケント・ベック氏の主張は、ある種当然と言えば当然のようにも思われるのですが、彼がこの主張をすることにものすごく意味があると感じました。 開発プロセスにおける本質的な部分をテーマにした彼らしい発表だと感じました! NTTデータによる生成AI活用:開発効率化とビジネス変革 株式会社NTTデータグループ 海浦 隆一氏 NTTデータは2025年7月にApps&Data技術部からAI技術部へと組織改編して生成AIの活用を本格的に推進しており、これまでのミッションクリティカルなシステム構築で培った生産性向上ノウハウを基盤に、開発スピード向上と品質維持の両立を目指しているそうです。 取り組みのロードマップとしては自動化の段階的推進: 2023年のタスク自動化から始まり、2025年にはプロセス自動化、2027年にはビジネス全体の自動化を目指しており、既に250以上のプロジェクトでAIを活用しているとのことでした。 主な取り組みと成果として以下について紹介していました(一部) モダナイゼーションとレガシーシステムの解明 FigmaからのReactコード生成(Locofy) ソースコードからの開発ドキュメントのリバースエンジニアリング OSSからのマニュアル生成などにより、システムの理解と保守にかかる工数を削減 属人化防止とドキュメント作成の効率化 有識者の暗黙知を形式知化し、独自様式の設計書を標準形式に変換する「Coding by NTT DATA」の活用 ExcelからMarkdownへの変換など、AIが読み取りやすいフォーマットを採用 開発プロセスの各段階でのAI活用 GitHub CopilotやAzure OpenAIを利用 設計書からの結合テスト項目を作成 さらなる生産性向上への展望として開発工程全体の生産性向上を目指し、要求分析から直接コードを生成し、その後設計書をリバースエンジニアリングする「逆Wモデル」といった新しい開発プロセスの実現を模索していることが非常に印象的でした。 全体的にAIを中心に据えて最大限AIの恩恵を受けられるように開発プロセスを設計しているように見受けられ興味深かったです。 また、多種多様なプロジェクトに携わっている強みを活かしてシステム開発における全域に渡って実践・フィードバック・形式知化・横展開を行えているのが組織として非常に魅力的に感じました! 生成AI時代の品質保証:自動化とAIによるテスト改善 speakerdeck.com mabl株式会社 小田 祥平氏 現状を取り巻くQAの問題点と、そのソリューションとしてAIエージェントによる自律型テストを紹介されていました。 QAに関して課題を抱えているところは多いそうで、独自アンケートによると対象者の6割が手動でのテスト対応を行っているとのことでした。 この背景には以下の問題があるそうです。 保守コスト 基盤の構築と実施コスト ナレッジ不足 特にAIの台頭によりデプロイ頻度の増加と品質維持の要求が高まる中で、テストの自動化とAIの活用が不可欠であるということを強調されていました。 これらの課題のソリューションとしてAIを活用したテストマネージドツールの提案をされており、「mabl」というサービスをベースとして以下のようなテストマネージドツールの機能について紹介されていました。 マネージドツールの活用 生成AIによるテスト自動修復機能でメンテナンスコストを削減 AIによるデータ分析・推論 テストログからの原因分析、flakyテストへの対応 自然言語でのテスト構築 ユーザーストーリーからテストケースを自動生成 CI/CD環境との統合 シームレスなテストプロセスを実現 AIを活用したテストツールはこれまで詳しく追っていなかったので想像以上の多機能・高機能さに驚きました! 開発速度の向上に伴い迅速なQAは今後より求められていくので、こういったツールが不可欠になっていきそうだと感じました。 楽天のAI戦略:70以上のサービス運営と開発生産性向上 楽天グループ株式会社 久田 直次郎氏 楽天グループの展開する70以上サービスの中で、AIを事業成長と開発生産性向上の両輪として活用している現状を紹介されていました。 楽天グループのAI推進戦略として「トリプル20」を打ち出しています。 この戦略はAIを活用してマーケティング・オペレーション・カスタマーサポートの利益をそれぞれ20%向上させることで、年間105億円の利益貢献を目標としています。 社内でのAI活用は非常に効果が出ているそうで、既に16,000個以上のAIツール・テンプレートが作成され、営業資料の作成時間は48%減、ビジネスメール作成時間54%減などの効果が出ているとのことでした。 また、新たな事業として「Rakuten AI for Business」を開始しており一般ユーザー向けに事務・営業・企画/マーケティング・エンジニア向けサービスを提供しているそうです。 それだけでなく、「Rakuten AI LLM」という自社LLMの開発も行っており、用途に合わせた最適化・日本企業に合わせた設計・日本語性能の高さを強みとしているそうです 開発におけるAI活用ではコーディングが最も多く、GitHub Copilotなどの生成AIコーディングツールの導入PoCで一定の効果を確認しているとのこと。 開発サイクルタイムのデータ収集と標準的な可視化を進めており、30%~80%の開発効率削減を目指しているそうです。 楽天グループには約30,000人の従業員の方がいるそうで、AIによる業務効率化のインパクトは非常に大きいと思いました。 また、自社で日本語性能を強みにしたLLMを開発されているのが非常に興味深く、どういったところで活用されていくのかについても興味が湧きました。 まとめ 開発生産性Conferenceには今回初めて参加したのですが、各社の開発生産性に対する様々な取り組みや参加者の熱量を感じました。 今回参加して得た知見を自身や周りの開発にも活かし、より生産的なプロダクト開発を行ってまいります! お知らせ 開発生産性Conference2025でタイミーと同じく登壇されたログラスさん、DELTAさんと合同で「生産性改善しNight」と題したアフターイベントを開催します! 「開発生産性 Conference 2025」に参加された方はもちろん、開発生産性の向上や、社外のエンジニアとの交流に興味がある方も大歓迎ですのでぜひ遊びに来てください! timeedev.connpass.com
こんにちは!タイミーでバックエンドのテックリードをしている新谷( @euglena1215 )です。 最近、私たちのチームでは自律型 AI エージェント Devinの活用が広がっています。特に、GitHub Actionsのスケジュール実行や特定のイベントをトリガーに、定型的なタスクをDevinに任せるといった使い方を試しています。 しかし、Devinを使いこなそうとすると、多くの方がこんな課題に直面するのではないでしょうか。 「最初に作ったプロンプトでは、なかなか期待通りのアウトプットが出てこない…」 結局、何度か追加の指示を繰り返して、ようやく望む結果にたどり着く。これは「AIあるある」とも言える状況ですよね。そして、本当に大変なのはここからです。今回のやり取りで得た知見や改善点を、次回の実行のために元のプロンプトへ手動でフィードバックする作業。これが地味に面倒で、つい後回しにしてしまいがちです。 そこで私たちは、このプロンプトの改善作業自体をDevinに任せるという、面白い試みを始めました。今回はその具体的な手法と、それによって得られるメリットについてご紹介します。 面倒なプロンプト修正は、Devin自身にお任せ Devinとの数回のラリーを経て、タスクが無事に完了したとします。ここで、Devinに次のようなプロンプトを投げかけます。 今回私が行った指摘を、次回以降はしなくて済むように、{ここにGitHub ActionsのYAMLファイルのパス} に記載しているプロンプトに変更を加えてください。 たったこれだけです。これにより、Devinは今までのやり取りをすべて学習し、人間からのフィードバックを反映した新しいプロンプトを自ら生成してくれます。 Pull Requestによる変更提案で、レビューも簡単 さらに、私たちはDevinに次の条件を追加で指示しています。 条件 変更内容は、新しいPull Requestとして作成してください。 今回のやり取りで追加した指示と、既存のプロンプトに意味的に重複する部分があれば、それらを統合してプロンプト全体を最適化してください。 この指示により、Devinはプロンプトの変更内容をまとめたPull Requestを自動で作成してくれます。 Devinが作ってくれたPull Request エンジニアは、そのPull RequestをレビューするだけでOKです。 新しいプロンプトでテスト: 実際に新しいプロンプトを使ってDevinにタスクを依頼し、意図通りのアウトプットが出るかを確認します。 評価とマージ: 改善された場合: Pull Requestをマージし、プロンプトをアップデートします。 変わらない・悪化した場合: マージはせず、なぜ期待通りにならなかったのかをDevinに再度フィードバックします。このサイクルを繰り返すことで、プロンプトは継続的に洗練されていきます。 AIが生成したコードを見なくて良い時代はまだ先か。でも… 「AIエージェントが書いたコードを、人間が一切レビューしなくて良い」という未来は、まだ少し先かもしれません。しかし、AIエージェントに与えるプロンプトを、人間が逐一メンテナンスしなくても良い時代は、もう目の前に来ていると感じています。 Devinにプロンプト自身を改善させるアプローチは、単なる作業効率化に留まりません。これは、AIを単なるツールとして使うのではなく、 対話とフィードバックを通じてAIを育てる という、新しい協業の形と言えるのではないでしょうか。 最後に 今回は、DevinのプロンプトをDevin自身に改善させるという、私たちのチームの取り組みについてご紹介しました。この小さな工夫が、皆さんの開発プロセスをよりスムーズにする一助となれば幸いです。 皆さんなりのDevin活用術や面白いアイデアがあれば、ぜひ教えてもらえると嬉しいです。
はじめに まずPFEや開発者との関わりを整理 背景:DevOpsと認知負荷の増大 そこでPFE 開発者との関わり方 我々PFEチームの現状・課題 PFE1Gの立ち位置と現状 懸念とは? 提供サービスの整理 AWS周りを分解 現状は問題ない? XaaSやEnablingへの移行が鍵ではあるが Embeddedでチームが劣化してしまうかも 今までのお話をまとめると AI Coding Agent x PFEの青写真 AI Coding Agent技術の現状と可能性 理想のかたち:AI Enablingの実現 宣言的なインフラ変更の実現 余談ですが EnablingモードのAI化イメージ 現実的な課題:コードの外側のコンテキスト 事業要件とコードのギャップ 解決アプローチ:コンテキスト注入とドキュメント化 必要なドキュメント化 AIによるEmbeddedモード連発からの脱却 PFEの役割 この話のまとめ 最後に はじめに プラットフォームエンジニアリング1G Managerの橋本です。チームの名前の通り、私達はクラウドインフラ(AWS)やCI/CDパイプライン、Observability、クラウドセキュリティを軸としてタイミーのサービスプラットフォームを開発者へ提供しています。 昨今、AI Coding Agentの発展は目覚ましく、弊社でもCursorやDevinなどを日常的に利用して開発が行われています。そんな中、AIとPlatformEngineering(PFE)の交差によって、よりビジネスに資するPFEの推進ができるのではないかと"妄想"しました。その青写真や取り組む方向性について記事にします。 まずPFEや開発者との関わりを整理 jacopenさんの以下の登壇スライドが分かりやすいため、本記事に関わるポイントを抜粋します。 speakerdeck.com 背景:DevOpsと認知負荷の増大 クラウドの登場とDevOpsにより、開発とデリバリーの継続的な実施を目指すアプローチが広まった。DevOpsのプロセスにセキュリティ対策を組み込むDevSecOpsも登場 扱う技術スタックの激増により 開発者の認知負荷が非常に高くなった(特にこの10年) これをやり切れる人材は少なく「 真の DevOps」(開発者が フルサイクル でデプロイ・実行を行う)の実現は多くの組織で 現実的ではない そこでPFE 開発者体験と生産性を向上させるために、セルフサービスで利用できるツールチェーンとワークフローを設計・構築する分野 本質は、 開発者体験と開発生産性を高める取り組み PFEの始め方は、 開発フローの「ペイン」(辛いところ)を洗い出し言語化し、 必要な対応を行うこと 例えば、セルフサービス化やInternal Developer Portal/Platform(IDP)構築などがある(が、これが必須でもないと資料では言及されています) 開発者との関わり方 Team Topologiesの整理で、ビジネス価値に一気通貫で関わる Stream-aligned team(ストリームアラインド・チーム) と、その道のプロである Platform team などが定義されている チーム間のインタラクションモードとして以下があり関わりの濃淡で捉えている Collaboration (Embedded) ゴールを共有して一緒に動く(ガッツリ関わる) Facilitating (Enabling) 障害を取り除くためにその道のプロとして支援する(中程度の関わり) X-as-a-Service (XaaS) ツールを提供する(関わりが最も薄い) Platform Teamは、まず Collaboration から始めるのが良い。Stream-aligned Teamと1:1で協力し、必要なものを理解して作ることで、誰得なものを作り込むことを防ぐ Collaborationで得た知見をもとに、より多くのチームを助けられる XaaS モード(プラットフォーム提供)を構築していく。ここでIDPの要素が出てくる 我々PFEチームの現状・課題 先の認識をもとに私達の組織の現状認識や課題感について書きます。 PFE1Gの立ち位置と現状 我々が所属するプラットフォームエンジニアリング部では、開発ライフサイクルの各所でドメイン知識を持ったチームやメンバーにより支援を行っています。(以下の図の 開発プラットフォーム Tribe ) 私達1Gはその中でもサービス実行環境であるAWS基盤全般、リリースツール(CI/CD)や運用(observabilityやAWSに関わるOps)の一部に責務を持ち、開発生産性に寄与するための業務を担っています。実態としてインフラチーム + SREチームの混合というイメージです。 なお、PFEの文脈で出てくるセルフサービスやIDPの提供はしていません。これらの仕組みがなくても価値提供の大きなボトルネックやブロッカーになる状況が観測されていなかったためです。 しかし、将来的に我々自身がボトルネックとなりうる懸念がありました。 開発組織イメージ図 懸念とは? 提供サービスの整理 主な領域に切り出した場合、以下のような整理になり、AWSという大きな領域以外はおおよそXaaS的なサービス提供ができており、関わりが薄い状態で開発者体験や生産性に寄与できている状態と考えています。 領域 提供方法 提供詳細 AWS いろいろ(後述) - Observability Datadog 関連記事1 , 関連記事2 ダッシュボード化など XaaS的な提供ができていそう CI/CD GitHub Actions 関連記事3 CI/CDパイプライン XaaS的な提供ができていそう AWS周りを分解 AWS環境はTerraform/IaCによる管理をしています。GitHub上でコード管理されており、おおよそのCODEOWNERは1Gになっています。開発者は必要な変更があればPullRequestを作成し、1Gのエンジニアが問題ないことを確認してmergeができます。これは、XaaS的な提供と言えそうです。 ベースラインの運用は先の通りXaaS化がなされています。しかし、必要となるAWSに関する知識、設計難易度やドメイン知識に応じてTeam Topologiesでいう、FacilitatingやCollaborationが必要となるケースがあります。なお、用語的にイメージしやすいFacilitating → Enabling、Collaboration → Embedded として以降は表記します。 なお、例としてバケット追加にXaaS or Enablingと書いていますが、ほぼ依頼をもらって我々が作業を行うことがほとんどです。頻度があまりなく、対して要件によって必要なパラメータが変わるため、Terraform Module化や詳細な手順書を書いていたとしても、結局聞いて我々が考えて設定した方が提供が早く認知負荷も低かったためです。 要件 難易度・範囲 例 Team Topologiesのモード 実装済へ軽微なもの 簡略的・限定的 既存のバケットpolicy変更 XaaS 明確な要件/定型化可能なもの 繰り返し・限定的 バケット追加 XaaS or Enabling もしくは依頼作業型 新しいAWS機能の利用開始 新規・不確定 AWS 〇〇を新規構築 Enabling or Embedded 新サービス/サブシステム構築 新規・広範囲 - Embedded 現状は問題ない? 先の整理が現状ですが、今時点は大きな問題は起きていません。 しかし、将来への課題感がありました。 Embeddedのチームへの負荷の高さ です。XaaS, Enabling, Embeddedのチーム間の距離感や工数感をイメージにした画像を示します。この絵のようにEmbeddedはほぼ対象チームに人を派遣する形になり、比例して工数的にも他パターンよりも大きくなる傾向があります。Embeddedは、例として新しいサブシステム構築プロジェクトが発生した場合にチームから人を送り込むようなものになります。数ヶ月にわたってヘッドカウントが減ることになり、チームの計画に影響があります。 もちろん、組織全体のビジネス達成観点ではプラスなので間違っていませんが、Embeddedが継続的に発生したり、複数発生した場合はチームが機能不全に陥るリスクがあります。結果、組織全体へ悪影響や我々がボトルネックになるリスクが発生しうると考えました。 XaaS/Enabling/Embeddedの距離感・工数感のイメージ XaaSやEnablingへの移行が鍵ではあるが リスク回避のアプローチはPFEの考えに沿えば、XaaS化やEnablingによって関わり(≒ 工数)を減らし開発者生産性向上を目指すことです。しかし、先に述べた バケット追加が依頼作業型になる ように、現実としては インフラ領域のドメイン知識は多岐にわたるため簡略化・手順化することが困難なケースが多くあります。 仮にenablingパターンで進めたとしても、あれこれお手伝いをしているうちにEmbeddedになってしまうことが想像されました。 Embeddedでチームが劣化してしまうかも Embeddedが多発すると、チームへの負担が増すと述べました。例えば、1人から2人、瞬間的には3人がサブシステム構築プロジェクトに関わることがあります。こうなると、チーム(だいたい1pizza的な人数で構成しています)の半数が出払ってしまうことにもなり、定常的な業務遂行が劣後してしまいます。 サブシステム構築が1つだけであれば「暫く待てば皆戻って来る」という期待が持てますが、2つ以上並走した時点で詰みになります。まだ2以上の並走プロジェクトはありません。しかし、弊社の今後の事業成長・加速に応じて発生する可能性があります。 複数のembeddedパターンが走るケース こうなると、PFEチームがスケールできない = 事業開発への遅延となってしまいます。 このリスクを如何に回避できるか?を考えていた中でAI Coding Agentの急激な成長を見てできることがありそうだと思い至ったこと。これが本ブログの趣旨になります(やっと本題です) 今までのお話をまとめると 以下のようになります 新システム開発のようなEmbeddedでなければならない(XaaSやEnablingでは限界がある)ケースがある 理想はEnablingではあるものの、インフラ領域自体のドメインが巨大であり一朝一夕で開発者が自走できるものではない 結局、巨大なドメイン知識に対応しうる人材が張り付く(Embedded)する必要があり、このスケーラビリティが事業成長のボトルネックになりうる AI Coding Agent x PFEの青写真 AI Coding Agent技術の現状と可能性 我々はIaC/TerraformによりAWS環境を扱うことが多いため、AI Coding Agentのコード生成についてはHCLの記述性に着目することが多いです。 AIのHCL記述力は急速に改善されています。以前はHCLを扱うのが苦手で、古いAWSプロバイダー仕様や新しく出たサービス定義に対応できないケースが多発していました。ウェブなどの情報からでは正しい一次情報をAIがピックアップできないからだと思われます。 しかし、 Terraform MCP Server や AWS MCP Servers によって正しい一次情報へアクセスした上で生成するようになるなど、以前のような課題は解決されつつあります。 これら改善により、CursorやDevinなどのAI Coding Agentを活用して、開発者が直接AWS基盤に変更や追加を加えることが現実的になってきました。とはいえギャップが大きいのも事実です。 理想のかたち:AI Enablingの実現 宣言的なインフラ変更の実現 現状では「terraformのリソース○○に○○なパラメータで追加して」のようなかなり明示的・指示的なプロンプトになりがちです。しかし理想は「○○な要件でバケットがほしい。追加して」といった 宣言的な自然言語での要求を実現 することです。 また、「〇〇な要件では〇〇への考慮が必要なので、以下の質問に答えてくれますか?」といったAIからの打ち返しを通じて、特にセキュリティ的なガードレールが満たされる実装まで開発者とAIの対話によってなされることが理想です。 開発者とAIのインタラクションの図 最終形としてこれが達成されれば、簡単な自然言語によるAWS基盤の変更がXaaS的に提供できそうです。また、変更適用までは難しくてもAWS基盤に関する壁打ち相手としてAIが提案をしてくれ、気にすべき点を開発者が適切に認知できるようになればEnablingとして機能していると言えそうです。 余談ですが 我々のチームではDevinに対してIaCの変更を依頼することが多くあります。一例として以下の画像のような、とても指示的な依頼になってしまいがちであったります。 指示的・明示的なプロンプトになる例 これをできる限り 宣言的に行える ようにすること、 AWSやTerrafromリソースに対して知識がなくても依頼できる ようにすることが目指すかたちだと言えます。 EnablingモードのAI化イメージ 例として、開発者が「○○な用途で○○したいけれどどうしたらいい?」といった質問を、従来PFEエンジニアに問い合わせていた内容をAIに対して行い、適切な回答を得られるようになります。 副次的効果として、PFEチームのエンジニア自身も当然AIに質問できるので、 PFEエンジニア間のドメイン知識のばらつき解消やSPOF防止 (Aの領域はXさんしかしらない。Bの領域はYさんしかしらない)が期待できます。 現実的な課題:コードの外側のコンテキスト 事業要件とコードのギャップ AWS基盤はほぼコード化されていますが、コード化されていること=事業要件ではないケースが存在します。 例えば、S3バケットのセキュリティ要件は、保存するデータが個人情報かどうか、グローバル公開するかどうかなど、事業要件によって変わります。また、IAM Roleなども組織体制や運用要件によって大きく変わります。しかし、コードにはそこまでの要件が細かく記述されていることは少ないのではないでしょうか。IAM Roleであれば、どのRoleが付与されているかと追加・変更理由ぐらいまではコメントにあっても、なぜこのRoleが存在するのか、どのような使われ方をするのかについては別のドキュメント・手順書にコンテキストがあるのではないかと思います。 つまり、 コードの外側に事業や運用に関わるコンテキストが存在することが多いと考えています。 解決アプローチ:コンテキスト注入とドキュメント化 必要なドキュメント化 コードの外側にあるコンテキストをAIに理解してもらうため、例えば以下のようなドキュメント化が必要になりそうです。 サービス仕様のドキュメント化 アプリケーションの仕様 ユビキタス言語などのローカル言語定義 Devinを賢くする秘訣は「ユビキタス言語」にあり? NotionとTerraformで実現する半自動ナレッジ更新術 実行に関わる運用ルール・実装方法・GitHubコメントの書き方などのナレッジ 気づけばDevinのナレッジが山積みに。Terraformで片づけてみた 技術仕様に応じたAWSリソースのドキュメント化 コードの外側にある情報(人間が補足する情報) 例えば、 特定のIAM Roleに付与された権限の文脈や運用ドキュメントとのリンクなど AIによるEmbeddedモード連発からの脱却 上記が達成されれば、現状Embeddedモードで人が大きく関わっている新規サブシステム構築プロジェクトでも、XaaSやEnablingのような薄い関わりで遂行できると期待されます。開発者とPFEの関わり方・分担は以下のようなイメージになれば良いと考えています。 開発者の作業フロー Devin, CursorなどのAI Coding Agentに並走してもらい、作りたいサービスのTerraformコードを生成 インフラ構築を実行 PFEチームの関わり方 コードや変更の正しさ・ガードレールが必要かなどレビューで関わる 誤りや複雑性・危険な操作の予兆を発見した場合は訂正・ガードレールの規し修正事項をドキュメントに反映する 新しい設計などコンテキストに存在しないものがあれば 一時的なEmbedded モードで並走 開発者・PFE・AI・ドキュメントの相関の絵 PFEの役割 先の絵を見るとHCLの記述やIaC・クラウドインフラのメンテナンスはAIによって行われることがより効率的であるという未来が見えます。その時、 我々PFEは何を責務とすべき なのでしょうか。 絵を見ると、 コード外のコンテキスト・ドキュメントを充実させること にあるかもしれません。大まかなイメージではありますが 日々の開発・運用・ビジネス変化を観測・メトリクス/KPIの計測から問題を発見する 問題を解決するための議論・必要に応じてルールメイキングを行う 解決策・ルールをドキュメントに反映してAIが正しい出力をできるようにする 言うなれば、ビジネスを観測し経験などに基づいて課題抽出を正しく行ったり、目まぐるしく変わる優先順位を整理して、 AIに"気持ちよく"仕事をしてもらう ために必要な情報やルールメイキングをドキュメントに反映したり、 "お願い"することが仕事 になるかもしれません。なんだか、エンジニアリングマネージャーっぽいですね。 この話のまとめ 新システム開発のようなEmbeddedモードでなければならないケースが連発するとPFEのスケーリングが事業ボトルネックになるリスクがある リソースが限られるのでEmbeddedの連発は不可能。しかしながら、AIによってEnabling + 最小限のEmbeddedで事業のスケーリングに対応できるプラットフォームエンジニアリングができるのではないか、と、現在は"妄想"段階 コードに表現されていない様々な要件をAIに与える必要があり、ドキュメント化や入力方法を工夫してAI Coding Agentに正しい出力をしてもらうことが鍵になりそう。AIに気持ちよく仕事をしてもらう工夫をすることに労力を費やすことになるかもしれない。 最後に 既に弊社の他の方々がブログに取り組みを書いているように、先の取り組みが始まりつつある状態です。また、AI Coding Agent界隈の変化が激しく1〜2週間でも目まぐるしく注目の話題が生まれてくる状況にあります。(2025年6月現在) 変化によってやり方が全く変わる可能性がありますが、2〜3ヶ月後にはある程度の目処が見えてくるのではないかと思います。過去半年のAI Coding Agentの発達を思えば、今年中にはさらに大きな発展をしている期待感もあります。 不確実なことが多い取り組みではありますが、もし達成できればPFEがビジネス上のボトルネックになるリスクを回避できる、少ない人数で最大のアウトカムを得るチャンスだと思うので、力を入れて取り組んでいきたいと思います。 長い文章になりましたが、最後まで読んでいただいてありがとうございました。
読んで欲しいと思っている人 スクラムイベントがうまくいかない感じがして困っている方 スクラムイベントをもっと良くしたいと思っている方 読むとわかること スクラムイベントを改善するための1つのアイデア スクラムイベントは互いにインプットとアウトプットとなりながら循環していること スクラムを改善したい時はシステム思考を勉強するとちょっと助けになること はじめに バックエンドエンジニアを務めている @Juju_62q です。スクラムでのロールとしては「開発者」を務めています。突然ですが質問です。 スクラムイベントがうまく改善できないという経験はありませんか? 例えば「スプリントプランニングが時間内に終わらない」という問題があるとします。この時にスプリントプランニングで効率的に意思決定を行うための実験を開始してもどうにもうまく問題が解決していかないことがあります。時間内に収めるために強引な意思決定手法を導入することもできますが、それだと開発者のコミットメントをうまく引き出せないこともしばしばあります。 こういった時に自分が気をつけていることの1つを紹介させていただければと思います。 スクラムイベントが何かうまくいかないと感じている方はスクラムをやめる前にぜひ考えてみて欲しいです。 結論 まず結論から紹介させてください。 スクラムイベントがうまくいっていない時は、大抵の場合別のイベント等に原因があります。要は準備やインプットが足りていません。事前条件が整っていないがゆえにチームメンバーがそれぞれ別のことを志向して意思決定がしにくかったり、不確定要素が多くてコミットメントがしにくいという現象が発生します。 それぞれのイベントがうまくいかない場合に対応して改善を試みるイベントとして自分は下記を意識しています。 うまくいかないイベント 改善を試みるイベント スプリントプランニング リファインメント、スプリントレビュー スプリントレビュー スプリントプランニング、リファインメント スプリントレトロスペクティブ スプリントプランニング、スプリント(スプリント中の活動全般) デイリースクラム スプリントプランニング スクラムイベントではありませんが、リファインメントがうまくいかない場合は大抵プロダクトゴール周辺に問題があります。 スクラムイベントは相互に関連している スクラムガイドではスクラムイベント一つひとつの解説が載っています。しかし、それぞれのイベントは独立して存在しているわけではありません。それらはスクラムイベントのインプットとアウトプットを通じて、互いに深く関連し、循環的なフィードバックループを形成しています。 スクラムイベントを個別の事柄として捉えるのではなく、相互にインプットとアウトプットを持つシステムとして理解することが、スクラムイベントを効果的に改善する鍵となります。この循環がうまく機能しない時にスクラムイベントは機能不全に陥ります。したがって、スクラムイベントの改善を試みる際にはそのイベントが何に依存しているのかを考えることが重要です。 具体的に考えてみましょう。 スプリントプランニングがうまくいかない時 例として「スプリントプランニングが時間内に終わらない」という問題を考えてみます。時間内に終わらない原因のほとんどはチームでの意思決定がうまくできないからでしょう。 ここで、過去の自分のチームでは「どうしたらいろんな意見がある中で1つの意見にまとめられるか」という観点で実験を実施していました。例えば「スプリントプランニングで意見が割れたら最終的にはプロダクトオーナーが決める」というアイデアを採用した場合「スプリントプランニングが時間内に終わらない」という課題は解決できそうです。 しかしながらこのアイデア、実はあまり賢明ではありません。なぜかというとうまくいかなかった場合に、チームで原因を究明し改善するのが困難であるためです。この意思決定方法でスプリントに問題があった場合、レトロスペクティブでは何を振り返るのかを考えるとわかりやすいです。プロダクトオーナーの意思決定が原因だとすれば、責任を特定するのは容易ですが、チームとしての学びにはつながりにくいです。チーム全体で問題に向き合う機会が失われ、根本的な改善が見送られてしまうことになります。 一方で「なぜ意思決定ができないのか」という問いを立てると別の解決策が見えてきます。スプリントプランニングでの意思決定が滞る主な原因として、プロダクトバックログアイテム(PBI)が「生煮え」の状態であることや、チームメンバー間でプロダクトや開発の方向性に対する「目線が揃っていない」という状況が挙げられます。例えば、PBIの目的や詳細が曖昧であれば、開発者は具体的な計画を立てにくく、コミットメントも困難になります。また、チームが共通のゴールを明確に認識していなければ、どのPBIから着手するのが良いのか、プロダクトゴール達成のためのアプローチについて意見が分かれやすくなります。 これらの課題は、スプリントプランニングよりも前の段階、すなわちリファインメントが適切に行われていない、あるいはスプリントレビューで顧客から良いフィードバックが得られていないことに起因している可能性が高いです。スプリントプランニングに必要なインプットが不足しているために、その場で多くの議論が必要となり、結果として時間超過につながっています。自分のチームではそれまで任意参加だったリファインメントを必須参加とすることでプランニング時点での疑問を抑制し、スムーズに進めることができました。最適な対応かはわからないですが、スプリントプランニングの問題を解決するためにはリファインメントを改善する必要があるという一例だと考えています。 このブログを書いたきっかけ これまでスクラムチームで開発者として活動する中で、上記のような「スクラムイベントがうまくいかない」という課題にしばしば直面してきました。当時の自分は考え方として「とにかく問題を小さくして対策を試みる」というのが癖になっていました。これを続けてもどうもうまく問題が解決していきませんでした。今思えば、この考え方はスクラムイベントが相互に関連していて互いが互いのインプットであり、アウトプットになっていることを無視していたのだろうと思います。ある時チームのスクラムマスターからひとつ前の段階の改善を提案されて実施したところ驚くほど上手に問題が解決したことをよく覚えています。 この経験を通じて、スクラムイベントは単独で存在するのではなく、インプットとアウトプットで繋がれた一つのシステムとして捉えることの重要性を強く感じました。この視点を持つことで、問題の原因を見つけやすくなり対症療法でない対策を講じることができるようになりました。 この考え方は、システム思考と呼ばれています。もしスクラムをやっていて何か改善が行き詰まっている方がいればぜひ一冊で良いので本を読んでみてください。自分が読んだ書籍を一冊紹介しておきます。 https://www.amazon.co.jp/dp/B00SUT1ODK 終わりに もし今、あなたのチームのスクラムイベントが何らかの課題を抱えているのであれば、ぜひ一度、そのイベント単体を見るのではなく、「そのイベントへのインプットは何だったか?」「そのインプットは適切だったか?」 というシステム的な視点で振り返ってみてください。 もしかしたら問題の根本は、あなたのチームが普段意識していないような少し前のフェーズに潜んでいるかもしれません。「相互依存関係」という視点を取り入れて、改めてスクラムの改善に取り組んでみるのもおすすめです。
タイミーでバックエンドのテックリードをしている新谷( @euglena1215 )です。 タイミーでは自律型 AI エージェント Devin を活用した開発を行っています。 Devin を効果的に活用する上で鍵となるのが、どのような「knowledge(知識)」を与えるかです。Devin を活用している各社で、試行錯誤が進められているのではないでしょうか。 もし Devin に一つだけ知識を与えて賢くするとしたら、何が最適でしょうか? 私は「会社固有の知識であり、かつ社員にとっては当たり前すぎて、AIに教えるという発想に至らない情報」が、AIの精度を向上させる鍵になるのではないかと考えています。 社員は知っているが Devin は知らない、そんな情報の代表格として思いついたのが「ユビキタス言語」です。実際に Devin にユビキタス言語を knowledge として教えてみたところ、抽象的な概念に対する理解度が向上する手応えがあったため、その TIPS を共有します。 また、Devin に教えるユビキタス言語が古くなっては逆効果です。そこで、ユビキタス言語の knowledge を半自動で更新する仕組みも作ってみたので、合わせて紹介したいと思います。 前提 私たちタイミーの環境における、2つの重要な前提について説明します。 1. Notion DBによるユビキタス言語の管理 タイミーでは、ユビキタス言語を Notion のデータベースで一元管理し、常に最新の状態に保つワークフローが確立されています。このデータベースには、以下の情報が含まれています。 表現(事業者向け): 企業向けの表現。企業向けとワーカー向けで指すものが同じでも表現が異なることがあるため分けています。 (例:求人を公開) 表現(ワーカー向け): ワーカー向けの表現。(例:募集を公開) 意味: 用語の意味 NG表現: 誤って使われやすい用語例 実装の英語表記: 用語に対応する実装上のキーワード 備考: 用語を使用する際の注意事項 こちらに関して詳しく知りたい方は以下の記事をご覧ください。 note.com 2. TerraformによるDevin knowledgeの管理 次に、タイミーでは Devin の knowledge を Terraform で管理しています。 以下のような Terraform ファイルを記述することで、knowledge を登録できます。 resource " devin_knowledge " " this_is_knowledge_1 " { body = << EOT Pull Requestの説明には、.github /PULL_REQUEST_TEMPLATE .md のテンプレートをベースとして使用してください。 このテンプレートは、このリポジトリのすべてのPull Requestで使用する必要があります。 EOT name = " PR作成時のテンプレート利用 " parent_folder_id = data.devin_folder.this_is_folder_name.id trigger_description = " foo リポジトリで Pull Request を作成する場合 " } こちらに関して詳しく知りたい方は、以下の記事をご覧ください。 tech.timee.co.jp 実装 運用されているユビキタス言語の Notion DB と Devin の knowledge を Terraform で管理する仕組みが整備されているので、あとはそれらをつなぎこむだけです。 今回 Notion DB を CSV Export し、Terraform ファイルとして出力する Shell スクリプトを用意しました。 Shell スクリプトを生成するプロンプトは以下です。参考にしてみてください。 ユビキタス言語CSVからDevin KnowledgeのTerraformファイルを生成するスクリプト === 生成プロンプト === 以下の要件でユビキタス言語データベース(CSV)からDevin knowledgeのTerraformファイルを 自動生成するBashスクリプトを作成してください: 【目的】 - CSVに定義されたユビキタス言語をDevin Knowledgeに変換 - Devinが「お仕事リクエスト」→「offeringRequest」のような用語対応を理解できるようにする - 用語について質問された際に適切な検索指示を提供するナレッジベースを構築 【CSVファイル構造】 - ファイルパス: source/ubiquitous.csv - 列構成: 事業者向け表現, ワーカー向け表現, 意味・定義, 避けるべき表現, 実装上の英語表記, 備考 - 文字エンコーディング: UTF-8 - 引用符内の改行やカンマを含むデータあり(CSVパーサーで適切に処理が必要) 【処理要件】 1. CSVパーサー: Rubyの標準CSVライブラリを使用(引用符内改行問題を解決済み) 2. フィルタリング: 意味・定義がある全エントリを処理対象(実装向け表記の有無は問わない) 3. primary_expr決定: 事業者向け表現 → ワーカー向け表現 → "用語N" の優先順位 4. カウンター管理: 正しいインクリメントでリソース名重複を防止 5. 動的トリガー生成: 実装向け表記の有無でトリガー記述を分岐 【ナレッジ内容構造】 - タイトル: 「ユビキタス言語「XX」の用語対応ガイド:」(検索指示中心) - 【用語の定義】: 意味・定義の内容 - 【実装・開発時の検索キーワード】: * 実装向け表記がある場合: 「コードや実装: 「XX」」 * 事業者向け・ワーカー向け表現も追加 * 実装向け表記がない場合: 「概念・ドキュメント用語として使用」を追加 - 【避けるべき表現】: 避けるべき表現がある場合のみ - 【使用ガイダンス】: 実用的な使用方法の3項目リスト - 【補足情報】: 備考がある場合のみ 【トリガー記述】 - 実装向け表記あり: 「「XX」やその関連用語(YY等)に関する質問、実装、ドキュメント作成を行う場合」 - 実装向け表記なし: 「「XX」に関する質問やドキュメント作成を行う場合」 【出力ファイル】 - パス: envs/knowledge/ubiquitous_language.tf - 自動生成ヘッダー付き - terraform fmt で自動フォーマット - data.devin_folder.ubiquitous_language.id 参照(data.tfで定義済み) 【エラーハンドリング】 - CSVファイル存在チェック - 一時ファイル管理(trap使用) - 処理結果の統計表示 === 生成プロンプト終了 === 上記によって生成した Shell スクリプトを実行すると、以下のような Terraform リソースが作成されます。 resource " devin_knowledge " " ubiquitous_language_53 " { body = << EOT ユビキタス言語「グループ限定公開」の用語対応ガイド : 【用語の定義】 グループ機能で作成したグループに所属する、特定のワーカーのみに求人を公開する機能 【実装・開発時の検索キーワード】 - コードや実装 : 「limited」 - 事業者向け文書 : 「グループ限定公開」 【使用ガイダンス】 この用語やその関連概念について質問・実装・ドキュメント作成を行う際は: 1 . 上記の適切なキーワードで検索してください 2 . 文脈に応じて事業者向け・ワーカー向け・実装用の表現を使い分けてください 3 . 避けるべき表現は使用しないでください EOT name = " ユビキタス言語: グループ限定公開 " parent_folder_id = data.devin_folder.ubiquitous_language.id trigger_description = " 「グループ限定公開」やその関連用語(limited等)に関する質問、実装、ドキュメント作成を行う場合 " } 更新手順 更新ステップは以下の通りです。 Notion DB を CSV としてエクスポートし、Terraform を管理しているリポジトリに配置 CSV から tf ファイルを生成する Shell スクリプトを実行し、Pull Request を作成 terraform plan & apply を実行 現状は手動での CSV エクスポートが必要ですが、 Notion API・MCP などを活用すれば、この更新フローの完全自動化も可能だと考えています。 Devin がどのように賢くなったか このナレッジを与えたことで、Devin の振る舞いにどのような変化があったかを見ていきましょう。 まず、Devin が knowledge を適切に参照できているかを確認します。 Devin スクリーンショット 確認した結果、数あるユビキタス言語の中から、本当に関連するユビキタス言語のみを参照することに成功していました 🎉 次に、質問に対する回答の精度を比較します。上記のスクリーンショットにあるように、「“limited”という単語は何を意味しますか?」と質問してみました。 【ユビキタス言語 knowledge なしの場合】 「limited」は 求人の公開範囲を制限する包括的な機能 を表します。 【ユビキタス言語 knowledge ありの場合】 「limited」は求人の 限定公開機能 を指し、特定の条件を満たしたワーカーのみに求人を表示する仕組みです。 どちらも内容は似ていますが、 よりタイミーの社員らしい、解像度の高い回答になったのは「ユビキタス言語あり」のパターンだと感じました。 ナレッジがない場合、Devin はコードベースを広範囲に検索・抽象化して回答を生成するためか、少し曖昧な表現に留まっています。一方、ナレッジを与えた後は、 私たちが定義した「意味」に沿って、より的確な言葉で回答できるようになりました。 最後に 生成 AI ツールの進化によって、これまでチームの暗黙知とされてきたものを、いかに形式知として AI に与えていくかが、これまで以上に重要になってきています。 タイミーのエンジニアリング組織はフルリモートという特性もあり、以前からドキュメント化の文化が根付いています。今回の取り組みは、その文化をさらに一歩進めるものになりました。 これからも、AI との協業を前提とした開発体制の構築を進めていきたいと思います。
はじめに タイミーでPlatform Engineerをしている 徳富(@ yannKazu1 )です。 2025年2月、私たちの開発組織にAIエージェント「Devin」が導入されました。 Devinは、機能開発のサポートやテストケースの提案など、日々の開発に自然と溶け込む形で活躍してくれていて、今では月に数十〜数百件のマージに関わる頼もしい存在になっています(2025年4月17日時点で489件マージ!)。 そんなDevinと一緒に開発を進めるなかで、ある悩みが浮かび上がってきました。それが「ナレッジの管理が難しくなってきた」ということです。 ナレッジが増えてうれしい、でも…… Devinには「ナレッジ」と呼ばれる、ルールや指針のような情報を登録する機能があります。 「こういうときはこう書く」「こう判断する」など、チームの経験や判断基準をDevinに覚えてもらうことで、より実用的な回答を得ることができます。 ですが、チーム内のいろんなメンバーがナレッジを追加するようになると、次第にこんな状況が生まれてきました: どのナレッジが誰の意図で変更されたのかわからない 重複したり矛盾した内容が出てきてしまう Devinの提案にブレが出るようになった このままだと、Devinの力を活かしきれない。そう感じた私たちは「ナレッジにもレビューと履歴の管理が必要だ」と考えるようになりました。 Terraformで「Knowledge as Code」を実現してみる インフラをコードで管理する「Infrastructure as Code(IaC)」のように、ナレッジもコードで管理できたらどうだろう? そうしてたどり着いたのが、 「Knowledge as Code」 というアプローチでした。 Terraformを使えば、ナレッジの追加・変更・削除をコードとして記述でき、次のような良いことがあります: Gitで履歴が追える :誰がどんな意図で変更したかを残せる Pull Requestでレビューできる :ナレッジにブレが出るのを防げる terraform plan で差分が見える :意図しない変更に気づける 他のAIエージェントに移行しても再利用しやすい 「これならナレッジの質も保てるし、チーム全体での共有もしやすくなるはず」——そんな期待を込めて、Terraformによる管理に挑戦することにしました。 でも、Terraform Providerがない……! とはいえ、Terraformで管理するには専用のProviderが必要です。 調べてみたところ、Devin用のTerraform Providerは世の中に存在していませんでした。 そこで、私は思いました。「それなら、作ってみよう」 Devin Terraform Provider を作ってみた 自作したTerraform Providerでは、以下のような操作が可能です: 👉 Devin Terraform Provider — Terraform Registry Devinへのナレッジの作成・更新・削除 ( devin_knowledge リソース) フォルダー一覧の取得 ( data "devin_folders" ) 既存ナレッジの参照 ( data "devin_knowledge" ) ナレッジの作成 resource "devin_knowledge" "example" { name = "Example Knowledge" body = "This is an example knowledge resource." trigger_description = "Use this knowledge when talking about examples." parent_folder_id = "optional-folder-id" } フォルダー一覧の取得 data "devin_folders" "example" { name = "example" } ナレッジの参照 data "devin_knowledge" "existing" { name = "Example Knowledge" } これにより、ナレッジの変更内容をコードで管理しつつ、レビューを通して安心して運用できるようになりました。 これからのこと Terraformでのナレッジ管理は、私たちにとってとても大きな一歩でした。 でも、それは「Devinの管理がしやすくなった」だけの話ではありません。 私たちは今、AIエージェントが自然とチームにいる時代に生きています。 そのなかで、単なる効率化ではなく「人とAIが一緒に考え、一緒に働く」開発のあり方をどう作っていくかが重要だと感じています。 タイミーでは日頃から、Notion上にユビキタス言語やチームごとのナレッジが丁寧にまとめられており、ドキュメンテーションの文化が根付いています。 こうした文化があるからこそ、今回のような取り組みも自然な流れとして始められましたし、ナレッジを「コードとして残す」ことにもチーム全体で前向きに取り組むことができました。 これからの開発の現場では、Devinだけでなく、Jules、Cursor、Copilotといった様々なツールが活躍するようになるかもしれません。 そうした多様なAIと気持ちよく協力していくために、私たちは次のような基盤づくりを進めていきたいと思っています: Devin以外のAIでも参照できる、再利用しやすいドキュメントとその自動更新の仕組みを整える ナレッジを「読み物」ではなく「役立つデータ」として整理し、どのエージェントでも活用できるようにする 「Knowledge as Code」から「Project as Code」へと視野を広げる スプリントの運用方法、CI/CDの流れ、ドキュメントの構成や技術方針までをコードで一元管理し AIがそれらを理解した上で、プロジェクトの流れに沿った提案をしてくれるような世界へ 全社的にナレッジを育てていける運用の仕組みを整える 各チームがそれぞれルールを持つのではなく、共通のガイドラインと形式で蓄積・再利用できるようにし 自動化と人のレビューをうまく組み合わせて、 スピード感と品質の両立 を目指す こうした取り組みを通じて、ただAIを活用するだけでなく、 チームの一員としてAIと一緒に働ける環境 を整えていきたいと考えています。
2025年4月16日から18日の3日間 、 愛媛県松山市 にて、RubyKaigi 2025 が開催されました。 https://rubykaigi.org/2025/ タイミーでは、昨年に続き、世界中で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を活用し、 新卒内定者やインターン生を含む総勢16名 が現地でカンファレンスに参加しました。 この記事では、現地参加した各エンジニアの印象に残ったセッションとその感想をまとめてお届けします。 今回はその第4回で、Day3の内容をまとめています。 Day1, Day2のセッションに関する内容についてもぜひ合わせてお読みください! tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp 各セッションごとに内容を整理し、参加者自身の視点から学びや気づきをまとめています。読者の皆様にとって、今後の学びの参考になれば幸いです。 On-the-fly Suggestions of Rewriting Method Deprecations 発表 rubykaigi.org speakerdeck.com 概要 deprecated への対応は開発者にとって時間と手間がかかる作業であり、本来の開発から注意を逸らします。ドキュメントの作成や警告表示、静的解析ツールなどを用いた既存の対応策には限界があり、特に Ruby のような動的型付け言語では、静的解析による検知や修正には過不足が生じてしまいます。そこでコードの実行時に自動書き換えまで行うアプローチを提唱し、それを実現するため deprewriter-ruby Gem を開発したという発表でした。これは deprecated なメソッド呼び出しを検知して、規定したルールに則って上書きをするというもので、ライブラリ開発者が非推奨化するメソッドに「どのように書き換えるべきか」という変換ルールを定義することで、利用者がテストなどでそのメソッドを呼び出すと、Gemが変換ルールに則り自動で書き換えてくれるようになります。 gem の説明の中ではメソッド呼び出しのインターセプト、呼び出し元情報の取得(caller_locations)、ソースコード解析(Prism/SyntaxTree)、AST変換(Synvertベース)、ファイル書き換え/差分出力といった技術要素を解説してくださいました。また、ファイルを直接上書きするだけではなく、ログ出力モード、差分(パッチ)出力モード、直接書き換えモード(主にテスト環境向け)を提供しているそうです。 この gem は各言語の deprecation の対応状況を調べていく中で、Pharo言語の自動リファクタリング機能に影響を受けて開発されました。 Pharo での deprecated なメソッドの置き換え等は Deprewriter と呼ばれていますが、それを Ruby でも実装してみて、実際にどのように利用できるか、動くのかを紹介してくださいました。 将来的には、 Ruby エコシステム全体で非推奨対応の負担を軽減し、開発者がより本質的な作業に集中できる環境を目指したいというビジョンを示してくださいました。 感想 メソッドの Deprecation(非推奨化)に関して、ドキュメントを参照しながら開発の過程で修正していくというプロセスは、自分にとってあまりに当たり前なものでした。本番環境で実際に適用するかどうかはさておき、実行中にそれらが自動で修正されるという体験は、自分にとって非常に斬新かつ素晴らしい開発者体験だと感じ、プログラミング言語にはまだまだ進化の余地があるのだと改めて実感できました。何らかのアップデートに伴いCIが実行され、差分があった場合に別途PR(Pull Request)が作成されるという状況は、開発者体験を大きく向上させそうです。また、言語やライブラリの開発者にとっても、互換性の問題を発生させにくい優れた仕組みだと感じています。最近論文を読んでいないことも思い出したので、自分も改めて論文を読み直してみたいと思います。 ( @Juju_62q ) Rails などの著名なライブラリに対して RuboCop がいわば「肩代わりして」行っているようなことを、ライブラリ自身の責任で行えるようになるというのは、ライブラリ開発者としても理想的な機能ではないでしょうか。とはいえ、実際のコードでよく起こりうる「同じメソッド名で挙動が異なる」という場合(例えば引数のキー名が変わったなど)は、「現在どのような状態なのか」の判定が難しいため、うまく実現するのは大変そうだという予感がします。今後の発展に期待しています。 ( @masarakki ) 非推奨メソッドへの対応は、特に Rails のバージョンアップの際に度々発生します。その度にリリースノートを読み込み、ソースコードの差分を確認して対応しますが、コストのかかる作業だと常々感じており、そのような状況下でこの発表を聞き、自動で修正されるというアプローチに感銘を受けました。 この Gem は、ライブラリの利用者にとっては夢のような機能を提供する一方で、利用者が便利になるためのコストをライブラリ作成者に強いる設計だと思います。これは RBS にも言えることですが、こういった設計の機能が広く浸透するには時間がかかるでしょう。浸透させるためには、この Gem を利用するユーザーが増え、よりスタンダードな機能にしていくことが重要ですが、そう簡単ではないだろうとも感じました。 個人的には是非とも普及してほしい Gem だと思うので、自分でライブラリを作成する際や、deprecation の自動修正に共感してくれるライブラリを見つけた際には、積極的に活用していきたいと思いました。 (@rhiroe) Matz Keynote - Programming Language for AI age(Day3) 発表 rubykaigi.org 概要 毎年恒例の Matz による Closing Keynote です。今年は「AIとプログラミング言語」をテーマに、言語デザイナーの視点からプログラミング言語について論じられました。 犬における「アルファシンドローム」(ペットが自分がリーダーだと勘違いする現象)を紹介し、それを AI に当てはめ、「逆アルファシンドローム」という概念を提唱しました。これは、人間が AI のできない「面倒な」あるいは「望ましくない」タスクのみを担当し、AI ができる(そして人間にとって楽しいかもしれない創造的な)部分を AI に任せてしまうことで、人間が AI に従属してしまう危険性を指摘するものです。全体を通して、人間が主人であり続け、AI は奉仕者であるべきとし、プログラミングの楽しさや主導権を失わないために、どのタスクを AI に委任するかを意識的に選択する必要があると主張していました。 AI 時代に望ましい言語の特性として「簡潔さ(Conciseness)」「表現力(Expressiveness)」「拡張性(Extensibility)」の3点を挙げ、Ruby が全てを満たしている素晴らしい言語だとしました。AI 時代にはプログラミング言語ではなく、人間の話す自然言語が最適なのではないか、という可能性については、数式を例に挙げ、自然言語は形式言語に比べて正確性に限界があることにも触れました。 近年話題の静的型付けについて、不可欠かどうかについては疑問を呈し、役立つ場面もあるが、第一に必要なものではないかもしれず、過度に複雑なシステムは簡潔さや楽しさを損なう可能性があると指摘しました。 またセッションの最後に、今年は Ruby 4.0 がリリースされる(かもしれない)というサプライズもありました。 感想 今回の RubyKaigi では AI の話題がほとんどなかったなと思っていたところ、最後に Matz が話してくださいました。タイトルは「Programming Language for AI age( AI 時代のプログラミング言語)」(「Programming Language for AI( AI のためのプログラミング言語)」ではない点がポイント)。これは Matz にしか語れない内容だ!と、わくわくしながら聞いていました。途中、いつもの「静的型付き言語 vs 動的型付き言語」の話になっていったのも、風物詩の趣があり良かったです。 さて、Matz によれば AI 時代に求められるプログラミング言語とは「Concise, Expressive and Extendible」、つまり簡潔で表現力が高く、拡張しやすい言語であるべきだと。それは、つまり Ruby のことだ、というオチでした。 また、本題の前に語られていた「人間(プログラマ)と AI の関係」の話も非常に印象的でした。主従関係としては人間が主人であり、人間が AI に従うべきではないという考えです。この考え方は過去にも語られており、当時は「コンピュータ」だったものが、今回は「AI」に置き換わっている形です。何にせよ、主役は人間であるということを改めて再確認しました。AI を使えば色々便利になり、あれもこれも置き換えられると考えていた自分としては、ハッとする内容でした。 ( @sugaishun ) 途中、「AI 支援を使っている人は挙手してください」という質問があり、半数くらいが手を上げていました。これは個人的には想像以上に多いという印象です。 Ruby は「たのしい」を重視している言語なので、我々ユーザーも「たのしい」から Ruby を選んでいて、それほど AI 支援に興味を持っていないのではないかと思っていたからです。(AI に仕事を奪われるのはもう仕方ないとしても、AI に「たのしい」ことを奪われるのは我慢ならないですよね。) 「人間が主人、AI が従者」という主張も、それが成り立つのは「Ruby がたのしい」という前提があってのことだと思います。AI の利用が拡大することで「たのしい」の価値や意味が無くなってしまうのではないかと危惧しています。 ( @masarakki ) AI のサポートはこれまでそれなりに試しましたが、「よくある機能の作成」や「簡単な雑務」、「実装からテストの作成」くらいしかまともに使えていません。個人的には「要求から要件と仕様を作る」、「仕様からテストを作る」部分を AI でできるようになれば嬉しいなぁと思いつつ、普段の業務では自分がテストを書くしかない状況で、世の中の「AI すごい!!」みたいな空気に若干違和感がありました。 今回の話の中で、AI は奉仕者に過ぎず人間がプログラミングの楽しい部分を担うべきだという話には、共感しかありませんでした。自分にとって楽しい部分は「設計」と「実装」なので、その部分は自分でやりつつ、その他を AI がやってくれる未来がやってくると嬉しいなぁと思いながら聞いていました。 一方で、AI を駆使した方が工数やコストを削減できるという話もちらほら聞くことがあり、その影響で AI にできる部分を AI にやらせ、AI ができないことを人間がする、まさにこの話の中での逆アルファシンドロームが実現された未来がやってくる可能性もないとは言えません。そうならないためにも全てのプログラマには、人間が主導権を持つための AI に委任する作業の選択を意識的に行うようにしてほしいなと切に願います。 (@rhiroe) The Ruby One-Binary Tool, Enhanced with Kompo 発表 rubykaigi.org speakerdeck.com 概要 Kompo というツールを開発されている @ahogappa さんによる発表です。 Ruby のプログラムをワンバイナリにまとめるためのツール「Kompo」の開発とその進捗についての発表でした。 以前の発表(RubyKaigi 2024)時点では、 require をオーバーライドして必要な Ruby スクリプトやライブラリを実行ファイルに埋め込む方式でしたが、Sinatra と SQLite 程度の規模のアプリケーションでしか動作しないという課題がありました。 今回の発表では、仮想ファイルシステムを構築することで以前の課題を解決し、Rails アプリケーションのワンバイナリ化に成功したことが報告されました。 感想 Ruby で実装したゲームをクロスプラットフォームで配布したいという背景から Kompo の実装を始めたとのことで、2日目に発表された「How to make the Groovebox」と同様に自身の趣味と結びついたセッションでした。 Kompo に関しては今回の発表で初めて知りましたが、Rails で作られたアプリケーションをワンバイナリにできるという発想がなく、単純に驚きました。 この技術が発展することで、Ruby のアプリケーションがより手軽に、より多くの環境で利用できるようになり、Ruby の発展に繋がりそうだと思いました。 クロスプラットフォーム化の部分に関してはまだ達成されていないとのことでしたので、今後の進展に期待しています。 (@Keisuke Kuwahara) Analyzing Ruby Code in IRB 発表 rubykaigi.org drive.google.com 概要 2024年から Ruby Committer となった @tompng さんによる、IRB における「解析」に関する発表でした。IRB の内部動作において、特にシンタックスハイライト、オートインデント、コード補完、コードの終了判定といった機能は、これまで主に Ripper というツールを使用して実装されてきました。それを、Ruby のパーサーである Prism への移行を進めることで、これらの機能の精度と堅牢性向上を図っているという内容でした。また、IRB でエッジケース的な “weird-code”(奇妙なコード)を受け取った際の挙動が、具体的な事例を交えて紹介されていました。 感想 普段何気なく自分が使用している IRB の奥深さ、シンプルなインターフェースの奥底にある課題に触れることができました。本セッションに限らず RubyKaigi ではパーサーにフォーカスした内容が多く、個人的に好きなテーマです。 def を入力するとハイライトされる、 end を入力するとオートインデントされるといった基本的な動作すら誰かがメンテナンスしてくれているんだな…と改めて感慨深い気持ちになったと共に、表現力が高く奇妙な構文を書ける Ruby ならではの様々な入力ケースが披露され、苦悩の歴史が垣間見えました。特に Nesting Analysis(ネスト解析)の内容に入ってからは「こんなコードも想定しなきゃいけないの?」と勝手に絶望的な気持ちになりながら見ていました。Prism への本格移行の道のりはまだまだ長いと思いますが、従来のトークンベース解析に比べて、AST(抽象構文木)ベースの Prism を使えば、IRB が担っていた独自の構文解析を委譲できる点が魅力的だと感じました。Ruby における楽しみがまた一つ増えた感覚があり、今後の RubyKaigi でも動向をウォッチしていきたいと思います。 ( @edy629s ) 終わりに さて、本ブログにてタイミーによる RubyKaigi 2025 の参加レポートも終了となります。Day1やDay2に関してもブログを書いているのでよろしければそちらも併せてご覧ください。 今後も Ruby を利用する会社の一員としていろんな発信、貢献をしていけたらと考えているので、今後お会いした際にぜひ一緒にお話ができると嬉しいです!それではまた来年函館でお会いしましょう!
2025年4月16日から18日の3日間 、 愛媛県松山市 にて、RubyKaigi 2025が開催されました。 rubykaigi.org タイミーでは、昨年に続き、世界中で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を活用し、 新卒内定者やインターン生を含む総勢16名 が現地でカンファレンスに参加しました。 この記事では、現地参加した各エンジニアの印象に残ったセッションとその感想をまとめてお届けします。 今回はその第3回で、 前回 に引き続きDay2の内容をまとめています。Day3のレポートも近日中に公開予定です。 読者の皆様にとって、今後の学びの参考になれば幸いです。 Day2開始前の様子。緞帳の絵柄は毎日変化していてちょっとした楽しみでした。 RuboCop: Modularity and AST Insights rubykaigi.org 概要 セッションでは、主に以下の 3 つの主要なテーマについて掘り下げられました : Ruby LSP Add-on : Ruby Language Server Protocol (LSP) のアドオン機能に関する議論がなされました。Shopify製のruby-lspをRails開発コンテナで使用している現状を踏まえ 、RuboCop、StandardRuby、Ruby LSPがそれぞれ独自のLSP実装を持っている非効率性を指摘し 、RuboCopのLSPランタイムの統一が提案されました。Ruby-LSPのAdd-on機能を利用し、RuboCopの組み込みLSPランタイムを再利用する実験的な試みが紹介されました。これにより、複数の開発ツールと連携するRuby LSPの利点を活かしつつ、各ツールでのコード解析の重複を避けることが期待されます。 Plugin System : RuboCopのプラグインシステムの刷新について詳細な説明がありました。従来、非公式なモンキーパッチである "Inject" ハックが拡張機能の事実上の標準となっていましたが、設定の衝突やロード順序による不整合などの問題点がありました。この課題を解決するため、公式の拡張APIとなりうるプラグインシステムがRuboCop 1.28で導入されました。この新しいプラグインシステムは、Linterプラグインの仕様に基づいており、安定した抽象インターフェースを提供し、RuboCop内部で設定を管理します。プラグインの利用者と開発者向けに、具体的な移行方法や実装方法が解説されました。 AST Insights : Abstract Syntax Tree (AST) に関する洞察として、特にParser gemとPrismという2つのRubyパーサーに焦点が当てられました。メンテナンスの課題を抱えるParser gem に対し、Shopifyが開発するPrismがより将来性のあるパーサーとして紹介されました。RuboCop 1.27からPrismをオプションのバックエンドとして利用可能であり、RuboCop 1.28以降では Ruby 3.4以降のデフォルトパーサーとしてPrismの変換レイヤーを使用することで、構文の互換性を確保し、メンテナンスコストを削減しています。PrismのASTを直接利用することの利点と課題についても議論されました 。 全体として、このセッションは、RuboCopの拡張性とRubyエコシステムとの連携を強化するための重要なアップデートと、Rubyコード解析の基盤となるASTパーサーの進化について、最新の情報と将来の展望を提供するものでした。 感想 今回のセッションは、RuboCopが単なるコードフォーマッター、リンターから、より広範な Ruby開発エコシステムの中核となるツールへと進化しようとしている意欲を感じさせる内容でした。 特に印象的だったのは、 公式のプラグインシステムの導入 です。これまで、サードパーティの拡張機能は "Inject" ハックという、やや不安定で保守性の低い方法に依存していたため、今回の刷新はRuboCopのエコシステム全体の健全性を高める上で非常に大きな進歩と言えるでしょう。プラグイン開発者にとっては、より安定したAPIを利用できることはもちろん、設定管理がRuboCop側で統合されることで、より本質的なCopの開発に集中できるようになるのではないでしょうか。 また、 Ruby LSPとの連携 も注目すべき点です。異なるツールが個別にLSP機能を持つのではなく、RuboCopの持つ強力な解析能力をRuby LSP経由で他のエディタやIDEでも活用できるようになることは、開発者体験の向上に大きく貢献すると感じました。まだ実験的な段階とのことですが、今後の発展が非常に楽しみです。 そして、 ASTパーサーをParser gemからPrismへと移行する動き は、Rubyの進化に追従し、より現代的な構文をサポートするための必然的な流れだと感じました。Parser gemのメンテナンスが困難になっている現状を踏まえると、Shopifyが積極的に開発しているPrismを採用することは、RuboCopの将来的な安定性と機能拡張にとって重要な決断と言えるでしょう。翻訳レイヤーを介してParser gemのAPIを維持しつつPrismを利用するというアプローチは 、既存のRuboCopのエコシステムへの影響を最小限に抑えながら、最新のRuby構文への対応を進めるための賢明な戦略だと感じました。ただし、将来的にはPrismネイティブのASTへの移行も視野に入れているような議論もあり、その際の移行コストや互換性維持が重要な課題となるでしょう。 全体として、このセッションは、RuboCopの内部構造のモジュール化を進め、より多くの開発者やツールとの連携を強化し、そしてRuby言語の進化に柔軟に対応しようとするKoichi ITO氏をはじめとするRuboCopチームの強い意気込みを感じさせるものでした。今後のRuboCopの発展がますます楽しみになる発表でした。 (@hiroshi) 概要 本登壇はRubocopに関するトピックを三本立てで提供する。最初にRubocopプラグインシステムの導入により、拡張性を持たせるとともに、非公式なモンキーパッチが横行することで安全でない書き方を一掃することを目指している。 次に、Ruby LSPアドオンは、RubocopのデフォルトのLSPにアドオンとしてRuby LSPを組み込めるようにした。これは、Ruby本体、Rubocop、Ruby LSPが今までバラバラにLSP実装を持っていたものを統合することを狙いとしている。ステータスとしてはまだExperimentalでデバッグの最中である。 最後に、Rubocopの内部ASTとしてPrismを採用したことと、それまでの検討についての発表を行っている。Prismに関しては今年のRubyKaigiでも様々な活用が発表されたが、並行してparser gemのメンテナンスが縮小しているという背景もあり、Rubocop 1.75からはRuby 3.4以降のバージョンではデフォルトのパーサーがPrismとなる。また、Prismとparser gemでASTの互換性を保つためにPrism::Translation::Parserというクラスを用いている。 感想 思い出話をしますが、私は2社前、7年ほど前は超Rubocopアンチでした。 時間をかけてじっくり適応して今となっては当たり前のものとして使用できていますが、ルール同士が競合し合ってダブルバインドしてくることにブチ切れたのも懐かしい話です。 さて、登壇者のkoicさんには「なんか毎年RubyKaigiで登壇してんな」という印象を持っていますが、実際その通りで私が初めて参加した2018年仙台から登壇が途切れておらず、私がひよっこのRailsエンジニアとして「Rubocop使いづれー!」と叫んでいた頃からこのように持続的なアウトプットを続けていることが、Rubocopをデファクトスタンダードの開発ツールとしての立場を揺るぎないものにしているんだなという敬意を覚えます。 そして今回の発表内容である、プラグインシステムやデフォルトパーサの変更もまさしくプロダクトの鮮度を保つための持続的な開発であると言えます。 gemのちょっと込み入った利用方法になってくると途端に情報が少なくなって、書いている人も意味がよくわかっていないような秘伝のタレ化したスニペットが出回る、ということは利用側としてあるあるだなという実感がありますが、そのような状況を提供側として問題視してモンキーパッチが必要ないように仕組みで解消したのは素晴らしいことだと思いました。 (@Hiromi Kai) speakerdeck.com Keeping Secrets: Lessons Learned From Securing GitHub rubykaigi.org 概要 GitHubでの重大なセキュリティ脆弱性の発見や原因調査プロセス、教訓などが語られました。特にRubyコードにおける send メソッドの危険性を深堀りする内容となっていました。登壇スタイルも珍しい2名体制となっており、GitHub社のシニアプロダクトセキュリティエンジニアの Dennis Pacewicz 氏ならびにPraetorian社のスタッフセキュリティエンジニアの Wei Lin Ngo 氏が登壇していました。 感想 ソフトウェアエンジニアであれば誰しもがお世話になっている GitHub。それが Ruby on Rails 製のサービスであることは有名な話だと思います。Rubyistである私も以前から GitHub 社の取り組みには関心はあったものの、実はこのようなカンファレンスや技術イベントでも直接内部の開発者の発表を聞いたことはありませんでした。更に2名体制での登壇スタイルは RubyKaigi では珍しかったので興味を持って視聴しました。 まず、冒頭で GitHub のコンテナ上のすべての本番環境シークレットにアクセスできる可能性があった と語られました。非常に恐ろしい話ですね…。 具体的な原因となるプログラムでは Ruby で時折見かける send メソッドの利用がありました。私もプロダクションのコードで利用したことがあり、耳が痛い話になりそうだなと身構えました。send メソッドは強力な動的メソッドディスパッチですが、GitHub では特定のControllerにてユーザー入力された値を検証なしに send メソッドに引き渡すことで最終的にすべてのプロダクションシークレットを含むハッシュが返される処理が存在していたとのことです。紐解いていくと必ずしも send メソッドの柔軟性が必要な訳ではなく便宜上の理由程度で使用されていたようです。対応後は動的なメソッドコールは消え、特定条件に基づいてメソッドを直接呼び出すより静的で安全なコードに置き換えられました。 今回の事例で登場した send のように Ruby には便利で柔軟性のあるメソッドが存在していると思います。GitHub 社においても今回の脆弱性に繋がった事例が存在するため、業務利用する場合にはメソッドの特性や利用ケースに対するリスクの理解及びそれを検知する仕組みづくりが改めて重要だと身を引き締める機会になりました。脆弱性が見つかった場合も特定個人を非難するのではなく組織全体として学びを得て改善していくブラムレスカルチャーや、発見された脆弱性を起点に類似パターンを探すバリアント分析など、今回の脆弱性発見から恒久対応までに GitHub にて取られたアプローチも学びとして得られました。 (@edy629s) Making TCPSocket.new "Happy"! rubykaigi.org 概要 このセッションでは、Rubyの標準ライブラリであるSocketにおける TCPSocket.new メソッドへのHappy Eyeballs Version 2 (HEv2) の導入 について解説されました。 まず、導入の背景として、IPv4とIPv6が共存する環境での従来の接続処理の問題点、すなわち逐次的なアドレス解決と接続試行による遅延の可能性が挙げられました。これに対し、より効率的な接続確立を目指すHappy Eyeballs Version 2 (HEv2) アルゴリズムの概要、特に 並行したアドレス解決と接続試行 、IPv6の優先、遅延タイマーなどの特徴が説明されました。 次に、Rubyで実装された Socket.tcp へのHEv2導入がRuby 3.4で完了したことを踏まえ、より多くのユーザーが利用するC言語実装の TCPSocket.new への導入における 技術的な課題 が詳細に語られました。主な課題として、状態管理の複雑さ、割り込み可能な名前解決の必要性、スレッド数の違い、完了検出方法の違い、そして select(2) システムコールの上限による問題と poll(2) への移行などが挙げられました。 これらの課題に対し、状態管理を排除した新しい Socket.tcp の実装を参考に、 TCPSocket.new では 新しいスレッドを作成して並行して名前解決を行い、パイプで結果を通知する 仕組みや、GVLなしで待機する関数の利用、 rb_thread_fd_select() という内部APIを活用して必要最小限の修正で対応したことが説明されました。 その結果、HEv2がデフォルトで有効になった Ruby 3.4 がリリースされ、ベンチマークテストでは大幅な接続時間短縮が確認されたことが示されました。また、HEv2の有効/無効を切り替える方法や、利用上の注意点なども解説されました。 最後に、この開発に貢献した多くのRubyコミッターへの感謝の言葉で締めくくられました。 感想 この発表では、ネットワークの低レイヤーに関わる重要な機能であるHappy Eyeballs Version 2の TCPSocket.new への導入という、非常に興味深いテーマについて深く掘り下げた解説を聞くことができました。IPv4/IPv6の共存という現代のネットワーク環境における課題に対し、ユーザーが意識することなく恩恵を受けられるような改善が、標準ライブラリに地道に積み重ねられていることに感銘を受けました。 特に、C言語での実装における並行処理の実現や、システムコールの選定、そしてそれに伴う複雑な課題を一つ一つ解決していく過程が、具体的なコードやアーキテクチャの変化と共に示されており、非常にわかりやすかったです。 select(2) の制約という普段意識しないような問題に直面し、 poll(2) への移行という大きな決断と実装を行った点など、技術的な深さと熱意を感じました。 RubyKaigiという場で、このような基盤となる技術の進化について知る機会が得られたことは、今後のRubyを使った開発においても大いに役立つと感じました。HEv2がデフォルトで有効になったRuby 3.3.0を積極的に利用していきたいと思いました。 (@hiroshi) Happy Eyeballs V2 を TCPSocket.new に導入する過程で直面した課題と、それらの解決策を段階的に解説してくださる、非常にわかりやすい発表でした。 Happy Eyeballs V2 が、IPv4 と IPv6 の両方に対応した環境において、より高速かつ効率的な接続確立を実現するために導入された背景についても触れられており、その必要性を理解できました。 また、RFC などの標準仕様への準拠は、これまで Ruby が対応してくれるのを待っているような感覚でしたが、この発表を通してその裏側で Ruby コミッターの方々が尽力してくださっていることを改めて認識しました。 塩井さんのご発表は、過去の RubyKaigi でも拝聴しており、そのわかりやすさを楽しみにしていました。今回の発表も期待を裏切らず、大変理解しやすく、興味深い内容でした。 (@nissy325) speakerdeck.com おわりに 今回の記事では、RubyKaigi 2025 Day2の3つのセッション、RuboCopの進化、GitHubのセキュリティ教訓、そしてTCPSocket.newへのHappy Eyeballs V2導入について、参加者の視点からの学びと感想をお届けしました。 次回はDay3のレポートを公開しますので、どうぞお楽しみに! Day2では弊社主催でDrinkUpイベントも開催しました!@味ふく
2025年4月16日から18日の3日間 、 愛媛県松山市 にて、RubyKaigi 2025が開催されました。 rubykaigi.org タイミーでは、昨年に続き、世界中で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を活用し、 新卒内定者やインターン生を含む総勢16名 が現地でカンファレンスに参加しました。 前回 に引き続き参加レポートの第2回として、Day2 vol.1と題し、Day2で現地参加した各エンジニアの印象に残ったセッションとその感想をまとめてお届けします。 今後も、 Day2 vol.2 、 Day3 と続けてレポートを公開予定です。 各セッションごとに内容を整理し、参加者自身の視点から学びや気づきをまとめています。読者の皆様にとって、今後の学びの参考になれば幸いです。 Performance Bugs and Low-Level Ruby Observability APIs rubykaigi.org 概要 「遅すぎて不具合に感じる」というパフォーマンスの問題をPerformance Bugsとして紹介し、その問題は「遅さ」ではなく、CPU、メモリ、時間といったリソースの過剰消費の問題として捉えるべきとしました。その問題が本番環境やユーザー体験、コストに与える影響を評価することが重要とした上で、そのための調査にはRubyのObservability APIを使うと良いということが紹介されました。発表ではTracePoint APIやPostponed Job APIなど具体的なAPIと簡単なプロファイラの作り方を紹介していました。最後にPerformance Bugsとの向き合い方を紹介して終わっています。 主要APIの解説と活用例: low_level_toolkit gem: 低レベルAPIの利用例と簡単なツール群を提供。 TracePoint API (内部イベント含む): メソッド呼び出し、クラス定義、例外発生に加え、オブジェクト生成(new_object)やGCの開始/終了(gc_start, gc_end)といったVM内部イベントもフック可能。オブジェクト割り当ての追跡やGCタイミングの計測デモが示された。コールバック内での制限(オブジェクト生成不可など)にも言及。 Postponed Job API: 低レベルAPIのコールバック内で安全にRubyコード(オブジェクト生成やAPI呼び出しを含む)を実行させるための仕組み。「セーフポイント」と呼ばれるVMが安全な状態になったタイミングで実行される。GC完了時にRubyコードで情報を記録するデモが示された。 Frame Profiling API: 低オーバーヘッドで現在のバックトレース(コールスタック)を取得できる。プロファイラ構築の基礎。 Debugger Inspector API: フレームプロファイリングより高コストだが、はるかに詳細な情報(呼び出し元のオブジェクト、メソッド引数、ローカル変数、バインディング、命令シーケンスなど)にアクセスできる。デバッガ構築に利用される。呼び出し元のオブジェクトやそのバインディングを取得するデモが示された。 GVL Instrumentation API: Global VM Lock (GVL)の取得・解放、スレッドの実行・待機状態遷移を追跡できる。スレッドがGVL待ちでどれだけ時間を費やしているかを計測するデモが示された。 感想 タイミー入社からの約5年間、自分はそれなりにパフォーマンスとは向き合ってきたと思っています。弊社でもDatadogを利用しているのですが、これまでのパフォーマンス改善でとても役に立ちました。パフォーマンス改善の話をすると、昔は超簡単なn+1の改善をすれば2倍3倍と早くすることができました。しかしながら明らかに低速な部分が減るとちょっとずつ丁寧な観測が要求されます。その際にメソッドコールやオブジェクト生成などが観測できるととても便利です。今回の発表では、そんな際に利用しているプロファイラがどうやって作られているのかを紹介しているものでした。言語やプロファイラの理解を深めるために一回触ったり作ったりしてみようと思います。プロファイラは小さいものを含めてまだ作ったことがないので楽しみです。 (@Juju_62q) RubyKaigi前に #Rubygemsコードリーディング部で dd-trace-rb のソースコードを読んでいました。各Rubyバージョンへのパッチ対応をしつつ、C実装も独自に拡張しており、尚且つ型を書いていたので、とても練度の高いgemだなと。 発表では、TracePoint API、Postponed Job APIなどRuby VM内のAPIにはどんなものがあって、どのように活用できてどんなデータが取得できるのかという話がありました。 これらのAPIを使ってRelease GVL profilerをわずか107行で作ったという話がありましたね。 普段からモニタリングやログ探索の場面でDatadogにはかなりお世話になっており、便利に使っていました。内部実装に関しては知見がなかったので、プロファイラの実装に関してイメージが湧いたのは自分にとって有意義でした。 プロファイラは使うだけで作ったことはないのですが、イメージが湧いたので自分で作ってみようと思います。 P.S. IvoにセッションやDatadogへの感謝を直接伝えて、一緒に写真を撮ってもらいました!ありがとうございました! (@ dak2 ) サービスの規模が大きくなっていくほどパフォーマンスの問題とも真摯に向き合っていく必要があります。自分はタイミーで初めて規模の大きいソフトウェア開発を経験したこともあり、パフォーマンスの問題との付き合い方は勉強中です。 これまではとにかく「遅ければ遅いほど問題だ」と考えていましたが、そうではなくパフォーマンス劣化によって「ユーザー体験や自社のコスト増にどの程度影響しているか」という視点が大事なんだという学びを得られました。 監視ツールでは純粋に処理に時間がかかっているものはわかりますが、それぞれがどの程度ユーザー体験やコスト増に繋がっているかはパッと見わからないです。この辺りの判断を行えるようになるためには各リソースにかかるコストを把握する必要があり、また様々あるドメインについて、レスポンスが悪化することによってどの程度ユーザーに不便をかけるのかも把握しておく必要がありそうだなと思いました。一人で全部把握するのは大変ですが、組織全体として誰かが知っていれば評価はできると思うので、誰がどの領域に詳しいか、誰も知らないものはどれかをきちんと把握し、これからもパフォーマンス問題に向き合っていきたいです。 今回紹介していただいたツールもパフォーマンス劣化の原因を特定するのに役立ちそうなので、一通り使えるようになりたいと思います。 (@rhiroe) プロダクト開発は作って終わりではなく、日々モニタリングを行い改善していく必要があります。今までもdatadogを使ってモニタリングは行っていましたが、どのような仕組みでモニタリングを可能にしているのかは理解できていない状態でした。 発表では、低レベルなRubyの可観測性 (Observability) APIについての解説があり、複数のAPIが紹介されていました。また、パフォーマンスの問題をどう捉えるかという視点についても言及がされており、どれくらいユーザーやコストに対して影響を与えているかが大事であるというものでした。パフォーマンスは良い方が良い、というのは間違いないかなとは思っているのですが、どこからが修正すべき問題として捉えるのかどうか、というのは新しい観点であり新鮮でした。 今回の発表でプロファイラのイメージが少しだけ湧いたため、紹介されていたAPIやサンプルコードを用いてプロファイラの作成にも取り組んでみようと思いますし、今後の改善においては、ユーザーやコスト面の影響などを考えて優先度をつけていきたいです。 (@nissy325) docs.google.com ZJIT: Building a Next Generation Ruby JIT rubykaigi.org 概要 ShopifyのRuby & Rails infrastructure teamのMaximeによるセッションでは、新しいRubyのJIT コンパイラであるZJITの開発概要が説明されました。ZJITは、 将来20年以上にわたる利用を見据え 、高性能、高保守性、高拡張性を目指しているようです。ZJITはメソッドベースのコンパイルと SSAに基づく中間表現を採用し、高速な関数呼び出しの実現を目指しています。初期のマイクロベンチマークでは、インタプリタやYJITよりも高速な結果が出ています。Ruby 3.5でオプショナルで利用可能になるとのこと。4.0では実験的に取り込まれる予定らしいです。今後は、より現実的なベンチマークでの性能向上とコンパイラの最適化に注力していくとのことです。 感想 一番気になっていたMaximeのセッション。このセッションではRubyの次の20年を見据えたZJITという新しいコンパイラや、YJITとの違いについて発表がなされました。 近年、Rubyのバージョンが上がるごとにYJITの性能も良くなっており、Rubyのバージョンを上げたら速くなった…!という体験をされている方も多いかと思います。 ただ、性能の伸びは徐々に鈍化しているようです。 Rubyは良い言語だけど、もし速度が遅ければ、パフォーマンス最適化要求の波に飲まれていずれ滅ぶという趣旨の発言もありました。 そういったモチベーションからZJITに取り組まれているとのこと。 ZJITはSSA(Static Single Assignment Form)に基づく中間表現を採用しているようです。SSAとは「すべての変数の使用に対して、その値を定義(代入)している場所がプログラム上で一箇所しかないように変数の名前を付け替えた中間表現形式」のようです。これは多くのコンパイラで広く使われている中間表現です。これによってコンパイラの設計が理解しやすくなり、拡張も容易になるとのこと。コンパイラについては何もわからないので、Deep Diveしてみようと思いました。 高速なJIT-to-JITの呼び出し、ポリモーフィックインラインキャッシュなどYJITでは難しかった高度な最適化機能の実装になるらしいです。 セッションの中で弊社のブログが紹介されましたね!これからも発信し続けていきたいです。 tech.timee.co.jp この記事にもあるようにRuby 3.4.2のYJITによる高速化の恩恵は受けられませんでしたが、次の YJIT、並びにZJITの動向に目が離せません。(ZJITのPRマージされたみたいですね!) 参考資料 https://www.jstage.jst.go.jp/article/jssst/25/1/25_1_1_19/_pdf https://bugs.ruby-lang.org/issues/21221 https://github.com/ruby/ruby/pull/13131 (@ dak2 ) Dissecting and Reconstructing Ruby Syntactic Structures rubykaigi.org 概要 Rubyの柔軟性と表現力を裏側で支えるParser(特にparse.y)が抱える課題と、解決アプローチを通して、Rubyの構文構造の根底にある原則とパターンについて学ぶことができます。 感想 これまでRubyでアプリケーション開発を行う上で、Parserの存在を特に意識することはありませんでした。しかし、この発表を通して、Rubyのシンプルに見える見た目の内部には、非常に複雑な構文構造が存在し、それがRubyの持つ柔軟性や豊かな表現力を支えていると実感することができ、発表者の@ydah_ さんの熱意も相まって、一気にこの分野への興味が出てきました。 重複した部分を特定し共通構造を抽出して抽象化するというアプローチは、日々のアプリケーション開発でも行われているものですが、それを長年にわたり多くのRubyコミッターによって開発されてきたparse.yに対して行うのは非常に困難だったのではと想像します。今回、Lramaの新しい記法を用いることで構造の抽象化を実現し、Rubyの柔軟な文法を維持しながら、保守性と可読性の向上を可能にしている点にとても感銘を受けました。 (@creamstew) speakerdeck.com Speeding up Class#new rubykaigi.org 概要 このセッションでは、 RubyのClass.newのパフォーマンス改善について解説していました。現状のC言語実装では、RubyとCの呼び出し規約の切り替えなどにコストがかかる点が課題でした。このオーバーヘッドを解消するため、Ruby自身でClass.newを実装する新しい試みが紹介されました。これにより、多くの場合で高速化を実現しましたが、メモリ使用量の増加やスタックトレースのわずかな変化といったトレードオフも存在するとのことです。 感想 普段Railsアプリケーションの開発に携わる中で、Rubyのコードがどう動いているかについて気にすることはほとんどありません。ましてや、パフォーマンスを改善しようと考えたことはなかったので、Class.newのような基本的な部分に改善の余地があるとは想像もしていませんでした。このような改善に取り組む熱意を尊敬するとともに、こういった方々に我々は支えられているのだなと改めて感じました。 また、RubyとCがどのようにデータをやり取りしているかの深い部分を知ることができ(完全には理解できませんでしたが…)、よりRubyに詳しくなれたような気がします。 今後は、感謝の気持ちを忘れずに開発に臨むとともに、パフォーマンス改善をする際には「実は Rubyのコード自体にボトルネックがあるのでは?」という視点を持ちたいと思います。 (@otaksy) “Class.newをCじゃなくRubyで動かす”、とだけ聞くと「Cの方が速いでしょ?Rubyで動かすと遅くならない?」と思いましたが、話を聞くとClass.newの呼び出し箇所が非常に多く、オブジェクト生成の部分だけを見た場合の速度はCで動かした方が速いが、RubyからCに切り替えるためのコストも含めるとRubyだけで動いた方が速いという説明を聞いて納得しました。 この改善によって一般的なユースケースではパフォーマンスの有意な改善が見られるそうなので楽しみです。Ruby3.5にこの変更が含まれる予定だそうですが、次はRuby4.0になるかもみたいな話もあり、楽しみが2倍です。 (@rhiroe) Benchmark and profile every single change rubykaigi.org 概要 このセッションでは、Benchmark-Driven Development(ベンチマーク駆動開発)という手法が紹介されていました。その内容は、コーディングする前にベンチマークを設計し、コーディング前後でベンチマークの実行結果を比較することで、変更によるパフォーマンスの悪化を早期に発見できるというものです。ベンチマーク駆動開発を用いて、RubyフレームワークのSinatraを100倍高速化させたXinatraを実装する取り組みについても紹介されていました。 感想 これまでパフォーマンス改善を何度か経験してきましたが、多くの場合、パフォーマンスが無視できないほど悪化してから改善に着手していました。そのため、コーディング段階でベンチマークを実行し、パフォーマンスの悪化を防ぐというアプローチは、斬新でありながらも有効だと感じました。 また、N+1のような明確なボトルネックを解消した後に、チリツモでパフォーマンスが悪化している状態を何度も見てきたため、チリをツモらせないための解決策としても活用できそうです。 ただし、すべての開発にこの手法を適用すると、開発効率が落ちる可能性があるため、そのトレードオフは考慮する必要がありそうです。そのため、まずはパフォーマンスが特に重要な機能に絞って、この手法を実践してみようと思いました。 (@otaksy) おわりに RubyKaigi 2025 Day2 vol.1レポートでは、低レベルAPIやパフォーマンス改善などRubyの深層に迫るセッションを中心に、現地参加したエンジニアそれぞれの視点からの学びや気づきをお届けしました。 本レポートで取り上げたセッションでは、普段は見えないRubyの仕組みやパフォーマンスへの深い知見を得られたことで、Rubyの奥深さに一層興味が湧きました。 今後もDay2 vol.2、Day3とレポートを公開しますので、どうぞお楽しみに! Day1の前日に立ち寄った松山市内の海岸