Findy/ファインディのブログ - TECH PLAY

TECH PLAY

Findy/ファインディ

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

215

こんにちは!ファインディのTeam+開発部でEMをしている奥村です。 チームや組織が大きくなるにつれ、横の繋がりが薄くなった気がする…そんな課題を感じたことはありませんか? 私たちファインディのTeam+開発部は多くのメンバーを迎え入れながら拡大を続けています。 現在26名(業務委託除く、正社員のみ)が所属しており、そのうちここ一年でジョインしたメンバーが11名にのぼります。 一方で横軸のコミュニティ構築とメンバーの主体性の促進が組織の課題として挙がっていました。 そこでOpen Space Technology(以下OST)というワークショップを実施したので、今回はワークショップの紹介と実施レポートを報告します。 なぜOST? まず前提として私たちは、Team+開発部を 「チーム横断での協働・協力等の相互支援を活性化し、Findy Team+開発のあるべきを主体的に思い描き、建設的な議論を行いながら自走できる組織」 にしたいと考えています。 冒頭で述べた通り、私たちTeam+開発部は多くのメンバーを迎え入れて拡大をしています。 人数増加に伴いチームも6チームに分かれていますが、正直なところ、 かつてのような横軸のつながりが薄くなってきている と感じています。 また、組織課題に触れる機会も断片的・限定的になりがちで、他のチームの状況や各メンバーがどんなことを考えているのかを知る機会が減ってきています。 何かしら課題を感じても「周囲の考えが分からない」「どんな活動が進められているか見えない」といった具合に主体的な行動が抑制されかねないと感じています。 実際、属人化や対応偏り、知見や活動の共有の不足などを聞くこともありました。 そこで、次のような目的を持ってOSTを実施することにしました。 横軸のコミュニティを再構築し、課題解決に向けた協働文化や成長の相互支援を活性化する Team+開発の未来のあるべきを主体的に思い描き、建設的な議論を行いながら自走できる組織にする もう少し具体的に言うと、次の狙いです。 信頼関係・相互理解:チームを超えた交流の促進 自己組織化:主体的にあるべき姿を考える文化の醸成 自立性:自立して学び、行動する文化の促進 OSTってなに? 「OST」というワークショップをご存知でしょうか? OSTは、参加者が自分で「これを話したい!」というテーマを持ち寄って、自由に議論するスタイルのワークショップです。 セッションテーマの提案からタイムテーブルの作成、セッションの進行までを参加者自身が主体的に行うことが特徴です。 セッションテーマは誰でも提案可能で、アジェンダもその場で決まります。 参加するセッションも参加者が自身の興味関心に合わせて自由に選べます。また、セッションの途中で他のセッションへの移動も可能です。 「対話」をメインの目的としており、明確なネクストアクションを決めるようなことはありません。 対話を通して、テーマに対する理解の深化や知見の共有、アイデア創出など行うワークショップになります。 OSTには"4つの原則"があります。これらの原則は参加者の主体性を促すOSTの鍵となります。 ここにやってきた人は、誰もが適任者である 何が起ころうと、それが起こるべき唯一のことである いつ始まろうと、始まった時が適切なときである いつ終わろうと、終わった時が終わりのときである なお、他にも"蝶と蜂"や"移動性の法則"といった特徴がありますが、私たちの人数規模では詳細に説明する必要がないと判断して省略をしました。 似たワークショップにワールドカフェがあります。 ワールドカフェは設定されたテーマに対してメンバーを変えながら議論を深めていきます。 これに対して、OSTはテーマが複数並行して進行し、参加者が自由に選べる点で異なります。 当日の流れ 全体タイムテーブル 10:00 ~ 10:15: 準備 10:15 ~ 10:30 アイスブレイク 10:30 ~ 11:00 概要説明、タイムテーブル作成 11:00 ~ 15:00 セッション 11:00 ~ 11:40 セッション① 11:50 ~ 12:30 セッション② 12:30 ~ 13:30 お昼(お弁当) 13:30 ~ 14:10 セッション③ 14:20 ~ 15:00 セッション④ 15:00 ~ 15:10 クロージング、片付け 弊社オフィス内のイベントスペースで実施をし、フルリモートのメンバーもオフィスに集まってもらい23名が参加をしました。 アイスブレイクでは、テーブルごとに他己紹介を行なってもらい、各メンバーのパーソナルな部分を知る時間を設けました。 フルリモートのメンバーやチーム外のメンバーの意外な一面を知り、本題のセッションに入る前の心理的なハードルを下げることができたと思います。 各セッションは40分+10分のバッファで設定していました。 セッションタイムテーブル 大枠のテーマとして 「Team+の今後を考えるとき今話したいこと」 を置いて、各セッションのテーマはその場で各メンバーから自由に提案してもらいました。 念の為、テーマが挙がらなければマネージャー陣がファーストペンギンに…と裏で話していましたが、 全くの杞憂でした。 AIの話から、開発の進め方、品質、コミュニケーションなどなど、様々なテーマが挙がりました。 重複するものはマージし、類似するテーマは別時間にズラすなどの調整をして、最終的にはこのようなタイムテーブルとなりました。 セッション一部紹介 実際のセッションを一部紹介します。 ・チームを超えた交流の方法について ・どうやって考えている?(プロセス・手法) やってみてどうだったか? 実施後アンケートから、非常にポジティブな結果が得られました。 対話と発散を意図していたため業務への活用はあまり期待していませんでしたが、「ある程度活用できる」が60%、「積極的に活用できる」が40%と、全員が何かしらの活用を考えることができたようです。 実際に、OST実施後に改善へ向けたアクションを起こしたメンバーもいました。 自由記入の感想では次のような回答がありました。 なかなか話す機会ないトピックについて話ができた チーム外のメンバーがどう課題感を持っているか、どういう考えを持っているのかを広く知れる機会になった 普段感じている課題感や難しさを共有できた マネージャーからメンバーまで、役職関係なくさまざまな視点からの意見が聞けた 今回のOSTを通して、各メンバーが何かしらに興味関心を持ち、何かしらに課題感を持っていることを再確認できました。 また、それらを発散・共有するだけでも組織の一員としての意識が高まることを実感しました。 目的が達成されたのかは今後のアクション次第ではありますが、少なくとも重要で大きな一歩目を踏み出せたと感じています。 コミュニケーションにおいても、普段フルリモートのメンバーやチーム外のメンバーなど幅広く交流ができ、通常の業務で会話する際のハードルを下げられたと考えられます。 次回以降の改善点として、他セッションでの議論を知る時間を設けることやエンジニア以外のメンバーを巻き込むことなどを考えています。 まとめ Team+開発にとってははじめてのOSTでしたが、単なる交流会ではなく、 組織を強くするための大きな一歩になったと確信しています。 交流を深められた・課題感を共有できた・アイデアを出し合えた等ポジティブな感想が多く、実施後に多くのメンバーから「定期的にやってください」と直接言われるほどでした。 反省点もあるものの、それを活かして今後も引き続き、組織の強化・文化の醸成に向き合っていきます。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。Findy Tech Blog編集長の高橋( @Taka-bow )です。 前回の記事 では、全体の44.3%が開発生産性に前向きという結果をご紹介しました。今回は開発手法別に深掘りすると、予想外の事実が浮かび上がってきました。 開発生産性への印象は多様 ── 約半数が中立的立場も抵抗感は少数派 意外な結果 ── アジャイル実践者の59.6%が開発生産性に前向き なぜアジャイル実践者は開発生産性に前向きなのか アジャイルの価値観と生産性改善の親和性 Kent Beck氏が語る測定の本質 ── 「測定が目標になると、システムは歪む」 アジャイル実践者の「前向きさ」に潜む3つの勘違い 何を測るべきか ── Kent Beck氏が示す価値創造の道筋 測定を「コントロール」ではなく「認識」のツールとして ── Kent Beck氏の4つの提言 次回予告 【調査概要】 調査対象: ソフトウェア開発(組み込み開発を含む)に直接関わるエンジニア、プロダクトマネージャー、プロジェクトマネージャー、エンジニアリングマネージャー、開発責任者など 調査方法: インターネット調査 調査期間: 2025年4月2日(水)~2025年5月21日(水) 調査主体: ファインディ株式会社 実査委託先: GMOリサーチ&AI株式会社 有効回答数: 798名(95%信頼区間±3.5%) 統計的検定力: 80%以上(中程度の効果量d=0.5を検出) 調査内容: 開発生産性に対する認識 開発生産性に関する指標の活用状況 開発生産性に関する取り組み 開発環境・プロセス評価 組織文化と生産性 開発生産性への印象は多様 ── 約半数が中立的立場も抵抗感は少数派 あらためて、「開発生産性」という言葉に対する印象を見てみましょう。 開発生産性への印象に関する回答分布 選択肢 回答者数 割合 詳細内訳 どちらでもない 384人 48.1% – ポジティブ 354人 44.3% とてもポジティブ + どちらかというとポジティブ ネガティブ 61人 7.6% とてもネガティブ + どちらかというとネガティブ 合計 798人 100.0% – 「開発生産性」という言葉に対してネガティブな印象を持つ人は わずか7.6% (61人)。一方で、 44.3%がポジティブ (354人)な印象を持っており、 約半数(48.1%)が中立的 (384人)な立場を取っています。 この結果から、多くのエンジニアが生産性向上に対して前向き、あるいは少なくとも抵抗感を持っていないことが分かります。これは、日本の開発現場が変化を受け入れる準備ができていることを示唆しています。 意外な結果 ── アジャイル実践者の59.6%が開発生産性に前向き 私がこれまで出会ったアジャイルコーチの多くは、口を揃えて「生産性は測れない」「生産性に意味はない」と言っていました。そのため、アジャイル実践者ほど開発生産性という概念に抵抗を示すのではないかと予想していました。 しかし、調査結果は意外でした。 開発手法別の開発生産性に対するポジティブ印象の比較 フレームワーク 対象者数 ポジティブ印象者数 ポジティブ率 アジャイル系 245名 146名 59.6% ウォーターフォール 294名 116名 39.5% 差 – – 20.1ポイント アジャイル実践者の約6割(59.6%)が開発生産性に前向きという結果は、ウォーターフォール開発者(39.5%)と比べて20.1ポイントも高い数値でした。 さらに、実際の取り組み状況を見てみましょう。 開発手法別の開発生産性向上への取り組み状況の比較 フレームワーク 対象者数 取り組み実施者数 取り組み率 アジャイル系 245名 117名 47.8% ウォーターフォール 294名 105名 35.7% 差 – – 12.1ポイント アジャイル系では47.8%が実際に取り組みを実施しているのに対し、ウォーターフォールでは35.7%にとどまっています。しかし、ポジティブ印象の差(20.1ポイント)に比べて、実際の取り組み率の差(12.1ポイント)は小さいことが分かります。 つまり、アジャイル実践者は「開発生産性」に対して前向きな印象を持っているものの、実際の取り組みに落とし込めていない人が多いということです。ポジティブな印象を持つ59.6%のうち、実際に取り組んでいるのは47.8%。この差は何を意味するのでしょうか? 前回の記事で指摘した「測定指標の混乱」を考慮すると、このギャップの原因が見えてきます。実際、組織が重視する指標は千差万別です。 コード行数、バグ数、残業時間、機能数、ストーリーポイント──組織によって測定する指標はバラバラで、業界全体で「何を測るべきか」の共通認識が欠けています。DORA指標(デプロイ頻度、リードタイム、MTTR、変更失敗率)の認知度がわずか4.3%という事実も、この混乱を裏付けています。 アジャイル実践者の多くは開発生産性の重要性は理解しているものの、「何を測るべきか」「どう測るべきか」が分からず、結果として行動に移せていない可能性があるのです。 なぜアジャイル実践者は開発生産性に前向きなのか アジャイルの価値観と生産性改善の親和性 なぜアジャイル実践者の方が前向きなのでしょうか。私の経験から考えると、アジャイルの実践と生産性改善の考え方には、次のような共通点があるのかもしれません。 1. 継続的な改善が文化として根付いている スプリントやイテレーション(短期間の開発サイクル)ごとにレトロスペクティブで定期的に振り返り、改善を繰り返す。この習慣により、「生産性を向上させる」という考え方が自然に受け入れられています。 2. 測定と可視化が日常的な実践 ベロシティ、バーンダウンチャート、イテレーション完了率など、アジャイルチームは様々な指標を日常的に活用しています。そのため、「測定する」ことへの心理的抵抗が少ない。 3. 変化への適応力 「変化を歓迎する」というアジャイルの原則により、開発生産性という概念も「改善の機会」として前向きに捉えられます。 4. チームの自律性と当事者意識 アジャイルでは、チームが自ら課題を発見し解決策を考えます。開発生産性も「上から押し付けられる」ものではなく、「自分たちが主体的に改善する」ものとして受け止められています。 Kent Beck氏が語る測定の本質 ── 「測定が目標になると、システムは歪む」 しかし、アジャイル実践者の59.6%が前向きだという事実は、彼らが「正しく」生産性を理解していることを意味するのでしょうか? 実は、この問題について、アジャイル界のレジェンドであるKent Beck氏が重要な示唆を与えています。19年ぶりに来日し、開発生産性Conference 2025で登壇した彼は、測定と生産性の本質的な問題について警鐘を鳴らしました。 Kent Beck 氏(開発生産性Conference 2025にて) Kent Beck氏は「グッドハートの法則」を引用しながら、こう語りました。 "When a measure becomes a target, it ceases to be a good measure. If we exert pressure on that system, the regularity will disappear. It's worse than that. If we exert pressure on that regularity to make things better, we will destroy the system that created that regularity in the first place." 「測定が目標になると、それは良い測定ではなくなります。システムにプレッシャーをかけると、規則性は消えます。それよりも悪いことに、物事を良くするためにその規則性にプレッシャーをかけると、最初にその規則性を作り出したシステムを破壊してしまうのです」 プルリクエストの例を挙げて、具体的に説明しています。 "I'm going to take my pull request that made some sense and I'm just going to slice it up. Their less readable leads to less cooperation leads to more waste leads to fewer pull requests. So by applying pressure to the software development process to make it better, we have made it worse." 「理にかなった1つのプルリクエストを細かく分割します。読みにくくなり、協力が減り、無駄が増え、プルリクエストが減ります。ソフトウェア開発プロセスにプレッシャーをかけて改善しようとすることで、悪化させてしまったのです」 このような単一メトリクスの問題に対して、「では複数のメトリクスでバランスを取ればよいのでは?」という反論が予想されます。Kent Beck氏は、この点についても次のように警告しています。 "People say well you need a balanced set of metrics. That doesn't solve the problem. Every metric that you introduce is going to distort the system that you're working in in ways that aren't what you want it to be." 「『バランスの取れたメトリクスのセットが必要だ』と言う人もいます。しかし、それでは問題は解決しません。導入するすべてのメトリクスは、望ましくない方法で作業しているシステムを歪めます」 つまり、メトリクスを増やしても、歪みが複雑化するだけで根本的な解決にはならないということです。これは、日本の組織でよく見られる「各チームが異なるKPIを追求する」状況と重なります。 ただし、Kent Beck氏自身も 「測定自体は極めて価値がある」 と強調しています。 "I've been measuring my own software development process as long as I've been developing and I find it extremely valuable to turn what I'm doing into numbers that I can analyze and interpret." 「私は開発している限り、自分のソフトウェア開発プロセスを測定してきました。私がしていることを分析し解釈できる数字に変えることは非常に価値があると思います」 つまり、問題は測定そのものではなく、 何を測るか と どう使うか なのです。 アジャイル実践者の「前向きさ」に潜む3つの勘違い Kent Beck氏の警告を踏まえると、アジャイル実践者の「前向きさ」には次のような勘違いが潜んでいる可能性があります。 1. ベロシティ=生産性という誤解 ベロシティが上がると「生産性が向上した」と感じてしまいがちです。しかし、ベロシティはあくまでもチーム内での前イテレーションとの相対比較でしかなく、チーム間の比較や組織全体の生産性を示す指標ではありません。さらに、ストーリーポイントのインフレーション(見積もりの甘さ)や、価値の低いタスクの量産でも数字は上がります。Kent Beck氏が指摘するように、これはまさに「測定が目標になった」状態です。 2. プロセスの遵守をアウトカムと混同 アジャイルの「儀式」を正しく実行していることと、実際に価値を生み出していることは別物です。毎日スタンドアップをやり、レトロスペクティブを欠かさず、バーンダウンチャートが美しい右肩下がりを描いていても、それは「プロセスを守っている」だけかもしれません。顧客が本当に必要としている機能を届けているか、ビジネスアウトカムにつながっているか、技術的負債を積み上げていないか──これらの本質的な問いを忘れ、「アジャイルをちゃんとやっている」ことに満足してしまうリスクがあります。 3. 複数メトリクスの罠 ── なぜ全体最適が失われるのか 日本の組織では、各チームが自分たちの領域で完璧を追求する傾向があります。開発チームはベロシティを上げ、QAチームはバグ検出率を誇り、運用チームは安定性を守る。それぞれが「うちのチームは生産性が高い」と思っています。しかし、これはまさにKent Beck氏が警告する「バランスの取れたメトリクス」の問題です。各チームが異なるメトリクスを最適化することで、システム全体に複雑な歪みが生じます。開発が早くても、QAで長時間滞留し、運用への引き渡しで調整に時間がかかり、結局顧客に価値が届くまでのリードタイムは改善されない。 Kent Beck氏が指摘するように、「システムを歪めるメトリクスが多いほど、理解しにくく影響を与えにくくなる」のです。各チームの「優秀さ」が、かえって全体のボトルネックを見えなくし、誰も全体像を把握できない状況を生み出しています。 つまり、アジャイル実践者が「前向き」なのは、 自分たちの測定方法や改善活動が正しいと信じているから かもしれないのです。 何を測るべきか ── Kent Beck氏が示す価値創造の道筋 本調査から明らかになったのは、どの開発手法でも「何を測るべきか」の共通認識が欠けていることです。この根本的な問題について、Kent Beck氏は価値創造の道筋を次のように説明しています。 Kent Beck 氏(開発生産性Conference 2025にて) "We start out with effort... That's effort. We can measure it in time... Now we have some output... But we still haven't created value until the customer does something, behaves in some new kind of way... And finally the value that we created... comes back to the company in terms of increase in revenue, increase in customer satisfaction." (*下図を示しながら)「まず努力(Effort)から始まります。これを時間で測定できます。次に何らかの成果物(Output)が生まれます。しかし、顧客が新しい行動を取るアウトカム(Outcome)が生まれるまでは、まだ価値は生まれていません。そして最終的に、創出された価値が収益増加や顧客満足度向上という影響(Impact)として会社に還元されます。」 Kent Beck 氏のプレゼン資料から引用 (p.8) そして、この価値の道筋における測定の難しさと歪みの関係について、次のように述べています。 "The further over here we are towards effort the easier things are to measure. But also the more likely that measurement is to distort the system... The further over here you are... the harder it is to attribute value to any one person or one team but the less prone that measurement is to distorting the system." 「投入した努力(作業時間など)に近い指標ほど測定は容易ですが、同時にその測定がシステムを歪めるリスクも高まります。一方、創出された価値(ビジネスアウトカム)に近い指標ほど、そのアウトカムを特定の個人やチームに帰属させることは困難になりますが、測定によるシステムの歪みは生じにくくなります」 測定を「コントロール」ではなく「認識」のツールとして ── Kent Beck氏の4つの提言 では、どうすればこの問題から抜け出せるのでしょうか。Kent Beck氏は講演の結論で、4つのアプローチを提示しています。 Kent Beck 氏のプレゼン資料から引用 (p.11) 1. Observe later(後で観察する) 価値連鎖の早い段階(努力やコード量)ではなく、後の段階(アウトカムや影響)を観察することを推奨しています。「開発者1人あたりの利益を見てください」と彼は例を挙げています。 2. Encourage awareness(認識を促す) 「システムを高速化する最良のテクニックの1つは、システムがどれだけ速いかをグラフ化することです」と述べ、可視化によって自然な改善を促すことを提案しています。 3. Avoid pressure(プレッシャーを避ける) 「リーダーとしてプレッシャーをかけないことは最も難しいことです。しかし、プレッシャーをかけると、システムの歪みが生じます」と警告しています。 4. Instill purpose(目的を植え付ける) 「今のような頻度で本番環境のインシデントが発生しない世界は素晴らしいと思いませんか?」という形で、プレッシャーではなく共通の目標として提示することの重要性を語っています。 この観点から見ると、 DORA指標 (デプロイ頻度、リードタイム、MTTR、変更失敗率)も実は「Output」レベルの測定です。これらは「コード行数」のような純粋な努力(Effort)レベルよりは価値に近いものの、依然として「どれだけ速く・頻繁にリリースしたか」を測っているに過ぎません。顧客の行動変化(Outcome)やビジネスへの影響(Impact)を直接測定しているわけではないのです。 それでも、DORA指標には意味があります。なぜなら、これらの指標を プレッシャーツールとしてではなく、チームの健全性を把握し、改善の機会を見つけるための認識ツール として使うことができるからです。 重要なのは、 どんな指標であっても、それを目標化してプレッシャーをかけるのではなく、現状を理解し、チーム自身が改善方法を考えるためのツールとして活用すること です。 アジャイル実践者への提案 ベロシティだけでなく、顧客価値の提供速度を測る チームの指標とビジネス指標を接続する DORA指標やDevExの考え方を取り入れる ウォーターフォール開発者への提案 現在の指標(バグ数、納期)を維持しつつ、先行指標を追加 小さな改善サイクルを導入して効果を検証 リスクを最小化しながら段階的に変化を進める 次回予告 第3回は「 開発生産性を阻む『日本の3大悪習』── 要件定義、会議、コミュニケーションの罠 」をお届けします。 日本の開発現場が抱える構造的な課題と、その改善への道筋を探ります。 第1回、日本の開発現場の「リアル」を数字で見る ── 798名の声から浮かび上がる衝撃の実態 調査全体について 第2回、開発生産性への意外な好印象 ── アジャイル実践者59.6%が前向きな理由 開発手法による意識の違いの本質 第3回、開発生産性を阻む「組織の3大課題」 ── 要件定義、会議、コミュニケーションの問題 取り組みが失敗する本当の理由 第4回、AI時代の技術格差 ── Visual SourceSafe 15.8%が示す変革への壁 なぜ従来型ツールから移行できないのか 第5回、なぜDevExは日本で知られていないのか ── 認知度4.9%が語る未開拓領域 日本の開発者が本当に求めているもの また、ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 突然ですが皆さんは、イベントに参加することはありますか? コロナ禍を経てオンラインイベントも増えましたし、最近はオフラインイベントも少しずつ戻ってきてるように感じています。 そこで今回は エンジニアの人生を変えたイベント と題して、弊社エンジニア達が過去に参加したイベントの中で、特に印象に残っているイベントを紹介していきます。 それでは見ていきましょう! Hiyoko Developer Meeting TDD Boot Camp 2020 Online #1 RubyKaigi 2022 まとめ Hiyoko Developer Meeting Tech Lead をやらせてもらってる戸田です。 僕が今まで参加して一番印象に残っているのは、Hiyoko Developer Meetingと呼ばれるイベントです。 hiyoko-dev.connpass.com 当時の自分は20代中盤くらいで、会社には先輩しかいない状況でした。同年代のエンジニアとの比較が出来ない状況が長く続き、自分自身のエンジニアとしての立ち位置、そして市場価値を測ることが難しかったのを覚えています。 そんな中、このイベントが開催されました。同年代のエンジニアと交流できるとのことで、すぐに参加申請を押したのを覚えています。 実際に参加して、同年代のエンジニアのみんなと交流して、自分自身の立ち位置と市場価値の現在位置を大まかに把握できましたし、自分のキャリアの方向性の答え合わせが出来ました。 その中でも強烈に覚えているのは、「エンジニアの友人」が出来たことです。 社外の横の繋がりは、転職によって会社が変わっても消えることはありません。当時は違う会社で働いていましたが、今ではファインディで一緒に働いている友人もいます。 彼らと初めて出会うきっかけをくれたこのイベントを、僕は一生忘れないでしょう。 ファインディでも先日、若手エンジニア限定のイベントを開催しました。 findy.connpass.com このイベントに参加してくださった若手エンジニアのみなさんがXのアカウント交換をしている姿を見て、10年前の自分と友人の姿を重ねました。 当時の僕と同じ境遇の若手エンジニアの読者のみなさんも、是非イベントに参加してみてください。 そしてまずは顔見知りを作るところから始めてみてください。その出会いが友人となり、気づいたら同僚となり、戦友と呼べるような関係になるかもしれません。そのきっかけと出会いを作るのに必要なものは、あなたが持つであろう小さな勇気だけです。 TDD Boot Camp 2020 Online #1 Findy Team+を開発しているEND( @aiandrox )です。 私が一番印象に残っているイベントは、「TDD Boot Camp 2020 Online #1」というイベントです。コロナ禍で配信のみのイベントがほとんどの中で、初めて参加した「見るだけではないイベント」でした。 tddbc.connpass.com 当時、私はプログラミングスクールを卒業して、エンジニアとして就職活動をしていた頃です。テストについては興味があるが、チーム開発の経験もなく「良いテスト」がどういったものなのか肌で理解できていませんでした。そんな中で、TDDを実践できるイベントがあるということを知り、勇気を出して参加しました。 実際に参加してみると、想像していた以上に濃い体験が待っていました。 t_wadaさんによる基調講演のライブコーディングでは、FizzBuzzのテストと実装をここまで細かく繰り返すのかと衝撃を受けました。仕様のTODOリストを作成する、まずは落ちるテストから書く、利用者の視点でテストを書く、など、すべてが新しい発見でした。 初めてのモブプロでは、わからないことだらけではあったものの、現役エンジニアの方と話しながらテスト駆動開発を進めることができました。同じコードを見ながらちゃんと会話ができたのと、どう進めていくか相談をして自分の意見が取り入れられた経験が自信にもなりました。 このイベントをきっかけに、私はテストの目的や良さについて自分の言葉で話せるようになりました。それは今も開発スタイルの根源にあります。 振り返ると、あのとき「まだエンジニアでもない自分には無理かもしれない」とひよってしまうのではなく、思い切って参加して本当によかったです。 RubyKaigi 2022 Findy IDを開発しているsontixyou( @sontixyou )です。 私にとっては「RubyKaigi 2022」への参加でした。 rubykaigi.org 当時、私はベンチャー企業でエンジニアとして働いており、Ruby歴は2年でした。 RubyKaigi 2022への参加は、私にとって初めてのテックカンファレンス体験。行きの道中は、参加が楽しみであるのとワクワク感でいっぱいでした。 参加の目的はつぎのものです。 セッションを通じて、Rubyが好きな理由を言語化したい Rubyistのつながりをつくりたい RubyKaigi 2022の3日間、毎セクション何かしらの発表を聞きました。 分からない用語もたくさんありましたし、当時の自分の実力でもなんとか分かる内容もありました。 カンファレンス終了後、私はRubyが好きでプライベートでも仕事でもRubyを使い続けたいと思いました。 しかし、同時に課題も見つかりました。「Rubyの具体的にどんな点が好きなのか」を自分の言葉で説明できなかったのです。Ruby良いよなという感情はあるのに、それを論理的に語る知識と経験が不足していました。 この気づきから、自分のスキルアップのための取り組み方を大きく変えました。 Rubyの動的型付けの柔軟性を客観視できるように静的型付け言語のRustに挑戦 gemの開発を通じて、Rubyの深い知識を身につける 地域のRubyコミュニティに定期的に参加してRubyistと交流することで、自分の考えを深める これらを通じて、ただ「Rubyが好き」から「Rubyのこの部分がこういう理由で素晴らしい」と語れるようになりました。技術的な実力向上はもちろん、自分のキャリアの方向性も明確になったと感じています。 技術カンファレンスは、新しい知識を得る場としてだけでなく、自分の現在地を知り、自分の伸びしろを見つけるチャンスだと思います。 「分からないことがあっても大丈夫」という気持ちで、ぜひ積極的に参加してみてください。きっと、予想もしない成長のきっかけや出会いが見つかるはずです。 最後に、RubyKaigi 2022でスポンサーしていたファインディで現在働いているのはなにかの縁かもしれません。 まとめ いかがでしたでしょうか? 1回のイベントに参加するだけで、学びだけではなく、エンジニアとしてのキャリアや人生に対して大きなヒントを得ることが出来るかもしれません。ぜひ皆さんの思い出のイベントも教えてください。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。Findy Tech Blog編集長の高橋( @Taka-bow )です。 皆さんは「開発生産性」という言葉を聞いて、何を感じますか? これまで、エンジニアの「開発生産性」という概念に対する理解度や、その活用状況を体系的に調査した事例はほとんどありません。 そこで2025年、ファインディは ソフトウェア開発における「開発生産性」に関する実態調査 を実施し、日本のIT従事者798名にこのテーマを真正面から問いかけました。 【調査概要】 調査対象: ソフトウェア開発(組み込み開発を含む)に直接関わるエンジニア、プロダクトマネージャー、プロジェクトマネージャー、エンジニアリングマネージャー、開発責任者など 調査方法: インターネット調査 調査期間: 2025年4月2日(水)~2025年5月21日(水) 調査主体: ファインディ株式会社 実査委託先: GMOリサーチ&AI株式会社 有効回答数: 798名(95%信頼区間±3.5%) 統計的検定力: 80%以上(中程度の効果量d=0.5を検出) 調査内容: 開発生産性に対する認識 開発生産性に関する指標の活用状況 開発生産性に関する取り組み 開発環境・プロセス評価 組織文化と生産性 その結果は、私たちの想定を大きく覆すものでした。これまで「日本は海外に比べてアジャイルやDevOpsの浸透が遅れている」といった一面的な見方がされがちでした。 しかし、実際に見えてきたのはそれだけではありません。日本の開発現場には、品質へのこだわりやチームワークといった確かな強みがある一方で、それを十分に活かしきれない構造的な課題が浮き彫りになったのです。 まずは今回の調査から見えてきた全体像をお伝えし、その後はシリーズでテーマごとに深掘りしていきたいと思います。 第1回、日本の開発現場の「リアル」を数字で見る ── 798名の声から浮かび上がる衝撃の実態 調査全体について 第2回、開発生産性への意外な好印象 ── アジャイル実践者59.6%が前向きな理由 開発手法による意識の違いの本質 第3回、開発生産性を阻む「組織の3大課題」 ── 要件定義、会議、コミュニケーションの問題 取り組みが失敗する本当の理由 第4回、AI時代の技術格差 ── Visual SourceSafe 15.8%が示す変革への壁 なぜ従来型ツールから移行できないのか 第5回、なぜDevExは日本で知られていないのか ── 認知度4.9%が語る未開拓領域 日本の開発者が本当に求めているもの それでは、第2回以降で深掘りしていく各テーマに入る前に、まずは調査全体を象徴するいくつかの結果をご紹介します。 開発生産性への認識は前向き、でも実践にはギャップが 組織運営の課題が技術的課題を上回る現実 従来型ツールがAI時代の足かせに Developer Experience(DevEx)の低い認知と見えてきた課題 測定指標の混乱 ── 業界全体で「何を測るべきか」が不明確 なぜ変われないのか ── ケイパビリティと体験のギャップ 数字だけでは動けない現場 必要なのは「体験から学ぶ」ステップ 日本の強みを活かしながら 開発生産性への認識は前向き、でも実践にはギャップが 興味深い発見のひとつは、IT従事者の開発生産性に対する認識が予想以上に前向きだったことです。 「開発生産性」という言葉に対してネガティブな印象を持つ人は わずか7.6% 。多くのエンジニアが、生産性向上に対して前向きな姿勢を示していました。 特に注目すべきは、開発手法による意識の差です。 アジャイル実践者の59.6% がポジティブな印象 ウォーターフォール開発者は39.5% に留まる 私は「アジャイル実践者」のほうが、よりネガティブに捉えているのではと予想していたので、これは意外な結果でした。 また、開発生産性向上への取り組みは「実施36.6%」「未実施37.8%」と拮抗している一方で、25.6%が自組織の状況を把握していないという結果が浮かび上がりました。これは、生産性への関心は高いにもかかわらず、取り組みが十分に浸透しておらず、組織内の情報共有やコミュニケーションに課題が残っていることを示しています。 組織運営の課題が技術的課題を上回る現実 開発生産性を阻害する要因を尋ねたところ、技術的な問題よりも組織運営の課題が上位を占めました。 最大の障壁は 「不明確な要件」(53.5%) です。半数以上のIT従事者が、プロジェクトの上流工程に大きな問題を感じています。続いて以下の通りです。 会議が多い 38.7% コミュニケーションの問題 33.6% これらはいずれも組織運営に深く関わる問題であり、しかも長年にわたり繰り返し指摘されてきた課題です。 その根本原因は「やり方を変えないこと」にあるのではないでしょうか。どれほど最新のツールやフレームワークを導入しても、こうした本質的な課題に向き合わない限り、生産性の大幅な向上は望めません。 日本の開発現場は、技術力そのものは十分に備えているにもかかわらず、それを最大限に活かせる土壌が整っていない──そんな実態を映し出しているのかもしれません。 従来型ツールがAI時代の足かせに ソースコード管理ツールの利用状況を見ると、技術格差の深刻さが明らかになりました。 GitHub 30.5% Visual SourceSafe 15.8% Subversion 13.7% GitHubがトップあることは驚きませんでしたが、2012年にサポートが終了したVisual SourceSafeが2位という事実は衝撃的でした。さらにSubversionも含めると、約3割の組織が従来型のバージョン管理システムを使用していました。 これは単なる「古いツールを使っている」という話では済みません。 GitHub CopilotやAmazon CodeWhispererなど、最新のAI開発支援ツールはGitベースのワークフローを前提としています。従来型ツールに縛られている組織は、AI活用による生産性向上の波に乗り遅れるリスクが高いのです。 つまり、現在の技術格差が、将来的にはさらに大きな生産性格差へと発展する可能性があるということです。 Developer Experience(DevEx)の低い認知と見えてきた課題 日本において「Developer Experience(DevEx)」という概念は、まだ広く浸透していません。今回の調査でも、DevExという言葉を知っていると答えたエンジニアはわずか 4.9% にとどまりました。 同じ調査では、DevExの要素であることを伏せたうえで、基盤的な要素の満足度も尋ねました。その結果、以下のようにきわめて低い数値が明らかになっています。 CI/CDパイプライン 満足度14.2% ドキュメント管理システム 満足度17.5% 開発環境整備 満足度24.7% これらの結果は、日本の開発現場におけるインフラ整備の遅れを如実に物語っています。特にCI/CDパイプラインの満足度が14.2%にとどまっているのは深刻です。継続的インテグレーション/デリバリーは現代のソフトウェア開発の基本であるにもかかわらず、8割を超えるエンジニアが不満を抱えたまま日々の開発を続けているのです。 こうした環境の不備は、エンジニアのモチベーション低下を招くだけでなく、生産性そのものにも直結します。ビルド待ち時間、手動デプロイによるミス、ドキュメント不足による知識共有の停滞 ── これらの問題が開発現場を日常的に妨げているのです。 測定指標の混乱 ── 業界全体で「何を測るべきか」が不明確 最後に、最も根本的な問題があります。業界全体で「何を測るべきか」という共通認識が欠けているのです。 実際、組織によって重視する指標は大きく異なります。ある企業はコード行数を追い、別の企業はバグ数を数え、さらに別の企業は残業時間を管理しています。しかし、これらの指標が本当に開発生産性を正しく示しているのか、確信を持てている人はほとんどいません。 世界的に注目されているDORA指標(デプロイ頻度、リードタイム、平均復旧時間、変更失敗率)の認知度がわずか 4.3% にとどまっているという事実も、この混乱を裏付けています。 測定基準が曖昧なまま「生産性を上げろ」と求められても、現場は困惑するばかりです。まるでゴールの見えないマラソンを走らされているようなものです。 なぜ変われないのか ── ケイパビリティと体験のギャップ 調査では、44.3%が「開発生産性を高めたい」と前向きに答えました。 しかし、実際に自社で具体的な取り組みをしていると答えたのは36.6%にとどまります。 ここで重要なのは、この36.6%が必ずしも「正しい指標に基づいて取り組んでいる」とは限らないという点です。測定基準が不明確なままでは、努力が空回りしてしまう危険があるのです。 その背景には、“知識として知っていること”と“実際に体験していること”の間に横たわる、大きなギャップがあります。 数字だけでは動けない現場 たとえば、DORA指標の認知度はわずか4.3%。「デプロイ頻度を上げよう」「リードタイムを短縮しよう」といった施策を伝えても、それがもたらす真の価値──素早いフィードバック、リスク低減、チームの自信向上──を実感したことがなければ、単なる数字遊びにしか見えません。 同じことはCI/CDの整備にも言えます。満足度14.2%という結果は、自動化がまだ十分に根付いていないことを示しています。ビルドやテストが自動化されていれば「コードを書いたらすぐに安心できる」「金曜の夕方でもデプロイできる」──そんな開発体験が得られます。しかし、体験がなければその価値を想像することすら難しいのです。 必要なのは「体験から学ぶ」ステップ 本当に必要なのは、生産性の高い組織が備えている ケイパビリティ(組織能力) を理解し、実際に体験することです。 疎結合なアーキテクチャ :チームが独立して素早く動ける 自動テスト :安心してリファクタリングできる モダンなバージョン管理 :PR・レビュー・CI/CDが可能になる ただし、これらのケイパビリティは一足飛びには身につきません。段階を踏んで育てていくしかないのです。 Visual SourceSafeを利用している組織は15.8%、Subversionを利用している組織は13.7%に上り、両者を合わせると全体の約3割を占めます。つまり、GitHub(30.5%)とほぼ同じ規模で、いまだにレガシー寄りの環境が現場に残っているのです。こうした環境では、PRやコードレビュー、CI/CDパイプラインといったモダンな仕組みを前提とした開発体験を実現するのは難しく、「デプロイを自動化しましょう」と言われても、その基盤自体が存在しません。 だからこそ、小さな一歩から始める必要があります。新しいツールの価値を「頭で理解する」のではなく、まずは「体験する」こと。その実感が、次のステップに進む原動力となります。こうした積み重ねが、最終的に組織全体の変革を実現していくのです。 日本の強みを活かしながら 日本の開発文化が培ってきた 品質へのこだわり や チームワーク は、決して手放す必要はありません。むしろそれを土台にしながら、新しいケイパビリティを段階的に身につけていく。そのプロセスこそが現実的な改善への道筋です。 あなたの組織は今、どの段階にいますか? そして明日から、何を始めますか? この問いへの答えを探るために、次回以降は7回にわたり調査結果をテーマ別に深掘りしていきます。 第2回は「開発生産性への意外な好印象 ── アジャイル実践者59.6%が前向きな理由」を取り上げます。 また、ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやClaude Codeなど生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中で先日、Findy AI Meetupの記念すべき第1回を福岡で開催しましたので、今回はそのイベントの様子や内容を紹介します。 findy-inc.connpass.com 福岡でのイベント開催は実に2年ぶりとなっており、我々も参加者の皆さんにお会い出来ることを楽しみにしていました。 ありがたいことにキャンセル待ちが出るほどに参加申し込みをしていただきました。当日参加くださったみなさま、ありがとうございました! Findy AI Meetupとは? 登壇内容 Nx × AI によるモノレポ活用 ~ コードジェネレーター編 Findy Freelance利用シーン別AI活用例 ファインディ株式会社における生成AI活用までの軌跡 懇親会 まとめ Findy AI Meetupとは? ファインディ株式会社のエンジニアが主催する技術系のオフラインイベントです。 ファインディ株式会社では、生成AIやAIエージェントの活用を通じて開発生産性の向上を目指す取り組みを行っています。このイベントでは、ファインディのエンジニアが社内での実践事例を紹介するとともに、エンジニア同士がつながり、知見の共有や交流を目的としています。 今回のMeetupは初めての開催となっており、登壇者は全員弊社のエンジニアとなっています。 登壇内容 Nx × AI によるモノレポ活用 ~ コードジェネレーター編 まず弊社のフロントエンド テックリードの新福が登壇しました。 弊社のフロントエンドの多くにはNxが採用されています。今回はNxを採用してきたことが、生成AIの時代にマッチしていたというお話をしました。 tech.findy.co.jp これまで弊社では、NxのGeneratorを用いて開発効率の向上に取り組んできました。NxのGeneratorは強力な機能を持つ反面、覚えることも多く、初心者がとっつきにくいというのが課題でした。 tech.findy.co.jp 最近のNxは生成AIとの連携が強化されており、中でもNx MCPの登場によって、モノレポ内の情報を生成AIのコンテキストとして利用できるようになりました。 Nx MCPの素晴らしい点は、モノレポ内のプロジェクトやNxのGeneratorを自然言語で操作できることにあります。これにより、複雑なコードを書かなくても柔軟で対話的なコード生成の業務フローが実現可能になりました。 例として今回は、CopilotやClaude CodeのスラッシュコマンドからNx MCP + Nx Generatorを起動させる方法を紹介しています。 生成AI時代の業務標準化は、もうすぐそこに来ているのかもしれません。 今回はNxのGeneratorに焦点を当ててお話しましたが、Nx公式のCIサービスである「Nx Cloud」にもAI機能が続々と追加されているので、いつかご紹介できればと思います。 Findy Freelance利用シーン別AI活用例 次にフロントエンドエンジニアの主計が、Findy Freelanceチームのコーディング以外でのAI活用事例をいくつか紹介しました。 1つ目は、不具合調査時の Ask Devin の活用です。 不具合報告があった際に、不具合内容をAsk Devinに調査を依頼しています。 対象となるリポジトリを複数選択できるため、原因箇所の特定や切り分けが素早くできるようになっています。 専門領域に関わらず一次調査ができるのもありがたいです。 2つ目は、dependabotのAIレビューです。 最初はDevinのPlaybookを利用して週1でまとめてレビューを依頼していましたが、 Claude Code Base Actionを利用して随時自動で行うように改善しました。 精度も上がり、日々の作業の負担が軽減されています。 3つ目は、AI によるリファインメントの実施です。 PdMとエンジニアで行っているリファインメントの文字起こしデータをNotebookLMに追加して、 リファインメントの観点を洗い出しプロンプト化しています。 ラベル付与をトリガーとすることで、PdMメンバーが任意のタイミングでAIリファインメントを実施できるようになり、リファインメントの負担を軽減できています。 アウトプットに関しては文量が多かったり、肯定的なフィードバックになりがちだったりと課題があるので、引き続きプロンプトを調整しています。 チームでAI活用を進めるため、10分勉強会(5分LTを正社員メンバーで持ち回り)で実施しています。 継続することを優先し、スキップ可や記事紹介可などハードルを下げて取り組んでいます。詳細はこちらの記事をご覧ください。 findy-code.io 普段の業務にAIを活用するために、AIのキャッチアップと同時に、どの業務にどうAIを活用するか日々チーム全体で考えることが大事だと考えています。 引き続きAIを積極活用していくので、良い事例があれば紹介していきたいと思います。 ファインディ株式会社における生成AI活用までの軌跡 最後に、テックリードの戸田が、「ファインディ株式会社における生成AI活用までの軌跡」と題しまして、弊社が生成AIで結果を出せるようになるまでの軌跡を紹介しました。 まず弊社の開発組織の開発文化を支えている考え方やテクニックをいくつか紹介しました。以前にこのテックブログでも紹介した内容もあります。 特にタスク分解とPull requestの粒度は重要です。 tech.findy.co.jp tech.findy.co.jp また、統一されたコーディング規約や設計、ドキュメントを整備することも文化として根付いています。特にドキュメント整備は重要で、弊社ではJOIN初日にPull requestを出せるようにしています。 このように、弊社の開発文化を支えているテクニックはコードを書く前の事前準備を重要としており、また、環境や自動化、スピードに拘りを持っています。 これは小さなことをコツコツと積み重ねることでしか実現できませんが、それをしっかりやり切ってきた歴史があり、その積み重ねこそが開発組織の文化となっています。着実に積み重ねたものは強いのです。 次に、弊社が生成AIを活用するために取り組んだ内容を紹介しました。 既存コードの最適化や不要なコードの削除、テストコードの整備やドキュメンテーションなど、生成AIのガードレールとなる要素の整備に関して紹介しました。 また、生成AIに命令を投げる際は、可能な限りスコープを限定的にして、具体的な内容を段階的に渡すのが良いとされています。そのため、弊社で取り組んでいたタスク分解のスキルが重要となるシーンが増えました。 ここまで読んだ読者なら気付いた方もいるかもしれません。そうです。弊社の開発組織の開発文化は、生成AIが流行するずっと前から生成AIフレンドリーな文化となっていたのです。 今までの開発組織に生成AIを足した。ということではなく、今までやってきたことの延長線上に生成AIが乗っかってきた。という表現が近いかもしれません。そのため、生成AIを導入したことで一時的に生産性が落ちた。といった光景は、弊社ではほとんど見られなかったのです。 今までの積み重ねが、結果的に生成AIとの協業を可能としていました。もちろんガードレール整備がまだ行き届いていない箇所もあります。しかしながら、そこの整備に対して投資をするという意思決定が当たり前となっている開発文化でもあります。 このあと、生成AI時代の弊社の開発現場の様子をいくつか紹介させてもらいましたが、これはまた別の記事でも紹介できればと思います。 懇親会 登壇発表後は参加者の皆さんと懇親会を開催しました。 懇親会では「パックマンルール」をお願いしました。懇親会で誰かと話すときは新しい人が会話に入れるように、一人分のスペースを空けて話しましょう。というルールです。 生成AI活用における悩みや知見を意見交換して、楽しんでいただけたようです。 まとめ いかがでしたでしょうか? 当日、イベントに足を運んでくださった参加者のみなさん、本当にありがとうございました。頂いたアンケート結果を、次回開催の参考とさせていただきます。 次回開催は9月前後を予定しております。残念ながら今回のイベントに参加出来なかったみなさんも、次回イベント開催時には是非ご参加ください! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやClaude Codeなど生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中でこのたび、Findy AI Meetupの記念すべき第1回を、2025年8月4日(月)に福岡にて開催することとなりました! findy-inc.connpass.com 今回は、このイベントの紹介をしたいと思います。それでは見ていきましょう! Findy AI Meetupとは? 登壇予定 Nx × AI によるモノレポ活用 ~ コードジェネレーター編 Findy Freelance利用シーン別AI活用例 ファインディ株式会社における生成AI活用までの軌跡 まとめ Findy AI Meetupとは? ファインディ株式会社のエンジニアが主催する技術系のオフラインイベントです。 ファインディ株式会社では、生成AIやAIエージェントの活用を通じて開発生産性の向上を目指す取り組みを行っています。このイベントでは、ファインディのエンジニアが社内での実践事例を紹介するとともに、エンジニア同士がつながり、知見の共有や交流を目的としています。 福岡でのイベント開催は実に2年振りとなっており、我々も参加者の皆さんにお会い出来ることを楽しみにしています。 登壇予定 Nx × AI によるモノレポ活用 ~ コードジェネレーター編 弊社では、ほぼ全てのフロントエンドでNxによるモノレポ管理が採用されています。 tech.findy.co.jp tech.findy.co.jp 最近のNxは生成AIとの連携が強化されており、中でもNx MCPはモノレポ内の情報を生成AIのコンテキストとして利用できるなど非常に便利です。 今回は、NxのGeneratorをより柔軟かつ対話的に利用できるよう、Nx MCPや プロンプトファイル を組み合わせ、生成AI時代の業務の標準化を目指したお話を紹介します。 Findy Freelance利用シーン別AI活用例 Findy Freelanceの開発ではコーディング時の生成AI活用はもちろんのこと、 コーディング以外の開発関連業務のなかでも生成AIを活用し業務効率化を図っています。 特長の異なる生成AIをどのように使い分けているか、利用シーン別にご紹介します。 ファインディ株式会社における生成AI活用までの軌跡 「ファインディ株式会社における生成AI活用までの軌跡」と題しまして、弊社が生成AIで結果を出せるようになるまでの軌跡を紹介します。 まず弊社の開発組織の開発文化を支えている考え方やテクニックをいくつか紹介します。 tech.findy.co.jp tech.findy.co.jp その開発文化の上で、どのように生成AI活用を推し進めたのか、現在はどのような開発現場になっているのかを紹介します。 まとめ いかがでしたでしょうか? 会場へのアクセスは天神駅から徒歩3分となっています。また、TVCM公開記念ノベルティや、イベント後半には懇親タイムもご用意しています。 申込みの先着順となっており、ありがたいことに参加枠も残りわずかとなっております。生成AIの活用事例に興味のある方は奮ってご参加ください! イベント参加申し込みはこちらから ↓ findy-inc.connpass.com みなさんにお会いできることを楽しみにしています!
こんにちは。ファインディでソフトウェアエンジニアをしている千田( @_c0909 )です。 2025年3月末頃からファインディに導入されたClaude Codeは、私たちの開発フローに大きな変化をもたらしました。特に私が注目し活用を進めてきたのが、カスタムスラッシュコマンドの機能です。 Claude Codeを初めて触った時は、 CLAUDE.md に長文で汎用的な指示を書いてコードを生成していました。しかし、全てのプロンプトを網羅するには限界があり、より効率的な活用方法を模索していました。そんな中で出会ったのが、このカスタムスラッシュコマンド機能です。 この機能は、日々のGit操作やコーディング作業の自動化を後押ししてくれます。本記事では、私が実際にどのようなカスタムスラッシュコマンドを作成し、どのように開発業務に役立てているのかを具体的な事例と共にご紹介します。 Claude Codeのカスタムスラッシュコマンドとは 実際に作成したカスタムスラッシュコマンド ブランチを作成 commitメッセージを作成 Pull Requestを作成 ブランチ, commit, PRの全てを一度に作成 頻出するコードを自動生成 まとめ Claude Codeのカスタムスラッシュコマンドとは Claude Codeでは、 .claude/commands/ ディレクトリにMarkdownファイルを配置することで、個人またはチーム独自のコマンドを作成できます。例えば /create-branch のようなコマンドを実行すると、事前に定義したルールに従ってClaude Codeが作業を進めてくれます。 docs.anthropic.com 実際に作成したカスタムスラッシュコマンド まずはGitのコマンド実行です。Gitの操作は同じ内容を CLAUDE.md にも書いていて、コードを書いてPR作成までの流れを一貫して依頼することもあります。ただ、コーディングとGit操作の工程を分けて、その間に人がチェックした方が手戻りが少ないため、敢えてカスタムスラッシュコマンドとして用意しています。 ブランチ命名やメッセージの作成などは、次のように自動化しています。 ブランチを作成 .claude/commands/git-create-branch.md ## branchを作成 - ブランチ名は [ Conventional Branch ]( https://conventional-branch.github.io/ ) に従う - feature/[FeatureName]-[実装した機能名] 例: feature/admin-user-role-edit-invite-form 毎回悩みがちなブランチ名の命名。Conventional Branchに従っていても、命名するタイミングで手が止まってしまうこともありますよね。このコマンドのおかげでブランチ名を考える手間がなくなり、開発がスムーズになりました。 次の画像は、コマンドを実行した時の結果です。 commitメッセージを作成 .claude/commands/create-commit.md # commitメッセージを作成 ## 実行手順 1. Read @~/.claude/commands/guideline-read-code.md 2. 違反があれば作業を中断 4. ` git status ` でファイルを確認 5. [ Conventional Commits ]( https://www.conventionalcommits.org/en/v1.0.0/ )に従ってコミットを実行 ## 形式の指定 - type(scope): subject の形式に従う - タイトルは50文字以内、本文は72文字程度で改行 - 動詞は原形を使用(add, fix, updateなど) - scope は原則記述するが、適切なものがない場合は省略可 - コミットメッセージは小文字で始める ## 実装とテストが含まれる場合の優先ルール - 実装とテストコードが含まれている場合、typeはtestよりもfeat/fixを優先する このコマンドの特徴は、コミット前に必ずコーディングガイドラインをチェックすることです。手順1の Read @~/.claude/commands/guideline-read-code.md の部分で読み込ませてます。 例えば、Reactのテストコードでhooksの関数を作成した場合、そのテストとしてコールバック関数がパラメータ付きで実行されることなどを確認しますが、実行回数やエラー時のコールバック関数が実行されていないことを必ずセットで検証します。このような内容をガイドラインとして盛り込んでいます。 機械的にできるレビューは、Commit前にClaude Codeが事前チェックすることで、レビューの負荷を下げます。 なお、弊社のテストコードの考え方については Findyの爆速開発を支える「システムを守るテストコード」の実例3選 - Findy Tech Blog で紹介しています。 Pull Requestを作成 .claude/commands/git-create-pr.md # PRを作成 - Read @.github/PULL _ REQUEST _ TEMPLATE.md に従うこと - Draftで作成すること - push時は ` git push -u origin <branch_name> ` のように ` --set-upstream ` を指定すること - コマンドの例: ` gh pr create --draft --title "title" --body "body" ` PRのテンプレートに詳細な情報が記載されているため、ファイルを参照するだけのシンプルな構成です。エディターでもセルフレビューをしますが、GitHubのdiffの方が見やすいため、PRは必ずDraftの状態で作成してセルフレビューを実施するフローを標準化しています。 また、 PULL_REQUEST_TEMPLATE.md には「動作確認」の項目を用意しています。これはブラウザ上で目視で動作確認する目的で、Claude Codeに内容を列挙して貰っています。 一部抜粋すると次のイメージです。 ## 動作確認 - [ ] レスポンシブ対応が正しく動作すること(スマートフォン、タブレット、デスクトップ) - [ ] Xのシェアボタンが正しく表示されること - [ ] 背景色がブレークポイントに応じて適切に変更されること この対応により、特にフロントエンドの実装時はレビュー前にブラウザで動作確認をする時のチェック観点として、PRのレビュアーにも共有しています。 ブランチ, commit, PRの全てを一度に作成 .claude/commands/git-create-branch-commit-pr.md # branch & commit & pr を作成 ## 実行手順 1. Read @~/.claude/commands/create-branch.md を実行 2. Read @~/.claude/commands/create-commit.md を実行 3. Read @~/.claude/commands/create-pr.md を実行 ブランチ作成からPR作成までの一連の作業は、開発サイクルの中で何度も繰り返されます。この定型的なプロセスを自動化するコマンドを作成しています。 開発プロセスの中で事前にタスクを分解し、その粒度に沿ってPRを作成しています。そのため、PRの粒度が小さく、1つのPRに対してコミットは1件が多いです。これにより、ブランチ作成からPR作成までの自動化が容易に実現できています。 タスク分解の詳細は Findyの爆速開発を支えるタスク分解 - Findy Tech Blog で紹介しています。 頻出するコードを自動生成 カスタムスラッシュコマンドは、Git操作だけでなく、具体的なコーディング作業の自動化にも威力を発揮します。私の経験則ではIssueに作成したタスクリストに基づき、小さな単位で具体的なコードを指示すると期待した結果が得られやすいと感じます。 そのため、定型化できる実装はカスタムスラッシュコマンドで対応してもらいます。例えば、フロントエンドの実装では、次のよく使うコードはカスタムスラッシュコマンドで対応しています。 保存ボタンの連打防止の実装 テキスト入力の必須バリデーションの実装 フォーム入力中の離脱防止の実装 .claude/commands/[Repository name]-coding-is-saving.md ## 保存ボタンの連打防止を実装 作業対象のフィーチャー: $ARGUMENTS ### 参考情報 - PRの確認にghコマンドを使うこと - https://github.com/Findy/[リポジトリ名]/pull/111 ### 実装コードの例 < Button priority= "primary" size = "large" disabled = {isSaving} type = "submit" > 保存 </ Button > ### テストコードの例 describe('isSaving', () => { it('should disable save button when isSaving is true', () => { // Arrange setup({ isSaving: true, }); // Act & Assert expect(screen.getByRole('button', { name: '保存する' })).toBeDisabled(); }); it('should enable save button when isSaving is false', () => { // Arrange setup({ isSaving: false, }); // Act & Assert expect(screen.getByRole('button', { name: '保存する' })).toBeEnabled(); }); }); コーディングにおいてカスタムスラッシュコマンドを作成する基準は次の通りです。 3回以上同じような実装に遭遇した プロダクトコードとテストコードを1セットでPRを作成できる 実装内容が分かり切っている このようにClaude Codeに小さな粒度でコードを書いてPRを出して貰いつつ、その間に私は別の作業をします。 Claude CodeのHooksの設定により、コーディングなどの作業が完了したら通知音を鳴らしているため、スムーズに切り替えることができます。 まとめ 本記事では、私が実践しているClaude Codeのカスタムスラッシュコマンド活用術をご紹介しました。Git操作の自動化から、具体的なコーディング作業の効率化まで、多岐にわたる場面でClaude Codeが開発をサポートしてくれています。 カスタムスラッシュコマンドは汎用的な指示よりも、具体的で小さなタスクに特化させて作成することで、その効果を最大限に発揮すると感じています。機械的な作業をClaude Codeに任せることで、私たちはより本質的な開発業務に集中できるように今後も試行錯誤していきたいです。 この記事が、皆さんの開発現場におけるAI活用のヒントになれば幸いです。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやClaude Codeなど生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中で、MCP(Model Context Protocol)の新バージョンが公開され、いくつかの機能が追加されました。 modelcontextprotocol.io そこで今回は、その中でも特に注目すべき3つの機能について紹介したいと思います。 それでは見ていきましょう! toolの表示名の項目追加 MCPサーバーからの出力データの構造化 Elicitation まとめ toolの表示名の項目追加 MCPサーバーにtoolやpromptを登録する際に、 title を設定することが出来るようになりました。 github.com 今までのMCPサーバーでのtoolの登録は次のようなコードで実行されていました。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; import { z } from "zod" ; const mcpServer = new McpServer( { name : "Sample MCP Server" , version : "0.0.1" } ); mcpServer.registerTool( "addition" , { description : "足し算をする" , inputSchema : { a : z.number(), b : z.number() } } , ( { a , b } ) => { return { content : [{ type : "text" , text : String (a + b) }] } ; } ); MCPクライアントからtoolの情報を確認すると、次のような出力になります。 ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │ Tools for sample (1 tools) │ │ │ │ ❯ 1. addition │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │ addition (sample) │ │ │ │ Tool name: addition │ │ Full name: mcp__sample__addition │ │ │ │ Description: │ │ 足し算をする │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ Tool nameに addition が、Full nameに mcp__sample__addition が設定されているのがわかります。 同じMCPクライアントで複数のMCPサーバーに接続した場合、tool名が重複してしまうケースが有り得ます。そのため、Tool nameとは別にFull nameが用意されており、MCPサーバー名とtool名を組み合わせた一意な名前が用意されています。 しかしここで重要な問題が起こります。MCPクライアントによっては、Full nameに文字数制限が存在しており、制限を越えてしまうとMCPサーバーの実行に影響が出ることがあります。とはいえ、tool名はLLMが実行対象を決めるための判断材料となっているため、短縮しすぎることはできません。 そこで今回追加された title の出番です。 title を次のように設定します。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; import { z } from "zod" ; const mcpServer = new McpServer( { name : "Sample MCP Server" , version : "0.0.1" } ); mcpServer.registerTool( "addition" , { description : "足し算をする" , inputSchema : { a : z.number(), b : z.number() } , annotations : { title : "add two numbers" , } } , ( { a , b } ) => { return { content : [{ type : "text" , text : String (a + b) }] } ; } ); MCPクライアントでtool情報を再確認すると、次のような出力に変化します。 ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │ Tools for sample (1 tools) │ │ │ │ ❯ 1. add two numbers │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │ add two numbers (sample) │ │ │ │ Tool name: addition │ │ Full name: mcp__sample__addition │ │ │ │ Description: │ │ 足し算をする │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ title を活用することで、Full nameの文字数制限を気にすることなく、よりわかりやすい名前をMCPクライアントに提供できるようになります。 MCPサーバーからの出力データの構造化 MCPサーバーにtool等を登録する際に inputSchema を設定することは以前から可能でしたが、今回のバージョンアップから outputSchema を設定できるようになりました。 modelcontextprotocol.io outputSchema を定義して、MCPサーバーからのresponseに、 content とは別に structuredContent を設定することで、MCPクライアントは構造化されたデータを受け取ることができるようになります。 実際に outputSchema を設定したMCPサーバーのtoolを見てみましょう。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; import { z } from "zod" ; const mcpServer = new McpServer( { name : "Sample MCP Server" , version : "0.0.1" } ); mcpServer.registerTool( "addition" , { description : "足し算をする" , inputSchema : { a : z.number(), b : z.number() } , outputSchema : { result : z.number().describe( "Sum of the two numbers" ) } , } , ( { a , b } ) => { const result = a + b; return { content : [{ type : "text" , text : JSON . stringify ( { result } ) }] , structuredContent : { result } } ; } ); toolを登録する際に、 inputSchema だけではなく outputSchema も設定しています。更にtoolのresponseには content に加えて structuredContent を追加しています。 後方互換性を持たせるために、 content には structuredContent をJSON文字列に変換して返します。 これらの設定により、MCPクライアントはtoolの実行結果をより構造化された形で受け取ることができます。 今回の outputSchema と structuredContent の追加により、MCPクライアントとLLMがMCPサーバーからのresponseをより適切に解析して利用できるようになることを期待できます。 Elicitation 最後になりますが、今回のMCPの新バージョンで追加された機能の中でも特に注目すべき機能が Elicitation です。 modelcontextprotocol.io Elicitation を活用することで、MCPサーバーとMCPクライアントの通信中に、ユーザーに追加情報を要求できるようになります。 今まで紹介したMCPの機能とは一線を画しているのでイメージしづらいと思いますので、実際のコードと具体例で説明していきます。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; const mcpServer = new McpServer( { name : "Sample MCP Server" , version : "0.0.1" } ); mcpServer.registerTool( "validate_username" , {} , async () => { const elicitInputResponse = await mcpServer.server.elicitInput( { message : "Input your username." , requestedSchema : { type : "object" , properties : { username : { type : "string" , title : "your username" , description : "input your username." } } , required : [ "username" ] } } ); if (elicitInputResponse. action !== 'accept' ) { throw new Error ( "username is required." ); } const userName = elicitInputResponse.content?. [ 'username' ] as string ; if (userName. length > 12 ) { throw new Error ( "username must be less than 12 characters." ); } return { content : [{ type : "text" , text : ` ${ userName } is valid.` }] , } ; } ); elicitInput を呼び出すことで、ユーザーに追加情報を要求できます。GitHub Copilotで実行した場合、次のような表示になります。 usernameを入力するように要求されているので、次のように入力してみます。 追加要求が成功した場合、ユーザーの入力内容を取得でき、その内容を元に処理を続行できます。 今回は入力されたユーザー名の長さをチェックして、12文字以下であれば有効なユーザー名として処理を続行しています。 今回は12文字以内で入力して送信したため、次のような結果になりました。 また、 elicitInput は文字列の入力だけではなく、enumを使って選択式にするといったことも可能です。選択式にすることにより、入力内容からの分岐をより明確にできます。 mcpServer.server.elicitInput( { message : "select period" , requestedSchema : { type : "object" , properties : { period : { type : "string" , title : "Period" , description : "Select the period" , enum : [ "today" , "yesterday" , "this_week" ] , enumNames : [ "Today" , "Yesterday" , "This week" ] } } , required : [ "period" ] } } ); このように Elicitation を活用することで、MCPサーバーからの追加要求を通じて、ユーザーとのインタラクションをより柔軟に行うことが可能になります。MCPサーバーの使い方、作り方、提供内容がより多様化し、ユーザーにとっても使いやすいツールを提供できるようになることが期待されます。 まとめ いかがでしたでしょうか? 今回紹介したMCPの新バージョンでは、 title 、 outputSchema と structuredContent 、そして Elicitation といった重要な機能が追加されました。 これらの機能は、MCPサーバーとMCPクライアントの連携をより強化し、ユーザーにとって使いやすいツールを提供することが期待できます。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。Developer Productivity Engineer(DPE)兼 Findy Tech Blog編集長の高橋( @Taka-bow )です。 おかげさまで、Findy Tech Blogは2年目に突入しました。 この1年で、私たちのブログは多くのエンジニアやIT業界関係者の皆さんにご愛読いただき、記事の内容もますます多様化・充実してきたと感じています。 日々の開発現場で役立つノウハウや、最新技術のトレンド、エンジニアの日常など、さまざまなテーマを取り上げてきました。 「現場で本当に使える知見がほしい」「他社のエンジニアはどんな工夫をしているのか知りたい」「自分の成長のヒントを探したい」――そんな方々にとって、少しでもヒントや刺激となる記事をお届けできていれば幸いです。 今回は、2025年上半期に特に多くの反響をいただいた記事を、ランキング形式でご紹介します。 技術のトレンドから生産性向上テクニックまで、見逃していた記事が見つかるかもしれませんよ! それでは、2025年上半期のFindy Tech Blogを一緒にふりかえっていきましょう! 2025年上半期トピックス 「テックブログ運営 井戸端会議〜2025年を走り切るために〜」というLT大会を開催 【2025年上半期(1月〜6月)】PV数ランキングTop3 第3位 第2位 第1位 【2025年上半期(1月〜6月)】はてなブックマーク数Top3 第3位 第2位 第1位 おわりに 2025年上半期トピックス 「テックブログ運営 井戸端会議〜2025年を走り切るために〜」というLT大会を開催 年明け早々に「テックブログ運営」という、ありそうでないテーマでLT大会を開催しました。 はじまった〜📝 #techbrew_findy https://t.co/uFBws89kch pic.twitter.com/ERWbz5ZcT2 — ゆーだい@Findy Team+ (@dai___you) 2025年1月27日 LT大会では、株式会社ログラスの粟田さん、株式会社Goalsの今村さん、株式会社リブセンスの鈴木さん、フューチャーアーキテクト株式会社の伊藤さん、株式会社タイミーの吉野さん、ウェルスナビ株式会社の長さんという豪華なメンバーにご登壇いただきました。 テックブログと一口に言っても、その目的や運営の悩みは本当にさまざまであることを、あらためて実感しました。 当日の雰囲気や盛り上がりは、Xのまとめからも感じていただけると思います。 posfie.com ファインディからは、戸田さんが Findy Tech Blog の誕生秘話や立ち上げ時のターニングポイントについて、私(高橋)は運営における定量的な測定目標の考え方や、普段どんな点を意識しているかについてお話ししました。これらは今も変わっていません。資料もぜひご覧ください! speakerdeck.com speakerdeck.com 【2025年上半期(1月〜6月)】PV数ランキングTop3 2025年上半期、Findy Tech Blogには数多くの注目記事が登場しましたが、ここからは、上半期で一番アクセス(PV)のあった記事を紹介します! 第3位 \ 第3位 /13,710 PV ファインディのエンジニアたちが自身の成長に影響を与えた一冊を語る人気シリーズ「エンジニア達の人生を変えた一冊 Part4」がランキング。 記事では、『コンピュータの構成と設計』(通称「パタ&ヘネ」)や『体系的に学ぶ 安全なWebアプリケーションの作り方』、そして『現場で役立つシステム設計の原則 変更を楽で安全にするオブジェクト指向の実践技法』といった名著が取り上げられており、それぞれがどのようにエンジニアたちの視点やスキルに変化をもたらしたのかが語られています。 とても実直なラインナップでしたが、多くの方に読まれました。ぜひチェックしてみてください! 第2位 \ 第2位 /14,012 PV 2位は、こちらも人気シリーズの「エンジニア達の自慢の作業環境を大公開 Part6」でした! 第6弾となるこの記事では、ファインディエンジニアの安達さん、土屋 (しゅんそく)さん、秋田さんの3名それぞれが、生産性向上と快適性を追求した作業環境を詳しく紹介しています。単なるガジェット紹介にとどまらず、各エンジニアがどのような思想で作業環境を構築しているかが詳しく語られています。生産性向上、身体への配慮、空間の美しさやコストパフォーマンスなど、それぞれ異なる優先順位で環境を整えており、エンジニアの多様な働き方スタイルが見えてくる内容となっています。 第1位 \ 第1位 /14,743 PV 2025年上半期、最も多くの方に読まれた記事は「【エンジニアの日常】これが私の推しツール!〜日々の開発を豊かにするおすすめツール〜 Part2」でした。 エンジニアの日常シリーズの人気企画「推しツール」第2弾。Findyのエンジニアたちが日々の開発で愛用しているツールやOSSを紹介し、Neovimやlazygit、Raycastなど、業務効率化に役立つツールの活用法やおすすめポイントを詳しく解説しています。他のエンジニアの工夫やツール選びを知りたい方におすすめの記事です。 2025年上半期のトップ3は、いずれも【エンジニアの日常】シリーズからのランクインとなりました。 【2025年上半期(1月〜6月)】はてなブックマーク数Top3 続いては、はてなブックマーク(はてブ)の数が多かった記事のランキングをご紹介します。 PVランキングとはまた違った切り口で、読者の皆さんが「あとでじっくり読み返したい」「何度も参考にしたい」と思った記事が上位に並びました。 日々の業務や学びの中で役立つと感じていただけた記事が多くランクインしているのではないでしょうか。 それでは、はてブ数Top3を見ていきましょう! 第3位 \ 第3位 /131 users Findyの爆速開発シリーズの一環として、生成AI活用の実践編を紹介しています。MCPサーバーの作成を通じて、実際の開発現場でどのようにAIを活用しているか、具体的な実装方法や効果について詳しく解説しています。AI技術を活用した開発効率化に関心のあるエンジニアにおすすめの記事です。 第2位 \ 第2位 /136 users PVランキングでも3位に入った人気シリーズ「エンジニア達の人生を変えた一冊 Part4」が、はてブランキングでも2位にランクイン! 第1位 \ 第1位 /190 users 2025年上半期、最も多くのはてブが付いた記事は「Findyの爆速開発を支えるタスク分解」でした! ファインディの開発チームが実践している効率的なタスク分解手法について詳しく解説。複雑な機能開発を小さな単位に分割し、段階的に実装していくことで、開発速度と品質を両立させる方法を紹介しています。開発生産性向上に関心のあるエンジニアやマネージャーに特に人気の記事となっています。 おわりに 2025年上半期のトピックスや、公開した35本の記事の中から注目の内容をランキング形式でご紹介しました。ここでご紹介しきれなかった記事もたくさんありますので、ぜひ他の記事もあわせてご覧いただければと思います。 今後も新しい技術への挑戦や、ファインディならではの開発の取り組みについて、積極的に発信していきます。 また、読者の皆さんからのコメントやSNSでの反応は、私たち編集部にとって大きな励みです。 これからも「面白い!」「参考になった!」と思っていただける記事をお届けできるよう、ファインディエンジニア一同取り組んでまいります。 引き続きFindy Tech Blogをよろしくお願いいたします。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募ください。 herp.careers
こんにちは。データエンジニアの田頭( tagasyksk )です。 本記事では、MCPとAIエージェントを活用して、複数CRMの顧客情報を横断的に検索できるようにした事例をご紹介します。 背景 システム構成図 技術選定 エージェント間連携の簡易さ Google Cloud統合 MCP Toolbox for Databasesによる簡単なBigQuery接続 工夫した点 オーケストレーションの設計 ツールを搭載したサブエージェントの呼び出しについて Slack統合 導入後の効果 今後の展望 終わりに 背景 ファインディでは、エンジニア組織をあらゆる場面で支援するため、複数のプロダクトを展開しています。 事業成長に伴う課題として、お客様の大切な情報がプロダクト毎にサイロ化してしまう状況が起きました。 そこで、この課題を解消し、一社でも多くのお客様にファインディの価値を届けるため、CRMに蓄積されていた顧客情報をBigQueryに集約し、部門横断で利用できる「共通企業マスタ」を構築しました。 これにより、全部門が常に同じ最新の顧客情報を参照できるようになり、スムーズな連携が可能な体制を整えました。 しかし、この共通企業マスタをどのようにセールスチームやCSチームに届けるかが新たな課題となりました。 全員にSQLを書かせるのは現実的でなく、新しい分析インターフェースを作るのも工数がかかります。そこで、MCPとAIエージェントを活用したSlack上での企業検索システムの構築に取り組みました。 システム構成図 Slackとソケットモードを利用して疎通するAIエージェントサーバーと、後述するBigQueryのMCPサーバーをCloud Runのマルチコンテナ構成を利用してホスティングしています。 技術選定 AIエージェントのフレームワークには、GoogleからリリースされているAgent Development Kit(ADK)を採用しました。 google.github.io ADKを選定した理由は次の通りです。 エージェント間連携の簡易さ Google Cloud統合 MCP Toolbox for Databasesによる簡単なBigQuery接続 エージェント間連携の簡易さ ADKでは、次のようにシンプルなコードでエージェント間でのオーケストレーションを実装できます。 今回のケースでは、企業の業務情報や従業員数をWEBから取得したいユースケースがあったので、Google検索ができるエージェントをサブエージェントとして実装しています。 # Google検索で企業の情報を取得するエージェント google_search_agent = LlmAgent( model= "gemini-2.5-flash" , name= "google_search_agent" , description= "A helpful AI assistant that can search company information from google." , instruction=GOOGLE_SEARCH_AGENT_INSTR, tools=[google_search], ) root_agent = LlmAgent( model= "gemini-2.5-pro" , name= "company_master_agent" , description= "A helpful AI assistant that can search company." , instruction=ROOT_AGENT_INSTR, sub_agents=[google_search_agent] #Google検索エージェントをサブエージェントとして追加 ) タスクごとに細かくサブエージェントを立てられるため、非常に見通しの良いエージェントシステムが構築できます。 Google Cloud統合 データ基盤をBigQueryで構築しており、Geminiも活用している弊社にとって、権限やホスティングに必要な知識を新しくキャッチアップする必要がないのはかなり大きかったです。 MCP Toolbox for Databasesによる簡単なBigQuery接続 MCP Toolbox for Databasesでは、次のようなyamlファイルを定義するだけで簡単にBigQueryへの接続情報をMCP化できます。 my-bigquery-source : kind : bigquery project : ${your_project} location : asia-northeast1 toolsets : search_company : - search-company-by-name tools : search-company-by-name : kind : bigquery-sql source : my-bigquery-source description : 企業情報を企業名から検索する。 parameters : - name : company_name type : string description : 企業名 statement : SELECT * FROM `${your_dataset}.companies` WHERE company_name LIKE CONCAT('%', @company_name,'%'); MCPサーバーは、次のようなコマンドで簡単に起動できます。 containers: - image: us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest name: toolbox args: - "toolbox" - "--tools-file" - "/app/tools.yml" - "--address" - "0.0.0.0" - "--port" - "5001" エージェントからは次のように参照させると、yaml上で登録したtool(今回は search-company-by-name )を使えるようになります。 from toolbox_core import ToolboxSyncClient toolbox = ToolboxSyncClient( "http://localhost:5001" ) search_company_tools = toolbox.load_toolset( "search_company" ) agent = LlmAgent( model= "gemini-2.5-pro" , name= "company_search_agent" , description= "A helpful AI assistant that can search company in BigQuery" , tools=search_company_tools ) このように事前にBigQueryとの接続を定義しておくことで、意図したSQLを使ってデータにアクセスさせる事ができ、不要なデータベースの参照や誤ったコマンドを防ぐことができました。 工夫した点 オーケストレーションの設計 メインエージェントのInstructionはサブエージェントのユースケースのみを記載し、BigQueryやGoogle検索の具体的な利用方法はサブエージェントのInstructionに記載しています。 これにより、メインエージェントは全体のオーケストレーションに集中し、各サブエージェントは専門的なタスクに特化できるような設計と なっています。 ツールを搭載したサブエージェントの呼び出しについて 2025年7月現在、ビルトインツールやPythonの関数で定義したツールを搭載したエージェントを2つ以上同時にサブエージェントとして呼び出すことができません。 github.com エラー回避策として、エージェントをToolとして呼び出すAgentToolというラッパーを使っています。 # toolを持ったサブエージェントを定義 google_search_agent = LlmAgent( ~~~, tools=[google_search], ) bigquery_search_agent = LlmAgent( ~~~, tools=[bigquery_search], ) # AgentToolでラップ google_search_agent_tool = AgentTool(agent=google_search_agent) bigquery_search_agent_tool = AgentTool(agent=bigquery_search_agent) # メインエージェントからはツールとして参照 root_agent = LlmAgent( ~~~, tools = [google_search_agent_tool, bigquery_search_agent_tool], ) Slack統合 新しいツールを導入することで利用者の負担を増やすことを避けるため、既に社内で日常的に使用されているSlack上でやりとりできるシステムを構築しました。 ソケットモードで送信されてきたメッセージでエージェントを起動し、返答をSlackに返却するMCPクライアントを実装しています。 class SlackToADKClient : """Slack メッセージを ADK エージェントに橋渡しする MCP クライアント""" def __init__ (self): self.slack_app = AsyncApp(token=SLACK_BOT_TOKEN) self.session_service = InMemorySessionService() async def handle_slack_message (self, event, say): """Slackメッセージイベントを処理""" user_id = event.get( "user" ) message_text = event.get( "text" , "" ) # エージェントに問い合わせ response = await self.query_adk_agent(message_text, user_id) await say(text=response) async def query_adk_agent (self, message: str , user_id: str ): """エージェントにクエリを送信""" # セッション管理 session = await self.session_service.get_or_create_session(~~~) runner = Runner( agent=self.company_agent, session_service=self.session_service, ) # エージェントの実行 events = runner.run_async(~~~) # ~~~応答処理~~~ return response_text Slack側からは、Slack Botにメンションする形で簡単に企業情報を検索できるようにしました。 企業名で検索すると共通企業マスタの内容を回答してくれ、かつ事業内容などの企業マスタに含まれない情報はGoogle検索をベースにして回答してくれるようになっています。 導入後の効果 運用開始から1ヶ月で、インサイドセールスやカスタマーサクセスのメンバーの40%近くに利用されています。 ユーザーからは次のような声をいただきました。 各サービスごとの社内担当者がすぐわかるようになり、社内連携が迅速になった Slackで情報の確認ができるため、展示会やイベントの会場からスマホで企業の情報を得られるようになった 一方で、検索機能については次のフィードバックもいただいています。 全角アルファベットで検索したら、共通企業マスタ上では半角で登録されていて検索できなかった 同一会社名で重複しているレコードが表示され、どちらが正しいかわからない この課題については情報源である共通企業マスタの品質向上によって解決していけるものです。データ品質のテストをより厚くしたり、各CRMの担当者と協力してデータクレンジングを進めることで改善を進めています。 今後の展望 現在の検索機能をベースに、さらなる機能拡張を計画しています。 例えば、現在は企業名に基づいた検索のみ実装していますが、企業マスタに存在する様々なカラムから検索フィルタをエージェントが自動で作成し、営業リストとして提供する機能などを考えています。 終わりに いかがでしたでしょうか?今回は弊社でのMCPとAIエージェントの活用について書きました。 AIエージェントの活用は、単純な検索だけでなく、将来的にはより高度な顧客分析や提案機能へと発展させることができる可能性を秘めています。今回の事例が、同様の課題を抱える組織の参考になれば幸いです。 弊社ではデータ基盤を共に育てていくメンバーや、AIエージェントなどのデータ利活用を推進するメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております! herp.careers herp.careers
こんにちは。こんばんは。 開発生産性の可視化・分析をサポートする Findy Team+ 開発のフロントエンドリードをしている @shoota です。 ファインディのフロントエンドでは多くのプロダクトで Nx を用いたモノレポを構築しています。 tech.findy.co.jp Findy Team+ のフロントエンドもNxを採用し、各パッケージ間の依存関係の管理やライブラリのマイグレーションなどの恩恵を受けています。 なかでも強力なキャッシュ機構をベースとしたCIの高速化はなくてはならない存在となっています。 以下は、このブログの執筆時点での Findy Team+ のフロントエンドリポジトリが実行するCIの統計情報です。 Team+ の CI実行 直近30日間でCIの実行回数は2500回、平均時間は7分です。 そしてNxの機能によって 削減された実行時間はなんと167日分(約4000時間) にもなります(キャッシュはネットワークで共有されるので開発者のローカルでも有効です)。 しかし我々はこのような強力かつ高速なCIの環境を常に維持し続けていたわけではありません! 過去には平均のCI実行時間が13分以上かかっており、開発速度に大きな影響を及ぼしていました。 そこで今回はNxでのキャッシュ率を高め、CI時間を短縮するためのNxをベースとしたリアーキテクチャの実例についてご紹介したいと思います。 CI高速化のためのリアーキテクチャ ページレイアウトモジュールの分離、ライブラリ化 共有モジュールの分割 翻訳アーキテクチャの刷新 UI コンポーネントのモジュール分割 コードベースとCI時間の比較 まとめ CI高速化のためのリアーキテクチャ 2024年のはじめ頃から、Team+のフロントエンドのCI時間は伸び続ける傾向が見え始めてきました。 プロダクトの肥大化と複雑化、そして開発メンバー数の急増によって、コードベースの増加速度も急成長をしていました。 「開発速度が上がるほどCI時間が伸びる」というアンチパターンを打開すべく、1年以上をかけてモノレポの内部構造の再設計をしました。 ページレイアウトモジュールの分離、ライブラリ化 共有モジュールの分割 翻訳アーキテクチャの刷新 UI コンポーネントのモジュール分割 今回はこの内容を紹介していきたいと思います。 ページレイアウトモジュールの分離、ライブラリ化 まず初めに目をつけたのがページレイアウトに関連するモジュールでした。Team+のサイドナビゲーションやヘッダーUIなどのページ全体のレイアウトに関わるコードです。 これらはモノレポの共有モジュールの中に配置されていましたが、その役割ゆえにほぼすべての画面で利用します。 レイアウトを変更することは稀ですが、共有モジュール内にレイアウトが所属することでモジュール全体に依存関係を持ちます。このときレイアウト以外のコードを変更をすると、レイアウトを利用しているものすべてが依存関係にあるため、全画面のテストが発生してしまいます。 そこでレイアウト関連のコードを別モジュールに分離して、依存関係が集中しないようにしました。 図1. レイアウトモジュール分離 共有モジュールの分割 次にレイアウトを分離した後の共有モジュールを更に分割し、変更の影響範囲を効率化しました。 共有モジュールの中には古くからあり、成熟しており、そしてテストの重いものがいくつかありました。このような古参モジュールは多くの機能で利用します。一方で、最近の開発ドメインに向けて作られた新米モジュールも共有モジュールに存在します。 両者が同居していると日々のコード変更頻度と重いテストが複合し、全体効率を下げる要因になっていたため、別居計画を進めました。 図2. 共有モジュールの別居 変更頻度の低い古参モジュールを分離することで、開発を進めているドメインに関連した比較的軽いテストのみがよく回るような構造にできました。 翻訳アーキテクチャの刷新 これまでは通常のモノレポ構造の再設計でしたが、CI時間に最も影響を及ぼしていたのはここで紹介する翻訳システムでした。 Findy Team+ は日本語・英語・韓国語の3言語に対応していますが、これらの翻訳は1つのモジュールで集約管理していました。 しかし機能開発の高速化・大規模化に伴って、翻訳対象の文言も急増し、さらに韓国語対応を追加したことで爆発的な依存関係の連鎖が生まれ、CI時間を圧迫してしまいました。 図3. 翻訳辞書の一元管理 画面が追加されるごとに翻訳辞書が増え、かつ翻訳モジュールの変更が発生するので、全画面のテストが実行されます。 次の画面が追加されるとその前に追加された画面もテスト対象になり、さらに実行時間が伸びます。この繰り返しによってCI時間が指数的に長くなっていきました。 そこで画面個別の辞書を画面モジュールに分散し、それぞれの画面の開発で発生するコード変更が画面モジュールのなかで閉じるようにしました。分散した辞書は画面表示前に動的に読み込んで表示できるような修正も行いました。 図4. 翻訳辞書の分散 画面がどんどん追加されても全画面のテストが起きなくなり、開発速度・並行数が上がってもCI時間が伸びない構造に生まれかわることができました。 共有モジュールの分割とは異なり、依存関係は変更せずにコード変更の発生箇所を移動することで、平均の実行時間を大きく縮めることができました。 UI コンポーネントのモジュール分割 上記の3点の改善によってCI時間は概ね安定して短縮できていましたが、更にTeam+を構成するUI コンポーネントの分離を進めました。 ボタンやフォームなどのプリミティブなUI(HTMLに近いもの)とTeam+特有のセマンティックなUIに分類し、依存の親子関係となるように分けました。 これも先述のようにボタンコンポーネントやフォームなどのプリミティブなUIは変更頻度が少なく、かつ依存度が高いことを見据えた分離です。 UI分離 変更頻度の高いモジュールとそれに依存したモジュールのテストが実行されるので、Nxのキャッシュ率を向上させることができました。 コードベースとCI時間の比較 CI高速化のためのリアーキテクチャの内容をご紹介してきましたが、タイトルの「60万行」にも触れたいと思います。 今回のリアーキテクチャを開始した時点では、Team+のコード量は次のようになっていました。 Language files blank comment code TypeScript 5422 42462 13430 353578 JSON 349 0 0 51694 以下略 SUM: 6212 46170 17230 419602 TypeScriptのコードとして約35万行、翻訳辞書を定義しているJSONを合わせると約41万行です。 これらのコードの 平均のCI実行時間が13分以上 かかっていました。 そして冒頭にも記載したとおり、現在では 平均のCI実行時間が7分程度 になっています。この改善の間にも多くの機能リリースをしてきました。 こちらが現在のTeam+のコード量です。 Language files blank comment code TypeScript 9171 68280 22279 552539 JSON 672 6 0 66888 以下略 SUM: 10453 69658 22424 635517 TypeScriptのコードとして約55万行、翻訳辞書を定義しているJSONを合わせると約62万行です。 つまりコードベースとして約1.5倍の成長をしながら、CI時間を53%程度まで削減できたのです!! まとめ ここまで拝読いただきありがとうございます。 今回は Findy Team+ の開発を支えるCIとその改善内容についてご紹介いたしました。内容を以下3点にまとめてます。 Nxベースのモノレポアーキテクチャを再設計することで変更に依存しない高速なCI環境をつくることができる。 モノレポ間の依存関係と、開発現場のコード変更の傾向をつかむことがCI速度改善のカギになる。 CI速度の改善は規模の大きなコード、組織にとって不可欠な改善のひとつと言える。 なお今回のリアーキテクチャでいちばん大変だったのは、変更対象のCI時間が基本的に長いことでした。 CI時間が長いモジュールを修正し続けているので当然なのですが、効果がでるまでの我慢期間が長かったことは胸に刻みたいと思います。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから herp.careers
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub CopilotやCursorなど、生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そこで今回は、弊社のGitHub Copilotの活用方法について紹介します。 それでは見ていきましょう! カスタムインストラクション MCP Agent mode Coding Agent まとめ カスタムインストラクション GitHub Copilotを始めとする生成AIツールを効果的に活用するためには、まず最初にカスタムインストラクションの設定が必要不可欠です。 docs.github.com カスタムインストラクションに関しては以前の記事で紹介しておりますので、併せてご覧ください。 tech.findy.co.jp tech.findy.co.jp カスタムインストラクションを設定することで、生成AIがプロジェクトのコンテキストを理解し、より適切な提案を行うことが可能になります。 GitHub Copilotの場合は .github/copilot-instructions.md というファイルをリポジトリに配置するだけで利用することが出来ます。 他にも、実装コード、テストコード、コミットメッセージなど、目的別にカスタムインストラクションのファイルを分けることができるようになっています。 code.visualstudio.com 弊社の場合、ファイルや変数の命名規約に留まらず、コミットメッセージやテストコードについてもカスタムインストラクションに記載しています。 コミットメッセージにSemanticVersionを採用しているケースがあり、リリース時にコミットメッセージを元にリリースノートを自動生成しています。 そのため、コミットメッセージが持つ意味合いが重要となっており、誤ったSemanticVersionになっていた場合はレビュー時に修正依頼を出すこともあります。 しかし、Copilotが作業を行いコミットまで自動で行うケースの場合、AIが生成したコミットメッセージが誤っているケースが出てきました。 そこでカスタムインストラクションに次のようなコミットメッセージのルールを記載することで、Copilotが作成するコミットメッセージに適切なSemanticVersionが設定されるようにしています。 ## コミットメッセージ規約 ### 1. 基本構造 < semantic version > - < type > : < message > ### 2. 例 - major-feat: remove user field from api params - minor-feat: add api for get user list - patch-docs: fix typo in README ### 3. 各要素の説明 #### semantic version https://semver.org/ - major - 互換性のないAPIの変更 - 既存のフィールドの削除 - 既存のフィールドの型の変更 - 必須パラメータの追加 - エンドポイントの削除や名前変更 - minor - 互換性のあるAPIの変更 - 新しいフィールドの追加 - 新しいエンドポイントの追加 - 任意パラメータの追加 - 既存の機能を拡張するが後方互換性を維持する変更 - patch - リファクタリング - ドキュメントの追加、変更 - CI/CDの追加、変更 - コードの意味に影響を与えない変更 #### type - test - テストの追加、修正 - feat - 新機能の追加 - fix - バグ修正 - chore - ビルドプロセスや補助ツールの変更 - docs - ドキュメントの変更 - refactor - リファクタリング - style - コードの意味に影響を与えない変更 - ci - CIに関連する変更 - perf - パフォーマンスを向上させるコードの変更 #### message - 変更内容を要約した72文字以内の英語のメッセージ - 技術用語は英語のままにする カスタムインストラクションには事実のみを簡潔に書くのがポイントです。 複雑で長いルールを適用させたい場合は、具体例を示すと良いでしょう。今回紹介したコミットメッセージのカスタムインストラクションにも具体例を記載しています。 また、カスタムインストラクションは最初に1度作成して完成するようなものではなく、徐々に加筆修正して精度を上げていきましょう。 このように、ドメイン知識やプロジェクトのルールをカスタムインストラクションに記載することで、AIがより適切で自分たちの開発ルールに沿った提案を行ってくれるようになります。 MCP GitHub Copilotや各種AIツールを効果的に活用するためには、MCPの活用も非常に重要になってきます。 tech.findy.co.jp カスタムインストラクションに加え、MCPを活用することで、Copilotが扱う情報の範囲を広げ、より適切な提案やタスクの実行を行うことが可能になります。 例えばGitHubのMCPを利用する場合、次のような記述で設定します。 { " servers ": { " github ": { " command ": " docker ", " args ": [ " run ", " -i ", " --rm ", " -e ", " GITHUB_PERSONAL_ACCESS_TOKEN ", " ghcr.io/github/github-mcp-server " ] , " env ": { " GITHUB_PERSONAL_ACCESS_TOKEN ": " <YOUR_GITHUB_PERSONAL_ACCESS_TOKEN>> " } } } } GitHubのMCPの設定を行い、対象のIssueの情報を取得して、その内容をそのままCopilotに渡すことが出来ます。 Issueに要件やタスクの内容を記載しておくことで、Copilotがその内容を理解し、適切なコードの提案やタスクの実行を行うことが可能になります。 SentryのMCPも同様に活用することが出来ます。次のような記述で設定します。 { " servers ": { " sentry ": { " command ": " uvx ", " args ": [ " mcp-server-sentry ", " --auth-token ", " <YOUR_SENTRY_AUTH_TOKEN> " ] } } } Sentryで障害を検知した際、MCP経由でSentryのIssueの情報を取得して、その内容をそのままCopilotに渡すことが出来ます。その情報を元に、Copilotに原因を特定してもらい、Copilotにコードを修正してもらうことが可能です。 このように、MCPを活用することで、Copilotがプロジェクトやリポジトリ、さらにそれらに関連する情報を取得して、より適切な提案やタスクの実行を行うことが可能になります。 Agent mode GitHub CopilotのAgent modeを利用することで、Copilotが自律的にタスクを実行し、コードの修正や新機能の追加などを行うことが可能になります。 docs.github.com その際にカスタムインストラクションやMCPの設定が非常に重要な役割を果たします。 また、Agent modeを実行する際に、コンテキストを絞ることも非常に有効です。 特定のファイルや、コンテキストを指定することで、Copilotが参照する範囲を絞り込むことに繋がり、結果的に生成AIの提案の精度を向上させることができます。 例えば次のような実装コードとテストコードがあるとします。単純な描画を行うコンポーネントと、それに対するテストコードです。 export const TestComponent = () => { return ( <> < h1 > Test </ h1 > < div > < div > < span > Test Text </ span > </ div > </ div > </> ); } ; import { render } from '@testing-library/react' ; import { TestComponent } from './test.component' ; describe ( 'TestComponent' , () => { const setup = () => { const utils = render( < TestComponent /> ); return { ...utils, } as const ; } ; describe ( 'render' , () => { it ( 'render snapshot' , () => { const { asFragment } = setup(); expect (asFragment()).toMatchSnapshot(); } ); } ); } ); 一見問題ないように見えますが、弊社で開発しているFindy Team+は複数言語での表示に対応しています。そのため、表示されるテキストに翻訳処理を追加する必要があります。 翻訳処理を追加して、それに伴ってテストコードも修正するのは手間がかかりますが、ルールさえ覚えれば単純作業になります。こういったケースはAIエージェントの得意分野です。 翻訳処理を一気に追加したい場合、まずカスタムインストラクションに次のような記述を追加します。 # 翻訳処理 - 辞書データを定義する - json 形式のファイルで定義する ```json:libs/feature-hoge/src/lib/locales/ja.json { "component": { "hogeLabel": "ほげ", "hogeButtonText": "ほげボタンテキスト" } } ``` - Component 内 で ` useTranslation ` を利用する - ` keyPrefix ` に ` component ` を指定する ```tsx import { Trans, useTranslation } from 'react-i18next'; export const HogeComponent = () => { const { t } = useTranslation('hoge', { keyPrefix: 'component', }); return ( <> <span>{t('hogeLabel')}</span> <button type="button">{t('hogeButtonText')}</button> </> ); }; ``` - Component のテストコードで ` I18nextTestProvider ` と ` translateResources ` を利用する - ` translateResources ` は ` libs/feature-hoge/src/lib/locales ` を相対パスで import する ```tsx import { render } from '@testing-library/react'; import { I18nextTestProvider } from '@provider/i18n'; import { translateResources } from '../../locales'; import { HogeComponent } from './hoge.component'; const setup = () => { const utils = render( <I18nextTestProvider resources={{ ja: { hoge: translateResources.ja }, }} > <HogeComponent /> </I18nextTestProvider> ); return { ...utils, }; }; describe('HogeComponent', () => { it('should render', () => { const { asFragment } = setup({}); expect(asFragment()).toMatchSnapshot(); }); }); ``` そして次のようなプロンプトをAgent modeで実行します。 あなたは優秀なフロントエンドエンジニアです。 次の指示に従って作業を行ってください。 ## 対象ディレクトリ - ` libs/feature-test ` ## 辞書データ - ` libs/feature-test/src/lib/locales/ja.json ` ## 1. 辞書データのファイルに書き込みを行う ### 作業内容 - 対象ファイルに合致する既存ファイルの実装コードから文字列を抽出する - 抽出した文字列の中で辞書データのファイルに定義されていない文字列のみを、辞書データのファイルに追加する ### 対象ファイル - Component - **/*.component.tsx ## 2. 翻訳処理を追加する ### 作業内容 - 対象ファイルに合致する既存ファイル全てに翻訳処理を追加する - 辞書データに記述されているテキストを翻訳処理に利用する ### 対象ファイル - Component - **/*.component.tsx ## 3. テストコードを修正する ### 作業内容 - 対象ファイルに合致する既存のファイル全てに翻訳処理を追加する ### 対象ファイル - Component - **/*.component.spec.tsx ## 4. snapshotを更新する ### 作業内容 - 対象ファイルに合致する既存のファイル全てのsnapshotを更新する - MCPのWallabyを使用して、変更したテストコードの実行とsnapshotの更新を行う カスタムインストラクションとMCPをAgent modeで活用することで、次のようなコードへの変更が自動で実行されます。 実装コードに useTranslation での翻訳処理が追加され、テストコードには I18nextTestProvider と translateResources を利用した翻訳処理が追加されていることがわかります。 import { useTranslation } from 'react-i18next' ; export const TestComponent = () => { const { t } = useTranslation( 'test' , { keyPrefix : 'component' , } ); return ( <> < h1 > { t( 'testTitle' ) } </ h1 > < div > < div > < span > { t( 'testText' ) } </ span > </ div > </ div > </> ); } ; import { render } from '@testing-library/react' ; import { I18nextTestProvider } from '@provider/i18n' ; import { translateResources } from '../../../locales' ; import { TestComponent } from './test.component' ; describe ( 'TestComponent' , () => { const setup = () => { const utils = render( < I18nextTestProvider resources = { { ja: { test : translateResources.ja } , }} > < TestComponent /> </ I18nextTestProvider > ); return { ...utils, } as const ; } ; describe ( 'render' , () => { it ( 'render snapshot' , () => { const { asFragment } = setup(); expect (asFragment()).toMatchSnapshot(); } ); } ); } ); このように、カスタムインストラクションを使ってリポジトリのルールやドメイン知識をCopilotに提供することで、Agent modeの精度を向上させることができます。 またMCPを使うことで、Copilotが参照するリソースを増やしたり、実行できるタスクの幅を広げることができます。 Coding Agent Coding Agentを利用することで、Copilotをバックグラウンドで独立して動作させて、人間の開発者と同じようにタスクを実行できます。 docs.github.com 使い方はとても簡単です。タスクに対するIssueを作成して、Issueの担当者にCopilotを指定するだけです。その後、Copilotが自動でPull requestを作成して、GitHub Actions上でタスクが実行されます。タスクが完了した段階で、依頼者がレビュワーに設定されます。 また、Copilotが作成した変更に対してレビューコメントを書くことが出来ます。そのレビューコメントに対する修正もCopilotが自動で行ってくれます。 Coding Agentで作成されたPull requestに対してレビューコメントを書く場合、 Add single comment で一個ずつコメントを追加するのではなく、 Start a review から複数のコメントを追加した後にまとめて送信することをオススメします。全てのコメントを一括で送信すると、Copilotは個々のコメントを個別に処理するのではなく、レビュー全体を対象に処理を開始します。 docs.github.com また、ここでもカスタムインストラクションは効果を発揮します。 Copilotが作成するPull requestの内容やコミットメッセージ、コードのスタイルなどをカスタムインストラクションに記載しておくことで、より自分たちの開発ルールに沿った内容でPull requestを作成してくれます。 Coding AgentはMCPの利用も簡単に設定することが出来ます。リポジトリの設定でMCPの設定ファイルを記述することで簡単に設定可能です。 docs.github.com また、Coding AgentがGitHub Actions上でタスクを実行する前に事前に実行しておきたい処理を設定することも可能です。 .github/workflows/copilot-setup-steps.yml というファイルを作成して、GitHub Actionsのworkflowを定義することで、事前に必要な処理を実行しておくことができます。 次の例は、Pythonのプロジェクトで必要なライブラリのインストールと、テスト用のデータベースを事前に起動しておくための copilot-setup-steps.yml です。この設定をしておくことで、Coding Agentがファイルを修正してテストを実行する時に、必要なライブラリがインストールされており、テスト用のデータベースも起動している状態でタスクを実行できます。 name : "Copilot Setup Steps" on : workflow_dispatch jobs : copilot-setup-steps : runs-on : ubuntu-latest permissions : contents : read steps : - uses : actions/checkout@v3 - name : Set up Python uses : actions/setup-python@v4 with : python-version : '3.13' - name : Start database with Docker Compose run : docker compose up -d db --wait - name : Install dependencies run : | pip install ".[test]" - name : Run migrations run : | python -m alembic upgrade head Coding Agentが作成するPull requestの内容の精度は、次の要素に大きく左右されます。 カスタムインストラクションの内容 Issueに記載されているタスクの内容 既存実装の内容 特にIssueに記載されているタスクの内容は非常に重要です。タスクは具体的に且つ簡潔に記載することが重要です。そこで重要になってくるスキルがタスク分解です。 tech.findy.co.jp Issueのタスクを細分化して箇条書きにすると良いでしょう。大きなタスクをIssueに起票する際は、まず親Issueとして大きなIssueを作成することをオススメします。この親Issueに対してはCoding Agentを利用しません。 次に、親Issueに対して子Issueとして複数のSub Issueを作成します。このSub Issueに対してCoding Agentを利用します。Sub Issueの内容は具体的に且つ簡潔に箇条書きで記載しましょう。 このように簡潔で単純なタスクの集合体であるSub Issueを幾つも作成し、それに対してCopilotを担当者として指定することで、Copilotが自律的にタスクを実行し、Pull requestを作成してくれます。 Issueを作ってCopilotを担当者に設定するだけでPull requestが作成されるので、並行して複数のPull requestを作成してもらえることも強みの1つです。エンジニアはIssueを作って、担当者にCopilotを指定して、作成されたPull requestをレビューするだけです。 Coding AgentがPull requestを作成している間に、自分はローカル環境で別の作業をやっているのは、今では当たり前の光景になってきています。 まとめ いかがでしたでしょうか? 今回紹介した機能はGitHub Copilotの機能のほんの一部であり、今回は特に重要な機能に絞って紹介しました。 カスタムインストラクションを整備しつつ、MCPを活用することが、GitHub Copilotを始めとする生成AIを効率的に活用するための最初の一歩です。 その上で、Agent modeやCoding Agentを活用することで、より自律的にタスクを実行してもらい、開発の効率化を図ることが可能になり、エンジニア自身は他の作業に集中することが出来るようになります。 生成AIを活用した開発フローに変化していく上で、生成AIが出力したコードが正しいかどうかを判断するスキルが非常に重要になってきました。 この判断するスキルは基礎と経験によって培われるものであり、今まで以上に基礎力が重要になってきていると感じています。弊社でもエンジニアとしての基礎力を重要視しており、これを強化するための取り組みも幾つか行っていますが、それはまた別の機会で紹介したいと思います。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから herp.careers
こんにちは! Findy Team+ 開発チームでEMをしている ham です。 Findy Team+のバックエンドはRuby on Railsで開発しており、Rubyの静的解析ツールとして広く知られているRubocopをTeam+の開発でも積極的に活用しています。 ファインディでは「爆速開発」を掲げており、開発速度に直結するCI(継続的インテグレーション)の実行時間を非常に重視しています。具体的には、CIの実行時間は遅くとも10分以内、理想としては5分以内に完了することを目標にしています。 CIの実行時間短縮に向けた取り組みについては、以前公開した次の記事で詳しくご紹介していますので、ぜひご覧ください。 tech.findy.co.jp 今回、バックエンドのCIの実行時間を見直したところ、Rubocopの実行時間が5分以上かかっていることに気づきました。これは改善の余地があると感じ、実行時間短縮に取り組むことを決めました。 また、CIではRubocopの他にRSpecでテストを実行しているのですが、RSpecの実行時間の方がRubocopよりも圧倒的に長いためそちらの改善ばかりに気を取られて、Rubocopの実行時間は見過ごされていました。 なお、この時もテストは7分ほどかかっておりRubocopより長かったですが、こちらは並列実行と実行環境のスペックアップを駆使することで3分程度まで短縮できました。 そこで、今回はRubocopの実行時間短縮に取り組むことを決意し、その結果、5分以上かかっていた実行時間を1分未満に短縮できました! なぜRubocopの実行時間が長かったのか? CIにおけるRubocopの実行は、基本的に全てのRubyファイルに対して無条件に実行されていました。 そのため、プロジェクトの規模が拡大するにつれて、解析対象となるファイル数も増加し、比例して実行時間も伸びていったのが主な原因です。 改善内容 実行時間短縮のために、次の3つの変更を加えました。 無条件で全ファイル解析していたが、編集したファイルだけ対象とする Gitの差分情報を用いて、変更があったファイルのみをRubocopの解析対象とするようにしました。これにより、CIの実行ごとに解析するファイル数を大幅に削減できました。 ファインディではGitHub Actionsを使ってCIを実行しているため変更したファイルを取得できる tj-actions/changed-files を活用して対象ファイルを取得しました。 設定ファイルやGemがアップデートされたときは全て解析 前述の変更により通常時は変更ファイルのみを対象としますが、Rubocopの設定ファイル(.rubocop.ymlなど)やRubocop本体や関連Gemのバージョンがアップデートされた場合は全てのファイルを解析するようにしました。 これは、設定変更やバージョンアップによって、これまで問題なかった箇所が新たに指摘される可能性があるため、CIの信頼性を保つ上で重要な対応です。 ファイル指定だと除外設定が無視されたので無視されないように変更 Rubocopには、コマンド引数に対象ファイルを明示的に指定すると、.rubocop.ymlで指定されている除外設定(Exclude)が無視されるという仕様があり、本来は解析対象外のファイルまで解析されてしまうという問題が発生しました。 これを解決するため、 --force-exclusion オプションを利用できることがわかりました。こちらのオプションを指定することで対象ファイルを明示的に指定した場合でも除外設定が反映されるようになります。 bundle exec rubocop -f github --force-exclusion ${{ all_changed_files }} 結果 これらの改善を適用した結果、5分以上かかっていたRubocopの実行時間は1分未満にまで劇的に短縮されました! これにより、CI全体の実行時間が短縮され、開発者はより素早くフィードバックを得られるようになりました。Rubocopの指摘への対応も迅速に行えるようになり、コードの品質維持にも貢献しています。 まとめ CIにおける静的解析の実行時間は、テスト実行時間に比べると見過ごされがちですが、積み重なると開発体験を損なう要因となります。 今回のRubocopの実行時間短縮で行った次の対応は、実装難易度も低く簡単にできるものでしたが、大きな効果をもたらしてくれました。 無条件で全ファイル解析していたが、編集したファイルだけ対象とする 設定ファイルやGemがアップデートされたときは全て解析 ファイル指定だと除外設定が無視されたので無視されないように変更 もしあなたのプロジェクトでもCIのRubocop実行時間が長いと感じているのであれば、本ブログで紹介した内容が少しでも参考になれば幸いです。変更ファイルのみを対象とする工夫は、他の静的解析ツールにも応用できる可能性がありますので、ぜひ検討してみてください。 ファインディでは一緒に働くメンバーも絶賛募集中です。興味がある方はぜひこちらから ↓ herp.careers
こんにちは、ファインディでソフトウェアエンジニアをしている nipe0324 です。 先日、AWSさんの Coding Agent at Loft #2 〜 AI コーディング活用事例 Night - 効果的な組織導入と実践〜 (第2回目) で登壇させていただき、登壇内容を記事として書き起こしました。 この記事では、Devinと協働して 「個人のアウトプットを1.5倍にした実践3ステップ」 をご紹介します。 Devinと協働して個人のアウトプットは1.5倍に増加 2025年5月末時点では、Copilot Coding Agent、Codex、Jules などのリリースが続々とされており、自律型のコーディングエージェントが盛り上がってきています。 Devinに特化せず他のコーディングエージェントでも使える内容になっていますので、 自律型のコーディングエージェントの利活用に興味ある方 はご一読くださいませ。 ちなみに、生成AI界隈は動きが早いので、数ヶ月後はどうなるかわかりません。また、現時点での業務で試した結果の1事例として参考にしてください。 はじめに Devinと協働してアウトプットを1.5倍にした3ステップ ステップ1. Devinに教える 1-1. 小さなタスクから始める 1-2. Devinに開発のルールを教えていく ステップ2. Devinに慣れる 2-1. Devinのドキュメントを読む 2-2. 試行錯誤して勘所を掴む 2-3. Knowledgeを洗練させる 2-4. AI Friendlyな環境を整備する ステップ3. Devinと協働する 3-1. Devinに定型作業を任せる 3-2. Devinと一緒にタスクを進める 3-3. Devinにサブタスクを任せる おまけ: Devinの活用Tips Tips1. GitHub/AWSアカウント管理のワークフローを自動化 Tips2. 口調を変えるKnowledgeで親しみやすくする Tips3. PMが仕様把握のためにDevin Searchを利用 Tips4. AI駆動な仮実装 Devinに対する所感や協働して変わってきたこと まとめ はじめに Microsoftさんの最近の研究では、組織がAIトランスフォーメーションをしていくためには、次の3つのフェーズがあるようです。 Phase 1 Human with assistant :AIがアシスタントする Phase 2 Human-agent teams :エージェントがチームにジョインして、同僚として一緒に働く Phase 3 Human-led, agent-operated :人間がディレクションをして、エージェントが業務を遂行する。必要があれば人がチェックする AI Transformationの3段階(引用元: https://www.microsoft.com/en-us/worklab/work-trend-index/2025-the-year-the-frontier-firm-is-born ) その中で、今回の話はこの 「Phase2 エージェントと一緒に働く」 をトライしている話になります。 Devinと協働してアウトプットを1.5倍にした3ステップ ステップとしては次の3ステップで進めていきました。期間はDevinの導入から大体3ヶ月ぐらいかけて実施していきました。 ステップ1. Devinに「教える」 ステップ2. Devinに「慣れる」 ステップ3. Devinと「協働する」 個人的なポイントとしては、ステップ3までいくと、 コーディングエージェントの良さを感じ、日々のアウトプットをスケールしていけるという実感 をもてました。 ステップ1. Devinに教える 最初のステップは「Devinに教える」です。 Devinに小さなタスクを依頼しながら基本的な開発ルールを教えていくことで、 Devinが軽微な修正をそつなくこなせる ようになります。 1-1. 小さなタスクから始める まずは、文言変更や軽微なタスクを依頼してDevinの動きを知ります。 実際にDevinが開発している画面をみながら、Devinの開発環境・作業手順・やりとり方法などを押さえることで今後のDevinとのやりとりの土台をつくれます。 DevinとやりとりするWeb画面 アンチパターンとして、エージェントへの期待値が高すぎることで、最初から「急ぎのタスク」や「大きめなタスク」を依頼し精度がでなく幻滅してしまうことがあります。 人と同じで小さなタスクから開発に慣れてもらうことが大切です。Devinはチームに入った新人だと思い、焦らずまずは文言変更やドキュメント修正など小さなタスクから依頼していくことをオススメします。 1-2. Devinに開発のルールを教えていく 開発のルールは、会社やプロジェクトごとに違います。そのため、Devinに小さなタスクをお願いしながら開発ルールを教えていきます。 Devinには Knowledge という機能があります。Devinとの会話からルールをほぼ自動的に学び、Knowledgeとして保存することで、次回以降のタスク精度が高まります。 以下は、実際にDevinが学んだ開発ルールのKnowledgeの一部です。 ブランチ作成、PR作成、コミット作成、テスト実行など基本的な開発ルールをKnowledgeとしてDevinに学んでもらいました。 実際に学んだ開発ルールのKnowledge(抜粋) ステップ2. Devinに慣れる 次のステップとして、「Devinに慣れる」です。 Devinのドキュメントを読みながら、試行錯誤して依頼の勘所を掴みます。また、Knowledgeを洗練させ、AI Friendlyな環境を整えることで、 Devinがよくあるタスクで90点以上のタスク精度を実現できる ようになります。 2-1. Devinのドキュメントを読む Devin の Documentationの Essential Guidelines は必読です。Devinにうまく依頼するための重要なプラクティスが記載されています。 例えば、次のような内容が記載されています。 Devinは「ジュニアエンジニア」として扱うのが最適です。明確で十分な指示があれば、インターンや新人エンジニアが対応可能なタスクを任せることができます。 ベストプラクティス: 小さなタスクを並行して実行 :朝の始まりに複数の小さなタスクをDevinに割り当て、昼食時にレビューを行うと効率的です。 Slackでの迅速な対応 :Devinは30分程度で完了するタスクに適しており、長期間放置されがちなバックログの解消に役立ちます。 明確な成功基準のあるタスクに集中 :CIのパス確認や自動デプロイのテストなど、結果が明確に確認できるタスクが理想的です。 小さく始める :Devinの性能は長時間のセッション(≒10 ACU以上)で低下する可能性があるため、小規模なタスクから始めることを推奨します。 引用元: https://docs.devin.ai/essential-guidelines/when-to-use-devin の英語を翻訳 2-2. 試行錯誤して勘所を掴む Devinに様々なタスクを依頼しながら、依頼内容、依頼方法、タスク粒度の勘所を掴んでいきます。また、Devinのドキュメントを読んで学んだことを試しながら、より良い協働方法を模索していきます。 例えば、変数で指示をすることで汎用的なプロンプトを作成する、どの程度までの抽象的な指示ならタスクを遂行してもらえるか確認するなど試してみました。 そして、試行錯誤した結果、Linter対応や横展開系の対応、FeatureFlagの追加・削除、管理画面の軽微な改修、簡易なSentryのアラート対応などの定型作業は、ほぼ90点以上の精度でプルリクエストを作成できました。 Tipsとして、Devinの作成したプルリクエストの精度がいまいちなときは、Devinの設定画面で「Devinは承認を待たずに進める」のチェックをオフにするがおすすめです。複雑なタスクの場合、Devinの作業計画を承認してから作業を進めることができるので、作業計画段階で早めに方向性のすり合わせができ、「プルリクエストが出来上がった後のこれじゃない感」を大幅に減らせます。 「Devinは承認を待たずに進める」のチェックをオフにする 2-3. Knowledgeを洗練させる Devinとの試行錯誤を通しながら、DevinのKnowledgeのバリエーションを増やしていきます。 例えば、テーブルを扱う変更やビジネスロジックの作成、APIの実装、ドキュメンテーションの追加など、さまざまなケースのKnowledgeが溜まっていきます。 これにより、より多くのタスクを精度よく任せられるようになります。 しかし、KnowledgeがあってもDevinがその内容通りに動かないこともあります。 そのような場合は、うまくいかなかったやりとりをもとに「今回のやりとりを次回以降で活かすためにKnowledgeを更新して」と伝え根気強くKnowledgeを更新します。 それでも駄目なら、初期の依頼プロンプトに内容を盛り込んだり、現状のLLMの限界として諦めています。 2-4. AI Friendlyな環境を整備する 単純にDevinに頑張ってもらうだけでなく、AIが開発をしやすいコードベースや開発環境を整備することも大事です。 個人的に、AI Friendlyな環境として以下3つは特に重要だと考えています。 自動テスト、Linter、CIは必須 :Devin自身でフィードバックループが回せなくなるので作業の精度が下がります。また、レビュアーのレビュー時のガードレールにもなるので必須です。 コードの統一や暗黙のルールを明文化 :既存の実装を踏襲してもらうとDevinのタスク精度が高くなります。コードベース上で同じ目的のためにいろんな実装方式があるとDevinが迷ってしまうので、コードの統一感を高めています。また、暗黙知も明文化してKnowledgeとして教えます。 場合によっては開発ルールを変更する :Devinに何度伝えてもうまく対応できないことがあったので、ルールを変更しました。具体的には、コミットメッセージの文字数のルールを守れなかったため、開発ルールとしての制限を緩めることで対応しました。 ステップ3. Devinと協働する ここまででDevinへの依頼に慣れて、ある程度の難易度のタスクならほぼ満足できるようになってきます。 最後のステップでは、Devinに定型作業を任せたり、一緒にタスクを進めたりすることで、 個人のアウトプットを増加 させていきます。 3-1. Devinに定型作業を任せる 「これは9割以上の精度でDevinに任せられる」というタスクはDevinに任せていきます。定型作業のようなものは、ほぼ完璧にプルリクエストを仕上げてくれます。 最近では、個人のAIエージェントとの協働を通じてマインドも変化してきました。ある程度定型化されたタスクは「Devinに任せれば良さそう」いう考えになってきています。 例えば、軽微な修正やFeatureFlagの追加・削除、モデル作成、マイグレーションファイル作成、管理画面の簡易な対応などはDevinに任せて、その間に自分はDevinができない作業を進めることが多くなりました。 3-2. Devinと一緒にタスクを進める Devinは、CursorやClineなどローカルマシンで実行するエージェントに比べて相対的に作業時間は長くなります。しかし、タスクを分担して連携して開発できれば、大きな問題にはならないと考えています。 私がよく実施する「Devinと一緒にタスクを進める方法」は主に2つです。 よくあるDevinと一緒にタスクを進める方法 パターン①:タスクを分解し、Devinがメインで開発を担当し、難しい部分やレビューを自分が行う パターン②:横展開系のタスクで、最初の実装イメージは自分が作成し、その後の横展開はDevinに並列で実装を任せ、レビューを自分が行う 3-3. Devinにサブタスクを任せる たまに、メインでないサブタスクを裏でDevinに丸っと依頼して作ってもらうことをします。 Devinの公開APIを利用した自前ワークフローツール(※Roo Codeの Boomerang Tasks の簡易版のようなもの)を作成し、一連の依存関係のあるタスクリストをワークフローツールで実行しています。 これにより、1〜2時間ほどで一通りの対応(5〜8プルリクエスト)をDevinに実装してもらうことが可能になりました。 タスクの定義例。依存関係にそってタスクを実行してくれる 課題としては、個々のタスク精度にはまだ伸びしろがあります。また、メインタスクとサブタスクを頻繁に切り替える必要もでてくるため、かなり疲れることもあります。 改善案として、レビューの一部をエージェント化したり、ワークフローのオーケストレーターやタスク出しをエージェント化したりすることで、より丸ごと任せられるか試してみたいと考えています。 おまけ: Devinの活用Tips 最後におまけとして、Devinの活用Tipsをいくつかご紹介します。 Tips1. GitHub/AWSアカウント管理のワークフローを自動化 SREチームでは、SlackワークフローとDevinを組み合わせてGitHubとAWSのアカウント管理をほぼ自動化しています。 SlackワークフローでDevinに依頼 流れとしては次のとおりです。 前提として、Terraformでアカウント管理をしている。 Slackのワークフローで依頼をすると、@Devinメンションでワークフロー内容が記載される。 Devinが反応してアカウント管理(追加・更新・削除)のプルリクエストを作る。 SREがプルリクエストをレビューをする。修正がある場合プルリクエスト上でコメントをするとDevinが修正してくれる。 SREがプルリクエストをマージすると、Terraformによりアカウントが追加・更新・削除される。 SREの方に効果を聞いたところ、月末月初などユーザー申請の対応が五月雨にあり地味に時間がかかっていた工数が 感覚値で1日程度削減 できたようです。 Devinには、Slackからタスクを依頼をできる機能があるので、Slackのワークフローとの接続がとても簡単にできるところはいいところだと思っています。 Tips2. 口調を変えるKnowledgeで親しみやすくする DevinのKnowledgeで口調を指定することで、エンジニアがDevinに親しみを感じやすくしています。 Devinはデフォルトだと割とかしこまった感じの口調なのですが、Knowledgeを指定することで砕けた感じの会話ができるようになり、チームとDevinの親近感が醸成されました。(たぶん...) Devinの口調を変えるKnowledgeとDevinとのやりとり 実用的な観点ではDevinが Knowledge をどのぐらい理解して作業をするかを日々検証できるというメリットもあると思っています。 Tips3. PMが仕様把握のためにDevin Searchを利用 Devinには、コーディングだけでなくDevin Searchという自然言語で質問をして回答を得られる機能があります。現在はβ板なので無料で利用できます。 Devin Searchで仕様を確認 実際にPMからメール送信の条件に対する質問をされ、Devin Searchで検索したら100点の回答が得られました。 そのため、PMにDevinのアカウントを発行して、詳細の仕様が気になる場合はDevinに聞いてもらうという取り組みをしました。 Tips4. AI駆動な仮実装 まだ試行錯誤段階ですが、Devinをフル活用して、仮実装を感覚値で2~3日想定が1日で完了しました。また、仮実装を通して設計やコードの解像度が高まり、「実現性の検証」や「改善点の発見」を短期間で実現できました。 仮実装の流れは次のように進めました。 Devin Wikiで新しいリポジトリの主要機能や設計を把握 Devin Searchで影響範囲を設計とコードレベルで把握 Devin に大きめなタスクを渡して仮実装 Cursorを使いながら仮実装の細部を修正して動くようにする ある程度頭の中に設計イメージがあり、そのイメージをDevinに伝えて設計をしてもらい、仮実装を進めていくことで素早く検証を進めることができました。(※もちろん仮実装のコードは捨てて、本実装時に細部も含めてちゃんと作り込みます) Devinに対する所感や協働して変わってきたこと Devinとうまく協働することで、いままではチームのエンジニアが5~6名ぐらいだったのが、3名前後でも同程度のアウトプットをだせるようになっていきそうな感覚を受けています。 しかし、足元少しずつ顕在化しはじめているのですが、より少人数のチームでプルリクエストの数が増えているのでチームのレビュー負荷が高まっています。 具体的な解決策のアイデアはまだないですが、レビューのあり方をよりAI駆動によせていく必要があると思っています。 また、Devinと協働する中で個人の動きも少しずつ変わっています。 ミーティングが多くなってしまった日でも、Devinに実装をお願いすることで想定の進捗どおりに開発できた 一部のプロダクトマネジメント業務やデータ分析など業務の幅が広がった 生成AIの進歩は早いですが、新しい技術に一喜一憂しながら、楽しんでいこうと思っています。 まとめ 今回の記事では、 「Devinと3ヶ月協働して個人のアウトプットを1.5倍にした3ステップ」 についてご紹介しました。 Devinと協働する3ステップは次のとおりです。 ステップ1. Devinに教える :小さなタスクからはじめ、開発ルールを教える。 ステップ2. Devinに慣れる :Devinのドキュメントを読みながら試行錯誤をする。また、Knowledge拡充やAI Friendlyな環境を整備する。 ステップ3. Devinと協働する :Devinに定型作業を任せる。Devinと一緒にタスクを進める。Devinにサブタスクを全て任せる。 今後は次のようなことにトライしていきたいと考えています。 個人のアウトプット向上から、チームや組織のアウトプット増加につなげていきたい Devinに任せられる範囲を増やし、AI駆動開発をより推進したい また、セキュリティなどには気をつけつつも、DevinにとらわれずCopilot Coding Agent, Claude Code + GitHub Actionsなどいろいろと試しながら、より開発組織のスピードと品質を向上させていきたいと考えています。 ファインディでは生成AIやAIエージェントを試して開発生産性を高めることで、ユーザーにより価値を届けることを推進しています。 こうした新しい技術の利活用に興味がある方は、ぜひカジュアル面談にお越しくださいませ。 herp.careers
はじめに 皆さんこんにちは。ファインディに転職してまもなく1年を迎える、CTO室/SREチームの安達( @adachin0817 )です。今回は複数のWordPressサイトをShifterへ移行しましたので、その取り組みについてご紹介します。 Shifterとは ja.getshifter.io Shifterは、WordPressサイトを静的に変換・ホスティングできるマネージドサービスです。動的に動作するWordPressをShifterがビルドし、生成されたHTML/CSS/JavaScriptの静的ファイルをCDN経由で配信する構成となっています。主なメリットは次のとおりです。 セキュリティ強化:PHP実行環境を持たないため、WordPress本体やプラグインの脆弱性リスクが激減。 運用負荷の軽減:インフラやWordPressのバージョンアップ管理が不要。 表示速度の高速化:静的ファイルをCDN 経由で高速配信できるため、ユーザー体験の向上が期待。 自動バックアップ・簡単ロールバック:管理画面から任意のタイミングで復元可能。 Shifterに移行する背景 旧構成図 元々はAmazon Lightsail上の単一サーバーで複数のサイトを運用しており、画像ファイルやデータベースもすべて同一のインスタンス上で管理されていました。コーポレートサイト以外はPHPやプラグインのバージョン管理が行われておらず、明確な運用者もいなかったため、誰がメンテナンスしているのか分からない状況が続いていました。 また、コーポレートサイトに関しては情報システムチームが毎週のようにセキュリティアップデートを対応する必要があり、テーマのデプロイも自動化されておらず手動で行っていたため、運用負担が大きいという課題を抱えていました。 こうした背景に加え、会社全体でも定期的なバージョンアップ対応やセキュリティ強化に十分なリソースを確保することが難しく、改善が急務となっていました。そのような中、2024年に全社的な信頼性向上を目的として横断SREチームが発足しました。SREチームでは属人化していたWordPress環境を集約・統制することで、信頼性の向上を目指す取り組みが始まりました。 その解決策としてマネージドサービスへの移行を検討し、上記のメリットとコストが比較的安価のため、最終的にShifterを採用しました。次は、ローカル開発環境についてご紹介していきます。 開発環境の構築 ローカル開発環境では、コーポレートサイト以外の開発環境が整っていなかったため、Dockerを使って1から構築し直すことにしました。リポジトリ構成としては、WordPress本体をwordpress-coreリポジトリ(仮)で一元管理し、各サービスのテーマは個別のリポジトリで管理する方式を採用しました。これは、すべてを単一リポジトリに集約すると容量の肥大化や管理の複雑さを招くためです。 ※以下仮としています compose.yml ❯❯ cat docker-compose.yml volumes: php-fpm-sock: services: wp-nginx: container_name: wp-nginx build: docker/dev/nginx/ image: wp-nginx ports: - '80:80' - '443:443' volumes: - ./wordpress-core:/var/www/wp:delegated - ./site-corporate:/var/www/wp/corporate/wp-content/themes/site-corporate:delegated - ./site-enterprise01:/var/www/wp/enterprise01/wp-content/themes/site-enterprise01:delegated - ./site-enterprise02:/var/www/wp/enterprise02/enterprise/wp-content/themes/site-enterprise02:delegated - ./site-blog:/var/www/wp/blog/wp-content/themes/site-blog:delegated - php-fpm-sock:/var/run/php-fpm tty: true depends_on: - wp-app wp-app: container_name: wp-app build: docker/dev/app image: wp-app volumes: - ./wordpress-core:/var/www/wp:delegated - ./site-corporate:/var/www/wp/corporate/wp-content/themes/site-corporate:delegated - ./site-enterprise01:/var/www/wp/enterprise01/wp-content/themes/site-enterprise01:delegated - ./site-enterprise02:/var/www/wp/enterprise02/enterprise/wp-content/themes/site-enterprise02:delegated - ./site-blog:/var/www/wp/blog/wp-content/themes/site-blog:delegated - php-fpm-sock:/var/run/php-fpm tty: true depends_on: - wp-db wp-db: container_name: wp-db build: docker/dev/mysql image: wp-db command: --default-authentication-plugin=mysql_native_password ports: - '33066:3306' volumes: - ./mysql/db_data:/var/lib/mysql - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql ShifterがPHP 8.1に対応していることから、Appコンテナ・Nginxコンテナ・MySQLコンテナも同じバージョンに揃えて構成しました。WordPressのバージョンや依存パッケージに差異があると、静的化後に想定外の動作になる恐れがあるためです。Shifterでは開発用のDocker環境も用意されていますが、できる限り本番と同等の構成になるよう意識して環境を整備しました。 さらに、Justfileを導入することで、hosts登録やmkcertによる自己署名SSL証明書発行、S3からのDBダンプ取得などのセットアップを自動化しました。複雑だった開発環境の構築手順が、今では just all コマンドを実行すれば素早く構築できるようになりました。ただ、運用していく中で、開発環境自体のバージョンアップもしなければなりませんが、今後GitHub Actionsで自動化していきたいと思っています。 Justfile 開発用ドメイン設定 リポジトリのclone mkcertの実行 wp-config.phpのコピー Docker Composeの起動から停止 DBのリストア setup-hosts: for hosts in "127.0.0.1 dev.site.co.jp" "127.0.0.1 dev.site.co.com" "127.0.0.1 dev-site2.com" "127.0.0.1 dev-site3.com"; do \ if ! grep -q "$hosts" /etc/hosts; then \ sudo bash -c "echo '$hosts' >> /etc/hosts"; \ fi; \ done setup-mkcert: cd ~/www/wordpress-core && \ brew install mkcert && \ mkcert -install && \ mkdir -p docker/dev/nginx/cert && \ cd docker/dev/nginx/cert && \ mkcert "*.hoge.co.jp" clone-repos: @echo "Cloning repositories..." repos="site-corporate site-blog site-enterprise01 site-enterprise02"; \ for repo in $repos; do \ dir="$HOME/www/$repo"; \ url="git@github.com:hoge/$repo.git"; \ if [ ! -d "$dir" ]; then \ git clone --depth 1 "$url" "$dir"; \ echo "Cloned $repo repository."; \ else \ echo "$repo repository already exists. Pulling latest changes."; \ cd "$dir" && git pull origin main; \ fi; \ done copy-wp-config: for dir in "corporate" "site-blog/blog" "site-enterprise01/enterprise01" "site-enterprise02/enterprise02"; do \ cd ~/www/wordpress-core/$dir && cp wp-config-dev.php wp-config.php; \ done start-docker: docker-compose up -d stop-docker: docker-compose stop down-docker: docker-compose down restore-db profile: rm -rf ./db_dumps aws --profile={{profile}} s3 cp s3://hoge/dev/MySQL/ ./db_dumps --recursive --exclude "*" --include "*.sql" for file in ./db_dumps/*.sql; do \ db_name=$(basename "$file" .sql); \ echo "Copying $file to wp-db container"; \ docker cp "$file" wp-db:/tmp/$(basename "$file"); \ echo "Dropping and creating $db_name"; \ docker exec wp-db mysql -u root -e "DROP DATABASE IF EXISTS \`$db_name\`; CREATE DATABASE \`$db_name\`;"; \ echo "Restoring $db_name from /tmp/$(basename "$file")"; \ docker exec wp-db sh -c "mysql -u root $db_name < /tmp/$(basename "$file")"; \ echo "Cleaning up /tmp/$(basename "$file") from wp-db container"; \ docker exec wp-db rm "/tmp/$(basename "$file")"; \ done rm -rf ./db_dumps all profile: just setup-hosts just clone-repos just copy-wp-config just start-docker just restore-db {{profile}} Shifter移行とトラブルシューティング Shifterへの移行にあたっては、公式ドキュメントにも記載されているとおり、All-in-One WP Migrationプラグインを使ったエクスポート・インポート方式が推奨されています。この方法を使えば、WordPressサイトを簡単に丸ごと移行できるのが大きなメリットです。実際に試してみたところ、基本的な移行作業はスムーズに完了しましたが、いくつか想定外の不具合も発生しました。以下にその内容を共有します。 独自テーマのページネーションが正しく動作しない コーポレートサイトのページネーションが正しく機能しないという事象が発生しました。Shifterでは、静的サイトを生成する際にWordPress REST API を通じて対象のURL一覧(JSON形式)を取得し、それをもとに静的化を行います。しかしながら、WordPressのアーカイブページのページネーションはデフォルト設定のままだと検出されず、静的化の対象から漏れてしまうことがあります。この問題に対しては、Shifterが提供する ShifterURLS::AppendURLtoAll を使うことで、手動で静的化対象のURLを追加が可能です。次のようにfunctions.phpに追加し、ページネーションURLを明示的に含めることで対応しました。 function.php function my_append_urls( $urls ) { $limit = get_option('posts_per_page'); $args = array( 'post_type' = > 'post', 'post_status' = > 'publish', 'posts_per_page' = > -1, 'fields' = > 'ids', 'no_found_rows' = > true, ); $the_query = new WP_Query($args); if ($the_query- > have_posts()) { $last_page = ceil(count($the_query- > posts) / $limit); for ($i = 2; $i <= $last_page; $i++) { $urls[] = home_url('/news/page/' . $i . '/' ); } } return $urls; } add_action( 'init' , function(){ add_filter( 'ShifterURLS::AppendURLtoAll' , 'my_append_urls' ); } ); 一部画像が表示されない All-in-One WP Migrationを使った移行ではスムーズに進みましたが、日本語ファイル名の画像が表示されないという問題が発生しました。Shifterへの移行後、原因を調査したところ、画像ファイル名が日本語の場合に限って読み込めないというバグを確認できました。数枚ほどだったので、対象のファイルを手動でリネームし、再アップロードをする必要がありました。 サブディレクトリでシェアボタンがShifterの仮ドメインになってしまう 既にCloudFrontにカスタムドメインが設定されている場合、Shifter 側のCDNに同じカスタムドメインを適用できません。このようなケースでは、Shifterで生成された静的コンテンツのみを対象に、CloudFront経由でカスタムドメイン配下のサブディレクトリに公開する必要があります。 /blog のようにサブディレクトリでの公開が必要な場合、 shifter-cli を使って --no-shifter-cdn オプションを指定することで、ShifterのCDN配信を無効化し、自前のCloudFront経由でのホスティングが可能になります。 CloudFrontのオリジンドメインにShifterが提供するCloudFront URLを指定し、キャッシュポリシーを無効化に設定することで、Shifterで生成された静的サイトをそのまま公開できます。最後にShifterでデプロイを実行することで、シェアボタンやOGPのリンク先にShifterの仮ドメインが含まれることはなくなりました。 ドメイン紐づけ $ npm install -g @shifter/cli $ shifter domain:attach --username hoge --password hoge --site-id hoge --domain hoge.com --no-shifter-cdn terraform/cloudfront.tf data "aws_cloudfront_cache_policy" "caching_disabled" { name = "Managed-CachingDisabled" } resource "aws_cloudfront_distribution" "hoge" { provider = aws.us-east-1 origin { domain_name = "hoge.cloudfront.net" origin_id = "blog" origin_path = "" custom_origin_config { http_port = 80 https_port = 443 origin_protocol_policy = "https-only" origin_ssl_protocols = [ "TLSv1.2" ] } ordered_cache_behavior { allowed_methods = [ "DELETE" , "GET" , "HEAD" , "OPTIONS" , "PATCH" , "POST" , "PUT" ] cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id cached_methods = [ "GET" , "HEAD" ] compress = true path_pattern = "blog/*" target_origin_id = "blog" viewer_protocol_policy = "https-only" } ordered_cache_behavior { allowed_methods = [ "DELETE" , "GET" , "HEAD" , "OPTIONS" , "PATCH" , "POST" , "PUT" ] cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id cached_methods = [ "GET" , "HEAD" ] compress = true path_pattern = "blog/" target_origin_id = "blog" viewer_protocol_policy = "https-only" } } これらトラブルシューティングを解決したことにより、次はテーマのデプロイ方法について説明したいと思います。 Shifter Github Plugin/Theme Installedでのテーマデプロイ https://github.com/getshifter/shifter-github ShifterではGitHub経由でテーマをデプロイするための公式プラグイン「Shifter GitHub Plugin/Theme Installed」が提供されています。このプラグインを利用することで、次の手順でテーマの更新が可能になります。 テーマをgit tagでバージョン付け git pushでタグを反映 テーマ一式を .zip に圧縮し、GitHubの Releases にアップロード Shifter側で該当リリースの.zip を取得し、テーマを最新化 もともとは複数のテーマをモノレポで管理しようとしていましたが、Shifterの仕様上、1テーマ、1プロジェクト(単一リポジトリ)が前提となります。さらに、GitHub Actionsを活用してリリースの自動化も実装しており、手動作業を減らして運用効率を向上させました。 github/workflows/release.yaml name : Tag and Release on : push : branches : [ main ] jobs : tag-and-release : name : Tag and Release runs-on : ubuntu-latest permissions : contents : write defaults : run : working-directory : "./" steps : - uses : actions/checkout@v4 - name : Fetch tags run : git fetch --tags - name : Get latest tag id : get_latest_tag run : | TAG=$(git tag --sort=-v:refname | head -n 1 || echo "0.0.0" ) echo "Latest tag: $TAG" echo "latest_tag=$TAG" >> $GITHUB_ENV - name : Calculate next tag id : calculate_next_tag run : | IFS='.' read -r MAJOR MINOR PATCH <<< "${{ env.latest_tag }}" NEXT_TAG="$MAJOR.$MINOR.$((PATCH+1))" echo "Next tag: $NEXT_TAG" echo "next_tag=$NEXT_TAG" >> $GITHUB_ENV - name : Create new tag run : | git tag ${{ env.next_tag }} git push origin ${{ env.next_tag }} - name : create archive env : PACKAGE_NAME : "hoge-theme" FILES_TO_ARCHIVE : "*" run : | sed -i -e "s/{release version}/${{ env.next_tag }}/g" ./style.css zip -r ${PACKAGE_NAME}.zip ${FILES_TO_ARCHIVE} - name : Upload to GitHub Release env : PACKAGE_NAME : "hoge-theme" GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} GOPATH : /home/runner/go run : | go install github.com/tcnksm/ghr@latest ${GOPATH}/bin/ghr \ -b "Release ${{ env.next_tag }}" \ -replace \ "${{ env.next_tag }}" \ "${PACKAGE_NAME}.zip" style.css Version: { release version } 現在の運用体制について Shifterのアカウント管理は情報システムチームが担当し、テーマの修正はエンジニアやSREチームが対応しています。また、記事の公開やコンテンツの更新は広報チームやマーケティングチームが行っており、各チームの役割が明確に分担されるようになりました。 移行してみて Shifter導入によって、SREチームだけでなく非エンジニアのメンバーでも運用できる環境が整いました。Shifterのダッシュボードはシンプルで直感的に操作でき、バックアップの復元も簡単です。また、静的ファイル化によりPHPの脆弱性リスクが排除され、HTMLとCSSのみで構成されることでセキュリティ面でも安心できるようになりました。さらに、CDNが標準で組み込まれているため、パフォーマンスの向上も実感しています。一方で気になったところは記事をリリースするまで、毎回Shifter側で静的化デプロイをしなければならないので、反映までに時間がかかるといったところです。 さらに、1つのShifterアカウントで複数のサイトを一元管理できる点も大きなメリットです。以前はサイトごとにユーザーアカウントを発行していたため管理が煩雑でしたが、現在は運用効率が大幅に向上し、ユーザー棚卸しも簡単になりました。また、デジタルキューブ様の導入事例でも紹介していただきましたので、ぜひご覧ください。 ja.getshifter.io まとめ 長らく技術的負債となっていたWordPress環境でしたが、SREチームを中心にShifterへの移行を進めたことで、信頼性の向上と一元管理を実現できました。自分自身、初めてShifterを導入するにあたり、静的化に伴う挙動の違いなど、試行錯誤する場面も多く苦労しました。しかし、今では導入して本当に良かったと感じています。今後は新たなメディアを立ち上げる際もShifterを利用し、SREチームを通じた管理フローを社内で徹底していきたいと思っています。 最後まで読んでいただきありがとうございました。SREチームは絶賛募集しているので、カジュアル面談ぜひお待ちしております!🙏 herp.careers 最後に aws.amazon.com AWS Summit Japan 2025で登壇することになりました!Security LakeとAIの活用についてお話します!6/26(木) 12:40~行いますので、ご都合合う方はぜひご参加をお待ちしております!
こんにちは。Findy Tech Blog編集長の高橋(@Taka_bow)です。 本記事は「 エンジニア達の人生を変えた一冊 」シリーズの第4弾となります。エンジニアとしてのキャリアや技術的な視点に大きな影響を与えた一冊とは?それぞれの思い入れのある本から、技術への向き合い方や成長の軌跡が垣間見えるかもしれません。 今回は佐藤さん、中村さん、甲斐さんの3名のエンジニアに、人生を変えた一冊を紹介していただきます。 まずはファインディのテクノロジーを統括するCTO佐藤さんからです!幅広い知見を持つ佐藤さんが、エンジニアとしての原点となった一冊とは?大学時代に出会った運命の本が、その後のキャリアをどう形作ったのでしょうか。 ■ 佐藤将高さん / CTO ■ ファインディ株式会社のCTOを務めています。トップバッターを務めさせていただきます! コンピュータの構成と設計 コンピュータの構成と設計 MIPS Edition 第6版 上 作者: David Patterson , John Hennessy 日経BP Amazon コンピュータの構成と設計 MIPS Editoin 第6版 下 作者: David Patterson , John Hennessy 日経BP Amazon コンピュータの構成と設計 作者: デイビッド・A・パターソン、ジョン・L・ヘネシー 出版社: 日経BP Amazon: 第6版 上 、 第6版 下 私が紹介する「コンピュータの構成と設計」は、コンピュータアーキテクチャの基礎から応用までを体系的に解説した書籍です。通称「パタ&ヘネ」として知られており、著者の両名はチューリング賞も受賞している著名な研究者です。 この本を読んだきっかけ 私が大学時代、恥ずかしながら「コンピュータについて何もわからない」状態で授業を受けていました。その後、大学院受験をするタイミングで試験内容にコンピュータアーキテクチャのセクションがあり、この本を何度も読み返し勉強を進めてきました。命令セットやプロセッサの種類を詳しく知ることが自分にとってどれほど重要なのか理解できていませんでしたが、この本との出会いが私のコンピュータに対する理解を大きく変えることになりました。私にとっては革命的な本です。 本の内容 この本は世界中の大学でコンピュータアーキテクチャの教科書として使われている名著で、もしかしたら大学で勉強したことがある方がいるかもしれませんね。 コンピュータアーキテクチャの内容をわかりやすく解説しており、コンピュータの歴史を踏まえながら命令やプロセッサなどの概念を理解しやすく説明しています。1996年の初版以来、私が読んだ時点の第5版ではMIPSアーキテクチャが中心でしたが、現在の6版では最新のアーキテクチャやトレンドも反映されています。 この本から影響を受けた点/学んだ点 この本を読んだことで、コンピュータの動作が頭の中でだんだんイメージできるようになりました。特に、Webサービスを提供する上では、クライアントと記憶媒体間のデータのやり取りを考慮しながらプログラムを組む必要があることを理解できました。サービスをより大規模に展開しようとすると、ハードウェアについての知識がますます重要になってくることを実感しました。また、I/Oやメモリに関する知識が深まったことで、プロダクトの課題発見に今でも役立てています。 特に印象に残った部分 世の中にある技術書は難解なものが多いと感じていましたが、この本は特に読みやすく、当時学生だった私にとってアーキテクチャの基礎を掴むのにとても役立ちました。 表面的なプログラミングだけでなく、その下層で何が起きているかを理解することで、より良いシステム設計ができるようになりました。例えば、CPU内部の論理設計から、メモリ階層・I/O・並列計算機までのコンピュータの動作原理を広く理解することは、エンジニアとしてのキャリアを積む中で常に私の基盤となっています。 全体的に図が多く、内部の動作をイメージしやすい良書です。 このような方におすすめ ソフトウェア以外にも、コンピュータサイエンス全般を幅広く学びたい方にお勧めの一冊です。特に、Webサービスやアプリケーション開発に携わるエンジニアの方々には、パフォーマンスチューニングやシステム設計の基礎知識として役立つでしょう。また、コンピュータサイエンスを学び始めたばかりの学生の方にも、その読みやすさから入門書として最適です。 また、理解が進んだ方には「上パタ&ヘネ」と言われる「Computer Architecture: A Quantitative Approach」という本もありますので、物足りない方はこちらもおすすめです。 佐藤さんの原点は「パタ&ヘネ」にあったんですね。大学時代に出会ったこの一冊が、現在CTOとして活躍する佐藤さんのコンピュータに対する深い理解の礎となったことがよく伝わってきます。技術書との出会いが、その後のキャリアを大きく左右することを実感させられます。 次は、Findy Team+のフロントエンド開発を担当する中村さんです!中村さんが選んだ一冊は、実際の開発現場で直面した課題から見つけ出した救世主のような本。Webセキュリティの世界への扉を開いた体験とは? ■ 中村大輝さん / フロントエンドエンジニア ■ こんにちは、 Findy Team+ の開発をしている 中村 です。 体系的に学ぶ 安全なWebアプリケーションの作り方 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 作者: 徳丸 浩 SBクリエイティブ Amazon 体系的に学ぶ 安全なWebアプリケーションの作り方 作者: 徳丸 浩 出版社: SBクリエイティブ 私が紹介する「体系的に学ぶ 安全なWebアプリケーションの作り方」は、Webアプリケーションのセキュリティを体系的に解説した書籍です。通称「徳丸本」として知られています。 この本を読んだきっかけ エンジニアとして働き始めた1〜2年目の頃、当時私が担当していたWebサービスで脆弱性診断を受ける機会がありました。その結果、XSSやCSRFといった複数の脆弱性が指摘され、修正を求められる事態となりました。 1つ具体的な例を挙げると、そのWebサービスにはユーザーがレビューのようなものを投稿できる機能がありました。しかし、その入力欄に悪意あるスクリプトが埋め込まれ、他のユーザーがそのレビューを閲覧すると、JavaScriptが実行されるXSS(クロスサイトスクリプティング)が発生しました。この脆弱性により、ユーザーのクッキー情報が盗まれたり、不正な操作が実行されたりする可能性があり、非常に危険でした。これらの修正事項を解決するため、Webセキュリティに関する知識が必要となり、何をどう対策すれば良いのか悩んでいたときに出会ったのが「体系的に学ぶ 安全なWebアプリケーションの作り方」でした。 本の内容 この本は、Webアプリケーションの脆弱性を体系的に解説し、その対策方法を具体的に示しています。特に、XSSやCSRF、SQLインジェクションなど、代表的な脆弱性ごとにその仕組みと対策をわかりやすく解説しており、Webセキュリティに関する理解を深めることができます。また2011年の初版から、HTML5の普及に伴う改定などいくつかの改訂が重ねられた第2版まで現在出版されています。 この本から影響を受けた点/学んだ点 この本を読むことで、脆弱性とは単なる「エラー」ではなく、悪意ある攻撃者によって悪用される可能性があるとても重大なリスクであることを理解しました。また、脆弱性の種類ごとにどのような攻撃が行われるかを学び、実際のコードにどう対策を実装すればよいかを具体的に理解できました。 特に印象に残った部分 特に印象に残ったのは、XSS(クロスサイトスクリプティング)の項目です。当時私が担当したWebサービスでもXSSが報告され、その危険性を初めて実感しました。本書の例をもとに、エスケープ処理やCSP(コンテンツセキュリティポリシー)を適用することで安全性を高める方法を学び、実際の修正にも役立ちました。 このような方におすすめ Webアプリケーション開発に関わるすべてのエンジニアにお勧めです。特に、開発経験が浅く、Webセキュリティに自信がない方には非常に助けになる一冊です。 中村さんの「徳丸本」との出会いは、まさに現場のピンチを救った実践的な体験でしたね。エンジニアとして直面した実際の脆弱性問題が、セキュリティへの深い理解につながった瞬間が印象的です。技術書は時に、現場の課題を解決する強力な味方になるのですね。 最後は、2025年3月に入社したばかりの甲斐さんです!同じくFindy Team+のフロントエンド開発を担当する甲斐さんが選んだのは、コードの「変更しやすさ」という永遠のテーマに挑んだ一冊。大規模開発の現場で見つけた設計の知恵とは? ■ 甲斐和基さん / フロントエンドエンジニア ■ こんにちは、 甲斐 です! 2025年3月にファインディへ入社、フロントエンドエンジニアとして Findy Team+ の開発をしています。 現場で役立つシステム設計の原則 変更を楽で安全にするオブジェクト指向の実践技法 現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法 作者: 増田 亨 技術評論社 Amazon 現場で役立つシステム設計の原則 変更を楽で安全にするオブジェクト指向の実践技法 作者: 増田 亨 出版社: 技術評論社 この本を読んだきっかけ エンジニアとして働き始めて2年目の頃、初めて大規模なコードベースのアプリケーションを担当することになりました。コードベースが巨大かつ複雑で影響範囲を調査するだけでも数時間かかるような状況に課題感を感じ、変更しやすいコード・設計に興味を持ったことがきっかけでこの本を手に取りました。 本の内容 システム設計について、ドメイン駆動設計とオブジェクト指向プログラミングを中心に、変更に強いコードを書くための設計・手法について具体的なコードを例に挙げて解説しています。ベースの話はオブジェクト指向に沿ったものですが、変更に強い構造を作るための手法や考え方は他のプログラミングパラダイムでも活用できるものになっています。 この本から影響を受けた点/学んだこと この本を読んだことで、高凝集・疎結合であることで変更しやすい構造になるということを知識としてだけではなく、具体的に実践するための手法・考え方をベースに設計を考えるようになりました。この考え方は直接的にではないですが、フロントエンド開発に主軸を移してもからもコンポーネント設計や共通ロジックの切り出しなどを検討する際に活かされています。 特に印象に残った部分 全体を通して「変更を楽にするため」の手法について触れていたことが印象に残っています。特にドメインオブジェクト(ドメインに紐づくデータとロジックを扱うことに特化したオブジェクト)を使用した関心ごとの分離について言及しており、コードの整理だけでなく業務ドメインに対する理解を深めることが良い設計をする上でも重要であることを学びました。 例として取り上げるサンプルコードの題材が発注システムなど実践的なものだったので、よくあるサンプルコードのような「定義はわかるけど実際にどう扱うのか?」がイメージしづらいようなことはなく読みやすかったです。 このような方におすすめ プログラミングを始めて、コードの書き方はわかったけど設計ってどうすればいいのか?現場のコードベースが変更しづらいけどなぜだろう?など設計・オブジェクト指向について具体的なユースケースを見つつ学びたい方におすすめです。 おわりに 今回ご紹介した3名のエンジニアたちが人生を変えた一冊は、それぞれの専門分野や関心領域を反映した多様な選択でした。コンピューターの基礎原理からWebセキュリティ、そしてシステム設計まで、エンジニアとしての成長過程で出会った本が、その後のキャリアや技術的視点に大きな影響を与えていることがわかります。 技術書との出会いは、単なる知識の獲得だけでなく、問題解決の糸口や新たな視点をもたらしてくれるものです。皆さんも、自分の技術的な課題や興味に合わせた一冊を見つけ、エンジニアとしての視野を広げてみてはいかがでしょうか。 ファインディでは、さまざまなバックグラウンドを持つエンジニアが活躍しています。技術にこだわり、より良いものを追求する仲間とともに働いてみませんか? 現在、ファインディでは新しいメンバーを募集中です。 興味のある方は、ぜひこちらからチェックしてみてください!
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub Copilotやチャットベースの開発支援ツールなど、生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中で、このたび弊社からリモートMCPサーバーを公開することとなりました。 そこで今回は、リモートMCPサーバーを公開する上で実際に考慮したポイントを紹介します。 それでは見ていきましょう! 公開したリモートMCPサーバーの概要 インフラ構成 内部実装 認証情報 Streamable HTTP Transport まとめ 公開したリモートMCPサーバーの概要 MCPに関しては、前回の記事で詳しく説明していますので、公式ドキュメントと合わせてそちらをご覧ください。 tech.findy.co.jp modelcontextprotocol.io 今回公開したリモートMCPサーバーを使うことで、GitHub CopilotやDevinの利用状況を取得して可視化することが可能になります。詳細はリリースブログをご覧ください。 https://findy.co.jp/2843/ findy.co.jp なお、今回公開したリモートMCPサーバーのご利用は、2025/05/19現在、ファインディ株式会社のクライアント企業様限定となっております。 ご利用希望の方は、申込みフォームからお申し込みください。 docs.google.com インフラ構成 今回、弊社が公開したリモートMCPサーバーのインフラ構成は次のようになっています。 開発当初はAWS Lambdaを使うことを検討していたのですが、次の理由から採用を見送り、現状のシンプルな構成に落ち着きました。 実装内容をLambdaに合わせる必要がある 後述するSSE Transportを使う場合、クライアント、サーバー間のコネクションを維持する必要があり、その要件がLambdaと合わない 今回はdeploy時にDocker imageをECRにPushして、ECSを使ってサーバーを起動します。ログ出力はCloudWatchを使い、VPC経由でクライアント側からアクセス出来るようになっており、比較的よく見かけるシンプルな構成になっているかと思います。 今回のリモートMCPサーバーは、ファインディのSREチームが取り組んでいるセキュリティを担保したインフラ環境構築の一環として、HCP TerraformのPrivate Registryを活用した初の本番環境構築事例となりました。 このPrivate Registryに登録したモジュールは、Trivyによるセキュリティスキャンでエラーが出ない状態を担保しています。 一方で、全社的に必須とされている数多くの設定の中には、リモートMCPサーバーの特性上、一部適用が難しいものもありました。 特に、一部のWAFルールがリモートMCPサーバーの通信をブロックしてしまうケースが存在しました。 そのため、インフラ構築を進めながらPrivate Registryに登録したモジュールのカスタマイズも同時に行い、リモートMCPサーバーの要件を満たすインフラ環境を実現しました。 この取り組みにより、ファインディではより迅速かつセキュアにサービス提供ができる基盤が整ったと言えます。 内部実装 リモートMCPサーバーの内部実装の方法は、後述する認証情報の取得とTransportの利用が異なるだけで、基本的にローカルで実行するものと同じです。 具体的なコードを書くと、次のようになります。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js" ; import express, { Request , Response } from "express" ; import { z } from "zod" ; const getMcpServer = ( name : string ) => { const mcpServer = new McpServer( { name : 'sample-mcp-server' , version : '1.0.0' , } , { capabilities : { logging : {} } } ); mcpServer.tool( "addition" , "足し算をする" , { a : z.number(), b : z.number() } , async ( { a , b } ) => ( { content : [ { type : "text" , text : `Hello ${ name } ` } , { type : "text" , text : String (a + b) } ] } ) ); return mcpServer; } ; async function main () { try { const app = express(); const transports: Record < string , SSEServerTransport > = {} ; app. get ( "/sse" , async ( req : Request , res : Response ) => { const transport = new SSEServerTransport( "/message" , res); const sessionId = transport.sessionId; transports[sessionId] = transport; const name = req. get ( "X-Hoge-Name" ); const { server } = getMcpServer( name ); await server.connect(transport); server.onclose = async () => { await server. close (); process .exit( 0 ); } ; transport.onclose = () => { delete transports[sessionId]; } ; } ); app.post( "/message" , async ( req : Request , res : Response ) => { const sessionId = req.query.sessionId as string | undefined ; if (!sessionId) { res. status ( 400 ). send ( 'Missing sessionId parameter' ); return ; } const transport = transports[sessionId]; if (!transport) { res. status ( 404 ). send ( 'Session not found' ); return ; } await transport.handlePostMessage(req, res, req. body ); } ); const PORT = process .env.PORT || 3001 ; app.listen(PORT, () => { console .log( `Server is running on port ${ PORT } ` ); } ); process .on( 'SIGINT' , async () => { for ( const sessionId in transports) { try { await transports[sessionId]. close (); delete transports[sessionId]; } catch (error) { console .error( `Error closing transport for session ${ sessionId } :` , error); } } process .exit( 0 ); } ); } catch (error) { console .error( 'Error starting server:' , error); process .exit( 1 ); } } main(). catch ( error => { console .error( 'Unhandled error:' , error); process .exit( 1 ); } ); SSE TransportでステートフルなMCPサーバーを実装する場合のサンプルコードとなります。 MCPサーバー自体の実装はローカル環境で実行するものと変わりませんが、MCPサーバーをExpressなどのサーバーに接続して起動している点が異なります。 つまるところ、サーバーに接続する箇所以外は基本的に同じ実装で良いので、サーバーの起動部分とMCPサーバーの実装部分を分けて実装しておくと、ローカルで実行するケースとリモートで実行するケースの両方に対応できるようになります。 また、SSE Transportを使って通信を行う場合、MCPクライアントとのセッション管理を行う必要があります。MCPサーバーと接続、切断した時や、サーバーそのものを停止した際にセッションに対する各種操作を実行する必要があります。 認証情報 MCPサーバーからAPIを実行する際にアクセストークンが必要なケースがあります。 ローカル環境でMCPサーバーを実行する場合は環境変数を使ってアクセストークン等を渡すのが一般的です。 しかし、リモートMCPサーバーの場合は環境変数に個人のアクセストークンを設定することは出来ません。リモートMCPサーバーの場合、動作する場所がローカル環境ではなく共通のサーバーになるからです。 こういったケースの場合、環境変数ではなくheaders経由でアクセストークンを渡すことが出来ます。 { " servers ": { " sample-mcp ": { " url ": " https://example.com/sse ", " type ": " sse ", " headers ": { " X-Hoge-Name ": " Fuga ", " X-Access-Token ": " <YOUR_ACCESS_TOKEN> " } } } } このようにMCPクライアント側の設定ファイルを記述することで、MCPサーバーと接続したタイミングにheaders経由でリモートMCPサーバーが必要な情報を受け取ることが出来るようになります。 Streamable HTTP Transport これまでのリモートMCPサーバーとの通信方式はSSE Transportを使うのが一般的でした。 しかし、PROTOCOL VERSION 2025-03-26からSSE Transportはdeprecatedになり、代わりにStreamable HTTP Transportを使うことが推奨されるようになりました。 modelcontextprotocol.io Streamable HTTP Transportに置き換わることで、次のようなメリットがあります。 ステートレスなMCPサーバーを実装できる プレーンなHTTPサーバーとして実装できる MCPクライアントとサーバーのコネクションを維持し続ける必要がなくなる 2025/05/19現在ですと、MCPクライアント側のStreamable HTTP Transportへの対応が出来ていないケースがあるため、しばらくはSSE Transportで通信できるようにする必要がありそうです。 弊社としましても、公開直後はSSE Transportでの提供を行い、折を見てStreamable HTTP Transportに移行していく予定です。 MCPサーバー側のTransport関連の実装は、公式SDKにサンプルコードがあるので、そちらを参考にしてみると良いでしょう。 github.com まとめ いかがでしたでしょうか?今回の記事がリモートMCPサーバーを公開する上での参考になれば幸いです。 今回公開したリモートMCPサーバーはα版という位置付けであり、今後も機能追加や改善を行っていく予定です。 2025/05/19現在、ファインディ株式会社のクライアント企業様限定の公開とはなっていますが、ご利用希望の方は是非、申込みフォームからお申し込みください。 docs.google.com 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub Copilotやチャットベースの開発支援ツールなど、生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中で、MCPというプロトコルが話題となっていることは読者の皆さんもご存知かと思います。 そこで今回は、弊社の開発組織でのMCPサーバーの導入と実装、そして実績について紹介します。 それでは見ていきましょう! MCPとは 導入 実装 実績 動的にプロンプトのテキストを作成して返す Devinと連携する Figmaデータのlintを行う セキュリティ面の考慮 まとめ MCPとは MCP(Model Context Protocol)は、アプリケーションが大規模言語モデル(LLM)に情報やツールへのアクセス方法を提供する、新しいオープンプロトコルです。 USB-Cが様々なデバイスを標準的な方法で接続するように、MCPはAIモデルを多様なデータソースやツールへつなぐための、標準化された方法を提供します。 これがこれまでのやり方、特に従来のAPIとどう違うのかというと、AI連携の開発を大幅に簡素化し、より動的な機能を提供する点にあります。従来は、各サービスに対して個別のコードや設定が必要で、「それぞれのドアに個別の鍵が必要」な状況に似ていました。しかし、MCPは単一の標準化されたコネクタとして機能するため、一度の統合で複数のツールやサービスにアクセスできる可能性があります。 詳しくは次の公式ドキュメントをご覧ください。 modelcontextprotocol.io このMCPの規格に則って作成されたサーバーをMCPサーバーと呼びます。 導入 弊社でも例に漏れず、MCPサーバーの利用を開始しました。 Model Context Protocol servers で紹介されている公式MCPサーバーを開発リポジトリに追加するだけで、すぐに利用開始できます。 github.com GitHubのMCPサーバーを使って、Pull requestやIssueの情報を取得して、そのままLLMに渡すことができます。 github.com SentryのMCPサーバーを使って、不具合の詳細を取得して、そのままLLMに渡すことが可能です。その情報をそのままCopilotやAgentなどに解析してもらい、原因を特定した後に自動的に実装コードを修正してもらうことが出来ます。 github.com AWSのDocumentのMCPサーバーを使うことで、CopilotなどからAWSについての質問を投げて、ドキュメントの内容を検索して返してもらうことができます。その内容はそのままLLMに渡すことも可能です。 github.com 利用方法はとても簡単です。各種AIエージェントの設定ファイルに追記して、MCPサーバーを起動するだけです。 例えばVSCodeでGitHubのMCPサーバーを利用する場合、次のような記述を追加します。 { " servers ": { " github ": { " command ": " docker ", " args ": [ " run ", " -i ", " --rm ", " -e ", " GITHUB_PERSONAL_ACCESS_TOKEN ", " ghcr.io/github/github-mcp-server " ] , " env ": { " GITHUB_PERSONAL_ACCESS_TOKEN ": " <YOUR_ACCESS_TOKEN> " } } } } このように、既に多くのプロダクトやサービスでMCPサーバーは公開されており、開発者やプロダクト開発の生産性を向上させるための強力なツールとなっています。 実装 各社から提供されているMCPサーバーを活用していると、組み合わせ次第で色々なことが出来ることに気づきます。 そこで弊社の開発組織で活用できるようなMCPサーバーを自分たちで作ることにしました。 公式から開発用のSDKが提供されているのですが、今回は弊社が普段から使っているTypeScriptのSDKを使って実装しています。 github.com 公式のSDKを使うことで、MCPサーバー内部の実装に集中することが出来るので、利用しない手はありません。 次のコードは、与えられた2つの数値に対して計算を行い、その結果を返すMCPサーバーの実装例です。 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ; import { z } from "zod" ; const mcpServer = new McpServer( { name : "Sample MCP Server" , version : "0.0.1" } ); mcpServer.tool( "addition" , "足し算をする" , { a : z.number(), b : z.number() } , async ( { a , b } ) => ( { content : [{ type : "text" , text : String (a + b) }] } ) ); mcpServer.tool( "multiplication" , "掛け算をする" , { a : z.number(), b : z.number() } , async ( { a , b } ) => ( { content : [{ type : "text" , text : String (a * b) }] } ) ); try { const transport = new StdioServerTransport(); await mcpServer.connect(transport); } catch (error) { console .error( 'Error starting server:' , error); process .exit( 1 ); } mcpServer.tool でtoolを追加します。 1つ目の引数でtoolの名前、2つ目の引数でtoolの説明、3つ目の引数でtoolのパラメータ、4つ目の引数でtoolの実装を定義しています。 また、用途や内容によってはMCPサーバーそのものを分けたいケースが出てきます。ですが、そのたびにリポジトリを切ってしまうと、同じような処理のコードを分散管理することになってしまいます。 そのため弊社では、以前から活用していたNxを利用して、MCPサーバーの実装をモノレポで管理するようにしました。 tech.findy.co.jp モノレポにすることで、複数のMCPサーバーから利用できる共通関数などを作成できます。外部APIを実行するClientなどが良い例です。このように弊社ではMCPサーバーの社内エコシステムを実現しています。 更にNxのgenerator機能を使うことで、モノレポとMCPサーバーの初期設定はコマンドを数回実行するだけで完了するようにしています。 Nxのgenerator機能については以前の記事で紹介しておりますので、併せてご覧ください。 tech.findy.co.jp このような整備を行うことで、社内のエンジニアがMCPサーバーを作るハードルを下げることができました。 実績 社内エコシステムの整備を行ったことにより、数名のエンジニアで、3日間で10個のMCPサーバーと30個のtoolを実装して、社内のエンジニアに配布することを実現できました。 今回はその中の一部を紹介します。 動的にプロンプトのテキストを作成して返す パラメータを受け取り、その内容に応じて動的にプロンプトのテキストを生成して返すMCPサーバーを実装しました。 開発チーム内で共通で利用したいプロンプトがあり、内容を動的に切り替えたい場合などに便利です。 例えば、他のMCPサーバーからデータを取得して、そのデータをこのMCPサーバーに渡すことで、外部データのテキストを利用してプロンプトを生成するといったことが実現できます。 このように、プロンプトのテキストを返し、それをそのままLLMで実行するような使い方がMCPサーバーでは可能です。 Devinと連携する 完全自律型AIエンジニアのDevinは、α版ではありますがAPIを公開しています。 docs.devin.ai そのAPIをMCPサーバーから実行することにより、Devinに関する情報を取得したり、セッションを作成、停止できるようにしました。 これによりエンジニア自身の作業中に、SlackやDevinの画面を直接確認せずともDevinの管理ができるようになりました。 このように、外部APIを実行して情報を取得したりデータ登録、削除を行うことがMCPサーバーでは可能です。 Figmaデータのlintを行う デザインプラットフォームのFigmaはAPIを公開しています。 www.figma.com そのAPIをMCPサーバーから実行して、対象のFigmaのデータを取得して、データの中身をチェックして、デザインルールに則っているかどうかlintのようなチェックを行うMCPサーバーを実装しました。 例えば、指定したフォント以外を使っている場合や、利用できるpx数ではない場合など、デザインルールに則っていない場合は警告を返すようなことが可能です。 このように、外部APIからデータを取得して、内容を解析したり加工して返すようなことがMCPサーバーには可能です。 セキュリティ面の考慮 外部APIを実行する場合、アクセストークンが必要になるケースが多いと思います。 このようなケースの場合、MCPサーバーを実行する際に環境変数を使ってアクセストークンを渡すことができます。 利用するアクセストークンの権限を絞り、環境変数でアクセストークンを隠蔽して実行することで、安全にMCPサーバーを管理、実装することが可能になります。 また、外部の公式以外のMCPサーバー、いわゆる野良MCPサーバーを利用する場合は注意が必要です。 悪意のあるMCPサーバーに対してアクセストークンなどを渡してしまうと、意図しない情報漏洩やデータの改ざんなどのリスクがあります。 そのため、外部の野良MCPサーバーを利用する場合は、内部実装を確認して実際に実行されている処理を確認することをオススメします。 まとめ いかがでしたでしょうか? MCPサーバーを実装するハードルとコストは非常に低く、それに対するリターンは非常に大きいため、コストパフォーマンスが非常に高いです。 是非一度、公式ドキュメントを参考にして簡単なMCPサーバーを実装してみてください。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
このブログの内容をポッドキャストでも配信中! ソフトウェア開発現代史年表 Ver2.07 このブログの内容をポッドキャストでも配信中! はじめに DevOps誕生以前(〜2000年代前半) 2009年:DevOpsのはじまり Flickrの伝説的講演「10+ Deploys Per Day」 パトリック・ドボアと「DevOps」という言葉の誕生 2010年代前半:ジェズ・ハンブルと継続的インテグレーション(CI)から継続的デリバリー(CD)への発展 継続的インテグレーション(CI)とは何か 継続的デリバリー(CD)への発展 2010年代中盤:ジーン・キムとDevOpsの理論体系化 2010年代後半〜現在:DevOpsの普及と進化 Googleによる「SRE(Site Reliability Engineering)」の提唱 「You build it, you run it(作ったものは自分で運用する)」文化の定着 DORA(DevOps Research and Assessment)の設立と影響 クラウドネイティブ技術とDevOpsの融合 DevOpsの文化的側面の重視 DevOpsの本質と今後の展望 日本におけるDevOps:まだ「一部の人たちのモノ」状態 DevOpsとAI導入の共通障壁 【告知】ソフトウェア開発の伝説的パイオニアたちが来日! はじめに こんにちは。ソフトウェアプロセス改善コーチ兼アジャイルコーチ兼エンジニア兼Findy Tech Blog編集長の高橋( @Taka-bow )です。 30年以上前、エンジニアとしての第一歩を踏み出したばかりの私に、ある先輩が教えてくれた言葉があります。 「動いているコードには触れるな」 この言葉は、当時の日本のIT現場における「安定性最優先」の価値観を象徴しています。一度リリースされたシステムは「完成品」として扱われ、必要最低限の変更以外は避けるべきという考え方が主流でした。変更は常にリスクをはらんでおり、「動いているものを変えれば壊れる可能性がある」という恐れが、技術的な進化よりも優先されていたのです。 しかし、DevOpsの登場によって、この価値観は大きく変わりました。「変更を恐れる」文化から「変更を受け入れる」文化へ。「安定性のために変更を避ける」から「頻繁な小さな変更によって安定性を高める」へと変化しました。 つまり「動いているコードには触れるな」から 「常に改善し続けるコード」 へと進化したのです。 この価値観の転換は、単なる技術的な進化ではなく、ソフトウェア開発に対する根本的な考え方の変革です。 世界的には当たり前となりつつあるこの変革ですが、日本の状況はどうでしょうか。興味深いことに、日本では一部のWeb系企業やスタートアップを除き、DevOpsの波はまだ十分に広がっていません。 なぜでしょう? この疑問を探る前に、まずDevOpsがどのように生まれ、発展してきたのかを理解する必要があります。ソフトウェア開発現代史の視点から、この変革をもたらした先駆者たちの物語を紹介していきたいと思います。 下図の年表に示すように、DevOpsの歴史は2009年頃から始まります。 DevOps誕生以前(〜2000年代前半) 2000年代前半までのソフトウェア開発では、 開発と運用は完全に分断され、しばしば対立関係にありました 。開発チームの目標は「新機能を素早くリリース」、運用チームの目標は「システムの安定性維持」であり、この2つの目標はしばしば衝突していました。 開発チームは「とにかく早くリリースしたい」 → 変更を加えたがる 運用チームは「安定稼働が最優先」 → 変更を嫌う 結果として、開発は「リリース遅延」に苛まれ、運用は「障害対応」に追われる 変更のリスクを最小限にするために、厳格なリリースプロセスが敷かれ、開発者は運用チームから「勝手にデプロイするな」と釘を刺されていました。その結果、リリースサイクルは長期化し、開発の俊敏性が犠牲になっていったのです。 特に、大規模なリリースでは 手作業によるデプロイ が行われることが多く、設定ミスや環境差異が原因で障害が頻発していました。こうした問題を解決し、 開発と運用のギャップを埋める新たなアプローチ が強く求められていました。 2009年:DevOpsのはじまり Flickrの伝説的講演「10+ Deploys Per Day」 こうした状況に一石を投じたのが、2009年のO'Reilly Velocity 09 Conferenceで行われた、Flickrのエンジニアによる伝説的な講演です。当時Flickrのエンジニアだった ジョン・オールスパウ(John Allspaw)とポール・ハモンド(Paul Hammond) が「 10+ Deploys Per Day: Dev and Ops Cooperation at Flickr 」のタイトルで発表し、業界に衝撃を与えました。 この講演で彼らは、当時としては驚異的な「 1日に10回以上のデプロイ 」を実現している事実を明らかにしました。多くの企業が月に1回や四半期に1回のリリースサイクルに苦しんでいた時代に、これは革命的な実践だったのです。 彼らが強調したのは次のポイントです。 開発と運用の協力関係 - 両チームが共通の目標(ユーザー価値の提供)に向かって協力する 小さな変更の頻繁なデプロイ - 大きな変更を一度にリリースするのではなく、小さな変更を頻繁にリリースする 自動化の徹底 - テスト、デプロイ、モニタリングなど、あらゆる工程を自動化する 「失敗は避けられない」前提 - 失敗を防ぐのではなく、素早く検知して回復する能力を高める この講演により「高頻度デプロイは可能」との認識が広まり、多くの企業がFlickrの実践に触発されて自社のデプロイプロセスを見直すきっかけとなりました。この講演は、YouTubeで「10+ Deploys Per Day: Dev and Ops Cooperation at Flickr」として今でも視聴可能であり、DevOpsを学ぶ人々にとって必見の資料となっています。 このとき日本では:アジャイル導入の緩やかな歩み 2001年に発表された「アジャイルソフトウェア開発宣言(アジャイルマニフェスト)」は、「プロセスやツールよりも個人と対話を」「包括的なドキュメントよりも動くソフトウェアを」といった価値観を掲げ、後のDevOps誕生の重要な思想的背景となりました。しかし、2000年代前半のアジャイル導入期において、日本企業の多くはこの本質である「変化への適応」や「顧客との協働」といった考え方を十分に受け入れることができませんでした。日本の階層的な組織構造や詳細な計画を重視する文化が、アジャイルの柔軟性と相容れなかったのです。DevOpsはアジャイルの延長線上に生まれた考え方であり、この最初のアジャイル導入のチャンスを逃したことが、後のDevOps導入の遅れにも直接的な影響を与えることになりました。 パトリック・ドボアと「DevOps」という言葉の誕生 Flickrの講演と同じ2009年、「 DevOps 」という言葉が誕生しました。この言葉の背後には、ベルギーのITコンサルタント パトリック・ドボア(Patrick Debois) の興味深い物語があります。 *1 実は、ドボアの旅は2007年に始まっていました。ベルギー政府のデータセンター移行プロジェクトに携わっていた彼は、開発者とシステム管理者の間の対立に悩まされ、解決策を模索していました。 転機となったのは2008年8月、トロントで開催されたAgileカンファレンスでした。ソフトウェア開発者の アンドリュー・シェーファー(Andrew Shafer) が「Agile Infrastructure(アジャイルインフラストラクチャ)」というセッションを開催しましたが、参加者はたった一人、パトリック・ドボアだけでした。二人はこの出会いをきっかけに、開発と運用の間の壁を取り払うアイデアについて議論を始めました。 そして2009年、先述のFlickrの講演「10+ Deploys Per Day」に触発されたドボアは、エンジニアのナスラット・ナサー(Nasrat Nassar)からの「ベルギーで独自のVelocityイベントを開催してはどうか」というツイートをきっかけに行動を起こします。彼は「 DevOpsDays 」というイベントを開催することを決意しました。 この名前は、「development(開発)」と「operations(運用)」の最初の3文字を取り、「days(日)」という単語を追加したものでした。2009年10月30日に開催されたこのカンファレンスには、開発者、システム管理者、ツール開発者など多様な参加者が集まりました。 カンファレンス終了後、議論はTwitterに移り、より覚えやすいハッシュタグとして、ドボアは名前を「 #DevOps 」に短縮しました。これが「 DevOps(Development + Operations) 」という言葉の誕生であり、それ以来、このムーブメントはDevOpsとして知られるようになりました。 興味深いことに、スペルについては今でも意見の相違があります。主流の使用法は「DevOps」ですが、創始者のドボアを含む少数派は「Devops」を主張し、一部の人々は大文字を完全に排除して「devops」とすることを主張しています。 ドボアのX(当時はTwitter)アカウント(@patrickdebois)は初期のDevOpsムーブメントの中心的な情報源となり、#devopsというハッシュタグを通じて、世界中の実践者がアイデアを共有する場となっていきました。 このとき日本では:クラウド導入の機会損失 2006年から2010年にかけてのクラウド黎明期において、AWSをはじめとするクラウドサービスの登場は、単なるインフラの選択肢ではなく、DevOpsの実践を加速させる技術的基盤でした。「Infrastructure as Code」や「自動化」といったDevOpsの核心的な実践を可能にする環境が整いつつあったのです。しかし、日本企業の多くは「セキュリティ懸念」「既存システムへの投資保護」「クラウドの信頼性への疑問」などを理由に慎重な姿勢を取り続けました。この時期に積極的なクラウド活用を進めていれば、DevOpsへの移行も自然な流れとして実現できたはずです。この「待ちの姿勢」が、後のDevOps導入の遅れにも繋がることになりました。 なお、パトリック・ドボアは昨年2024年1月に行われたDevOpsDays Tokyo 2024の基調講演のため来日しています。 私は現地でお話を聞きましたが、このときのドボアは AIにとても興奮 しており、特にRAGについてのお話でした。 当時の私は、ドボア氏が何に興奮していたのか、何も分かっていませんでした……でも、今なら分かります。 改めてビデオを見返して、気になった発言をピックアップしました。 私がとても気に入っている概念のひとつに、こういう考え方があります。 エージェントの性能が向上すれば、私たちは直接「もの」を作るのをやめ、 「ものを作るもの」を作るようになります。 つまり、自動化の次の段階に進むのです。 多くの人が私にこう言いました。 「DevOpsでは乗り遅れた。でも今度のAIの波では遅れたくない。」 成熟したDevOps文化を持つ人々こそ、GenAIのアーリーアダプターになりつつあるのです。 私たちエンジニアは、常にやりすぎる傾向があります。 でも、それでいいのです。 今もっとも難しい新しいプログラミング言語? それはもしかすると「英語」か「日本語」かもしれませんね。 もっと、たくさん痺れる事を仰っているので、ぜひ本編YouTubeをごらんください。 2010年代前半:ジェズ・ハンブルと継続的インテグレーション(CI)から継続的デリバリー(CD)への発展 さて、話を戻しましょう。ここで登場するのが、DevOpsの歴史において重要な役割を果たした人物、 ジェズ・ハンブル(Jez Humble) です。彼はソフトウェアデリバリーの自動化と効率化に関する先駆的な研究と実践で知られ、継続的デリバリー(CD)の概念を体系化した第一人者として世界中のソフトウェア開発に多大な影響を与えました。 DevOpsの言葉が広まり始めた2010年代前半、まず理解しておくべき重要な概念が「 継続的インテグレーション(Continuous Integration, CI) 」です。CIは実はDevOpsより前から存在していた概念で、2000年代初頭にアジャイル開発の文脈で広まりました。 特に マーティン・ファウラー(Martin Fowler) と ケント・ベック(Kent Beck) がその重要性を提唱しています。 継続的インテグレーション(CI)とは何か 継続的インテグレーションの核心は、 「開発者が頻繁にコードを統合し、自動テストによって問題を早期に発見する」 という実践です。具体的には次のような特徴があります。 頻繁なコミット - 開発者は少なくとも1日1回、コードをメインブランチに統合する 自動ビルド - コードがコミットされるたびに自動的にビルドが実行される 自動テスト - ビルド後に自動テストが実行され、問題があれば即座にフィードバックが得られる 問題の早期発見 - 統合の問題を早期に発見することで、修正コストを低減する CIの実践により、「統合地獄(Integration Hell)」と呼ばれる、長期間分岐したコードを統合する際の困難を避けることができます。CIを実現するツールとしては、 Jenkins (旧Hudson)、 Travis CI 、 CircleCI などが広く使われるようになりました。 なお、CI(継続的インテグレーション)と密接に関係する実践として、TDD(Test-Driven Development:テスト駆動開発)があります。TDDは「テストを先に書き、そのテストをパスする最小限の実装を行う」という開発手法で、Kent Beckがエクストリーム・プログラミング(XP)の中で体系化し、広く普及させました。 テスト駆動開発 作者: Kent Beck オーム社 Amazon TDDによって作成される自動テスト群は、CIパイプラインにおける重要な構成要素となり、コードの品質を継続的に保証する基盤となります。TDDが主にコードレベルの品質を担保するのに対し、CIはチーム全体での統合品質を確保する役割を果たします。両者はいずれも「早期フィードバック」と「問題の早期発見」を重視しており、DevOps実践の基盤として不可欠な考え方です。 継続的デリバリー(CD)への発展 CIが「コードの統合と検証の自動化」に焦点を当てているのに対し、 継続的デリバリー(CD) はその先の「デプロイメントまでの自動化」にまで範囲を広げた概念です。この概念を体系化したのが、ジェズ・ハンブルとデビッド・ファーリー(David Farley)による「 Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation 」(2010年、日本語訳は2012年)の書籍でした。 継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化 作者: Jez Humble , David Farley KADOKAWA Amazon この書籍では、「 継続的デリバリー(Continuous Delivery, CD) 」の概念が体系的に説明され、その核心は「 ソフトウェアをいつでも本番環境にリリース可能な状態にする 」ことにありました。 ジェズ・ハンブルとデビッド・ファーリーは、この書籍で継続的デリバリーを実現するために次のような実践を提唱しています。 デプロイメントパイプライン - コードの変更が自動的にビルド、テスト、デプロイされる一連のプロセス 自動化されたテスト - 単体テスト、統合テスト、受け入れテストなど、あらゆるレベルのテストを自動化 本番環境と一致したステージング環境 - 「開発環境では動くのに本番では動かない」問題を解消 ブルーグリーンデプロイメント - ダウンタイムなしでのデプロイを可能にする手法 これらの実践は現代のCI/CDパイプラインの基盤となり、ジェズ・ハンブルとデビッド・ファーリーの貢献によって「継続的インテグレーション(CI)」から「継続的デリバリー(CD)」へと、自動化の範囲が大きく拡大していきました。 このとき日本では:継続的デリバリー(CD)とゲートキーパー文化の相克 2010年代前半には、継続的デリバリー(CD)の波が世界中に広がりました。海外では多くの企業がデプロイパイプラインを構築し、頻繁なリリースを実現していました。一方、日本企業の多くは「手動リリース」や「長いリリースサイクル」、「厳格な承認プロセス」を維持し続ける傾向がありました。これは日本特有の品質管理への強いこだわりや、変更に対する慎重な姿勢が影響していると考えられます。「リリース=大イベント」「変更=リスク」という認識が根強く、DevOpsの核心である「小さな変更を頻繁に行う」文化への移行が進みにくい土壌があったのです。特に、多くの組織では品質保証部門が「ゲートキーパー」として機能し、リリース前の最終承認権を持つ構造が確立されていました。このゲートキーパー型の品質保証プロセスは、継続的デリバリーが目指す「自動化されたテストによる品質担保」という考え方と根本的に相容れず、プロセス重視の文化から脱却することが難しかったのです。 2010年代中盤:ジーン・キムとDevOpsの理論体系化 2010年代中盤、DevOpsムーブメントの中心人物として台頭したのが ジーン・キム(Gene Kim) です。彼は優れた技術者であると同時に、複雑な概念を分かりやすく伝える稀有な才能を持ち合わせていました。それまで現場レベルの実践知として広がっていたDevOpsの考え方を、組織全体で取り組むべき体系的な方法論として確立した功績は計り知れません。彼の著作は技術書の枠を超え、多くの組織でDevOps変革の指南書となっています。 2013年、ジーン・キムは、ケビン・ベア(Kevin Behr)、ジョージ・スパッフォード(George Spafford)と共に「 The Phoenix Project: A Novel about IT, DevOps, and Helping Your Business Win (邦題:The DevOps 逆転だ!)」を出版しました。 The DevOps 逆転だ! 作者: ジーン・キム , ケビン・ベア , ジョージ・スパッフォード 日経BP Amazon この小説形式の書籍は、架空の自動車部品メーカー「Parts Unlimited」のIT部門が、DevOpsの原則を採用することで危機を乗り越える物語を描いています。物語形式でありながら、DevOpsの本質的な考え方を分かりやすく伝え、多くの読者に影響を与えました。 続いて2016年には、 ジェズ・ハンブル 、パトリック・ドボア、ジョン・ウィリス(John Willis)と共に「 The DevOps Handbook: How to Create World-Class Agility, Reliability, and Security in Technology Organizations 」を出版し、DevOpsの実践をより体系的にまとめあげました。 The DevOps ハンドブック 理論・原則・実践のすべて 作者: ジーン・キム , ジェズ・ハンブル , パトリック・ボア , ジョン・ウィリス 日経BP Amazon この書籍では、 DevOpsの三つの原則(Three Ways) が提唱されています: フロー(Flow) - 開発からデプロイまでの流れを最適化する フィードバック(Feedback) - 問題を早期に発見し、素早く修正する 継続的学習と実験(Continual Learning and Experimentation) - 失敗から学び、継続的に改善する ジーン・キムの貢献により、DevOpsは単なる技術的プラクティスではなく、 組織文化の変革 として広く認識されるようになりました。 このとき日本では:DevOpsの理論と技術基盤の受容の遅れ ジーン・キムらがDevOpsの理論を体系化していた2013年以降、世界ではマイクロサービスアーキテクチャが注目され、Dockerの登場によりコンテナ技術が普及し始めました。これらの技術は、DevOpsの三つの原則(フロー、フィードバック、継続的学習)を実践するための技術的基盤でしたが、日本企業の多くはモノリシックなアーキテクチャと従来のデプロイモデルを維持し続けました。マイクロサービスへの移行には技術的な挑戦だけでなく、組織構造の変革(「2ピザチーム」など小規模で自律的なチーム編成)も必要でしたが、日本の階層的な組織文化はこうした変革に適応しにくい面がありました。「The Phoenix Project」や「The DevOps Handbook」といった書籍は日本語にも翻訳されましたが、その思想を実践に移す組織はWeb系企業の一部に限られていました。 2010年代後半〜現在:DevOpsの普及と進化 2010年代後半になると、DevOpsの考え方は業界全体に広がり、様々な形で進化していきました。 Googleによる「SRE(Site Reliability Engineering)」の提唱 2016年、Googleは「 Site Reliability Engineering: How Google Runs Production Systems 」の書籍を出版し、「 SRE(Site Reliability Engineering) 」の概念を広めました。 SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム オライリージャパン Amazon SREはDevOpsの思想を具現化し、システム運用と開発の連携を深めるための実践的なアプローチです。具体的には、ソフトウェアエンジニアリングの考え方をインフラや運用に適用し、システムの信頼性を向上させることを目的としています。 「You build it, you run it(作ったものは自分で運用する)」文化の定着 Amazonのエンジニアリング文化から生まれた「 You build it, you run it (作ったものは自分で運用する)」の考え方もこの時期に広く普及しました。これは開発者が自ら作ったシステムの運用にも責任を持つ考え方で、開発と運用の境界をさらに曖昧にするものです。この文化の下では、開発者はコードを書くだけでなく、デプロイ、モニタリング、障害対応など、システムのライフサイクル全体に関わることが求められるようになりました。 DORA(DevOps Research and Assessment)の設立と影響 Dr. Nicole Forsgren (開発生産性Conference 2024にて) 2016年、 ニコール・フォースグレン(Nicole Forsgren) 、 ジェズ・ハンブル(Jez Humble) らによって「 DORA(DevOps Research and Assessment) 」が設立されました。DORAはDevOpsの実践と組織のパフォーマンスの関係を科学的に調査・分析する組織として、毎年「 State of DevOps Report 」を発行し、世界中の何千もの組織からデータを収集・分析することで、DevOpsの実践がビジネス成果にどのように影響するかを明らかにしてきました。 特に、 「デプロイ頻度」「変更のリードタイム」「変更失敗率」「サービス復旧時間」 の4つの主要指標(Four Key Metrics)を確立し、これらがビジネスパフォーマンスと強い相関関係にあることを示しています。 2018年には、ニコール・フォースグレン、ジェズ・ハンブル、そしてジーン・キムによって書籍「 Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations (邦題:LeanとDevOpsの科学)」が出版され、DORAの研究成果が体系的にまとめられました。この書籍によってDevOpsの実践は「科学」として確立される重要な一歩を踏み出しました。 LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する (impress top gear) 作者: Nicole Forsgren Ph.D. , Jez Humble , Gene Kim インプレス Amazon DORAの10年にわたる研究と進化については、2025年4月に開催されたDevOpsDays Tokyo 2025にて私がお話した資料で詳しく解説していますので、そちらもぜひご参照ください。 DORAの研究は、DevOpsの実践が単なるトレンドではなく、科学的に裏付けられた効果的なアプローチであることを証明する上で、非常に重要な役割を果たしています。 クラウドネイティブ技術とDevOpsの融合 AWS、Google Cloudなどのクラウドサービスの活用が拡大し、「 クラウドネイティブ 」な開発が注目され始めました。これを支える技術として、コンテナ技術(Docker)やコンテナオーケストレーション(Kubernetes)が普及し、インフラとアプリケーションの管理がより柔軟かつ自動化されるようになりました。これらの技術はDevOpsの実践をさらに加速させる役割を果たしています。特に「 Infrastructure as Code(IaC) 」の考え方が広まり、インフラストラクチャの構成もコードとして管理されるようになりました。これによりインフラの変更も開発プロセスの一部として扱われるようになり、開発と運用の統合がさらに進みました。現代ではTerraform、AWS CloudFormation、Ansible、Puppet、ChefなどのIaCツールが広く使われるようになっています。 DevOpsの文化的側面の重視 技術的な進化と並行して、DevOpsの 文化的側面 も重視されるようになりました。成功したDevOps組織では次のような文化的特徴が見られます。 心理的安全性 - 失敗を非難せず、学びの機会として捉える文化 実験と学習の奨励 - 小さな実験を繰り返し、継続的に改善する姿勢 部門間の協力 - 開発、運用、セキュリティなど、従来は分断されていた部門間の壁を取り払う 共有責任 - 「これは私の担当ではない」考え方ではなく、全員がプロダクトの成功に責任を持つ これらの文化的側面がなければ、いくら優れたツールを導入しても、DevOpsの真の価値を実現できないという認識が広まっています。 DevOpsの本質と今後の展望 2009年に始まったDevOpsの旅は、今や業界標準となる考え方を生み出しました。現在、多くの開発チームが CI/CDを導入し、自動化されたデプロイパイプラインを運用 しています。開発者がコードをコミットすると、すぐにテストが走り、数分後には本番環境へデプロイされるようになりました。リリースのたびに夜を徹して作業したり、「障害対応のために今すぐオペレーションチームを呼べ」と叫んだりする文化は、徐々に過去のものになりつつあります。 しかし、DevOpsの本質は単なる「自動化」ではありません。 開発と運用の対立を超え、継続的に改善し続ける組織文化を作る ことこそがDevOpsの本質なのです。パトリック・ドボア、ジェズ・ハンブル、ジーン・キムをはじめとする先駆者たちが伝えたかったのは、ツールや技術の導入ではなく、根本的な組織文化の変革でした。 これからの開発者は、ツールやプロセスだけでなく、 組織全体の在り方に目を向ける必要があります。 そして、彼らが築いたこの文化をさらに進化させていくことが求められているのです。 日本におけるDevOps:まだ「一部の人たちのモノ」状態 DevOpsは世界的に広がりを見せていますが、日本においては普及のペースが異なる面もあります。 例えば、AgileやScrumのイベントと比べると DevOpsDays Tokyo の参加規模や盛り上がりが海外の同様のイベントと比較して小さいことからも、日本特有の課題があることがうかがえます。 また、2018年10月には「ソフト高速開発のDevOps推進協議会が2年余で解散」というニュースも報じられました。 日本でDevOpsの導入が遅れている理由を構造的・文化的・歴史的背景から分析すると、次のような要因が浮かび上がってきます。 要因 説明 「開発」と「運用」の切り分けの曖昧さ 日本の多くの企業では、「システム部門」が開発・運用・保守のすべてを抱える体制が一般的でした。このため、DevOpsが解決しようとした「開発と運用の断絶」問題が顕在化していなかったのです。しかし、これは必ずしも良い状況ではありませんでした。役割は分かれていなくても、責任やナレッジの分担があいまいで属人的になりやすいという弊害がありました。つまり、「DevとOpsが分かれていない」状態が「連携している」状態を意味するわけではなかったのです。 受託開発構造と多重下請けによる分業文化 日本では、ユーザー企業 → SIer(元請)→ サブ → 孫 という多重下請け構造が見受けられます。この構造だと、開発はA社、運用はB社、保守はC社という分断が起きやすく、DevOpsの前提である「共通の目標と責任」が成立しにくい環境にあります。DevとOpsが物理的にも契約上も分断されているため、DevOps導入が困難な状況が生まれているのです。 製造業モデルの異なる解釈:工程主義・完璧主義 日本のITは製造業の品質管理思想の影響を強く受けていますが、その解釈に課題がありました。本来、トヨタ生産方式は「継続的改善(カイゼン)」や「小さな改善の積み重ね」を重視し、これはDevOpsの思想と共通しています(実際、DevOpsの「リーン」の考え方はトヨタ生産方式が起源です)。しかし、多くの日本のIT現場では、製造業の手法を「工程の厳格な管理」「完璧な品質の追求」という側面だけを取り入れ、「リリース=出荷」「不具合=欠陥品」という感覚が強くなりました。このため、頻繁なリリース(Continuous Delivery)や早期フィードバックといったDevOpsの実践が「リスク」だと認識される傾向があるのです。皮肉なことに、トヨタ生産方式の本質を正しく理解していれば、DevOpsへの親和性はむしろ高かったはずなのです。 インフラのアウトソーシング文化 データセンターやネットワーク運用を外部委託(SIer、DC事業者など)するのが主流で、自社にインフラ運用の知見が蓄積しにくい環境があります。クラウドネイティブな文化が根付く前は、Opsの自動化やSRE的観点がなじみにくかったのです。これにより、DevOpsの「Infrastructure as Code」「SRE」文化が根付きにくい土壌が形成されていました。 ITが"事業の中核"ではないという認識 海外(特に米国)では、2000年代以降「ITは競争力の源泉」と位置づけられていましたが、日本ではITが依然として「業務支援」「コストセンター」と見なされ、IT部門が戦略の中心になりにくい状況がありました。このため、DevOpsが本来持つ「ビジネス成果を最大化するための仕組み」としての意義が伝わりにくかったのです。 しかし、近年日本企業においてもDevOpsへの関心が高まっています。その背景には次のような変化があります。 クラウドネイティブの普及 :AWS、Google Cloudなどのクラウドサービスの活用が拡大し、インフラのコード化や自動化の基盤が整いつつある 内製回帰の動き :特にメガベンチャーやSaaS企業を中心に、システム開発の内製化が進み、DevOpsの実践がしやすい環境が生まれている 開発生産性の重視 :Developer Productivity向上への注目が高まり、CI/CDパイプラインの構築など、開発効率を高める取り組みが増えている AI革命の波 :ChatGPTをはじめとする生成AIの登場により、ソフトウェア開発および運用の在り方が根本から変化しつつある。コードの生成、テストの自動化、運用時のログ分析や障害対応といった領域でAIが実用段階に入り、従来の手作業中心のプロセスは再構築を迫られている。AIは単なる補助ツールではなく、開発サイクル全体に組み込まれる存在となりつつあり、その文脈においてDevOpsも再定義され始めている。 この変化は一様ではありません。新興企業やIT専業企業ではDevOpsの実践が進む一方、大企業・公共系・受託構造の現場では依然として課題が残っています。 DevOpsとAI導入の共通障壁 冒頭のパトリック・ドボアは、1年前のDevOpsDays Tokyo 2024に於いて 「成熟したDevOps文化を持つ人々こそ、GenAIのアーリーアダプターになりつつある」と仰っており、事実そうなりました。 つまり、AI革命の波が押し寄せる中、DevOpsを受け入れられなかった組織は、同じ理由でAIの波にも乗り遅れる危険性があります。 日本でDevOpsを根付かせるためには、単なる「技術導入」ではなく「組織文化改革」として捉える必要があります。「DevOpsを導入する」=「ツールを導入する」ではなく、「職能や役割を超えてチームが協働する文化を育む」ことであり、この文化的転換が日本では特に重要です。 そのため、日本の組織構造を考慮した上で、DevOpsの本質を理解し、自分たちの組織に合った形で取り入れていくためには、次のようなアプローチが有効と思われます。 変化を恐れない文化の醸成 「失敗は学びの機会」という認識を組織全体で共有する 小さな変更から始め、成功体験を積み重ねることで自信をつける クロスファンクショナルチームの形成 部門の壁を越えた協働を促進し、共通の目標に向かって取り組む環境をつくる 開発・運用・ビジネス部門が一体となって価値を生み出す体制を構築する 長期的視点での投資判断 短期的ROIだけでなく、競争力維持の観点から技術投資を判断する 継続的な学習と実験の文化を育み、組織全体の適応力を高める DevOpsの歴史は、技術の進化だけでなく、人々の協力関係や組織文化の変革の歴史でもあります。その本質を理解し、自分たちの組織に合った形で取り入れていくことが、現代のソフトウェア開発者に求められています。そして、日本の文化や組織構造に合ったDevOpsの形を模索していくことも、私たち日本のエンジニアの重要な課題なのです。 ◆ AI時代の適応 ◆ AI時代は、変化に適応できる組織とそうでない組織の差がさらに拡大します。DevOpsの本質である「変化を恐れず、継続的に改善し続ける文化」は、この時代において競争力の源泉となります。 AIの導入に伴い、一部では大規模言語モデルのコストやセキュリティの観点から自社データセンターでのAI基盤構築が選択されています。しかし、これは単なるオンプレミスへの回帰ではなく、クラウドで培われたDevOps手法(IaC、コンテナ技術)を活用した新たな形態です。インフラの場所に関わらず、「自動化」「協働」「継続的改善」というDevOpsの価値はAI時代においてより重要になっています。 過去にDevOpsの波に乗り遅れた組織も、AI時代という転換点を変革の契機として活かすことができるのではないでしょうか。 【告知】ソフトウェア開発の伝説的パイオニアたちが来日! 2025年7月3日(木)・4日(金)9:30〜19:00、弊社主催「 開発生産性Conference2025 」にて、ソフトウェア開発の歴史を塗り替えた二人の巨匠が来日します。 アジャイルとDevOpsの世界的権威が同時来日する歴史的瞬間に、ぜひ立ち会ってください。 ケント・ベック(Kent Beck) — アジャイル開発の父、XPの創始者、TDDの提唱者。 ジーン・キム(Gene Kim) — DevOps革命の立役者、『The Phoenix Project』著者。 本ブログで紹介した「ソフトウェア開発の開拓者たち」が、目の前で語る貴重な機会です。彼らの思想と実践が世界のソフトウェア開発をどう変えたのか、そして日本のエンジニアが今後どう進むべきか—直接その声を聞ける、まさに一生に一度のチャンスです。 DevOpsの本質を理解し、AI時代を勝ち抜くための知恵を、開発現場の革命家たちから直接学びませんか? 参加登録はこちら : 開発生産性Conference2025公式サイト ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 *1 : Edwards, D. (2014, May 16). The incredible true story of how DevOps got its name. New Relic. https://newrelic.com/blog/nerd-life/devops-name
こんにちは! Findy Team+ 開発チームでEMをしている ham です。 今年もRubyKaigi 2025に参加してきました。 私はコロナ後に三重県で開催されたときから4年連続で参加しているのですが、今年も興味深いセッションがたくさんあり、Rubyが着実に進化していることを感じることができました! 本記事では、その中の1つである「 The Ruby One-Binary Tool, Enhanced with Kompo 」で紹介された「 Kompo 」について、実際に試してみた結果と所感を紹介します。 Kompoとは 'Hello, world!'を返すスクリプト kompo-vfs Kompo Rails 最後に Kompoとは Kompoとは、READMEで「A tool to pack Ruby and Ruby scripts in one binary.」と紹介されている通り、Rubyスクリプトをバイナリにして配布できるツールです。 Rubyのスクリプトをバイナリにすることで、配布が容易になったり、実行環境にRubyのインストールが不要になるため配布先での実行が容易になります。 Kompoは2024年のRubyKaigiでも「 It's about time to pack Ruby and Ruby scripts in one binary 」のセッションで紹介されており、興味を持っていました。 2024年の時点ではRailsなどの大きなGemは実行できていないとのことだったのですが、2025年の発表ではRailsが動いており進化を感じました! 'Hello, world!'を返すスクリプト 今回のセッションでRailsが動作するようになったと発表されていたので、Webサーバーが動作するバイナリを作ってみることにしました。 とはいえ、最初から大きなものを作ろうとすると詰まる可能性が高いです。何事もスモールスタートが良いですね。 入門といえば 'Hello, world!'ということで、まずは'Hello, world!'を返却するRubyスクリプトでトライしました。 なお、ここからの内容は執筆時点(2025年4月)の情報なので最新版では変更されている可能性があります。 kompo-vfs Kompoは内部で仮想ファイルシステムを使っているとのことです。 当初は既存のライブラリで実現できないか検討したとのことですが、Kompoのやりたいことにマッチするものがなかったとのことで「 kompo-vfs 」を自作したそうです。 リポジトリを見ていただければわかりますが、こちらはRustで書かれていました。 Kompoを使うにはまずkompo-vfsをbuildしておく必要があるとのことです。 READMEに沿って作業します。 READMEには次のように記載されています。(※手順はKompoのREADMEに記載されています) ## prerequisites Install [kompo-vfs](https://github.com/ahogappa/kompo-vfs). #### Homebrew $ brew tap ahogappa/kompo-vfs https://github.com/ahogappa/kompo-vfs.git $ brew install ahogappa/kompo-vfs/kompo-vfs ### Building To build komp-vfs, you need to have cargo installation. $ git clone https://github.com/ahogappa/kompo-vfs.git $ cd kompo-vfs $ cargo build --release Set environment variables. $ KOMPO_CLI=/path/to/kompo-vfs/target/release/kompo-cli $ LIB_KOMPO_DIR=/path/to/kompo-vfs/target/release MacBookを使っているのでbrewの手順を試しましたがうまくいかなかったので、リポジトリをcloneする方法で実施しました。 mainブランチで試してみましたが、buildがエラーになりました。 % cargo build --release ... error: could not compile `kompo_storage` ( lib ) due to 2 previous errors; 1 warning emitted こちら色々解析したところ、MacBookには対応してなさそうだとわかりました。 そこでDockerを立ち上げてその中でbuildすることにしました。 Kompoの実行もDockerで実施した方が良さそうだったので、Rubyイメージから作成しました。 # Dockerfile FROM ruby:3.4.3 # Install dependencies RUN apt-get update && apt-get install -y \ git \ build-essential \ libssl-dev \ zlib1g-dev \ libyaml-dev \ libgmp-dev \ libreadline-dev \ pkg-config \ autoconf \ bison \ curl \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Install latest Rust using rustup RUN curl --proto ' =https ' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH= "/root/.cargo/bin:${PATH}" # Set working directory WORKDIR /app # Copy project files COPY . /app/ # Install bundler and dependencies RUN gem install bundler && bundle install CMD [ " tail ", " -f ", " /dev/null " ] buildしてbashでコンテナに入り、改めてbuildしたら成功しました🙌 % docker build -t hello-world . % docker run -it --rm -v .:/app hello-world bash root:/app# cd kompo-vfs/ root:/app/kompo-vfs# cargo build --release ... Finished `release` profile [ optimized ] target ( s ) in 5 .40s Kompo 次に'Hello, world!'を返すRubyスクリプトを作成します。 # hello.rb p ' Hello, world! ' Kompoはgemが公開されていないのでリポジトリをcloneしてローカルで生成します。 色々試行錯誤したのちに気づいたのですが、登壇スライドの26ページによるとkompoは feature/use_rtld_next の方が最新と思われるのでそちらを利用します。 Dockerコンテナ内で gem build を実施して、無事 kompo-0.2.0.gem が生成できました。 root:/app/kompo# gem build kompo.gemspec WARNING: licenses is empty, but is recommended. Use an license identifier from https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, or set it to nil if you don't want to specify a license. WARNING: open-ended dependency on mini_portile2 (>= 0) is not recommended use a bounded requirement, such as "~> x.y" WARNING: open-ended dependency on async (>= 0) is not recommended use a bounded requirement, such as "~> x.y" WARNING: You have specified the uri: https://github.com/ahogappa0613/kompo for all of the following keys: homepage_uri changelog_uri source_code_uri Only the first one will be shown on rubygems.org WARNING: See https://guides.rubygems.org/specification-reference/ for help Successfully built RubyGem Name: kompo Version: 0.2.0 File: kompo-0.2.0.gem 次に、Kompoをインストールします。 root:/app# gem install kompo/kompo-0.2.0.gem ... Successfully installed kompo-0.2.0 10 gems installed 時は来た!あとは梱包(Kompo)するだけです!実行には数分かかるので待ちます。 root:/app# kompo --help Usage: kompo [options] -e, --entrypoint=VAL File path to use for entry point. (default: './main.rb') -g, --use-group=VAL Group name to use with 'bundle install'. (default: 'default') --[no-]gemfile Use gem in Gemfile. (default: automatically true if Gemfile is present) --local-kompo-fs-dir=VAL --verbose Verbose mode. --dest-dir=VAL Output directry path. (default: current dir) --bundle-cache=VAL Specify the directory created by 'bundle install --standalone'. --ruby-version=VAL Specify Ruby version. (default: current Ruby version) --rebuild --repack root:/app# kompo -e hello.rb --local-kompo-fs-dir=kompo-vfs ... /usr/bin/ld: /app/kompo-vfs/target/release/libkompo_fs.a(529179467e613863-dummy_fs.o):(.rodata.WD+0x0): multiple definition of `WD'; /tmp/ccNwyWlB.o:(.rodata+0x0): first defined here /usr/bin/ld: /app/kompo-vfs/target/release/libkompo_fs.a(529179467e613863-dummy_fs.o):(.rodata.PATHS_SIZE+0x0): multiple definition of `PATHS_SIZE'; /tmp/ccNwyWlB.o:(.rodata+0x28): first defined here /usr/bin/ld: /app/kompo-vfs/target/release/libkompo_fs.a(529179467e613863-dummy_fs.o):(.rodata.PATHS+0x0): multiple definition of `PATHS'; /tmp/ccNwyWlB.o:(.rodata+0x30): first defined here /usr/bin/ld: /app/kompo-vfs/target/release/libkompo_fs.a(529179467e613863-dummy_fs.o):(.rodata.FILES_SIZE+0x0): multiple definition of `FILES_SIZE'; /tmp/ccNwyWlB.o:(.rodata+0x192c8): first defined here /usr/bin/ld: /app/kompo-vfs/target/release/libkompo_fs.a(529179467e613863-dummy_fs.o):(.rodata.FILES+0x0): multiple definition of `FILES'; /tmp/ccNwyWlB.o:(.rodata+0x192d0): first defined here collect2: error: ld returned 1 exit status /usr/local/bundle/gems/kompo-0.2.0/lib/kompo.rb:193:in 'Kernel#system': Command failed with exit 1: gcc (RuntimeError) エラーが発生しました。 kompo-vfsで、 WD や PATHS などの定義が重複しているようです。 Rustなんもわからんので雰囲気ですが、 kompo-vfs/kompo_fs/dummy_fs.c の中で WD や PATHS が定義されているので怒られた定義をコメントアウトして再buildしてやり直してみました。 // kompo-vfs/kompo_fs/dummy_fs.c // const char FILES[] = {}; // const int FILES_SIZE = 0; // const char PATHS[] = {}; // const int PATHS_SIZE = 0; // const char WD[] = {47,119,111,114,107,115,112,97,99,101,115,47,114,117,98,121,95,112,97,99,107,97,103,101,114,47, 0}; const char START_FILE_PATH[] = { 46 , 47 , 109 , 97 , 105 , 110 , 46 , 114 , 98 , 0 }; 再度Kompoを実行。今回は正常終了し、バイナリ( app )が生成されました🎉 root:/app# kompo -e hello.rb --local-kompo-fs-dir = kompo-vfs ... info: Finish kompo! root:/app# ls -l app -rwxr-xr-x 1 root root 76437456 Apr 24 02:15 app root:/app# ./app " Hello, world! " 最後に実行します。せっかくなのでRubyが入っていない環境で実行します。 Dockerfileはこちらを使いました。 FROM ubuntu:latest # Set working directory WORKDIR /app # Copy project files COPY . /app/ CMD [ " tail ", " -f ", " /dev/null " ] コンテナを立ち上げて、バイナリを実行します。 Rubyが入っていない環境で実行できました🎉 % docker build -t ubuntu-app . % docker run -it --rm -v .:/app ubuntu-app bash root@62df4e7aa257:/app# ./app " Hello, world! " Rails 簡単なRubyスクリプトでは実行できることがわかったので、次はRailsに挑戦です! ただ、結論は「色々試行錯誤したものの起動できず」でした... Kompoするところでエラーになったり、Kompoはできたが起動できなかったり、これ以上の解析は難しいので今回は諦めました🙏 最後に 今回は簡単なRubyスクリプトしかできませんでしたが、ワンバイナリで配布してすぐに実行できることはとても便利だと感じました。今後の更なる進化に期待です!! 5/13(火)に、「After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜」として、ピクシブ株式会社、株式会社ZOZO、ファインディ株式会社の3社でRubyKaigi 2025の振り返りを行います。 LTやパネルディスカッションなどコンテンツ盛りだくさんなのでぜひご参加ください!! https://pixiv.connpass.com/event/352852/ pixiv.connpass.com また、ファインディではこれからも新しいものを取り入れつつ、Rubyを積極的に活用してRubyとともに成長していければと考えております。 一緒に働くメンバーも絶賛募集中なので、興味がある方はぜひこちらから ↓ herp.careers