TECH PLAY

Findy/ファインディ

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

181

こんにちは。 ファインディ で Tech Lead をやらせてもらってる戸田です。 弊社では沢山のエンジニアがJOINしてくれておりますが、2年ほど前から「成長が期待ができる」エンジニアの採用もするようになりました。 そのため、エンジニアの教育についても様々な取り組みを行っており、それらの取り組みを明文化してエンジニア教育メソッドとしてドキュメント化を行いました。 そこで今回は、ドキュメント化された弊社のエンジニア教育メソッドの一部を公開したいと思います。 それでは見ていきましょう! 教育メソッドの目的 教育メソッドの一部を紹介 目の前のことに集中 色々なことを一度に叩き込むのではなく、段階を踏んで1個ずつ確実に覚えていく 正しい方法を正しい手順で作業する 教育メソッドをより良いものにしていく まとめ 教育メソッドの目的 まず教育メソッドを作成した目的について説明します。教育メソッドには次のように定義しました。 - 組織全体の「人数だけではない拡張性」を高める - 人数が倍になったら全体のアウトプット数が3倍になるような組織を目指す - チーム内だけで継続して育成することができるようになる ありがたいことに直近数年の弊社のエンジニア採用は順調に進んでおり、フルタイムだけで50人を超える規模になりました。 しかし、増えた人数に対して組織全体のアウトプット数が思ったよりも伸び切らないという悩みも出てきました。 伸び悩んでいた背景に、急激に人数が増える中でエンジニア達に対するサポートが追いついていないということがありました。これまでにない成長をしてきた我々にとって新しい課題でした。 当時は開発組織全体を見ている自分が特定のチームに一時的に入ってサポートすることで対応していましたが、これでは人数が増えてもスケールしづらいという課題が出てきました。1人で見ることが出来る人数には限界があるからです。 そこで自分が直接サポートする必要がないように、各チーム内で継続して育成するための指標、教科書としての教育メソッドを作成することになりました。 教育メソッドの一部を紹介 目の前のことに集中 - 記載されている教育メソッドの中で、一番重要なのがこれ - 他のことに目移りしているエンジニアが伸び悩む - 伸びる理由は人それぞれだが、弊社の環境で伸び悩んでいたエンジニアの全員に共通していたのがこれ - 目の前の一つのことに集中するように促す - 一定の等級以上に上がるまでは、問い合わせ対応や障害調査からは外し、与えられたタスクに集中してもらう - やることが無いのであれば、やることを一緒に探して考える - コードを一緒に追っていけば、小さなリファクタやテスト追加など必ず何か見つかる - 一緒に探して考えることが重要 - 「やりたいこと」ではなく「やるべきこと」に集中してもらう 作成した教育メソッドの中での最重要項目となっています。 inputした内容以上のoutputは出ないと考えており、まずinputを優先してもらうためにも重要な内容と言えるでしょう。 新しい環境が目新しく映り、やりたいことが沢山出てきたり、色々なことに興味が出るのは当然のことです。しかし1つのことを集中してやり切ることが出来なければ、他のことを並行してやり切ることは難しいのです。 そのため一定以上の等級、レベル感に上がるまでは、とにかく目の前のタスクだけに集中してもらうように促しています。 やりたいことをやらせてあげたい気持ちはありますが、まずは目の前の「やるべきこと」に集中してもらうことが重要です。 色々なことを一度に叩き込むのではなく、段階を踏んで1個ずつ確実に覚えていく #### 3段階に分けて確実に覚えていく - 基礎 - スキルマップを参照 - 手数 - 小さい修正内容でいいので、適切な粒度でPull requestを沢山作る - 量は質に転化する - 質と理解 - 正しいコードを理解して利用する - Pull requestでコメントを貰うことは問題ではない - 問題はコメントの内容 - セルフレビューで防げるようなことに対してのコメントは質が低い - 実装内容やパフォーマンスなど、本質に近いものに対するコメントを貰うことはOK #### クリアできるところ、つまずくべきところは分けて考える - セルフレビューで防げる指摘は、技術力や経験に関係なくクリアできるはず - テストや型定義、非同期処理やPromiseなど、難易度が高くて重要な要素はつまずいても問題ない - つまずくべきところでつまずいているかが重要 - 難易度が高いところでのつまずきが増えてきたということは成長している証拠 - 同じ失敗を繰り返さないことが重要 まず 基礎 手数 質と理解 の3段階に分け、段階を踏んで1個ずつ確実に覚えていくようにします。 基礎に関してはエンジニアの職種別にスキルマップを用意しており、自分に必要とされている項目をその都度覚えてもらいます。 手数に関しては、とにかく小さい修正でもいいので適切な粒度でPull requestを作り続け、大量のフィードバックを得るようにします。 量は質に転化すると言われているように、手数が増えれば増えるほど結果的に質と理解が深まっていき、最終的にはスピードが身に付きます。 また、指摘事項が多い場合はPull requestの粒度が大きすぎるケースが多く、そういったケースでは粒度を細かくしてPull requestを作り直してもらいます。一度に100個指摘されて100個覚えるよりも、1個指摘されて1個覚えることを100回繰り返すほうが覚えやすいからです。 この時、クリアできるところ、つまずくべきところは分けて考えています。 例えばlintやtypoでの指摘はセルフレビューである程度防げるはずであり、技術力や経験に関係なくクリアできるはずです。この指摘が多い場合は指導します。 逆にテストコードや型定義など難易度が一定以上高い要素に対する指摘を貰うことは問題ありません。次に同じような指摘をもらわなければ良いのです。 このように一度に全てのことを詰め込んで覚えてもらうのではなく、段階を追って覚えるべきタイミングで1個ずつ覚えてもらうことを重要視しています。 正しい方法を正しい手順で作業する - 正しい方法と手順を徹底するよう促す - 既存コードを変更するならば、まずは該当するテストコードの存在を確認 - テストが漏れてるなら、まずはテストケースの追加を先に行う - etc - スピードは気にしない - まずは正しい方法と正しい手順を身に付ける。そこから手数を増やし、結果的にスピードが身に付く。 - スピードは後から勝手に付いてくるものであり、最初から求めるべきものではない 開発や業務を進めるうえで、スピードを求める前に正しい方法と手順を覚えることを優先します。 単純な例で言うと、既存実装を変更する際にはまず該当するテストコードの存在を確認し、テストが漏れている場合はテストケースの追加を先に行います。 正しい方法と手順に拘る理由は2点あります。 1つ目は本当の意味で理解するためです。正しい方法と手順には必ず理由と意味があり、それらを理解して作業を行うことで何故その作業が必要なのかを理解することに繋がります。 2つ目は結果的に最速になるのが正しい方法と手順だからです。一見遠回りに見える時もあるかもしれませんが、開発サイクルを回す上で結果的に一番速く効率的な方法と手順が身に付くようになります。 教育メソッドをより良いものにしていく ドキュメント化された教育メソッドはGitHub上で管理されており、弊社エンジニアであれば誰でも閲覧して、変更提案のPull requestを作成することが出来るようにしました。 これは、今回作成した教育メソッドがver1.0という立ち位置であることを示しています。教育メソッドは会社のフェイズ、時代背景、開発組織の状態などに応じて変化し続けなければいけないものと考えているからです。 実際に教育メソッドを運用して気付いたことや、改善案やフィードバックがあれば積極的に提案してもらい、教育メソッドをより良いものにしていきたいと考えています。 まとめ いかがでしたでしょうか? 今回は弊社のエンジニア教育メソッドの一部のみを公開しました。 実際に私がこの教育メソッドを適用して、とあるメンバーを3ヶ月程度サポートした結果、Findy Team+上の数値は次のように向上しました。 Pull request作成数の1日あたりの平均が4個だったのが2倍以上の9個に増加しました。彼は私のサポートが外れた現在も、引き続き高いアウトプットを出し続けることが出来ているそうです。個人差はありますが社内の他の事例でも一定の教育効果が出ており、今後の成長が楽しみです。 現在、ファインディでは一緒に働くメンバーを募集中です。 今は技術力や経験に自信は無いけど、弊社の環境で爆速成長したいエンジニアの皆さん。 是非一度カジュアル面談を受けてみませんか? 興味がある方はこちらから ↓ herp.careers
アバター
こんにちは。こんばんは。 開発生産性の可視化・分析をサポートする Findy Team+ 開発のフロントエンドリードをしている @shoota です。 ファインディではチームの 小さな開発サイクルを高速に回し 、 価値を創りだすまでの開発生産性を高く維持するための開発環境を整えています。これまでもこのテックブログにてその実情やテクニックをご紹介してきました。私自身もこの開発環境の恩恵を十分に受けるとともに、 Findy Team+ の組織拡大と高水準な開発生産性の維持を両立させるために、リファクタリングや環境整備をミッションとして働いています。 先日、オライリー・ジャパンより Tidy First? ―個人で実践する経験主義的ソフトウェア設計 が発刊されました。本書ではコードを 整頓 するための実践的なテクニックや、そのための考え方がよく言語化されています。私はこれまで経験的に実践してことを本書を通して言語化されていくことで、リファクタリングの意味や適切な運用方法に対する理解をさらに高めることができました。 そこで今回はこの「Tidy First?」の内容のほんの一部とファインディでの取組みやこれまでの記事とを照らしあわせ、本書のエッセンスとファインディが取り組んでいる開発改善の姿勢を改めてご紹介したいと思います。 なお本書は三部構成となっておりますが、第一部はコード改善(整頓)の実践的なテクニックのため割愛します。 明日から使えるテクニックがたくさんありますので、ぜひ実際に読んでみてください。 第二部 16章 分けて整頓する 第二部 18章 バッチサイズ 第二部 21章 先に整頓、あとに整頓、改めて整頓、整頓しない 第三部 26章 オプション まとめ 第二部 16章 分けて整頓する 本書ではリファクタリングを「構造の変更」と「振る舞いの変更」に分けて解説されていますが、16章ではこの変更を分けてプルリクエストせよ、といった趣旨が書かれています。これはまさにファインディが考える「プルリクエストの粒度」と合致する内容になっています。 ファインディでは プルリクエストをできるだけ小さく することを強く意識づけていますが、一方で作業工程をバラバラにするだけでは意味がありません。そこで分解するときのプルリクエストを 適切な粒度 に分けることを意識しています。詳細は Findyの爆速開発を支えるPull requestの粒度 - Findy Tech Blog に記述していますが、その中で そのプルリクエストが1つのことに注力できているかどうか と表現しています。 また16章冒頭では変更の種類ごとにプルリクエストを分割すると、レビュー負荷を軽減できることが述べられています。 レビュアーがいかに素早く変更の意図と内容を把握できるかという点では、リファクタリングだけでなく、通常の機能開発にも当てはまるテクニックと言えるでしょう(機能開発を進めるときにコードを整頓するような小さなリファクタリングもあるでしょう)。 機能開発での「変更の種類を分ける作業」は タスク分解 にあたります。タスク分解の重要性については次の記事で記述していますが、やはりプルリクエストの粒度にも効果があることをファインディでの取組みとして説明しています。 tech.findy.co.jp 第二部 18章 バッチサイズ 前項では「変更の種類」から分解することで、プルリクエストも適切な粒度にできることがわかりました。そしてレビュー負荷をさげて、 小さな開発サイクルを回す ことの重要性についても過去の記事で述べています。しかしそれでもプルリクエストが巨大になってしまうことがあるでしょう。 18章ではこれを開発コスト、つまりレビュー負荷やコンフリクトの発生率、リファクタリングの連鎖の面から言及しています。 これらはファインディの開発への取組みでも重要視されています。先ほどにも挙げた、次の記事を見てみましょう。 tech.findy.co.jp 18章ではレビューが不要なものを見極め、チームとしての信頼や文化につなげることを説いていますが、ファインディではこれを自然に実践しています。 GitHubの設定上でレビュアーが必須となっていますが、小さくまとまった改善はほぼレビューの時間をとらずにマージしています。 粒度が適切なPull requestが当たり前となれば、レビューを最優先にする習慣、文化が組織に根付くはずです。 弊社では1つのPull requestのレビューに掛ける時間はほんの数分程度となっています。1分以内で終わることもあります。 プルリクエストの粒度と合わせて「レビューが不要なプルリクエストはあるか?」や「このレビューはどれくらいで終わるか?」といった観点から、変更の範囲(バッチサイズ)を検討し、これをチームで共有することで、自然とチームの開発生産性を高いレベルで維持する文化を大事にしています。 第二部 21章 先に整頓、あとに整頓、改めて整頓、整頓しない ここまでは「プルリクエストをどれくらいの大きさにしようか?」といった観点で見てきました。しかしリファクタリング活動にはもう1つ大事な要素があります。それは 「いつやるか?」 です。 この21章ではリファクタリングを機能開発の前にやるか、あとにやるか、それともやらないか?といった「いつ」の選択肢についての言語化がされています。ここは以前の私の登壇資料とともにファインディの考え方をご紹介したいと思います。 この21章ではリファクタリングを実行するタイミングをタイトルの4種類に分け、「いつ」の選択肢に関する考え方が言語化されています。要約すると「リファクタリング(整頓)によってどれくらいの見返りがあるかは『状況による』ので、対象コードの変更頻度をもとに判断しよう。」といったものです。 この判断方法に関しては、以前の私の登壇資料とともにフィンディでの考え方をご紹介したいと思います。 結論からいうと、ファインディでは「いつ?」の判断軸を明確にしていません。ただし「リファクタリングはいつやってもいい」ということと、「リファクタリングはいつも求められている」ということを、メンバーが共通に認識しています。 ある機能のための変更前に 「小さな改善」 をすると、後続の開発が円滑に進むことを私達は知っています。これはFindy Team+のドッグフーディングから得られた事実です。「まだ見ぬ機能」のために抽象化したり共通化したりすることはせず、「これから作るもの」のために適切に抽象化や共通化を施します。 しかし開発を進めると構造的な歪みやわかりにくいコードが生まれてしまうこともあるでしょう。そこで機能開発のあとにもリファクタリングをします。「リファクタリングのためのリファクタリング(リファクタリングの連鎖)」が起きにくくなるようにし、次の機能開発が 「小さな改善」 から始められるようにするのです。 プルリクエストのレビュー指摘としてリファクタリングを求められることもありますが、これも 「プルリクエストの中で必ず直さなければならないものではない」 としています。 「プルリクエストを小さく / バッチサイズを分割する」の前提にたって、「いつやるか?」に対してメンバーそれぞれの裁量で判断するようにしており、本書の内容と合致するチーム文化で進めています。 第三部 26章 オプション 第三部では価値提供とリファクタリングのコストの関連性や設計や基礎理論について書かれています。少し抽象的にはなってしまいますが、この記事の最後にこれらについても軽く触れておきたいと思います。 26章では提供する価値の選択肢とそれらの時間的な変化について解説されています。三部の内容についてはここでは書ききれないのでぜひ読んでいただきたいと思いますが、暴力的に噛み砕いてまとめるならば、 将来的な変更可能性に備えてどれだけはやく現在の振る舞いを確定できるかが大事 ということになるかと思います。 これらについてファインディでの姿勢は 、 Findyの爆速開発を支える、価値提供を最優先にするための開発手法 - Findy Tech Blog にてご紹介しています。 綺麗なコードは後。アプリケーションの振る舞いが先。 (中略) 最初の段階で綺麗なコードを突き詰めることよりも、ユーザーに早く価値提供をすることを優先しています。 機能開発のなかでリファクタリングの必要性に気づくことは良くあります。しかし先ほども述べた通り、「いつやるか?」をルールとして決める必要はありません。プルリクエストをマージする前でも、あとでも、デプロイのあとでもリファクタリングをする意味はあります。重要なのは 開発の不確実性を収束させるには、振る舞いを確定させる必要があり、価値の不確実性はリリースによって収束していく ということです。 まとめ いかがでしたでしょうか。 今回は Tidy First? ―個人で実践する経験主義的ソフトウェア設計 とともにファインディの生産性向上への姿勢をご紹介しました。 私個人としては今回ご紹介できなかった本書の内容もとても重要で、チームメンバーにもおすすめの一冊となりました。 また「Tidy First?」について 翻訳者の方々にお話しをいただくイベント も予定しています。 今回は 翻訳者3名の方全員に集結いただき、参加者に本書の抽選プレゼントも予定 していますのでぜひこちらもチェックしてください。 findy.connpass.com
アバター
こんにちは。 突然ですが皆さんは、開発をするうえで欠かせないツールやOSSはありますか? キーボードやマウス、マイクといった物理的なツールは机を見ればわかりますが、他のエンジニアがどういったツールを使って効率化しているかは、その人の画面を見ないとわかりません。 そのため、他のエンジニアがどういったツールを使って効率化しているのか、実は意外と知らないということが多いのではないでしょうか? そこで今回は、大変ご好評いただきました 【エンジニアの日常】これが私の推しツール!〜日々の開発を豊かにするおすすめツール〜 Part1 の第二弾としまして、弊社エンジニア達が日々の開発業務で愛用しているツールやOSSを紹介していきます。 それでは見ていきましょう! Neovim Neovimの概要 Neovimで開発する コミュニティが活発 おすすめポイント lazygit 主なキーバインド Neovimとの連携 lazygitの良さ Raycast Raycastの概要 Raycastのセットアップ Raycastのおすすめ拡張機能 おすすめポイント ghq, peco ghqの概要 pecoの概要 ghq × pecoの便利な組み合わせによるリポジトリ移動 おわりに Neovim ファインディでSREを担当しています 大矢 です。昨年からSREはチームとなりました。これからもチームとして社内外ともに盛り上げていきたいと考えています! まずはそんな私から、推しツールのNeovimをご紹介します。 Home - Neovim Neovimの概要 NeovimはVi系エディタの1つです。元々Viというテキストエディタがあり、その拡張版としてVimが開発されました。NeovimはVimの派生版で、2025年現在も活発に開発が続けられています。 Viは、マウスなどを使わずにキーボードのみで操作可能なエディタで、その操作性は派生版であるNeovimにも受け継がれています。 Vi系エディタは、ノーマルモード、挿入モードなど複数のモードを切り替えながら操作するため、初心者には敷居が高いと感じるかもしれません。 しかし、一度慣れてしまえば、キーボードのみで高速にテキストを編集できる非常に強力なエディタです。 Neovimで開発する Neovimは標準でターミナル機能やLSPをサポートしています。そこにプラグインも併せて導入することでIDEのような環境を実現できます。 私自身Neovimを使って開発しており、次のようなプラグインを導入しています。(一部のみ) プラグイン 概要 lazy.nvim Neovimのプラグインマネージャ Neo-tree.nvim ファイルエクスプローラー telescope.nvim ファジーファインダー nvim-treesitter 高精度なシンタックスハイライト lualine.nvim ステータスラインのカスタマイズ GitHub Copilot for Vim and Neovim GitHub Copilot公式プラグイン プラグインを導入すると、このような見た目になります。IDEのように見えますね。 また、導入するプラグインの数にも依存しますが、起動に1秒もかからないという早さも嬉しいポイントです。 $ time nvim real 0m2.792s user 0m0.211s sys 0m0.116s コミュニティが活発 Vim / Neovimは国内のコミュニティも活発で、特にvim-jp Slackコミュニティは多くの情報交換が行われています。 vim-jp.org Vim / Neovim以外にもJavaScript, Ruby, コンテナ等々、幅広い話題を取り扱われているので、個人的にはVimを利用されていない方々にもお勧めできるコミュニティです。 おすすめポイント Neovimのおすすめポイントをまとめると、次のようになります。 Neovimはキーボードのみで操作可能なテキストエディタ プラグインを導入することでIDEのような環境を実現可能 起動が早い 国内のコミュニティも活発(Vim含む) Neovimは非常に優秀なツールです。今までVi系エディタを使ったことがない方も、この機会に試してみてはいかがでしょうか。 lazygit バックエンドエンジニアの 西村 です。 私が紹介したいツールはlazygitです。 github.com 普段、私はGitHubを使いながら開発をしています。 開発する中で一日何回もcommitやプルリクエストやブランチ作成をしています。 当時は作業ごとにgitコマンドを打っていることがとても手間でした。 少しでも作業を楽にしたいと思っていたところ、lazygitを見つけました。 lazygitはgitの操作をcliで行うことができるツールです。 基本的にcommitを作る等のgit操作に対応するキーがひとつ割り当てられています。 主なキーバインド space : ファイルのステージ/アンステージ a : すべてのファイルをステージ/アンステージ c : コミット作成 p : ローカルブランチへプッシュ P : リモートブランチへプッシュ d : 差分削除 このようなキーバインドを利用することでgitの基本的な操作をキーボードのみで行うことができます。 さらに、リベースやCherry-pickといった高度な操作をできます。 commitのログをグラフとともに表示しつつ、git bisectやamend等ができるため、git操作が苦手な方でも使いやすいツールになっています。 Neovimとの連携 普段、私はNeovimというエディタを使っています。 Neovimを閉じずに、lazygitを起動するため、Neovim上でlazygitを起動できるようにしています。 これによって、Neovimを使いながら素早くcommitを作成できます。 また、ターミナル上で素早くlazygitを起動するために、次のようなエイリアスを設定しています。 # ~/.zshrcに書いています。 alias l = ' lazygit ' lazygitの良さ lazygitを使うことで Gitの操作が格段に効率化される 複雑な操作も視覚的に確認しながら実行できる Neovimと連携することで、コミット作成〜プルリク作成まで完結できる 特にキーボード主体で作業したい開発者には、おすすめしたいツールです。 Raycast みなさんこんにちは。SREチームの 安達 です。私からは絶賛愛用しているRaycastについて紹介します。Macを使う人なら、SpotlightやAlfredなどのランチャー機能を一度は使ったことがあると思います。Raycastは多機能かつ高速で、様々な便利機能を備えているのでおすすめです。 https://www.raycast.com/ github.com Raycastの概要 MacのSpotlightやAlfredなどのランチャーアプリで、アプリケーションの起動などあらゆる作業を高速化できるツールです。具体的に次のようなことが操作可能です。 アプリやファイルの検索・起動 クリップボードの履歴管理 Web検索 システム管理(音量・画面輝度・シャットダウンなど) GitHubなどの連携 カスタムスクリプトや拡張機能の追加 さて、簡単にセットアップからおすすめの拡張機能について紹介していきましょう。 Raycastのセットアップ インストール $ brew install --cask raycast Generalからホットキーの設定 Shift Shift ホットキーは悩みどころですが、自分はShiftを2回押すことで立ち上がるようにしています。意外と便利です。 インポートとエクスポートについて Raycast Settings > Advanced > Import/Export Raycastでインストールした拡張機能や設定をエクスポートして、他のMacからインポートできます。 拡張機能のインストール方法 Shift Shift > Store Raycastのおすすめ拡張機能 Google Search https://www.raycast.com/mblode/google-search Google検索をブラウザを開かずに実行できます。検索バーにキーワードを入力するだけで、即座にGoogleの検索結果を表示できます。 Two-Factor Authentication Code Generator https://www.raycast.com/cjdenio/two-factor-authentication-code-generator Google AuthenticatorやAuthyのように、ワンタイムパスワード(OTP)を生成できます。アプリを切り替えずに2FAコードを取得できるので、セキュアかつスムーズなログインが可能になります。Alfredでは有料ですが、Raycastだと無料で利用できるのが素晴らしいですね。 Password Generator https://www.raycast.com/joshuaiz/password-generator 大文字と小文字、特殊文字などのオプションを使用して、5~64文字のランダムパスワードを生成できます。 Window Manager https://www.raycast.com/core-features/window-management Window ManagerはMacのアプリケーションウィンドウを高速で移動したり、拡大と縮小が可能です。自分は自宅がウルトラワイドモニターなので、ChromeをFirst Thirdにし、vscodeをLast Two Thirdsにすることで、2対一の割合で表示しています。便利。 Clipboard History https://www.raycast.com/core-features/clipboard-history 過去にコピーしたテキストや画像を一覧表示し、簡単に再利用できます。ショートカットキーは ⌘ + Shift + C にしています。 Snippets https://manual.raycast.com/snippets よく使う定型文を保存し、一瞬で呼び出すことが可能です。例えば、メールアドレス、コードスニペット、など入力できます。ショートカットキーは ⌘ + Shift + V にしています。 GitHub https://www.raycast.com/raycast/github GitHubを開かずに、リポジトリ検索・Issue / PR の管理・通知の確認が可能です。ですが、Organizationは利用できないので、個人のリポジトリのみになります。 Speedtest https://www.raycast.com/tonka3000/speedtest ブラウザを開かずにインターネットのダウンロード速度・アップロード速度・Pingをすぐに測定できます。地味に便利。 1Password https://www.raycast.com/khasbilegt/1password 1PasswordをRaycastに統合すれば、ブラウザやアプリを開かずにワンクリックでログイン情報を取得可能です。 Slack https://www.raycast.com/mommertf/slack Slackアプリを開かずにメッセージを送信、チャンネルを検索、DMを開始、ステータス変更などが可能です。個人的には Open Unread Messages で未読メッセージと Open Channel でチャンネルの検索ができるのはかなり重宝します。 おすすめポイント Raycastは、他のランチャーアプリと比較して以下のような魅力を持ち、エンジニアだけでなく幅広いユーザーにもおすすめできるツールです。今後はWindows版のリリースも予定されており、さらなる進化が期待されますね。 https://www.raycast.com/windows シンプルで直感的なUIとキーボードのみでアプリの確認が可能 プラグインによる機能拡張が可能 コードを活用した無限のカスタマイズ性 クリップボード履歴 & スニペット機能で作業効率アップ 高速 & 軽量でストレスフリーな操作感 ghq, peco こんにちは。去年の12月に入社しました、SREチームの 原 です。 私からはpecoとghqを使ったリポジトリ移動についてご紹介します。普段の業務で複数のリポジトリを行き来する場面が多く、そのたびcdコマンドでパスを入力してリポジトリを移動するのがかなり面倒でした。 そこで、pecoとghqを組み合わせたリポジトリ移動を取り入れ、瞬時に目的のリポジトリへ移動できるようになりました。 ghqの概要 github.com ghqはGitHubのリポジトリを管理してくれるCLIツールです。規則正しいディレクトリ構造に自動的に整理して保存し、管理しているすべてのリポジトリ一覧を簡単に取得できます。 Macの場合、ghqは次の方法でインストールできます。 $ brew install ghq 管理用のrootディレクトリを設定しておくことで、そのディレクトリ配下にリポジトリが整理されます。 $ git config --global ghq.root ' ~/src ' pecoの概要 github.com pecoは、リスト形式で表示された項目をインタラクティブにフィルタリングできるシンプルなツールです。CLI上で大量の情報から特定の項目を素早く選べるため、リポジトリを探す際にも非常に便利です。 Macの場合、pecoは次の方法でインストールできます。 $ brew install peco ghq × pecoの便利な組み合わせによるリポジトリ移動 これらのツールを組み合わせてリポジトリ間の移動を効率的にする方法を紹介します。管理しているリポジトリ一覧を取得するghq listコマンドとpecoを組み合わせると、gitリポジトリのみが抽出対象となります。 ターミナルの設定ファイルに次のようなエイリアスを設定して、ローカルリポジトリを移動できます。 # ~/.zshrcに書いています alias repo =' cd $(ghq list --full-path --exact| peco) ' ターミナルでエイリアスに設定したrepoコマンドを実行してみると、リポジトリの一覧が表示されます。目的のリポジトリ名を選択して、Enterを押すと瞬時に移動します。 この組み合わせを導入してからは、リポジトリ移動のストレスがなくなり、業務での作業がスムーズになりました。必要なときにサッとリポジトリへアクセスできます。 複数のリポジトリを行き来しながら開発されている方には、おすすめの組み合わせとなります。 おわりに いかがでしたでしょうか。今回は私達の推しツールを紹介しました。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
ファインディでデータエンジニアとして働いている ひらき( hiracky16 )です。 今回はデータ基盤チームで「エンドユーザーのためのデータ品質向上への取り組みと展望」という題目で合同勉強会を開催したので、そのレポートをお届けします。 データエンジニアは自社内の課題解決に集中するあまり、一般的なアプローチを学ぶ機会が不足しやすい傾向にあります。 私たちのチームでは特に「データ品質」について、場当たり的な対応が多く、十分な知見を持ち合わせていませんでした。 合同勉強会は、他社での実践的な取り組みや異なる視点を学ぶ絶好の機会になります。 特にクローズドな勉強会では、課題や悩みを気兼ねなく共有し、解決策を議論できるのが大きな魅力です。 今回の勉強会で得られた学びや成果を共有し、その魅力をお伝えできればと思います。 きっかけ ファインディでは、データの利活用を加速させるためにデータ基盤の構築を進めています。 先日公開したテックブログでは、Findy Toolsというローンチから1年ほどのプロダクトにおいて、事業上重要なデータを蓄積する仕組みを整えた話を紹介しました。 チーム発足から1年余りで、データ基盤のインフラが整いつつあります。 tech.findy.co.jp 構築してきたデータ基盤の運用フェーズになると、データ基盤に連携されるデータや、業務で使用するテーブルの品質が課題となりました。 また、データだけでなくSQLの品質基準についても、データエンジニアとデータ利用者の間で認識の違いがあり、記述方法や設計で議論になることが多々ありました。 これらの課題が業務に影響を与え始めており、データエンジニアとして早めに対処する必要がありました。 ただし、当時は品質向上に関する知見が不足しており、これもチームの課題として挙げられていました。 そんな中、「合同勉強会を開催しませんか?」とタイミーさんからお誘いいただきました。 タイミーさんはFindy Toolsにも寄稿いただいた実績があり、その内容を参考にさせていただいていたので、非常に助かるお話でした。 findy-tools.io findy-tools.io 2~3回の打ち合わせを重ねて、勉強会の方向性やスケジュールを決定しました。 事前にデータに関する悩みや取り組みを共有し合うことで、当日話す内容をすり合わせることができました。 これにより、お互いの期待値を理解し、先方が聞きたい内容をLTに反映できたと思います。 打ち合わせを進める中で、「今回はよりクローズドな話もできれば」との意見が出たため、弊社のイベントスペースを使用しオフラインで開催することにしました。 「エンドユーザーのためのデータ品質向上への取り組みと展望」と題し、双方でLT登壇者を募り、資料を準備して当日を迎えました。 勉強会の様子 当日のアジェンダです。 各社のLTがあったあとに懇親会も兼ねてディスカッションの時間を設けることにしました。 ここからはファインディの発表内容を中心に勉強会を振り返っていきます。 「マルチプロダクトのデータ基盤にデータメッシュを採用した話」ひらき 以前、弊社のデータ基盤は事業部問わず1つの基盤にデータを蓄積する中央集権型を採用していました。 しかし、利用用途が多岐にわたるにつれ、依存関係や権限管理が複雑化し、データの利活用におけるアジリティが低下するという課題が発生しました。 そこで、事業をドメインと捉えたデータメッシュを採用し、事業部ごとにデータ品質を高められる設計へとリアーキテクチャしました。 以下は、データメッシュの4つの基本原則をどのように実装したかを解説しました。 とはいえ、データメッシュにも課題があります。 その1つは、複数事業のデータ基盤を運用するコストが高いことです。 データエンジニアだけの頑張りではリソースが足りず、持続可能性にも限界があります。 そのため、領域の近いデータ利用者やデータ生成者を巻き込む体制を構築し、データメッシュを実現しました。 弊社のデータ基盤のアーキテクチャ図については、Findy Tools にも詳しく記載しています。 findy-tools.io 「PII保護のためのDLP運用」たがしら ファインディでは、多くのユーザー情報を扱うため、データ基盤におけるPII(個人識別情報)保護が重要な課題となります。 基本的な権限管理やマスク処理は、IAMやBigQueryのポリシータグを活用しています。 ただし、データメッシュの採用によりドメイン間で担当が分かれた結果、データインフラの実装が異なるようになりました。 これを解決するため、HCP TerraformのPrivate Registryを使い、インフラコードを共通化し、機能差分が生じないようにしました。 また、文字列中に含まれる個人データに関しては、DLP APIとBigQueryのリモート関数を用いてマスク処理を行っています。 エッジケースに対応するため、独自の辞書を管理し、日々更新しながらマスク処理を自動化しています。 タイミーさんのLTについては、テックブログで公開されていますので、ぜひご覧ください。 tech.timee.co.jp グループディスカッション 両社のLT終了後、終了時間までディスカッションの時間を設けました。 事前にいくつかテーマを準備していましたが、各々が近しい領域で自然に会話の輪を広げていたため、用意は不要でした。 LTの内容に限らず、日々の業務での悩みや使用している技術について、密度の濃い議論が交わされました。 議論は大いに盛り上がり、終了時間ギリギリまで話が尽きることはありませんでした。 まとめ 合同勉強会を開催するのは初めてだったため、準備を含めて大変でしたが、総じて成功だったと感じています。 メンバーからは「タイミーさんの取り組みが参考になった」「懇親会で同業者と話せて良かった」などのフィードバックを得られ、開催した甲斐がありました。 事前のすり合わせも功を奏し、タイミーさんのLTは弊社の課題に通ずる内容が多く、大変勉強になりました。 懇親会でもLTの話題について深く議論でき、理解をさらに深めることができました。 深いディスカッションができたのも、オフライン開催ならではの良さだと改めて感じています。 合同勉強会をお誘いいただき、弊社までご足労いただいたタイミーの皆さん、本当にありがとうございました! 今後もこういった合同勉強会の機会があれば開催していきたいと思います。 弊社の取り組みについては、引き続きテックブログで発信していく予定です。 興味がありましたら、ぜひひらき( hiracky16 )までご連絡ください!
アバター
ファインディ株式会社 でフロントエンドのリードをしている新福( @puku0x )です。 弊社のフロントエンドの多くは、プロダクト単位のモノレポで管理されています。 Nx を用いたモノレポでは、アプリケーションや関連モジュールを「プロジェクト」として管理しており、モノレポ内にある多数のプロジェクトを組み合わせてアプリケーションを作るため、各プロジェクトの依存関係の制御が非常に重要となります。 この記事では、Nxが標準搭載しているESLintルール @nx/enforce-module-boundaries を活用し、モノレポにおけるプロジェクトの依存関係の制御についてご紹介します。 Nxについては以前の記事で紹介しておりますので、気になる方は是非ご覧ください。 tech.findy.co.jp モノレポにおける依存関係の課題 @nx/enforce-module-boundaries Findyでの活用事例 まとめ モノレポにおける依存関係の課題 モノレポで開発していくと、モノレポ内のプロジェクトの依存関係が複雑になっていきます。 「ビルドが通らないと思ったら循環参照していた」 、 「関心の異なるモジュールがimportされていた」 など、思い当たるものがあるのではないでしょうか? 複雑な関係を持つプロジェクトの皆さん モノレポを用いた開発では、プロジェクト間の依存関係を適切に制御する必要があります。 つまり、 循環参照の防止 依存許可/拒否のルール定義 をいかに開発プロセスへ落とし込むかが課題となります。 特に、Nxを用いたモノレポでは プロジェクトの粒度がキャッシュヒット率の高さ(=CI速度)に直結する ため、プロジェクトの細分化を積極的に行う傾向があります。 プロジェクト数の増加・複雑化を避けて通れない以上、プロジェクト間の依存関係の制御は必須となるでしょう。 @nx/enforce-module-boundaries Nxには、モノレポ内のプロジェクトの依存関係を制御する仕組みとして、 @nx/enforce-module-boundaries というESLintルールがあります。 nx.dev @nx/enforce-module-boundaries は標準で循環参照を防止します。さらに、各プロジェクトに設定したタグを元に依存関係の制御も可能です。 例として、次のような依存関係を考えます。 libs/componentsからlibs/uiへの単方向依存 それぞれのプロジェクトにタグを設定します。 // libs/components/project.json { "name" : "components" , "tags" : [ "type:ui" ] , ... } // libs/utils/project.json { "name" : "utils" , "tags" : [ "type:util" ] , ... } 次に、ESLintの設定ファイルに @nx/enforce-module-boundaries の設定を追加します。 { files : [ '**/*.ts' , '**/*.tsx' , '**/*.js' , '**/*.jsx' ] , rules : { '@nx/enforce-module-boundaries' : [ 'error' , { enforceBuildableLibDependency : true , allow : [ '^.*/eslint(\\.base)?\\.config\\.[cm]?js$' ] , depConstraints : [ { sourceTag : 'type:ui' , onlyDependOnLibsWithTags : [ 'type:ui' , 'type:util' ] , } , { sourceTag : 'type:util' , onlyDependOnLibsWithTags : [ 'type:util' ] , // type:ui は許可しない } , ] , } , ] , } , } , これにより「 libs/components (type:ui) → libs/utils (type:util) の依存は許可され、逆方向の依存は許可されない」という制約を設定できました。 タグの仕様などについては、公式のドキュメントで解説されてありますので是非ご一読ください。 nx.dev Findyでの活用事例 ここでは、弊社における @nx/enforce-module-boundaries の活用事例を紹介します。 Findy のフロントエンドでは、公式ドキュメントの例に倣い、 scope:* や type:* といったタグを設定してモノレポ内のプロジェクトを管理しています。 共通モジュールを持つプロジェクトを作成する際は、次のように分類することが多いです。 モノレポ全体 の共通モジュールを持つプロジェクト( scope:shared ) アプリケーション内 の共通モジュールを持つプロジェクト( scope:app1 scope:app2 など ) モノレポ全体( scope:shared )とアプリケーション( scope:app1 scope:app2 )の分類 各アプリケーション( type:application )は複数のフィーチャー( type:feature )を持ち、上位レイヤーからのみ依存可能です。また、各フィーチャーはCRUD単位で細分化される場合があります。 アプリケーション( type:application )は複数のフィーチャー( type:feature )を持つ アプリケーション内の共通モジュールを持つプロジェクトには scope:* タグの他にも、用途に応じて type:ui や type:util 、分類が難しいものは type:shared といったタグを設定しています。 フィーチャーとその他の共通モジュールの依存関係 ※ type:ui のプロジェクトは省略されてあります ここまではよろしいでしょうか? ✋では、ここからが本題です。 type:feature の解説で「各フィーチャーはCRUD単位で細分化される場合がある」と述べましたが、 フィーチャー内の共通モジュールを持つプロジェクト の依存関係はどのように定義できるでしょうか? 新たな scope:* タグを作る案もありましたが、設定が複雑になってしまうと予想されたため、Findyでは type:feature-shared タグを作ることにしました。 フィーチャー内共通モジュール( type:feature-shared )の新設 ↑ type:feature と違い type:application からの依存を許可していないのがポイントです。 それでは、これらの依存関係をESLintルールとして記述しましょう。 { files : [ '**/*.ts' , '**/*.tsx' , '**/*.js' , '**/*.jsx' ] , rules : { '@nx/enforce-module-boundaries' : [ 'error' , { enforceBuildableLibDependency : true , allow : [ '^.*/eslint(\\.base)?\\.config\\.[cm]?js$' ] , depConstraints : [ { sourceTag : 'scope:app1' , onlyDependOnLibsWithTags : [ 'scope:app1' , 'scope:shared' ] , } , { sourceTag : 'scope:app2' , onlyDependOnLibsWithTags : [ 'scope:app2' , 'scope:shared' ] , } , { sourceTag : 'scope:shared' , onlyDependOnLibsWithTags : [ 'scope:shared' ] , } , { sourceTag : 'type:application' , onlyDependOnLibsWithTags : [ 'type:feature' , 'type:shared' , 'type:ui' , 'type:util' , ] , } , { sourceTag : 'type:feature' , onlyDependOnLibsWithTags : [ // 'type:feature', // type:feature 同士の依存は許可しない 'type:feature-shared' , // type:feature からのみ依存可能 'type:shared' , 'type:ui' , 'type:util' , ] , } , { sourceTag : 'type:feature-shared' , onlyDependOnLibsWithTags : [ // 'type:feature-shared', // type:feature-shared の乱用を防ぐため許可しない 'type:shared' , 'type:ui' , 'type:util' , ] , } , { sourceTag : 'type:shared' , onlyDependOnLibsWithTags : [ // 'type:shared', // type:shared の乱用を防ぐため許可しない 'type:ui' , 'type:util' , ] , } , { sourceTag : 'type:ui' , onlyDependOnLibsWithTags : [ 'type:ui' , 'type:util' ] , } , { sourceTag : 'type:util' , onlyDependOnLibsWithTags : [ 'type:util' ] , } , ] , } , ] , } , } , こうすることで、 モノレポ全体 の共通モジュールを持つプロジェクト アプリケーション内 の共通モジュールを持つプロジェクト フィーチャー内 の共通モジュールを持つプロジェクト という様々な特性を持つプロジェクトの依存関係を制御できようになりました。 まとめ この記事では @nx/enforce-module-boundaries を用いて、モノレポ内の依存関係を制御するテクニックを紹介しました。 今回は利用しませんでしたが、Nxの公式ブログでは bannedExternalImports を追加で設定し、複数のフレームワークが混在する場合の対応についても触れられています。 nx.dev プロジェクトのタグを毎回設定するのは煩雑ですので、Nxのジェネレータを使って設定済みのフィーチャーを生成すると良いでしょう。ジェネレータについては過去の記事で解説されてありますので、ご興味がありましたらこちらもご参照ください。 tech.findy.co.jp Nxにはモノレポ管理のための便利な機能が多く存在します。 この記事が皆様の参考になれば幸いです。それではまた次回! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
このブログの内容をポッドキャストでも配信中! こんにちは。ソフトウェアプロセス改善コーチでFindy Tech Blog編集長の高橋( @Taka_bow )です。 少し時間が空いてしまいましたが、前回の続きです。 tech.findy.co.jp DORA Reportを正しく読み解くために、前回のブログまでに説明してきたポイントをまとめます。 DORA Report は単なるサーベイの結果ではなく、2014年以降「科学的リサーチ」に基づいて分析されている。 「科学的リサーチ」の具体な内容は書籍『LeanとDevOpsの科学』で解説されている。 Four Keysを元にしたパフォーマンスレベルは統計的な分析手法(クラスター分析)が用いられ、調査年ごとに変化する。 DORA はこのレポートを用いて、各組織(企業)が独自の実験や仮説を立てることを望んでいる。 これらを念頭にレポートを読み解くことで、より公平で客観的な視点を養うことができると思います。 では、2024年版レポートの具体的な内容とその示唆について詳しく見ていきましょう。 今回はDORA Reportの中から、私が個人的に気になったAIに関するトピックを中心にまとめました。 本記事ではv.2024.3をベースに解説します。なお、執筆時点で日本語版はまだリリースされていませんでした。また、 正誤表 を確認しなるべく最新の情報を参照するように努めました。 DORA Reportのライセンスは次の通りです。 “Accelerate State of DevOps 2024” by Google LLC is licensed under [CC BY-NC-SA 4.0]( https://creativecommons.org/licenses/by-nc-sa/4.0/ ) なお、DORA Report原文は Google Cloudのこちらのページ からダウンロードできるので、ぜひ一次情報に触れてみてください。 このブログの内容をポッドキャストでも配信中! 開発現場におけるAIの浸透 生産性向上の実態 デリバリーパフォーマンスへの悪影響 コード生成AIが書くコードは信頼されにくい? AIがチームや組織のパフォーマンスに与える影響とは 組織のパフォーマンス向上 チームのパフォーマンスにも効果 製品のパフォーマンスとの関連性は限定的 AIが個人に与える影響:利点と課題 AIの導入で得られる明確な利点 AIによる潜在的な課題:トレードオフ DORAが示す、AIのこれから 開発現場におけるAIの浸透 DORAの調査に対する回答者の大多数(81%)が、自社がアプリケーションやサービスへのAIの導入を強化するために優先順位を変えたと報告しています。さらに、49.2%の回答者は、この変化の規模を「中程度」または「大きな変化」と表現しています。 AIの活用範囲は広範囲で【Figure 3. Percentage of respondents relying on AI】によると具体的なタスクごとの活用率は次のようになっています: Figure 3. Percentage of respondents relying on AI を元に筆者が翻訳 ソフトウェア開発業務におけるAIの最も一般的な使用例はコードの作成と情報の要約であり、これらのタスクを職務に含む回答者のうち、それぞれ74.9%と71.2%が少なくとも一部でAIに依存していると回答しました。 職種別の分析では、データサイエンティストと機械学習スペシャリストで特にAI依存度が高い傾向にありました。一方、ハードウェアエンジニアのAI依存度は最も低くなっています。これは、ハードウェアエンジニアの業務内容がAIの一般的な活用領域と異なる性質を持つためと考えられます。 利用方法としては、 チャットボット:78.2% 外部ウェブインターフェース(インターネット):73.9% IDEに組み込まれたAIツール:72.9% 内部ウェブインターフェース(社内イントラ):58.1% でした。 生産性向上の実態 生産性への影響に対する回答は次の通りでした。 10%が「極端に向上」 25%が「中程度に向上」 40%が「わずかに向上」 「極端」と「中程度」を合わせて、回答者の3分の1以上となっており、AIが開発者の日常業務に実質的な価値を提供していることを裏付けています。 Figure 4: Respondents’ perceptions of AI’s impacts on their productivity. を元に筆者が翻訳 また、職種別にみると次のような傾向が見られるそうです。 生産性向上の程度 職種 高い • セキュリティ専門家 • システム管理者 • フルスタック開発者 低い • モバイル開発者 • サイト信頼性エンジニア • プロジェクトマネージャー ※他の職種と比較した相対的な評価です DORAは、開発作業におけるAIの新規性とそれを習得するまでの時間が、開発者のコード作成能力を阻害する可能性があると考えていましたが、調査結果はDORAのこの仮説を支持しませんでした。生成AIについては、それだけ容易に扱えたということなのでしょう。 なお、AIがコード作成能力を阻害したと報告した回答者はわずか5%でした。 67%の回答者はAI支援のコーディングツールによってコード作成能力が少なくとも何らかの向上を見せたと報告し、約10%はAIによって「極端な」改善が見られたと述べています。 デリバリーパフォーマンスへの悪影響 DORAにとって予想外の発見もされています。それは、ソフトウェアデリバリーのパフォーマンスへの影響です。DORAはここ数年の調査から、ソフトウェアデリバリーにおける生産性(スループット)と安定性の指標が、 互いに独立した動きを示し始めている ことが分かってきたのです。 従来、この2つの指標には相関関係があるとされてきました。 しかし、最新のデータは、それぞれが独立した要因として機能していることを示唆しており、個別の評価が必要になってきています。 Figure 10. Impacts of AI adoption on delivery throughput and stability. を元に筆者が翻訳 この調査結果はAI導入がソフトウェアデリバリーパフォーマンスに悪影響を与えていることを示しています。 デリバリースループットへの影響は小さいものの、ネガティブな傾向(AI導入が25%増加するごとに推定1.5%の減少) デリバリー安定性への悪影響は大きく、AI導入が25%増加するごとに推定7.2%の減少 この結果に対しDORAは、 コード生成AIが「小さなバッチサイズの重要性」を損なっている と分析しています。 過去の調査結果に基づき、AIによる生産性とコード生成速度の根本的なパラダイムシフトが、DORAの最も基本的な原則の一つである「小さなバッチサイズの重要性」を見落とさせている可能性があると仮定しています。 つまり、AIによって同じ時間内により多くのコードを生成できるため、変更リストが大きくなっている可能性があります。DORAの調査では一貫して、大きな変更は遅く、より不安定になりやすいことが示されています。 総合的に見ると、デベロップメントプロセスの改善は、必ずしもソフトウェアデリバリーの改善に直結しないことを示唆しています。少なくとも、小さなバッチサイズや堅牢なテスト機構といった、成功するソフトウェアデリバリーの基本を適切に守らなければなりません。 この問題は、開発作業における認知負荷の観点から理解できます。当社のテックリードは開発パフォーマンス向上について次のように述べています tech.findy.co.jp 極論ですが、たとえ変更行数が1万行を超えていたとしても、変更内容が一意であれば問題は無いと考えています。 逆に変更行数が20行程度の不具合修正の中に「ついでにリファクタ」した内容が含まれていた場合、粒度が大きいと判断しPull requestを分割すべきなのです。 なぜならば、もし不具合修正に失敗していてrevertしようとした際に、ついでにリファクタした内容もrevertされてしまうからです。こういったケースの場合、リファクタをしたPull requestを別で作成します。 つまり本質はコードの変更行数や変更ファイル数ではなく、変更内容そのものにあるということを理解できたかと思います。 粒度が適切であれば、1行だけの修正でも、1万行の修正でも問題ありません。 10のプルリクを1回レビューするよりも、1のプルリクを10回レビューする方が、作成者、レビュワー共に負担が少ないのです。 コード生成AIは一度に大量のコードを生成できますが、本質的な問題は生成されるコードの量ではなく、認識可能なフィーチャーサイズ、つまりPull requestの粒度にあると考えられます。これがDORAの指摘する「小さなバッチサイズの重要性」の本質なのではないでしょうか。 コード生成AIが書くコードは信頼されにくい? 開発業務で使用されるAI生成コードの信頼性に対する参加者の認識は劣っていました。 大多数の回答者(87.9%)がAI生成コードの品質にある程度の信頼を寄せているとするものの、信頼の程度は全体的に低く「やや信頼」(39.2%)、「少し信頼」(27.3%)または「全く信頼せず」(11.9%)と報告しました。(Figure 5) Figure 5. Respondents' reported trust in the quality of AI-generated code. を元に筆者が翻訳 開発者がAIを急速に導入し、それに依存し、パフォーマンス向上に貢献すると認識している一方で、AIに対する信頼は薄いということになります。 しかし、興味深いのは、この「不信感」がAIの活用を妨げていないという点です。 開発者たちはAI生成コードを「完璧」なものとしてではなく、「改善が必要な出発点」として捉えている実態が明らかになっています。 以前このようなブログを出しましたが、 tech.findy.co.jp このブログで紹介した論文では、GitHub Copilotの効果を検証するため、大規模なランダム化比較試験を行っています。結果は、ジュニア開発者には生産性向上に効果をもたらすものの、シニア開発者には効果は限定的という発見がされています。 DORA Reportには回答者の熟練度による分析は含まれていません。しかし、「AIを活用しつつも信頼度は低い」という表面的な現象を裏付ける結果となっています。この点については、さらなる研究を期待したいところです。 AIがチームや組織のパフォーマンスに与える影響とは DORAの研究では、AIの導入がチームや組織、さらには製品にどのような影響を与えるのかを分析しました。この調査によって、AIの具体的な効果や課題が明らかになっています。 Figure 11. Impacts of AI adoption on organizational, team, and product performance. を元に筆者が翻訳 組織のパフォーマンス向上 研究によれば、AIの導入が25%増加すると、組織のパフォーマンスが約2.3%向上することが分かりました。この「組織のパフォーマンス」とは、収益性、市場シェア、業務効率、顧客満足度など、複数の要素を総合的に評価したものです。 AIは、業務の効率化や意思決定の迅速化、目標達成能力の向上といった面で組織にプラスの影響を及ぼしていると考えられます。 チームのパフォーマンスにも効果 チームのパフォーマンスもAIの導入によって約1.4%向上するという結果が出ています。この「チームのパフォーマンス」には、メンバー間の協力、イノベーション、効率的な作業、適応力などが含まれます。 特に、AIはチーム内でのコミュニケーションや知識共有の促進、意思決定プロセスの効率化といった課題を解消し、チーム全体の生産性を高める役割を果たしているようです。 製品のパフォーマンスとの関連性は限定的 一方で、製品のパフォーマンス(使いやすさ、機能性、価値、セキュリティなど)については、AIの導入による明確な影響は確認されませんでした。これは、製品の成功にはAI以外の要素、たとえば開発プロセスやクリエイティビティ、ユーザー体験のデザインなどが深く関係しているためと考えられます。 チーム、組織、製品のパフォーマンスが互いに密接な関連を持つことも示しています。例えば、優れたチームは高品質な製品を生み出す可能性が高い一方で、低品質な製品を扱うとチームの力が十分に発揮されないことがあります。また、良い組織は適切なリソースやプロセスを提供することで優れたチームを育てますが、逆に組織の問題がチームの力を制限するケースも見られます。 AIが個人に与える影響:利点と課題 次に、AIの導入が個人の仕事や生活にどのような影響を与えるのかが明らかになりました。この研究では、個人の成功やウェルビーイング(幸福感)に関連する要素を分析し、AIの影響を定量的に評価しています。 AIの導入で得られる明確な利点 DORAの調査によると、AIの導入が個人の「フロー(集中力)」「生産性」「仕事の満足度」を向上させることが分かりました(下表)。たとえば、AIの導入が25%増加すると次のような効果が予想されます: アウトカム 予想される%の変化 (推定値) フロー +2.6% 仕事の満足度 +2.2% 生産性 +2.1% バーンアウト -0.6% このような効果の背景には、AIによる情報の統合と効率的な作業環境の提供があります。従来は多くの時間を要した作業の効率化により、フロー状態に入りやすくなり、結果として仕事の満足度も向上します。 AIによる潜在的な課題:トレードオフ 一方で、AI導入による課題も浮かび上がっています。特に、 価値ある作業に費やす時間の減少 という予想外の結果が観察されました。 アウトカム 予想される%の変化 (推定値) 苦労する作業の時間:長期的な価値がほとんどない反復的な手作業に費やした時間の割合を測定する単一の項目 +0.4% 価値ある作業の時間: 価値があると考えるタスクに費やした時間の割合を測定する単一の項目 -2.6% AIは、価値ある作業(たとえばコーディング)を迅速に進めることで効率化を実現しますが、単調で繰り返しの多い労苦的な作業(たとえば会議や事務処理)にはほとんど影響を与えていません。これにより、余った時間が新たなタスクで埋められる「真空仮説(vacuum hypothesis)」が起きている可能性があります。 訳注:vacuum hypothesis(真空仮説/空白仮説) 生態系において「空いている場所には必ず何かが入る」という考え方を示す仮説です。例えば火山噴火後の新しい土地や、大量絶滅後の生態系の空白地帯には、時間の経過とともに必ず生物が進出し、その環境に適応した種が定着していきます。この仮説は特に、ガラパゴス諸島のフィンチ類(文鳥のような小鳥の類)のように、新しい環境で生物が多様化していく「適応放散」という現象を説明する際によく用いられます。名称の由来は、物理学における真空(vacuum)が必ず何かによって埋められようとするのと同様に、生態的な空白も必ず埋められていくという類推から来ています。 DORAが示す、AIのこれから DORAは今回の回答者に、今後1年、5年、10年のAIの影響についての見解や期待を尋ねています。 まず、楽観的な見方としては、AIによって製品の品質が引き続き向上すると予想しています。 一方で、AIが自身のキャリア、自然環境、そして社会全体に対して純粋にマイナスの影響を与えると予想しており、これらの悪影響が約5年後に完全に顕在化すると考えています。 「自然環境」が唐突に思われるかもしれませんが、DORAレポートの前半ではAIの環境負荷についての懸念が言及されており、具体的には、 2030年までにAIによってデータセンターの電力需要が160%増加する可能性 AIモデルの学習に、米国の1,000世帯以上の年間電力消費量に相当する電力が必要 回答者の30%以上がAIは自然環境に有害と考えている といった情報が添えられていました。 DORAレポートは "So now what? "という章で次のように提言しています。 私たちは、現時点でのAIが個人、チーム、そして組織を支援する可能性についての理解を深めたいと考えました。これまでに見えてきたパターンは、AIが単なる誇大宣伝ではなく、実際に確かな変化が起きていることを裏付けています。 AIを導入することの利点を示す明確な証拠が存在します。しかし同時に、多くの潜在的な障壁や成長に伴う痛み、そしてAIが有害な影響を及ぼす可能性があることも明らかです。 AIの大規模な導入は、単にスタートボタンを押すように簡単にはいきません。慎重で透明性があり、柔軟に適応できる戦略があってこそ、大きな効果が期待できます。この戦略は、リーダー、チーム、組織、研究者、そしてAI開発者が共同で作り上げていく必要があります。 リーダーと組織は、従業員を最もよく支援できる領域を優先してAIを導入する方法を見出す必要があります。 ここまで、AIに関するトピックをまとめてみました。 次回はAI関連以外の内容についてご紹介します。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは、ファインディ CTOの佐藤( @ma3tk )です! 今回は2024年の振り返りと、2025年のファインディのエンジニア組織における今後の方針についてお話します。 2024年はエンジニアが20名加わり60名規模の組織となり、退職者もほとんど出ない良好な組織文化を築きました。ファインディ全体でも100人以上も増え少しずつ大きくなってきました。テックブログは70本を超え、プロダクト開発の人数が増えていながら開発スピードは1.5倍に向上しました。 数字だけを見ても、この1年の変化の大きさを実感いただけるかもしれませんが、まだまだやるべきことが多く、この成長があってもファインディが実現したいことに少し近づいたというくらいです。今後の見通しについても後ほどご紹介します。 仲間が増え、組織で役割・状況が明確になった2024年 生成AIで開発がより加速した 2025年はエンジニアリングで事業に革命を起こす 生成AIを活用し、ユーザーのニーズに合わせた必須機能をつくり続ける開発体制の強化 より多くのユーザーに価値を届けるためのアーキテクチャ刷新やツールのリプレイス グローバル展開の加速に向けた国際化対応とセキュアで高品質な技術基盤の強化 メンバー数やつくりたい機能数が増えてもチーム開発の革新を実現する開発生産性の高いチームづくり これからエンジニアリングで革新を一緒に起こしませんか? 仲間が増え、組織で役割・状況が明確になった2024年 1年前を思い返すと、意図せず役割が不明確なメンバーもいたり、複数の業務を兼務しながら課題を解決する動きが多くありました。この1年で、元VPoE経験者や部長経験者など、様々なバックグラウンドを持つメンバーが加わってきたことで誰が何をすべきかを整備し、役割の明確化を行うことが出来ました。 お恥ずかしながら、ツールの運用確認などは昨年まで後手に回っていました。例えば、利用しているSaaSツールなどの管理をより精緻化しました。これにより「なんのために何を購入し、どれくらいの費用がかかっているのか」「今後の費用はどう推移していくのか」などがより細かく把握できるようになりました。その結果、組織として適切な支出ができているか、不要な支出を抑制できているかなど、経営状況の見える化が進みました。エンジニアリングのROIを見える化することで、より効率的な運用ができるようになったことで、お金をしっかり使うべきポイントにはきちんと使い、効果が見合わない場合は利用者と認識を合わせてきっぱりやめるというメリハリをつけられるようになりました。 また、印象的だったのは、Findy Team+の開発チームを4チーム体制へと拡大したことです。プロダクトの急成長に合わせて開発体制を強化する必要があり、沢山のメンバーに関わってもらいながら様々な角度からFindy Team+の開発を強化してきました。おかげで直近ではSOC2 1 を取得したり、利用者の皆様にとって必要な機能を爆速で提供し価値を感じてもらえるようになってきました。 同時にSREチームも新設され、それと共にインフラ面での強化がなされ、より安全で不要なリスクを排除できる環境を実現しました。セキュリティマネジメント室もでき、組織全体でも安全に運用できる体制にもなってきました。 その他にもこの一年でデータ基盤を整備しました。これにより、データ分析やデータサイエンスに必要な正しいデータを早いタイミングで提供できるようになりました。また、認証基盤の整備により、ファインディのサービスをより便利で安全に活用できる開発体制を実現しています。 前述したテックブログを始めたことで、「テックブログの取り組みを見て強くを興味を持った」と言って入社していただけるメンバーも増えました。メンバーが増えたことで、テックリードを始めとして組織的にオンボーディングを強化してきました。別な記事で詳しく触れていますのでご覧ください。 tech.findy.co.jp 全体的には組織を知ってもらう一年でしたが、後半からはどうやってメンバーを即戦力化し、技術力の高いエンジニアにすぐに近づけるための環境整備をしました。 個人としても1年がかりで開発生産性の教科書という書籍を執筆し、多くの方に読んでいただける状態になりました。レビューをしていただいたエンジニアの皆さん、ありがとうございます。まだ読まれていない方はぜひ読んでみてください。 https://www.amazon.co.jp/dp/429714249X www.amazon.co.jp 2024年は総じて、2025年以降に向けた新しい仕込みを開始できた素晴らしい年だったと思います。 生成AIで開発がより加速した 2024年は生成AI元年とも呼べる年でした。GitHub Copilotの各種リリース、ChatGPT 4oをはじめとする様々な生成AIが我々の開発環境をアップデートし、仕事の進め方を大きく変えてきています。 ファインディではGitHub Copilotを全社的に導入し、開発効率を大きく向上させることができました。具体的には、エンジニア一人あたり月間でPull request2個分くらいを平均的に上げることに成功しました。インタビューしていただいた記事もありますのでご覧ください。 xtech.nikkei.com アーキテクチャの観点では、8年目を迎えたプロダクトには、率直に言って古い箇所もあります。しかし、継続的な投資と改善を怠らず、アーキテクチャの刷新も進めてきました。その結果、デプロイ頻度は月平均20回から29回へと向上し、1.45倍以上プロダクトの改善が進むようになりました。開発スピードとクオリティの両立が実現できていると言えるでしょう。 2025年はエンジニアリングで事業に革命を起こす ファインディ社内に向けた2025年のエンジニアリング・デザイン組織のテーマ 「技術とデザインで事業に革命を起こし、挑戦するエンジニアを支え続ける」を我々エンジニアリング組織とデザイン組織の2025年テーマとして定めました。 生成AIを組み込むことがゴールではありませんが、プロダクト、サービス、そして組織そのものをより良くしていく。そのためのツールとして生成AIを活用していきます。 具体的には、以下のような挑戦をします。 生成AIを活用し、ユーザーのニーズに合わせた必須機能をつくり続ける開発体制の強化 より多くのユーザーに価値を届けるためのアーキテクチャ刷新やツールのリプレイス グローバル展開の加速に向けた国際化対応とセキュアで高品質な技術基盤の強化 メンバー数やつくりたい機能数が増えてもチーム開発の革新を実現する開発生産性の高いチームづくり この4点について1つずつ説明します。 生成AIを活用し、ユーザーのニーズに合わせた必須機能をつくり続ける開発体制の強化 昨年、我々ファインディでもFindy Team+に生成AIを活用したオンボーディング機能を組み込んでいきました。 「チームに開発革命を起こす」というプロダクトビジョンを発表し、サービスは大きく進化しています。この過程で様々なフィードバックをいただきました。僕の体感値では、今のFindy Team+は持てるポテンシャルの10%前後しか発揮できていない状況です。フィードバックから見えてきた課題を解決しようとすると、まだまだつくりたい機能が無限に湧いてきます。 この1年でも生成AIによって日々開発環境が進化し続けています。コードを書くこと自体も大切ですが、その作業時間は大幅に効率化されてきました。その分、「どんなサービスにするか」「どのような技術の組み合わせが最適か」といったアーキテクチャ設計により多くの時間を投資する動きが世の中でも見えてきました。 こういった環境を踏まえて、プロダクトの企画としても、ユーザーの皆様に向けて生成AIを活用しながらエンジニアの課題やエンジニアリング組織の課題を解決する開発を進めています。まだ検証中や開発途中のものも多く、さらなる進化を実現させていきます。 僕自身も生成AIに投資しながら新しい技術をプロダクトに組み込むアイディアを日々出し続けています。 より多くのユーザーに価値を届けるためのアーキテクチャ刷新やツールのリプレイス 事業が4つに拡大し、ファインディのサービスをより便利に連携させる仕組みを構築しています。 現在のファインディにおける4つの事業 基盤開発として、ファインディのサービスで利用できる認証基盤を強固にしながら、サービス間の連携を便利にしています。 また、日々新しく生まれるライブラリや外部ツールを最新にしていくため、継続的にアーキテクチャを見直しています。我々ファインディの成長、そしてファインディを取り巻く開発環境の変化を踏まえて、変更に寛容なアーキテクチャを目指し続けます。 グローバル展開の加速に向けた国際化対応とセキュアで高品質な技術基盤の強化 昨年は、Findy Team+でインド、韓国、台湾を中心にグローバルでの事業展開を強化してきました。そのために多言語化対応をし、様々なタイプのエンジニアリング組織の課題を解決するための開発を進めています。 日本でよく見られる課題を解決するプロダクトでしたが、各国で悩みの種類が異なることに気づきました。そこで、すべての国でワンプロダクトとして解決できるよう進めています。まだまだ多くの課題に応えきれていない状況です。 グローバル展開では、さらなるセキュリティ強化が求められます。常に安定した稼働ができるサービスづくり、そして万が一の障害時も爆速で復旧できる開発体制を維持します。これからも、グローバルで価値提供ができるプロダクトを複数つくっていきます。 メンバー数やつくりたい機能数が増えてもチーム開発の革新を実現する開発生産性の高いチームづくり 人材も増やしていきたいですし、つくりたいものもこれからますます増えていきます。 「エンジニアリングで事業に革命を起こす」ために、まずはファインディの開発組織を世界一の開発組織へと進化させる必要があります。 この5年で開発組織のレベルは大きく成長し、チームとしては開発生産性が高いと言えます。直近の課題は、メンバーが入社してすぐに慣れたと言える環境をつくることでした。そこで、組織全体でエンジニア育成に時間を投資してきました。 2024年は、組織全体で開発がスムーズに進み、障害が起こりにくく、起こっても解決できる体制を築きました。それだけでなく、エンジニア個人も市場価値の高い人材になれるよう育成してきました。 どこでも通用するスキル、そしてファインディで開発することが最高の福利厚生となる組織を目指し続けます。 そして、まだ工数の関係でできていない改善にも、積極的にチャレンジしていきます。「やりたいことリスト」は日々増えており、それだけ可能性が広がっているということでもあります。 これからエンジニアリングで革新を一緒に起こしませんか? 我々ファインディは今、非常に面白いフェーズにいます。組織は大きく成長し、技術的な挑戦も加速しています。しかし、まだまだ道半ばです。役割も明確にして集中して技術と事業に没頭しながらもっと面白いことができる、そんな環境に進化しました。 2025年は、さらにワクワクする変化の年になると確信しています。この革命が起こせそうな瞬間に興味を持っていただけた方は、ぜひファインディでカジュアル面談やイベントを通してお話ししませんか? 先ほど挙げたようなチャレンジを実現するために、次のような方も募集しています。 エンジニアリングをターゲットにしたプロダクトづくりに興味がある方 開発生産性の高い環境でアーキテクチャを進化させ続けたい方 生成AIを活用してプロダクトを進化させたい方 グローバル展開を技術で支えたい方 生産性の高いエンジニアリング組織で働きたい方 日常的に英語を使う環境で開発したい方 もちろんAND条件ではなく、どれかにマッチすれば是非お話しましょう! herp.careers 2024年は多くの優秀なメンバーがジョインし、新しいファインディへと進化するための仕込みの1年でした。2025年も、まだ見ぬ新しい仲間とともに、より大きな挑戦をしていきます! System and Organization Control 2:アメリカの公認会計士協会(AICPA)が制定した、クラウドサービス提供者やデータセンターなどの受託会社を対象とした信頼性を証明する国際的な仕組みです。 ↩
アバター
こんにちは!ファインディでFindy Team+開発チームのEMをしている 浜田 です。 Findy Team+開発チームでは、Slackワークフローとスプレッドシートを連携して開発工数の内訳を可視化しています。 開発工数の内訳を可視化することで、どの開発にどれくらい工数がかかったかや全体の工数のうちどれくらいの割合を開発に使えているかなどを定量的に把握できます。 Slackワークフローとスプレッドシートの説明 Slackワークフロー 工数の内訳と割合 トイル Slackワークフロー作成手順 まとめ Slackワークフローとスプレッドシートの説明 ここからはTeam+開発チームで実際に使っているSlackワークフローとスプレッドシートをキャプチャを交えつつ説明します。 Slackワークフローで入力した内容がスプレッドシートに連携されるので、スプレッドシートで集計して表やグラフに加工しています。 Slackワークフロー 開発メンバーの稼動終了時にSlackワークフローを使って日報を提出してもらっています。 日報としての役割を兼ねているため工数の可視化と直接関係ない項目も含んでいます。 午前のタスク / 午後のタスク その日に取り組んだタスクを午前・午後で1つずつ選択します。 自由記述の場合、選択肢が人によってブレるので選択式にしています。 選択肢は、改善開発 / トイル / 休暇 / 開発以外の4項目は固定で、現在進行中の施策開発ごとに選択肢を追加しています。 細かく分ければ工数の精度は上がりますが、入力の手間を考慮して0.5人日精度にしています。 全体の傾向を把握するだけであればこの精度で十分だと感じています。 トイル時間 アラート、問い合わせ、セキュリティチェックなど、Team+プロダクトに関係する運用作業に使った合計時間(0.5h単位)を入力。 ※トイルとは、 SRE サイトリライアビリティエンジニアリング で紹介されており、次のように定義されています。 Findy Team+の開発チームでは、繰り返し発生し、かつ手動で実施しなければいけないタスクとして主にアラートや問い合わせ、セキュリティチェックなどの作業が顕在化しているため、それらの時間をトイル時間として計測しています。 トイルとは、プロダクションサービスを動作させることに関係する作業で、手作業で繰り返し行われ、自動化することが可能であり、戦術的で長期的な価値を持たず、作業量がサービスの成長に比例するといった傾向を持つものです。 やったこと / 次やること / 所感 その日にやったことや翌営業日にやること、所感を自由記述。 こちらは日報としての役割のための項目です。 今日の調子 その日の調子を5段階で選択。 調子の推移を可視化したら面白そうと思って項目を追加したが、あまり活用できていない😭 担当イシューは見積もり通りに完了しそう? イシューの進捗を3段階(まかせろ/多分そう/ダメそう)で選択。 自身のタスク現状を考えるきっかけにちょうど良い項目だと感じています。 「ダメそう」の場合は、即相談を推奨しています! 工数の内訳と割合 Slackワークフローの「午前のタスク」「午後のタスク」のデータをもとにタスクごとの工数を集計しています。 午前と午後で入力しているので、工数の精度は0.5人日です。 黒塗りのところは実際の施策開発の名称が入っているのでマスクしています🙏 タスクを「施策開発」「改善開発」「トイル」「開発以外」に分類して、それぞれの工数の割合をグラフ化しています。 開発以外の作業やトイル対応が多い場合、「トイル」や「開発以外」の割合が大きくなります。 今までの傾向から施策開発と改善で7割を超えていたら開発に集中できていると判断しています。 トイルや開発以外のタスクが定常的に多い場合、開発に集中できるように早急に原因を取り除く必要があるとわかります。 また、開発の割合が多かったとしても「改善開発」の割合が多い場合は注意が必要です。 この場合、着手可能な施策開発がなく改善開発ばかりを実施している可能性があり健全とは言えません。施策開発に着手できていない原因を探り対策する必要があるとわかります。 トイル Slackワークフローの「トイル」のデータをもとにトイル対応した時間を集計しています。 トイル時間が定常的に多い場合、開発に使える時間が少なくなることを意味するので早急に対処する必要があります。 トイルに使った工数の割合をグラフ化しています。今までの傾向から5%未満で推移していたら健全と判断しています。 Slackワークフロー作成手順 Slackワークフローの設定方法を説明します。 *1 ワークフローを作成するために、サイドメニューから「その他」>「自動化」を選択します。 自動化の画面から「新しいワークフローを構築する」を選択します。 ワークフローを開始するイベントを選択します。 今回は任意のタイミングで起動したいので「Slack内のリンクから開始します」を選択します。 こちらを選択することで、発行されたリンクを実行したり、Slackのスラッシュコマンドから実行できるワークフローが作成できます。 1つ目のステップでは、日報の内容をフォームで収集するため「情報をフォームで収集する」を選択します。 ステップから見つからない場合は、検索ボックスからキーワードを入力して探すこともできます。 フォームのタイトルや項目を設定する画面が開くので収集したい項目を設定します。 入力形式はフリーテキストだけではなく、ドロップダウンやカレンダーから選択など様々な方法が準備されているので適したものを選択しましょう。 フォームで入力した内容をスプレッドシートに連携したいため、2つ目のステップでは「スプレッドシートに追加する」を選択します。 連携するスプレッドシートは1つ目のステップで作成したフォームを基に生成できます。利用者のユースケースが的確に捉えられており、とても良いUXですよね! フォームの項目とスプレッドシートの列を紐づけます。 入力した内容をSlackチャンネルにも投稿したいため、最後のステップでは「チャンネルへメッセージを送信する」を選択します。 Slackチャンネルへ通知するメッセージのテンプレートを作成します。 作成できたら公開します。公開すると実行するためのURLが発行されます🎉 Slackワークフローを実行すると、次のように連携したスプレッドシートにデータが1行追加されます。 スプレッドシートにデータが溜まりさえすれば、スプシ芸(?)を活用して様々な切り口でデータ分析できますね! ガンガン活用していきましょう💪 まとめ この記事では、Slackワークフローとスプレッドシートを連携して開発工数の内訳を可視化する方法を紹介しました。 前半に書きましたが、工数の可視化は入力の手間と精度のバランスが大事だと思います。 必要最低限の精度で手間なく可視化できるように工夫しつつ、開発工数やトイル時間を把握して開発組織が健全に開発を推進できている状態にしていきましょう! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers *1 : こちらは2025年1月時点の情報です。Slackのバージョンアップ等で変更される可能性があります。
アバター
こんにちは。 ファインディ で Tech Lead をやらせてもらってる戸田です。 既に皆さんも御存知かと思いますが、弊社では開発生産性の向上に対して非常に力を入れています。 以前公開した↓の記事で、弊社の高い開発生産性を支えている取り組み、技術についてお話させていただきました。 tech.findy.co.jp ありがたいことに、この記事を多くの方に読んでいただき反響をいただいております。 そこで今回は、↑の記事でも紹介されている「タスク分解」について更に深堀りしてお話しようと思います。 タスク分解は、弊社にJOINしたら最初に必ず覚えてもらう最重要テクニックの中の1つです。 それでは見ていきましょう! タスク分解とは メリット 事前に対応方針の認識を合わせやすくなる Pull requestの粒度を適切に保つことが出来る 進捗管理、引き継ぎをしやすくなる タスクの作り方 具体例 良いタスクリストを作るコツ まとめ タスク分解とは 何かしらの開発タスクを任されたあなたが最初にやるべきことは何でしょうか? もしいきなりコードを書き出す人がいるのであれば、この記事を読むことをオススメします。 開発タスクを任された際、まず最初にタスクの洗い出しを行い、それらを可能な限り分解していきましょう。 分解したタスク毎にPull requestを作成することで、自然とPull requestの粒度を適切に保つことが可能になります。 まずはタスク分解におけるメリットを紹介します。 メリット 事前に対応方針の認識を合わせやすくなる 弊社ではGitHubのIssueにタスクリストを作成し、実装着手前にタスクリストをレビューしてもらうようになっています。 実際に対応する内容と、考えているタスクの内容が一致しているのか、対応する順番は適切か、などを確認して実装着手前に認識を合わせるようにしています。 これからのタスクの予定を目に見える形で確認することが出来るので、事前に対応漏れや考慮漏れに気づきやすくなり、手戻りの発生が減ります。 これにより工数見積の精度も上がり、開発スケジュールが大きくずれ込むことを防ぐことが出来るようになります。 Pull requestの粒度を適切に保つことが出来る 基本的に作成したタスクごとにPull requestを作成することになります。 Pull requestの粒度が大きくなってしまう原因の1つに、「やるべきことがどんどん増えていって、結果的に大きくなってしまった」というものがあります。 しかし、事前にタスクをある程度の粒度で切り出しているため、Pull requestを作成している途中に肥大化してしまうことが少なくなります。 それでも考慮漏れなどでPull requestの粒度が大きくなってしまうこともゼロではありません。その場合、着手中のタスクの粒度が大きいと判断し、そこから更にタスクを分解するようにします。 実装中にタスクを細分化することにより、意図しないPull requestの肥大化を防ぎ、結果的に適切な粒度のタスクリストに近づくようになります。 また、Pull requestのレビュワーからの視点だと「これからどんな事をしようとしているのか」がIssue内のタスクリストによって把握することが出来るようになります。 そのため、Pull requestの粒度が細かい状態でレビュー依頼が来たとしても、局所的なレビューではなく全体像をある程度把握した上でのレビューが可能となります。 進捗管理、引き継ぎをしやすくなる タスクリスト内の終わったタスクにはチェックを入れ、進捗管理としても利用します。 全体を通してやるべきことと現在終わっていることがタスクリストを見ることで一目でわかるようになっているため、開発の進捗がどうなっているのか確認出来るだけでなく、他のメンバーに開発の引き継ぎをしやすくなります。 タスクの作り方 まず弊社では、GitHubのIssueのテンプレートにタスクリストの項目を用意しています。 --- name: Feature request about: 新機能や改善等の仕様用 --- ## なぜやるのか <!-- やることになった背景等を書く --> ## ゴール <!-- これをリリースすることで何を達成したいのか --> ## 仕様 ### 概要 <!-- 量が多ければ、概要と詳細に分ける --> <!-- 期待する・期待しない動作を書く --> ### タスクリスト - [ ] add task ## 補足事項 ### 懸念 <!-- 気になる点や仕様上での懸念事項等あれば記載する --> ## 関連Issue このように、Issueを作成し開発に着手する前にタスクリストを作成することが必要であることを明確にしています。 また、チェックボックスで作成したタスクからIssueを直接作成する機能などもGitHubから提供されているので合わせて確認してみてください。 docs.github.com 具体例 例えば、「ユーザーデータの一覧を返すREST APIを追加する」タスクが割り振られたとしましょう。 これだけだと、タスクリストの初稿はこうなります。 - [ ] ユーザーデータの一覧を返すREST APIを追加する これだけでは何がどう必要なのか、具体的によくわかりませんね。そこでPdMに確認すると、次のような要望が上がっているとのことでした。 - 登録しているユーザーの一覧を表示したい - idとnameで絞り込みが出来るようにしたい 現状わかっている要件だけでタスク分解をしてみましょう。 - [ ] ユーザーデータの一覧を返すREST APIを追加する - [ ] データベースからユーザーデータの一覧を取得して返す - [ ] 絞り込みに対応する - [ ] id - [ ] name とりあえず「動くもの」であれば、これだけで実装できそうです。 この状態でフロントエンド担当のメンバーにレビューしてもらいましょう。画面モックを確認するとページネーションとソートの機能が必要であることがわかりました。 ここでタスクを追加しておきましょう。 - [ ] ユーザーデータの一覧を返すREST APIを追加する - [ ] データベースからユーザーデータの一覧を取得して返す - [ ] 絞り込みに対応する - [ ] id - [ ] name - [ ] ページネーションに対応する - [ ] ソートに対応する - [ ] idのasc/desc 要件や必要な機能が少しずつ明確になってきましたね。次に他のバックエンドエンジニアにレビューしてもらいましょう。 すると、「nameの検索条件は完全一致、部分一致のどっちなのか?」という指摘をもらいました。 確かに画面モックから読み解くのは難しかったです。PdMと議論し、部分一致で実装することに決定しました。 ここで既存のタスクを修正しましょう。 - [ ] ユーザーデータの一覧を返すREST APIを追加する - [ ] データベースからユーザーデータの一覧を取得して返す - [ ] 絞り込みに対応する - [ ] id - [ ] nameの部分一致 - [ ] ページネーションに対応する - [ ] ソートに対応する - [ ] idのasc/desc 一通りの要件はこれで揃ったようです。これで実装に着手していきましょう。 ところが実装を開始してテストコードを書いていると、退会ユーザーのレコードが存在している可能性が出てきました。この場合、退会ユーザーは一覧に表示したくありません。 この要件をタスクリストに追加しましょう。 - [ ] ユーザーデータの一覧を返すREST APIを追加する - [ ] データベースからユーザーデータの一覧を取得して返す - [ ] 全件返す - [ ] 退会ユーザーは一覧から除外する - [ ] 絞り込みに対応する - [ ] id - [ ] nameの部分一致 - [ ] ページネーションに対応する - [ ] ソートに対応する - [ ] idのasc/desc ひとまず全件データを返すところまでPull requestで対応して、別のPull requestで退会ユーザーを一覧から除外するコードを追加すればOKです。この様に、実装中にタスクを更に細分化することも十分ありえます。 ひとまず退会ユーザーを一覧から除外するところまで対応が完了したので、チェックボックスにチェックを入れて進捗を管理します。 - [ ] ユーザーデータの一覧を返すREST APIを追加する - [x] データベースからユーザーデータの一覧を取得して返す - [x] 全件返す - [x] 退会ユーザーは一覧から除外する - [ ] 絞り込みに対応する - [ ] id - [ ] nameの部分一致 - [ ] ページネーションに対応する - [ ] ソートに対応する - [ ] idのasc/desc チェックを入れて進捗を管理することで、完了しているタスク、していないタスクを一目で確認することが可能になり、他のメンバーに開発の引き継ぎをしやすくなります。 今回は極端な例で紹介しましたが、タスクリストの作り方、整理の仕方を具体的に理解できたかと思います。 良いタスクリストを作るコツ 良いタスクリストを作成するためのコツは、 最初から完璧なタスクリストを作ろうとしない ことです。 まず最初に大枠のタスクを考え、そこから分解していくように意識してタスクリストを作成すると、結果的に詳細なタスクリストが完成しています。 小さくコツコツと修正を上乗せしていき、最終的に完成形に近づけていくような分解の仕方が良いでしょう。 大きな機能の実装担当になった際に、一度に全ての機能を実装するのではなく、 小さい機能追加を何回も繰り返して結果的に大きな機能を完成させる ようなイメージを持つと良いです。 まとめ いかがでしたでしょうか? 実装コードを書く前の準備は非常に重要です。タスク分解の精度を上げることにより、結果的にスピード感を持った開発を行うことが出来るようになります。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
アバター
あけましておめでとうございます! Findy Tech Blog編集長でソフトウェアプロセス改善コーチの高橋( @Taka_bow )です。 昨年2月末にスタートしたFindy Tech Blogが、なんと 総PV数30万を突破 しました! ここまで成長できたのも、記事を読んでくださる皆さんのおかげです。本当にありがとうございます。 今日は2024年、特に人気を集めた記事をいくつかの視点からピックアップしてご紹介します。技術のトレンドから生産性向上テクニックまで、きっと皆さんの関心に響く記事が見つかるはずです。 それでは早速、ふりかえっていきましょう! 2024年下期トピックス ITmedia NEWSの「IT企業デスクツアー」に取り上げて頂く 「修行をした話」から広がった新しい試み 【2024年】年間総PV数ランキングTop3 第3位 第2位 第1位 【2024年】はてなブックマーク数Top3 第3位 第2位 第1位 おわりに 2024年下期トピックス ITmedia NEWSの「IT企業デスクツアー」に取り上げて頂く 当ブログ人気シリーズ「【エンジニアの日常】エンジニア達の自慢の作業環境を大公開」で紹介した数々のデスク環境が、ITmedia様により改めて記事化して頂いてます!これは嬉しい! 「自慢の作業環境」の解説は、ブログの方が詳しいですのでぜひこちらもご覧ください。 下期では、Part5をリリースしております。 「修行をした話」から広がった新しい試み 2024年10月に公開した「プロダクト開発の修行をした話」シリーズが、新たな展開を見せました。弟子エンジニアと、師匠エンジニア、それぞれの視点で綴った2本のブログ記事が大きな反響を呼び、ついにはLTイベントの開催へと発展したのです。 このシリーズでは、実際のプロダクト開発現場で行われた「修行」の様子を、両者の生の声でお届けしました。技術的な学びはもちろん、メンターとメンティーの関係性の築き方、プロダクト開発を通じた成長の過程など、普段はなかなか表に出てこない貴重な体験が詳しく語られています。 そして、記事での反響を受けて実現したLTイベント。ブログには書ききれなかったエピソードや、視聴者から寄せられた質問への回答など、より深い内容をお届けできました。テックブログの新しい可能性を探る試みとなりました。 ブログでは語りきれなかった生の声を届ける、という新しいチャレンジをしました。 youtu.be 【2024年】年間総PV数ランキングTop3 ここからは、2024年一番アクセス(PV)のあった記事を紹介します! 第3位 \ 第3位 /19,305 PV 【エンジニアの日常】エンジニア達の人生を変えた一冊 Part3 - Findy Tech Blog ファインディのエンジニアたちが自身の成長に影響を与えた一冊を語る人気シリーズ「エンジニア達の人生を変えた一冊 Part3」ランキング。 記事では、『マスタリングTCP/IP―入門編』や『ハッカーと画家 コンピュータ時代の創造者たち』、そして『UNIXという考え方』といった名著が取り上げられており、それぞれがどのようにエンジニアたちの視点やスキルに変化をもたらしたのかが語られています。 とても玄人なラインナップでしでしたが、とても読まれています。ぜひチェックしてみてください! 第2位 \ 第2位 /19,379 PV 【エンジニアの日常】エンジニア達の人生を変えた一冊 Part2 - Findy Tech Blog 第3位に続き、同じシリーズがランクイン! この記事では、『SRE サイトリライアビリティエンジニアリング―Googleの信頼性を支えるエンジニアリングチーム』や『プログラマが知るべき97のこと』、そして『Clean Coder プロフェッショナルプログラマへの道』など、多くのエンジニアに愛読されている名著が取り上げられています。それぞれの書籍がどのように読者の成長を後押ししたのか、具体的なエピソードを交えて解説されています。 こちらも、ぜひチェックしてみてください! 第1位 \ 第1位 /20,108 PV 開発生産性指標を向上させるためにやってはいけないアンチパターン - Findy Tech Blog 2024年、最も多くの方に読まれた記事は「開発生産性指標を向上させるためにやってはいけないアンチパターン」でした。 開発現場で生産性向上に取り組む際、ついやってしまいがちな落とし穴について、実例を交えながら解説しています。デプロイ頻度やリードタイムといった指標を改善しようとするあまり、かえって本末転倒になってしまうケース。例えば、数字を上げるために無理にデプロイ回数を増やしたり、リードタイムを短くするためにコードレビューを省いたり...。一見、指標は改善されるものの、実は長期的に見るとチームの成長を阻害してしまう、そんな危険性を具体的に紹介しています。 「勝って兜の緒を締めよ」的、エンジニアの心構えを解いたブログです。 【2024年】はてなブックマーク数Top3 こちらでは、はてなブックマーク(はてブ)の数が多かったランキングをお届けします! *1 第3位 \ 第3位 /217 users 【エンジニアの日常】エンジニア達の人生を変えた一冊 Part1 - Findy Tech Blog こちらでは「Part1」がエントリー! 記事では、ソフトウェアとビジネスの未来を描く『ソフトウェア・ファースト』や、組織運営とリーダーシップの重要性を説く『1兆ドルコーチ』、アジャイル開発の実践的な手法を学べる『アジャイルサムライ』、さらに長期的なコード品質を支える設計の重要性に触れた『Clean Architecture』が取り上げられています。 加えて、Appleのデザインを牽引したジョナサン・アイブ氏のキャリアや哲学を深掘りした『ジョナサン・アイブ』も紹介され、デザインとエンジニアリングの融合が生むイノベーションの重要性について考えさせられる内容が語られています。 第2位 \ 第2位 /218 users 開発生産性を上げるために開発をする前に考えていること - Findy Tech Blog この記事では、開発をスムーズに進めるために、プロジェクト開始前に押さえておきたいポイントをまとめています。 プロジェクトのゴールをしっかり定めることはもちろん、ユーザー目線に立った設計の大切さ、既存の仕組みを上手く活用するコツ、将来の拡張も考えたシンプルな設計の進め方など、具体的な例を交えながら解説しています。段階的なリリースを通じて、ユーザーの声を活かしながら改善を重ねていく方法についても詳しく紹介されています。 日々の開発現場で使える知見が詰まっているので、プロジェクトの進め方を見直したい方や、開発の効率を上げたいと考えているエンジニア、マネージャーの方には、特に参考になるはずです。 第1位 \ 第1位 /328 users IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却 - Findy Tech Blog はてブが一番付いた記事は「IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却」でした! 2030年、日本のIT人材が約79万人不足するという衝撃的な予測をご存知でしょうか。この深刻な課題に対して、Findy Tech Blogでは「IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却」という記事を公開しました。 記事では、人材不足の根本的な原因として、日本のIT業界に根付いている「人月」という考え方と、ウォーターフォール型開発による従来の請負開発に着目。これらが開発現場の生産性向上を妨げ、人材不足を加速させている構造を丁寧に解き明かしていきます。 さらに、アジャイル開発の導入事例や新しい契約モデルの提案など、この課題を乗り越えるためのヒントも紹介しています。 おわりに 2024年に公開した73件の記事の中からほんの一部をご紹介させていただきました。 紹介しきれなかった記事もたくさんありますので、ぜひ他の記事もご笑覧頂ければと思います。 昨年は特に「【エンジニアの日常】シリーズ」に大きな反響をいただきました。これらのテーマは2025年も引き続き追求していきつつ、新しい技術への挑戦やファインディならではの爆速開発についても積極的に発信していきたいと思います。 そして何より、読者の皆さんとの対話を大切にしていきたい。記事へのコメントやSNSでの反応は、私たちの大きな励みになっています。 2025年も「面白い!」「参考になった!」と思っていただける記事をお届けできるよう、編集部一同張り切っていきますので、引き続きFindy Tech Blogをよろしくお願いします! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers *1 : 2024年12月31日時点で集計したランキングです。以後、増減する可能性はあります。
アバター
新年、明けましておめでとうございます。 ファインディ株式会社でフロントエンドのリードをしている新福( @puku0x )です。 今年も「エンジニアおみくじ」の季節がやって参りました 🎉 企画の詳細につきましては↓の記事をご参照ください。 findy-code.io 今回はエンジニアおみくじ開発の舞台裏をお話ししようと思います。 エンジニアおみくじとは 舞台裏① 企画からエンジニアが関わる 舞台裏② おみくじパターンは18万通り以上 まとめ エンジニアおみくじとは エンジニアおみくじは Findy で毎年1月に開催しているイベントです。 期間中にFindyへログインし、引いたおみくじをシェアすると抽選でプレゼントがもらえます。 期間中は毎日おみくじを引けます。目指せ超大吉! さらに今年はおみくじのパターンを増やしました。 その数、なんと 18万7,500通り !! たくさんご用意しましたので是非お楽しみください。 舞台裏① 企画からエンジニアが関わる ファインディでは、企画の段階からエンジニアがプロジェクトに参加しており、おみくじの内容に関してもエンジニアの監修が入っています。 エンジニアチームからは、用語やトレンドを共有したり、技術検証のフィードバックなどを行いました。運勢の一覧も皆でチェックしました。 おみくじにはエンジニアの監修が入っています 今年は年収やスキル偏差値などに加え、 生成AI や セキュリティ といった項目が盛り込まれてあります。 中には思わずニヤニヤしてしまうものもあるでしょう。 面白い運勢が出ましたら「 #Findyエンジニアおみくじ2025 」のハッシュタグを付けてシェアをお願いします。 舞台裏② おみくじパターンは18万通り以上 実は、これまでのエンジニアおみくじは「運勢別に固定の画像を返す」という仕様であり、画像作成の工数を抑えるため、 60パターン しかありませんでした。 単純な構成だっため実装面では楽でしたが、画像を作成する デザインチームへの負担が大きい という課題がありました。また、 おみくじを引き直した際に結果が重複する 確率もそこそこあり、ユーザー体験の面からもパターンの増加は必須でした。 このような背景から、今回は運勢(6通り)、各項目(5 5 通り)、コメント(10通り)からなる 6×5×5×5×5×5×10 = 187,5000 通りの組み合わせを用意することにしました。 すごい数ですね。ちなみに既存のやり方では 休まず働いて15年かかる作成量 であると試算されました。 すべての組み合わせの画像を手動で作成すると完成は...15年後! ここはエンジニアチームの出番です💪 大量の組み合わせの画像を作成するのは現実的でないため、実装を根本から見直し、動的に画像へテキストを挿入する形式を採用しました。 // ※説明のためコードを一部変更しております const textMaps = [ // 年収 { '超大吉' : { 0 : '項目1' , 1 : '項目2' , 2 : '項目3' , 3 : '項目4' , 4 : '項目5' , } , '大吉' : { ... } , '中吉' : { ... } , : } , // スキル偏差値 { '超大吉' : { ... } , '大吉' : { ... } , : // ※説明のためコードを一部変更しております const noteMap = { '超大吉' : { 0 : 'コメント1' , 1 : 'コメント2' , 2 : 'コメント3' , 3 : 'コメント4' , 4 : 'コメント5' , 5 : 'コメント6' , 6 : 'コメント7' , 7 : 'コメント8' , 8 : 'コメント9' , 9 : 'コメント10' , } , '大吉' : { ... } , '中吉' : { ... } , : // ※説明のためコードを一部変更しております const ids = [ ... ] ; const index = '超大吉' ; const texts = [ textMaps [ 0 ][ index ][ ids [ 0 ]] , textMaps [ 1 ][ index ][ ids [ 1 ]] , textMaps [ 2 ][ index ][ ids [ 2 ]] , textMaps [ 3 ][ index ][ ids [ 3 ]] , textMaps [ 4 ][ index ][ ids [ 4 ]]] ; const note = noteMap [ index ][ ids [ 5 ]] ; return ( < div style = {{ backgroundImage : 'url(...)' }} > < span > { texts [ 0 ]} </ span > < span > { texts [ 1 ]} </ span > < span > { texts [ 2 ]} </ span > < span > { texts [ 3 ]} </ span > < span > { texts [ 4 ]} </ span > < p > { note } </ p > </ div > ) ; 実装が新しくなったことで、将来的に運勢や項目が追加された場合でも柔軟に対応できるようになりました。 どのような内容になっているか気になった方は「 #Findyエンジニアおみくじ2025 」でシェアされている投稿を是非ご覧ください。 まとめ この記事では、Findyのエンジニアおみくじ実装の舞台裏をご紹介しました。 企画をより良いものにするためエンジニア、デザイナー、QA、マネージャーが一丸となって取り組んでおります。 過去に触ったことがあるという方におかれましても、これを機にアップデートされた「エンジニアおみくじ」をお試しいただければと思います 🙇‍♂️ findy-code.io それでは、本年もよろしくお願いします。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは!ファインディのプロダクト開発部でエンジニアをしているham ( @hamchance0215 )とEND( @aiandrox )です。 この記事はFindy Advent Calendar 2024 25日目の記事ということで、2人で共同執筆しています。 adventar.org この記事について ファインディでは日頃からお世話になっている皆さんに感謝の気持ちを込めて「 Findyユーザー感謝祭 2024 」を12/19に開催しました。 イベント中に、参加者の一人であるミノ駆動( @MinoDriven )さんが12/25発売の著書「 改訂新版 良いコード/悪いコードで学ぶ設計入門 」を参加者4名にプレゼントしてくださいました! じゃんけんで勝った4名が書籍をゲットするルールであり、hamとENDがじゃんけんの強さを発揮して書籍をゲットし、なんやかんやあってこの記事を書くことになりました。 さらにサインも頂きました! なんやかんや 「改訂新版 良いコード/悪いコードで学ぶ設計入門」を使ったリファクタリングとは? ユーザー感謝祭の懇親会でミノ駆動さんとお話しする機会があり、設計の知識を開発チームにインプットしていく方法について教えていただきました。 「改訂新版 良いコード/悪いコードで学ぶ設計入門」には、タイトルの通り「良いコード」だけではなく「悪いコード」の例もたくさん載っています。そこで、書籍に記載されている「悪いコード」をプロダクトのソースコードから探して「良いコード」にリファクタリングするという実践形式の学習をしているとのことです。 この学習方法、プロダクトのソースコードを使っていることから業務で活用できる生きた知識が身につくだけではなく、プロダクトがリファクタリングされて綺麗になっていくという一石二鳥な学習方法であり、とても興味を持ちました。 もっと知りたい方は、1/17にミノ駆動さん本人から紹介していただくイベントも企画されているのでぜひご覧ください! findy.connpass.com 実践 それでは早速プロダクトのソースコードから「悪いコード」を探して「良いコード」へリファクタリングしていきます。 今回は Findy Team+ のコードを使って実践しました。 実践1: 11.4 意図がわからない名前 実践1では「11.4 意図がわからない名前」に記載されている悪いコードを参考に探しました。 「意図がわからない名前」のデメリットについて、本著の一部を抜粋しました。 あいまいな変数名では、実際の意図に翻訳する作業が読むたびに必要になります。たとえば仕様変更の依頼があったとき、対応するメソッドや変数が何であるのか頭の中で翻訳作業が必要になります。また、チームに新しく参加したメンバーに対しての説明コストが増大します。 チーム開発において、コードは書くことより読むことの方が多いため、読み手に負担がかかっている状態は好ましくありません。 次のコードは、Team+で扱っている指標の1つである「LEAD_TIME_FOR_CHANGES_HOURS(変更のリードタイム)」を管理しているハッシュマップです。今回はこちらを対象にしました。 { statsType : 'LEAD_TIME_FOR_CHANGES_HOURS' , expectData : { label : '変更のリードタイム' , unit : 'h' , negativePositive : true , } } 各項目を見ていくと、labelは表示名でありunitは指標の単位であることが直感的にわかりますが、negativePositiveは何を意図しているかおわかりいただけるでしょうか? negativePositiveは「値が小さいほど良い指標か?」を表すboolean型の変数です。 ただ、negative(値が小さいほど良い) or positive(値が大きいほど良い)を示そうとしているところまでは理解できますが、trueの場合にどちらなのかを変数名だけで判断するのは困難であり、実際の設定値などから意図を推測する必要がありました。 そこで、isLowerBetterへリネームしました。 下記が修正した箇所の差分の1つです。isLowerBetterに変更したことで「値が小さいほど良い指標」の場合、ifの中に入ることがコードから読み取れるようになりました。 - if(negativePositive) { + if(isLowerBetter) { // do something } 学習しながらリファクタリングしてマージまで完了! 実践2: 7.1 ロジックの流用 Team+では、インポートに伴うさまざまな処理があり、それぞれを呼び出すBatchクラスも多く存在します。その中に、次のようなコードがありました。 module Batch class TransformXX < Batch :: Base # @param [ActiveSupport::TimeWithZone] xx_after 存在する場合はXXの更新処理を行う def call ( duration :, xx_after : nil ) Transformer .call( duration :) # 実際にはここでXXをアップデートする処理が走る UpdateXX .call( start_at : xx_after) if xx_after rescue StandardError => e Rails .logger.error ' データ変換処理に失敗しました ' end end end 問題はこの引数です。 # @param [ActiveSupport::TimeWithZone] xx_after 存在する場合はXXの更新処理を行う これは 8.6 フラグ引数 の節でも紹介されているものです。特に、Batchクラスでは引数によって処理を分岐しているものがちらほらあります。 フラグ引数付きのメソッドは、何が起こるか読み手の想像を難しくさせます。何が起こるのか理解するには、メソッド内部のロジックを見に行かなければなりません。可読性が低下し、開発生産性が低下します。 このBatchクラスは管理画面から呼び出される処理で、管理画面にチェックボックスがあるので、すぐにフラグを削除することは難しそうです。幸い、この条件分岐によってどう処理を行うかはクラスに切り出されており、可読性は悪くないと思われます。 問題は、このBatchクラスが管理画面を介する処理以外のいろんな箇所から呼ばれていることです。以下は一例です。 # Before def transform_resources (start_at) Batch :: TransformXX .call( duration : start_at.. Time .current) end ここでは、 xx_after が指定されていないので、 xx_after が nil になっています。つまり、実際には Transformer の処理しか行っていません。 ということで、不要な共通化をなくして直接実行クラスを呼び出すようにしました。このリファクタリングによって例外処理がなくなりましたが、ここでは例外処理を行う必要はなかったのでスッキリしました。 # After def transform_resources (start_at) Transformer .call( duration :) end これにより、過度な共通化がなくなり、フラグ引数が散乱する懸念も少なくなりました。 実践3: 15.1.3 条件を読みやすくする また、次のように unless と nil? を使っている箇所がありました。 return unless user.nil? 二重否定となっていて読みづらかったため、次のようにリファクタリングしました。 return if user 注意するべき点としては、条件が false になりうる場合、 nil と区別をする必要があります。そういった場合は unless と nil? を使う方がわかりやすいかもしれません。 まとめ 今回は「改訂新版 良いコード/悪いコードで学ぶ設計入門」を参考に、プロダクトのソースコードから「悪いコード」を探してリファクタリングしてみました。 本著では、さらに大きな「悪いコード」の事例についても紹介されており、実際に探してみるとそのようなコードもちらほらありました。短い時間だったため大きな設計変更はできませんでしたが、小さな変更でもコードの可読性が向上し、コードの意図が明確になることを実感しました。 また、なんとなく「悪いコード」と感じていた箇所が、本著を読んでみるとどのような問題があるのかが理解でき、リファクタリングの方向性が見えてきたのもよかったです。 今後も、本著を参考にしながら新規の設計やリファクタリングを行っていきたいと思います。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。 ファインディ で Tech Lead をやらせてもらってる戸田です。 弊社では開発生産性の向上のための投資、検証を継続して行っており、生成AIの活用にも取り組んでいます。 前回の記事で、導入編と題しましてGitHub Copilot in VS Codeのカスタムインストラクションの設定、利用方法を紹介しました。 tech.findy.co.jp 今回は実践編と題しまして、カスタムインストラクションに設定する内容の調整方法について紹介したいと思います。 それでは見ていきましょう! まず叩き台を用意する Copilotが理解しやすい形に書き換えていく 不要なものは削除する 長い文章よりも、簡潔な階層構造 曖昧な表現はNG 確認用プロンプトでカスタムインストラクションに渡す内容を調整していく まとめ まず叩き台を用意する 兎にも角にも、まず何かしらの叩き台を用意するのが良いです。一番手っ取り早いのは、開発組織におけるコーディングガイドラインを参考にすることです。 自分の場合は弊社のコーディングガイドラインのマークダウンテキストを丸っとコピペしてきました。カスタムインストラクションに渡す内容は日本語のテキストで問題なく動作するため、そのままコピペしてきても問題ありません。 .github/copilot-instructions.md を作成し、丸っとコピペしましょう。これを叩き台にして、Copilotが理解しやすい形に書き換えていきます。 Copilotが理解しやすい形に書き換えていく コーディングガイドライン等から引用して、カスタムインストラクションに渡す内容の叩き台は用意できました。 次はその叩き台をCopilotが理解しやすい形に書き換えていきます。コーディングガイドラインは人間が理解しやすい形になっており、これをCopilot用に書き換えていきます。 ※これから紹介する調整方法は、あくまで筆者の経験、調整内容に基づくもので、GitHubが公式に明言している内容ではありません。 不要なものは削除する カスタムインストラクションに渡す内容は、正しい内容のみを簡潔に渡す方がCopilotから出力される内容がイメージに近いものになることが多かったです。 例えば、次のような内容があるとします。 ## イベントハンドラの命名規則 - Component が受け取る Props は ` on ` + ` アクション名 ` + ` 対象名 ` - 関数そのものの名称は ` handle ` + ` アクション名 ` + ` 対象名 ` bad case ```tsx export const HogeComponent = () => { const { onChangeHoge } = useHogeHooks(); return <FugaComponent handleChangeHoge={onChangeHoge} /> } ``` good case ```tsx export const HogeComponent = () => { const { handleChangeHoge } = useHogeHooks(); return <FugaComponent onChangeHoge={handleChangeHoge} /> } ``` 良い例と悪い例の両方をサンプルコードで説明しています。しかし、自分が色々調整した結果、Badケースの内容も取り込まれた生成されるコードになってしまうケースがありました。 これは仮説ですが、Copilot的には 書いてある内容が正解 であり、不要なケースは逆にノイズになるのではないかと思います。 そのため、次のようにBadケースやそこに至るまでの議論の内容などは全て削除し、結論のみを完結に記述するようにしました。 ## イベントハンドラの命名規則 - Component が受け取る Props は ` on ` + ` アクション名 ` + ` 対象名 ` - 関数そのものの名称は ` handle ` + ` アクション名 ` + ` 対象名 ` ```tsx export const HogeComponent = () => { const { handleChangeHoge } = useHogeHooks(); return <FugaComponent onChangeHoge={handleChangeHoge} /> } ``` これによりBadケースの内容が生成結果に反映されることはなく、生成されるコードがイメージに近いものになることが増えました。 長い文章よりも、簡潔な階層構造 カスタムインストラクションには、長文を渡すよりもマークダウンの階層構造で渡すほうが、Copilotが理解しやすいようでした。 例えば、次のような文章があるとします。 boolean型のPropertyを定義する場合、引数名には ` is ` をprefixで付け、それが共通コンポーネントの場合はoptionalにする。 このような文章の場合、次のようにマークダウンの階層構造で渡したほうがCopilotが理解しやすいようでした。 - boolean 型のProperty - 引数名に ` is ` を prefix で付ける - 共通コンポーネントの場合 - optional にする 叩き台に長文が書かれていた場合、文章を分解し、マークダウン形式の段落構造などに書き換えるのをおすすめします。 曖昧な表現はNG 曖昧な言葉を使うと、Copilotはそれらを無視することが多かったです。 例えば次のような文章をカスタムインストラクションに渡すとします。 - 親コンポーネントからまとめてテストコードを書く - 子コンポーネントへの直接的なテストコードは不要 この場合、 不要 という言葉が曖昧に受け取られ、この命令文を無視されることが多かったです。 こういったケースでは、次のように書き換えることでCopilotが理解しやすくなりました。 - 親コンポーネントからまとめてテストコードを書く - 子コンポーネントへの直接的なテストコードは書かない 不要 を 書かない とシンプルに言い切ることによって、Copilotが理解しやすくなりました。 このようにCopilotが中々理解してくれないケースでは、言葉の表現を少し変えるだけで一気に理解度が上がることが多かったです。 確認用プロンプトでカスタムインストラクションに渡す内容を調整していく ここまでで、ある程度の内容をカスタムインストラクションに渡すことが出来ているはずです。 次は、そのカスタムインストラクションの内容がCopilotにどのように理解されるかを確認していきます。 例えば、次のような内容をプロンプトとして用意します。 以下の条件を全て満たすコードを生成してください - hooksである - 引数は次の通り - カウント数の初期値 - 任意項目 - 次の内容を変数で管理する - カウント数 - 引数で受け取ったカウント数の初期値で初期化する - 次の関数を用意する - カウント数をインクリメントする - カウント数をデクリメントする - hooksから次の内容を返す - カウント数 - カウント数をインクリメントする関数 - カウント数をデクリメントする関数 このプロンプトをCopilotに渡して、生成されたコードを確認します。 import { useState } from 'react' ; function useCounter ( initialCount = 0 ) { const [ count , setCount ] = useState(initialCount); const increment = () => setCount(count + 1 ); const decrement = () => setCount(count - 1 ); return { count , increment , decrement } ; } export default useCounter; プロンプトの内容を反映したコードが出力されました。ですが、これだけでは弊社のコードガイドラインと一致していない箇所がありました。そこでカスタムインストラクションの調整を行います。 次のような内容を .github/copilot-instructions.md に追記します。 ## Hooks - hooksから返す値は ` as const ` を付けてreadonlyにする ## イベントハンドラの命名規則 - Component が受け取る Props は ` on ` + ` アクション名 ` + ` 対象名 ` - 関数そのものの名称は ` handle ` + ` アクション名 ` + ` 対象名 ` ```tsx export const HogeComponent = () => { const { handleChangeHoge } = useHogeHooks(); return <FugaComponent onChangeHoge={handleChangeHoge} /> } ``` この状態で先程のプロンプトを再実行すると、次のようなコードが生成されました。 import { useState } from 'react' ; function useCounter ( initialCount = 0 ) { const [ count , setCount ] = useState(initialCount); const handleIncrementCount = () => setCount(count + 1 ); const handleDecrementCount = () => setCount(count - 1 ); return { count , handleIncrementCount , handleDecrementCount } as const ; } export default useCounter; カスタムインストラクションに渡した内容通りに、関数名の変更と as const の追加が反映されました。更にここから何かしら調整を加えたい場合は、またカスタムインストラクションの内容を変更し、同じプロンプトを実行して新たに生成されたコードの内容をチェックする手順を繰り返します。 この作業を繰り返すことで、カスタムインストラクションの内容を調整していくことが出来ます。 まとめ いかがでしたでしょうか? 今回は実戦編と題しまして、GitHub Copilot in VS Codeのカスタムインストラクションに設定する内容の調整方法について紹介しました。 カスタムインストラクションの説明や導入方法については次の記事を参考にしてみてください。 tech.findy.co.jp 弊社としましてもまだまだ検証段階ではありますが、カスタムインストラクションの内容を調整することで、Copilotのサジェスト内容や自動生成コードの質が向上したことを確認しています。 今回の記事が皆さんの開発生産性向上に少しでもお役に立てれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
アバター
ファインディ株式会社でフロントエンドの開発をしております千田( @_c0909 )です。 この記事はFindy Advent Calendar 2024 24日目の記事です。 adventar.org 転職サービス『Findy』の管理画面リニューアルプロジェクトで、約200ページ規模の開発をしました。 管理画面の機能は構成が似通っているため、NxのGeneratorによるコード自動生成を活用して画面作成の効率化を図りました。 本記事では、その取り組みについて共有させていただきます。 Nxについては以前の記事で紹介しておりますので、併せてご覧ください。 tech.findy.co.jp Generator導入の背景 なぜNxのGeneratorなのか Nxエコシステムとの親和性が高い 再利用性が高い Generatorに対するテストが書けるため、メンテナンスがしやすい どうやって対応したか 今後やりたいこと まとめ Generator導入の背景 既存の管理画面は約50の機能で構成されています。 各機能には一覧・詳細・作成・編集の4種類の基本画面が必要となるため、合計で約200ページ(50機能 × 4画面)の開発が必要でした。 開発工数を試算したところ、コンポーネント作成、ロジック実装、テスト作成を含め、1画面あたり約160分の作業時間が必要になります。 これを単純計算すると、全画面の開発には約67日(160分/画面 × 200画面 ÷ 1日8時間)もの期間が必要という結果になりました。 そのため、構造が類似した200ページの開発の効率化を目指し、Generatorによるコードの自動生成を検討しました。 なぜNxのGeneratorなのか 冒頭でも書いたように、FindyにおいてはNxのGeneratorを選択しました。 その理由は既にNxを使っていたという背景に加え、次の技術的な利点があるためです。 Nxエコシステムとの親和性が高い GeneratorがNxのコア機能として提供されているため、開発者は追加のセットアップの必要なく利用可能です。 公式やサードパーティのNxプラグインはGeneratorに対応しているものがほとんどであり、コンテキストスイッチの負荷を最小限にできます。 また、Nx ConsoleをIDEにインストールすれば、GUIからGeneratorを起動できます。 Nx Consoleはオプションの確認やコマンドのDry-runといった機能もサポートされているため便利です。 nx.dev 再利用性が高い Generatorから他のGeneratorを呼び出すことができます。 これにより、Generatorの構成をシンプルに保つことができます。 export default async function ( tree : Tree , schema : Schema ) { // 設定ファイル群の追加 generateFiles( tree, path. join (__dirname, 'files/feature' ), `libs/projectName/src` , substitutions ); // 特定のフィーチャーコンポーネントの追加 generateFiles(tree, path. join (__dirname, 'files' ), options.projectRoot, { ...names(options. name ), importPath : options.importPath, projectRoot : options.projectRoot, ... } ); } nx.dev Generatorに対するテストが書けるため、メンテナンスがしやすい 仮想ファイルシステムを利用してファイル生成の結果を確認できます。 例えば、次のようにJestでGenerateコマンド実行後のファイルの存在を確認できます。 import { Tree } from '@nx/devkit' ; import generator from './generator' ; it ( 'should generate expected files' , async () => { await generator(tree, defaultOptions); expect (tree.exists( '/src/components/index.ts' )).toBe( true ); } ); どうやって対応したか NxのGeneratorを使用したコード生成の実装について説明します。 実際にテンプレートファイルからファイルを生成するには、 generate コマンドを利用します。 画面の雛形を生成するためのコマンドは次のように設計しました。 npx nx generate @findy-code/workspace-plugin:features user \ --featureType = detail \ --featureNameJa = ユーザー user : 機能名(変数名やファイル名として使用) --featureType : 画面タイプ(list/detail/create/edit) --featureNameJa : 画面に表示する日本語名 これらの引数の設定は schema.json で行います。 { " $schema ": " http://json-schema.org/schema ", " properties ": { " name ": { " type ": " string ", " description ": " The name of the feature (feature-<name>-{list,detail,create,edit}) . ", " $default ": { " $source ": " argv ", " index ": 0 } , " x-prompt ": " What name would you like to use? " } , " featureType ": { " type ": " string ", " description ": " The mode of feature generation. Possible values are 'list', 'detail', 'create', 'edit', or leave empty to generate all types. ", " default ": "" } , " featureNameJa ": { " type ": " string ", " description ": " The name of the feature in Japanese ", " default ": "" } ... } } 次に、生成されるファイルのテンプレートを作成します。 例えば、 詳細画面用のカスタムフックのテンプレートは次のように実装しました。 export const use<%= functionName %>Detail = ( { <% = propertyName % >Id } : Props ) => { const <%= propertyName %> = { id : <%= propertyName %>Id } ; // ここに詳細画面用のロジックを実装 return { <%= propertyName %> } as const ; } ; 次のように展開されます。 export const useUserDetail = ( { userId } : Props ) => { const user = { id : userId } ; // ここに詳細画面用のロジックを実装 return { user } as const ; } ; テンプレート内では<%= %>記法で動的な値を埋め込みます。 テンプレートファイルは src/__featureName__-detail.ts.template という形式で作成し、ファイル名も可変にしています。 テンプレート内で使用する functionName や propertyName などの変数は、Nxが提供する names 関数を使用して適切な命名に変換します。 例えば、次のように names('my-name') と呼び出すことで、 className 、 propertyName 、 constantName のように、よくある命名規則に従った文字列を作成できます。 names( 'my-name' ); // { // name: 'my-name', // className: 'MyName', // propertyName: 'myName', // constantName: 'MY_NAME', // fileName: 'my-name' // } 最後に、 generateFiles 関数を使用してファイルの生成を実装します。 この関数にテンプレートのディレクトリ、出力先のディレクトリ、そして置換する変数を指定することで、実際のファイル生成が行われます。 const substitutions = { featureName : names(schema. name ). name , featureNameJa : schema.featureNameJa, functionName : names(schema. name ).className, ... } ; generateFiles( tree, path. join (__dirname, 'files/feature' ), // テンプレートを定義しているファイルのディレクトリ ` ${ options.projectRoot } /src` , // 生成したいディレクトリ substitutions // テンプレートで置換される変数 ); これにより、コマンド1つで必要な画面の雛形を生成できるようになりました。 生成されるファイルには、カスタムフックの実装だけでなく、対応するテストファイルやコンポーネントなども対応しています。 今後やりたいこと NxのGeneratorの導入により、画面を作り込むことは出来ましたが、新たな課題も見えてきました。 現在のGeneratorは画面のコードを一気に生成するため、ファイルの変更数が増えPull requestの粒度が大きくなり、レビューの負荷が高くなりました。 今後は、コード生成の粒度をより細かく制御できるように改善を進めていく予定です。 具体的には、画面を構成する要素ごとに生成を分割し、Componentの生成、ルーティング設定の追加、カスタムフックの実装といった単位でPull requestを作成できるようにすることで、レビューの負荷を軽減したいと考えています。 適切なPull requestの粒度については、既に以前の記事で紹介しておりますので、気になる方は是非ご覧ください。 tech.findy.co.jp まとめ この記事では、約200ページ規模の開発におけるNxのGeneratorを活用した事例をご紹介しました。 私自身、Nxを単にモノレポ管理ツールとして認識していましたが、今回のプロジェクトを通じてGeneratorという強力な機能の存在を知ることができました。 今回の取り組みを通じて、類似した構造を持つ画面を大量に開発する場合、NxのGeneratorが非常に効果的なツールとなることが分かりました。 この記事が皆様のプロジェクトにおける開発効率化のヒントになれば幸いです。 それでは、また次回の記事でお会いしましょう! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
アバター
こんにちは。 ファインディで Tech Lead をやらせてもらってる戸田です。 弊社では開発生産性の向上のための投資、検証を継続して行っており、生成AIの活用にも取り組んでいます。 そこで今回は、GitHub Copilot in VS Codeのカスタムインストラクションを導入した際の話を紹介しようと思います。 筆者も最近導入したばかりでフル活用までいっていないのが現状ですが、開発生産性の向上を見込めると確信している強力な機能となっています。 それでは見ていきましょう! GitHub Copilot in VS Codeとは 設定方法 効果検証 まとめ GitHub Copilot in VS Codeとは 公式ドキュメントはこちら code.visualstudio.com VS CodeにはGitHub Copilot、GitHub Copilot Chatを利用するための拡張機能が用意されています。 marketplace.visualstudio.com marketplace.visualstudio.com デフォルトの設定だとCopilot自身がコード生成や変更内容をサジェストしてくれるのですが、このサジェスト内容をカスタマイズできるようになるのがカスタムインストラクションです。 サジェスト内容をカスタマイズするために必要なのがコードガイドラインとなっています。これを自然言語などで記述しておくとCopilotが読み込み、設定内容を反映したコード生成、変更内容のサジェストを出すようになります。 極端な例えになりますが、指定したファイルに開発チームのコードガイドラインを記述しておくことで、Copilotがそのコードガイドラインに従ったコードを生成してくれるようになります。 設定方法 基本的にはVS Codeを最新バージョンに更新して、 .github/copilot-instructions.md というファイルを作成するだけでOKです。 作成したファイルにコードガイドラインを記述していきます。記述する内容は日本語やマークダウンでOKです。 コードガイドラインを他のフォルダやファイルで管理したい場合は、 .vscode/settings.json に次のような設定を追記します。 file で指定したファイル名でファイルを作成しコードガイドラインを記述していきます。 { " github.copilot.chat.codeGeneration.instructions ": [ { " file ": " path/to/code-guideline.md " } ] } また、次のように設定を直接追加することもできます。 text で指定した内容がサジェスト内容に直接反映されます。 { " github.copilot.chat.codeGeneration.instructions ": [ { " text ": " Always add a comment: 'Generated by Copilot'. " } , { " text ": " In TypeScript always use underscore for private field names. " } , { " file ": " path/to/code-guideline.md " } ] } これで設定は完了です。あとはコードガイドラインを記述してサジェスト内容をチューニングするだけです。 効果検証 カスタムインストラクションの設定が無い状態で、GitHub Copilot Chatで次のプロンプトを実行します。 以下の条件を全て満たすComponentを作成してください - Function Componentである - propsは以下の通り - title: string - description: string - link: string - linkText: string - isShowLink: boolean - titleはh1タグで出力する - descriptionはpタグで出力する - isShowLinkがtrueの場合、linkで指定したurlをaタグにして、linkTextを出力する - linkのテキストがurlではない場合、linkを出力しない シンプルなコンポーネントを作成するプロンプトです。実行すると次のコードが生成されました。 プロンプトの命令に忠実なコードが生成されたかと思います。 import React from 'react' ; type Props = { title : string ; description : string ; link : string ; linkText : string ; isShowLink : boolean ; } ; export const MyComponent: React.FC < Props > = ( { title , description , link , linkText , isShowLink } ) => { const isValidUrl = ( text : string ) => { try { new URL (text); return true ; } catch { return false ; } } ; return ( < div > < h1 > { title } </ h1 > < p > { description } </ p > { isShowLink && isValidUrl(link) && < a href = { link } > { linkText } </ a > } </ div > ); } ; 次にカスタムインストラクションの設定内容をチューニングします。 今回は .github/copilot-instructions.md に次のような記述をしました。 # コードガイドライン - props の項目で boolean 型の項目があった場合は、その項目を optional にする - a タグのリンク先が別ドメインだった場合、以下の属性を追加する - rel="noopener noreferrer" - チェック処理などは可能な限り memo 化する これでプロンプトを再実行すると、次のコードが生成されました。 import React, { memo, useMemo } from 'react' ; type Props = { title : string ; description : string ; link : string ; linkText : string ; isShowLink ?: boolean ; // booleanはoptionalにする } ; export const MyComponent: React.FC < Props > = memo(( { title , description , link , linkText , isShowLink } ) => { const isValidUrl = useMemo(() => { try { new URL (linkText); return true ; } catch { return false ; } } , [ linkText ] ); const isExternalLink = useMemo(() => { try { const linkUrl = new URL (link); return linkUrl. origin !== window . location . origin ; } catch { return false ; } } , [ link ] ); return ( < div > < h1 > { title } </ h1 > < p > { description } </ p > { isShowLink && isValidUrl && ( < a href = { link } rel = { isExternalLink ? "noopener noreferrer" : undefined } > { linkText } </ a > ) } </ div > ); } ); プロンプトの命令通りのコンポーネントですが、コードガイドラインに指定したルールを反映したコードに変化したことがわかるかと思います。 この例で見る通り、コードガイドラインは自然言語でもマークダウン形式でも問題なく読み込み可能であることがわかります。 弊社でもまだ実験段階なのですが、ひとまずは既存で運用していたコードガイドラインをそのまま流用し、そこから少しずつチューニングしていくことでサジェストの精度を上げていこうと考えています。 まとめ いかがでしたでしょうか? 今回は導入編と称しまして、GitHub Copilot in VS Codeのカスタムインストラクションの設定方法と効果検証を紹介しました。 弊社としましてもまだまだ検証段階ではありますが、コードガイドラインを設定することでサジェスト内容をチューニングできることがわかりました。 検証が進んだら、次回は【実践編】と称しまして具体的にどのようなコードガイドラインのチューニングを行ったのかを紹介できればと思います。お楽しみに! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
アバター
はじめに この記事は Findy Advent Calendar 2024 21日目の記事です。 adventar.org データソリューションチーム、エンジニアの土屋(@shunsock)です。本日は、Findy Toolsのデータ基盤を構築したので、その内容を共有します。 Findy Tools は、2024年1月23日にリリースされた開発ツールのレビューサイトです。利用者は開発者向けツールのレビューやアーキテクチャの記事を閲覧、投稿できます。 Findy Toolsのデータ基盤のシステム設計の紹介 システム設計の目標、要件 今回の構築では、「Findy Toolsを訪れたユーザーの行動ログとデモグラフィックデータを組み合わせて分析可能にする」という目標がありました。Findy Toolsではユーザーの行動ログにユーザーidやリファラーを保存しています。また、ユーザー情報をはじめとしたデータを保存するデータベースがあります。今回は、これらを繋ぎ合わせた分析を可能にすることが目標です。 この目標を分解していきます。 まず、分析可能にするためには、分析対象であるデータが保存されている必要があります。行動ログとデモグラフィックデータは別々の場所にあるので、それぞれを集める必要があります。 また、データ分析をする主体はビジネスサイドの方で、BIを通じてデータを閲覧します。SQLのロジックついてはデータエンジニアが管理します。従って、データの加工が必要です。さらに、日々データは更新されます。よって加工されたデータも更新する必要があります。 以上をまとめると次のシステムが必要であることがわかります。 分析対象のデータを一定期間で取得する処理 取得したデータを一定期間で加工する処理 システムには既存のリソースなどの前提や組織方針などの制約があります。ファインディの場合、ウェブアプリケーションがAWS、データ基盤・機械学習基盤をGoogle Cloudでそれぞれ稼働しています。今回扱う行動ログデータとデモグラフィックデータはそれぞれ、ECSとRDS(Aurora MySQL)にありました。また、データウェアハウスはBigQueryであることが必須要件でした。これは、社内の分析担当者がBigQueryのUI/UXに慣れていることに起因します。最後に同期の期間ですが、即時性を求められるデータは今のところないため、1日ごとのバッチ処理でデータを転送することにしました。 以上の前提と制約からシステムの要件が次であるとわかります。 データの転送処理 行動ログの転送: ECSのコンテナに出力されている行動ログをBigQueryに1日ごと転送 ※ データベースの転送: RDSのデモグラフィックデータをBigQueryを1日ごとに転送 データの整形 BigQueryに保存されたデータを1日ごとに加工処理を実行 ※ 実際には、これより短い間隔で送信されるシステムになりました。 システム設計図 次の写真がFindy Toolsのデータ基盤のシステム設計図です。 Findy Toolsのデータ基盤 データの取得、加工の仕組み データの取得 はじめに、ユーザーの行動ログの転送方法を説明します。Findy Toolsでは、ユーザーの行動ログを次のように取得しています。 Next.js(フロントエンド)からRails API(バックエンド)にHttp Requestを送信 Rails APIがログを出力 よって、このログをBigQueryに転送する手法を検討しました。工数がかからないことと送信に必要な追加費用がBigQuery APIのみであることからfluentbitを採用しました。fluentbitは、ログを収集し、閾値やバッファの条件に応じて送信するソフトウェアです。 次に、データベースの転送方法を説明します。Findy Toolsの場合、データベースとしてAWS Aurora MySQLを採用しています。 Aurora MySQLからBigQueryに送信する手法はいくつかありました。 方法 構築難易度 コスト メリット 採用判断 理由 Private Linkを使う 高 中 セキュリティ強化、直接送信可能 不採用 今回のケースでは受けられる恩恵が小さい。 Private SubnetにECSを立てる 中 低 シンプル構成、コスト効率が良い 採用 実現可能性が高く、コスト効率が良い。 3rd Party ETLツールを使う 低 高 導入が楽 不採用 費用が高い。 Private Linkを使う方法は構築難易度が高いものの、今回のケースでは受けられる恩恵が小さいことから採用しませんでした。また、3rd PartyのETLツールを使う方法は相当な費用が必要と判明し、断念しました。よって、Private SubnetにECSを立てて送信する方法を採用しました。 ECS上でデータの転送するソフトウェアは社内で実績のあったEmbulkを採用しました。 今回の構築では次のような手順でデータを送信します。 CloudWatch Eventsが設定した時刻にECSを起動 ECSがEmbulkを起動 EmbulkがAurora MySQLからデータを取得 EmbulkがBigQueryにデータを送信 データの加工 データの加工にはdbtを採用しました。dbtは、SQLを使ってデータを加工するため、データエンジニアがSQLを書くことができれば、簡単にデータを加工できます。似たツールで非エンジニアでも触りやすいGUIを持つDataformがありますが、今回はGit操作になれているメンバーが触ることを考慮してdbtを採用しました。 dbtの実行はGitHub Actions上で行っています。具体的な手順は次の通りです。 GitHub ActionsのScheduleによってワークフローが発火 dbtがlake層に入ったデータを加工 エラー処理、アラートの仕組み 今回作成したインフラストラクチャでは、次のようにエラー・アラートを通知しています。 Google Cloud, AWSのエラー通知の仕組み 行動ログの転送のエラー処理 行動ログの転送では、エラーの発生箇所がいくつか考えられます。 Next.jsからRails APIへのHttp Requestの失敗 Rails APIのログ出力の失敗 fluentbitの停止・暴走によるログ転送の失敗 BigQueryへの送信の失敗 今回データソリューションチームでは、BigQueryへの送信の失敗の監視を担当することになりました。(他はウェブアプリケーションの開発チームが担当)BigQueryへの送信の失敗は、Cloud Loggingに出力されるBigQuery APIの応答を監視することで実現できます。 Cloud LoggingにBigQuery APIのログが出力される Cloud Monitoringでエラーのログを検知する Slackに通知を送る データベースの転送のエラー処理 データベースの転送では、エラーの発生箇所がいくつか考えられます。 Aurora MySQLからデータを取得する際のエラー BigQueryにデータを送信する際のエラー これらのエラーが発生した場合、AWS ECSのログにエラーが出力されます。そのため、CloudWatch Logsに出力されるログを監視することでエラーを検知し、Slackに通知を送ることができます。 具体的には、次の手順でアラートを設定しました。 CloudWatch Logsに出力されたログをCloud Watch Metrics Filterでエラー検出 CloudWatch Alarmでアラートを発火 SNS・Chatbot経由でSlackに通知 この手法の場合、全ての実装をTerraformで管理できるため、運用が楽です。他の手法として、CloudWatch Logsに出力されたログをLambdaでSNSに送信するという方法もあります。しかし、この方法は、Lambdaのソースコードの管理(GoやPythonなど)が必要になるため、運用が複雑になります。よって、今回はTerraformで管理する方法を採用しました。 インフラストラクチャの管理 Terraformによるリソース管理の仕組み Findy Toolsのデータ基盤ではTerraformを用いてリソースを管理しています。 各環境は、 environments ディレクトリに分割しています。Findy Toolsのデータ基盤では、 production と staging の2つの環境を管理しています。 Terraformのワークスペースは、機能ごとに分割しています。例えば、Embulkのバッチ処理に関連するリソースは次のように管理しています。 . ├── environments │   ├── production │   │   └── embulk │   └── staging │   └── embulk └── modules └── embulk このように管理することで、機能内の変更(ここでは embulk ワークスペース)が他の機能(他のワークスペース)に直接影響を与えないため、運用が安定します。つまり、機能の変更や破棄が容易になります。 一方で、共通のリソースが必要になることがあります。その場合は、プロバイダのモジュールを作成して、共通のリソースを管理します。例えば、Google Cloudのリソースは次のように管理しています。 . ├── environments │   ├── production │   │   ├── embulk │   │   └── google │   └── staging │   ├── embulk │   └── google └── modules ├── embulk └── google ここで作成したリソースは複数のワークスペースで共有できるため、運用には注意が必要です。 uvによるPythonパッケージ管理の仕組み 今回の構築では、データ加工ツールとしてdbt(Data Build Tool)を採用しました。dbtはETLツールのTransformationの部分を担当します。 dbt-coreはPythonで書かれており、周辺ツールもPythonのエコシステムで提供されています。そのため、Pythonのパッケージ管理ツールの選定が必要でした。 今回は、Pythonのパッケージ管理ツールであるuvを採用しました。Pythonのパッケージ管理をする方法は virtual env や PyEnv + Poetry 、 Docker などいくつか選択肢があります。uvを利用するとPythonのインタープリタとパッケージを1つのツールで管理できるので、環境構築が非常に楽です。 前述したものの中だと Docker もインタープリタとパッケージを1つのツールで管理可能です。今回は、 Dockerfile のメンテナンスが必要であること、やりたいことがシンプルであることから、採用を見送りました。 $ # たったこれだけで環境構築ができる🎉 $ curl -LsSf https://astral.sh/uv/0.5.7/install.sh | sh $ uv python install 3.12.6 $ uv python pin 3.12.6 $ uv sync 開発時に発生した課題と解決法 EmbulkのDockerをローカルで動かすことが難しい EmbulkのリポジトリではDocker Containerを管理しています。開発当初、AWSのPrivate Subnetと通信する必要がありローカルで動かすことが難しいという課題がありました。 すぐに思いつく対策として、Docker Composeを使ってDBのMockを立ち上げる手が考えられます。しかし、今回はあえてローカル環境を作らない選択をしました。ローカル環境を作らないことにより、その分の開発工数を削減できます。 前述の選択により基本的にステージング環境で管理することになりました。ここで課題になるのが、ステージング環境のECRやデプロイやECSの実行に手間がかかることです。そこでコマンドを作成し、デプロイと実行に手間がかからないようにしました。 ステージング環境へのデプロイは次のコマンドで実行します。 $ ./command/push_image_to_ecr staging [NOTICE] 🚀 ステージング環境にDockerイメージをpushします [NOTICE] 🚪 ECRとDockerにログインします Login Succeeded [NOTICE] ✅ ECR にログインしました [NOTICE] 🛠 Dockerイメージを作成します [+] Building 1.4s (19/19) FINISHED ... [NOTICE] ✅ Dockerイメージの作成が完了しました [NOTICE] 🏷 イメージにタグを付与します [NOTICE] ✅ イメージにタグの付与が完了しました [NOTICE] 🚀 ECRにDockerイメージをpushします ... [NOTICE] ✅ ECR へのDockerイメージのpushが完了しました [NOTICE] 🎉 DockerイメージのビルドとECRへのpushが完了しました ステージング環境での実行は次のコマンドで実行します。 $ ./command/run_embulk_on_ecs [NOTICE] 🚀 EmbulkのECSタスクを起動します { "tasks": [ ... ] } [NOTICE] ✅ EmbulkのECSタスクの起動に成功しました [NOTICE] 🎉 EmbulkのECSタスクの起動が完了しました また、Embulkで新しいテーブルを処理するためには liquid.yml ファイルを新たに作成する必要があります。こちらも手間を省くために独自コマンドを作成しています。 $ ./command/generate_conf new_table [NOTICE] 🔍 テンプレートファイルと出力先ディレクトリの存在確認 [NOTICE] ✅ テンプレートファイルと出力先ディレクトリの存在確認が完了しました [NOTICE] 🚀 Embulkの設定ファイルを生成しています: new_table [NOTICE] ✅ Embulkの設定ファイルの生成が完了しました: new_table [NOTICE] 🎉 Embulkの設定ファイルを生成しました。ファイル名: new_table.liquid.yml 本番の手動デプロイも時間がかかります。Embulkのリポジトリではデプロイを自動化しています。 main branchにPull Requestを作成した時点で、stgへのデプロイ main branchにMergeした時点で、本番環境にデプロイ uvとdbtを組み合わせるとコマンドが長く入力の負担が大きい uv は非常に便利です。しかし、 dbt を組み合わせて使うとコマンドが長くなる問題がありました。 # コマンドの全体像 # 実際の開発の時は、modelを指定するので、これよりも長くなります $ uv run dbt debug --profile *** --target dev --project-dir ./tools そこで、Shell Script, Taskfileを使ってラッパーを作成し、コマンドを短くしました。 # コマンドの全体像 # 実際の開発の時は、modelを指定するので、これよりも長くなります $ uv run dbt debug --profile *** --target dev --project-dir ./tools # Shell Scriptとして実行 # 使い慣れている方が多い、Shell Scriptでラッパーを作成 # 少し短くなります🙌 $ bash scripts/dbt_wrapper.sh debug # Go Taskで実行 # 元のコマンドに比べ、半分以下にすることができました🎉 $ task dbt -- debug 開発を振り返って 今回の取り組みでは、持続的開発が可能なデータ基盤とその開発環境を作成できました。また、当初の見積もりよりも一ヶ月早く実装できました。 今回のデータ基盤構築プロジェクトを振り返って、プロジェクト成功の鍵がいくつかあったと考えています。 実績のあるツールの活用による開発の効率化 構築にあたって、既存の知見が多いツールや実績のある技術を積極的に採用しました。それぞれが成熟したエコシステムを持っているため、課題が発生した際に素早く調査・解決できたのが大きな利点でした。 社内エンジニアとの連携 データ基盤構築は多くの技術やチームが関わるため、横のつながりを活用することが非常に重要でした。ファインディは横のつながりが強く、相談しやすい環境です。初見の技術で課題に直面した際、SREチームやデータソリューションチームのメンバーに相談することで、迅速に解決できました。特にTerraformやAWSの運用においては、社内のエンジニアの知見を活用したことで、手戻りや長時間の調査を防ぐことができました。 ラッパーや便利ツールの作成 ラッパーやコマンドの短縮化により、日常的な作業の効率が大幅に向上しました。日常の作業効率を上げた分、アーキテクチャの議論や意思決定に時間を割くことができたので、これらのツールに投資した時間は、長期的に見ると価値のあるものでした。 学びと次への展望 データ基盤のような横断的なプロジェクトでは、他チームとの連携やツールの選定が効率性に寄与すると学びました。また、技術としては、AWSの通知システムの構築手法やEmbulkの実用上の課題を認知したことが学びでした。特に、Embulkの起動時間が長いことは想定外でした。 1 今後、転送するテーブル数が増えた場合は、ECSの並列化などの高速化をする予定です。 今後は作成したデータ基盤で、データの利活用を進めていく所存です。 今回の取り組みが、他のエンジニアにとっても何かしらのヒントとなれば幸いです。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers 調査により、Embulkの起動時間が原因であると判明しています。具体的には、JVMとJVM上のRubyランタイムの初期化の時間でした。なお、Embulk本体はJavaではありますが、プラグインはRubyで記述可能です。 ↩
アバター
このブログの内容をポッドキャストでも配信中! こんにちは。ソフトウェアプロセス改善コーチでFindy Tech Blog編集長の高橋( @Taka_bow )です。 さて、前回の続きです。 tech.findy.co.jp 順調に行っていたかに見えたState of Devops Reportですが、ここにきて大きな壁が立ちふさがります。それが、 ソフトウェア界の巨匠Martin Fowler(マーティン・ファウラー) でした。 Martin Fowler(Image source: Wikimedia) このブログの内容をポッドキャストでも配信中! Martin Fowler氏とは 巨匠の不満 2015 State of Devops Report DORAの設立へ 2016 - 2017 State of DevOps Report DORA激動の年 Puppet版State of DevOps Report GoogleになってからのState of DevOps Report 入れ替わる著者陣 David Farleyの登場 Eliteレベルがまた消える Four Keysの定義が変更 ソフトウェア開発は、今も昔も、どこか実験的である Martin Fowler氏とは (良くご存じの方は飛ばしてください) Martin Fowlerを知らない方向けに簡単に紹介すると、ソフトウェア設計やアジャイル開発の分野で世界的に影響力を持つスーパーエンジニアです。「マイクロサービス」の提唱者であり、彼の著書『リファクタリング』は、コードの品質を向上させる方法論としてエンジニアのバイブルとなりました。 www.ohmsha.co.jp 個人的な印象は、最初は「UMLモデリング」に長けた方という印象だったのですが、徐々に「パターン」の話が多くなり、最終形態として「アジャイル」に話題が移っていった気がします。 また、この写真、エンジニアだったら見たことありますよね? Alistair CockburnのFacebookより( https://www.facebook.com/TotherAlistair/posts/10156214284634035 ​) アジャイルマニフェスト (アジャイルソフトウェア開発宣言) の背景画になってるアレですね。 この、ホワイトボードを指さしている人物こそMartin Fowlerそのひとです。(と、言われています) アジャイルマニフェストの署名者の一人であり、 ブログ や講演を通じてアジャイルを実践的に解説してくれる重要な立役者です。 巨匠の不満 さて、State of DevOps Reportの話に戻しましょう。Martin Fowler 本人によって、書籍「LeanとDevOpsの科学[Accelerate] 」 *1 の冒頭では、次のようなエピソードが寄稿されています。 本書に寄せて 2、3年前、あるレポートを読んでいたら、こんな文に出くわしたーー「今や我々は自信をもって断言できる。IT部門のパフォーマンスの高さには、生産性、収益性、そして市場占有率を高める効果があり、組織全体の業績と高い相関をもつ」。この手のレポートは即、 ゴミ箱に投げ捨てる のが私の通常の反応である。大抵は 「科学」を装ったたわごと にすぎないからだ。しかしそのとき読んでいたのは 『2014 State of DevOps Report (DevOpsの現況に関するレポート2014年版)』 であったため、私はためらった。著者の1人が私の同僚であり友人でもある Jez Humble氏 で、私に負けず劣らずこの種のたわごとを嫌う人物であることを知っていたからだ(もっとも、正直言ってゴミ箱に投げ捨てなかった理由はもう1つある。あのレポートはiPadで読んでいたのだった)。 苛烈な文章です。紙だったら捨てられていたのでしょうか!Martinは、さっそくNicole ForsgrenとJez Humbleと3人で話す機会(電話会議)を作ります。 Forsgren氏は根気強く丁寧に研究の論拠を説明してくれた。その説明は、そういった調査・分析方法には詳しくない私にとっても十分な説得力があり、通常をはるかに上回るレベルの(学術論文で発表される研究さえ凌ぐ)厳密な分析が行われている、ということが理解できた。 実際に書籍が出版されるのは、この会議から4年後(2018年)になるのですが……2014年時点で、まずは一旦は納得したようです。 しかし…… そのため、 私はその後もState of DevOpsレポートを興味深く読み続けていたが、その一方で不満も募ってきた。 どの年度のレポートも研究の成果を公表するばかりで、Forsgren氏が電話で私にしてくれたような説明が一切ないのである。おかげでレポートの信頼性が大きく損なわれていた。 推測だけに基づいた研究ではないことを示す根拠がほぼ皆無なのだ。 Martin Fowlerはレポートの方針に納得がいっていないようです。 そこで私も含めて内情を知る者が3人を説得し、 研究の調査・分析手法を紹介・解説する本を執筆してもらった。 このように、Martin Fowlerの不満があったからこそ「LeanとDevOpsの科学[Accelerate] 」が存在すると言っても過言ではありません。 「LeanとDevOpsの科学[Accelerate] 」が技術者からすると慣れない文体で書かれているのは、あれが技術書ではなく 「研究の調査・分析手法を紹介・解説する本」 だからだと思われます。統計手法の解説本ですものね。 2015 State of Devops Report Martin Fowlerから「根拠の提示がない」と言われた2015 State of DevOps Report ですが、前年と比べ分析に苦慮していた様子が伺えます。 まず、Change Failure Rate(変更失敗率)は、あいかわらずITパフォーマンスの主要な構成要素(construct)からは除外されています。レポートには具体的な事に触れられていませんでしたが、後日出版された「LeanとDevOpsの科学[Accelerate] 」には次のような記述がありました。 クラスター分析では「ハイパフォーマー」「ローパフォーマー」「ミディアムパフォーマー」のいずれの集団についても、この4つの尺度で有意な分類と差別化(チームのカテゴリー化)が行えた。ところが、この4つの尺度で1つの構成概念を得ようとすると問題が生じた。 妥当性と信頼性を検証するための統計的仮説検定にパスしないのである。 分析の結果、リードタイム、リリース頻度、サービス復旧までの所要時間の3つの尺度だけを使えば、妥当で信頼性のある構成概念が得られることが判明した。 ちょっと分かりにくい文章なので整理すると、ソフトウェアデリバリーのパフォーマンスを正確に測定するには、 「リードタイム」「リリース頻度」「サービス復旧までの所要時間」の 3つの尺度だけなら 信頼性高く妥当な評価ができる。 変更失敗率も重要な指標であり、これら 3つの尺度と強い相関はある 。が、独立した構成概念として扱うには適していない。 「変更失敗率」は予測しずらい 異質な指標 であり、分析や予測の際には補足的な要素として考慮する必要がありそうです。最新の2024 DORA Reportでも「変更失敗率」はイレギュラーな結果を残しています(別ブログで詳しく触れたいと思います)。 2015年のパフォーマンス・クラスターはSuper High、High、Medium、Lowに分けられ、それぞれ「4段階のスピード」で集計されました。 2015 State of DevOps Reportより しかし、パフォーマンスの傾向を特定するまでには至っていません。かろうじて、高パフォーマンスチームと低パフォーマンスチームの間には、明らかに大きな差がある、ということを突き止めたに過ぎませんでした。 【高パフォーマンスチームと低パフォーマンスチーム間のITパフォーマンス指標の比較】 2015 (Super High vs. Low) 2014 (High vs. Low) Deployment Frequency 30x 30x Deployment Lead Time 200x 200x Mean Time to Recover (MTTR) 168x 48x Change Success Rate 60x 3x DORAの設立へ 翌年2016年10月、Nicole ForsgrenとJez HumbleはDevOps Research and Assessment (DORA)を立ち上げます。これは、誰からの支援(投資)を受けずに立ち上げた会社だったそうです。そもそも、なぜ会社設立に至ったのか? 後日書かれたJez Humbleのブログをもとに解き明かしたいと思います。 medium.com State of DevOps Reportの研究は地道に成果を上げ始め、その取り組みが実際のビジネス成果を改善することも証明し、多くの企業からデータを集めることにも成功していました。 一方で、組織が抱える2つの大きな問題も見えてきたそうです。その2つとは…… ビッグバン型変革の問題 多くの組織が陥った失敗パターンの代表例が「ビッグバン型変革」でした。これは、アジャイル手法と成熟度モデルを一度に導入しようとしたアプローチです。「どんな組織にも当てはまるテンプレート」として導入されたものの、実際の組織の状況とは相容れないことが多く、持続可能な改善にはなかなかつながりませんでした。 特に大きな問題は、現場で働く実務者の関与が不足していたことでした。日常業務の中で原則や実践を少しずつ試しながら改善していくプロセスが欠如しており、このことが変革の成功率を大きく下げる要因となっていました。 コンサルタントモデルの問題 多くの組織は改革のためにコンサルタントを採用し、現状分析と改善策の提案を求めました。しかし、このアプローチにも課題がありました。コンサルタントが話を聞けるのは、実際に作業を行っている現場の人々のほんの一握りに過ぎません。さらに、改善提案はコンサルタント個人の専門知識に大きく依存することになり、客観的に進捗状況を追跡することも難しくなりました。 実は、このやり方はコンサルティング会社にとっても理想的なビジネスモデルとは言えませんでした。なぜなら、優秀な人材を現場に配置しなければならないにもかかわらず、継続的な仕事が保証されているわけではなかったからです。また、このアプローチは規模の拡大も難しく、ビジネスとしての成長にも限界がありました。 これらの問題認識から、NicoleとJezは、アルゴリズムを活用して組織の改善領域を特定し、具体的な改善戦略を提案できるプラットフォームの必要性を認識しました。 特に注目すべきは、変革や改善を 「どこから始めるべきか?」 という組織からの本質的な問いに、データとアルゴリズムを用いて客観的に答えられる仕組みを作ろうとした点です。 この話題が出た時、Nicoleの目が輝きました。「ねえ、もしソフトウェアデリバリーのプロセス全体から何十人もの人々のデータがあれば、その質問に答えることができる。どのアルゴリズムを使うべきか、そしてそれをどのように修正すべきかも分かっている。これは 制約理論(TOC)の問題 に過ぎないのよ!最も賢く、効率的な方法で戦略を立てる方法を伝えることができるわ。」 私は一瞬考えて言いました。「待って、本当に?それならば作ってみよう!」そして、そこからDORAは誕生したのです。私たちは翌日からモックアップの作成に取り掛かりました。 Jez Humbleのブログから 2016年にDORAは設立されました。同年10月にはNicoleがフルタイムでの経営を開始し、DevOps Enterprise Summitでは最初の顧客となったCapital Oneとともに、DORAの正式な「お披露目」が行われています。 2016 - 2017 State of DevOps Report かくして、Puppet + DORA の連名で発表された2016年と2017年のState of DevOps Reportは、制約理論をベースにしたアルゴリズムを活用し、数千の組織から得られたデータを統計的に分析することでDevOpsの実践と組織のパフォーマンスの関係性を客観的に実証しました。 【2016 パフォーマンス指標】 パフォーマンス指標 High Medium Low Deployment Frequency オンデマンド(1日複数回) 週1回〜月1回 月1回〜6ヶ月に1回 Lead Time for Changes 1時間未満 1週間〜1ヶ月 1ヶ月〜6ヶ月 MTTR 1時間未満 1日未満 1日未満* Change Failure Rate 0-15% 31-45% 16-30% * ローパフォーマーは概して(統計的に有意なレベルで)成績が悪かったが、中央値はミディアムパフォーマーと変わらなかった。 【2017 パフォーマンス指標】 パフォーマンス指標 High Medium Low Deployment Frequency オンデマンド(1日複数回) 週1回〜月1回 週1回〜月1回* Lead Time for Changes 1時間未満 1週間〜1ヶ月 1週間〜1ヶ月* MTTR 1時間未満 1日未満 1日〜1週間 Change Failure Rate 0-15% 0-15% 31-45% * ローパフォーマーは概して(統計的に有意なレベルで)成績が悪かったが、中央値はミディアムパフォーマーと変わらなかった。 これらの結果を元に読み取った洞察が、あの有名な 「パフォーマンスの改善と、安定性と品質の向上との間に、トレードオフの関係はない」 というものです。 さらに、統計的に有意な形で改善できるケイパビリティ(組織全体やグループとして保持する機能や能力)を24個特定したのです。このケイパビリティモデルは、研究の進展とともに進化し続けています。 これこそが、DORA設立の背景にあった 「どこから始めるべきか?」 の答えでありFour Keysのパフォーマンス・スコアと、この相関図を見比べながら改革や改善の戦略を立てられるようしたことがDORA研究のもたらした最大の成果と言えます。 LeanとDevOpsの科学[Accelerate] 図A.1 本研究の全体の構成 を元に筆者が作成 また同じ年2016年に、Gene KimとJez Humbleは他の著者とともに"The DevOps Handbook: How to Create World-Class Agility, Reliability, & Security in Technology Organizations"(邦題:The DevOps ハンドブック 理論・原則・実践のすべて)を刊行します。 bookplus.nikkei.com この本の内容は、DORAが提唱したケーパビリティモデルを補完する内容であり、DevOpsに必要な実践内容が書かれた本です。 2021年には2nd Editionが刊行されているのですが、残念ながら日本語訳はありません。 itrevolution.com なお、2nd Edition ではDr. Nicole Forsgrenも新たに参加し、加筆しているという個人的には胸熱な展開になっています。 DORA激動の年 2018年は、DORAにとって激動の年でした。 まず、2018年3月27日、かねてより進めていた新しい書籍が発売となります。 Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations (邦題「LeanとDevOpsの科学」)です。 itrevolution.com この本の出版でMartin Fowlerと約束を果たしたことになります。冒頭で述べた通り、この本はDORAの「研究の調査・分析手法を紹介・解説する本」として生まれました。 発行はIT Revolution Pressで、DORAの二人Nicole Forsgren、Jez Humble、そしてIT RevolutionのGene Kimの名前で発行されました。 ここにPuppet Labsのメンバーはいません。(謝辞の中には出てきますが) そして「LeanとDevOpsの科学」が出版された翌月、書籍名(原題"Accelerate")を冠した Accelerate State of DevOps Report という、新しいプログラムを発表します。 これは、長年共に歩んできたPuppet社とのパートナーシップ解消を意味しました。DORAは、次のパートナーとしてGoogle Cloudを選択したのです。当時のインタビュー記事があります。 www.infoq.com 新しい Accelerate State of DevOps Reportは 2018年8月29日にリリース されます。 筆者としてクレジットされたメンバーは3人だけでした。 Nicole Forsgren PhD(ニコール・フォースグレン博士) Gene Kim(ジーン・キム) Jez Humble(ジェズ・ハンブル) 2018 Accelerate State of DevOps Reportの表紙 パートナーであるGoogle Cloudがダイヤモンドスポンサーであることはもとより、ゴールドスポンサーがAmazon Web Services、CA Technologies、CloudBees、Datical、Deloitte、Electric Cloud、GitLab、IT Revolution、Microsoft、PagerDuty、Pivotal、Redgate、Sumo Logic、Tricentis、XebiaLabsであり、非常に豪華です。 肝心の中身ですが、2018年のパフォーマンスの指標とレベルにはちょっとした変化が生じます。 それは、MTTRが "Time to restore service" という言い方に変わったことと、レベルに初めて Elite が登場したことです。 【2018 パフォーマンス指標】 パフォーマンス指標 Elite High Medium Low Deployment Frequency オンデマンド(1日複数回) 1日1回〜週1回 週1回〜月1回 月1回〜6ヶ月に1回 Lead Time for Changes 1時間未満 1日〜1週間 1週間〜1ヶ月 1ヶ月〜6ヶ月 Time to restore service 1時間未満 1日未満 1日未満 1週間〜1ヶ月 Change Failure Rate 0-15% 0-15% 0-15% 46-60% このように、リサーチは順調であったようですがDORAのCEO兼主任研究員であったDr. Nicole Forsgrenには大きな重圧がかかっていたようです。 この頃のことをJez Humbleはブログで次のように振り返っています。 経費を抑えた自力での会社運営には大きな代償がありました: それは燃え尽き症候群です 。スタートアップは創業者を疲弊させることで有名ですが、私たちも例外ではありませんでした。特に最も大きな負担を背負っていたのはNicoleでした。CEOとして彼女は、会社の戦略、財務、そして事業運営全般に責任を負っていました。それだけではありません。CEOとして市場戦略の立案と実行をほぼ一人で担うだけでなく、State of DevOpsレポートの主任研究者、『Accelerate』の主執筆者、そして買収交渉の責任者も務めていました。彼女が言うように、これらの成果はすべて何年もかけて築き上げたものですが、驚くべき仕事の処理能力を持っていた彼女でさえ、膨大な時間の労働なしにはこれらを実現することはできなかったでしょう。 これこそが投資を受けなかったことの代償でした - より大きなチームを雇って、この重荷を分散することができなかったのです。 Jez Humbleのブログから 2018年12月、Nicole Forsgrenは DORAをGoogleに売却する決断をしたのでした。 Puppet版State of DevOps Report 一方、Puppet社も2018年は独自のState of DevOps Reportを発行します。 しかし、これはDORA版とは異なるポリシーで編集されたものでした。2013年版に原点回帰するかの如く、DevOpsの進化の段階を特定し、DevOpsへの変革プロセスの定量化に舵を切っています。 Puppet版 2018 State of DevOps Reportについて語る人物は、あのAlanna Brownでした。 その後、Puppet社は、2022年4月にソフトウェア開発ツール大手 Perforce Software, Inc. に買収 されましたが、現在もState of DevOps Reportはシリーズを継続中であり、主にDevOpsに取り組む現場での実用性に重点を置いています。 2024 State of DevOps Report GoogleになってからのState of DevOps Report Googleの一員となったことで、安定した環境、持続可能な研究環境を手に入れたDORAは、途中COVID-19による2020 DORA Reportの中止もありましたが、晴れて今回で10冊10年目を迎えることができました。 ここでは2019年〜2023年までのトピックを駆け足で紹介します。 入れ替わる著者陣 2019年にGene Kim、2021年にはDr.Nicole ForsgrenとJez HumbleがDORAを去ります。現在は、他のDORAメンバーやGoogleのリサーチャーを中心に研究が引き継がれています。 Gene Kim は現在もIT Revolutionの代表であり、執筆活動や講演を精力的にこなしています。2019年に来日しており、DevOpsDays Tokyo 2019のキーノートセッションに登壇しています。(私は現地で拝聴できました!) thinkit.co.jp Jez Humble は現在もGoogleに席を置きSRE(Site Reliability Engineering)のエンジニアとして活躍する傍ら、カリフォルニア大学バークレー校(UC Berkeley)の教員も続けているようです。 www.ischool.berkeley.edu Dr.Nicole Forsgrenは現在Microsoft Research のパートナーとして Developer Experience Lab を率いており、ACM Queue の取締役も務めています。最近は、科学を活用しソフトウェア開発者をより楽しくする研究を実践しています。DevExやSPACEフレームワークに関する研究論文を発表し、精力的に活動中です。 彼女の最近の論文について、以前解説ブログを書いたので貼っておきます。 tech.findy.co.jp また、今年の6月に来日しファインディ主催の「開発生産性Conference 2024」にて基調講演をご担当頂きました。 Dr. Nicole Forsgren (開発生産性Conference 2024にて) David Farleyの登場 2022年と2023年の2年間だけ、著名なエンジニアDavid(Dave) Farley(デイビッド(デイブ)・ファーリー)が関わりました。 David(Dave) Farley(Image source: InfoQ.com) 彼は、Jez Humbleと共にベストセラー「Continuous Delivery」を書いた人物です。 www.kadokawa.co.jp 書籍「Modern Software Engineering」の筆者でもあり、文中、Dr. Nicole ForsgrenにまつわるエピソードやDORAの研究成果が引用されており、非常に参考になる本です。 bookplus.nikkei.com Eliteレベルがまた消える 2022年の分析では、 パフォーマンスレベルからEliteが消滅します。 これは、最もパフォーマンスの高いクラスタが、2021年のEliteの特徴を示していなかったためと述べられています。翌年2023年は復活しました。 これは、クラスター分析の特性として仕方のない現象でもあります。クラスター分析は、データの分布やその年の回答者の特性に基づいて自然に分類を形成する手法であり、 事前にクラスター数やその特徴を固定するものではありません。 そのため、特定のパフォーマンス層が少数であったり、他の層と重なりがある場合、ある年には明確なクラスターとして現れず、翌年に再び明確化することがあります。この柔軟性こそがクラスター分析の利点であり、 データに忠実である ことを意味しています。 Four Keysの定義が変更 2023年から、Four Key Metricsの一部名称と定義が変更され、より簡潔かつ実務的な表現に更新されました。次の表に、2022年までの定義と2023年の定義、および具体的な変更点をまとめています。 指標 2023年の定義 2022年までの定義 変更点 Deployment frequency (デプロイ頻度) 変更を本番環境に push する頻度。 主なアプリケーションまたはサービスで、組織が本番環境にコードをデプロイする頻度、またはエンドユーザーにリリースする頻度はどのくらいか。 定義が簡潔化され、 本番環境への変更適用に焦点が絞られています。 Lead time for changes (変更のリードタイム) コードの変更を commit してからデプロイするまでの時間。 主なアプリケーションまたはサービスで、変更のリードタイム(commit されたコードが本番環境で正常に実行されるまでの時間)はどのくらいか。 定義が簡潔化され、 コミットからデプロイまでの具体的な工程に限定。 「本番環境で正常に実行される」という表現が省かれています。 Change failure rate (変更失敗率) デプロイにより障害が発生し、すぐに対処する必要が生じる頻度。 主なアプリケーションまたはサービスで、本番環境に変更を加えた、またはユーザーに変更をリリースしたとき、サービスの低下(サービス障害、サービスの停止など)が発生して、対策(修正プログラム、ロールバック、フィックス フォワード、パッチなど)が必要になった割合はどのくらいか。 「デプロイにより障害が発生し」という表現 に変更され、障害の発生原因がデプロイに限定。具体的な対策例が削除されました。 Failed deployment recovery time (失敗デプロイの復旧時間) (旧名称: Time to restore service (サービス復旧時間)) デプロイの失敗時に復旧にかかる時間。 主なアプリケーションまたはサービスで、サービスのインシデントや、ユーザーに影響を与える障害(計画外のサービス停止やサービス障害など)が発生した場合、サービスの復旧に通常どれくらいの時間がかかるか。 指標名が変更され、定義が「デプロイの失敗」に絞られました。 例として挙げられていた「計画外のサービス停止やサービス障害」が削除されました。 ソフトウェア開発は、今も昔も、どこか実験的である ここまでが去年までの振り返りとなります。 前回のブログで、Tom DeMarco はのIEEE Software誌を引用し「ソフトウェアの力で世界を変えるようなプロダクトを生み出すことの方が重要」というDeMarco自身の「気づき」について引用しました。実は、彼はその記事の最後で、こう締めくくっています。 Photo of Tom DeMarco by Hans-Rudolf Schulz ソフトウェア開発は、今も昔も、どこか実験的である。 実際のソフトウェアの構築はそれほど実験的ではありませんが、その構想は実験的です。そして、この点にこそ私たちの焦点が当てられるべきでしょう。私たちは常にここに焦点を当てるべきでした。 (Tom DeMarco, 2009) DORAの10年は、まさにDeMarcoが語った「ここに焦点」を当て続けた挑戦そのものだと感じます。日々の実践と実験の中から何が本当にチームを強くし、ソフトウェアをより良いものにするのかを探求し続けたその姿勢こそ、彼の言葉を現実のものとし未来を照らし出す希望そのものだと私は信じたいのです。 では、いよいよ2024 DORA Report の中身を見ていきましょう! 次回に続きます。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers *1 : Forsgren, N., Humble, J., & Kim, G. (2018). LeanとDevOpsの科学 [Accelerate]: テクノロジーの戦略的活用が組織変革を加速する. インプレス.
アバター
このブログの内容をポッドキャストでも配信中! こんにちは。ソフトウェアプロセス改善コーチでFindy Tech Blog編集長の高橋( @Taka_bow )です。 2024年10月23日、2024 DORA Accelerate State of DevOps Report、通称DORA Reportが公開されました。 2024 DORA Accelerate State of DevOps Report 表紙 このレポートは、ソフトウェア開発における運用と実践について、科学的な手法で調査・分析した結果をまとめたものです。 私は毎年このレポートを楽しみにしています。今年は10回目10年目の節目ということで、いつもより丁寧に読みました。 詳しい人でしたら、10年よりもっと長くないだろうか?と不思議がる方もおられるでしょう。 その辺の複雑な事情を含め、DORA Report 10年間の軌跡とその上に成り立つ最新レポートを解説したいと思います。全4回の予定です。 本記事ではv.2024.3をベースに解説します。なお、執筆時点で日本語版はまだリリースされていませんでした。また、 正誤表 を確認しなるべく最新の情報を参照するように努めました。 DORA Reportのライセンスは次の通りです。 “Accelerate State of DevOps 2024” by Google LLC is licensed under [CC BY-NC-SA 4.0]( https://creativecommons.org/licenses/by-nc-sa/4.0/ ) なお、DORA Report原文は Google Cloudのこちらのページ からダウンロードできるので、ぜひ一次情報に触れてみてください。 このブログの内容をポッドキャストでも配信中! DORAの知見を「実践」に活かすために 科学とは何か? 「科学的リサーチ」方法とは 定量的データと統計分析がもたらす信頼性 DORA Report 10年の変遷 State of DevOps Report のはじまり なぜ2013年版はカウントされないのか? Dr. Nicole Forsgren の参画 最初はFour Keysじゃなかったし、Eliteも居なかった DORAの知見を「実践」に活かすために 私の35年のエンジニア人生を振り返ると、かなりの時間「意味のない計測データ」の収集と加工に時間を費やしたと思います。なぜなら、(その時の)品質保証部門がプロダクトの「出荷」をなかなか認めてくれないからです。 いま思い出すと、 私は被告側の弁護士のようであり、品質保証部門はまるで検察側のよう でした。 裁判長は、事業部のトップです。 私はプロジェクトを終わらせるために、ありとあらゆるデータを集めて「そのプロダクトは動く。(きっと)問題ないはずだ!」を弁護する必要がありました。 DFD(data flow diagram)の生みの親であり、 「ピープルウェア」「デッドライン」等の名著 で有名なTom DeMarco(トム・デマルコ)というエンジニアの巨匠がいます。 Photo of Tom DeMarco by Hans-Rudolf Schulz 彼は、若かりし頃(1982年)の論文で次のような言葉を発しました。 「計測できないものは制御できない」 “You can’t control what you can’t measure.” これは、私のような古いエンジニアにとっては、しばらくのあいだ 呪言 となりました。 しかし、2009年7月、IEEE Software誌7月8月合併号 *1 に、Tom DeMarco は衝撃的な記事を寄稿します。 タイトルは ”Software Engineering: An Idea Whose Time Has Come and Gone?(ソフトウェアエンジニアリング:その考えは、もう終わったことなのか?)” “You can’t control what you can’t measure.”(計測できないものは制御できない) このセリフには本当の真実が含まれているのですが、私はこのセリフを使うことに違和感を覚えるようになりました。 (中略)例えば、過去40年間、私たちはソフトウェアプロジェクトを時間通り、予算通りに終わらせることができないことで自らを苦しめてきました。 この文章は当時、Tom DeMarco 自身が「測定できないものは制御できない」は誤りだったと認めた!ということで業界に衝撃が走りました。しかし、Tom DeMarco が本当に言いたかったことは、次の文章に含まれます。 しかし、先ほども申し上げたように、これは決して至上命題ではありませんでした。 もっと重要なのは、世界を変えるような、あるいは企業やビジネスのあり方を変えるようなソフトウェアを作るという「変革」です。 Tom DeMarcoが指摘したように、時代はさきほどのような「裁判ごっこ」よりも、もっと顧客との関係性を重視する方向に確実に変化してきました。それが、リーンであり、アジャイルでありDevOpsなのだと思います。 そんな中で登場してきたFour Keysですが、出会ったときの衝撃は今でも鮮明に覚えています。その指標があまりにもシンプルで、なおかつ説得力に満ちていたからです。 DORAの研究成果は決して一時的なトレンドではありません。Four Keysを単なる「流行り」と捉えるのは誤りです。しかし、その一方で、すべてを鵜呑みにする必要もありません。 2024年で10周年を迎えたDORA Reportには、この取り組みが成熟してきたことを示す重要なメッセージが随所に見られます。その代表例が"Applying insights from DORA"(DORAの知見を実践に活かすために)という章です。 一部を訳します。 私たちの調査結果は、皆様が独自の実験や仮説を立てる際の参考にしていただけます。チームや組織に最適なアプローチを見出すために、変更による影響を測定しながら実験を重ねることが重要です。それにより、私たちの調査結果の検証にもつながります。結果は組織によって異なることが想定されますので、ぜひ皆様の取り組みを共有していただき、その経験から互いに学び合えればと思います。 これは、DORAの取り組みが科学的だからこそ言えることであり、数々の困難があったなかで10年間継続してこれた理由でもあると思うのです。 科学とは何か? DORA Reportから少し脱線するのですが、とても大事なことなので説明させてください。 書籍「LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する」(原題"Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations") が、DORAの研究ベースに書かれていることは広く知られているところです。 book.impress.co.jp ところで、このタイトルの 「科学」 は何を指しているのでしょうか。 科学とは「なぜだろう?」という疑問に対して、実験と観察を重ねながら、誰でも同じ結果を得られる答えを見つけ出す取り組み、と言えます。天文学者であり小説家でもあった、20世紀屈指の科学者カール・セーガンは科学について次のような表現をしていました。 "Science is a way of thinking much more than it is a body of knowledge." Carl Sagan 科学は、思考の方法であり、知識の集積ではない。 カール・セーガン 例えば、あるカレー店の人気の秘密を科学的に考えてみましょう。 「このカレーが美味しいのはなぜか?」という問いに対して、「シェフの腕が良いから」という個人的な感想や、「創業100年の伝統の味だから」という言い伝えだけでは、科学的な説明とはいえません。 科学的なアプローチでは、次のような調査と実験を行います。 100人のお客さんに同じ条件で食べてもらい、評価を集める スパイスの配合を少しずつ変えて、味の変化を測定する 調理時間や火加減を細かく記録し、最適な条件を探る 異なる調理人が同じレシピで作っても、同じ味になるか確認する このような過程を経て、「このスパイスの配合で、この温度で30分煮込むと、8割以上のお客さんが美味しいと感じるカレーができる」と言った、誰でも確認できる答えにたどり着けるのです。 開発の現場でも同じです。 「このやり方は効果的だ」という個人の経験や、「有名な企業がやっているから」という理由だけでは、本当にそれが正しいのかわかりません。 DORAの研究では、これらを科学的アプローチによってDevOpsの成功要因を明らかにしました。個人の経験や直感を超えて、数多くの組織のデータを分析し、客観的な証拠に基づいて「何が効果的なのか」を示したのです。これは単なる成功事例の集積ではなく、 科学的リサーチ によって検証された信頼性の高い知見なのです。 「科学的リサーチ」方法とは 科学的リサーチとは、現象を体系的に調査し、新しい発見や理論を導き出す手法です。観察から始まり、概念化、測定可能な 変数 への置き換え、モデル化という段階を経て、客観的なデータに基づいた結論を導きます。 向後, 千春. (2016). 18歳からの「大人の学び」基礎講座: 学ぶ, 書く, リサーチする, 生きる. 北大路書房. 図3-3に筆者が加筆 研究の流れは次の通りです。研究プロセスは次の4段階で進みます: 現象の観察 例えば、「なぜある開発チームは他のチームより高い成果を上げているのか」という問いからDORA(DevOps Research and Assessment)チームの研究が始まりました。 概念の特定 DORAの研究では、継続的デリバリー、継続的インテグレーション、自動化テストの実施などを成功要因として特定しました。 変数への変換 概念を測定可能な形に変換します。例えば、デプロイ頻度、変更リードタイム、障害復旧時間、変更失敗率などの具体的指標として定義します。 モデルの構築 収集したデータを統計的に分析し、因果関係を明らかにします。DORAの研究では、自動化テストの実施が変更リードタイムを短縮することや、チームの独立性がサービスの信頼性向上につながることを実証しました。 この一連のプロセスを通じて、科学的リサーチは客観的な検証可能性、再現性、そしてデータに基づく実証性という特徴を持ちます。これらの特徴により、DORA Reportは他の研究者が検証・発展させられる形でDevOpsの成功要因を明らかにできました。 定量的データと統計分析がもたらす信頼性 DORA Reportで用いられる科学的アプローチに対して、「都合の良いデータ解釈をしているのではないか」という批判を目にすることがあります。 しかし、この批判は科学的リサーチの本質を十分に理解していないことから生じている可能性があります。科学的リサーチとは、単にデータを収集し結果を得ることではなく、現象を客観的に理解し、実証可能な方法で結果を導き出す「方法論」そのものです。 この考え方は、DORAの研究において次のように具体化されています: 思考の方法の適用 DORAの研究では、特定の仮説(例えば「継続的デリバリーはパフォーマンス向上に寄与する」)を立て、それを証明または反証するために厳密な手法でデータを収集・分析しています。これは、科学的な「疑う」姿勢と「検証する」姿勢の両立です。 透明性と再現性 測定方法や分析手順を厳密に文書化し、他の研究者が追試可能な形で公開しています。これは、科学が単なる知識の蓄積ではなく、「共有されるべきプロセス」であることを象徴しています。 実践への応用 科学の思考方法をもとに導き出された成果が、現場での実践を通じて再び検証されています。たとえば、継続的デリバリーやテストの自動化が現実の組織で具体的な効果をもたらすことが示されています。 DORAの研究は10年にわたり、理論と実践の両面で成果を示してきました。カール・セーガンが述べたように、科学とは「知識の集積」ではなく「より良い問いを立て、より深く理解するための思考の道具」です。 DORAはこの科学的アプローチを用いて、LeanやDevOpsの成功要因を信頼性の高い方法論として確立し、現場の改善や組織変革に直接応用できる形で提供しています。毎年のクラスター分析結果の微細な変化も、このような継続的なデータ分析の重要性を示しているのです。 DORA Report 10年の変遷 今回の2024 DORA Reportでは、 "A decade with DORA"(DORAと共に過ごした10年) という章があります。DevOpsの起源から、State of DevOps Report誕生の背景、今日に至るまでの歴史が書かれています。 私は、その説明内容からこれまでの変遷を1枚の画にまとめてみました。 State of DevOps Reportの歴史 この画から分かるように「DORA Report 10年」とは 2014年版State of DevOps Reportから2024年版State of DevOps Reportまでを指します。2020年版はCOVID-19の影響で発行されていませんので、時間の経過を指す10年ではなく、この10冊が10年というわけです。 ですが、2013年版のState of DevOps Reportは10年の10冊には含まれていません。それはなぜなのか? 順を追って解説します。 State of DevOps Report のはじまり 2011年、Puppet Labsで働いていたAlanna BrownはDevOpsについてより深く理解するための調査を開始しました。この調査は、「'DevOps'的な働き方がITにおける新しいビジネスの方法として台頭している」ということを裏付ける助けとなりました。 itrevolution.com この調査の成功をベースに、2012年に新たな調査を開始、2013年 Puppet LabsとGene Kim氏が率いるIT Revolution Pressが共同で、最初のState of DevOps Reportを発行しました。 書籍「LeanとDevOpsの科学[Accelerate] *2 」には、次のような記載があります。 「State of DevOps Report』の初回は2014年版だが、研究自体はそれ以前に始まっていたという点に留意されたい。Puppet社のチームは、 DevOpsという(まだそれほど知られていなかった)概念 をより良く理解し、それが現場でどう採用されつつあるか、組織パフォーマンスの改善を組織がどう実感しているかを把握するための研究を始めており、 2012年にこの研究への参画をGene Kimに求めた。 Gene KimはTripwire, Inc.の創業者兼CTOとして13年間務めたあと、IT Revolutionを創業し出版活動、DevOpsコミュニティへの貢献に尽力する人物でした。 itrevolution.com さらに、優秀なキーマンが巻き込まれることになります。 そしてGene Kimがその後、 Jez Humbleにも応援を仰ぎ、 ともに調査に加わって全世界の組織から4,000件の回答を集め、分析した。この種の調査では最大規模である。 Jez Humble は、カルフォルニア大学バークレー校で教鞭も執っているDevOpsの研究者でした。 github.com このような経緯を経て、2013 State of DevOps Reportはリリースされたのです。 なぜ2013年版はカウントされないのか? 一言で言えば「調査方法が違う」からです。 現在の統計的アプローチが取られたのは2014年以降となります。2013年当時のPuppet社は、ITインフラストラクチャの自動化を支援するソフトウェアを開発・提供している会社でした。 その中心的なプロダクトは Puppet Enterprise であり、これはサーバーやクラウド環境、ネットワークデバイスなどの管理を効率化し、DevOpsやインフラ管理の自動化を推進するツールでした。 2013 State of Devops Report は、当時あまり知られていなかったDevOpsという概念を広め、Puppet Enterpriseの市場を開拓することが主な目的だったと思われます。実際、2013年版の調査による【主要な発見】は、やや意図的な印象を受けます。 【主要な発見】 DevOps導入状況 回答者の63%がDevOpsを導入(2011年から26%増加) 導入期間が長いほど、高パフォーマンス達成の可能性が5倍に上昇 高パフォーマンスを実現する共通実践 バージョン管理システムの使用(89%) コードデプロイの自動化(82%) DevOpsスキルの需要 コーディング/スクリプティング(84%) コミュニケーションスキル(60%) プロセス再構築スキル(56%) また、このレポートでは、後のDORAメトリクスの基礎となる4つの主要指標、デプロイ頻度・変更のリードタイム・変更の失敗率・復旧までの平均時間、いわゆるFour Keysが登場します。 しかし、現在の観点とは異なる分析結果でした。下記に、2013 State of DevOps Reportのパフォーマンス指標の解説と、グラフを転載します。 DevOpsの成熟度(未導入から12ヶ月以上前に導入) に基づいて、デプロイ頻度、変更のリードタイム、変更の失敗率、復旧までの平均時間という4つの主要なDevOpsパフォーマンス指標を分析しました。DevOpsの導入が成熟している組織は、 まだDevOpsを導入していない組織と比較して、すべての指標において著しく高いパフォーマンスを示しました。 2013 State of DevOps Report, p5 ご覧の通り、4つの指標はそれぞれ、「DevOpsを導入しているか否か」で期間分類されているのです。 Not Implemented(未導入) Currently Implementing(導入中) Implemented <12 Months(導入後12ヶ月未満) Implemented >12 Months(導入後12ヶ月以上) そして、このレポートは回答者の多くがDevOpsに関心の高い層に偏っている可能性を検証しておらず、バイアスの制御が十分でないという問題も抱えていました。 Dr. Nicole Forsgren の参画 2014年、State of Devops Report に大きな転機が訪れます。 それが、当時ユタ州立大学ハンツマンビジネススクールの教授であったDr. Nicole Forsgren(ニコール・フォースグレン博士)の参画です。 彼女は、ITインパクト、ナレッジマネジメント、ユーザー体験の専門家でした。 itrevolution.com 「LeanとDevOpsの科学[Accelerate] 」に書かれた「謝辞」には、Nicole Forsgrenの次のようなコメントがあります。 私が初めて皆さんのところへお邪魔して、「ここは違っています」などと指摘させていただいたとき(そのときの私の口調、失礼じゃなかったですよね、ハンブルさん?)、皆さんは私を部屋から蹴り出したりしなかった。 おかげで私はその後、忍耐力と共感力を養い、冷めかけていたテクノロジーへの愛を再燃させることができた。また、「あともう1回だけ、分析やってみて!」が口癖であるキム氏の無尽蔵の熱意と気合いは、我々の仕事を堅牢で大変興味深いものにしてくれている。 この謝辞から読み取れるように、Dr. Nicole Forsgren は2014年以降のState of Devops Reportに科学的厳密性をもたらした重要な人物です。それまでの調査手法に対して建設的なフィードバックをし、その結果、2014年のレポートから、より体系的で科学的なリサーチがもたらされます。 そして、2014年から2017年までの間、State of Devops Report は次のメンバーによって調査・研究がなされました。 Nicole Forsgren Velasquez(ニコール・フォースグレン・ベラスケス) Gene Kim(ジーン・キム) Jez Humble(ジェズ・ハンブル) Nigel Kersten(ナイジェル・カーステン) Puppet LabsのCIO Alanna Brown(アラナ・ブラウン) 2012年からState of Devops Report を担当する発案者 最初はFour Keysじゃなかったし、Eliteも居なかった Dr. Nicole Forsgrenの参加は、リサーチプログラムに科学的な厳密さをもたらしました。 このことで、最初のFour Keysは統計学的有意(=確率的に偶然とは考えにくく、意味があると考えられる)が検証されるようになります。 このことで、 Change Failure Rate(変更失敗率)は、他の3つの指標とは有意な相関が見られなかった ため、ITパフォーマンスの定義から除外されています。 【2014 パフォーマンス指標】 指標 High Medium Low Deployment Frequency 1日に複数回 週1回〜月1回 月1回〜6ヶ月に1回 Lead Time for Changes 数分単位 1日〜1週間 1週間〜6ヶ月 MTTR 分単位 時間単位 日単位 とはいえ、2014 State of DevOpsレポートは、ソフトウェアデリバリーのパフォーマンスと組織のパフォーマンスの関連性を明らかにし、 「高パフォーマンスのITチームを持つ上場企業は、低パフォーマンスのIT組織を持つ企業と比較して、3年間で市場価値の成長率が50%高かった」 ということが発見されています。(2014 Accelerate State of Devops Report) 2014 State of Devops Reportは、Nicole Forsgrenの「科学的リサーチ」によって次第にデータは説得力のあるものに変わっていきました。 ところが、ここにきて大きな壁が立ちふさがります。 それが、 ソフトウェア界の巨匠Martin Fowler(マーティン・ファウラー) でした。 次回に続きます。 tech.findy.co.jp ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers *1 : https://www.cs.uni.edu/~wallingf/teaching/172/resources/demarco-on-se.pdf *2 : Forsgren, N., Humble, J., & Kim, G. (2018). LeanとDevOpsの科学 [Accelerate]: テクノロジーの戦略的活用が組織変革を加速する. インプレス.
アバター
こんにちは。 FindyでMLエンジニアをしているyusukeshimpo( @WebY76755963 )です。 今回は直近で公開した「 スキル偏差値ver.3 」機能について、その内容や具体的な機械学習モデルの作成方法について紹介します。 Findyのスキル偏差値とは? スキル偏差値の概要 アップデートすることになった背景 スキルの見える化する、スキル偏差値ver.3の詳細 1.学習データの作成 1-1.使用言語ごとのデータ準備 1-2.ペアワイズ形式のデータ構築 1-3.勝敗アノテーションの付与 2.ランキング学習 2-1.ペアワイズデータの特徴量生成 2-2.機械学習モデルによる勝敗予測 3.モデルによるスコアリング 実装で苦労した点と解決策 1.モデル精度の担保 アノテーションの工夫 評価設計 2.言語固有の特徴量設計 言語特徴の言語化をしてデータ化 最後に Findyのスキル偏差値とは? スキル偏差値の概要 まずはプロダクトの概要を説明いたします。 「スキル偏差値」は、Findyに登録されているユーザーのGitHubリポジトリ(※Open-access repositoryのみ)を解析し、 コミット量、OSSプロジェクトへの貢献度、他者からのコードの支持などに基づいて技術力をスコアリングする機能です。 GitHubの解析は機械学習技術を用いて実施しており、これまでに何度かアルゴリズムや学習データのアップデートを行ってきましたが、 今回は2017年のリリース以降で最も大幅なリニューアルを行なっており、大元のアルゴリズムや学習データの作り方自体をガラッと変更しています。 アップデートすることになった背景 アップデートの背景には、大きく分けて2つの理由が存在します。 リリースから数年が経過する中でユーザーの方からの要望が増えてきたから。 特に「言語別」のスコアに対する要望が強く、言語別のスキル判定の精度改善を求めるニーズが強かったため。 2023年以降、LLMやAI Agentが登場し、エンジニアリング(特にコーディング)の領域でも、それが当たり前に使われるようになってきたから。 今後エンジニアに求められる「スキル」も環境に合わせて変わっていくことが予想される中で、よりサービス開発や運用に直結する能力を評価できるモデルに進化させていく必要があったため。 上記「ユーザーボイス」と「開発を取り巻く環境変化」を受けて、このタイミングで新たな「スキル偏差値」を作ることを決めました。 スキルの見える化する、スキル偏差値ver.3の詳細 今回のスキル偏差値の開発では次の3つの手順でスキルの見える化をしています。 学習データの作成 ランキング学習 学習モデルによるスコアリング この3つの手順について詳しく解説します。 1.学習データの作成 ランキング学習を支えるのは「質の高いデータ」です。 GitHubリポジトリから収集したデータを加工し、言語ごとに特徴量を整備することで、正確なモデル構築を目指しました。 1-1.使用言語ごとのデータ準備 GitHubリポジトリを次の主要言語ごとに分類しました。 Python JavaScript TypeScript Go Ruby PHP 各言語ごとで重視される特徴量に違いがあり、言語ごとにデータを分ける方針にしました。 1-2.ペアワイズ形式のデータ構築 ランキング学習するために、今回は「ペアワイズ形式」のデータを用意しました。これは、2つのエンティティ間でどちらが優れているかを比較する形式です。 今回のケースではGitHubユーザー間のリポジトリ情報を比較し、相対的なスキル勝敗データを生成しました。また、ペアはバイアスが生まれないようにランダムでペアを作るようにしています。 1-3.勝敗アノテーションの付与 生成したペアデータに対して、上の図のようにスキルの「勝敗」をラベリングしました。 特にラベル基準をある程度明確化しておくと担当者間でのクロスレビューの際の議論がまとまりやすかったです。 2.ランキング学習 次に、上で用意した学習データに対して、次の2つのステップを経て、「ランキング学習」の手法を用いて特徴量間の比較します。 「ランキング学習」(Learning to Rank)は、複数ある事象の「順位」を目的変数とした場合に用いられる機械学習の手法で、身近な例としては「検索エンジン」などで使われています。 機械学習を用いた「ランキング学習」の実装にはいくつか方法がありますが、今回は上述したペアワイズなデータ間の「勝敗」を学習し、 2-1.ペアワイズデータの特徴量生成 2-2.機械学習モデルによる勝敗予測 以下、それぞれのステップを解説していきます。 2-1.ペアワイズデータの特徴量生成 ランキング学習するために、まずは各々のデータを機械が認識できる形にする必要があります。 具体的には、各データを「特徴化」し、ベクトル化した数値で比較できるようにしています。 当初はこの「特徴」抽出のプロセスについては、言語を問わずある程度一元化できると考えていましたが、 実験過程で、言語間の「特徴」に大きな違いが見られました。 詳細は社外秘情報にあたるため公開できませんが、一例として、ある言語では「Readmeなどのテキストの長さ」が重要な意味を持ちます。 別の言語だとボイラープレート内にReadme用のテキストが充実しているため「Readmeの長さ」を特徴として重視しない方が好ましい、という傾向が出ていました。 上記のように、言語ごとに利用者を取り巻く環境が大きく違う点も考慮し、現段階では「言語ごとに異なる特徴を採用する」という意思決定をしています。 *1 2-2.機械学習モデルによる勝敗予測 データを特徴化したら、機械学習モデルによるランキング学習をし、当該データ間の順位を予測します。 検討初期にはより複雑なモデルを利用することも検討しましたが、「言語ごとに個別のモデルを動かす」という仕様上の制約や、特徴抽出の工夫によりシンプルなモデルでも十分な精度が実現できたため採用しています。 上記のアルゴリズムにペアワイズの学習データとその勝敗を学習させ、勝敗の判定を行なっています。 モデルの精度についてはこちらも非公開ですが、検証方法としてはこちらも「複数人が判断した際の判断と同様の出力(=勝敗)を出せるか」を基準に評価しています。 リリース時点で、対象としている6言語はいずれも人間の判断を8割以上の精度で模倣できており、一定正確なジャッジができていると判断しています。 *2 3.モデルによるスコアリング 学習モデルを作成したら、その推論結果を元にユーザーのスキルをスコアリングしていきます。 学習したのは、ペアワイズデータの勝敗ですので、計算したいユーザーと他のユーザーとの勝敗をシミュレーションして、それを元にユーザーのスキルスコアを算出します。 このスコアを一般的に偏差値計算をする数式に当てはめ、最後に調整(言語ごとに異なる尺度を正規化するなど)をしたものを「スキル偏差値」としています。 実装で苦労した点と解決策 上記を実装する上で困難な点が多々ありました。 今回は次の苦労した点と解決としてどんなことをしたかも説明していきます。 モデル精度の担保 言語ごとの特徴量 1.モデル精度の担保 アノテーションしたデータを使用しているので、モデルはアノテータに影響を受けます。 アノテータのバイアスを極力抑えて客観的に良いモデルを作成するための工夫が必要だったため、次の工夫をすることで精度改善を試みました。 アノテーションの工夫 データ作成時のアノテーションには次のような手順を導入しました。 言語経験者による判断: 経験者がアノテーションをすることで正確性を担保 ラベル基準の明確化: ラベル基準を言語化してアノテータに共有 クロスレビュー: 複数人がレビューすることでバイアスを極力抑える 例として、社内でRubyを日常的に利用する有識者へアノテーションの基準づくりを依頼しました。筆者は普段の業務でRubyを使用しないため、このように経験者から合意を得ることで、より良質な正解データを作成できました。 評価設計 アノテーションという定性的な評価を学習データにしているため、ただ単に評価関数の良し悪しで判断できません。 そんな中 どのようにモデルの精度を評価したのか も非常に重要かつ難しいポイントでした。 そこで、アノテーションとモデルの精度を担保するために定性と定量の両方で確認しました。 定量評価: 正解率や偏差値の分布を測定 定性評価: 偏差値の妥当性を人間が確認 勝敗の正解率を確認したのち、Ratingや偏差値を実際に算出しますが、正規分布に基づいているか、ユーザーはこの数値で妥当かを定性的に評価しました。 これによるアノテーション結果の正当性を確保しつつ、モデルの方向性も正しいと確認できました。実際には次のサイクルでモデル評価とアウトプット評価をして都度アノテーションから見直すこともしました。 2.言語固有の特徴量設計 また、言語ごとに特徴量設計をするのも苦労したポイントです。同じ特徴量では表現できなかったため、言語ごとに最適な特徴量設計を見つける必要がありました。 言語特徴の言語化をしてデータ化 言語ごとにどんな特徴を持っているのかを言語化し異なる特徴を設計しました。 例えば、あるプログラミング言語ではボイラーテンプレートが充実しているため独自ロジックにスキルが出やすい傾向にあったり、ライブラリの利活用が盛んなプログラミング言語など特徴量が変わってくることがわかりました。 この特徴量の言語化のフローは大きく4つのポイントに分かれます。 まず、仮説の立案し、各言語の特性を調査し、スキルの違いを反映するための特徴を言語ごとに仮説立てを行います。その後実験を重ねて、仮説に基づいて特徴量を作成し、推論結果や評価指標を確認します。 確認した結果に違和感があれば、仮説を見直して新たな特徴量を追加・修正します。これらを繰り返し、最後に評価基準と実際の結果にズレがあれば、特徴量の設計を見直し、適正化という流れを繰り返しました。 最後に 以上が スキル偏差値ver.3 の開発についてでした。参考にしていただければ幸いです。 また、弊社では機械学習エンジニア・データエンジニアなど一緒に働いてくれるメンバーを募集しております。 興味がある方は↓からご応募していただければと思います。 herp.careers *1 : 今回のリニューアルが6言語限定になったのも、上記の理由からモデルを言語別に作る必要があったためです *2 : 余談ですが、人間が判断した際も"意見が分かれる"ペアは10~20%程度存在するため、8割の精度というのはかなり妥当な水準だと考えています
アバター
こんにちは、ファインディでFindy Team+(以下Team+)を開発しているEND( @aiandrox )です。この記事は Findy Advent Calendar 2024 10日目の記事です。 adventar.org Team+ではコード管理ツール・イシュー管理ツール・カレンダーなど、様々な性質の外部サービスと連携して、エンジニア組織における開発生産性の可視化・分析を行うためのデータを取得しています。 この分析を行うためには、外部サービスごとに異なるデータ構造やAPI仕様の差を吸収した統一的なデータ管理を行う必要があります。この課題を解決するため、異なるサービスのデータを統合し、単一のUIで一貫性を持って表示する仕組みを整えています。 この記事では、コード管理ツールのデータインポートをどのようなアーキテクチャで実現しているかを紹介します。 Team+と外部サービス差分の例 全体のアプリケーションアーキテクチャ メリット 責務が明確になりコードの見通しがよい 不具合が起きたときの原因がわかりやすくなる 2種類のデータを扱うことで、柔軟性と速度を担保する 層ごとにスケールすることができる デメリット 層ごとの独立性が高いがゆえの複雑さがある リアルタイム性に欠ける 一部のリソースのみインポートするといった処理が難しい 各層について Client層 Importer層 Transformer層 API層 おわりに Team+と外部サービス差分の例 前提として、Team+では現在GitHub, GitLab, Bitbucket, Backlogから取得したコード管理系のデータを以下のように表示しています。 この画面の分析のために取得しているデータは、プルリクのステータス、コミット日、オープン日、最初のレビュー日、レビューステータス、マージ日です。 外部サービスごとの小さな差分の例として、プルリクのステータスがあります。Team+では「対応中」「クローズ」「マージ」の3種類がありますが、各サービスのAPIレスポンスの値は以下を返すようになっています。 GitHub GitLab Bitbucket Backlog open, closed opened, closed, locked, merged OPEN, MERGED, DECLINED, SUPERSEDED Open, Closed, Merged GitHubの場合、ステータスの値だけを参照してもクローズとマージの区別がつかないため、 merged_at に値が入っているかどうかで判定しています。また、GitLabの locked やBitbucketの SUPERSEDED のようなイレギュラーなステータスは、他の値に丸めるようにしています。 全体のアプリケーションアーキテクチャ 全体の流れは、以下のようになっています。これらのインポート処理は、各サービスごとに分割して全8インスタンスで行い、それぞれのインスタンス内で組織ごとに20プロセスで並列して処理しています(2024年12月時点)。 層 主な役割 Client層 APIの仕様差を吸収し、レスポンスをRepresentationインスタンスとして返す Importer層 エラーハンドリングをし、サービス独自テーブルに保存する Transformer層 各サービスごとのデータ形式差分を吸収し、共通テーブルに保存する API層 表示データのフロントエンド提供 GitHub, GitLabはClient層とImporter層の設計が少し違うため、この図では省略しています このように4つの層と2種類のテーブルを使うことで、以下のようなメリットとデメリットがあります。 メリット 責務が明確になりコードの見通しがよい この設計では、新しい外部サービスを追加する際はClient層とTransformer層、それぞれ単独で実装することができます。また、コードレビュー時も変更範囲が限定されるため、確認すべき箇所を絞りやすく、レビューの効率がよいです。 不具合が起きたときの原因がわかりやすくなる 例えば、外部サービスのAPIのエラーによってデータが取得できなかった場合、Importer層でエラーがキャッチされます。また、値がTeam+で扱うものとして想定外だった場合はTransformer層でエラーになります。 外部サービスのAPIを使っているため、こちらで対応できないエラーが起きることや想定されないデータが返ってくることは避けられませんが、それによる影響が最小限になるようにしています。 2種類のデータを扱うことで、柔軟性と速度を担保する Team+には、サービス独自テーブルと共通テーブルの2種類があります。前者はAPIレスポンスの形に近い形で保存することを目的とし、後者はTeam+で扱いやすい形式で保存することを目的としています。これにより、フロントエンドからのリクエストに対しては、外部APIと独立して安定したデータソースとして迅速に提供することができます。 他にも、サービス独自テーブルに保存されたデータはTransformer層でエラーが発生しても再利用可能なため、外部APIを再度叩く必要がありません。 層ごとにスケールすることができる 現時点では行っていませんが、Import処理とTransform処理が独立しているため、必要に応じて片方のみスケールするという選択肢を持つことができます。 デメリット 層ごとの独立性が高いがゆえの複雑さがある 層ごとに責務が分離しているため、全体の流れを把握するのが大変です。特に新しいメンバーが参加した場合、どの処理がどの層で行われているかを理解するまでに学習コストがかかります。また、デバッグ時には層の間をまたぐデータフローを追う必要があり、状況によっては負担になることもあります。 リアルタイム性に欠ける このアーキテクチャは、データの取得から変換、提供までを複数の層に分割しているため、一連の処理がリアルタイムで完結する用途には適していません。例えば、ユーザーがリアルタイムにデータを参照したい場合、現行のバッチ処理的なインポートでは対応が難しいです。 Team+でも、初回連携の際の一時的なデータ取得ではClient層しか利用していません。 一部のリソースのみインポートするといった処理が難しい このアーキテクチャでは、すべてのデータのImport処理が完了した後にTransform処理を行っています。これが完了するまで画面上にデータを表示できないため、Import処理に時間がかからないリソースから逐次的に表示できるようにするなどの柔軟性は持たせづらいです。 各層について Client層 この層では、外部サービスのAPIレスポンスや仕様がサービスごとに違うため、その差分を吸収することが大きな目的としています。 libディレクトリ配下に置いてGemのように独立して作用できるようにしつつ、アプリケーションで統一して扱えるようにしています。主に、以下のような処理を行っています。 外部サービスのAPIにリクエストを行い、そのレスポンスをアプリケーションで扱いやすい形に成形加工するRepresentationクラスに格納する リトライ処理を行う 例外を発生させる エラーに対しては、Rate limitのみリトライ処理を行っています。その他のエラーと、最大回数を上回ったエラーは例外を投げるようにしています。ここでは、主にレスポンスステータスを参照しています。 これらの処理には、外部サービス独自のGemは使わずスクラッチで実装しています。また、1ページごとに遅延実行をするようにしてメモリを圧迫しないように対策しています。 Importer層 Client層から取得したRepresentationインスタンスを使い、レコードごとのアソシエーションに応じて関連レコードと一緒に独自テーブルに保存します。 また、Clientインスタンスのような依存性を注入することで、Importerの単体テストを容易にしています。 class PullsImporter def self . call (client, repo_id :, repo_full_name :) new(client, repo_id :, repo_full_name :).call end def initialize (client, repo_id :, repo_full_name :) @client = client @repo_id = repo_id @repo_full_name = repo_full_name @user_finder = UserFinder .new end def call client.pulls(repo_full_name).each do |response| attributes = response.map do |representation| PullApiMapper .call(representation, repo_id :, user_finder :) end Source :: Pull .import!(attributes) end end end Importer内では、FinderやApiMapperなどを定義し、それを用いてインポート処理を行っています。 関連レコードの取得はFinderクラスを作成し、これを介するようにしています。これにより、関連レコードを読み込むためのN+1を最小限に抑えることができるようにしています。 class UserFinder def find_by ( uuid :) users_index_by_uuid[uuid] end private def users_index_by_uuid @users_index_by_uuid ||= Source :: User .reload.index_by(& :uuid ) end end ApiMapperは、Representationからサービス独自テーブルへの変換のためのattributes作成を行っています。関連レコード(この例ではuser)の外部キーを取得するためにFinderを渡しておき、レコード取得の処理はApiMapper内で行っています。 class PullApiMapper def call { repo_id :, user_id : user.id, title : representation.title, state : representation.state } end private attr_reader :representation , :repo_id , :user_finder def user @user ||= user_finder.find_by( uuid : representation.user.uuid) end end Transformer層 サービス独自のテーブルからレコードを取得し、各サービスのデータ構造の差分を吸収し、表示データ用のテーブルに保存します。 class PullConverter def self . call (duration) sources = Source :: Pull .where( updated_at : duration) attributes = sources.map { |source| PullMapper .new.call(source) } View :: Pull .import!(attributes) end end ここでもPullMapperが使われていますが、これはImporterで使われているApiMapperとは似ているようで少し違います。前者は、Representationクラスのインスタンスをテーブルに保存するためのもので、後者はモデルのレコードを共通テーブルに保存するためのものです。外部サービスのデータ形式の差分はここで吸収されることがほとんどです。 class PullMapper def call (source) { source_type : source.class.name, source_id : source.id, repo_id : source.repo.view_repo.id, user_id : source.user.view_user.id, title : source.title, status : to_view_status(source) } end private def to_view_status (source) return :merged if source.merged? return :closed if source.closed? :created end end API層 バックエンドから表示データ用のテーブルの値をフロントエンドに返します。ここでは、サービス独自テーブルにはアクセスせず、共通テーブルの値のみを使用します。 リアルタイムのデータ集計には独自のアーキテクチャを利用していますが、こちらに関してはまた別の機会にご紹介します。 おわりに 今回、Team+のデータインポート周りのアプリケーションアーキテクチャについて紹介しました。 このアーキテクチャは、最初からこの形だったわけではありません。複数の外部サービスと連携する中で、API仕様やデータ形式の違いに直面し、それらを克服するために少しずつ設計を見直してきました。また、例えば、初期にはエラー処理がClient層やImporter層に散在していたり、それぞれの層が密結合になっていたため、層ごとの役割分担を明確化しました。こうした試行錯誤を繰り返しながら、現在の仕組みに至っています。 今も、旧アーキテクチャの名残が残っている箇所があったり、データインポートの時間が長い組織があるといった伸びしろがあります。これからも、改善を重ねて、みなさんにとって価値のあるサービスを提供していきます! ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味のある方は、ぜひカジュアル面談で話を聞きに来てください! herp.careers
アバター