TECH PLAY

Findy/ファインディ

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

193

こんにちは、 Findy Freelance の開発をしているエンジニアの @2bo です。 先日、愛媛県で開催されたRubyKaigi 2025に参加してきました。ファインディのブースにお立ち寄りいただいた方、Rubyクイズに答えてくださった方、Drinkupに参加していただいた方、運営やSpeakerの皆様、ありがとうございました! おかげさまでとても楽しく過ごすことができ、興味深いセッションもたくさんありました。 本記事では、その中の1つである @sinsoku_listy さんの「 Automatically generating types by running tests 」で発表されていた「 RBS::Trace 」を早速、Findy FreelanceのRailsプロジェクトで試してみた結果と所感を紹介します。 RBS::Traceとは 実行手順 1. Gemfileへの追加 2. RSpecの設定 3. テストの実行 結果の確認 Inline RBS RBSファイル 参考: テストコード 結果からわかったこと Steepの導入 1. Gemfileへの追加 2. Bundle install 3. Steepの設定 4. VSCodeのSteep拡張のインストール 5. RBSファイルのエラーをコメントアウト VSCodeでの型情報の表示結果 所感 RBS::Trace導入のメリットと可能性 活用における注意点 RBSのプロジェクトへの導入について 最後に 参考 RBS::Traceとは RBS::Trace は、コード実行時にメソッドの引数と戻り値の型情報を収集し、自動的にInline RBSとしてコメントを挿入したり、RBSファイルを作成してくれるGemです。 実行手順 Findy FreelanceのRailsプロジェクトのテストでRBS::Traceを実行してみました。 執筆時点のバージョンは 0.5.1 です。 なお、今回は大枠の動作と結果を確認することが目的のため、対象は app/models/ 配下に絞っています。 次の手順で実行しました。 1. Gemfileへの追加 gem " rbs-trace " Gemfile追記後にbundle installを実行します。 $ bundle install 2. RSpecの設定 次に、RSpec用の設定ファイルを作成します。 RBS::Trace.new の引数 paths で対象のファイルを指定しています。 RBSファイルの格納先として、 sig/trace/ を指定しています。なお、この設定は任意です。 # spec/support/rbs_trace.rb RSpec .configure do |config| # RBSの出力対象とするファイルを指定 trace = RBS :: Trace .new( paths : Dir .glob( "#{ Dir .pwd } /app/models/**/* " )) config.before( :suite ) { trace.enable } config.after( :suite ) do trace.disable trace.save_comments # RBSファイルの格納先を指定 trace.save_files( out_dir : " sig/trace/ " ) end end 3. テストの実行 テストを実行します $ bundle exec rspec spec/models/ 結果の確認 テストを実行すると、Inline RBSが対象のファイルのメソッド定義の上に追記され、RBSファイルが生成されます。 それぞれの結果を次に示します。 なお、掲載しているのは例示用のコードで、実際のFindy Freelanceのコードや処理とはまったく関係ありません。 Inline RBS app/models/user.rb に次のようなInline RBSが生成されました。 class User < ApplicationRecord has_many :projects # @rbs () -> String def full_name format_name end # @rbs () -> Project? def main_project projects.find_by( active : true ) end # @rbs (Date) -> Project::ActiveRecord_AssociationRelation def projects_after_date (date) projects.where( ' start_date >= ? ' , date) end private # @rbs () -> String def format_name "#{ last_name } #{ first_name }" end end RBSファイル sig/trace/app/models/user.rbs に次のようなRBSファイルが生成されました。 class User def full_name : () -> String def main_project : () -> nil | () -> Project def projects_after_date : ( Date ) -> Project :: ActiveRecord_AssociationRelation def format_name : () -> String end 参考: テストコード RBS::TraceによるRBSの自動生成は、テストで実行された内容に依存するため、参考としてテストコードの例を掲載します。 RSpec .describe User do describe ' #full_name ' do subject { user.full_name } let( :user ) { create( :user , first_name : ' 太郎 ' , last_name : ' 山田 ' ) } it ' returns a string combining last_name and first_name ' do expect(subject).to eq( ' 山田 太郎 ' ) end end describe ' #main_project ' do subject { user.main_project } let( :user ) { create( :user ) } context ' when there is an active project ' do let!( :active_project ) { create( :project , user : user, active : true ) } let!( :inactive_project ) { create( :project , user : user, active : false ) } it ' returns the active project ' do expect(subject).to eq(active_project) end end context ' when there is no active project ' do let!( :inactive_project ) { create( :project , user : user, active : false ) } it ' returns nil ' do expect(subject).to be_nil end end end describe ' #projects_after_date ' do subject { user.projects_after_date(target_date) } let( :user ) { create( :user ) } let( :target_date ) { Date .new( 2025 , 4 , 1 ) } let!( :before_project ) { create( :project , user : user, start_date : Date .new( 2025 , 3 , 31 )) } let!( :on_date_project ) { create( :project , user : user, start_date : Date .new( 2025 , 4 , 1 )) } let!( :after_project ) { create( :project , user : user, start_date : Date .new( 2025 , 4 , 2 )) } it ' returns only projects starting on or after the specified date ' do expect(subject).to include (on_date_project, after_project) expect(subject).not_to include (before_project) end end end 結果からわかったこと 実行した結果、次のようなことがわかりました。 直接テストしていないが、テスト中に実行されるprivateメソッドの型情報も生成されている ApplicationRecordのサブクラスを返すメソッドは、具体的なクラス名で型情報が生成されている Railsのassociationやscopeメソッドには、型情報が生成されない これらはメソッド定義ではないため当然の結果である ActiveRecord::AssociationRelationのサブクラスのインスタンスを返すメソッドは、[具体クラス名]::ActiveRecord_AssociationRelationのように型情報が記載される これはRailsの仕様によるもので、そのようなクラスを動的生成しているためである 既に記載されているInline RBSは上書きされない RBSファイルの内容はテストを実行するたびに更新される Steepの導入 せっかくRBSファイルが生成されたので、型チェッカーである Steep もセットアップして型のあるRailsプロジェクトを疑似体感してみました。 ただし、RBS::TraceだけでRailsプロジェクトの型チェックすべてパスさせることはできないため、VSCodeで型情報を確認できるようにすることを目的としています。 次の手順でセットアップしました。 1. Gemfileへの追加 # Gemfile gem ' steep ' 2. Bundle install Gemfile追記後にbundle installを実行します。 $ bundle install 3. Steepの設定 設定ファイルとなる Steepfile 作成します。 D = Steep :: Diagnostic target :app do # RBSファイルの格納先を指定 signature " sig/trace " # Steepで型チェックする対象のファイルを指定 check " app/models " # 型チェック結果を全て抑制(無音)する configure_code_diagnostics( D :: Ruby .silent) end 4. VSCodeのSteep拡張のインストール steep-vscode をVSCodeにインストールします。 5. RBSファイルのエラーをコメントアウト RBSファイル内にエラーがあると、VSCodeのSteep拡張が動作しないため、エラーしている箇所をコメントアウトしました。本来は型定義を追加、修正するなどしてエラーを解消する必要がありますが、今回はVSCodeで型情報を確認できることが目的のため、このような対応をしました。 先のRBSファイルの例で言うと、RBS::Traceの実行だけでは Project::ActiveRecord_AssociationRelation クラスの型情報が生成されないため、 RBS::UnknownTypeName エラーになります。これをコメントアウトすることでエラーを握りつぶしています。 class User def full_name : () -> String def main_project : () -> nil | () -> Project # RBS::UnknownTypeName エラーになるためコメントアウト # def projects_after_date: (Date) -> Project::ActiveRecord_AssociationRelation def format_name : () -> String end VSCodeでの型情報の表示結果 メソッドの呼び出し箇所をホバーすると、型情報が表示されます。 また、入力の補完時にも型情報が表示されます。 所感 RBS::Trace導入のメリットと可能性 RBS::Traceは、RBSが全くないRailsプロジェクトにとって、型情報導入の最初の一歩として非常に有効だと感じました。テスト実行だけで型情報が自動生成されるため、手動で記載する手間が大幅に省けます。 Inline RBSだけの生成も可能なので、ドキュメント生成ツールとしても活用できそうです。これは人間にとって読みやすいだけでなく、GitHub Copilotなどの生成AIツールにも型情報を提供できるメリットがあります。生成AIがInline RBSから型情報を読み取れば、より正確なコード提案が得られるのではないかと期待しています。 将来的には、 RBS::Inline が RBS 本体に組み込まれる計画もあるようで、Inline RBSだけで型チェックができる日も来るかもしれません。 活用における注意点 型情報の出力結果はテストの実行内容に依存します。例えばStringとnilを返すメソッドがあっても、nilを返すケースのテストがなければ、型情報はStringだけになってしまいます。つまり、RBS::Traceを活用するには、テストの品質確保が前提となります。 また、Railsプロジェクト全体にRBSやSteepを導入した場合、相応のメンテナンス工数がかかると感じました。RBS::Traceだけでは、Rails自体が生成するクラスやメソッドの型情報は提供されないため、 rbs_rails などの併用や、手動での型情報メンテナンスも必要になるでしょう。 RBSのプロジェクトへの導入について 今回の試行から、Findy FreelanceプロジェクトへのRBSやSteep導入を決定したわけではありませんが、これらのツールとエコシステムの現状を実感できました。RBS::Traceのおかげで試すハードルが下がったのは大きな収穫です。開発者の @sinsoku_listy さんには感謝しています。 最後に RubyKaigi 2025では、Rubyの型に関するセッションがいくつかありました。 すべてを聞けてはいませんが、総じてRubyの型に関するエコシステムは今後もまだまだ進化していきそうだと感じました。 正直、私は今までちゃんとキャッチアップができていなかったのですが、RubyKaigiへの参加をきっかけに興味が強くなり、理解を深めるきっかけとなりました。 今後もRBS, Steep, Sorbetなどの型に関するエコシステムの進化をキャッチアップしつつ、プロジェクトに導入するかどうかを検討していきたいと思います。 5/13(火)に、「After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜」として、ピクシブ株式会社、株式会社ZOZO、ファインディ株式会社の3社でRubyKaigi 2025の振り返りを行います。 オンライン・オフラインどちらもありLTやパネルディスカッションなどコンテンツが盛りだくさんなのでぜひご参加ください!! pixiv.connpass.com ファインディでは、一緒にRubyやRailsの開発をしてくれる仲間を募集しています。 興味のある方は、ぜひこちらからチェックしてみてください! herp.careers 参考 RBS::Trace GitHub Automatically generating types by running tests (発表資料) Steep GitHub "型"のあるRailsアプリケーション開発 (発表資料)
こんにちは!ファインディ株式会社でエンジニアをしている みっきー です。 先日開催されたRubyKaigi 2025に参加しました。 去年はLTの登壇があり、準備で忙しかったので、今年はたくさんのRubyistと話したり、セッションを見られることをとても楽しみにしていました!! 今回は特に印象に残った「 On-the-fly Suggestions of Rewriting Method Deprecations 」というセッションについて紹介します。 自己紹介 deprewriter-ruby deprewriter-ruby gemの紹介 動かしてみた 作者のohbaryeさんに聞いてみた 最後に 自己紹介 私はFindy Team+でバックエンドエンジニアとして働いており、普段はRubyを使った開発をしています。 また、プライベートでは「 omochi gem 」というRuby gemを開発・メンテナンスしています。 そのため、今回のRubyKaigi 2025で「On-the-fly Suggestions of Rewriting Method Deprecations」というセッションを見つけたときは、すぐに興味を持ちました。非推奨メソッドの置き換えを自動化できるツールがあれば、ユーザーの移行をスムーズにサポートできると思ったからです。 deprewriter-ruby deprewriter-ruby gemの紹介 「On-the-fly Suggestions of Rewriting Method Deprecations」セッションでは、 ohbarye さんが開発した「 deprewriter-ruby 」というgemが紹介されました。このgemは、非推奨になったメソッドの呼び出しを検出し、新しいメソッドへの置き換え方法を自動的に提案してくれるツールです。 deprewriter-rubyの特徴は次の通りです: 設定ファイルによる柔軟な定義 : YAMLファイルで非推奨メソッドとその代替メソッドのマッピングを定義できます。 インラインの提案 : コードを実行すると、非推奨メソッドが使われている箇所で、代替メソッドへの置き換え方法が提案されます。 自動修正機能 : 提案された変更を自動的に適用することも可能です。 このgemは、Rubyの標準的な警告メカニズムを拡張して、単に「このメソッドは非推奨です」と警告するだけでなく、「このメソッドは非推奨です。代わりにこのように書き換えてください」という具体的な提案をします。 speakerdeck.com 動かしてみた セッション後、早速deprewriter-rubyを試してみました。 まず、次のようにインストールします # Gemfile gem " deprewriter " , github : " ohbarye/deprewriter-ruby " 次に、ライブラリコードで非推奨メソッドとその代替メソッドを定義します # Library code require " deprewriter " class Legacy def old_method (arg) puts " Using deprecated old_method with #{ arg }" end def new_method (arg) puts " Using new_method with #{ arg }" end extend Deprewriter deprewrite :old_method , to : ' new_method({{arguments}}) ' end そして、非推奨メソッドを含むコードを実行すると # User code legacy = Legacy .new legacy.old_method( " example argument " ) 環境変数を設定して実行することで、異なるモードで動作させることができます # ログモード - 非推奨メソッドの警告と提案を表示 $ DEPREWRITER=log ruby your_script.rb # 差分モード - 変更の差分を表示 $ DEPREWRITER=diff ruby your_script.rb # 書き換えモード - 自動的にコードを書き換え(注意して使用してください) $ DEPREWRITER=dangerously_rewrite ruby your_script.rb ログモードでは次のような警告と提案が表示されます $ DEPREWRITER=log bundle exec ruby user_code.rb Calling deprecated method: W, [2025-04-21T19:49:55.132998 #2137] WARN -- : DEPREWRITER: Legacy#old_method usage at user_code.rb:9 is deprecated. You can apply the diff below to resolve the deprecation. --- ./user_code.rb 2025-04-21 19:49:55.123740000 +0900 +++ ./user_code.rb 2025-04-21 19:49:55.123740000 +0900 @@ -6,7 +6,7 @@ # Call the deprecated method puts "Calling deprecated method:" -legacy.old_method("example argument") +legacy.new_method("example argument") # The deprewriter will detect this call and show a warning # suggesting to use new_method instead Using deprecated old_method with example argument 書き換えモードでは次のような警告と変更がおこなわれます。 $ DEPREWRITER=dangerously_rewrite bundle exec ruby user_code.rb Calling deprecated method: W, [2025-04-21T20:11:49.426183 #39447] WARN -- : DEPREWRITER: Dangerously trying to rewrite. It will rewrite a file to apply the deprecation and load the file Calling deprecated method: Using new_method with example argument Using deprecated old_method with example argument $ git diff diff --git a/user_code.rb b/user_code.rb index d1a2a2b..bfcab60 100644 --- a/user_code.rb +++ b/user_code.rb @@ -6,4 +6,4 @@ legacy = Legacy.new # Call the deprecated method puts "Calling deprecated method:" -legacy.old_method("example argument") +legacy.new_method("example argument") 手元の環境で demo を作成し、試してみました。 驚くほど簡単に非推奨メソッドの検出と提案が行われ、ユーザーがコードを更新する手間を大幅に削減できることを実感しました。 作者のohbaryeさんに聞いてみた セッション後、ohbaryeさんに直接話を聞く機会がありました。セッションの内容だけでなく、ツール開発のきっかけや普段の情報収集の方法についても興味深いお話を伺うことができました。 ohbaryeさんは Hacker News を定期的にチェックして、技術トレンドや面白いプロジェクトの情報を集めているそうです。 セッション内で紹介のあったPharoというプログラミング言語もHacker Newsで見かけたそうです。 また、PharoのDeprewriterに触れたきっかけで、deprewriter-rubyを作ったそうです。 「最近は日本語版もあるので、英語が苦手な方にもとっつきやすくなりました」と教えてくれました。さらに、情報収集の効率化について次のようなアドバイスもいただきました。 著名人や有名企業(Shopify、GitHubなど)のブログなど質の高い情報ソースはfeedlyというRSSリーダーを使って集めるようにしています。すべての未読記事を消化するのは大変なので、時間があるときに気になったものだけを読むようにしていますね。 このような効率的な情報収集の方法は、私も取り入れていきたいと思いました。 「必要だから作る」という実践的なアプローチにも共感し、自分のプロジェクトでも同じような姿勢で取り組んでいきたいと感じました。 ohbaryeさんに直接感想を伝えられたことで、オープンソースコミュニティの温かさも実感できた貴重な機会でした! 最後に deprewriter-rubyは、Rubyの非推奨メソッドの置き換えを自動化するという、一見小さな問題に焦点を当てたgemですが、その影響は大きいと感じました。 非推奨メソッドの変更は避けられないものであり、ユーザーの移行をいかにスムーズにサポートするかは、ライブラリ開発者にとって重要な課題です。 day3の Ruby Committers and the World 内で、Matzも後方互換を大切にしている話をしていました。 Matz「基本的にはなにもdeprecateしたくない。提案するのは彼らですが、互換性を壊すと怒られるのは僕なので… deprecateするにはマイグレーションパスを用意して、十分猶予期間を準備してからになるので数年から十年単位の話になる」 #rubykaigi #rubykaigiA — 黒曜@Leaner Technologies (@kokuyouwind) 2025年4月18日 x.com 現在のdeprewriter-rubyには、複雑なメソッド呼び出し(メタプログラミングなど)の書き換えができない、非推奨メソッドが呼び出されるたびに書き換え処理が実行されて効率が悪い、非標準のRubyライブラリに依存しているといった制限があります。 しかし、ohbaryeさんはこれらの課題に対して、より複雑なメソッド呼び出しへの対応、最初の呼び出し後の処理をスキップして最適化する、依存関係を減らしてスタンドアロン化するといった明確な改善計画を持っています。 このような継続的な改善への取り組みを見ると、今後さらに実用的なツールへと進化していくことが楽しみです!! RubyKaigi 2025では他にも多くの興味深いセッションがありました。 Rubyコミュニティの活発な技術共有やライブラリやツール開発の文化に、改めて感謝の気持ちを抱いた3日間でした。 5/13(火)に、 「After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜」 として、ピクシブ株式会社、株式会社ZOZO、ファインディ株式会社の3社でRubyKaigi 2025の振り返りを行います。 オンライン・オフラインどちらもありLTやパネルディスカッションなどコンテンツが盛りだくさんなのでぜひご参加ください!! ファインディでは、一緒に働く仲間を募集しています!! 興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。Findy Tech Blog編集長の高橋(@Taka_bow)です。 この記事は これが私の推しツール!シリーズ の第3弾になります。今回も、 推しツール紹介 と題して、弊社エンジニア達が日々の開発業務で愛用しているツールやOSSを紹介していきます。 トップバッターは奥田さんです! ■ 奥田さん / PdM室 / GenAIイネーブルメント ■ データサイエンティストのだーさん ( @Dakuon_Findy ) です。2025年の1月よりファインディのプロダクトマネジメント室 GenAIイネーブルメントチームにデータサイエンティストとして参画しております。このチームでは、LLMを活用した各種プロダクトの強化や、社内オペレーションの改善に取り組んでいます。 Polars (Pythonライブラリ) Polarsの概要 Polarsは、高速かつ明示的なスキーマ定義を特長とするデータフレームライブラリです。大規模データであってもローカル環境でカラムの型の一貫性を保ったまま効率的に処理できるため、信頼性とスピードを両立したデータ分析が可能になります。 Polarsを使ってる様子 Polarsの推しポイント 処理が速い!型がある!の2点です。この2点がデータ分析における推しポイントとなる理由を以下で詳述します。 1. 処理速度 前職で経験したのですが、pandasで2時間かかっていた処理が、Polarsに書き換えた途端に5分少々で完了し、驚愕しました。処理が速すぎて「処理の間に別のコードをのんびり書こう」が成立せず、自分のタイピング速度が開発のボトルネックになっているような感覚になります。ひりつきますね。 次の図は公式が公開している、Parquet形式データ読み込みを含んだ処理速度のベンチマークです。例えば1つめのクエリ (Q1) ではpandasは25秒、Polarsでは約1.5秒と、約16.7倍の速度が出ており、全体を通じてPolarsの処理速度はpandasの約11倍 (Q6) 〜81倍 (Q5) の速度が出ていることが見て取れます。 Updated PDS-H benchmark results より引用 2. カラムごとに明確な型を持てる Polarsでは、スキーマを用いてカラムごとに明示的な型を定めることができます。たとえば「数値型 ( pl.Int64 )」とスキーマで決めたカラムに文字列が混ざっていると読み込み処理の段階で型エラーになります(もちろん、Object 型を使えば混在も可能ですが、それを明示しない限りはエラーで気づけます)。これは一見「融通が利かない」と思われがちですが、表記揺れに気づけたり、特定の型を前提とした処理を組んでもバグが起こりづらいというメリットがあります。 正常なスキーマでCSVを読み込んだ例 誤ったスキーマでCSVを読み込んだ場合のエラー Polarsがここまで快適なのは、単なる実装の工夫ではなく、そもそもの「設計思想」によるところが大きいと考えられます。 公式ドキュメント でも次のように述べられています: Philosophy The goal of Polars is to provide a lightning fast DataFrame library that: Utilizes all available cores on your machine. Optimizes queries to reduce unneeded work/memory allocations. Handles datasets much larger than your available RAM. A consistent and predictable API. Adheres to a strict schema (data-types should be known before running the query). Polars is written in Rust which gives it C/C++ performance and allows it to fully control performance-critical parts in a query engine. これを見てみると、私の推しポイントはまさにこの設計思想の上に成り立っていることがわかります。 “provide a lightning fast DataFrame library” → 推しポイントの「処理が速い」につながる話です。まさに "lightning" な速度です。 “Strict schema” → 推しポイントの型の話そのものです。明示的な型で処理を行えるという安心感は本当に大きいです。 つまり、「速い・型がある」が推しポイントになるデータフレームライブラリというのはPolarsが最初から目指していたものだった、というわけです。 たとえば長期の時系列データのように、機器の変更などで表記揺れが発生しやすくデータ量も非常に大きいケースでは、Polarsの「型」と「処理速度」の強みが特に活きます。そんな場面に出会ったときにはぜひPolarsのことを思い出してもらえると嬉しいです。 Polarsの設計思想にしっかり踏み込み、自分の手で試したからこその実感が伝わる記事ですね。速度と型、安全と快適さを追い求めるPolars愛が詰まったツール紹介でした! 次は、久木田さんです! ■ 久木田さん / プロダクト開発部 / バックエンド・SRE ■ Freelance開発チームの久木田です。ファインディ入社3年目です。 バックエンド開発からインフラ構築、SRE的業務にも携わっています。 HTTPie HTTPieの概要 HTTPieとはコマンドラインで使えるHTTPクライアントツールです。 curl の代替として使用できるものです。 コマンドが直感的でわかりやすく、レスポンスのJSONは自動的に色付けされて見やすく表示されます。まだβ版ですが、Webアプリやデスクトップアプリも提供されています。 HTTPieを使ってる様子 HTTPieは、レスポンスがJSONであれば自動で整形・色付けしてくれます。 公式サイトのインタラクティブなデモページでCLIコマンドを試すことができるので、ぜひそちらでも試してもらいたいです。 HTTPie CLI: HTTP & API testing client https://httpie.io/cli/run デスクトップアプリも使っており、こちらも使いやすく愛用しています。 デスクトップアプリ版は基本的にはGUIで操作するようになっており、リクエスト履歴の管理などがしやすくAPIテストを効率的にできます。 HTTPieの推しポイント CLIで使う場合 JSON出力の見やすさ 自動整形とシンタックスハイライトでAPIレスポンスの確認がしやすい オプションが簡潔 覚えるオプションが少なく、短く済むので直感的に使える デスクトップアプリの場合 使いやすいUI リクエストの作成や管理が簡単 コード生成機能 作成したリクエストをcurlコマンドやPython (requests)、JavaScript (fetch)など、他の言語やツールのコードに変換してくれる機能が便利 CLIとデスクトップアプリと場合によって使い分けできるので、API開発やテストでJSONデータを頻繁に扱う人に、HTTPクライアントツールとしておすすめです。 AWS Peacock Management Console AWS Peacock Management Consoleの概要 Chromeの拡張機能で、AWSコンソールを使いやすくするためのツールです。 AWSアカウントIDによってAWSコンソールのヘッダーの色を変更してくれます。 また、右上のログインユーザーの情報部分にアカウントのエイリアスも表示してくれます。 AWS Peacock Management Consoleを使ってる様子 拡張機能に追加してもらったあとに、オプションで設定をします。 適用したいアカウントIDを入力し、環境ごとに設定したい色を16進数のカラーコードで指定します。 指定することで次のように色が変わります。 アカウントのエイリアスの表示は自動でしてくれます。 Staging環境 Production環境 AWS Peacock Management Consoleの推しポイント 自分がログインしている環境を間違えない。 プロダクト・環境ごとにAWSの環境が違うのですが、ヘッダーの色分けによって自分が今どのアカウントにいるかを常に把握できます。 複数のAWSアカウントを使っている開発者にはぜひ導入してもらって、事故を減らしてもらえたらと思います。 直感的な操作感と環境ごとの安全設計にこだわったHTTPieとAWS Peacock Management Console。CLIとGUIを使い分けながら、開発の快適さを追求したツール紹介でした! 最後は金丸さんです! ■ 金丸さん / プロダクト開発部 / バックエンド ■ Findy Freelance バックエンド開発の金丸です。 オペレーション改善などのバックオフィス機能開発を中心として、Findy Freelanceのバックエンド開発に携わっております。 Warp Warpの概要 Warpは次の特徴を持つターミナルツールです。 - 強力なコマンド補完 - コマンド単位で入出力を管理するブロック - ショートカット、ペイン分割などのカスタマイズ可能 生成AIと連携したAgentモードも特徴の1つです。 (私自身はまだ使いこなせていません。。。) Warpの推しポイント 推しポイントは2つあります。 サジェストが強力 過去に実施したコマンドの傾向やエラー出力をもとに、次に実施するべきコマンドをサジェストしてくれます。 例: git add -> git commit -> push branch -> open pull request の流れを自動的に補完してくれる 上記のGIFでは git push でエラーが出た際に出力された git push --set-upstream origin hogehoge をサジェストしてくれています。 ブロック機能 Warpはコマンド実行単位でブロックが作成されます。 ブロック機能により、各コマンドに対応する出力結果が明確になり、理解しやすくなるという利点があります。 また、ブロック内の出力だけを選んでコピーしたり、検索したりする操作も簡単に実施できます。 特定コマンドの実行結果をコピーする 出力結果内から該当箇所を検索する なるほど、Warpの補完とブロック機能は確かに嬉しいですね。日々のターミナル操作がぐっと快適になる感じ、良さそうです。使い込むほどに良さがわかるツールですね。 おわりに 今回ご紹介した3名も、それぞれの開発スタイルに合わせてツールを選び抜き、日々の作業を快適にする工夫を重ねていましたね。スピードや操作性、ミスの防止など、それぞれが注目したポイントからはエンジニアとしてのこだわりが垣間見えます。道具選びひとつ取っても、開発生産性と心地よさを追求する姿勢が伝わってきました! ファインディでは、さまざまなバックグラウンドを持つエンジニアが活躍しています。技術にこだわり、より良いものを追求する仲間とともに働いてみませんか? 現在、ファインディでは新しいメンバーを募集中です。 興味のある方は、ぜひこちらからチェックしてみてください!
こんにちは。ファインディでデータサイエンティストをしています、sasanoshouta( @Edyyyyon )です。 今回は、社内向けに提供している「Findy Team+の使い方について、ざっくばらんに質問できる」社内Botを作成した際の取り組みと、そこから得た学びをご紹介します。 どんなBot? Bot作成の背景 社内PdMに舞い込んでくるプロダクトに関する問い合わせに対する業務効率化 Difyを社内用に解放しており、既にいくつかのBotがSlackワークスペースに産み出されていた どのように作成したか 作成した結果どうだったか 今後について 最後に どんなBot? まず、今回作成したBotの概要を、代表的な2つのユースケースを通じてご紹介します。 1つ目の代表的なユースケースとして、Botの名前の通り、 「Team+の使い方」に関する質問 ができます。 ユースケース1では、Team+のDevOps分析画面の使い方についての質問に、Botがどのように回答するかを紹介します。 後述しますが、こちらのBotを作る上で基にした情報はサポートページの内容をコンテキストとしている為、URLを付与して返答する事のできる質問に対しては基本的にURL付きで返答を返してくれます。 ユースケース1: デプロイしたはずのプルリクがDevOps分析に表示されない原因を教えて下さい デプロイしたプルリクがDevOps分析に表示されない場合、以下のような点をご確認いただくと原因を特定しやすくなります。 1. スタッツ管理で設定している正規表現が実際のブランチ名やタグ名に合っていない 例として、「^(main|master|pri)$」のように設定している場合、ブランチ名が「pri/~」などスラッシュを含む形だとマッチせず、デプロイ対象に含まれません。 → 正規表現を見直し、「^(main|master|pri.*)$」など適切な設定に修正いただくと改善されるケースがあります。 2. デプロイ(プルリク作成/タグ付け)を行ったメンバーが対象チームに所属していない、または表示対象OFFになっている → プロダクト画面上で、チームメンバーの設定や表示設定が正しく行われているかどうかご確認ください。 3. モニタリングのラベル設定が適切でない → 特定の文字列を含んだラベルのみを集計対象にしている場合は、ラベル付けのルールを再度ご確認ください。 上記を確認いただいても解決しない場合は、以下のサポートページや社内向けドキュメントURLもあわせてご参照ください。 ■サポートページ ・正規表現を使ったデプロイ頻度の集計例など https://hogehoge ・DevOps分析の概要 https://fugafuga もしご不明点や追加のご質問があれば、遠慮なくお知らせください。 2つ目の代表的なユースケースとして、単純なTeam+の使い方だけでなく 「特定のシチュエーションを想定した時にTeam+をどのように活用すると良いのか?」 と言うようなやや抽象度が高い質問や、壁打ちのような質問にも対応することができます。 ユースケース2: プロダクトオーナー、プロダクトマネージャーの育成観点でどんな活用方法が有効ですか?また重視するといい指標があれば教えてください。 プロジェクトオーナーやプロダクトマネージャーの育成には、以下のようなTeam+活用方法が考えられます。 1. プロジェクト全体を俯瞰できる情報共有 - 各担当メンバーのタスクを整理し、進捗と課題を可視化することで、オーナーおよびマネージャーが的確に優先度を判断しながら学習・意思決定できる環境を整えます。 2. 定量的なデータにもとづく振り返り - スプリント終了時やマイルストーンごとに、タスク消化数・リードタイム・タスク完了率などのデータを確認しながら振り返りを実施することで、チームビルディングの視点を持ちつつ育成が行えます。 3. コラボレーションを通じたスキル学習 - 例えば、生産性向上やユーザーインタビューなど多面的な業務に関わる際、それぞれ詳しいメンバーからレビューやフィードバックをもらえる仕組みを作り、学習機会を増やすことで、オーナーやマネージャーへ幅広いスキルを身につけさせることができます。 重視するとよい指標の例: • タスク完了率・計画対実績の差 • リードタイム(アイデアからリリースまでの期間) • タスクごとの担当メンバーのフィードバック量・質 • プロダクト改善提案数(チームやユーザーからの新たなアイデア) • チームメンバー間のコミュニケーションログやレビューの頻度 これらを定期的にモニタリングし、学習サイクル(学習→実践→振り返り)を短く回すことで、プロジェクトオーナーやプロダクトマネージャーが実践的に成長しやすくなります。 (中略) これらをプロダクトオーナーやプロダクトマネージャーの活動に取り入れることで、顧客への価値提供や開発組織の生産性向上につながりやすくなります。 Bot作成の背景 このBotを作るに至った背景は、以下のような理由からです。 社内PdMに舞い込んでくるプロダクトに関する問い合わせに対する業務効率化 Difyを社内用に解放しており、既にいくつかのBotがSlackワークスペースに産み出されていた 社内PdMに舞い込んでくるプロダクトに関する問い合わせに対する業務効率化 Team+には、日夜プロダクトの進化を支えるPdMが6名在籍しています。Team+はユーザー様に多様な機能を提供している性質上、様々な観点での問い合わせが届きます。 平均すると、1人1日2件程度は問い合わせをいただいており、これに対応する必要があります。 Difyを社内用に解放しており、既にいくつかのBotがSlackワークスペースに産み出されていた カレー屋さんBotをはじめ、ファインディ内では幅広い職種が使うことのできる多様なBotが稼働しています。これらのBotは社内向けにホスティングされたDifyで作成されており、希望者はDify上で色々なテストをすることができるので、気軽にBotを始めとしたツール作成にチャレンジをすることができます。 こうした背景と、今年よりプロダクトマネジメント室に所属するデータサイエンティストが 生成AI活用を推進するミッションを背負うようになった 事もあり、「 勝手にBot作ってみよう。面白いものができそうだよね 」と言うチャレンジから産まれました。 (余談ですが、同じやってみた系の取り組みとして同チームメンバーのだーさん( @Dakuon_Findy )が書いてくれた記事もありますので、是非ご覧になってみてください。) tech.findy.co.jp どのように作成したか 作り方自体は至ってシンプルです。以下の情報をコンテキストにしたBotを、簡単なプロンプトを添えてDify上に作成するだけです。 Team+のサポートページコンテンツ100ページ分 社内に蓄積された問い合わせFAQ100問分 プロンプトも非常にシンプルで、実際にはたった 4行 で構成されています。 あなたはTeam+というプロダクトについて知り尽くしているプロフェッショナルです。 ユーザーからの問い合わせに対して相応しいものをコンテキスト内から回答してください。 コンテキストの情報には、プロダクトのサポートページURLまたは社内ドキュメントのURLが添付されているはずです。 コンテキストの情報を元に回答が行える場合は、参照元のURLをユーザーへ提供してください。 たったこれだけで出来てしまいました。 作成した結果どうだったか Bot作成前、PdMに届いていた問い合わせの件数が新機能に関する問い合わせを除き ほぼゼロ にすることができました。 また、このBotは社内で職種問わず広く使われているのですが、以下のような声を多数いただくことができました。 今後について このように社内でも好評を得られていることから、プロダクトへの実装を進めようと考えています。 実際にプロダクト上への実装を行う為に、コンテキストの強化・Ops構築やハルシネーション対策など、生成AIを活用した機能ならではの考慮すべき点が論点として残っていますので、これらを解消していく予定です。 最後に ファインディでは、データサイエンティストを始めとするデータアナリスト、データエンジニアなどのデータ系職種の採用を強化中です。 こちらの記事を読んでいただき、取り組みに興味を持っていただいた方は是非カジュアル面談でお話しましょう。 herp.careers また、こちらの記事は「 プロダクトマネージャーLT Night 」と言う弊社主催のイベント内でも登壇させていただいた内容になります。 その際の登壇資料も掲載しておきますので、ぜひご覧ください。 speakerdeck.com
こんにちは。 ファインディ株式会社 で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub Copilotやチャットベースの開発支援ツールなど、生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 そのような状況の中で、「プロンプトの書き方がわからない」「プロンプトが思った動作をしてくれない」といった声をよく耳にします。 そこで今回は、生成AIに対するプロンプトの書き方のコツを紹介します。プロンプトの書き方のコツを知るだけで、生成AIの精度は驚くほど向上します。 それでは見ていきましょう! 長い文章よりも、簡潔な階層構造 記述の順序 対象と実行内容を絞る まとめ 参考文献 長い文章よりも、簡潔な階層構造 長文のプロンプトよりも、マークダウン記法などを利用して作成した階層構造のプロンプトの方が、生成AIの理解度が高い傾向にあるようです。 例えば、次のプロンプトを実行するとします。 buttonを作成して返すReact Componentを作ってください。propsにはテキストと無効フラグとクリック時のイベントを受け取ることが出来ます。テキストは必須です。無効フラグは任意で ` is ` のprefixを付けてデフォルト値は無しです。クリック時のイベントは任意です。 このプロンプトの実行結果は次のようになりました。 import React from 'react' ; type ButtonProps = { text : string ; isDisabled ?: boolean ; onClick ?: () => void ; } ; export const ButtonComponent: React.FC < ButtonProps > = ( { text , isDisabled = false , onClick } ) => { return ( < button type = "button" disabled = { isDisabled } onClick = { onClick } > { text } </ button > ); } ; プロンプトの意図が伝わっていない箇所が見られました。 isDisabled にデフォルト値が設定されてしまっています。 今度は、次のようにマークダウン記法の階層構造に書き直して実行してみます。 buttonを作成して返すReact Componentを作ってください。 - props - テキスト - 必須 - 無効フラグ - 任意 - ` is ` のprefixを付ける - デフォルト値は無し - クリック時のイベント - 任意 import React from 'react' ; type ButtonProps = { text : string ; isDisabled ?: boolean ; onClick ?: () => void ; } ; export const ButtonComponent: React.FC < ButtonProps > = ( { text , isDisabled , onClick } ) => { return ( < button type = "button" disabled = { isDisabled } onClick = { onClick } > { text } </ button > ); } ; isDisabled にデフォルト値が設定されなくなりました。この結果から、階層構造で書かれたプロンプトの生成結果の精度が上がることを理解できたかと思います。 このようにプロンプトに長文が書かれていた場合、文章を分解してマークダウン記法などの段落構造などに書き変えることをオススメします。 記述の順序 プロンプトやサンプルコードを記述する順番によって、生成AIが出力する内容が変わるケースがあります。 例えば、次のプロンプトを実行するとします。 次のコードを参考にして、UserSetting用のRepositoryクラスを作ってください ```typescript export interface UserSetting extends Entity { userId: string; notificationTarget: 'email' | 'slack'; } ``` ```typescript export interface IRepository<T> { findById(id: string): Promise<T | null>; } export interface Entity { id: string; createdAt: Date; updatedAt: Date; } ``` ```typescript export interface User extends Entity { name: string; email: string; role: 'admin' | 'user'; } export class UserRepository implements IRepository<User> { private users: User[] = []; async findById(id: string): Promise<User | null> { return this.users.find(user => user.id === id) || null; } async findAll(): Promise<User[]> { return [...this.users]; } async findByEmail(email: string): Promise<User | null> { return this.users.find(user => user.email === email) || null; } async findByRole(role: 'admin' | 'user'): Promise<User[]> { return this.users.filter(user => user.role === role); } } ``` ```typescript export interface Organization extends Entity { name: string; contractStatus: 'active' | 'inactive' | 'pending'; } export class OrganizationRepository implements IRepository<Organization> { private organizations: Organization[] = []; async findById(id: string): Promise<Organization | null> { return this.organizations.find(org => org.id === id) || null; } async isContract?(org: Organization): Promise<boolean> { return org.contractStatus === 'active'; } } ``` 実装内容が多い UserRepository を先に記述して、実装内容が少ない OrganizationRepository を後に記述しています。 このようなプロンプトの場合、先に書いた大きい方の内容が優先され、後に書いた小さい内容が無視されることがあります。 今回のケースだと、後述した OrganizationRepository の isContract? メソッドの例が無視される可能性があります。 実行結果は次のようになりました。 export class UserSettingRepository implements IRepository< UserSetting > { private userSettings : UserSetting [] = [] ; async findById ( id : string ): Promise < UserSetting | null > { return this .userSettings. find ( setting => setting. id === id) || null ; } async findAll (): Promise < UserSetting []> { return [ ... this .userSettings ] ; } async findByUserId ( userId : string ): Promise < UserSetting | null > { return this .userSettings. find ( setting => setting.userId === userId) || null ; } async findByNotificationTarget ( target : 'email' | 'slack' ): Promise < UserSetting []> { return this .userSettings. filter ( setting => setting.notificationTarget === target); } } 生成されたコードは全て this.userSettings に対するもののみで、 UserSetting のデータに対しての関数が生成されていないことがわかります。 次に、実行したプロンプトの OrganizationRepository に対する記述と UserSettingRepository に対する記述を入れ替えて実行してみます。 実行結果は次のようになりました。 export class UserSettingRepository implements IRepository< UserSetting > { private userSettings : UserSetting [] = [] ; async findById ( id : string ): Promise < UserSetting | null > { return this .userSettings. find ( setting => setting. id === id) || null ; } async findAll (): Promise < UserSetting []> { return [ ... this .userSettings ] ; } async findByUserId ( userId : string ): Promise < UserSetting | null > { return this .userSettings. find ( setting => setting.userId === userId) || null ; } async findByNotificationTarget ( target : 'email' | 'slack' ): Promise < UserSetting []> { return this .userSettings. filter ( setting => setting.notificationTarget === target); } async hasActiveNotification ( setting : UserSetting ): Promise < boolean > { return setting.notificationTarget !== null && setting.notificationTarget !== undefined ; } } UserSetting のデータを受け取ってチェックを行う hasActiveNotification が追加されていることがわかります。 この結果から、プロンプトの内容の記述順が生成結果に影響が出ることが理解できるかと思います。 対象と実行内容を絞る 生成AIからの結果の精度が低い場合、一度に多くの対象を選択しているケースがあります。 例えば、次のプロンプトを実行するとします。 次の変更を実行してください ## 変更対象 - 次の条件の全てに合致するファイル全て - ` app/lib/**/*.tsx ` に合致する - ` app/lib/**/*_spec.tsx ` に合致しない ## 変更内容 - ` window.alert ` を ` toast.error ` に変更する - ` toast ` は ` @findy/ui ` からimportする - propsで定義されているboolean型の項目の型定義を ` boolean ` から ` boolean | undefined ` に変更する 対象のファイル全てに対して複数の変更内容を実行するプロンプトになっています。 階層構造になっていますし、対象と内容を具体的に指定しており、特に問題ないように見えます。 しかし、このプロンプトを実行した場合、場合によっては実行結果の精度が落ちる可能性があります。 変更対象となっている app/lib 配下には多くのファイルが含まれている可能性があります。生成AIに対して一度の多くの対象を指定すると、対象を絞り込むことに対してリソースを使ってしまうため結果の精度が落ちてしまう傾向にあります。 このようなケースの場合、合致するフォルダの指定を app/lib/hoge/ 以下を見るようにプロンプトを変更して複数回の実行に分けると良いでしょう。 次の変更を実行してください ## 変更対象 - 次の条件の全てに合致するファイル全て - ` app/lib/hoge/**/*.tsx ` に合致する - ` app/lib/hoge/**/*_spec.tsx ` に合致しない ## 変更内容 - ` window.alert ` を ` toast.error ` に変更する - ` toast ` は ` @findy/ui ` からimportする - propsで定義されているboolean型の項目の型定義を ` boolean ` から ` boolean | undefined ` に変更する 変更対象のフォルダを指定して、一度に対象とするファイルを限定的にしました。このプロンプトを実行後、次は別のフォルダに対して同様のプロンプトを実行することで、生成AIの結果の精度が向上する可能性があります。 これで解決かと思いきや、更に改善の余地が見つかりました。変更内容が複数ある場合、プロンプトを分割して実行すると更に精度が上がります。今回のケースだと処理自体の変更と型定義の変更で異なる変更の指示が含まれています。 こういったケースの場合、プロンプトと実行を分割すると良いです。 次の変更を実行してください ## 変更対象 - 次の条件の全てに合致するファイル全て - ` app/lib/hoge/**/*.tsx ` に合致する - ` app/lib/hoge/**/*_spec.tsx ` に合致しない ## 変更内容 - ` window.alert ` を ` toast.error ` に変更する - ` toast ` は ` @findy/ui ` からimportする 次の変更を実行してください ## 変更対象 - 次の条件の全てに合致するファイル全て - ` app/lib/hoge/**/*.tsx ` に合致する - ` app/lib/hoge/**/*_spec.tsx ` に合致しない ## 変更内容 - propsで定義されているboolean型の項目の型定義を ` boolean ` から ` boolean | undefined ` に変更する 今回のケースのように複数の対象、内容の全てを一度に指定するのではなく、対象を絞って単一の変更内容を指示してプロンプトの実行そのものを分けることで、生成AIの結果の精度が向上する傾向にあります。 まとめ いかがでしたでしょうか? ちょっとした工夫や気遣いでプロンプトの精度が上がることがわかったかと思います。今後もトライアンドエラーを繰り返しながら、生成AIを活用するためのプロンプトの書き方を磨いていきましょう。 カスタムインストラクションでのプロンプトのコツも紹介しているので、是非こちらも参考にしてみてください。 tech.findy.co.jp 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers 参考文献 Best practices for using GitHub Copilot in VS Code
ファインディ株式会社 でフロントエンドのリードをしております新福( @puku0x )です。 弊社では、フロントエンド系のリポジトリの多くに Nx を採用しています。 Nxは、Nx Cloudと連携することでCIの高速化やコストパフォーマンスの改善が期待できます。 直近のアップデートにより、Nx Agents(Nx Cloudが提供するサービスの1つ)の新機能「Assignment rules」が正式リリースされました。 nx.dev これまで解決が難しかったタスク割り当ての最適化が、いよいよ解決できそうです👏 今回はAssignment rulesの解説と、実際に使った場合の効果をご紹介しようと思います。 Nx Agentsとは? DTEの革命「Assignment rules」 Nx Agentsの課題 Assignment rulesの登場 Assignment rulesの効果 まとめ Nx Agentsとは? Nxには、Distribute Task Execution(DTE)というCI高速化の機能があります。 nx.dev DTEでは、ビルドやテストといったタスクを複数のCIマシンで分散実行します。単純なタスク別の並列化と比較して、CIマシンの数を増やした際の高速化の効率が良いという特徴があります。 Nx Agentsの動作イメージ(Nx公式ドキュメントより抜粋) DTEのマネージドサービスが「Nx Agents」であり、ファインディでは昨年Nx Agentsを導入し、CIの高速化に成功しました。 tech.findy.co.jp DTEの革命「Assignment rules」 Nx Agentsの課題 Nx Agentsを用いたDTEでは、CIの負荷に応じて利用するマシンの台数やスペックを動的に切り替えられます。 次の設定は、スペックが中程度のマシン3台を最小構成とし、Nxが検知したCIの負荷(=コードの変更に影響のあるプロジェクトの割合)をもとに、高スペックなマシンを混ぜつつ最大8台でCIを動かす例です。 distribute-on : 00-changeset-s : 3 custom-linux-medium-js 01-changeset-m : 3 custom-linux-medium-js, 2 custom-linux-large-js 02-changeset-l : 4 custom-linux-medium-js, 4 custom-linux-large-js # changesetは任意の数を定義できます # マシンスペックは https://nx.dev/pricing#resource-classes 参照 この機能はCIの高速化に役立つ一方、課題もありました。 コア数の多いCPUを活用できない (Nxの --parallel オプションはCI全体に適用されてしまう) 負荷の高いタスクがスペックの低いマシンで実行されるのを防げない 後者は特にメモリ不足によるエラーを発生させやすく、CIの再実行にかかる時間やコスト・開発者体験の低下が問題となっていました。 Assignment rulesの登場 そんな時に現れたのが「Assignment rules」です。 nx.dev この機能により、メモリ不足の最大の要因であった「負荷の高いタスク」をスペックの高いマシンに割り当てるといったことが可能になりました。 また、タスク単位で parallelism を設定することで、マシン内の最大タスク並列実行数を調整でき、コア数の多いCPUを有効活用できます。 設定の例をお見せします。 assignment-rules : - projects : - app1 # アプリケーション用のタスクを想定 targets : - build* # build や build-storybook が該当 - typecheck run-on : - agent : custom-linux-medium-js parallelism : 1 # メモリが足りなくなるため並列実行させない - agent : custom-linux-large-js parallelism : 3 # 高スペックなマシンの場合は並列実行させる - targets : - build - test - typecheck run-on : - agent : custom-linux-medium-js parallelism : 2 - agent : custom-linux-large-js parallelism : 4 - targets : - cspell - lint - stylelint run-on : - agent : custom-linux-medium-js parallelism : 6 - agent : custom-linux-large-js parallelism : 8 Assignment rulesの効果 比較対象として、4コアマシン×8台の場合を設定します。 参考: Nx Agentsを導入してフロントエンドのCIを約40%高速化しました - Findy Tech Blog Assignment rulesによってCI時間やコストがどれほど変化したかを見てみましょう。 次の表は、キャッシュヒット無しで全てのタスクが実行された場合のCI時間および想定されるCIのコストを表しています。 Before After(Assignment rules有効) CI時間 10m 31s 10m 54s コスト $0.968 $0.726 CI時間はそれほど変わらず25%ほど安くなりました。 マシンスペックを抑えた場合のメモリ不足を心配する必要が無くなったのも嬉しいところです。 まとめ Assignment rulesにより、Nx Agentsを用いたCIはさらに最適化されます。 個人的に parallelism での並列数設定は待望の機能でした。 (あとは各タスクの優先度を設定できたら最高なのですがNrwlの皆さんいかがですか...!?) CIの高速化・安定化は、チームのパフォーマンスを考える上で重要になります。Nxの機能の活用により、強固な開発の仕組みを構築できるでしょう。 今後もNxに目が離せませんね👍 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。ファインディでソフトウェアエンジニアをしている栁沢( @nipe0324a )です。 ファインディでは、25年1月末から転職開発チームにDevinがジョインし、現在2ヶ月ほど一緒に働いています。 Devinのアウトプットとして、プルリクエストのマージ数は「 2ヶ月で197件 」、「 1日あたり平均5.2件 」とバリバリ開発をしてもらっています。 過去2ヶ月のDevinのマージ済みプルリク数の推移 Devinの2ヶ月の費用としても約30万($2,000 = 1,000 ACUs)ほどで、比較的簡易なタスクかつ一部サポートは必要でしたが十分なアウトプットを得ることができました。 今回の記事では、Devinに効果的にアウトプットを出してもらうために 試して上手くいったところ 上手くいかなかったところ 具体的なTips などをご紹介できればと思います。 ちなみに、 ファインディ内でのDevinの利用状況は現在検証中の段階であり、まだ「開発生産性が劇的にあがりました!」といえる状況ではありません。 Devinの1つの利用事例として楽しんでいただければ嬉しいです。 Devinはどこまでできる? 試行錯誤しつつDevinで上手くいったこと 基本的な開発ルールやプロセスに慣れてもらう 開発中に見つけた軽微なタスクを任せる 軽微なアラート対応やWant対応を任せる 小規模な開発を任せていく ここが辛いよDevin 自分でやったほうが早くない? GitHub CopilotやClineなどのほうが精度良くない? レビューに反応して余計な対応をしてしまう Devinと今後どう付き合っていくか? 最後に Devinはどこまでできる? Devinを2ヶ月試した結果として、「 ジュニアからミドルレベルのタスクを概ね任せられそう 」という感触を得ています。 難易度が易しい〜普通ぐらいのタスクにおいて、要件把握・設計から動作確認までできるポテンシャルを感じています。 現段階でのDevinに任せられるタスク難易度と業務範囲のポテンシャル しかし、Devinの開発結果に対する品質担保は人の手で行う必要があるため、業務範囲を全部任せるということはまだできません。 そのため、「生産性が大幅にあがりました!」というにはもう少し時間がかかると思っています。 生成AI界隈の動きは激しく、今後のDevinの精度向上やスピードアップのネタは尽きないので、楽しみに待ちながらDevinと引き続き働いていきたいです。 Devinの継続的なバージョンアップ(現時点では1.3) LLMの応答速度や性能向上(最近だとClaude 3.7 など) 拡散モデルなどによるコード生成の大幅な高速化 マルチエージェントの高度化 などなど 試行錯誤しつつDevinで上手くいったこと 小さなタスクから依頼して試行錯誤しながら、Devinがチームに少しずつ慣れていけるように進めていきました。 基本的な開発ルールやプロセスに慣れてもらう Devinの開発環境は、次のようになっています。 左側に「Devinと人がやりとりするチャット欄」、右側に「エディタ」、「ターミナル」、「ブラウザ」、「プランナー」があります。 Devinの開発環境 また、Devinへのタスク依頼は、「DevinのWeb画面」、「Slackメンション」、「VS Code」、「API」から実施できます。 チームにJOINしたばかりのDevinはチームの開発ルールを知らないので、まずはチームの開発ルールやプロセスに慣れてもらうことから始めました。 具体的には、システム概要、リンターや自動テストの実行方法、コミットメッセージやプルリクの書き方など覚えていく必要があります。 そのため、文言変更や軽微な改修を通して、開発ルールを教えていきました。 Devinは作業のやり取りを通してKnowledgeという形でルールを学んでいきます。 Knowledgeは特定の条件のときに参照されるプロンプトで、Knowledgeとして学んだルールを次の開発で活かしていくことができます。 次のようにKnowledgeとして「コミット作成」「PR作成」「テスト実行」といったチームのルールにそった開発ができるようになりました。(たまに無視することもありますが...) 実際に学んだDevinのKnowledgeの一部抜粋 開発中に見つけた軽微なタスクを任せる コードを読んでいるときや実装中に「不要な処理を見つけたから消したい」、「この処理をリファクタしたい」となることはないでしょうか? VSCodeのDevinプラグイン( https://github.com/CognitionAI/devin-extension )を使うことでこういった軽微な修正をスムーズに対応できます。 プラグインを使うことで、後でやろうから「 Devinに依頼 → PRをレビュー → DONE!! 」というスムーズな流れに変わります。 VSCodeプラグインでDevinに軽微なタスクを依頼 軽微なアラート対応やWant対応を任せる 「Mustじゃないけどこのタスクもやりたいよね」、「アラートが気になっているけど忙しいから手がつけられない」といった話はよくあります。 そういったときに、Devinに任せることで、効果的に対応できます。 いろいろ試した結果として、軽微なものであれば、 7~8割の精度でイシュー作成〜対応という一連の作業を任せること ができました。 Devinにタスクを任せる際の工夫として、過去のプルリクを参考にさせることで、Devinがよりスムーズにタスクを理解し、実行できるようにしています。 例えば、次のようなタスクは概ねDevinに任せることができました。 管理画面のフィルター追加・ラベル付与・簡易なバリデーション追加 Sentryで通知がきたN+1の調査と対応方針検討・対応実施 命名ルールの統一 ログ出力フォーマットの横展開 Rubocopの対応 などなど 最近では、技術系の改善イシューは私が書くよりDevinに書いてもらったほうがよいとさえ思っています。 具体例として、Devinに次のようなイシュー作成の依頼をしました。 @Devin AAA, BBB などで XXX に設定するフィールドの名前が yyy になっているのを zzz にしてください イシューテンプレを参考にして、よしなに記載してください すると、コードを調べて数分後にはGitHubイシューを作ってくれました。 「概要」、「現状の問題点」、「期待される効果」が簡潔に記載されていて素晴らしいと思いました。もちろん、ちょっと気になる部分は調査したり、手直しをすることもあります。 Devinが作成したイシュー(一部マスクしています) 小規模な開発を任せていく 試行錯誤中ですが、私が持っている小規模なタスクにおいては、 フロントエンド、バックエンド問わず基本的にDevinに開発をリードしてもらっています。 イメージとしては、watanyさんのスライド内の「コーディングにおける"自動運転"のレベル」におけるレベル3の段階です。(とてもわかりやすかったので勝手ながら引用させていただきました) 具体的には次のような流れでDevinと開発を進めています。 1️⃣ Devinがイシューから対応範囲やタスク洗い出しをして、イシューにコメントをする 2️⃣ 私がイシューのコメントを見ながらヌケモレがないか確認して、Devinが実行しやすいようにTODOリストを整理する 3️⃣ TODOリストのアイテムごとに1つずつDevinに任せる 直列で実施する必要がある場合は、作業するbaseブランチを伝えながら作業を進めてもらう 並列で実施できる場合は、アイテム単位で依頼することで、5並列ぐらいでDevinに開発を進めてもらう 4️⃣ DevinがPRを作成したら、私がコードレビューや動作確認などで品質チェックをして、他の開発者にレビューを依頼する このような流れでDevinと開発を並走しています。 現状のDevinのタスク精度は50~100点とわりとブレがあります。そのため、レビューコメントでDevinに修正をしてもらったり、作業を引き継いで残りの開発や修正をするということもよくあるため、まだまだ試行錯誤な段階です。 ここが辛いよDevin ここまででDevinと一緒に働きながら上手くいったところをご紹介しましたが、使っている中でまだまだこれからかなという部分にもふれていきます。 自分でやったほうが早くない? シニアな方からよく聞きますが、Devinに任せるよりも自分でやったほうが早いので、自分でやってしまうことはよくあります。 次のグラフのように、Devinもスピードは早くなっているのですが、現時点では簡単なタスクでも5~10分ぐらいはかかっている印象です。 devin is now ~2.1x faster – and keeps getting faster every day. every night for the last 5 months, we ran devin on the same set of SWE tasks (a private set of tasks inspired by customer use cases). we've shipped a lot since and devin got 10-40% faster every month pic.twitter.com/CGxeXbTo7g — Silas Alberti (@silasalberti) 2025年2月27日 また、精度のブレの問題もあります。100点のPRを作るときもあれば、概ねいいんだけどちょっと気になるなという70~80点ぐらいのPRもあったり、全然だめじゃんという30点ぐらいのPRもあります。 この精度のブレがあるなら、「自分でやったほうがトータル早くない?」という考えになることはとてもわかります。 GitHub CopilotやClineなどのほうが精度良くない? 弊社の多くのエンジニアは、活用度は人それぞれですがGitHub CopilotやClineなどのAIアシスタントやAIエージェントを利用しながら開発をしています。 Devinに頼むよりも、Copilot Editsで編集するほうが精度の高い結果になることもあります。また、ローカルで動作するため、その後のプロンプトのやりとりやコードの修正もしやすいです。 やりとりの手間やコストを考えると、CopilotやClineなどを使ってローカルで開発するほうが良いと考えることもとてもわかります。 レビューに反応して余計な対応をしてしまう Devinは自律型AIエンジニアということもあり、Devinが作成したPRに対してコメントをすると、コメントの対応をしてくれます。また、CI結果をチェックしてCIを通るように対応をします。 Devinがコメントに反応すると👀がつき、対応すると🎉 便利な機能ではありますが、Devinが作成したPRでは、デフォルトでレビューコメントへの反応が有効になっています。 「(aside)」をつけたコメントをするとDevinは反応しないのですが、よく間違えて「(aside)」をつけ忘れることで、レビュー時に不要な対応をされることもたまにあります。 Devinと今後どう付き合っていくか? GitHub Copilot や Clineなどと併用しつつ、引き続きDevinを試していく予定です。 生成AI界隈は動きが早いので、今後どのプレイヤーが登場しどのように進化していくのかわかりません。そのため、Devinを試しつつ、他のAIエージェントやAIアシスタントとも併用しながら、開発生産性を高めていきたいと考えています。 また、個人的には、既存の仕組みを効率化するにとどまらず、 AIエージェントと人が協業することで良い意味で開発体験をリビルドしていきたい と考えています。 その結果として、一人のエンジニアがより大きな価値をだせるようになると、いろいろ面白くなってくると思っています。 現に0->1の世界では、生成AIやSaaSサービスをフル活用した開発スタイルで、今までよりも質の高いMVPをどんどん作って検証しているという話もちらほら聞き始めています。 最後に ファインディでは生成AIやAIエージェントを前向きに試して開発生産性を高めることで、ユーザーにより価値を届けることを推進しています。 こうした新しい技術の利活用に興味がある方は、ぜひカジュアル面談にお越しくださいませ。 herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。 GitHub Copilotやチャットベースの開発支援ツールなど、生成AIを活用した開発支援ツールが次々と登場し、開発者の日常的なワークフローに組み込まれつつあります。 しかし、これらのツールを導入すれば即座に開発生産性が向上する、というわけではありません。 生成AIを効果的に活用し、真の意味で開発生産性を向上させるためには、適切な準備と理解が不可欠です。 今回は生成AIと既存コードの関係性を掘り下げ、開発生産性を最大化するための具体的な準備について詳しく解説します。 単なるツールとしての導入にとどまらず、組織全体で生成AIと協調して働くための基盤づくりに焦点を当てています。 それでは見ていきましょう! 生成AI活用のための準備 既存コードの最適化 不要なコードの削除 統一されたコーディング規約 コードの設計の一意性 ドキュメンテーションの充実 docコメントやAPIドキュメント カスタムインストラクション プロンプトを記録 継続的な改善を可能にする開発文化 テストコードとCI/CDの整備 Pull requestの粒度 まとめ 参考文献 生成AI活用のための準備 生成AIの効果は既存のコードベースの品質と密接に関連していると言われています。( 1、 2) 生成AIは与えられたコンテキストを基に学習して提案を行います。既存のコードベースが高品質である場合、生成AIはより精度が高い提案をすることができるはずです。 そのため、生成AIを効果的に活用し、真の意味で開発生産性を向上させるためには、適切な準備が不可欠です。 既存コードの最適化 不要なコードの削除 不要なコードが残っていると、生成AIはそれらのコードも学習してしまい、不適切な提案をする可能性があります。 例として次のような実装コードがあるとします。 export const getNotEmptyStrList = ( data : string []): string [] => { const result = [] ; for ( let i = 0 ; i < data. length; i++) { if (data[i]. length > 0 ) { result. push (data[i].trim()); } } return result; } ; export const filterStrList = ( data : string []): string [] => { return data. filter (( item ) => item. length > 0 ). map (( item ) => item. trim ()); } ; 気付いた読者の方もいると思いますが、この例は関数名と実装コードが違うだけで、やっていることは同じです。 getNotEmptyStrList の方は冗長なコードとなっています。 このコードの状態で次のようなプロンプトを実行したとします。 このコードを参考にして、数値配列から0より大きい値だけを抽出して、その値を2倍にする関数を作成してください。 このプロンプトを複数回実行すると、生成されるコードにバラツキが出てしまいました。 export const filterAndDoubleNumbers = ( data : number []): number [] => { const result = [] ; for ( let i = 0 ; i < data. length; i++) { if (data[i] > 0 ) { result. push (data[i] * 2 ); } } return result; } ; export const filterAndDoubleNumList = ( data : number []): number [] => { return data. filter (( item ) => item > 0 ). map (( item ) => item * 2 ); } ; このように、不要なコードが残っていると生成AIからの提案の精度が低下してしまいます。 このようなケースの場合、不要なコードを削除して既存コードを最適化することで、生成AIの理解度を向上させることができます。 実装コードから不要なコードを削除して次のように変更します。 export const filterStrList = ( data : string []): string [] => { return data. filter (( item ) => item. length > 0 ). map (( item ) => item. trim ()); } ; filterとmapを使ったモダンなコードのみに変更しました。この状態で同じプロンプトを複数回実行すると、生成されるコードが一貫性を持つようになります。 export const filterAndDoubleNumList = ( data : number []): number [] => { return data. filter (( item ) => item > 0 ). map (( item ) => item * 2 ); } ; 統一されたコーディング規約 Google の Style Guides のようなスタイルガイドを採用し、統一されたコーディング規約に従ったコードベースは、生成AIの理解度を向上させます。 例えば、命名規則が一貫していれば、生成AIはその規則を学習し、同様の命名パターンを提案できます。 例として次のような実装コードがあるとします。 import { useState } from 'react' ; type SelectOption = { label : string ; value : number ; } ; export const useTestHooks = () => { const [ select_option , setSelectOption ] = useState< SelectOption >(); const [ submitValue , setSubmitValue ] = useState< number >(); const handleSelectOption = ( option : SelectOption ) => { setSelectOption(option); } ; const HandleClickSubmitButton = () => { if (!select_option) return ; setSubmitValue(select_option.value); } ; return { handleSelectOption , HandleClickSubmitButton , } as const ; } ; 各種名称にキャメルケースとスネークケースなどが混在してしまっています。 このコードの状態で次のようなプロンプトを実行するとします。 select_option.valueを3倍にしてsubmitValueにsetするハンドラー関数を追加してください プロンプトを複数回実行すると、実行されるたびに生成されるコードにバラツキが出てしまいました。 const HandleClickTripleSubmitButton = () => { if (!select_option) return ; setSubmitValue(select_option.value * 3 ); } ; const handleClickTripleSubmitButton = () => { if (!select_option) return ; setSubmitValue(select_option.value * 3 ); } ; そこで、命名規約をキャメルケースに統一するように変更します。 import { useState } from 'react' ; type SelectOption = { label : string ; value : number ; } ; export const useTestHooks = () => { const [ selectOption , setSelectOption ] = useState< SelectOption >(); const [ submitValue , setSubmitValue ] = useState< number >(); const handleSelectOption = ( option : SelectOption ) => { setSelectOption(option); } ; const handleClickSubmitButton = () => { if (!selectOption) return ; setSubmitValue(selectOption.value); } ; return { handleSelectOption , handleClickSubmitButton , } as const ; } ; この状態で同じプロンプトを複数回実行すると、生成されるコードが一貫性を持つようになります。 const handleClickTripleSubmitButton = () => { if (!selectOption) return ; setSubmitValue(selectOption.value * 3 ); } ; 単純な例ですが、既存コードに統一性がない場合、生成AIがどの情報を正とするかが曖昧になり、提案の精度が低下してしまう一例でした。 このように、コーディングスタイルの一貫性は生成AIの提案の精度や一貫性に大きく影響します。 コードの設計の一意性 アーキテクチャやデザインパターンが一貫している場合、生成AIはそのパターンを学習し、より適切な提案をすることができます。 例えば、次のようなコードがあるとします。 export interface IRepository < T > { findAll (): Promise < T []> ; findById ( id : string ): Promise < T | null > ; } export interface Entity { id : string ; createdAt : Date ; updatedAt : Date ; } export interface User extends Entity { name : string ; email : string ; role : 'admin' | 'user' ; } export class UserRepository implements IRepository< User > { private users : User [] = [] ; async findAll (): Promise < User []> { return [ ... this .users ] ; } async findById ( id : string ): Promise < User | null > { return this .users. find ( user => user. id === id) || null ; } } interfaceとclassを使ってリポジトリパターンを実装しています。このコードが存在する状態で、次のようなコードを追加します。 export interface Order extends Entity { userId : string ; products : Array < { productId : string ; quantity : number ; } > ; totalAmount : number ; status : 'pending' | 'completed' | 'cancelled' ; } そして、追加したinterface用のRepositoryクラスを生成してもらうためにプロンプトを実行します。 Order用のRepositoryクラスを生成してください すると、生成されたコードは次のようになります。 export class OrderRepository implements IRepository< Order > { private orders : Order [] = [] ; async findAll (): Promise < Order []> { return [ ... this .orders ] ; } async findById ( id : string ): Promise < Order | null > { return this .orders. find ( order => order. id === id) || null ; } } 既存コードの UserRepository を参考にして、 OrderRepository が生成されたことがわかると思います。 このようにデザインパターンや型定義などが一貫していると、生成AIはそのパターンを学習し、より精度の高いコード生成できます。 ドキュメンテーションの充実 生成AIが読み込む内容は実装コードだけでなく、READMEなどのドキュメントも含まれます。そのため、ドキュメントの充実は生成AIの学習に少なからず影響します。 生成AI時代のドキュメンテーション能力は、更に求められるようになってくるでしょう。 docコメントやAPIドキュメント 関数やクラスに記載されるdocコメントは、生成AIがコードの意図を理解する上で重要な情報源となります。 docコメントは実装コードを読み込んで生成AIが自動生成することも可能ですが、実装コードの内容によっては必ずしも十分な情報を提供できない場合があります。このようなケースの場合、まずdocコメントを生成AIに自動生成してもらい、意図や仕様を補足することで、生成AIの理解度を向上させることができます。 また、REST APIの仕様を記述したSwagger/OpenAPIドキュメントやGraphQLのスキーマ定義などは、生成AIがAPIの仕様やクエリを理解する上で重要な情報源となります。 生成AIがAPIの仕様を理解することでモックデータの自動生成などが容易になり、開発効率を向上させることができます。 カスタムインストラクション 生成AI向けのカスタムインストラクションを調整するのも良いでしょう。 カスタムインストラクションは生成AIに対して、特定のコンテキストやルールを教えるための手段です。これを調整して育てることで、生成されるコードや提案内容の精度を向上させることができます。 プロジェクトやリポジトリのコーディング規約やドメイン知識などをカスタムインストラクションに記載しておくことで、それらの内容を生成AIに読み込ませ、提案内容に反映できます。 カスタムインストラクションについては別の記事でも紹介していますので、是非参考にしてみてください。 tech.findy.co.jp tech.findy.co.jp プロンプトを記録 実際に利用したプロンプトを記録して残しておくことも重要です。コード内のコメントや各種ドキュメント、Pull requestなどに記載しておくとよいでしょう。 実際に求めている変更内容とプロンプトの内容が一致しているのかをレビューする必要があるからです。 また、そのコードがどんなプロンプトを利用して生成されたのかが残っていなかった場合、機能追加や修正時にまた一からプロンプトを作らないといけなくなってしまいます。 実装コードを変更したいならプロンプトを変更する。といったパラダイムシフトが来るのはそう遠くない未来なのかもしれません。 最近だと自分は、プロンプトのテンプレートもドキュメントに残すようにしています。状況と変更内容が近いのであれば、プロンプトをコピーして調整して実行するだけで、同じような作業を横展開することが簡単になるからです。 継続的な改善を可能にする開発文化 ここまで説明した内容を実践して維持するためには、継続的な改善や技術的負債の解消を可能にする開発文化が不可欠です。 なぜならば、ドキュメントの整備や既存コードの最適化などは一度だけで終わるものではなく、継続的な取り組みが必要だからです。 テストコードとCI/CDの整備 このような開発文化を作る上でテストコードの整備は特に重要な要素と言えます。一定以上のテストコードが存在することで、継続的な変更に対する心理的安全性を確保できます。 またCI/CDを整備し、自動化されたビルド、テスト、デプロイを行うことで、開発プロセスを効率化し、品質を維持できます。 テストコードとCI/CDの整備については別の記事でも紹介していますので、是非参考にしてみてください。 tech.findy.co.jp Pull requestの粒度 適切な粒度のPull requestを維持することも重要です。Pull requestの粒度が適切であれば、生成AIに対して「これを実現させるためにはこの修正が必要」とピンポイントで学習させることができます。 tech.findy.co.jp Pull requestの粒度はプロンプトの精度にも繋がってきます。 生成AIで実行するプロンプトは可能な限り単一責務の方が実行結果の精度が高い傾向にあります。1行のプロンプトで全ての内容を実行するのではなく、プロンプトを分解して階層構造にしたり、対話形式で実行することで、より精度の高い実行結果を実現できます。(*3) 日頃からタスク分解やPull requestの粒度を意識した開発文化にすることで、プロンプトを作成する際にも応用できるのです。 tech.findy.co.jp これらの準備ステップを着実に実行することで、生成AIをより効果的に活用するための基盤を整えることができます。 まとめ いかがでしたでしょうか? 生成AI活用のための準備ステップは、単なる事前作業ではなく、生成AIの効果を最大化するための基盤づくりです。 生成AIの活用は目的ではなく、より良いソフトウェアをより効率的に開発するための手段です。 堅固な開発基盤と文化こそが、生成AIの真の力を引き出す鍵となります。 小さな一歩から、大きな変革が始まります。技術の進化に伴い、私たち開発者の役割も進化していきます。 この変化を恐れるのではなく、積極的に受け入れ、活用していくことで、私たちはソフトウェア開発の新たな時代を切り開いていこうと考えています。その未来に向けて、今日から準備を始めましょう。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers 参考文献 Best practices for using GitHub Copilot in VS Code #Provide context to Copilot Copilot works best when it has sufficient context to know what you're doing and what you want help with. Best practices for using GitHub Copilot in VS Code #Be consistent and keep the quality bar high Copilot is going to latch on to your code to generate suggestions that follow the existing pattern, so the adage "garbage in, garbage out" applies. Best practices for using GitHub Copilot in VS Code #Be specific and keep it simple When you ask Copilot to do something, be specific in your ask and break down a large task into separate, smaller tasks.
こんにちは。Findy Tech Blog編集長の高橋(@Taka_bow)です。 この記事は 自慢の作業環境を大公開シリーズ の第6弾になります。今回も、3名のエンジニアの作業環境を紹介します! トップバッターは安達さんです! ■ 安達さん / プロダクト開発部 / SRE ■ みなさんこんにちは。SREチームの安達( @adachin0817 )です。 僕は週2出社とリモートワークでハイブリッドな働き方をしていますが、エンジニアガジェッターでもあります。それでは作業環境を紹介していきたいと思います。 デスク周り全体 マシン 個人 Mac mini(M2 Pro) Mac mini(Intel i7) MacBook Air(M1) iPad iPad mini 会社 MacBook Pro(M3 Max) 機材構成は上記のようになっています。なぜ個人でMacBook AirもあるのにMac miniも持っているの?とよく質問されますが、Appleオタクという理由だけではありません。ラップトップのバッテリーは数年で劣化してしまうため、交換時にコストがかかってしまいます。また、MacBook Proはコストも高いので、コストパフォーマンスが良いMac miniをメインとして利用しており、外で開発する場合はMacBook Airを利用しております。Intel Mac miniの利用用途としては、BootCampでWindows 11が動作するようにしています。仕事柄SREといったことから、環境依存が発生しないように個人の開発環境周りの検証を日々行っています。 デスク/ディスクシェルフ 最近、デスク周りを改善し、 COFO Desk Premium を購入しました。椅子も COFO Chair Premium でCOFOに統一をしています。昇降デスクは裏面が全てマグネットになっているため、配線をきれいに仕上げられるのと、 COFOマグネット用オリジナルアイテム も販売されています。モニター台である Fengeのデスクシェルフ を置くことで、見えない配線を隠すことができます。 ディスプレイ ディスプレイは BenQウルトラワイドモニター38インチ/EW3880R を利用しています。BenQといえば台湾を拠点とする電気製品メーカーですが、ディスプレイの鮮やかさはダントツだと思います。また、このディスプレイはtreVoloスピーカーが内蔵されており、高音質と迫力ある低音で、ゲームや映画にも最適です。 また、 モバイルディスプレイ/kksmart 16インチ(WQHD) も活用しています。このディスプレイにはSlackやChatGPTを表示させて素早く返信や検索ができる環境を構築しました。以前はワイドモニターのみで作業していましたが、コマンドタブでの頻繁な切り替えに煩わしさを感じていました。結果として、低価格な小型ディスプレイの導入により生産性向上を実感できています。 このように素晴らしい理想のデスク環境が整いましたが、次はこだわっているアイテムの紹介をしていきましょう。 キーボード/トラックボール キーボードは HHKB Studio でトラックボールは Kensington を利用しています。トラックボールはマウスと違って、手首が痛くならず、手全体で操作できるので、非常に便利です。キーボードの前に謎のスイッチングが見えていると思いますが、こちらについて解説していきたいと思います。 こだわりのアイテム紹介 自作充電マジェットスタンド iPhoneの充電を整えるにあたり、色々と考慮する必要がありました。元々は RORRY ワイヤレス充電器 を利用していましたが、スマホ、Apple Watch、イヤフォンと1つに充電ができるものの、アイテムが大きすぎるといったデメリットがありました。また、Magsafeで充電すると、取り外す際に必ず両手を使わなければならないのも不便でした。 こうした教訓から、リスペクトしている YouTuberツヨシ さんの動画を参考にして、デスクシェルフの裏に ステンレスカット版 を両面テープで固定し、 マジェットスタンド の上に THREEKEY Qi2 充電器 を磁石で貼り付けています。この自作マジェットスタンドにより、充電中のiPhoneを片手で簡単に取り外せるようになりました。 同じ仕組みを応用し、モバイルディスプレイもマジェットスタンドでデスクシェルフに取り付けているので、角度調整が非常に便利になりました。 分配器について このスイッチングは個人PCと会社PCを瞬時に切り替える 分配器 です。以前まで、会社PCを切り替える場合、毎回HDMIやUSB-Cを抜き差ししていましたが、この分配器があることで、簡単に行き来できるようになりました。 リモートワークでの工夫 リモートワークを快適にするには、昇降デスクは欠かせません。自分は午後になると集中力の低下を感じるため、スタンディングデスクを活用し、MTGやペアプロをより楽しくこなせるようにしています。(ちなみにスタンディングしていると愛犬がデスク下で眠りにつきます) また、基本的なことですが、「仕事したい」と思えるデスク環境を整えることが何より重要です。自分はガジェット好きなので、日々改善点を探しながら環境をアップデートするのも、リモートワークの楽しみのひとつになっています。 今後導入したいもの 購入しつくした、と言っても過言ではないですが、しいてあげるならiPadのアームです。それ以外は妻もリモートワークをしているため、昇降デスクを購入しようか検討しております。機会があれば個人ブログでも紹介したいと思います。 デスク環境はかなり費用がかかってしまいましたが、以上が僕の作業環境となります。もっとアイテムを紹介したいですが、長くなってしまうので、個人的に色々と聞きたい!という方にはぜひ、ファインディのイベントやXでのDM等お待ちしております!ありがとうございました! 安達さんは、Mac miniを活用し、コストパフォーマンスと環境依存を考慮した構成が印象的でした。また、自作の充電スタンドや分配器の導入による快適な環境構築が参考になりますね! では、次は土屋さん行ってみましょう! ■ 土屋さん / CTO室 / データエンジニア ■ データエンジニアの 土屋 (しゅんそく) です。私の所属するデータソリューションチームはFindyのデータ基盤の設計、開発、運用を担当しています。 所属チームにあわせて、週2-3日のペースで出社しています。土日は家で作業していることが多いため、作業環境は私の最も大きな関心事の1つです。 デスク周り全体 机は作業スペースが広く、昇降機能が付いている Flexispot E7 Pro を利用しています。天板はカーブ型にしています。手の届く範囲が増えるのでお勧めです。 デスクのモニターの高さを調節可能にしています。自分の目線とモニターの良く見る位置が同じ高さになっていてほしいので高さ調整ができるアームにしています。 モニター JAPAN NEXT WUXGA のモニターがお気に入りです。特徴は縦横比です。 コードを読むときにそれなりの高さがほしいですが、単純にサイズを大きくすると横が長くなり首を振る必要がでてきます。このモニターは24インチ、解像度1980x1200と縦長でコードが読みやすいです。 キーボード Mistel Barocco MD600 Alpha RGB BT Black(英語配列) を利用しています。キーボードは一日触るので体に負担の掛けないことを意識して選んでいます。肩を痛めない左右分離型でタッチが軽めのキーボードを探していたところ、Mistel Baroccoに行き着きました。 キートップは趣味の麻雀仕様にしています。Vimを使っているのでhjklが東南西北です。ただ、jに突起がついていないため若干使いにくいです。 マウス Kensington ケンジントン Slimblade Pro を利用しています。通常のトラックボールマウスとは異なり、指への負担を軽減する特徴を持っています。ブラウザなどの戻るボタンは右前に配置されており、この位置は非常に使いやすく感じられます。 こだわりのアイテム紹介 iPad Air iPad Air 。ほぼ GoodNotes と Kindle , ラムダノート で利用しています。 GoodNotesはメモアプリで、メモや頭の整理として紙に書く感覚でノートを書けます。 (※ 画像は業務と無関係です) エンジニアは油断すると物理本により家が埋もれます。KindleやLambda Noteを通じた電子書籍購入のおかげで床抜けの心配から開放されました。ただ、積読が増えてしまうのが難点といえます。 リモートワークでの工夫 家具、色彩 家の中で作業することが多いので、自分の趣味にあったものにこだわっています。具体的にはカフェやホテルのような見た目が好みなので、書斎は木製の素材と観葉植物をふんだんに利用しています。 作業するにあたって、光は重要です。白や青色の光を浴びていると目がすぐに疲れてしまいます。ブラウザやターミナルをダークモードにしたり、間接照明を黄色みがかったオレンジのライトにするなど工夫をしています。 冷凍庫 リモートワーカーは家に籠りがちであるため、食料庫も重要です。大量の冷凍食品、生鮮食品を保存するために冷蔵庫とは別の冷凍庫を購入しています。 今後導入したいもの 先日購入した サンワサプライ ワイヤレスカメラ CMS-V65BK のマイク機能が微妙なため、独立したマイクの購入を検討しています。 土屋さんは、縦長のモニターや分離型キーボードの活用など、身体負担を減らすことを重視した構成が特徴的ですね。さらに、家具、色彩の雰囲気作りが素敵です! では、最後になりますが秋田さんお願いします! ■ 秋田さん / プロダクト開発部 / フロントエンド ■ Findy(転職サービス)のフロントエンド開発を担当しています、秋田と申します。週1〜2日で出社しており、リモートワークが多めのため作業環境は落ち着く雰囲気を大事にしています。 デスク周り全体 デスクは FlexiSpot の 昇降式デスクにDIYで作成した天板を載せており、チェアは Ergohuman のものを利用しています。座り作業・立ち作業のどちらでも快適に使えるので助かっています。 また、ファインディではオフィスでErgohumanのチェアが利用できるので出社時とリモートで同じチェアが利用できるのは嬉しいポイントです。 マシン 会社貸与 16インチMacBook Pro 私物 12.9インチ iPad Pro ディスプレイ ディスプレイはPHILIPSの27インチ4Kディスプレイをメインに利用しつつ、MacBook Pro16インチのディスプレイをサブに利用して開発しています。また、時々iPad Proでメモを取りたい場合があるので手元に置いてあります。 キーボード/マウス HHKB Professional HYBRID Type-S にキーキャップをサードパーティのものでカスタマイズしています。メカっぽい色味が気に入ってます。 マウスについてはMacのTrackpadの操作感が好きなので、 Magic Trackpad のみで作業をしています。 こだわりのアイテム紹介 ERGOTRON モニターアーム モニターアームにはERGOTRONのアームを利用しています。 昇降デスクのおかげで立ったり座ったりすることが多いためディスプレイの位置は頻繁に調整したくなるのですが、 このアームはディスプレイやMacBookの位置を自由自在にスムーズな移動ができるためとても便利です。またシルバーな見た目も気に入っています。 belkin MagSafe 3-in-1 充電器 ガジェットの充電器は belkinのワイヤレス充電器 を利用しています。私はiPhone、Apple Watch、AirPodsなど小型ガジェットにはApple製品を多く使用しているため、この充電器1台で気軽にワイヤレス充電できる点に満足しています。Apple製品を複数お持ちの方におすすめです。 リモートワークでの工夫 作業に集中するときは音楽を流すことが多いので、iPhoneからBluetoothで TEAC のUSB DACアンプに接続し、 DALI のスピーカーで出力しています。 スピーカーは天井近くに設置しており音が自然に広がるため、部屋のどこにいても違和感なく聴くことができます。スピーカーの位置を工夫するだけで音の響き方が変わり、高音から低音までバランスよく鳴るので気に入ってます。長時間聴いていても耳が疲れにくく気分転換にもなるので、仕事の効率を上げるためにも良い環境を整えたいと考えています。 今後導入したいもの HHKBのキーボードも気に入っているのですが自作の分割キーボードに興味があり、HHKBの配列に似た Choco60 や 7sPro あたりで組み立てを検討しています。チーム内にも詳しいメンバーがいるので教えてもらいながら導入したいと考えています。 秋田さんは、DIY(!)で作成した天板を活用した昇降デスクや、オーディオ環境への強いこだわりが印象的でした。スピーカー配置と音響効果の工夫は、作業空間をより快適にするヒントとなりそうですね! おわりに 3名それぞれが、自分の働き方に合わせて最適な作業環境を整えており、エンジニアがどのように生産性を高めているかが垣間見える内容でした。デスクやデバイスの選定だけでなく、作業の効率化や快適さを追求する工夫が随所に見られ仕事に対する熱意が感じられます。 ファインディでは、さまざまなバックグラウンドを持つエンジニアが活躍しています。技術にこだわり、より良いものを追求する仲間とともに働いてみませんか? 現在、ファインディでは新しいメンバーを募集中です。 興味のある方は、ぜひこちらからチェックしてみてください!
このブログの内容をポッドキャストでも配信中! open.spotify.com こんにちは。ソフトウェアプロセス改善コーチでFindy Tech Blog編集長の高橋( @Taka_bow )です。 2024 DORA Reportについての連載も、今回で最終回です。 今回は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のこちらのページ からダウンロードできるので、ぜひ一次情報に触れてみてください。 このブログの内容をポッドキャストでも配信中! Software delivery performance 本当に優れたチームとは「Eliteな改善」を実現するチーム 「手戻り率」の登場 Reliability(信頼性)は引退? Platform engineering プラットフォームエンジニアリングとパフォーマンスの関係 プラットフォームエンジニアリングがもたらす可能性 意外な落とし穴 Developer experience ユーザー中心の開発がDevExを向上させる 質の高いドキュメントがユーザー中心開発を増幅する 常に変わる優先事項の危険性 おわりに Software delivery performance DORAは、ソフトウェアデリバリープロセスのアウトカムを効果的に測定する手法として、4つの重要指標(Four Keys)と呼ばれるソフトウェアデリバリーの指標を継続的に検証してきたことは御存知の通りです。 2024 DORA Reportの結論としては、 最高パフォーマンスのチームは、Four Keys(変更リードタイム、デプロイ頻度、デプロイ失敗時の復旧までの時間、変更失敗率)すべてで優れた結果を出している一方、最低パフォーマンスのチームはこれらFour Keysすべてで低い結果となっています。 パフォーマンスの高低は業種に関係なく、あらゆる産業分野のチームが各パフォーマンスグループに存在しています。(p6) と、いつも通りです。 しかし、パフォーマンスレベル表が提示される直前、次のような注目すべき一文が添えられていました。 私たちは、前年のクラスター分析との 一貫性を保つため 、 元の4つの ソフトウェアデリバリー指標に対してクラスター分析を実施しました。(p13) 「一貫性を保つため」とはどういう事でしょうか? 実は、今回のレポートでDORAはソフトウェアデリバリーパフォーマンスの測定指標を再定義しています。 DORAはこの変更を 「Evolving(進化)」 と表現しています。 本当に優れたチームとは「Eliteな改善」を実現するチーム まず、この新しい指標の説明に入る前にFour Keysベースの、いつものクラスター分析の結果を見てみましょう。 【2024 パフォーマンス指標】 指標 Elite High Medium Low Deployment frequency オンデマンド(1日複数回) 1日1回以上週1回未満 週1回以上月1回未満 月1回以上6ヶ月に1回未満 Change lead time 1日未満 1日以上週1回未満 1週間以上1ヶ月未満 1ヶ月以上6ヶ月未満 Failed deployment recovery time 1時間未満 1日未満 1日未満 1週間以上1ヶ月未満 Change failure rate 5% 20% 10% 40% 全回答者に占める割合 19%(18-20%) 22%(21-23%) 35%(33-36%) 25%(23-26%) *89% 信頼区間 集計では、 Change failure rate (変更失敗率)に特異な傾向 が見られます。 この特徴は次のグラフを見るとより明確です。 Figure 1. Software delivery performance levels なんと、 変更失敗率のHighレベルとMediumレベルが逆転 しているのです。 私は、この決定を DORAからの強いメッセージ と捉えました。それは、次の解説に表れています。 私たちは、より高速なチームを「High パフォーマー」、より遅いが安定しているチームを「Medium パフォーマー」と呼ぶことにしました。この決定は、これらのパフォーマンスレベルを使用する際の 潜在的な落とし穴の一つを浮き彫り にしています。つまり、特定のパフォーマンスレベルに到達することよりも、改善を続けることの方がチームにとって重要であるという点です。 本当に優れたチームとは、「Eliteなパフォーマンス」を達成するチームではなく、「Eliteな改善(elite improvement)」を実現するチームなのです。 (p14) 「パフォーマンスレベルを上げましょう」「Eliteを目指しましょう」といったスローガンは、本質的な目的を見失わせる危険性をはらんでいます。真に重要なのは、品質とスピードを同時に追求するマインドです。この両立を実現するためには継続的な改善活動が不可欠だと言えます。 さて、変更失敗率ですがDORA Reportの歴史においては当初から 予測しづらい異質な指標 として認識されてきました( 第2回のブログ で触れています)。 2024年でもその影響が現れてしまったわけですが、一方で、DORAは変更失敗率に関して大きな実験をしています。それは、変更失敗率に関するアンケートの質問の追加と、新たな計測指標の仮説検証です。 私たちは、 変更失敗率という指標がチームに求められる手戻り作業量の代替指標として機能する という長年の仮説を持っています。デリバリーが失敗すると、チームはその変更を修正する必要があり、おそらく別の変更(修正コミット)を加えることになります。 この理論を検証するため、今年はアプリケーションの手戻り率に関する別の質問を追加しました。 「あなたが主に担当しているアプリケーションやサービスにおいて、過去6ヶ月間に計画されていなかったものの、アプリケーション内のユーザーに影響するバグに対処するために実施されたデプロイは約何回ありましたか?」 私たちのデータ分析により、手戻りと変更失敗率が関連しているという仮説が確認されました。(p11) 「手戻り率」の登場 そこでDORAは、 長年の仮説であった「手戻り率」を追加 することにしました。 しかし、具体的にどう影響を与えているのかの明確なデータは提示されていません(「仮説が確認された」という明言のみ)。 従来のFour Keysとの関係を整理すると次のようになります。 p11 の表を元に筆者が作成 ポイントは、ソフトウェアデリバリーに関連するメトリクスを 「スループット」と「安定性」を明確に分けた ことだと思います。(個人的には「デプロイ失敗時の復旧までの時間」は「安定性」を測る指標だと思っていましたが、今回は明確に「スループット」であると提案されました。) つまり、指標として不安定な「変更失敗率」は新たな「手戻り率」というパートナーを迎え、新ユニットを結成したのです。 従来所属していたグループ「Four Keys」(変更リードタイム、デプロイ頻度、デプロイ失敗時の復旧までの時間、変更失敗率の4つの主要メトリクス)に籍を置くものの、メンバー同士の関係性は変わった……と言ったところでしょうか。 今後の関係性も含め継続的な分析を期待したいところです。私達も実験してみる必要性を感じています。 Reliability(信頼性)は引退? なお、今回のDORA Reportではパフォーマンス指標としてのReliability(信頼性)についての言及は限定的であり、「A decade with DORA(DORAと共に過ごした10年)」という章で少し紹介されただけでした。 Reliability(信頼性)はこのままひっそりと引退するのか、それとも重要な指標として再評価されるか、今後も注目していきたいと思います。 なお、あくまでソフトウェアデリバリーパフォーマンスの指標として有意なのか?という視点の話であって、 信頼性が重要なメトリクスであることには変わりない ことを申し添えておきます。 Platform engineering 2024 DORA Reportは、基本的にソフトウェアデリバリーに焦点を当てたレポートですが、今回はプラットフォームエンジニアリングについてかなりの紙面を割いています。このレポートでは、プラットフォームの活用が、ソフトウェアのデリバリーと運用面のパフォーマンスにどのように関係しているのかを詳細に検証しています。 プラットフォームエンジニアリングとパフォーマンスの関係 まだ日本国内では聞き慣れない言葉かもしれませんので、最初にプラットフォームエンジニアリングの解説をしておきます。 ご存じの方は読み飛ばしてください。 【プラットフォームエンジニアリングとは】 プラットフォームエンジニアリングとは、近年、クラウドネイティブ技術の進化により、開発環境が複雑化し、開発者がインフラ管理に時間を取られる課題が浮上しています。プラットフォームエンジニアリングは、この問題を解決するために、開発者向けのセルフサービス型プラットフォームを構築し、生産性を向上させる手法 です。 この考え方は Team Topologies における Platform Team の役割と密接に関係しています。Team Topologies では、開発チーム(Stream-aligned Team)が機能開発に集中できるよう、Platform Team がインフラ管理を抽象化し、共通の開発基盤を提供することを推奨しています。Spotify の Backstage は、Internal Developer Platform(IDP)を構成する要素の一つであり、主に開発者向けのポータル(Dev Portal)として機能します。IDP には、インフラのセルフサービスプロビジョニングや CI/CD の統合など、より広範な機能が含まれる場合があります。 プラットフォームエンジニアリングを支える重要な技術の1つが Infrastructure as Code(IaC) であり、その実現において重要な役割を果たすのが Terraform です(他に、Pulumi や Crossplane などのツールも選択肢として存在します)。Terraform を活用することで、開発者がセルフサービスでインフラをプロビジョニングできる環境 を整えることが可能になります。例えば、Terraformモジュールを用意することで、開発者は簡単な設定だけでクラウドリソースを構築でき、インフラ管理の負担が軽減されます。 プラットフォームエンジニアリングは単なるツール導入ではなく、組織文化やプロセスの改善も含めた包括的な戦略 です。適切なツールを導入するだけではなく、開発者のニーズを把握し、継続的にフィードバックを反映させる仕組みが求められます。チームが「本来やるべき仕事」に集中できる環境を整えることで、ソフトウェアの提供速度を向上させ、ビジネスの成長にも貢献します。 Internal Developer Platform(IDP)を利用している開発者は、次のような結果が分かったそうです。いくつかのポジティブな結果と共に、欠点も見えています。 ポジティブ ネガティブ 個人の生産性が8%向上 スループットが8%低下 チームのパフォーマンスが10%向上 変更の安定性が14%低下 組織全体のソフトウェアデリバリーおよび運用のパフォーマンスが6%向上 プラットフォームエンジニアリングがもたらす可能性 プラットフォームの使用期間と生産性 *1 の関係を見ると、プラットフォームエンジニアリングの取り組み開始時に初期の成果が得られ、その後プラットフォームが年数を重ね成熟するにつれて一旦低下し、その後回復するというパターンが見られました。 このパターンは、変革の取り組みにおいてよく見られるもので、初期の成果を上げた後に困難に直面するケースを指します。しかし、長期的には生産性の向上が維持されており、ソフトウェアデリバリーと運用プロセスにおける内部開発者プラットフォームの重要性とその潜在的な価値を示しています。 意外な落とし穴 上記で書いた通り、スループットの8%低下や変更の安定性の14%低下といった欠点も確認されています。DORAとしても明確な分析はできておらず、次のような仮説を提示しています。 # 仮説 詳細 1 プロセスの複雑化 コードが本番環境に到達するまでの「引き継ぎ」段階が増え、各段階で時間が追加される 2 プラットフォーム強制利用の問題 アプリ開発の全工程でプラットフォームの使用が義務付けられる場合、さらに6%のスループット低下 3 実験の促進 プラットフォームが開発者に変更を自信を持って行う環境を提供し、より多くの変更を可能にする 4 品質保証の課題 プラットフォームが変更の品質を十分に保証できていない、またはチームがスループットを優先して自動テスト機能を活用していない また、プラットフォームエンジニアリングとバーンアウト *2 の関係性に関する調査では、変更の不安定性とプラットフォーム利用の組み合わせによってバーンアウトリスクが高まることが明らかになりました。 この興味深い関連性について、DORAは3つの仮説シナリオを提示していますが、本ブログで取り上げるのは止めます。詳しく知りたい方は原著をお読みください。 プラットフォームエンジニアリングの章は全体的に具体性が欠けており、個人的には科学的ではないと感じた章です。 今後の研究成果に期待したいと思います。 Developer experience 2024 DORA Reportでは、デベロッパーエクスペリエンス *3 (以降、DevEx)に関して多くの誌面を割いています。このセクションでは、DevExが組織の成功に直結するという重要な発見と、それを改善するための具体的な方法について掘り下げています。 AIの時代においても、最終的にソフトウェアを構築するのは人間です。DevExがいかに製品品質と組織のパフォーマンスに影響するのか、DORAレポートに基づいて解説します。 なお、私は以前DevExの科学的な研究について解説したブログを書いておりますので、合わせてお読み頂ければと思います。 ユーザー中心の開発がDevExを向上させる レポートでは、DevExを向上させるにはまず、エンドユーザーエクスペリエンス(UX)を向上させることが重要であるという点が強調されています。エンドユーザーのニーズを深く理解し、それを開発プロセスの中核に据える組織では、開発者の生産性が向上するとともに、組織全体の成長が促進されることが調査で示されています。 ユーザーのニーズを軸に開発を行うことで、開発者の仕事の満足度が高まり、結果的に組織全体のパフォーマンス向上につながる可能性があります。ユーザー中心(User-Centric)のマインドセットを実践している開発者には、次のような特徴が見られます。 より高い生産性を発揮する( 目的意識が明確になり、不要な作業が減る ) バーンアウトのリスクが低下する( 仕事の意義を感じやすく、ストレスが軽減される ) より高品質な製品を生み出す( ユーザーの課題に直結したソリューションを提供できる ) また、ユーザーエクスペリエンス(UX)を最優先する組織では、ソフトウェアデリバリーの安定性やスループットが必ずしも品質の前提条件とはならないという点が指摘されています。 その理由として、最終的な製品の品質は「迅速なデリバリー」ではなく、「ユーザーにとっての価値」によって決まる可能性があるからです。 このレポートの知見を踏まえると、ユーザー価値の創出に組織的に取り組むことの重要性が浮かび上がります。ファインディでは幸いなことに、専門のデザインチームがありエンジニアと共にユーザーエクスペリエンス(UX)に力を入れているため、この課題への取り組みはすでに進んでいると言えるでしょう。今後もさらなる進化を目指して努力を続けていきたいです。 一方で、ユーザーフィードバックを十分に取り入れない組織では、安定したデリバリー速度が品質を確保する唯一の手段になりがちであるとも述べられています。 これは本来「ユーザー価値の創出」が目的であるべきところ、「安定したデリバリー」という手段が目的化してしまう典型的な例といえるでしょう。その結果、ユーザーの実際のニーズとはズレた機能や、見た目は魅力的でも実際にはほとんど使われない機能("shiny but hardly used")が生まれるリスクが高まるという考察がされています。 最終的な目標は、私たちが作る製品をユーザーに愛してもらうことです。「デベロッパーエクスペリエンス」の章で述べているように、ユーザーに焦点を当てることで、製品の機能に存在意義が生まれます。開発者は、これらの機能がユーザーエクスペリエンスの向上に役立つことを確信して、自信を持って開発を進めることができます。(p73) これは非常に興味深い考察です。シンプルに言い換えれば「エンジニアもお客様の喜ぶ顔を見れば生産性は上がり組織も成長する」ということなので、 商売の基本 みたいな話だなと思いました。 質の高いドキュメントがユーザー中心開発を増幅する 2021年からドキュメントの調査を開始したDORAですが、2024年のレポートでは、質の高いドキュメントとユーザー中心のアプローチを組み合わせると、製品パフォーマンスが向上することが明らかになりました。 質の高いドキュメントの評価には、内容の見つけやすさや信頼性といった要素が含まれます。 DORAは、 アジャイルマニフェスト(アジャイルソフトウェア開発宣言) を引用して次のように述べています。 アジャイルマニフェストは 「包括的なドキュメントよりも動くソフトウェアを」 *4 を提唱しています。しかし、私たちは依然として、質の高いドキュメントが動くソフトウェアの重要な構成要素であることを認識しています。 「包括的なドキュメント」という表現は、ドキュメントを含む不健全な慣行を表しているのかもしれません。 問題のあるドキュメントには、官僚的な目的だけのために作成されたドキュメントや、経営陣と従業員の間の不信感を取り繕うためのドキュメントが含まれます。不健全なドキュメント文化には、ドキュメントを作成するものの、維持や整理を行わないことも含まれます。 アジャイルマニフェストが宣言された2001年頃は、「ドキュメント作成に時間を取られすぎる問題」が開発現場の切実な課題でした。 アジャイルソフトウェア開発宣言 当時の多くの開発 では詳細な仕様書作成が前提とされ、要件変更が発生するたびに仕様書の修正に追われ、実際の開発よりもドキュメント管理に多大な時間を費やしていました。大量の紙にプリントして製本、そのドキュメントを納品、といった風習もまだ残っていた時代です。 また、現代に生きる私たちは忘れがちですが、2001年頃の技術的な制約も大きく影響していました。 ツールはWordやWiki、Lotus Notes/Domino *5 が主流でしたが、当時のツールはバージョン管理機能が貧弱で、複数人での同時編集が不可能、変更履歴の追跡も困難でした。 また、大きなドキュメントは頻繁にクラッシュし、図や表の扱いも現在より遥かに制限されていました。さらに、ストレージは現在と比べて容量が小さく高価であり、ネットワーク速度も遅いという環境でした。 一方、 クラウド中心の現代 ではNotionやConfluence、GitHub Wikiなど、協働作業に適したドキュメント管理ツールが普及し、リアルタイム共同編集や変更履歴の自動管理が当たり前となっています。 DORAレポートによれば、現代におけるドキュメントの役割は「ユーザーの声やフィードバックをチーム全体に共有し、それを製品に反映させる」という、より価値創造に直結したものへと進化しています。 DORAレポートは、健全なドキュメント文化を構築するための具体的な実践方法も提示しています: 重要なユースケースの文書化 テクニカルライティングの研修 明確な責任者と更新プロセスの定義 チーム内でのドキュメント作業の分担 開発ライフサイクルの一部としてのドキュメント維持 古いドキュメントの削除 業績評価における文書作成貢献の認識 さらに、詳しく知りたい方は原著をお読みください。 常に変わる優先事項の危険性 DORAの調査で最も注目すべき発見の1つは、組織の優先事項が頻繁に変わることによる悪影響です。 エンジニアであれば直感的に「危険」と思える現象です。 この感覚は誰もが経験したことがあるでしょう。数か月かけて新しい機能の開発に取り組んできて、それがユーザーにとって必要なものであると確信し、集中し、モチベーションも高い状態です。ところが、突然、あるいは突然のように感じるほど急に、 経営陣が組織の優先事項を変更します。 すると、あなたのプロジェクトが一時停止されるのか、中止されるのか、別の形に変わるのか、それとも全く違うものになるのかが分からなくなります。 データによれば、優先事項が不安定な組織では、 生産性に小さいながらも確実な低下が見られる バーンアウトが大幅に増加する 興味深いことに、強力なリーダーシップや質の高いドキュメント、ユーザー中心のアプローチがあっても、優先事項が不安定であれば従業員はバーンアウトのリスクにさらされ続けることが明らかになりました。DORAは、これが慢性的なストレスによるものと推測しています。 一方で興味深いことに、優先事項が安定すると、逆にソフトウェアデリバリーのスピードと安定性が低下するという予想外の結果も報告されています。これについてDORAは、安定した組織では変更が少なくなるか、推奨されるよりも大きなバッチでの出荷が行われるためではないかと仮説を立てています。 おわりに さて、全4回にわたってお届けしたDORAレポートに関するブログも一旦終わりにし、2025年のDORAレポートを待ちたいと思います。 皆様におかれましてはDORAレポートを参考にしながら、ぜひ自組織についての仮説や理論を組み立てるのに役立ててください。独自の実験に取り組むことで、より実践的な知見が得られるでしょう。 今回のブログを書きながら改めて感じたのは、ソフトウェア開発の複雑さです。 クネビン(Cynefin)フレームワークで例えると「Complicated」ではなく、「Complex」の領域に位置します。 Tom@thomasbcox.com, CC BY-SA 4.0 < https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons 領域 特徴 対応方法 例 明確(Clear) 因果関係が明確であり、誰が見ても同じ答えが得られる領域。ルールやベストプラクティスが効果的。(2014年までは単純(simple)、その後明白(obvious)と呼ばれ、最近の名称に変更) 「分類し、対応する」(Sense — Categorize — Respond) マニュアル化された業務、明確な手順がある問題 煩雑(Complicated) 因果関係が理解できるが、専門知識や分析が必要。答えが複数存在する可能性もある。理論的に解決可能。 「分析し、対応する」(Sense — Analyze — Respond) エンジニアリング、法律の専門的問題、データ分析が必要な業務 複雑(Complex) 因果関係が曖昧で、試行錯誤を通じてパターンが見えてくる。予測が困難で、正しい答えが最初からわからない。 「試し、理解し、対応する」(Probe — Sense — Respond) 新製品開発、文化変革プロジェクト、組織変革 混沌(Chaotic) 因果関係がなく、予測不可能な状況。迅速な介入が必要で、秩序を取り戻すことが優先される。 「即座に行動し、理解し、対応する」(Act — Sense — Respond) 自然災害、事故発生直後の対応、緊急事態 混乱(Confusion) どの領域にも属さない、または適用領域が不確かな状況。複数の視点が入り乱れ、争いが発生することも。 状況を分解し、他の4領域に割り当てることで解決の糸口を見つける 情報が混乱していて、どの領域に該当するか判断が難しい場合 様々な要因が絡み合いComplexになりやすいソフトウェア開発ですが、パターンは存在します。 まず「試し、理解し、対応する」(Probe — Sense — Respond)というアプローチで小さな実験を繰り返し、そこから学んでいく。この積み重ねが、ソフトウェア開発では大事なのだと、改めてDORAレポートを熟読して実感しました。 そして、この複雑さ(Complexity)こそが、ソフトウェア開発の魅力であり、日々新たな発見と創造の喜びをもたらしてくれるのだと実感しています。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers *1 : DORAの生産性(Productivity)の定義:個人が自身の仕事において、どれだけ効果的かつ効率的であると感じているか、価値を生み出し、タスクを達成できているかを測るもの。 *2 : バーンアウト(Burnout)とは、長期間のストレスや過重な業務負担によって、心身ともに疲弊し、モチベーションや集中力が低下する状態を指します。特にソフトウェアエンジニアのように、高い認知負荷や締切に追われる職種では発生しやすく、「燃え尽き症候群」とも呼ばれます。主な症状には、慢性的な疲労、仕事への意欲の低下、感情の枯渇などがあり、生産性の低下や離職の要因にもなります。DORAは10年に渡り、このようなバーンアウトのリスクを考慮した調査を数多く実施しています。 *3 : 私は頑なに「開発者体験」とは訳しません。正しいニュアンスを伝えるなら「開発者が快適かつ効果的に働ける環境全般」とするべきで、でもこれだと面倒なのでそのままの言葉で良いかなと思っています。 *4 : 「包括的なドキュメントよりも使い物になるソフトウェアを」と訳したほうが良い説を支持しています。 https://x.com/t_wada/status/1848630196775346294 *5 : Lotus Notes/Dominoとは、IBMが1995年にLotus Development社を買収して獲得した企業向けグループウェア・情報共有プラットフォームです。1990年代から2000年代初頭にかけて多くの企業で導入され、メール、カレンダー、文書管理、ワークフロー機能などを統合した先進的なシステムでしたが、操作の複雑さやカスタマイズの難しさも指摘されていました。
こんにちは、ファインディ CTOの佐藤( @ma3tk )です! ちょうどテックブログを始めて1年経ちましたので、今回はその振り返りと今後の方針についてお話します。結論としては、テックブログを始めて良かったと思います。 テックブログを始めるのは簡単です。そんな中で推進して継続することが大変でしたが、ファインディのエンジニア組織にとってポジティブな側面が多くありました。 なぜテックブログを始めたのか 始めてからの実績 テックブログによって起こった変化 ファインディ応募者にとって理解の助けになった チーム間の取り組みがよりクリアになった 「エンジニアの日常」が読まれることがわかった 社内でブラッシュアップして社外に記事を出せる テックブログを進める上で意識したこと 記事作成プロセスを初期から整えた 執筆者の思いや背景を盛り込んでもらう 2年目に向けた新しい取り組み おわりに それでは見ていきましょう。 なぜテックブログを始めたのか 我々ファインディは2024年2月にテックブログを始め、ちょうど1年が経過しました。 実は昔からテックブログは始めたい気持ちがあったものの、次の点で躊躇していました。 テックブログが途切れることで逆にエンジニア組織が微妙に見えてしまう可能性 推進する人が少なく、やりたいと言ってくれる人が多くなかった エンジニアリングとして高いレベルでプロダクト開発が行えているものの、個人のnoteの発信だけでは不十分で、組織的に技術広報をする必要があることを2023年に認識しました。 そして日々の目標設定をする上で、エンジニア個人でも実は「発信をして採用や技術広報にトライしたい」という意欲の高いメンバーが多かったことも相まりました。 このテックブログは単なる技術の紹介だけではなく、組織としてのアーキテクチャやツール選択の背景や組織としてのあり方に透明性を持たせて発信をすることを目的としました。 始めてからの実績 テックブログを始める以前の話ですが、カジュアル面談のタイミングでファインディについて「サービスは知っているが、エンジニアがどんなことをしているかはわからない」という声が多くありました。 テックブログを始めて1年で次のような実績になりました。 80記事以上をリリース(週平均1.5記事以上のペース) 延べ282,223人のユーザーにご訪問いただき、1記事あたり平均約3,500アクセス はてなブックマーク合計4,622、1記事あたり平均57はてブ 2025年2月時点での情報ですが、「思っていた以上にアウトプットできた」というのが僕の感想です。 特に反響の大きかった記事などは 2024年ふりかえり!Findy Tech Blogの人気記事まとめ - Findy Tech Blog でまとめておりますのでこちらもご覧ください。 テックブログによって起こった変化 ファインディ応募者にとって理解の助けになった テックブログを開始してから、カジュアル面談や選考の場で「ブログを読みました」という声を多くいただくようになりました。 実際に入社したメンバーからも「ブログを読んで、ファインディのエンジニア組織の考え方や業務の進め方にマッチすると感じて応募しました」といったポジティブなフィードバックをもらっています。 また、テックブログで過去の意思決定の背景が書いてあることによって、カジュアル面談でもファインディの未来についてお話する時間が多くなり、興味を持っていただける割合が増えたと感じています。 組織の意思決定プロセスや技術選定の背景や取り組みを伝えることで、入社前後のギャップを減らし、互いの期待値をすり合わせることができるようになったと感じています。 一方で、カジュアル面談で「ブログ記事を過去に読んだことがあるかどうか」を聞いても、テックブログの認知ができていないこともあります。まだまだ伸びしろがいっぱいですね。 チーム間の取り組みがよりクリアになった ブログ執筆をきっかけに、社内のエンジニアが外部イベントでの登壇や技術発信に積極的になるという好循環も生まれました。 社内でチーム間での取り組みを共有していたつもりでしたが、テックブログの記事を公開することで異なるチーム間でのコミュニケーションも活性化し、「他チームがどんな課題に取り組んでいるのか」を知る機会が増えました。 「エンジニアの日常」が読まれることがわかった 予想していなかった効果として、「日常シリーズ」として公開している日々使っているツールや作業デスクなど直接の業務に関係しない記事がヒットしています。 なぜそれほど読まれるのかについては分かりきっていませんが、技術的な内容だけでなく、実際に私たちがどのように働いているかという「日常」を見せることで、どんなメンバーがファインディに関わっているのかの人柄がわかってくるのではないかと思います。 PV数においても、当初の予想を大きく上回る記事が複数あり、これからも様々なエンジニアの「日常」についてシリーズ化して出していきます。 社内でブラッシュアップして社外に記事を出せる 実はテックブログの記事の原案の一部は、社内のナレッジ共有ツールに投稿しています。 まず社内向けの情報共有を行い、その記事をベースに社外に向けてテックブログに公開するという流れも徐々に確立されつつあります。 社内では多少荒削りな内容でも投稿して言語化の強化を進め、そこでの反応を見ながら外部に発信したい記事を選定・ブラッシュアップすることで、効率的なコンテンツ作成フローになります。 テックブログを進める上で意識したこと 記事作成プロセスを初期から整えた 1年間の運営を通して、効率的な記事作成プロセスに仕上げることができましたが、初期は失敗が多くありました。 例えば、記事の方向性を揃えずに一気に書き上げてしまって、テックブログの方向性からズレてしまうことがあり、差し戻し・手戻りも何度か発生しました。テックブログとしていいものに仕上げたいこともあり、しっかりレビューをしてきました。 執筆前にサマリを箇条書きで提出し、方向性のレビューを実施することで手戻りを防ぐ 編集長やCTOが中心となり、記事内容をレビュー(ファインディ社として出すべき記事になっているかの詳細の確認) 運用会議や目標設定により、全員で継続的なコミット・スケジュールを確保する 上述の流れによってなるべく執筆者に差し戻しや多数のコメントがつかない状況を作りました。合わせて、技術的な内容だけでなく「なぜその技術を選んだのか」「どのような議論があったのか」という背景情報を必ず含めることで、単なる技術ブログではなく、組織としての考え方を伝えられるコンテンツになりました。 執筆者の思いや背景を盛り込んでもらう これまで、執筆者の思いを積極的に取り入れた記事に仕上げることに注力してきました。「どんな記事を書きたいか」「どんな情報を発信したいか」をエンジニア自身から引き出すことで、意思決定の背景を理解できる記事が増えてきました。 また、技術解説と組織文化の両立を意識し、「技術的に面白いだけ」「組織論だけ」に偏らないバランスを取ることも重視しました。 定期的な運用会議での振り返りと、四半期ごとの目標設定により、一時的なブームで終わらない継続的な取り組みになりました。 2年目に向けた新しい取り組み 2年目では、これまでの技術領域に加えて、次のようなテーマにも挑戦していきたいと考えています。 生成AIの活用事例と開発プロセスへの統合の発信 エンジニア組織のマネジメント方針と成長支援の仕組み エンジニアの日常シリーズの拡張 などについてもトライしていきます。 その他にも、グローバル展開に合わせた英語での情報発信として、日本語記事の英語翻訳や英語でのオリジナル記事の作成などもトライしていく予定です。 より一層「働いてみたい」「技術の使い方で参考になった」と思っていただけるように、テックブログでファインディのエンジニア組織のリアルと技術を伝えていきます。 2年目も昨年と変わらない70記事を当たり前に公開し、様々な種類の記事に挑戦することで今まで以上に読んでもらえるテックブログへと進化させます。 おわりに この1年間、多くの方にテックブログを読んでいただき、本当にありがとうございました。 これからも、単なる技術情報の発信にとどまらず、ファインディのエンジニア組織の考え方や文化、そして目指す未来を共有していきます。 「こういうチームで働いてみたい」「この組織と一緒に成長したい」と思っていただける方がいれば、ぜひカジュアル面談などでお話しできれば嬉しいです。 興味がある方はこちらから↓ herp.careers これからも、より良いプロダクトと組織を一緒に作っていける仲間を待っています。
はじめまして、データサイエンティストのだーさん ( @Dakuon_Findy ) です。2025年の1月よりファインディのプロダクトマネジメント室 GenAIイネーブルメントチームにデータサイエンティストとして参画しております。このチームはLLMを活用した各種プロダクトの強化や内部の業務オペレーションを改善するチームです。 近年、GitHub Copilotをはじめとしてソフトウェア開発へのLLM導入が進む中で、 Cognition社 が開発した Devin というAIエンジニアが注目を集めています。Devinは、指示に応じてコードを自動生成し、PR作成や修正提案までこなす自律型AIです。 現在、Findy開発チームにおいてフロントエンド開発の支援にDevinを活用していますが、データサイエンティストとしてはデータ分析におけるDevinの力も気になるところです。 そこで、本記事ではWine Qualityデータセットを用いて、Devinに探索的データ分析 (EDA) を実施させた実験の結果を紹介します。Devinはデータをどのように解析し、どんな洞察を導き出したのか? そして実際に使ってみて感じた強みや課題とは?AIを活用したデータ分析の可能性を一緒に探っていきましょう。 ファインディ社内での活用状況 DevinにWine QualityデータセットのEDAをやらせてみた 実験の概要 実験の手法 結果の考察 まとめ ファインディ社内での活用状況 現在Findy開発チームではフロントエンド業務に対するDevinのオンボーディングが進んでおり、オンボーディング初期の4日間で26件のPRを作成し、そのうちの20件がマージされるという結果を出しています。 実際に使用したメンバーに感想を尋ねたところ、どのPRもジュニアレベルの内容で、微修正のみで済んだPRが4割、それを踏まえてプロンプトを調整した結果、2割が承認のみで十分なPRとなり、残り4割はある程度の修正が必要だったとのことです。 4割には依然として伸びしろはあるものの、「ミドル〜シニアエンジニアの業務の中で発生したジュニアレベルの作業をDevinに任せることで、ミドル〜シニアエンジニアの時間をより高度な作業に充てることができる」というメリットがあるように個人的には感じています。 詳細は別の機会により詳しい記事を掲載する予定ですので、続報をお待ちください。 DevinにWine QualityデータセットのEDAをやらせてみた 実験の概要 データ分析には前処理、可視化、モデリングなど多くの工程がありますが、今回はデータ分析の最初のステップとなるEDA(Exploratory Data Analysis)でDevinを試しました。 1 EDAとは「データの傾向や特徴をざっくりと掴むための分析」です。機械学習のモデルを作る前に「このデータにはどんなパターンがあるのか?」「おかしなデータ (異常値) はないか?」といったことをグラフや統計量を使って可視化し、「このデータで本当に良いモデルが作れそうか?」を見極め、「もし作るならばどのようにすればよいか?」を探るために行います。 データにはWine Qualityというワインの品質に関するデータセットを使いました。 Cortez, P., Cerdeira, A., Almeida, F., Matos, T., & Reis, J. (2009). Wine Quality [Dataset]. UCI Machine Learning Repository. https://doi.org/10.24432/C56S3T. データサイエンスの分野では初学者の学習目的でよく利用されるデータセットがあります。Wine Qualityデータセットもその1つで、赤ワインと白ワインの品質に関するデータが含まれています。ワインのアルコール度数や糖分などの成分と、品質スコア (0〜10点) が記録されています。成分の情報から機械学習モデルを作り、品質を予測できるか?などを試すことができるデータセットです。 実験の手法 まずDevinにWine Qualityデータセットを UC Irvine Machine Learning Repository からダウンロードするように指示を出しました。 Devinへの指示 Devinにはこの画像のようにSlack経由で指示を出すことができます。DevinにSlack経由で開発を任せる際のざっくりとした流れは次の通りです。 SlackからDevinに指示を出す Devinが指示を受けて自動でコードを生成し、GitHubにPRを作成する DevinからPRを作成した旨通知が来る ユーザがレビューし必要なら修正する。LGTMならmainブランチにマージする 1〜4を繰り返し、開発を進める 作業が終わったら、DevinにSLEEPコマンドを送り、休止させる 休止後にDevinがここまでの指示をもとにナレッジを提案し、ユーザはそれを採用するかどうかを選択したり文言を変更したりする 7で採用するナレッジによりある程度Devinの行動をコントロールできます。私が事前の実験で与えたデータ分析に関するナレッジは次の3点のみで、それ以外はほとんど指示していません。データのダウンロードほか残りの作業はDevinが自律的に判断し行いました。 PRやSlackのやりとりは日本語で行うこと 図のキャプションなどは日本語で書くこと (事前にIPAexフォントをDevinに与えています) 図示のカラーパレットには viridis を使うこと 結果の考察 こちらがEDAの結果の抜粋です。実際にDevinが書いたコードの詳細は リンク先のPR で確認でき、作業後にDevinが書いたEDA結果の考察や今後の課題は リンク先のIssue に記載されています。 2 個人的な感想ではありますが、未知のデータに対するEDAであり人間による詳細な指示を加えていないことを踏まえると、非常に良い結果が得られていると感じました。 特に作業後に書かせたIssueには、どのデータをどの表現形式で図示するかといった意図や、EDAの結果わかったデータの特徴、次のステップについての提案が書かれていました。 今回はあえて白ワインと赤ワインを分けずにデータを取ってくるよう指示を出したのですが、Devinは可視化の際にワインの種類を意識して1つの図に分布をまとめて表示することで特徴量の分布の違いを比較しやすくしていました。結果としてデータ数の不均衡や品質に影響を与える特徴量の違いを把握できており、次のステップとして赤ワインと白ワインを分けた分析・モデリングを提案するなど、適切なデータ分析に基づく判断ができていると感じました。 今回の実験で感じたDevinの伸びしろは次の2点です。いずれも修正するよう依頼するとすぐに修正され、ナレッジにも追加されたため今後は改善される可能性があります。 特に初回の可視化において日本語フォントが正しく設定されていない図を作成することがある 修正依頼の図 今回の実験で新たに追加されたナレッジ ナレッジへの追加 作成した図をコミットしたりSlackに送付したりせず、ユーザが確認できないことがある 結果をGitHubにpushするよう依頼 それに対するDevinの返答 実験段階ではSlackに画像が直接添付されることもあったため、ナレッジを追加すれば改善できそうです。 事前実験でcsv等のローデータはGitHubにアップロードしないように指示しており (ライセンスの問題等を孕むため)、ローデータが推測できる図版もGitHubにpushすべきでないとDevinが判断した可能性もあります。 まとめ Devinの活用はまだ発展途上ですが、データ分析の新しいアプローチを試す機会にもなります。 GenAIチームは、上記のように生成AI技術による技術検証を行ったり、プロダクト実装も担い全社において生成AI利活用を推進するチームです。 こうした取り組みから、プロダクトのエンハンスと事業成長に貢献することを目指しています。我々の取り組みに興味を持っていただいた方は、是非一度カジュアル面談でお話しましょう! これは初めての実験ではありません。 寺本さんの記事 を拝読していたところ、secretsに近い文字列をpushしてしまうというセキュリティリスクが存在することがわかっていたため、この記事を書く前に何度か実験とセキュリティに関する注意事項を提示し、セキュリティに対するナレッジをある程度学習させてから記事を書いています。セキュリティに関してはどうやら 徐々にアップデートされているような記事 も寺本さんより出ていますので今後の動向を注視したいところです。 ↩ PRやIssueに記載されていたDevinの実行リンクを公開に際して削除している都合でPRがeditされていますが、実行リンクの削除以外の変更はありません。 ↩
こんにちは。 ファインディ で 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のバージョンアップ等で変更される可能性があります。