ファインディ株式会社でフロントエンドのリードをしております 新福( @puku0x )です。 弊社では、数年前に社内のCI環境をすべてGitHub Actionsに移行しました。 この記事では、弊社のGitHub Actions活用事例の内、CI高速化についてご紹介します。 なぜCI高速化に力を入れるのか CI高速化 キャッシュの活用 ジョブの並列化 Larger Runners まとめ なぜCI高速化に力を入れるのか 当ブログをはじめ弊社では、たびたびCI高速化の大切さについて言及しています。 Findyの爆速開発を支えるテクニック - Findy Tech Blog RailsのCIのテスト実行時間を 10分から5分に高速化した話 - Findy Tech Blog Findy転職フロントエンドの開発生産性を向上させるためにやったこと - Findy Tech Blog これはなぜでしょうか? 開発が進むにつれて、コードベースが肥大化し、CIの待ち時間が増えていくのは皆さんにも経験があると思います。 CIの待ち時間が長いとついレビューを放置してしまいがちです。 レビューが遅いとブランチの生存期間が伸び、コンフリクトの発生確率が上がります。 コンフリクトを解決しても、CIが遅い状態ではまた同じことの繰り返しとなるでしょう。 GitHubの調査では、開発者は多くの時間をCI待ちに費やしていると報告されています。 github.blog 見方を変えると、CI高速化はコーディングの効率化と同程度のインパクトがあると言えます。 チームの開発生産性を支える基盤として、弊社はCI高速化に力を入れているのです。 CI高速化 キャッシュの活用 弊社では、 actions/cache を使って、依存関係のインストールを省く工夫を取り入れています。 ここでは例として、フロントエンド系のリポジトリのワークフローを紹介します。 - uses : actions/setup-node@v4 id : setup_node with : node-version : 20 - uses : actions/cache@v4 id : cache with : path : node_modules key : ${{ runner.arch }}-${{ runner.os }}-node-${{ steps.setup_node.outputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }} - if : steps.cache.outputs.cache-hit != 'true' run : npm ci フロントエンド周りのCIを組んだことのある方はピンと来たかと思います。 このワークフローでは、 node_modules ディレクトリをキャッシュしています。 npm公式では非推奨とされていますよね? なぜこのような書き方でも大丈夫なのでしょうか?その秘密はキャッシュのキーにあります。 key : ${{ runner.arch }}-${{ runner.os }}-node-${{ steps.setup_node.outputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }} キャッシュキーとして、OSやNode.jsのバージョン、パッケージマネージャーの種別などが細かく設定されています。 node_modules ディレクトリのキャッシュが非推奨とされる理由は、異なる環境で実行されることによるファイルの不整合を防ぐためです。これに気を付けていればキャッシュしても良いのです。 ※最近のGitHub ActionsではArmランナーが利用できるため、キャッシュキーにCPUアーキテクチャを追加するとより堅牢になるでしょう。 node_modules がキャッシュヒットしなかった場合を考慮して、 .npm ディレクトリのキャッシュも含めると次のようになります。 - uses : actions/setup-node@v4 id : setup_node with : node-version : 20 - uses : actions/cache@v4 id : cache with : path : node_modules key : ${{ runner.arch }}-${{ runner.os }}-node-${{ steps.setup_node.outputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }} - uses : actions/cache@v4 if : steps.cache.outputs.cache-hit != 'true' with : path : | ~/.npm key : ${{ runner.arch }}-${{ runner.os }}-node-${{ steps.setup_node.outputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }} restore-keys : ${{ runner.arch }}-${{ runner.os }}-node-${{ steps.setup_node.outputs.node-version }}-npm- - if : steps.cache.outputs.cache-hit != 'true' run : npm ci 弊社の場合では、これでおよそ20秒〜30秒ほど高速化できました。 ジョブの並列化 バックエンドのテストを例に挙げます。このワークフローでは、 matrix 機能を用いてテストを10並列で動作させるようにしました。 strategy : matrix : ci_node_index : [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] steps : - name : Test env : CI_NODE_TOTAL : ${{ strategy.job-total }} CI_NODE_INDEX : ${{ matrix.ci_node_index }} run : | # get spec files order by filesize TEMP_FILE_PATH=$(mktemp) git ls-tree -r -t -l --full-name HEAD | grep '_spec.rb' | sort -n -k 4 | awk '{ print $5 }' | ./scripts/ci/rspec_split_files.sh > $TEMP_FILE_PATH # echo outputs echo "====SPEC FILES COUNT====" cat $TEMP_FILE_PATH | tr ' ' '\n' | wc -l echo "====SPEC FILES====" cat $TEMP_FILE_PATH | tr ' ' '\n' # run rspec bundle exec parallel_rspec -- --format progress -- $(cat $TEMP_FILE_PATH) #!/bin/bash i = 0 ret = () while read -r line do if [ $[ i % $[ CI_NODE_TOTAL ]] = $[ CI_NODE_INDEX ] ] ; then ret += ($line) fi let i++ done echo ${ret[ @ ]} 単純にテストを均等配分するのではなく、ファイルサイズでソートするという工夫が施されています。これは、テスト実行時間がファイルサイズに比例するという仮定に基づいています。 これらの工夫により、実行時間が従来の約半分になるまで高速化できました 🚀 詳細は↓こちらの記事をご覧ください。 tech.findy.co.jp Larger Runners 基本的には並列化でCI高速化を目指しますが、難しい場合はLarger Runnersを使うのも手です。 (並列化の可否の判定は、テスト対象ファイルの分割を外部から制御可能かどうかで決めています) Larger Runnersは、契約しているプランが「GitHub Teamプラン」または「GitHub Enterprise Cloudプラン」の場合に利用可能です。 最大で64コアまでスペックアップできるらしいです。いつか使ってみたいですね! docs.github.com Armランナーについては先日GAとなったこともあり、積極的に移行を検討するようになりました。 github.blog 3割程度のコスト削減ができることから、既に社内のいくつかのプロジェクトではLinux Armランナーに完全移行しています。 2024年9月現在では、 ruby/setup-ruby などサードパーティの対応が進んでいないものもあります。移行の際は動作検証を十分にしておくと良いでしょう。 参考までに、弊社のフロントエンドでの高速化の例を示します。 Build Test 2コア 15m8s 12m7s 4コア 8m38s 6m56s スペックアップするとコストは増えますが、その分CIの待ち時間の削減が期待できます。実質的な負担に大きな変化が無い場合は強気でスペックアップしていきましょう 💪 まとめ いかがでしたでしょうか? この記事では、弊社のGitHub Actions活用事例の内、CI高速化についてご紹介しました。 CIの待ち時間については、「継続的デリバリー」の書籍を参考に 10分以内 を目指すと良いでしょう。 www.kadokawa.co.jp 実際に弊社では、これらの取り組みを行う前は1PRあたり15分〜20分ほどかかっていたCIが、10分以内の完了を目指して取り組んできた結果、平均5分程度まで高速化できた例もあります。 弊社にはCIの整備に関心の高いメンバーが多く在籍しております。勉強会等でお会いする機会がありましたらぜひお声がけください。 CIは5分以内!素早い開発サイクルを支えるCI - Speaker Deck ファインディでのGitHub Actions活用事例 - Speaker Deck こちらの発表については、connpassのイベントページにアーカイブ動画へのリンクを載せております。 findy.connpass.com 次回へ続きます!👋 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 突然ですが皆さんは本を読みますか? エンジニアという職業柄、技術書やビジネス書など、様々なジャンルの本を読む機会が多いのではないでしょうか? そこで今回は、人生を変えた一冊と題して、弊社エンジニア達のお気に入りの一冊を紹介していきます。 それでは見ていきましょう! 人生を変えた一冊 戸田 ソフトウェア・ファースト あらゆるビジネスを一変させる最強戦略 ジョナサン・アイブ 高橋 1兆ドルコーチ シリコンバレーのレジェンド ビル・キャンベルの成功の教え 森 アジャイルサムライ――達人開発者への道 まとめ 人生を変えた一冊 戸田 ソフトウェア・ファースト あらゆるビジネスを一変させる最強戦略 ソフトウェア・ファースト 作者: 及川 卓也 日経BP Amazon 及川卓也さん著の本で、DX(デジタルトランスフォーメーション)の本質を理解するためには必読の一冊です。 2024年9月には内容を大幅改定した第2版が発売予定とのことで、こちらも合わせてチェックしておきたいですね。 ソフトウェアファースト第2版 あらゆるビジネスを一変させる最強戦略 作者: 及川 卓也 日経BP Amazon 内容としては、日本のIT史の振り返りから始まり、現在の問題点の指摘、そしてDXの在り方、進め方について詳しく解説されています。 また、これからの時代の強い開発組織の在り方や作り方にも言及されており、エンジニアだけではなくマネージャーや経営者の方にも是非読んで欲しい一冊になっています。 実際に読み進めていくと共感できる部分が多く、「わかっているけど中々実行に移すことができない」という方にヒントを届けてくれるような内容でした。 この本が世に出た当時、自分は30代に入ったばかりで、いわゆるマネージャーとしてのキャリアを少しかじっていた頃でした。 経営陣がやって欲しいことと開発組織がやりたいことがズレている感覚が少なからずあり、この本を読んだことによってそれらがクリアになり、実際に実行に移すことが出来たことがありました。 自分が抱いていた感覚というものは当時所属していた組織特有のものではなく、社会全体の問題であるということを再確認できたため、逆に割り切って行動に移すための勇気を貰うことができました。 おそらくこの本と出会っていなかったら、今でも違和感と葛藤して何も進められないままだったと思います。そういうこともあり、エンジニア人生のターニングポイントとなった1冊になったと思います。 ジョナサン・アイブ ジョナサン・アイブ 偉大な製品を生み出すアップルの天才デザイナー 作者: リーアンダー ケイニ― 日経BP Amazon 1冊と言っていながら、もう1冊の紹介をさせてくださいw かのスティーブ・ジョブズが絶対的な信頼を寄せたデザイナー、ジョナサン・アイブ氏の生い立ち、学生時代、アップル入社後のiMac、iPhone、iPad、MacBook Airなど数々の革新的な製品づくりでの試行錯誤、社内での争いまでを描いた一冊です。 モノづくりに対する思考や姿勢、デザインに対する考え方など、エンジニアにも多くのヒントを与えてくれる内容になっています。 この本が世に出た当時、自分は20代中盤くらいで若く、これから何をしてキャリアを考えるべきなのか模索していた頃でした。その時にこの本と出会い、何気なしに読んでいくとアイブ氏のモノづくりに対する姿勢に驚かされました。 詳細は本を読んでいただきたいのですが、例えば新製品のデザインをする際、彼は数百、数千パターンのプロトタイプを作るそうです。 そのパターンなのですが、素人からみたらパッと見だと全く同じデザインに見えるそうです。しかしこれらは全て数ミリ単位で違うそうで、その違いを比べつつ、最終的なデザインに辿り着くそうです。iPhoneやMacbookなどのデザインも最初はこのようにして生まれたとのことで驚かされました。 これを読んだ時、自分が悩んでいたことが実はまだ甘い考えだったと気付かされました。世界的プロダクトを生んだデザイナーだとしても、まず最初に泥暗いことをやり切っているからです。 自分程度のエンジニアが今の段階でウダウダ悩んでいる暇があったら、目の前のことに集中して1個ずつ泥暗いことをやり切り続け、引き出しを増やすことに集中しようと決意できました。 おそらくこの本と出会っていなかったら、今でもウダウダ悩んで手を動かしていなかったかもしれません。この本もまた、エンジニア人生のターニングポイントとなった1冊になったと思います。 高橋 ファインディでエンジニア兼プロセス改善コーチをしている高橋( @Taka_bow )です。 1兆ドルコーチ シリコンバレーのレジェンド ビル・キャンベルの成功の教え 1兆ドルコーチ シリコンバレーのレジェンド ビル・キャンベルの成功の教え 作者: エリック・シュミット , ジョナサン・ローゼンバーグ , アラン・イーグル ダイヤモンド社 Amazon シリコンバレーの伝説的コーチでありスティーブ・ジョブズの親友でもあったビル・キャンベル。 『1兆ドルコーチ』は、彼の様々な教えを記録した本です。著者は元Google会長のエリック・シュミット、元Google SVPのジョナサン・ローゼンバーグ、元Googleで経営コンサルタントのアラン・イーグルの3名。(すでに著者がすごい面子!) この3人のみならず、ビルの指導を仰いだ起業家たちの多くが今日のテクノロジー業界を牽引しています。現在のGAFAMの隆盛は、ビルの影響力なくしては語れないと言われています。 私が好きなエピソードの1つに、Googleがマネジャーを「全廃」し管理職のいない組織を作った直後の、ラリー・ペイジとビルのやりとりです。 ビルは言います。 「ここにはマネジャーを置かないとダメだ」 ラリーは答えにつまった。ちょうどマネジャーを全廃したばかりで、彼は結構満足していたのだった。(後略) 二人はどちらも譲らず、しばらく堂々めぐりの議論を続けた。とうとうビルはラリーの流儀にならって、それならエンジニアに直接聞いてみればいいと言った。(中略)ビルはその一人に、マネジャーがほしいかと訪ねた。 ええ、という返事だった。 なぜだ? 「何かを学ばせてくれる人や、議論に決着をつけてくれる人が必要だから」 その日彼らは数人のソフトウェアエンジニアと話したが、答えはほとんど同じだった。 このエピソード 1 は、たとえテック企業でもマネージャーがきわめて重要な存在であることを示しています。エンジニア組織のマネジメントで悩みがあると、今でも読み返します。 森 FIndy バックエンドエンジニアの森 @jiskanulo です。 アジャイルサムライ――達人開発者への道 アジャイルサムライ――達人開発者への道 作者: JonathanRasmusson , 西村直人 , 角谷信太郎 オーム社 Amazon アジャイル開発を進める上でのチーム作り、見積もり計画、日々の開発と多岐にわたって解説があり入門書としておすすめです。 アジャイルサムライ日本語訳版が出版された2011年当時、IT業界のエンジニアが集まり各章を読み合わせる輪読会のコミュニティが日本各地で生まれました。 このコミュニティは次第に盛り上がり、翌2012年には原著者のJonathan Rasmussonさんを日本にお招きして参加者100人超えの大イベント Agile Samurai Dojo Gathering 2012 を開催するに至りました。 蒔かれた種子は今も世界でも芽吹いているでしょう。 私個人の当時の思い出を記します。 2010年に当時勤めていた企業を退職、数ヶ月の無職期間を経て新しい会社に勤めていました。 ユニットテストを導入して安全に開発するための仕組みづくり、営業メンバーの業務効率化のためのツール作成、社内サーバーの管理やデータセンターへのラッキングなどなど会社とプロダクトに貢献するべく取り組んでいました。 そんな日々を1年ほど過ごし、ただ作業をこなすだけで1日終わってしまう作業者になっているなと感じていました。 一人でできることは限界があるとも感じており、チームを組んでよりよい課題解決のやり方を模索しどうすればいいプロダクトを作れるのか、そもそもいいプロダクトとは…と色々なことに思い悩んでいました。 思い悩んでいるなかでアジャイルサムライに出会い、この本を通じてコミュニティに参加して他の方と交流を深めることで同じような悩みを抱えている仲間がたくさんいることを知りました。 ファインディ社に入社してから、この本にある「達人開発者」の振る舞いをあらためて心がけようとしています。 まとめ いかがでしたでしょうか? 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers (引用)エリック・シュミット. ジョナサン・ローゼンバーグ. アラン・イーグル. 櫻井 祐子 (翻訳). 1兆ドルコーチ シリコンバレーのレジェンド ビル・キャンベルの成功の教え. ダイヤモンド社, 2019/11/14, p.63 ↩
はじめに 皆様、はじめまして。Findyでプロダクト開発部/SREとしてジョインしました安達( @adachin0817 )と申します。今年の6月に入社し、ちょうど3ヶ月が経ちました。本日は、SREチームの立ち上げに関する0から1のプロセスと、今期の取り組みについてご紹介させていただきたいと思います。 SREチーム発足 2023年までは、バックエンドチームがインフラを担当していました。しかし、サービスの拡大に伴い、バックエンドチームのリソースが不足し、SRE的な改善が十分に行えない状況が続いていました。そこで、昨年からSREの大矢とチームリーダーの下司( @gessy0129 )がジョインし、現在は3名体制で活動しております。 SREチームの位置づけとミッション SREチームは横断的なSRE活動をしており、これを「横断SRE」と指しています。一方で、各プロダクトにおいてSRE的な役割を担っていたメンバーは「Embedded SRE」と呼ばれ、引き続き改善活動を担当しています。 SREチームは現在、チームを作り上げていく段階にあり、まだまだやることが多く残されています。こうした背景を踏まえ、SREチームの短期および中期におけるミッションを設定しました。 短期ミッション 「ファインディの事業成長を支えるための、SRE組織のあり方の確立」 中期ミッション 「社員全員が事業成長に集中できような仕組みを構築し、提供する」 SREの存在意義 SREは道を作るために存在する リスクを受け入れ、管理する SLOを計測する トイルの削減 モニタリングする 自動化する 他プロダクトの支援 SREチームの業務の進め方 アジャイル開発手法を採用しており、各メンバーにはそれぞれIssue(タスク)が割り当てられます。一週間イテレーションで管理し、Issueのクローズを目指しています。毎朝、GitHubのProjectsを使用してカンバンボードを確認し、今日のタスクや困っていることを共有や、雑談をしています。また、毎週金曜日にはチーム全体で振り返りを行い、Findy Team+を活用しながら内容をKibelaに記録し、全員が閲覧できるようにしています。さらに、隔週でEmbedded SREチームとのお茶会も実施しており、取り組みたいことを共有する場を設けています。 カンバン/ステータス ステータス 内容 To Do Issueを作成した状態、未着手 Parent In Progress 親子関係のあるIssueの親 In Progress 進行中のIssue Done 対応が完了したIssue では、今期SREチームの取り組みについてご紹介していきたいと思います。 今期の取り組みについて 全環境のTerraform import化 これまで全ての環境がTerraformで完全にコード管理されていない状態でしたが、現在は全リソースをコード化することで一元管理を実現し、環境間での設定の整合性が保たれるようになりました。まずは既存の設定を棚卸しし、リソースをインポートすることで、今後の変更や拡張がより容易になっています。さらに、Terraform Cloudを活用しながら、今後はmodule化を進めて、効率的でスケーラブルなインフラ管理を目指しています。 Findy Toolsのインフラ改善 私が入社してからFindy Toolsのインフラ改善として、いくつか対応していきました。まずは、RDSのSSL/TLS証明書更新とAuroraのマイナーバージョンアップを開発環境から本番環境まで3日で実施しました。次に監視とオブザーバビリティの強化では、元々はインフラリソースをモニタリングしておらず、SentryのエラートラッキングとAPMのみでした。そこでDatadogでのインフラリソース(ECS、外形監視、CloudFront、RDS、イベントログ、WAF)、APMなどを対象に、アラートをTerraformで管理し、ダッシュボードを手動で運用するようになりました。普段見えていなかった部分がオブザーバビリティの向上によって可視化されていきました。 また、SLI/SLOの策定を進め、ページ表示速度やリクエスト成功率の目標を設定し、エラーバジェットとバーンレートの管理を進めていきました。SLOの振り返りは隔週で実施しており、アラートが発生した際に、開発メンバーと改善案を話し合えることは非常に重要だと感じています。 最後に、Rails serverやNode.js、MySQL8の開発環境の構築を改善し、Justfileを活用して自動化を進めました。JustはMakefileと比較すると、シンプルで直感的な構文で、シェルスクリプトに似ています。また、依存関係の管理が簡単なため、学習コストも低いです。これにより、開発メンバーはスピーディーに構築できるようになりました。以下フロントエンドのJustfileになります。 Frontend Justfile # Justfile for setting up development environment # Install Homebrew and essential packages install_homebrew: @echo "Installing Homebrew if not already installed..." @if ! command -v brew >/dev/null 2>&1; then \ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; \ else \ echo "Homebrew is already installed."; \ fi install_essential_packages: @echo "Installing essential packages..." brew install coreutils curl git # Configure Git configure_git: @echo "Configuring Git..." git config core.ignorecase false # Install asdf and Node.js install_asdf: @echo "Installing asdf if not already installed..." @if ! command -v asdf >/dev/null 2>&1; then \ brew install asdf; \ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc; \ else \ echo "asdf is already installed."; \ fi install_nodejs: @echo "Installing Node.js..." @if ! asdf plugin list | grep -q 'nodejs'; then \ asdf plugin add nodejs; \ else \ echo "Node.js plugin is already added."; \ fi asdf install nodejs asdf reshim nodejs # Install mkcert and create certificates install_mkcert: @echo "Installing mkcert if not already installed..." @if ! command -v mkcert >/dev/null 2>&1; then \ brew install mkcert; \ mkcert -install; \ else \ echo "mkcert is already installed."; \ fi create_certificates: @echo "Creating local certificates..." mkcert -cert-file localhost.pem -key-file localhost-key.pem localhost 0.0.0.0 hoge-web # Install npm packages install_npm_packages: @echo "Installing npm packages..." npm ci # Run all tasks all: install_homebrew install_essential_packages configure_git install_asdf install_nodejs install_mkcert create_certificates install_npm_packages これらの改善については、7月の弊社DevRelイベントでLTを行いましたので、まだご覧になっていない方はぜひスライドをご確認ください。 findy.connpass.com speakerdeck.com AWSセキュリティ周り向上 AWSセキュリティの強化策として、Security Hubの実装を検討しましたが、予想以上の導入工数と既存ダッシュボード機能の現状を考慮した結果、我々の要件により適した別のアプローチを模索することにしました。複数のSaaSセキュリティサービスを検討し、最終的にShisho Cloudを選定しました。Shisho Cloudは使いやすさとコスト面で現在のファインディ社の課題にマッチしており、現在はAWSセキュリティポリシーガイドラインを作成し、Embedded SREチームと協力して対応を進めています。 「Findy Team+」オブザーバビリティ周り強化 Findy Toolsで培ったオブザーバビリティやSLOの経験を活かし、Findy Team+のSRE支援も行いました。元々設定されていたDatadogのアラートはTerraformで管理されていなかったため、まず棚卸しをし、全てをTerraformでimport化しました。しきい値などは次のように環境変数で管理し、テンプレート化することで他のプロジェクトにも適用可能にしました。SLOの策定にはまだ改善の余地がありますが、今後はミッションクリティカルな領域にも取り組んでいき、開発メンバーと振り返りを実施していく予定です。 rds.alert.tf resource "datadog_monitor" "rds_cpu_alert" { name = "[${var.service_name}]rds_cpu_alert" type = "metric alert" query = "avg(last_5m):avg:aws.rds.cpuutilization{rds:${var.service_name}-${var.environment}} by {dbinstanceidentifier} > ${var.rds_cpu_critical_threshold}" escalation_message = "RDS CPU usage for ${var.service_name}_${var.environment} instance has exceeded ${var.rds_cpu_critical_threshold}%" notify_no_data = false notify_audit = false timeout_h = 1 include_tags = true monitor_thresholds { critical = var.rds_cpu_critical_threshold } message = <<-EOT @${var.slack_channel} EOT tags = local.combined_tags } 今期まだやりきれていないタスク DevSecOpsの推進に向けたセキュリティ基盤のさらなる整備 AWSコスト最適化 開発メンバー生産性の向上 開発環境 完全Docker化とJustfile化 ECS Arm化 Stg複数環境 自動化 デプロイ高速化 後半では、AWSコスト最適化や開発メンバーの生産性向上のために、さらなる効率化とやりやすさを追求し、インフラ管理や開発プロセスの改善を進めています。 まとめ SREチームの発足と今期の取り組みについて、簡単にご紹介させていただきました。チームの立ち上げからインフラの改善、セキュリティ対策まで、多岐にわたる課題に取り組んできましたが、まだやるべきことがたくさんあります。(Issueが100個以上あります) 今後も引き続き、SREチームとしてサービスの信頼性向上に努めていくのと同時にSREに興味のある方は、ぜひ一緒に働きましょう!カジュアル面談お待ちしております🙏 herp.careers findy-code.io findy-code.io
こんにちは。エンジニアの佐藤( @t0m0h1r0x )です。 今回は、弊社で現在進めている Emotion から CSS Modules への移行について紹介します。 移行の背景、検討した代替ライブラリ、そして最終的な決定について話していきます。 移行の検討理由 代替ライブラリの検討 Panda CSS Pigment CSS CSS Modulesへの移行 今後の展望 まとめ 移行の検討理由 弊社では現在、CSS-in-JSライブラリとしてEmotionを使用しています。ピュアなCSS記法を好むメンバーが多いので、EmotionのTagged Template Literal記法がチーム文化との相性も良く、これまで活用してきました。 一方で、フロントエンド開発フレームワークに Next.js を採用しており、そちらではApp Routerへの移行を進めています。 App RouterのメリットはやはりReact Server Components(RSC)の活用だと思います。RSCはユーザー体験と開発者体験の向上につながる重要な機能ですが、2024年9月現在、その仕様上EmotionでRSCをスタイリングできません。 このような背景から、RSCに対応できる新たなCSSライブラリの検討を始めました。 代替ライブラリの検討 代替ライブラリの選定にあたっては、パフォーマンスやAPIの使い勝手といった要素も大切ですが、チームとの相性も重要な要件としました。特に、Tagged Template Literalをサポートしていて、Emotionとの書き心地に互換性があることをポイントとしました。 Panda CSS Panda CSS は Chakra UI のチームが開発しています。CSSの記法としてObject LiteralかTagged Template Literalを選択できますが、後者には機能制限があるようです。 詳細については 公式ドキュメント を参照してください。 Pigment CSS Pigment CSS は Material UI のチームが開発しています。 こちらも要件と合致しそうなのですが、開発初期段階のためプロダクション利用には検討が必要です。 ちなみにPigment CSSは、最近リリースされたMaterial UI v6に、experimentalなopt-inとして組み込まれました。さらなる開発が期待できそうです。 CSS Modulesへの移行 上記の検討を踏まえ、弊社では一時的に信頼と実績があるCSS Modulesへの移行を決定しました。その理由は次の通りです。 プロダクトとチームの要件に合致 他ライブラリへの将来的な移行が比較的容易 一方でCSS Modulesの採用にあたっては、特に次の点に留意しています。 TypeScriptによる型定義 動的スタイリングの実装 仕様がメンテナンスモード 型定義には Happy CSS Modules を使用して、自動生成することで対応しています。 動的スタイリングについては、コード中にpropsベースのスタイリング実装が多くなかったことや、コンポーネントのルールを整備していたことで不要なcomponent targetingを予め減らせていたため、現時点では大きな支障は出ていません。 仕様についてはメンテナンスモードであるものの、長らくこの状態が続いていながら今の所大きな問題は起きていないため安定しているのではないかと思っています。 参考: Future of CSS Modules · Issue #187 · css-modules/css-modules · GitHub Interoperability across tools and support plain JS modules imports · Issue #1050 · webpack-contrib/css-loader · GitHub 今後の展望 CSSを取り巻く環境は日々進化しています。例えば、React v19からは<style>のホイスティングがサポートされる予定であり、それを活かした RESTYLE というライブラリも登場しています。 このような状況を踏まえ、当面はCSS Modulesへの移行を進めつつ、新たなライブラリの登場にも注目していきたいと思います。 まとめ EmotionからCSS Modulesへの移行は、弊社のフロントエンド開発環境を大きく変える重要な取り組みでした。 RSCとの互換性という課題はありましたが、暫定的な解決策を見つけつつ、より良い選択肢を模索し続けていきたいと思います。 弊社では一緒に働いてくれるメンバーを募集中です。興味を持っていただいた方は是非こちらのページからご応募お願いします。 herp.careers
はじめに Findyでデータエンジニアとして働いている開( hiracky16 )です。 この記事ではGoogle Cloudの製品であるCloud DLPを中心に弊社で取り組んでいるデータマスキングについて紹介します。 弊社はFindyやFindy Freelanceなど人材に関する事業を取り扱っているため個人データがより集まりやすい環境にあります。 ファインディの組織が日々拡大しサービス拡張していく中で、利用者の安全性を担保し、データにおけるリスクを低くするためのデータ基盤づくりが求められてきました。 データ基盤には事業部のデータを集約しているため、利用者にすべてを公開してしまうと運用を誤り、思わぬ事故につながる可能性が上がります。 ただ、閲覧できないと困る業務もあり、データの閲覧権限を絞りすぎてもリスクがあります。 今回は、個人データなどのセンシティブなデータを自動で検出・マスキングを行い、業務に必要な場合にのみ閲覧できる状態にする取り組みについてご紹介します。 権限周りの基本設計 マスキングの前に権限周りの基本設計を説明します。 データセットにはレイヤーを設けており、それぞれ次のようになっています。 source ... ローデータが入っているテーブル staging ... ローデータをBigQuery用に加工したテーブル intermediate ... CTEなどのテーブル mart ... 利用用途ごとに用意したテーブル まずはデータ基盤を利用するにあたり用途ごとにロールを定義しようと考えました。 用途以外のことができてしまうと誤操作によってデータを書き換えたり、消してしまったりするおそれがあるためです。 データの用途は大きく3つに分けることができ、特定のデータを定期的に見ることやBigQueryコンソールやDataformで自分のほしいデータを作ること、外部ツールにデータを連携することになります。 これらの利用用途ごとに権限を付与するためのロールを作りました。 また1ユーザーごとにロールを付与するのは大変なので、Googleグループを用意しあらかじめ付与しています。 こうすることでグループへの追加・削除によりロールの管理が比較的簡単な操作で可能になります。 更にデータマートに相当するデータセットは用途ごとに作りGoogleグループのメールアドレスをデータセットのIAMメンバーとして追加しておきます。 ロール できること Google Cloudプロジェクト上のIAMロール 対応するGoogleグループ 管理者 全てのデータセットに対して編集 プロジェクトレベルのオーナー - 編集者 source以外のデータセットへの編集、またDataformなどの周辺サービスの利用 プロジェクトレベルの「BigQueryユーザー」と「BigQueryデータ編集者」 editor (各データセットの)閲覧者 特定の mart_ で始まるデータセットの閲覧 プロジェクトレベルの「BigQueryユーザー」とデータセットレベルの「BigQueryデータ閲覧者」 mart_sales, mart_external_system 上記のようにデータセットごとにIAMロールを付与するためのTerraform Moduleを公開しているのでよかったらお使いください。 registry.terraform.io ポリシータグによる動的マスキング 基本的に個人データはsourceからstagingへの伝搬時にセンシティブなデータを省いています。 また上記の通り権限が絞れているので一見問題なさそうに見えますが、 mart データセットの中には業務システムに使うものもあり個人データが含まれます。 そういったデータをグループに属する全員が閲覧できる状態というのは望ましくありません。 このような場合には、カラムレベルでポリシータグを付与し、許可されたユーザーには通常のデータを、許可されていないユーザーにはマスキングされたデータを表示させています。 タグの付与はDataformのconfigで行っています。 次のように書くとテーブルが作られる際にタグを付与してくれます。 config { type: "table", "schema": "stg_hoge", "description": "ユーザーテーブル", "columns": { "id": "ユーザーのID", "email": { description: "メールアドレス", bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"] }, "tel": { description: "電話番号", bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"] } }, } ... マスキングのルールもいろいろなものがあります。 なお今回は試していませんが、BigQuery UDFをルールに追加できます。 cloud.google.com 動的マスキングの方法はわかりました。 ただ、個人データに対して曖昧な理解のまま運用してしまうと付与忘れや、付与しすぎて情報量が落ちてしまうおそれがあります。 そこで役立つのがCloud DLPです。 Cloud DLPによる個人データ検出 Cloud DLP(Data Loss Prevention)は、機密性の高いデータを検出、分類、保護するために設計されたGoogle Cloudのサービスです。 Cloud DLPにはBigQueryのデータをスキャンして個人データに該当するテーブル、カラムを検出してくれる機能が備わっています。 この検出を定期的に実行することによりポリシータグを付与する候補となるカラムを特定できます。 テーブルはサンプルですが、検査するとデータリスクが中程度〜高のカラムに個人データが含まれていそうなことが一目でわかるようになります。 以下は公式ドキュメントに載っていたイメージになります。 cloud.google.com DLP APIを用いてテキスト内の情報をマスキング ポリシータグを使ったマスキングは値全体をマスクしてしまいますが、ロングテキストの場合一部だけマスクしたいといったニーズが存在します。 例えば、商品レビューのテキストデータをポジネガ判定したい場合、テキスト全てをマスクしてしまうとポジネガ判定に使う情報が落ちてしまいます。 DLP APIを使うとテキスト中の個人情報をマスクできます。 DLP APIによるマスクの手順は「個人データの検出」と「データの匿名化」の2ステップがあります。 「個人データの検出」では事前に用意された検出器(INFO TYPE)を使い検出できます。 INFO TYPEは特定したい情報、例えば名前や電話番号、住所など情報の種類ごとに違います。 INFO TYPEはGCSに置いた辞書から自作でき、固有名詞にも対応できます。 下記が事前に用意されたINFO TYPEのリファレンスです。 cloud.google.com 「データの匿名化」は検出したINFO TYPEごとにどのように情報をマスクするかを定義します。 DLP APIにはPython ClientがあるのでこれをCloud RunにデプロイしてBigQueryからリモート関数で呼び出せるようにしています。 declare text string; set text = """ 私は山田太郎です。 本日はよろしくお願いします。 山田 090-0000-0000 tensyoku.taro@gmail.com """; select text, `function_dataset.dlp_api`(text) as masked_text; まとめ Cloud DLPの機能を使うことでマスキングする術をまとめてみました。 データ利活用が増えることは喜ばしいことですが、常にデータの扱いを気にしながらデータ抽出や分析するのにも限界があります。 これからもデータエンジニアとして安全に意思決定をサポートするデータ基盤を作っていきたいと思っています。 弊社ではデータ基盤を共に育てていくメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております🙏 herp.careers herp.careers
Findyでエンジニアをしている栁沢(@nipe0324)です。 今回は、Findyの名物企画である「 コントリビューション・オブ・ザ・イヤー2024中間発表 」の裏側を公開します。裏側を知り、キャンペーンをより楽しんでもらえたら嬉しいです。 キャンペーン期間中にXでシェア後にフォームから応募することで「Anker充電器(Findyオリジナルデザイン入り)」が抽選で当たるかも!? ぜひお申し込みください。 👇👇👇 コントリビューション・オブ・ザ・イヤー2024中間発表を試してみる コントリビューション・オブ・ザ・イヤーとは コントリビューション・オブ・ザ・イヤーの裏側 裏側①:コントリビューション・オブ・ザ・イヤーのランキング表示 裏側②:コントリビューション・オブ・ザ・イヤーのOGP表示 コントリビューション・オブ・ザ・イヤーを楽しんでください コントリビューション・オブ・ザ・イヤーとは コントリビューション・オブ・ザ・イヤーとは、Findyの名物企画の1つです。 1年間のGitHubのコントリビューション数やFindyユーザー内でのランキングを見ながら開発成果を振り返る期間限定のイベントです。 コントリビューション数を見ることで、自分が日々どのくらいGitHubで開発しているかを知ることができます。 コントリビューション数やランキングを見るにはFindy上で自分のGitHubアカウントを連携している必要があります。もしまだGitHubを連携してない方は こちら から連携してみてください。 過去5回ほど開催しており、多くの方に楽しんで頂けました。 過去のコントリビューション・オブ・ザ・イヤー 実際にXのシェアでは次のような声があり、開発の振り返りとして楽しんで頂けたようです。 ことしもがんばった 【yshrsmzさんの2023年の振り返り】 2023年にGitHubで4,341コントリビュートし、月間の最大は462(4月)、一日あたりの平均は13/日でした。 あなたも今年のGitHubでの活動をチェックしよう! https://t.co/4saXCthnEV #コントリビューション・オブ・ザ・イヤー2023 — せーい(CodingFeline) (@_yshrsmz) 2023年12月20日 草はやしきれなかったのが悔しい 【mogmetさんの2023年の振り返り】 2023年にGitHubで4,715コントリビュートし、月間の最大は663(2月)、一日あたりの平均は13/日でした。 あなたも今年のGitHubでの活動をチェックしよう! https://t.co/MzvBGuMw8k #コントリビューション・オブ・ザ・イヤー2023 — もぐめっと❄️ITイノベーター (@mogmet) 2023年12月21日 今回は、 「 コントリビューション・オブ・ザ・イヤー2024中間発表 」 ということで、2024年の1月から6月のコントリビューション数とランキングを振り返ることができます。 コントリビューション・オブ・ザ・イヤーの裏側 コントリビューション・オブ・ザ・イヤーの主要な機能について2つ紹介します。 裏側①:コントリビューション・オブ・ザ・イヤーのランキング表示 裏側②:コントリビューション・オブ・ザ・イヤーのOGP表示 裏側①:コントリビューション・オブ・ザ・イヤーのランキング表示 コントリビューション・オブ・ザ・イヤーでは、Findyユーザー内で「期間内のコントリビューション数のランキング」を表示しています。(ランキングの数字は上位の方のみ表示) コントリビューション・オブ・ザ・イヤーのランキング表示(※データはサンプルです) 実装にあたり、SQLでランキング表示を実現すると、クエリが複雑になりパフォーマンスも出しにくいという問題がありました。 そのため、Redisの ZREVRANK を採用しました。 ZREVRANKはソート済みセットのスコアが高いものから低いものに並べてデータを取得可能で、次のような形でシンプルにランキング表示を実装できます。 # ランキングの取得処理イメージ def contribution_ranking # zrevrankを使ってランキングを取得 ranking = redis.zrevrank(store_key, user.id) return nil if ranking.nil? # zrevrank は0始まりで順位を返すので、1を足して1位からの順位にする ranking + 1 end このように、Redisの機能をうまく利用することで、シンプルな実装で、ランキングの値を高速に取得しています。 裏側②:コントリビューション・オブ・ザ・イヤーのOGP表示 また、コントリビューション・オブ・ザ・イヤーでは、XでシェアしてもらったときにOGP画像を表示しています。 Xのポスト時のOGP表示(※データはサンプルです) Xのポスト上でOGP画像を動的に生成する流れは次のようになっています。 X上でOGP画像を動的に生成するシーケンス図 XからFrontend(Next.js)がリクエストを受けて、Next.jsのサーバーサイドレンダリング(SSR)の機能を使ってOGP画像のURLを返す OGP画像の生成は、内製のOGP画像生成サービスを利用して、APIの動的データをつかってユーザーに応じたOGP画像を生成している ちなみに、内製のOGP画像生成サービスは、Findy内でOGP画像を生成するマイクロサービスを用意しており、他機能のスキル偏差値やおみくじなどのOGP画像を生成するためにも使われている特徴的なサービスです。 また、今後の技術的な取り組みとしてNext.jsのApp Routerを活用することで、OGP画像の生成をNext.js上で実現できないかも思案しています🤔 コントリビューション・オブ・ザ・イヤーを楽しんでください 現在、「コントリビューション・オブ・ザ・イヤー2024中間発表」が期間限定で開催されています。 ぜひ、2024年上半期のコントリビューション数を振り返って、2024年後半のモチベーションにつなげてもらえると嬉しいです。 キャンペーン期間中にXでシェア後にフォームから応募することで「Anker充電器(Findyオリジナルデザイン入り)」が抽選で当たるかもしれません! 👇👇👇 コントリビューション・オブ・ザ・イヤー2024中間発表を試してみる
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 弊社では遠隔地フルリモートで働いているメンバーが多数おり、北は北海道から南は福岡まで、全国各地に点在しています。 本社は東京にあって関東在住のエンジニアも多数おり、遠隔地フルリモートの人数の比率で言うと半々くらいでしょうか。 実を言うと、弊社のフルタイム勤務でのエンジニアの遠隔地フルリモート勤務の第一号は私なのです。 2020年7月にJOINしてから4年以上、ずっと福岡から遠隔地フルリモートで働いていますが、第一号の私が結果を出すことで「出社・フルリモート関係なく成果が出るよね」と思ってもらうために、当初は本当に頑張りましたw 結果として弊社では、「ハイスキルなエンジニアであればフルリモートでも問題ない」という認識になり、遠隔地フルリモートで働くエンジニアが増えていきました。 そこで今回は、私がフルリモート勤務をする上で心がけていることを公開しようと思います。 それでは見ていきましょう! 心がけてることリスト とりあえず自分のtimesになんか書く わからないこと。上手くいったことは全力でアピールする メンションには最優先で反応する テキストと通話の使い分け とはいえ出社も大事だよね? まとめ 心がけてることリスト とりあえず自分のtimesになんか書く 弊社ではエンジニアを中心にSlackで自分自身のtimesチャンネルを持つようにしています。 timesチャンネルは一般的に使われている運用方法ですが、「開始します」「終了します」だけの書き込みになってしまっている人はいませんか? このtimesチャンネルの使い方というのが重要で、 とりあえず自分のtimesになんか書く ということを心がけています。 つぶやく内容は何でもいいです。無言よりは数万倍マシです。 フルリモート勤務だと出社メンバーの顔も、他のフルリモートメンバー同士の顔も見えないので、お互いに存在感を出すことが重要です。 そのため、自分自身に割り当てられたtimesチャンネルで好きなようにつぶやくことが、フルリモート勤務でのコミュニケーションの1つの形だと思っています。 作業ログ的に自分の作業をtimesに記録することもオススメです。作業途中に詰まった時などに、timesを見てくれた他のメンバーが助け舟を出してくれることがあります。 timesが無言なのはダメゼッタイ。 わからないこと。上手くいったことは全力でアピールする 自分が何に困ってるのか、何に苦しんでいるのかは、自分から発信します。 先ほど紹介した自分のtimesチャンネルに書いてもいいですし、そこから直接メンションして誰かに助けを求めるのもいいでしょう。 作業に詰まって1人でずっと悩んで結果的に1日潰しました。はオフィス出社でもそうですが、フルリモート勤務においては特に信頼を大きく失ってしまいます。 わからないことだけじゃなくて、解決したこと、上手くいったことは特に全力でアピールします。 嬉しいことは形に残ったほうがいいので、timesにガンガン書き込みます。 周りのみんなも全力で祝福しましょう。 わからないこと、上手くいったことといったような作業の進捗に関わる発信は都度行うようにしています。 メンションには最優先で反応する 何かしらの作業をしていても、自分へのメンションを優先してチェックします。 今の作業に集中したいなら、「あとで確認する」旨を相手に伝えたり、リアクションアイコンを付けます。 「メンション送ったのに反応が何もない」ということは、相手からしたら「無視されてる」のか「忙しくて見れてない」のかが分かりません。 まずは「あなたのメンションを見てますよ」ということを伝えます。 テキストと通話の使い分け テキスト、通話でのコミュニケーションを適切に使い分けることを心がけています。 テキストでのコミュニケーションだけではどこかしらで必ず限界がきますが、テキストにも形に残る、非同期でコミュニケーションできるといったメリットもあります。 これは誰が相手でも、自分がどれほどテキストコミュニケーションが上手いと思ってても、必ず限界があります。 あ、これ伝わってないなと察したり、認識が一致していないと感じたらハドルやZoomで繋いで通話をします。 その際、議事録的なものを書いて対面で話した内容のサマリを議事録として形に残します。その議事録を後で相手に送り、認識が合ってるかどうかを確認します。 議事録は必要があれば他メンバーが見える場所にも共有します。そうすることで何の話をしていたのか、何で困っていたのかを他のメンバーが把握できるようになります。 また、テキストは後々まで形に残るので、相手への感謝や称賛はテキスト、リアクションで送ります。 逆に文脈を口頭で伝えたほうがよい話、ネガティブな話は対面で、ハドルやZoomを使います。自分が言及されているのを他の人に見られたり、後々まで形に残るのは良い気分ではないです。 あと自分の場合は、不定期に自分のtimesチャンネルのハドルを開いて雑談をする「お茶会」を開いています。 なんか話したい、雑談したい、相談したいことがあるなど、動機は何でもOKです。エンジニア以外の職種の子が参加してくれることもあります。 とはいえ出社も大事だよね? ここまでフルリモート勤務での話を書いていましたが、やはり出社しての対面コミュニケーションに勝るものはありません。 遠隔地フルリモートで勤務していたとしても、1年に数回は出社して対面コミュニケーションを取るようにしています。 自分の場合は4ヶ月に1回程度、費用は会社持ちで1週間程度出社しています。 その期間は自分の作業よりも出社メンバーとの対面コミュニケーションを重視しています。 この期間での対面コミュニケーションにより、帰宅後のお互いのコミュニケーションのハードルが下がり、結果的に意思疎通がスムーズになります。 まとめ いかがでしたでしょうか? 今回の記事が、フルリモート勤務での悩み事に少しでも役に立てれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 2024年の2月末に弊社テックブログを開設してから半年が過ぎようとしています。 今年は上半期だけで31個の記事を投稿しており、テックブログを開設してから6月いっぱいまでで週に1~2記事のペースで投稿できています。 また総PV数は10万PV、はてブ数は1200を超え、多くの方に読んでいただいているようです。いつもありがとうございます! イベントでお会いした方や、弊社に応募していただき面接でお会いした方からも「テックブログ読んでます!」と言っていただけることが増えてきており、改めて技術広報の重要性を感じています。 そこで今回は、2024年上半期の弊社テックブログの振り返りと称しまして、2024年上半期の人気記事達を紹介します。 それでは見ていきましょう! 2024年上半期の人気記事 【エンジニアの日常】エンジニア達の自慢の作業環境を大公開シリーズ 開発生産性指標を向上させるためにやってはいけないアンチパターン 開発生産性を上げるために開発をする前に考えていること Findyの爆速開発を支えるテクニック Findyの爆速開発を支える「システムを守るテストコード」の実例3選 Wallaby.jsを使ってフロントエンド開発のテストを効率化しよう ファインディにエンジニアとして入社していいなと思ったこと3選 まとめ 2024年上半期の人気記事 【エンジニアの日常】エンジニア達の自慢の作業環境を大公開シリーズ tech.findy.co.jp 弊社テックブログの最初のターニングポイントとなった記事です。おそらくこのシリーズが出ていなかったら、総PV数が10万を超えることはなかったでしょう。 2月末にテックブログを開設してから1ヶ月程度が経った頃にPart1が公開され、想定以上の反響があったため、Part2、Part3と続けてシリーズ化された人気シリーズの1つです。 もともとテックブログを開設した理由の1つに、エンジニア採用を強化したいという狙いがありました。 採用を強化する上で技術的な発信は重要ですが、それと同じくらい文化の発信も重要だと考えており、まずはどんなエンジニア達が働いているのかを知ってもらいたいという思いからこのシリーズを企画しました。 おかげさまで多くの方に読んでいただき、上半期のPV数の3割はこのシリーズが占めています。 内容としましては、弊社エンジニアたちの自宅での作業環境を写真付きで紹介しており、ガジェットやキーボード、デスク周りのアイテムなどが紹介されています。 ちなみに記事のタイトルですが、タイトルを考えるのに行き詰まった私がChatGPTにタイトル案をいくつか生成してもらい、その中から選んだものですw いや〜生成AIって便利ですね! 開発生産性指標を向上させるためにやってはいけないアンチパターン tech.findy.co.jp 記事単体のPV数としては上半期1位の記事です。 開発生産性を向上するためにやったほうがいいことは多くの記事が発信していますが、こちらはその逆でアンチパターンを紹介しています。 一見、「そんなの当たり前やろ」と思うかもしれませんが、その当たり前をきちんと明記したことに価値があると思います。 やってはいけないことを理由付きできちんと説明できるからこそ、正しい方法を理解、実行できるのです。 開発生産性に興味関心がある方には是非一読していただきたい記事となっています。 開発生産性を上げるために開発をする前に考えていること tech.findy.co.jp 記事単体のはてブ数としては上半期1位の記事です。 こちらも開発生産性に関する記事で、実際にコードを書く前にやるべきこと、準備すること、考えることを紹介しています。 いかに速く、シンプルに、効率よくリリースしてユーザーに価値提供をするか、という視点で書かれており、開発において重要なポイントがまとめられています。 Findyの爆速開発を支えるテクニック tech.findy.co.jp 弊社は開発生産性、とりわけ開発スピードには非常に拘っています。 この開発スピードを継続し、更に速くするために弊社で実践しているテクニックをいくつか紹介しているのがこの記事です。 タスクの分解の仕方やPull requestの粒度、テストコードの考え方などをシンプルにまとめている記事となっています。 開発生産性の向上に着手したいけど何から着手したらいいのかわからない。という方には是非読んでいただきたい記事です。 Findyの爆速開発を支える「システムを守るテストコード」の実例3選 tech.findy.co.jp 先ほど紹介した「Findyの爆速開発を支えるテクニック」の記事で紹介したテストコードに関する内容を更に掘り下げた記事となっています。 実際のテストコードを交えて、具体的にどのようなテストコードでシステムを守るのかを説明しています。 実際に読んでみると、抜け落ちていた視点などもあるかと思いますので、ジュニアエンジニアの方にもシニアエンジニアの方にも是非1度読んでいただきたい記事です。 Wallaby.jsを使ってフロントエンド開発のテストを効率化しよう tech.findy.co.jp Wallaby.jsはフロントエンド開発において非常に便利なツールです。 多数のIDEに対応しており、ほぼリアルタイムに修正内容を反映しつつテストコードの実行結果を表示してくます。 この記事では、Wallaby.jsの使い方や設定方法、実際にどのように活用しているかを紹介しています。 フロントエンドのテストコードを書くのが苦手だったり、テストコードをもっと効率的に書きたい!と思ってる方にオススメの記事です。 ファインディにエンジニアとして入社していいなと思ったこと3選 tech.findy.co.jp 実際に弊社にJOINしてくれたエンジニアが、入社して1ヶ月程度経ってから感じたことをまとめた記事です。 JOIN直後のエンジニアが弊社の開発環境をどのように感じているのか、どのような点が良かったのかなど、長年弊社に在籍している自分からは気づかない視点もありました。 弊社に興味を持ってくれている方には是非読んでいただきたい記事となってます。 まとめ いかがでしたでしょうか? ここでは紹介しきれなかった記事も多数ありますので、それらも是非読んでみてください。 全体的に見て、開発生産性やフロントエンド関連の記事に対しての反響が大きかったように感じます。 下半期も引き続き、これらのトレンドを追いつつも技術的な挑戦を続け、社内の文化、雰囲気なども含めてテックブログを通じて発信できればと思います。 今後とも弊社テックブログをよろしくお願いします。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
ファインディ株式会社でフロントエンドのリードをしております 新福( @puku0x )です。 この記事では、ファインディで導入しているモノレポ管理ツール「 Nx 」について紹介します。 モノレポとは Nxとは Nxワークスペースの作成 Nxの機能 コード生成 変更検知 依存関係の管理 キャッシュ機構 自動マイグレーション まとめ モノレポとは モノレポは全てのコードベースを単一のリポジトリで管理する手法です。 monorepo.tools コードの共通化や可視化、ツール・ライブラリの標準化、一貫性のあるCI/CDパイプラインを構築できるといったメリットがあります。また、マイクロサービスと相性が良いとも言われています。 circleci.com ファインディでは主にフロントエンド系のリポジトリをモノレポとして運用しています。 アプリケーションとそれに関連するフィーチャー、UIライブラリがひとつにまとまっているため、複数のリポジトリを移動することなくコードを参照できます。 Nxとは Nx はモノレポ管理やアプリケーションのビルド、テストの実行、コード生成などの機能を備えた統合的なツールです。 nx.dev モノレポ管理ツールは他にも Lerna や Turborepo などがあります。アプリケーション開発において有用な機能が多くあることや、コミュニティが活発で継続的なメンテナンスが見込めること、前職で導入実績があったことなどがNxを選んだ理由です。 後述する「変更検知」や「キャッシュ機構」といった機能は、Pull Requestの粒度を細かくするファインディの開発スタイルと高い親和性があり、導入当初から私達の開発を支える頼もしいツールとなっています。 大手企業でも採用事例が増えており、Nxはモノレポ管理ツールとして有力な選択肢といえるでしょう。 https://npmtrends.com/lerna-vs-nx-vs-turbo (個人的に推していたOSSがここまで有名になったことには感慨深いものがありますね!) Nxワークスペースの作成 create-nx-workspace を実行するとワークスペースを作成できます。 Reactをはじめ、メジャーなフレームワーク用のプリセットもあるためすぐに開発を始められます。 npx create-nx-workspace@latest <ワークスペース名> --preset=react-monorepo --appName=<アプリケーション名> --bundler=webpack --e2eTestRunner=playwright --style=scss --nxCloud=skip 詳細は公式のチュートリアルをぜひご覧ください。 nx.dev Nxの機能 コード生成 nx generate コマンドでプロジェクト(アプリケーションやライブラリ)を作成できます。 npx nx generate @nx/react:application --name=<アプリケーション名> --directory=<ディレクトリ> --routing=false --e2eTestRunner=playwright --projectNameAndRootFormat=as-provided npx nx generate @nx/react:library --name=<ライブラリ名> --directory=<ディレクトリ> --bundler=rollup --unitTestRunner=jest --projectNameAndRootFormat=as-provided nx generate で実行できるGeneratorは自分で作ることもできます。 nx.dev ファインディではフィーチャー用のファイル一式を生成するGeneratorを作って開発を効率化しているチームもあります。また別の機会に紹介できればと思います。 変更検知 Nxはプロジェクト間の依存関係を自動的に算出する機能を備えています。 npx nx affected --graph を実行すると次のように依存関係を可視化できます。 npx nx affected --target=build のように指定すると、変更のあったプロジェクトとそれに依存する他のプロジェクトを全てビルドしてくれます。 nx affected は変更されたコードに関するプロジェクトのみ実行する 個人的なおすすめは、npm-scriptsやCI上で実行するコマンドを nx affected ベースにすることです。 "scripts": { "build": "nx affected --target=build", "test": "nx affected --target=test", "lint": "nx affected --target=lint", ... }, 必要なタスクのみ実行されるためスピーディーに開発できます。 依存関係の管理 Nxが持つプロジェクト間の依存関係はLintルールにも応用されます。 ファインディでは、 @nx/enforce-module-boundaries ルールを適用し、意図しない依存関係の逆転が起こらないように制御しています。 nx.dev 具体的には、各プロジェクトに次のようなタグを設定し、 { " name ": " utils ", " sourceRoot ": " libs/utils/src ", " projectType ": " library ", " tags ": [ " scope:shared ", " type:util " ] , ... } - apps/ - app1 (scope:app1) - app2 (scope:app2) - libs/ - app1/ - feature-dashboard (scope:app1, type:feature) - ui (scope:app1, type:ui) - app2/ - feature-user (scope:app2, type:feature) - ui (scope:app2, type:ui) - utils (scope:shared, type:util) .eslintrc.json に対応するルールを設定しています。 " @nx/enforce-module-boundaries ": [ " error ", { " allow ": [] , " depConstraints ": [ { " sourceTag ": " scope:shared ", " onlyDependOnLibsWithTags ": [ " scope:shared " ] } , { " sourceTag ": " scope:app1 ", " onlyDependOnLibsWithTags ": [ " scope:shared ", " scope:app1 " ] } , { " sourceTag ": " scope:app2 ", " onlyDependOnLibsWithTags ": [ " scope:shared ", " scope:app2 " ] } , { " sourceTag ": " type:feature ", " onlyDependOnLibsWithTags ": [ " type:ui ", " type:util " ] } , { " sourceTag ": " type:ui ", " onlyDependOnLibsWithTags ": [ " type:ui ", " type:util " ] } , { " sourceTag ": " type:util ", " onlyDependOnLibsWithTags ": [ " type:util " ] } ] } ] 設定したルールを図にするとこのようになります。 scope がプロジェクト間の依存関係、 type が内部のレイヤーの依存関係を表します。 @nx/enforce-module-boundaries ルールが設定されたプロジェクトでは依存してはいけないモジュールに対してエラーが表示されます。 大規模なコードベースの管理においては、モジュール同士の依存関係の制御が非常に重要であり、こういった「かゆいところに手が届く」機能を持っていることがNxの魅力でもあります。 キャッシュ機構 Nxは一度実行されたコマンドのキャッシュを保持しており、同じコマンドが実行された場合にキャッシュから結果を再現する機能を持っています。 nx.dev また、関連サービスである「 Nx Cloud 」のリモートキャッシュ機能を有効にすると大幅なCI高速化が可能です。 実際にファインディでは、キャッシュの活用で毎月1,000時間以上のCI時間を削減できました。 自動マイグレーション Nxには Codemod や Angular CLI の ng update と似たコマンドが備わっています。 nx.dev npx nx migrate latest npx nx migrate --run-migrations nx migrate を実行すると、Nx本体と各種プラグイン、 react や eslint 、 typescript などの依存ライブラリ・ツールがまとめて更新されます。 バージョンアップに伴うマイグレーションは手動で対応すると大変ですが、Nxでは自動化されています。メンテナンスの手間が省けると同時に属人化も抑えられるため重宝しています。 まとめ この記事では、Nxの概要と基本的な機能について紹介しました。 Nxは単なるモノレポ管理ツールに留まらず、「開発者体験の改善」や「開発生産性の向上」といったポテンシャルを秘めています。 ✨✨✨ Nxはいいぞ! ✨✨✨ Nxはいいぞおじさんから伝えたいことは以上です。 より詳細な活用法やNx Cloudの高度な機能については、今後の記事で取り上げる予定ですのでご期待ください。 ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 突然ですが皆さんは、開発をするうえで欠かせないツールやOSSはありますか? キーボードやマウス、マイクといった物理的なツールは机を見ればわかりますが、他のエンジニアがどういったツールを使って効率化しているかは、その人の画面を見ないとわかりません。 そのため、他のエンジニアがどういったツールを使って効率化しているのか、実は意外と知らないということが多いのではないでしょうか? そこで今回は 推しツール紹介 と題して、弊社エンジニア達が日々の開発業務で愛用しているツールやOSSを紹介していきます。 それでは見ていきましょう! 推しツール紹介 戸田 git-cz git-cz-for-api-developer 新福 Nx vscode-spell-checker 森 Rectangle Hammerspoon Vimium まとめ 推しツール紹介 戸田 git-cz まず紹介したいのがgit-czというツールです。 github.com このツールはnpmのパッケージで、ステップに沿って選択、入力を行うことでコミットメッセージのフォーマットを統一することが可能になります。 パッケージをインストールしてコマンドを実行すると、cliで次のような出力が表示されます。 hoge@fuga Piyo % npx git-cz cz-cli@4.3.0, @commitlint/cz-commitlint@19.2.0 ? Select the type of change that you're committing: (Use arrow keys) ❯ feat: A new feature fix: A bug fix docs: Documentation only changes style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) refactor: A code change that neither fixes a bug nor adds a feature perf: A code change that improves performance test: Adding missing tests or correcting existing tests ここでコミットの種類を選択します。 機能追加、バグfix、ドキュメント修正などの選択肢を選び、その後にコミットメッセージを入力すると、自動的にコミットメッセージが作成されます。 選択肢だけではなく、コミットメッセージの内容を入力するステップもあり、全部のステップを通ると自動的にコミットメッセージが作成されコミットを実行します。 hoge@fuga Piyo % npx git-cz cz-cli@4.3.0, @commitlint/cz-commitlint@19.2.0 ? Select the type of change that you're committing: docs ? What is the scope of this change? (See README for more details; e.g. project name): piyo ? Write a short, imperative tense description of the change: (max 188 chars) (13) update readme ? Provide a longer description of the change (press enter to skip): ? Are there any breaking changes?: No ? Does this change affect any open issues?: No ✔ Preparing lint-staged... ✔ Running tasks for staged files... ✔ Applying modifications from tasks... ✔ Cleaning up temporary files... [test-git-cz aaaaaaa] docs(piyo): update readme 1 file changed, 1 insertion(+), 1 deletion(-) 弊社では各リポジトリに導入しており、コミット時に実行することでコミットメッセージのフォーマットの統一を行っています。 フォーマットが統一されているため、リリース時のリリースノートを自動生成したり、リリース内容の分類を自動で行ったりすることが容易になります。 git-cz-for-api-developer git-czをForkして、API開発者向けにカスタマイズしたものもあります。 github.com こっちのツールを利用してコミットメッセージを作成することで、SemanticVersionに対応したコミットメッセージを作成できます。 hoge@fuga Piyo % npx git-cz-api ? Select the release type of change that you're committing: patch: patch update ? Select the type of change that you're committing: ✏️ docs: Documentation only changes ? Write a short, imperative mood description of the change: [-------------------------------------------------------------] 49 chars left patch-docs: update readme ? Provide a longer description of the change: fix hoge fuga ? List any breaking changes BREAKING CHANGE: ? Issues this commit closes: [git-cz-test aaaaaaaaa] patch-docs: ✏️ update readme 1 file changed, 1 insertion(+), 1 deletion(-) hoge@fuga Piyo % git log commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (HEAD -> git-cz-test) Author: test <example@gmail.com> Date: Wed Jun 26 17:27:10 2024 +0900 patch-docs: ✏️ update readme fix hoge fuga 弊社ではAPIを提供しているリポジトリで導入しています。 コミットメッセージのフォーマットが統一されているため、SemanticVersionに対応したリリースノートを自動で作成し。major updateがある場合に一目でわかるように仕組み化しています。 興味がある方は是非試してみてください。 新福 フロントエンドTech Leadの新福( @puku0x )です。好きなツールを発表します。 Nx 一番は何と言っても「Nx」です。社内のフロントエンド系のリポジトリのほぼ全てに導入しました。Nxのコア機能自体はフレームワーク非依存であるため、バックエンド系のリポジトリに導入される日もそう遠くないでしょう。 github.com 元々は前職でCRAに代わるツールを探していたことがきっかけで触れるようになりました。今ではCI高速化に欠かせない存在となっています。Nxはいいぞ。 余談ですが、Nxで作成したプロジェクトには、VS Code拡張として「vscode-jest-runner」が推奨されています。 github.com ファイル単位でテストを実行できるので、Wallaby.jsと同じぐらい重宝しています。 Wallaby.jsをどのように活用しているか気になった方はこちらの記事もご覧ください。 tech.findy.co.jp vscode-spell-checker VS Code拡張については他にも「vscode-spell-checker」がオススメです。タイポの検出に一役買ってくれます。 github.com 設定を変更すれば、よくある英単語の他にも技術用語や固有名詞などもチェックできます。企業名やサービス名を登録しておけば早い段階でミスに気付けるため便利です。 { " version ": " 0.2 ", " language ": " en ", " ignorePaths ": [] , " dictionaries ": [ " en_US ", " project-words ", " softwareTerms ", " misc ", " companies ", " typescript ", " node ", " html ", " css ", " bash ", " npm ", " powershell " ] , " dictionaryDefinitions ": [ { " name ": " project-words ", " path ": " ./.cspell-project-words.txt ", " description ": " Project Words Dictionary ", " addWords ": true } ] } 直近のPRでのタイポに心当たりのある方はぜひ導入しましょう。 森 2024年6月に入社しました森 @jiskanulo です。 できるだけキーボードから手を離さずに作業を続ける、という観点で私が利用しているツールをご紹介します。 Rectangle Rectangle はウィンドウの移動、リサイズをキーボードショートカットやドラッグ移動で行うことができるMacOS用のアプリケーションです。 操作しているウィンドウをモニター左半分や右半分にリサイズする、最大化最小化をする、複数ディスプレイを接続している場合に別ディスプレイへ送る、ということができます。 私の場合は次のようにショートカットを設定しています。 ショートカット ふるまい Ctrl + Shift + Alt + h ウィンドウをモニター左半分にリサイズ Ctrl + Shift + Alt + l ウィンドウをモニター右半分にリサイズ Ctrl + Shift + Alt + j ウィンドウをモニター中央半分にリサイズ Ctrl + Shift + Alt + s ウィンドウをモニター中央に配置 Ctrl + Shift + Alt + k ウィンドウを最大化 Ctrl + Shift + Alt + ← ウィンドウをモニター左上にリサイズ Ctrl + Shift + Alt + → ウィンドウをモニター右下にリサイズ Ctrl + Shift + Alt + ↓ ウィンドウをモニター左下にリサイズ Ctrl + Shift + Alt + ↑ ウィンドウをモニター右上にリサイズ Ctrl + Shift + Alt + n ウィンドウを次のディスプレイに移動する Ctrl + Shift + Alt + p ウィンドウを前のディスプレイに移動する Hammerspoon Hammerspoon はツール操作を自動化するためのMacOS用のアプリケーションです。 キーボードショートカットの組み合わせでアプリケーションを操作、alertの実行などをLuaを記載して定義できます。 主に ターミナル Alacritty とメモツールの Obsidian を起動、最小化、最大化するショートカットを登録しています。 Gitの操作やコマンド実行したいときにAlacrittyを画面最大化しコマンドを実行終えたら最小化、メモを残しておきたいことがあればObsidianを起動してメモを記述し元の作業に戻る、というように使っています。 ショートカット ふるまい Ctrl + Command + 6 Alacrittyを全画面に表示、もう一度押すことで最小化 Ctrl + Command + 7 Obsidianを全画面に表示、もう一度押すことで最小化 Vimium 最後に Vimium です。これは名前の通りにViのキーバインドのようにキーボードだけでブラウザを操作するGoogle Chrome拡張機能です。 ページ上のリンク要素を表示してキー入力で開く、ブラウザ履歴の戻る進む、前後のタブに表示を切り替える、ブックマークを検索してタブを開くなどの操作が行えます。 ブラウザ履歴の操作は標準のショートカットでも可能なのですが、Vimiumの設定で右手だけで無理なく操作が行えるようにしているのでインターネット閲覧が快適になります。 とくにリンク要素の表示機能はマウスカーソルを細かく操作せずにリンク要素を開くことができるので重宝しています。 ショートカット ふるまい f リンク要素の一覧を表示、さらに表示されたキーを押してリンク先に遷移 Shift + f リンク要素の一覧を表示、さらに表示されたキーを押してリンク先を別タブで開く Shift + h ブラウザ履歴を戻る Shift + l 前のタブを表示する Shift + j 次のタブを表示する Shift + k ブラウザ履歴を進む まとめ いかがでしたでしょうか? 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは。 Findy Freelance の開発をしている中坪です! この記事は 自慢の作業環境を大公開シリーズ の Part 5 になります。 今回はそれぞれ住む場所や普段担当するプロダクトが異なる 3 名のエンジニアの作業環境を紹介します! 作業環境を大公開 中坪 まずは名古屋からフルリモートワークをしている中坪の作業環境です。 デスク全体はこのようになっています。 デスクは FlexiSpot EF1 を使っています。 ボタン 1 つであらかじめ設定しておいた高さに自動で昇降してくれるので、気軽に立ち座りを繰り返すことができます。 ディスプレイは LG 35WN75C-B を使っています。 シンプルに画面が広くて作業しやすい点とデスクのサイズにちょうどよく収まっている点が気に入っています。 机の上、左側にはポモドーロタイマーと Amazon Echo Show があります。 このポモドーロタイマーは振るとカウントダウンが開始されて、90 度倒すと止まります。 特に集中して作業したいタイミングで使います。この記事もこのタイマーを使って書いています。 Echo Show は主にエアコンを操作したり、ラジオをかけたりするのに使っています。 「アレクサ。エアコンの温度 25 度にして」などと言うとその通りに設定してくれるので、リモコンを使わずに済むのが便利です。 ラジオは radiko で RaNi Music♪ をよくかけています。 音楽だけをずっとかけてくれるのがお気に入りポイントです。 デスクの右側には Anker 737 MagGo Charger があります。 毎日 iPhone、AirPods、Apple Watch を使っているのですが、それらすべてを充電できます。ワイヤレスって便利ですね。 キーボードは Keyball61 をメインで使っています。 見た目の通り、トラックボール付きの分割キーボードで、ホームポジションから全く指を動かさずにマウス操作ができるため、とても気に入っています。 一度これに慣れると、普通のキーボードに戻れないという感覚があります。 慣れていないはんだ付けに苦労しながら組み立てたので愛着も湧いています。 キースイッチは Kailh Box Silent Pink を使っています。押下圧約 35g で適度に軽く、静音性も高いので気に入っています。 また最近、 torabo-tsuki(M) という無線接続のマウスボール付き分割キーボードを組み立てました。 まだ、仕事で使えるほどキー配置と操作に慣れていないので、プライベートで練習している最中です。 以上、中坪の作業環境紹介でした! 嶋村 Findy Team+ のバックエンド開発を担当している嶋村です! 現在は出社とリモートワークのハイブリッドで勤務しており、作業環境はこのようになっています。 Macbook をノート PC スタンドに置き、モニタ 2 枚を配置しています。 それぞれ用途としては、Mac が Slack 用、横置きモニタがエディタ用、縦置きモニタがブラウジング用といった感じです。 Mac はノート PC スタンドの上にあるため基本的に位置は固定していますが、2 枚のモニタはそれぞれモニターアームで縦横の向きや位置などは自由に動かせる形になっています。 位置の調節がメインの用途ですが、スタンドが不要になって下のスペースが空くのでモニターアームは重宝しています。 マウスは無線のものを充電次第で交換しながら使っています。 左は安めで買った静音のマウスで、小さくクリック音が静かなのでオフィスへ持ち込むのに適しています。 右はロジクールの G Pro X Superlight で、その名の通り軽くて持ちやすいです。 また、普段 PC でゲームをしているため、大きめなマウスパッドを使用しています。 キーボードは HHKB Professional Type-S の無刻印モデルを使用しています。 7~8 年使っていて色が少々汚いのはご容赦ください。 奥に見えるのは Realforce GX1 で、デスクトップ PC 用途です。 静電容量無接点式の打鍵感が気に入っており、ずっと Realforce か HHKB がメインです。 あとは奥にチラッと映っていましたが、水を入れるだけで使える陶器の加湿器を置いています。 加湿効果としては通常の加湿器には及びませんが、電源不要で水を入れ替えるだけでよいのと、見た目がかわいいので気に入っています。 以上、嶋村の作業環境でした! 松本 Findy のフロントエンド開発を担当している松本( @bennkyougirai )です。普段は福岡からリモートワークをしています。まず私の作業環境の全体像はこんな感じです。 デスクは電動昇降式で FlexiSpot のフレームを使っています。 ディスプレイは DELL の 4k モニタを使っています。自分にとっては少し広すぎたので、次回はもう少し小さいものを選びたいです。 モニターにはモニターライト( Quntis デスクライト モニターライト バーライト )を取り付けています。コンパクトで場所を取らない、それでいて明るさも十分です。価格がお手頃なのも良いです。 キーボードは Ultimate Hacking Keyboard の分割キーボードを使っています。左右のキーボードにはオプションパーツを装着できて、左にはマウスクリックボタン、右にはトラックパッドを追加しています。キーボードの設定の自由度も高くて、カスタマイズしやすいのが特徴です。 マウスは MX Ergo と Apple Magic Trackpad を使っています。メインは MX Ergo を使っていて、Apple Magic Trackpad はマウスジェスチャーや Miro のようなスクロール操作が必要なアプリで使用しています。 業務での通話には、 OpenComm を使っています。長時間使用しても疲れづらく相手に届く音質も良いので気に入っています。私の使用しているのは 1 つ古い型ですが、最新のものも良いものが出ているので興味がある方は是非チェックしてみてください。 まとめ キーボードなどもそれぞれ個性的でこだわりが感じられました! 個人的には松本さんと嶋村さんのキーボードを見て、バックライト付きのキーボードにロマンを感じました。 また、ノート PC をスタンドに置いて使うスタイルも試してみたいと思いました。 ブログを読んでくださっている皆さんの作業環境構築の参考になれば幸いです! 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは!ファインディ CTOの佐藤( @ma3tk )です。 表題の通り、約1年半ほどの期間をかけて「エンジニア組織を強くする 開発生産性の教科書 ~事例から学ぶ、生産性向上への取り組み方~」(以降、開発生産性の教科書)という本を執筆しました。 本日(2024年7月11日)発売となりましたので、改めて「開発生産性」に対する思いをお伝えしたり、本の内容の一部をご紹介したいと思います。 「開発生産性の教科書」のご紹介 エンジニア組織を強くする 開発生産性の教科書 本の概要は次のとおりです。 項目 詳細 タイトル エンジニア組織を強くする 開発生産性の教科書 ~事例から学ぶ、生産性向上への取り組み方~ 著者 佐藤 将高、Findy Inc. 発行 技術評論社 定価 2,860円(税込) 発売日 2024年7月11日 ISBN 978-4297142490 購入 Amazon / 楽天ブックス 全国書店、その他オンライン書店 電子版 Gihyo Digital Publishing / Amazon / 楽天ブックス 全国書店にてお買い求めいただけますので、是非チェックしてみてください。 そもそもなぜ本を執筆しようとしたのか 元を辿ると、2019年末頃から Findy Team+ (当時はFindy Teams)というサービスを僕が開発し始めた時に遡ります。 「エンジニア組織で困っていることってなんですか?」 この問いをおおよそ20〜30社のCTOやVPoE、開発部長やEMの皆様とお話してきました。 エンジニア組織課題を深堀りさせていただく中で、よりよい組織を作っていきたいという思いを受け取りました。少子高齢化や開発内製化の動きを受けエンジニア採用が難しくなる中で、在籍しているメンバーの技術力を向上し、組織の開発生産性を向上させることに興味関心をいただきました。 「何をどうしたら組織が良くなるのかがわからない」 「生産性を上げる必要があるが、初手に困っている」 お伺いする中で、開発生産性の向上に直結する打ち手で迷うことが多いと学びました。ファインディでも開発生産性の向上をどう実現するか、Findy Team+のサービス利用者の悩みを解決するお手伝いをさせていただいたく上でどう価値提供ができるかを模索し続けてきました。 「開発生産性」の理解が難しいように感じてしまう サービスを通じた価値提供を続ける中で自分自身が感じたことは、「開発生産性という言葉は多義語で、どう定義するといいのかわからない」ということでした。 開発生産性についてずっと調べ続けていくと、Four KeysやSPACEといった概念が出てきて混乱したり、「数値化して本当にエンジニアにとって嬉しいのか?」というような疑問を自分自身でも考えるようになりました。今となっては理解が進みましたが、初学のタイミングでは整理に時間を要しました。同じように難しく感じてしまう方もきっといらっしゃると思います。 開発生産性についてどこかで学んだことがある方は多くはないはずです。1年ほど前からエンジニアの方を始め、プロダクト開発に関わる様々な方・経営者の方に開発生産性に関する知見を共有するためには本を書くことで「開発生産性に対しての理解を向上する」ことが実現できそうであると思い立ちました。 今回の本では、「開発生産性」という言葉の難しさを少しでも紐解き、どんな組織でも取り組みやすい入門書として出版するに至りました。 「開発生産性を上げるために大事なこと」を多くの人に知ってもらいたい Findy Team+のサービスをリリースする中で、「監視されるのではないか?」「数値を可視化するリスクがあるのではないか?」というご意見が特に多いです。 本書によって開発生産性を向上させるための認識を統一し、誤解を減らしたいと思っております。本書の中にも「監視するのではなく、認識を揃える」という内容も記述しています。 組織の定量化にフォーカスが当たりがちですが、開発生産性を上げて顧客に価値を多く提供することや、もっと言えば売上やKPI向上へつながるような開発に集中できることが大事だと思っています。そのため、定量化そのものよりも定量化して過去と比較することで「どこに課題がありそうか?」を知るための道しるべのようなものかと思っています。 開発生産性指標を向上させるためにやってはいけないアンチパターン - Findy Tech Blog の記事にも書いているように、数値に影響しないようにハックをすることではなく、現在のプロダクト開発においてどこがボトルネックかの目星をつけ、定量的にすることで他者との認識を揃えることが本質だと思っています。 数値だけを追ってしまうと監視につながってしまいかねませんし、数値に現れにくい「社内のメンバーの積極的なヘルプ」や「積極的なミーティングのファシリテーション」などを誰もやらなくなってしまいます。これでは本末転倒ですね…! こういった誤解や誤用があるため、本書によってそれを少しでも減らしたいと考えています。そして、これまで以上に事業貢献につながる開発ができる世の中で溢れてほしいと考えています。 本書の特徴:入門から実践まで網羅している教科書であること 改めて、本書の特徴としては大きく3つあります。 1. 体系的に整理された開発生産性の知識が学べる 前述したようにFindy Team+の開発を通じて、プロダクトオーナーとして「開発生産性」について色々調べてきました。しかし、「開発生産性」について体系的にまとまっているものがあまりなかったため、改めて自分の理解度向上も兼ねてまとめなおしました。 2. 実践への第一歩として、始めやすさにフォーカスした 海外の訳書などはアカデミックに研究が重ねられており、非常に良質な本があります。特に、 LeanとDevOpsの科学 は「開発生産性」について学ぶうえで是非読んでほしい一冊です。一方でどう始めるとよいのかについて自分はもっと情報が欲しかったこともあり、「開発生産性の教科書」は取っ付きやすさを大事にし、具体的にどうするといいのかを私自身の実体験や企業事例を交えながらなるべく読みやすい言葉遣いで記載しています。是非どちらも読んでいただくと「開発生産性」に対する理解が深まると思います。 3. 成功へのヒントとして事例を5社集めまとめた また、ファインディ社を含め5社の事例を集めました。 BuySell Technologies社:生産性の高さをIR資料に掲載し、社内外での評価を高めたことで、エンジニア採用にも好影響を与え、候補者からの関心を引いたお話 ツクルバ社:開発生産性を向上させるための基盤を作ったことで、iOSアーキテクチャの改修プロジェクトを成功させ、変更行数の削減やサイクルタイムの短縮を実現したお話 クラスメソッド社:開発生産性を向上させるための予算獲得や施策実行をしたことで、エンジニア組織全体のモチベーションも向上し、エンジニアリングの効率化と品質向上を実現したお話 ワンキャリア社:SPACEフレームワークの実現や毎日のリリース体制への移行を進めたお話 ファインディ社:CI時間の短縮やテストコードの拡充によるサービスの安定性と開発フローの改善の話 具体的にどう進めるとどんな効果があるかについても読める一冊に仕上げております! また、執筆にご協力いただいた各社のご担当者様に、心より感謝申し上げます。 開発生産性の向上とこれから 本記事では開発生産性の教科書の一部をご紹介させていただきました。 開発生産性を向上することで、個人の市場価値も上げられたり、組織のKPI/売上がよりよいものになるだけではなく、組織そのものの雰囲気がよくなることにもつながってくるはずです。あくまでも数値は健康指標として扱いながら、課題を見つけ出し解決に向けて進めることが大事だと思っています。 ファインディは「挑戦するエンジニアのプラットフォームをつくる」というビジョンの元、様々なエンジニアの皆さまやエンジニア組織においてより前向きに挑戦できる環境を一緒に作れたらと思っています。 改めて、今回の本を執筆するにあたりご協力いただいた方・編集の皆様、ありがとうございました。「開発生産性の教科書」が皆様の挑戦に役立てられたら嬉しいです。是非興味を持っていただけたらお手元にとっていただけると幸いです。 購入は以下からどうぞ! Amazon 楽天ブックス 全国書店、その他オンライン書店 また、こういったイベントもありますのでよかったらご参加どうぞ〜! d-plus.connpass.com
こんにちは、ファインディ株式会社でフロントエンドのリードをしております 新福( @puku0x )です。 この記事では、 IT/Webエンジニアの転職・求人サイト Findy のメッセージ画面の改善についてご紹介します。 メッセージ画面の課題 メッセージ画面の改善 Apollo Clientキャッシュの利用 読み込み画面の条件修正 ページ設計の最適化 まとめ メッセージ画面の課題 Findyのメッセージ画面は数年前にデザインを刷新しました。 現在では、3種類のメッセージを表示するようになっています。 通常のマッチングのメッセージ プレミアムスカウトのメッセージ Findyからのメッセージ 機能拡充される一方で「読み込みが多い」「画面遷移がサクサク動くようにして欲しい」との声をいただく機会が増えていきました。 実際に触ってみると確かに読み込み画面が頻繁に表示され、画面遷移に時間がかかっていることがわかりました。 メッセージ画面の改善 Apollo Clientキャッシュの利用 最初に取り組んだのはキャッシュの利用です。 Findyのフロントエンドには既にApollo Clientが組み込まれていたので、データ取得の際に fetchPolicy: 'cache-and-network' を指定して体感速度の向上を狙いました。 www.apollographql.com この改修により、ページ切替時の読み込み時間(ローカル環境)は約1,200ms→約900msと高速化されました。 読み込み画面の条件修正 当時の実装では、キャッシュの有無に関係なく読み込み画面を表示するようになっていました。 新しい実装では、読み込み中かつキャッシュが無い場合のみに修正しています。 const { data , loading } = useQuery(..., { fetchPolicy : 'cache-and-network' } ); < Loading isLoading = { loading && !data } /> この改修では、ページ切替時の読み込み時間への直接的な影響はありませんが、体感時間は最大で300ms(読み込み画面のアニメーションの再生時間)ほど削減されていると思われます。 ページ設計の最適化 当時の実装では、前述した3種類のページを個別のファイルで実装し、内部にメッセージの一覧と詳細コンポーネントを持つという構成でした。 このため、ページ遷移の度に一覧と詳細コンポーネントの両方が再描画され、体感速度に課題を残していました。 解決にはページ設計の見直しが必要ですが、 Layouts はFindyのフロントエンドがまだApp Routerに移行できていないため利用できず、 getLayoutパターン も画面全体の再描画を防ぐことが難しいため見送りとなりました。 手詰まりかと思われましたが、他のページで採用されたCatch-all Segmentsの実装を参考に、Optional Catch-all Segmentsを使った実装が今回の要件に合致することがわかったため採用することにしました。 nextjs.org 新しい実装では、 [[...keys]]/index.page.tsx に3種類のページ実装が集約され、ページ遷移の際はメッセージ詳細コンポーネントのみが差し代わるようになっています。 この改修により、メッセージ一覧の不要な読み込みが削減されたため、ページ切替時の読み込み時間(ローカル環境)はメッセージ詳細のキャッシュが無い場合でも約500ms、キャッシュがある場合は読み込み時間をほとんど感じさせないほど大幅に高速化されました。 まとめ キャッシュの活用やページ設計の見直しにより、メッセージ画面のパフォーマンスを向上させることに成功しました。 改善できて嬉しい一方、Optional Catch-all Segments自体はPages Routerの基本的な機能でもあるので「よく調べてから実装していれば...」と反省する点もあります。 ドキュメントはちゃんと読みましょう(自戒)😇 メッセージ画面以外についてもパフォーマンス改善を進めて参りますので、今後もよろしくお願いします。 今回は採用を見送りましたが、App Router移行やReact 19の新機能を活用して更に快適に動作するフロントエンドが実現できればと考えております。 ご興味のある方・挑戦してみたい方はぜひ↓のリンクからご応募ください。私達と一緒にFindyをより良いサービスにしませんか? ファインディは積極的にエンジニアを採用しています。CI/CD を始め、Four Keys、開発生産性、技術トレンド、転職市場など興味のある方は、お気軽にカジュアル面談を受けてみてください。 ファインディの採用情報はこちら ↓ herp.careers
こんにちは。 2024/05よりファインディ株式会社にデータエンジニアとして入社した田頭( tagasyksk )です。本記事では、データ変換サービスであるDataformについてその活用方法や導入後の効果についてご紹介します。 弊社では、現在次のような構成でデータ基盤を構成しており、BigQuery内でのデータ変換にDataformを利用しています。 この構成を踏まえてご覧いただければ幸いです。それでは見ていきましょう! Dataformについて 導入の背景 データ基盤に必要な機能が揃っており、簡単に運用を始められること クエリ作成のハードルが非常に低いこと 導入後の効果 FindyでのDataform運用 導入しての課題 改善点 今後の展望 データの品質向上 データモデリング 終わりに Dataformについて サービスの説明については、 公式ドキュメント を引用します。 Dataform は、データ アナリストが BigQuery でデータ変換を行う複雑な SQL ワークフローを開発、テスト、バージョン管理、スケジュール設定するためのサービスです。 例えば、 BigQueryでスケジュール実行しているSQLをGit管理したい 依存関係のあるSQLを順番に実行してほしい クエリの実行結果が意図した挙動を行うかどうかをテストしたい というようなタイミングで活用できます。 導入の背景 Dataform導入前の課題点として、SpreadsheetやGASから利用されているクエリを管理できていませんでした。その結果、利用者が想定しているデータと実際にクエリで取得しているデータが異なっていたり、正しくないテーブルを参照しているケースが発生していました。 このような背景のもと、次のメリットを踏まえてDataformを導入しました。 データ基盤に必要な機能が揃っており、簡単に運用を始められること Dataformは無料でありながら、次のようなデータ基盤に必要な機能が揃っています。 依存関係を定義してDAGを構成できる 特定のタグが付与されたテーブルでワークフローを構成できる データリネージを可視化できる Gitと連携してクエリ管理ができる Google CloudのIAMでカラム単位での権限制御ができる Google Cloudのマネージドサービスなので、余計なメンテナンスをする必要もありません。 クエリ作成のハードルが非常に低いこと ソフトウェア開発の経験がないアナリストやBizサイドにとって、データ基盤への学習コストが低いことは非常に重要です。 Dataformでは.sqlxというSQLを拡張したファイル形式でクエリを開発します。 config { type: "table", "schema": "stg_hoge", "tags": [ "stg_hoge" ], "description": "ユーザー", "columns": { "id": "", "user_name": "ユーザー名", "created_at": "作成日", "updated_at": "更新日", }, "assertions": { "nonNull": [ "id", "user_name", "created_at" ], "uniqueKey": [ "id" ] } } SELECT id, user_name, created_at, updated_at FROM ${ref("lake_hoge", "users")} sqlxは普通のSQLとdescriptionやassertionを含む簡単なconfigで作成可能なので、学習コストが非常に低いです。 Gitを用いたクエリ管理に関しても、Dataform側がバックエンドで行ってくれます。ブラウザ内でクエリ開発からPR作成までが完結するため、Gitのコマンドを覚える必要がありません。 導入後の効果 Dataform導入によって、Bizサイドが作成したクエリをアナリスト・データエンジニアが適切にレビューできるようになりました。 mart層のモデルの数もDataform導入後約4倍となり、開発が活発になっていることが分かります。 また、社内メンバーにDataformの利点について聞いてみたところ、次のような声も聞きました。 1モデルあたり1ファイルの作成で済むので、開発の負担が減った 実行ログをDataformコンソール上で確認できるので、BigQueryと実行ログの横断が楽になった FindyでのDataform運用 ここからはDataformを運用していく上でどのような課題が生じ、どのように解決しているかを詳しく書いていきます。 導入しての課題 Dataform導入当初は、次のようなフローでクエリを開発していました。 データ基盤を運用していく中で、次の課題が生じました。 Production環境にあるテーブルに対してワークスペースからモデルを実行できてしまう Dataformのコンソール画面上から、まだレビューしていないモデルを実行できてしまうのは、意図しないスキーマの変換やデータ変換のバッティングが起きてしまいます。データエンジニア側としても望ましい状態ではありませんでした。 新しいワークフロー用のタグの追加忘れが頻発した Dataformではsqlx内に記述するタグを指定してワークフローを構成します。ワークフローの管理はTerraformで行っていたため、Dataform側のPRからはタグが追加されているか分からず、データ更新時にタグの追加忘れが発覚することがありました。 テーブル変更時、影響範囲が不透明でレビューしづらい クエリを修正する際、修正したテーブルがどのテーブルから参照されているかを確認できていませんでした。計算ロジックの変更がどのテーブルに伝播するのか分からず、レビューが不十分なままマージされてしまうことがありました。 改善点 クエリ開発フローを次のように変更しました。 緊急対応以外の開発は全てdevelop環境で行なうように取り決め、リリース作業を導入しました。また、CIパイプラインの中で次のような項目を自動でチェックし、事故を防止しています。 変更されたsqlxファイルを検出し、クエリとAssertionをDevelop環境で自動実行 変更モデルに依存しているテーブルを検出し、PR上に表示 dataform compile で取得してきたjsonをパースし、変更ファイルのテーブルを検索することで検出しています。 - name: Detect Referenced Table run: | DIFF_FILES=$(echo "${{ steps.get_change_files.outputs.diff_files }}") echo "referenced_tables<<EOF" >> $GITHUB_OUTPUT for file in $DIFF_FILES; do dataset=$(jq -r ".tables[] | select(.fileName == \"$file\") | .canonicalTarget.schema" definition.json) table=$(jq -r ".tables[] | select(.fileName == \"$file\") | .canonicalTarget.name" definition.json) referenced_tables=$(cat definition.json | jq -r ".tables[] | select(.dependencyTargets[]?.schema? == \"$dataset\" and .dependencyTargets[]?.name? == \"$table\") | .canonicalTarget | .schema+\".\"+.name" | awk '!a[$0]++') echo "**$file**" >> $GITHUB_OUTPUT echo "$referenced_tables" >> $GITHUB_OUTPUT done echo "EOF" >> $GITHUB_OUTPUT 開発に利用したワークスペースを自動で削除する Dataform CLIのdry-runでProductionの依存テーブルに問題が無いか確認 1 ワークフローで付与されているタグとsqlxファイル上で付与されているタグを比較し、ワークフローに無いタグをリリースPRで表示 ワークフロー構成で利用されているタグは、Google Cloud側から提供されているAPIで取得できます。 cloud.google.com APIで取得したタグとsqlxに付与されているタグを突合し、ワークフローに追加し忘れたタグが無いか確認しています。追加忘れが見つかった場合は、Terraformで管理しているリリース構成に新しいタグを追加して対応しています。 以上のような改善活動の結果、データの更新漏れやエラーが減りました。アラート対応が減ったことで、データエンジニアが他の業務に時間を割けるようになりました。 リリース導入前後でアラート数を集計してみたのですが、導入前1ヶ月のワークフローで生じたエラーは54件なのに対し、リリース導入後1ヶ月では25件と半分以下になっていました。 今後の展望 データの品質向上 クエリのレビュー体制を整えることができましたが、クエリやデータの品質にはまだ課題を残しています。 GASやスプレッドシート内で発行されていたクエリをDataformの管理下に置くことはできましたが、DRYの原則に反していたり、可読性に課題のあるクエリがまだ存在しています。 データ品質については、異常なデータを検知してアラートを出す仕組みが整える必要があります。Dataformではassertionやtestといった形式でテストを書くことができますが、現状はデフォルトでサポートされているassertion(nullチェックやuniqueKeyなど)を組み込んでいる程度です。 これからも社員が増えていくことが予想される中で、データ品質をどうやって維持・向上していくかはこれからも模索していきたいです。 データモデリング データ利用者がスムーズに分析を進めていくために、データモデリングは必要不可欠です。しかし、弊社ではモデリングに精通した人材がいないのが現状です。 5月からデータエンジニアとアナリストで定期的に集まってデータモデリングの勉強会を行い、チーム内のナレッジを揃えながら少しずつクエリの見直しを進めています。 ※一緒にデータモデリングをしていきたい方がいましたら、是非カジュアル面談にご応募ください!データモデリングを一緒にやっていきましょう! 終わりに いかがでしたでしょうか?今回は弊社でのDataformの活用について書きました。 弊社ではデータ基盤を共に育てていくメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております! herp.careers herp.careers Dataform CLIがver3.0未満だとdry-runで検証できるのはDataform内での依存関係やテーブルの有無のみで、 declaration で宣言したデータソースがBigQuery上に存在しない場合などでエラーが起きません。( 最近のリリース で出来るようになったみたいですが、Dataform CLIのver3.0以上はbreaking changeが多いのでまだ試せていません...)現状は、データソースを参照するようなクエリはリリース時に目視チェックすることでカバーしています。 ↩
こんにちは! ファインディの @Taka-bow です。 まもなく「開発生産性Conference 2024」が開催されます。2日目のキーノートスピーカーであるNicole Forsgren博士は、昨年はビデオ越しのご登壇でしたが、今回は来日してくださる予定です。 昨年は「SPACE:生産性フレームワーク」の研究についてご紹介いただきましたが、今回はどのようなお話を伺えるのでしょうか? ご講演のタイトルは Mastering Developer Experience: A Roadmap to Success (デベロッパーエクスペリエンスを極める:成功へのロードマップ) とのこと。大変楽しみです。 dev-productivity-con.findy-code.io 博士は、書籍 "Accelerate" *1 の筆頭著者としても広く知られていますが、最近はデベロッパーエクスペリエンス( DevEx : Dev eloper Ex perience)研究の第一人者としても注目されています。 そこで、そもそもデベロッパーエクスペリエンスとは何か?博士らの論文を引用しながら紐解きたいと思います。 デベロッパーエクスペリエンスの科学的な研究 Nicole Forsgren 博士らがデベロッパーエクスペリエンス(以降、DevEx)に関して発表した論文はいくつかありますが、今回は最近の2つの論文にフォーカスします。 1つ目は、昨年5月 Association for Computing Machinery(ACM)で発表された "DevEx: What Actually Drives Productivity: The developer-centric approach to measuring and improving productivity" 『DevEx: 何が実際に生産性を向上させるのか: 生産性を測定し改善するための開発者中心のアプローチ』 2つ目は、今年1月に発表された "DevEx in Action: A study of its tangible impacts" 『実践的 DevEx:その具体的な影響に関する研究』 どちらの論文も、DevEx の「質」が、開発生産性に大な影響を与えているという仮説を、科学的に証明しようと試みています。 デベロッパーエクスペリエンスの3次元 DevEx とは、ソフトウェアエンジニア(ここで指す開発者)が日々経験している業務、言い換えれば「エンジニアの業務体験や環境」そのものを指しています。 そして、影響を与える要因を「DevExの3次元」フレームワークと呼びます。 参照: Noda, A., Storey, M. A., Forsgren, N., & Greiler, M. (2023). DevEx: What Actually Drives Productivity: The developer-centric approach to measuring and improving productivity. ACM Queue, Vol.21, No.2, p.35-53. それぞれ、 Feedback Loops (フィードバックループ) Cognitive Load (認知負荷) Flow State (フロー状態) と言います。これを意識することで DevExの改善ステップがより具体的にできます。 Feedback Loops (フィードバックループ) フィードバックループは、テスラのような自動運転の自動車をイメージすると分かりやすいでしょう。 自動運転車は、前方や左右の障害物、車間距離などを判断するために、センサーやカメラから得られる情報を高速で処理するフィードバックループが必要です。この処理が遅いと、障害物にぶつかってしまう可能性がありますよね。 Ian Maddox, CC BY-SA 4.0, via Wikimedia Commons ソフトウェア開発組織は、デリバリーの遅延を減らしてアウトカムの流れを最適化しようとしています。遅延が減ることで、フィードバックと学習が迅速に行われ、速やかな軌道修正が可能となります。 研究によれば、頻繁なデプロイとリードタイムの短縮がパフォーマンス向上に繋がるとされています。迅速なフィードバックループは、開発者が障害なく作業を進めるのに役立ち、逆に遅いフィードバックループは中断や遅延を引き起こし、開発者のフラストレーションを増します。 フィードバックループを高速にするための改善案として、次の点が挙げられます。 開発ツールの高速化 :ビルドやテストの時間を短縮。 人の引き継ぎプロセスの改善 :コードレビューや承認の迅速化。 組織構造の最適化 :チーム間の相互作用を合理化し、遅延を減らす。 これらの改善により、ソフトウェア開発の効率と生産性を向上させることができます。 Cognitive Load (認知負荷) 2011年に旧Twitterで話題になった案内板がありました。 その案内板がこちら 参照: https://note.openvista.jp/2011/redesigning-shinjuku-building-sign, CC BY-SA 4.0 さて、トイレに行くにはどちらに進めば良いのでしょう?前?右?左?と混乱する人が大勢いたそうです。 (正解は左) 少なくとも、ほとんどの人がぱっと見て分からない状態は「認知負荷が高い」と言えるでしょうね。 余談ですが、この案内板はその後認知科学の分野で研究もされ発表されました。 2016年度 日本認知科学会 第33回大会【矢印を用いた「組み合わされた方向サイン」のわかりやすさ: 構造,アイコン,加齢の効果】: 研究リンク ソフトウェア開発は複雑であり、ツールや技術が増えることで開発者の認知負荷が増加しています。認知負荷とは、タスクを実行するために必要な精神的な処理量を指します。 難しいタスクや新しいフレームワークの理解に取り組む場合、この負荷は特に高まります。また、情報の提示方法や精神的な処理が必要な場合も負荷は増加します。 高い認知負荷は、開発者が顧客に価値を提供する妨げとなります。不十分なドキュメントや複雑なシステムにより、開発者はタスク完了に多くの時間と労力を費やすことになります。 認知負荷を軽減するには、次の改善案が挙げられます。 不要な障害の排除 :開発プロセスから不必要な障害を取り除く。 整理されたコードとドキュメント :理解しやすいシステムを構築し、コンテキストやタスクの切り替えを減らす。 専任のDevExおよびプラットフォームチーム :使いやすいセルフサービスツールを提供し、開発とリリース手順を合理化する。 これにより、開発者の認知負荷を軽減し、効率的に価値を提供できる環境を整えることができます。 Flow State (フロー状態) 弓道における基本的な射法の8つの動作を射法八節(しゃほうはっせつ)と言います。 足踏み(あしぶみ) 胴造り(どうづくり) 弓構え(ゆがまえ) 打起し(うちおこし) 引分け(ひきわけ) 会(かい) 離れ(はなれ) 残心(ざんしん) この中でも、6番目の「会」は、他が具体的な動作にも関わらず、これだけが少し違います。 簡単解説!射法八節 によると、 引分けが完成し、矢を放つ機会を待つのが「会」です。丹田に力を入れ、自然な呼吸を心がけます。肩と肘の高さに注意しましょう。体全体のバランス、重心に気を配り、的をしっかりと見つめます。 実際の動作は5秒ほどキープする必要があるそうですが、これがまさにフロー状態だと思います。周囲の音や考え事などの雑念があれば「会」とはならず、矢は的を外れてしまうでしょう。 Pierre-Yves Beaudouin / Wikimedia Commons 開発者は「フローに入る」や「ゾーンに入る」といった表現を使います。 これは、活動中に集中力と活力を持ち、完全に没頭するフロー状態を指します。この状態を頻繁に経験することは、生産性の向上、イノベーションの促進、従業員の成長に繋がります。研究によれば、仕事を楽しむ開発者はより高いパフォーマンスを発揮し、質の高い製品を生み出します。 フロー状態を妨げる主要な要因は、中断や遅延です。その他にも、自律性の欠如、目標の不明確さ、そして刺激的でないタスクが影響します。 フロー状態を作りやすくするためには 中断の最小化 :会議をまとめて行い、計画外の作業を避け、支援依頼をまとめて処理する。 自律性の確保 :開発者に自律性を与え、充実感のある挑戦的なタスクを提供する。 積極的なチーム文化の構築 :リーダーはフロー状態を重視し、自律性とチャレンジの機会を提供する環境を作る。 これにより、開発者がフロー状態に入りやすくなり、生産性と製品の質を向上させることができます。 DevExの測定 「DevExの3次元」は、測定可能な領域を特定するためのフレームワークを提供します。開発者の認識やワークフローを捉えるだけでなく、全体的なKPI(主要業績指標)や「北極星指標」を含めることが重要です。表1では、包括的なKPI指標と3つの次元に沿った具体的な認識およびワークフロー測定の例を示しています。 表1 フィードバックループ 認知負荷 フロー状態 認識 (人間の態度と意見) - 自動テストの速度と出力に対する満足度 - コードベースの複雑さの認識 - 集中して中断を避ける能力の認識 - ローカル変更を検証するのにかかる時間に対する満足度 - 本番システムのデバッグの容易さ - タスクやプロジェクト目標の明確さに対する満足度 - 本番に変更をデプロイするのにかかる時間に対する満足度 - ドキュメント理解の容易さ - オンコールの際の中断性の認識 ワークフロー (システムとプロセスの行動) - CI結果を生成するのにかかる時間 - 技術的質問に対する回答を得るのにかかる時間 - 会議や中断なしでブロックする時間の数 - コードレビューのターンアラウンドタイム - 変更をデプロイするために必要な手動ステップ - 計画外のタスクやリクエストの頻度 - デプロイリードタイム(変更を本番にリリースするまでの時間) - ドキュメントの改善頻度 - チームの注意を必要とするインシデントの頻度 KPI (北極星指標) - ソフトウェア提供の全体的な容易さの認識 - 従業員のエンゲージメントや満足度 - 認識された生産性 最新の調査結果 DX社によるDevExの横断的調査が行われました。この調査は、DX社の顧客の中から研究調査に協力した219人からの回答を基にしています。アンケートに回答した人のうち、170人(77.6%)がテクノロジーを主な事業とする企業の社員であり、200人(91.3%)が従業員数500人以上の企業(中堅または大企業のしきい値)に勤務していました。 以下に、調査・分析結果の重要なポイントを示します。 フロー状態 深い作業に時間を割く開発者は、生産性が50%向上する。 集中時間を確保し、中断を最小限に抑えることが重要。 魅力的な仕事をしている開発者は、生産性が30%向上する。 タスク配分を再考し、燃え尽き症候群を防ぐことが必要。 認知的負荷 コードの理解度が高い開発者は、生産性が42%向上する。 コードを明確でシンプルにし、十分に文書化することが重要。 直感的で使いやすいツールやプロセスは、革新性を50%向上させる。 フィードバックループ コードレビューのターンアラウンドタイムが早いと、革新性(innovative)が20%向上する。 緊密なフィードバックループは、技術的負債を50%減少させる。 質問に迅速に回答することが、技術的負債を減らす鍵となる。 DevEx 改善のためにはどうやって組織に投資させるか 研究の結果、DevExの改善は個人、チーム、そして組織にとってプラスの結果を生み出すという証拠が明らかになりました。しかし、このデータを見ただけでは、組織が改善に向けて舵を切るとは限りません。 そこで、データドリブンかつ継続的な改善を始めるための5つのステップが提案されています。 現在の開発者体験のデータ収集 開発者の体験を把握するためにデータを収集する。これには、アンケートや専用ツールを使用して現在の課題や改善点を明らかにすることが含まれる。 データに基づいて目標設定 収集したデータを元に、改善すべきポイントを特定し、目標を設定する。ビジネスの優先事項とも照らし合わせる。 チームの成功をサポート 設定した目標を達成するために、チームに必要な支援を提供する。目標を共有し、進捗を定期的に確認する。 進捗を共有し、投資を評価 開発者や関係者に進捗を報告し、投資の効果を評価する。学んだことや驚いた点も共有し、改善策を調整する。 プロセスを繰り返す 再びデータを収集し、プロセスを見直して改善する。3~6ヶ月ごとにこのサイクルを繰り返す。 デベロッパーエクスペリエンス(DevEx)改善の重要性 日本では、デベロッパーエクスペリエンス(DevEx)の改善に関する研究はまだまだこれからだと言われています。しかし、これこそが今後のIT業界の競争力を大きく左右する重要な要素となるでしょう。 日本CTO協会が毎年実施している「開発者体験ブランド力」の調査は、すでに一部の企業にとって重要な指標となっていますが、今後はさらに実際のDevExに基づいたエビデンスデータを活用することが求められます。 例えば、アメリカやヨーロッパのIT企業では、DevExの改善が企業文化の一環として浸透しており、優秀な人材の確保や社員の満足度向上に直結しています。 論文 "DevEx: What Actually Drives Productivity" には実際のeBayとファイザーの実例が載っています これにより、企業のイノベーション能力や市場での競争力が劇的に向上しています。 日本のIT企業もこの潮流に乗り遅れることなく、DevExの重要性を認識し、積極的に改善に取り組む必要があります。 具体的な取り組みとしては、開発ツールやプロセスの改善、継続的なフィードバックループの確立、エンジニアの教育とスキルアップの支援などが挙げられます。これらの施策を通じて、開発者がストレスなく効率的に仕事を進められる環境を整えることができます。また、データに基づいた評価と改善を繰り返すことで、より具体的で効果的なDevExの向上が期待できます。 またチーム・トポロジーのイネーブリングチームとしてDevExチームを立ち上げてもよいかもしれません。 実際のDevExデータが調査されるようになれば、日本のエンジニアのDevExへの投資が見直されるかもしれません。 DevExの継続的改善サイクルが回り、結果として、企業全体の生産性や創造性も高まり、ひいては日本のIT業界全体の競争力が強化されるはずです。 経営者やマネジャーの皆様が率先してDevEx改善に取り組み、次世代のIT産業をリードする企業としての地位を確立するチャンスだと私は思います。 *1 : Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations"(邦題「LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する」)
こんにちは!ファインディでFindy Team+開発チームのEMをしている 浜田 です。 昨今、開発生産性を高めるための取り組みを行っている組織が増えてきていると感じています。 開発生産性を向上させるためには、まずは定量的に可視化することが重要です。 可視化することで現状を把握して、開発組織の伸びしろを発見したり、課題を明らかにし、改善活動に取り組みやすくなります。 一方、定量的な指標に焦点を当てすぎてしまい本質的ではない対応をしてしまい、指標は向上したものの実際の生産性は向上していなかったり、むしろ悪化してしまうこともあります。 この記事では、開発生産性指標を向上させるためにやってはいけないアンチパターンについて紹介します。 デプロイ頻度を向上させるために、デプロイプロセスは変更せずに実施回数を増やした デプロイ頻度は DORA が提唱するDevOpsの4つの指標(Four Keys)の1つであり、開発生産性の高い開発組織はこの数値が高いとされています。 そのため、開発生産性を向上させようと考えたときに最初に取り組むことが多い指標です。 デプロイ頻度はただ向上させるだけであれば簡単に向上させることができます。 現状のデプロイプロセスのまま実施回数を増やせば良いのです。 デプロイする回数を増やすだけでデプロイ頻度が向上して開発生産性が向上することもありますが、ほとんどの場合はデプロイ頻度だけが向上するだけで開発生産性は向上しません。 高いデプロイ頻度は、CI/CDが自動化されていたり、小さなパッチ単位でコードベースに変更を入れることができていたり、テスト自動化により変更のリスクが低減されているなど、様々なプラクティスが実践できている結果として得られるものです。 これらの前提を満たさないままデプロイ頻度を向上させることは、変更障害率が上がって障害対応する時間が増加したり、デプロイをすること自体の手間で開発する時間が減ってしまうなど開発生産性を悪化させる可能性があります。 無理やりデプロイ頻度だけを増やすのではなく、前述したプラクティスを実践するとことで、無理なくデプロイ頻度を向上させていきましょう。 リードタイムを短縮するために、全て実装し終わってからコミットする 開発生産性を可視化する際、リードタイムを指標として設定することは有効です。 なお、リードタイムには様々な定義がありますが、今回はGit/GitHubを活用し、コミットしてからメインブランチにマージされるまでの時間をリードタイムと定義します。 上記のリードタイムの定義には欠点があります。Gitの仕組み上ブランチを切った時間が記録されないため、開発に着手してからファーストコミットまでの時間が入っていません。 そこを逆手にとって、リードタイムを短縮するために全て実装し終わってからコミットするというアンチパターンが生まれます。 ただ、このようなことをしても数値だけが短縮されるだけで開発に使っている時間は変わりません。 それどころか、コミットを適切な粒度で行わないことで、コミットログが見づらくなったり、少し前の状態に戻したりすることが困難になります。 本来やりたいことは正しい指標を取得して伸びしろを見つけて本質的な改善に繋げることです。 このような数値ハックは、ただ無意味なだけではなく、コード管理の履歴が活用しづらくなったり、正しく数値を可視化していたら気づけるはずだった課題を見逃してしまう可能性もあるためやめましょう。 リードタイムを短縮するために、必要以上に細かいプルリクエストを作成する リードタイムを短くするプラクティスとして、1つ1つの変更を小さくすることがあります。 1つ1つの変更が小さいことで、実装の時間が短くなり、影響範囲が小さいためテストも容易になり、リードタイムが向上します。 変更サイズが小さいことを可視化するためには、プルリクエスト数を指標とすることがおすすめです。 変更サイズが小さい→さくさくプルリクエストがマージできる→プルリクエスト数が増加。というロジックです。 ただ、プルリクエスト数を指標とした場合、必要以上に細かいプルリクエストを作成するアンチパターンが生まれます。 例えば一括変換でできた機械的な修正であれば、それが複数ファイルに渡っていたとしても1プルリクエストにまとめるべきです。 これをファイルごとにプルリクエストを分割した場合、プルリクエスト数は増加しますが、分割の手間やレビュアーの負荷が増加することで開発生産性は悪化します。 プルリクエスト数はあくまで適切な粒度に分割できていることを確認するための指標なので、数だけを追い求めないようにしましょう。 プルリクエストの粒度については別の記事で詳しく紹介していますので、ぜひご覧ください。 tech.findy.co.jp レビュープロセスに時間がかかるので、コードレビューを省略してマージする リードタイムに着目した際、コードレビューに時間がかかっていることが課題として浮かび上がることがあります。 この課題を正攻法で解決する場合、コードレビューに時間がかかっている理由を分析して、課題を解消する必要があります。 以下によくある課題と解決例を挙げます レビュアーが特定の人物に集中しているのでレビュアーを増やして分散する プルリクエストのサイズが大きいことでレビューに時間がかかるので、プルリクエストのサイズを小さくする インデントや書き方の指摘が多いので、リンターやフォーマッタを導入して機械的に検知できる指摘は自動化する 指摘が多くなりやり取りに時間がかかっているので、ペアプロ/モブプロを導入する 一方でレビューにかかっている時間を最も簡単に削減する方法はコードレビューを省略することです。 ただし、コードレビューを省略することはお勧めできません。 コードレビューをすることでバグの発見やコード品質の向上につながったり、コードの内容を実装者とレビュアーで共有することでコードの属人化を軽減できたり、レビュアーの目を通すことで第三者が読みやすいコードになり保守性が向上します。 コードレビューはとても有意義な活動なので、省略せずに根本解決することで有意義にレビューしつつリードタイムを向上させましょう。 プルリクエストのサイズを小さくするためにテストコードを別のプルリクエストにする 意味のある最小単位でプルリクエストを作成して、小さい単位でサクサクマージしていくことは開発生産性を向上させるための有効なプラクティスです。 プルリクエストを小さくする際、テストコードを別のプルリクエストに分けたくなることがあります。 1つ目のプルリクエストでテストコードなしのコードのみ実装して、2つ目のプルリクエストでそのテストコードを書くという方法です。 この方法はプルリクエストのサイズを小さくできますが、一時的とはいえテストコードで守られていないコードがメインブランチに混入することになります。 テストで守られていないコードは何かしらの変更で不具合が混入しても気づくことができないため、品質低下につながります。 また、すぐにテストコードが追加されれば良いですが、別にすることでテストコードの実装を忘れてしまう可能性も高まります。 コードと対応するテストコードは1つのプルリクエストに含め、テストコードで守られていないコードがメインブランチに混入しないようにしましょう。 変更障害率を下げるために、デプロイ頻度を下げる 変更障害率はDORAが提唱するDevOpsの4つの指標(Four Keys)の1つであり、デプロイを起因とした本番障害の発生確率を指しています。 また、開発生産性に関係なく、変更障害率は関係者全員が低く保ちたいと願っているのではないでしょうか。 本番障害が発生する最大の原因はデプロイで不具合を混入させてしまうことです。 そのため、デプロイすることに慎重になり、デプロイ頻度が低下してしまうことがあります。 しかし、変更障害率を下げるためにデプロイ頻度を下げることはアンチパターンです。 デプロイ頻度を下げて、1回のデプロイに含まれる変更量が増えることで次の問題が発生します。 変更内容が複雑になり、相互作用や予期せぬ結果が発生する可能性が高くなり、本番障害が発生するリスクが高まる テスト範囲が広くなるため、テスト漏れが発生する可能性が高くなり、本番障害が発生するリスクが高まる 障害が発生した際、原因特定に時間がかかり、平均修復時間が増加する 影響範囲が大きくなるため、障害の影響範囲が広くなる可能性が高まる 変更障害率を下げるためのプラクティスは、デプロイ1回あたりの変更量を小さくすることです。 変更量が小さいことで、変更範囲を正確に把握できるので、テストが容易になってテストのリードタイムを短縮できたり、テスト精度が向上することで品質が向上します。 また、頻繁にデプロイするためには自動テストを充実させることも重要です。自動テストが充実していることで既存機能が壊れていないことを自動的に確認できるためリードタイムの向上や品質の向上につながります。 デプロイを過度に恐れず、デプロイあたりの変更量を小さくしたり、自動テストを充実させるなど開発生産性を向上させるプラクティスを取り入れることで変更障害率を下げましょう。 変更障害率を下げるために、hotfixでの対応を出し惜しみする 変更障害率を可視化するために、hotfixの数から算出することがあります。 前述した通り、変更障害率は誰もが低く保ちたい指標です。 そのため、本来はhotfixで即対応した方がベストだとわかっている場合でも、通常フローで対応してしまうことがあります。 hotfixを使わないことで、変更障害にカウントされないので結果として変更障害率は下がるかもしれません。 ただし、hotfixを使わなかったからといって発生した障害がなるなるわけではありません。 また、本来は変更障害率に計上されるべきものを計上しないことで、振り返りなどで課題に気づきづらくなり、自分たちの成長機会を妨げる可能性があります。 開発生産性の可視化を自分たちの成長機会に繋げるためにも、数値を良くすることばかりに注目するのではなく、正しく取るように心がけましょう。 まとめ ここまでで紹介したアンチパターンは開発生産性の数値を高めるための組織の能力に注目せずに、数値を向上させることだけを目標に設定してしまったために発生しているものが多いです。 このことは「グッドハートの法則」として広く知られています。 以下、ChatGPTによる説明です。 グッドハートの法則(Goodhart’s Law)は、経済学者チャールズ・グッドハートが提唱した概念で、「特定の統計的指標が政策目標として使われると、その指標はもはや信頼できるものではなくなる」という法則です。 つまり、ある指標が目標となると、人々はその指標を達成するための行動を取り始めるため、指標自体の本来の意味や有用性が失われるということです。 定量的な目標を設定することは開発生産性の現在地を把握するためには有効ですが、目標を達成するために本来備えておくべき能力を理解せずに数値だけを追い求めないようにしましょう。 なお、開発生産性の高い組織を目指すために備えるべき能力は、Google Cloudの DevOpsの能力 がとても参考になります。 また、DORA Core Modelにも開発組織のケイパビリティと開発生産性指標との関係が示されていますので、ぜひ参考にしてみてください。 出典: DORA’s Research Program 6月28日(金)・29日(土)に『LeanとDevOpsの科学』の著者であるNicole Forsgrenの来日、テスラ共同創業者元CTOの登壇など、国内外の開発生産性に関する最新の知見が集まるConferenceを開催します。 開発生産性に関する他の企業の取り組みや海外の事例に興味がある方は、ぜひお申し込みください! dev-productivity-con.findy-code.io
こんにちは。 FindyでMLエンジニアをしているyusukeshimpo( @WebY76755963 )です。 今回はLLM Embeddingを活用した自動応答Botを開発&導入し、社内の問い合わせ業務を効率化することができたので、その取り組みを紹介します。 Botを開発することになった背景 弊社ではSlackを使用し、自社サービスに関する社内質問に回答するチャンネルを運用しています。 主にビジネスサイドからの技術的な疑問にエンジニアが答える仕組みです。 質問はテンプレートを使って送信され、エンジニアが回答しますが、このワークフローには次のような問題が発生しています。 同じ質問が異なる人から届いてしまう 質問の度にエンジニアの工数が発生してしまう 半期で70件以上の質問が発生し、1件につき1~1.5時間かかることもあります。 多くの質問は社内ドキュメントで解決可能ですが、検索がしづらく利用されていません。 質問に関連するドキュメントを渡すことで、エンジニアに質問する前に自己解決を促すことができます。 これがBot導入の背景です。 Bot導入のためのアプローチ Botの要件について Botを導入する理由は、質問対応でエンジニアの労力を減らすことです。 しかし、Kibela(社内の情報共有ツール)のQ&A集やSlackの問い合わせ履歴などの社内ドキュメントは全て構造化されておらず、検索性に乏しいという課題があります。 また、Botが全てを解決するのは難しく、ハルシネーション(AIが実際には存在しない情報を生成する現象)の問題もあります。 これらを踏まえ、クイックに実装できる要件を考えました そこでBotの機能としては、 質問の内容に関連しそうな社内ドキュメントへのリンクを送る 上記で解決できたかを質問者にフィードバックしてもらう 解決できない場合はあらためてエンジニアへ質問を投げる というものにしました。 Botの構成 上記の要件を踏まえて、Botの仕組みは次のようにしました。 ① データの取得 ② データの構造化 ③ 類似度計算とBotの回答 ④ 質問者からのフィードバック 以下に、各処理について簡単に説明します。 ①データの取得 最初にデータの取得をKibelaとSlackからAPIを使って行います。 過去きた質問と同じ質問に回答できることや社内の基本的なドキュメントで解決することを考えて、KibelaとSlackチャンネルのメッセージ履歴をBotで使用するデータにしました。 ②データの構造化 今回の開発で最も重要なことの一つに、テキストデータの構造化処理があります。 フォーマットが異なる、または整備されていないテキストを扱うため、地道な作業で対応しました。 以下に、非構造の社内ドキュメントを構造化するプロセスを図示しています。 このプロセスを経て、最終的にKibelaとSlackから次の情報を持った構造化データを作成します。 ドキュメントタイプ(Kibela or Slack) テキスト ドキュメントのURL テキストのEmbedding(質問との類似度計算用) このように構造化することで、質問内容に合わせた関連ドキュメントを検索することができるようになります。 テキストデータ処理後、コサイン類似度計算のためにOpenAIのtext-embeddingを使用しました。 作成した構造化データはBot内で保持します。 ③類似度計算とBotの回答 質問者からのインプットである質問文をEmbeddingしたものと、構造化データ内のEmbeddingデータとのコサイン類似度を計算し、類似したドキュメントのリンクを渡せるようにします。 Botの返信内容として、質問と類似度の高いドキュメントのURLを採用します。 ④質問者からのフィードバック 最後に、質問者が想定している回答を、Botが応答できているかどうか確認するプロセスを設けました。 ここでは、望んでいた応答が得られたかどうかをフィードバックしてもらい、フィードバック別にその後のフローを分けています。 フィードバック後のフローについてはこの後の工夫した点のところで、詳細を説明します。 Bot導入時の工夫 Botの導入の際に工夫した点が以下2点あるので、それについても紹介をさせてください。 ワークフローの変更 データの準備 ワークフローの変更(フィードバックプロセスの追加) ハルシネーション問題に対応する為、Botはテキストで返答するのではなく類似度のリンクを返信するようにしています。 これにより、質問者がリンク先のドキュメントを参考に自己解決を促すようにしました。 しかし、Botが提案したドキュメントで解決しきれない場合があった為、既存のワークフローを「 自己解決できなかった場合に 、エンジニアへ質問として受け付けられる」よう工夫しました。 上記工夫を取り入れた変更後のワークフローを以下図のように変更しました。 このように、質問者がBotの応答で自己解決できるかをチェックし、解決できない場合に「いいえ」を選択するとエンジニアへ質問が飛ぶ仕組みとしています。 Slack APIによるフィードバックの作成方法 回答が役に立ったかどうかのフィードバックを作成する際に、Slack APIによる以下実装の要領で、質問者に手軽に回答してもらえるボタンを用意する事ができました。 @ app.action ( "feedback_yes" ) def handle_feedback_yes (ack, body, say): ack() thread_ts = body[ "message" ][ "ts" ] say( "あなたは「はい」を押しました \n フィードバックをありがとうございます!他にお問い合わせがある場合はフォームからお願いいたします。" , thread_ts=thread_ts) @ app.action ( "feedback_no" ) def handle_feedback_no (ack, body, say): ack() thread_ts = body[ "message" ][ "ts" ] user_group_id = "hoge" # SlackグループID(メンション先) say(f "あなたは「いいえ」を押しました \n <!subteam^{user_group_id}> \n 上記のお問い合わせが来ているのでご対応お願いいたします!" , thread_ts=thread_ts) このように、フィードバックステップを簡易に組み込む事ができたおかげで、Botでどのくらい自己解決を促す事ができたかどうかを後述のように可視化できました。 導入時点で組み込んでおいた事で、評価用プロセスの追加実装や別で実装する等の手間を省く事もできました。 データの準備 先述の通り、今回の仕組みによるBotを実装するにあたり、応答精度を高めるには様々な形式で保存されているテキストデータの クリーニングや加工 は重要なポイントの1つでした。 これまで、Botを構築し社内ドキュメントを検索するような用途で参照する事を想定していなかった為に、今回の用途に合わせてデータを丁寧に加工する事で、応答精度を高める事ができました。 今回紹介した仕組みで自動応答Botのデータとして応用する事を検討する場合は、ドキュメントが構造化されやすく整理されているかが意識されていると実装コストが削減できるようになると感じました。 例えば、Kibelaのような自由記述のテキストであれば、テンプレートを用意する等して形式を統一すると前処理が楽になります。 社内ドキュメントの整備には手間がかかるため敬遠されがちですが、このような用途に利用できることがわかれば、社内ドキュメントの整備に時間を割きやすくなるように思います。 Bot導入の結果 社内の問い合わせオペレーションを改善できた 実際にBotを導入してみて工数の削減ができたのかを集計してみました。 導入後2ヶ月で、お問い合わせ対応にかかる所要時間を 1/3減少 する事に貢献している事がわかりました。 オペレーションの改善になったポイント このように効率化できたポイントは、 問い合わせ対応のワークフローを改善できた ことです。 今まではどんな質問でも問い合わせとして送信していたものを、Botによる自己解決を促すプロセスを組み込んだワークフローにできた事で、 本来であれば自己解決する事ができた質問を炙り出す事ができるようになったから だと振り返っています。 Botを単純に導入するだけでなく、今回の評価プロセスのように「どんな課題に対してどのようにBotを組み込み効率的な仕組みを作るか」を意識することが大切です。 Botの精度は今後社内ドキュメントを充実させることで改善をしていきますが、質問への対応時間削減は実現できたので導入した甲斐はありました。 Botで社内向けの問い合わせ対応の効率化をしたいという方はぜひ参考にしていただければと思います! 最後に 以上が社内お問い合わせの自動化Botの開発についてでした。 参考にしていただければ幸いです。 また、弊社では機械学習エンジニア・データエンジニアなど一緒に働いてくれるメンバーを募集しております。 興味がある方は↓からご応募してしていただければと思います。 herp.careers
こんにちは。 Findy で Tech Lead をやらせてもらってる戸田です。 弊社では本番環境へのデプロイを1日に複数回実行していますが、本番環境での不具合の発生率は低いです。 次の画像は弊社のあるプロダクトの直近1年のFour Keysの数値です。 平均で1日2.3回の本番デプロイを行っていますが、変更障害率は0.4%程度を維持しています。単純計算ですが、1年で障害が2件程度の水準です。 また、平均修復時間は0.3hとなっており、障害が発生しても20分以内には復旧できていることがわかります。 この数値を維持できている理由の1つにテストコードの品質があると考えています。 システムで発生する不具合を自動テストが検知することで本番環境への不具合の混入を事前に防ぐことができ、仮に不具合が発生したとしても修正内容が他の箇所に影響が出ないことをテストコードが保証してくれるため迅速に修正できるからです。 弊社ではテストカバレッジよりも、テストで何を守るのか?という観点を重視しています。その上でテストカバレッジの90%超えは珍しいことではありません。 しかし、実際にはカバレッジを意識したことはなく、システムを守るテストを意識した結果、勝手にカバレッジが上がっていただけなのです。 我々としては「全てのテストコードが通る」ことよりも、「コケるべき時にコケるテストコード」の方が重要だと定義しています。 この記事では、弊社で実践している「テストを通すためのテストコード」ではなく、「システムを守るテストコード」の書き方をいくつか紹介していきます。 それでは見ていきましょう! 実例紹介 関数の実行状態のチェック 出力対象外のチェック チェックする値の厳密化 まとめ 実例紹介 関数の実行状態のチェック 特定の処理を実行したあとに、結果に応じてコールバック関数を実行するようなケースは少なくありません。 コンポーネントに関数を渡し、ボタンをクリックした時にその関数を実行するようなケースもあるでしょう。 このようなケースの場合、関数を特定の処理で実行する際に、その関数が適切に扱われているのかを守るテストケースが必要になります。 例えば正常系の次のようなテストコードがあるとします。 const mockOnSuccessCallback = jest.fn(); const mockOnErrorCallback = jest.fn(); const { result } = renderHook(() => useHoge( { onSuccessCallback : mockOnSuccessCallback, onErrorCallback : mockOnErrorCallback } )); act(() => { result. current .handleSubmit(); } ); expect (mockOnSuccessCallback).toHaveBeenCalledWith( 'test' ); hooksの関数を実行し、成功時に引数で渡したコールバック関数がパラメータ付きで実行されることを確認しています。 一見何の変哲もないテストコードですが、このテストコードには次の視点が抜けており、システムを守るテストとしては不十分です。 成功時の関数が複数回実行されたとしても通ってしまう エラー時のコールバック関数が実行されたとしても通ってしまう こういったケースでは、弊社では次のようなテストコードが推奨されます。 const mockOnSuccessCallback = jest.fn(); const mockOnErrorCallback = jest.fn(); const { result } = renderHook(() => useHoge( { onSuccessCallback : mockOnSuccessCallback, onErrorCallback : mockOnErrorCallback } )); act(() => { result. current .handleSubmit(); } ); expect (mockOnSuccessCallback).toHaveBeenCalledTimes( 1 ); expect (mockOnSuccessCallback).toHaveBeenCalledWith( 'test' ); expect (mockOnErrorCallback).not.toHaveBeenCalled(); このテストコードにより、「成功時に1回だけコールバック関数がパラメータ付きで実行され、エラーのコールバック関数が実行されない」ことを守ることができます。 この2つのテストコードのカバレッジは変わりませんが、システムを守ることができる内容が変更前よりも増えており、アプリケーションの振る舞いをより厳密に守ることができるようになりました。 出力対象外のチェック 特定の情報のみを返す処理がある場合、その情報が正しく取得できることを確認するテストケースが必要になります。 特定のユーザー情報を取得し、そのユーザーに紐付く各種情報を取得する処理はよくあるケースです。 このようなケースの場合、特定の情報のみを取得できることを守るテストケースが必要になります。 例えば次のようなテストコードがあるとします。 RSpec .describe User do describe ' .skills ' do let!( :user ) { create( :user ) } let!( :user_skills ) { create_list( :user_skill , 3 , user :) } it ' returns user skills ' do expect(user.skills).to eq(user_skills) end end end 特定のユーザーデータに紐付くスキルデータを取得することを確認しています。 一見何の変哲もないテストコードですが、このテストコードには次の視点が抜けており、守るテストとしては不十分です。 他のユーザーのスキルデータが混在してしまう可能性を否定できていない 対象のユーザーがスキルデータを持っていない場合の挙動を確認できていない 特に他のユーザーのスキルデータが混在してしまうケースが発生してしまった場合、最悪の場合インシデントにもなりかねません。 こういったケースでは、弊社では次のようなテストコードが推奨されます。 RSpec .describe User do describe ' .skills ' do let!( :user ) { create( :user ) } before do # NOTE : 他ユーザーのレコードが対象外になることを守る create_list( :user_skill , 3 , user : create( :user )) end context ' when user has skill ' do let!( :user_skills ) { create_list( :user_skill , 3 , user :) } it ' returns user skills ' do expect(user.skills).to eq(user_skills) end end context ' when user not has skill ' do it ' returns empty array ' do expect(user.skills).to eq([]) end end end end このテストコードにより、「他のユーザーのスキルデータが混在してしまう可能性を否定」し、「対象のユーザーがスキルデータを持っていない場合でも正常に処理を実行できる」ことを守ることができるようになりました。 対象のレコードをチェックすることだけではなく、対象外のレコードが本当に対象外になっているのかどうか、レコードが存在しなかった場合にエラーが起きないかどうかまで確認することで、アプリケーションの振る舞いをより厳密に守ることができるようになりました。 チェックする値の厳密化 特定の値を返す関数がある場合、実行時に期待する値が返ってくることを確認するテストケースが必要になります。 例えば次のようなテストコードがあるとします。 RSpec .describe User do describe ' .has_multi_skills ' do let!( :user ) { create( :user ) } before do # NOTE : 他ユーザーのレコードが対象外になることを守る create_list( :user_skill , 3 , user : create( :user )) end context ' when user has multi skills ' do before { create_list( :user_skill , 3 , user :) } it ' returns true ' do expect(user.has_multi_skills).to be_truthy end end context ' when user has skill ' do before { create( :user_skill , user :) } it ' returns false ' do expect(user.has_multi_skills).to be_falsy end end context ' when user not has skill ' do it ' returns false ' do expect(user.has_multi_skills).to be_falsy end end end end 対象のユーザーが複数のスキルデータを持っている場合にtrueを、それ以外の場合にはfalseが返ってくることを確認しています。 パッと見で特に問題は無さそうですが、 be_truthy be_falsy の仕様には注意が必要です。 it { expect( true ).to be_truthy } # passes it { expect( " hoge " ).to be_truthy } # passes it { expect( nil ).to be_truthy } # fails it { expect( false ).to be_truthy } # fails it { expect( false ).to be_falsy } # passes it { expect( nil ).to be_falsy } # passes it { expect( " hoge " ).to be_falsy} # fails it { expect( true ).to be_falsy } # fails be_truthy be_falsy はbooleanの値以外でも実行結果が変わります。 そのため、例えば関数が返す値がbooleanではなく文字列になってしまった場合にテストが通ってしまう可能性があります。 何かしらの値が入っていることを確認するテストケースであれば問題ありませんが、今回のケースではbooleanの値を厳密にチェックすることが要求されます。 こういったケースでは、弊社では次のようなテストコードが推奨されます。 RSpec .describe User do describe ' .has_multi_skills ' do let!( :user ) { create( :user ) } before do # NOTE : 他ユーザーのレコードが対象外になることを守る create_list( :user_skill , 3 , user : create( :user )) end context ' when user has multi skills ' do before { create_list( :user_skill , 3 , user :) } it ' returns true ' do expect(user.has_multi_skills).to be true end end context ' when user has skill ' do before { create( :user_skill , user :) } it ' returns false ' do expect(user.has_multi_skills).to be false end end context ' when user not has skill ' do it ' returns false ' do expect(user.has_multi_skills).to be false end end end end このテストコードにより、関数が返す値をbooleanの値で厳密にチェックすることが可能になり、関数の実装が壊れてしまった場合にテストがコケて教えてくれるようになります。 テストライブラリのマッチャーは便利で多用しがちですが、それらの仕様を理解し適切に利用することが重要です。 まとめ いかがでしたでしょうか? テストコードは全て通ると安心しますが、本質はそこではなくコケるべき時にコケてくれるテストコードを書くことが重要です。 今回挙げた例はほんの一例です。弊社ではこの様にシステムを守るテストを重視しており、既存コードへの修正を行ったとしてもほとんどのケースをテストコードでカバーすることが出来ています。そのため安心して機能追加、リファクタリングなどを行うことができます。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers
こんにちは、ファインディのEND( @aiandrox )です! 2024年4月30日より、ファインディは新オフィスに移転しました。 findy.co.jp 新オフィスのここがすごい! 大崎駅から直結徒歩5分!雨に濡れずに出社できる! 前オフィスの2.3倍の広さ! オフラインイベントが開催できるイベントスペースが増えました! この記事では、そんな新オフィスについて、エンジニア目線で紹介します(2024年5月時点)。 執務室について ソファ席・ハイテーブル パントリー イベントスペースについて 社内イベントの様子 オフラインイベントの様子 おわりに 執務室について 執務室は前オフィスと同じようにシンプルな作りです。1フロアで、大体徒歩5分あれば1周できるくらいの広さです。 最大500席入る広さですが、現在は出社メンバーが200人程度なので空席が多いです。毎月ガンガン新しい方にジョインしていただいているので、今後どんどん埋まっていく想定です! この辺りはまだ空席です エンジニアの島はCエリアのサンパウロのあたりに位置しています。サインの名前はクラウドサービスのリージョンになっているので、なんとなく身近な感じ。 また、前のオフィスのときからそうでしたが、エンジニアの席には4Kモニターとエルゴヒューマンが完備なので、開発環境も◎。 さらに、新オフィスでは全席に有線LANが用意されるようになったので、回線速度もUPしました。最大1GBくらい出ます。 ソファ席・ハイテーブル 新しく入社したメンバーはチームメンバーと1on1をするオンボーディングがあるのですが、そのときにはソファ席を使うことが多いです。テイクアウトのランチのときにも大活躍です。 また、オフラインで設計の相談などをするときにはハイテーブルやスタンディングデスクを使うことが多いです。この席は予約がいらないので、ちょっとした相談やざっくばらんに話したいときに役に立ちます。 Flexispotの電動昇降なので、高さもらくらく調整できて使いやすいです! パントリー ファインディのバリューの1つに「スピード」があります。そのためにも、1人あたりの生産性を高めるために業務用の電子レンジがあります。お弁当を食べるときも他の人を待つことがありません(自分は普段外食しているためあまり使っていませんが……)。 なんと最大1900Wの電子レンジ イベントスペースについて 最大の目玉がこれ! 今までファインディでは数多くのオフラインイベントをしていましたが、イベントスペースを借りる必要がありました。新オフィスではイベントスペースが新設されたので、出社時にはイベントにふらっと遊びに行くこともできます。 とても広い! こちらは最大100名収容できるようになっています。 また、イベントスペースには、エンジニア心がくすぐられるマークがたくさんあります。 入口からはsshで入ります メインスクリーンは普段はこんな感じ。よく見ると……? こちらの扉の向こう側は執務室となっています 他にも、エンジニア心のくすぐられるサインがたくさんあるので、ぜひイベントスペースに遊びに来てご確認ください! 社内イベントの様子 イベントスペースは予約していれば自由に使えます。 私は社内のボードゲーム会によく参加しているのですが、前のオフィスでは増えていく執務テーブルに圧迫されて活動休止していました。新オフィスでイベントスペースができたので、お昼に社内のメンバーでボドゲ会をやりました。 コトバーテル いかだの5人 また、社内限定の移転イベントの様子は以下から見ることができます! note.com これだけ集まるとさすがに圧巻です オフラインイベントの様子 5月28日に開催されたオフラインイベント「 After RubyKaigi 2024〜メドピア、ZOZO、Findy〜 」の様子です。 配信ブースもあるので、オンライン/オフラインのハイブリット開催も可能です!このときのイベントもハイブリット開催でした。 配信ブースの機材 オンラインの配信画面 今後も、社内・社外問わずいろんなコミュニケーションのできるスペースとして使っていきます🙌 おわりに 新オフィス移転後も、ファインディはどんどんメンバーを増やしてさらなる成長をし続けます! 現在、ファインディでは一緒に働くメンバーを募集中です。興味がある方はこちらからどうぞ! herp.careers
こんにちは。 今年の4月より Findy Tools の開発をしている林です! この記事は 自慢の作業環境を大公開シリーズ の第4弾になります。 今回は3名のエンジニアの作業環境を紹介します! 作業環境を大公開 林 私はオフィスへの出社と在宅のハイブリッドで勤務しており、自宅にも快適な作業環境を備えています。 デスク周りの全体像はこのようになっており、シンプルで機能性を重視した構成にしています。 ポイントは昇降デスクと34インチのウルトラワイドモニターです。 昇降デスクは FlexiSpotのEF1 を使っています。1日中座っていると体が凝るのと、疲れた時に気分転換で立ち作業をできて必要不可欠なものになっています。 ディスプレイは LGの34WN780-B を使っています。横に広いことでコードやウィンドウを3つくらい並べることが出来て作業が捗ります。また、ディスプレイアームが付属しており角度や位置を調整しやすいです。 さらに、14型のMacbook ProをノートPCスタンドに載せることでディスプレイの高さを揃えられて、Webカメラの位置もちょうど良くなるのが気に入ってます。 他にはメモや紙をつかって思考整理するためのノートとペン、iPadやKindle Paperwhite、私用のMacbook Airを横に置いてあります。 入力機器はメリハリがつくことや気分転換のため私用と社用で分けており、上段のが個人利用、下段が社用です。 私用は Keychron K1 のタクタイルスイッチと LogicoolのトラックボールERGO M575 を使っています。業務でもFigmaで図を書くときなどは、たまにトラックボールを使うこともあります。 社用は LOFREE Flow84 というリニアスイッチのキーボードとAppleのMagic Trackpadを使っています。元々、Keychron K1というキーボードだけを使っていましたが、リニアスイッチのキーボードも試してみたくFlow 84を今年になってから購入しました。打鍵感がスムーズでタイプ音も心地よく気に入っています。 昇降デスクが動く際、ケーブルに余裕を持たせておく必要があるので、天板にケーブルトレーを設置し、垂れるケーブルを最小限にしています。また、電源タップやUSB-Cのドッキングステーションを設置し、ここにケーブル類を集約することで、デスク上のケーブルがほとんど見えなくなりスッキリします。 以上、林の作業環境でした。 開 Findyでデータエンジニアやってる開です。 僕もハイブリットで働いているため最低限デスク周りは整えています。 デスクは FlexiSpot なんですが、手動で回すタイプのものです。 回す作業がちょっとした運動になるので気に入っています。 椅子は COFO Chair Premium を使っています。 ディスプレイは2枚を左右からアームで持ち上げて使っています。 1枚は新卒の頃から使っているものなので新しくしたく、4Kディスプレイを買うために家庭内稟議中です。 デスク上はこんな感じ。 キーボードは茶軸の MISTEL BAROCCO MD770 で、マウスは Logicool ERGO M575S ワイヤレストラックボール を使っています。 ハイブリットなので出社した際もなるべく同じ環境で働きたくキーボードとマウスは同じものを会社にも置いてます。 前はReal Forceが好きだったのですが、整体の先生に進められて2,3年前から分離キーボードを使うようにしています。 また WAVLINK のドッキングステーションを使っており電源や周辺機器への接続をこれ1つにまとめています。 仕事ではMacBook Pro 14インチを使っててクラムシェルで置いてます。 左上にはFine-day(Findyの全社総会)で頂いたPC拭きの上にイヤホンやドラゴンボール(三星球)を置いています。 いつか他の6つが見つかったときのために大切に保管しています。 デスク下はプライベートで使っているデスクトップPCを置いています。 GPU(RTX 4090)積んでるのでデータコンペに参加したりローカルLLMを動かしたりして遊んでます。 また引き出しやコードを収納するためのトレー、バックとヘッドホンを掛けるためのフックを用意して物を収納できるようにしています。 マイクには FIFNE K670 を使っています。 個人でポッドキャストやっているので吐息が入らないように風防はスポンジとポップガードの2重でやっています。 アームによって持ち上げることでタイピングした際の振動がマイクに伝わりづらくしています。 以上、開のデスク紹介でした! 古田 前のお二人の記事を見て昇降デスクが欲しくなった古田です。 Findy Team+ でプロダクト開発を担当しています。 自分も出社と在宅のハイブリッドで働いていますが、一時期リモート中心だった時期に椎間板ヘルニアを患い、それ以来作業環境では「健康」に気を遣っています。 そんな作業環境がざっと次のようなかんじです。 モニタに関しては以前は大きめのデスクにトリプルディスプレイで配置をしていたんですがヘルニアになってからは首の可動域をあまり増やしたくないので、ノートPCの上部にモニタを配置してそれに併せてデスクも約90cmほどのコンパクトな物にしました。 キーボードは BAROCCO MD600 Alpha BT RGB という分割キーボードを使用しています。 分割キーボードを使うまでは整体に行くと「肩の筋肉ガチガチに固まってますね...」と言われるくらいに肩が凝り固まっていましたが、分割キーボードを使うようになってから肩周りは大分ラクになってきました。 現状の分割キーボードでも充分に満足なのですが、社内のエンジニアの中には分割キーボードにして右側キーボードの端にトラックボールを配置する自作キーボードとかを作っているメンバーも居たりしていつか理想の自作キーボードを作ってみたいと憧れる今日このごろです。 カーソル移動には Magic Trackpad を使用しています。 トラックパッドの配置場所は最初、収まりの良さから分割キーボードで挟んで置いていましたが、どうしてもトラックパッドを触る腕の肩が内巻きになりがちでした。 なので現在は分割キーボードの外側に配置しています。 作業環境なのか?と質問されたら回答に困りますが、作業時は常に着用しているということでアクティビティトラッカーの vívosmart 5 も紹介します。 アクティビティートラッカーなので用途としては色々あるのですが、作業をする上で一番ありがたいのがMoveアラートという一定時間身体を動かしていないとアラート通知をしてくれる機能です。 このアラート通知が来たら立ち上がってちょっとウォーキングをしたり、ストレッチをしたりして身体をほぐしています。 ストレッチの際は ハンドルチューブ などを使って胸を大きく開くようなストレッチをすると首や肩周りの凝りが軽減されます。 また座席には BackJoyのサポートクッション を必ず敷いて作業しています。これがあるかないかでは長時間作業した後の腰回りの疲労感が大分違ってきます。 以上、作業環境紹介という健康グッズ紹介みたいでしたが、古田の作業環境でした! まとめ いかがでしたでしょうか? 分割キーボードや昇降デスク、ストレッチグッズなど身体の健康に気を遣った環境が多かったですね! やはりエンジニアは1日の大半をデスクで仕事をするので、作業環境の大切さを再実感しました。 何か参考になるものがあれば幸いです。 現在、ファインディでは一緒に働くメンバーを募集中です。 興味がある方はこちらから ↓ herp.careers