Slackワークフローとスプレッドシートを連携して開発工数の内訳を簡単に可視化

こんにちは!ファインディでFindy Team+開発チームのEMをしている浜田です。

Findy Team+開発チームでは、Slackワークフローとスプレッドシートを連携して開発工数の内訳を可視化しています。 開発工数の内訳を可視化することで、どの開発にどれくらい工数がかかったかや全体の工数のうちどれくらいの割合を開発に使えているかなどを定量的に把握できます。

Slackワークフローとスプレッドシートの説明

ここからはTeam+開発チームで実際に使っているSlackワークフローとスプレッドシートをキャプチャを交えつつ説明します。 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ワークフロー作成手順1

自動化の画面から「新しいワークフローを構築する」を選択します。

Slackワークフロー作成手順2

ワークフローを開始するイベントを選択します。 今回は任意のタイミングで起動したいので「Slack内のリンクから開始します」を選択します。

こちらを選択することで、発行されたリンクを実行したり、Slackのスラッシュコマンドから実行できるワークフローが作成できます。

Slackワークフロー作成手順3

1つ目のステップでは、日報の内容をフォームで収集するため「情報をフォームで収集する」を選択します。 ステップから見つからない場合は、検索ボックスからキーワードを入力して探すこともできます。

Slackワークフロー作成手順4

フォームのタイトルや項目を設定する画面が開くので収集したい項目を設定します。 入力形式はフリーテキストだけではなく、ドロップダウンやカレンダーから選択など様々な方法が準備されているので適したものを選択しましょう。

Slackワークフロー作成手順5

フォームで入力した内容をスプレッドシートに連携したいため、2つ目のステップでは「スプレッドシートに追加する」を選択します。

Slackワークフロー作成手順6

連携するスプレッドシートは1つ目のステップで作成したフォームを基に生成できます。利用者のユースケースが的確に捉えられており、とても良いUXですよね!

Slackワークフロー作成手順7

フォームの項目とスプレッドシートの列を紐づけます。

Slackワークフロー作成手順8

入力した内容をSlackチャンネルにも投稿したいため、最後のステップでは「チャンネルへメッセージを送信する」を選択します。

Slackワークフロー作成手順9

Slackチャンネルへ通知するメッセージのテンプレートを作成します。

Slackワークフロー作成手順10

作成できたら公開します。公開すると実行するためのURLが発行されます🎉

Slackワークフロー作成手順11

Slackワークフローを実行すると、次のように連携したスプレッドシートにデータが1行追加されます。 スプレッドシートにデータが溜まりさえすれば、スプシ芸(?)を活用して様々な切り口でデータ分析できますね! ガンガン活用していきましょう💪

Slackワークフロー作成手順12

まとめ

この記事では、Slackワークフローとスプレッドシートを連携して開発工数の内訳を可視化する方法を紹介しました。

前半に書きましたが、工数の可視化は入力の手間と精度のバランスが大事だと思います。 必要最低限の精度で手間なく可視化できるように工夫しつつ、開発工数やトイル時間を把握して開発組織が健全に開発を推進できている状態にしていきましょう!


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers

*1:こちらは2025年1月時点の情報です。Slackのバージョンアップ等で変更される可能性があります。

Findyの爆速開発を支えるタスク分解

こんにちは。

ファインディ で Tech Lead をやらせてもらってる戸田です。

既に皆さんも御存知かと思いますが、弊社では開発生産性の向上に対して非常に力を入れています。

以前公開した↓の記事で、弊社の高い開発生産性を支えている取り組み、技術についてお話させていただきました。

tech.findy.co.jp

ありがたいことに、この記事を多くの方に読んでいただき反響をいただいております。

そこで今回は、↑の記事でも紹介されている「タスク分解」について更に深堀りしてお話しようと思います。

タスク分解は、弊社にJOINしたら最初に必ず覚えてもらう最重要テクニックの中の1つです。

それでは見ていきましょう!

タスク分解とは

何かしらの開発タスクを任されたあなたが最初にやるべきことは何でしょうか?

もしいきなりコードを書き出す人がいるのであれば、この記事を読むことをオススメします。

開発タスクを任された際、まず最初にタスクの洗い出しを行い、それらを可能な限り分解していきましょう。

分解したタスク毎にPull requestを作成することで、自然とPull requestの粒度を適切に保つことが可能になります。

まずはタスク分解におけるメリットを紹介します。

メリット

事前に対応方針の認識を合わせやすくなる

弊社ではGitHubのIssueにタスクリストを作成し、実装着手前にタスクリストをレビューしてもらうようになっています。

実際に対応する内容と、考えているタスクの内容が一致しているのか、対応する順番は適切か、などを確認して実装着手前に認識を合わせるようにしています。

これからのタスクの予定を目に見える形で確認することが出来るので、事前に対応漏れや考慮漏れに気づきやすくなり、手戻りの発生が減ります。

これにより工数見積の精度も上がり、開発スケジュールが大きくずれ込むことを防ぐことが出来るようになります。

Pull requestの粒度を適切に保つことが出来る

基本的に作成したタスクごとにPull requestを作成することになります。

Pull requestの粒度が大きくなってしまう原因の1つに、「やるべきことがどんどん増えていって、結果的に大きくなってしまった」というものがあります。

しかし、事前にタスクをある程度の粒度で切り出しているため、Pull requestを作成している途中に肥大化してしまうことが少なくなります。

それでも考慮漏れなどでPull requestの粒度が大きくなってしまうこともゼロではありません。その場合、着手中のタスクの粒度が大きいと判断し、そこから更にタスクを分解するようにします。

実装中にタスクを細分化することにより、意図しないPull requestの肥大化を防ぎ、結果的に適切な粒度のタスクリストに近づくようになります。

また、Pull requestのレビュワーからの視点だと「これからどんな事をしようとしているのか」がIssue内のタスクリストによって把握することが出来るようになります。

そのため、Pull requestの粒度が細かい状態でレビュー依頼が来たとしても、局所的なレビューではなく全体像をある程度把握した上でのレビューが可能となります。

進捗管理、引き継ぎをしやすくなる

タスクリスト内の終わったタスクにはチェックを入れ、進捗管理としても利用します。

全体を通してやるべきことと現在終わっていることがタスクリストを見ることで一目でわかるようになっているため、開発の進捗がどうなっているのか確認出来るだけでなく、他のメンバーに開発の引き継ぎをしやすくなります。

タスクの作り方

まず弊社では、GitHubのIssueのテンプレートにタスクリストの項目を用意しています。

---
name: Feature request
about: 新機能や改善等の仕様用

---

## なぜやるのか
<!-- やることになった背景等を書く -->


## ゴール
<!-- これをリリースすることで何を達成したいのか -->


## 仕様
### 概要
<!-- 量が多ければ、概要と詳細に分ける -->
<!-- 期待する・期待しない動作を書く -->

### タスクリスト
- [ ] add task

## 補足事項
### 懸念
<!-- 気になる点や仕様上での懸念事項等あれば記載する -->

## 関連Issue

このように、Issueを作成し開発に着手する前にタスクリストを作成することが必要であることを明確にしています。

また、チェックボックスで作成したタスクからIssueを直接作成する機能などもGitHubから提供されているので合わせて確認してみてください。

docs.github.com

具体例

例えば、「ユーザーデータの一覧を返すREST APIを追加する」タスクが割り振られたとしましょう。

これだけだと、タスクリストの初稿はこうなります。

- [ ] ユーザーデータの一覧を返すREST APIを追加する

これだけでは何がどう必要なのか、具体的によくわかりませんね。そこでPdMに確認すると、次のような要望が上がっているとのことでした。

- 登録しているユーザーの一覧を表示したい
- idとnameで絞り込みが出来るようにしたい

現状わかっている要件だけでタスク分解をしてみましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] name

とりあえず「動くもの」であれば、これだけで実装できそうです。

この状態でフロントエンド担当のメンバーにレビューしてもらいましょう。画面モックを確認するとページネーションとソートの機能が必要であることがわかりました。

ここでタスクを追加しておきましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] name
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

要件や必要な機能が少しずつ明確になってきましたね。次に他のバックエンドエンジニアにレビューしてもらいましょう。

すると、「nameの検索条件は完全一致、部分一致のどっちなのか?」という指摘をもらいました。

確かに画面モックから読み解くのは難しかったです。PdMと議論し、部分一致で実装することに決定しました。

ここで既存のタスクを修正しましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

一通りの要件はこれで揃ったようです。これで実装に着手していきましょう。

ところが実装を開始してテストコードを書いていると、退会ユーザーのレコードが存在している可能性が出てきました。この場合、退会ユーザーは一覧に表示したくありません。

この要件をタスクリストに追加しましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
    - [ ] 全件返す
    - [ ] 退会ユーザーは一覧から除外する
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

ひとまず全件データを返すところまでPull requestで対応して、別のPull requestで退会ユーザーを一覧から除外するコードを追加すればOKです。この様に、実装中にタスクを更に細分化することも十分ありえます。

ひとまず退会ユーザーを一覧から除外するところまで対応が完了したので、チェックボックスにチェックを入れて進捗を管理します。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [x] データベースからユーザーデータの一覧を取得して返す
    - [x] 全件返す
    - [x] 退会ユーザーは一覧から除外する
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

チェックを入れて進捗を管理することで、完了しているタスク、していないタスクを一目で確認することが可能になり、他のメンバーに開発の引き継ぎをしやすくなります。

今回は極端な例で紹介しましたが、タスクリストの作り方、整理の仕方を具体的に理解できたかと思います。

良いタスクリストを作るコツ

良いタスクリストを作成するためのコツは、最初から完璧なタスクリストを作ろうとしないことです。

まず最初に大枠のタスクを考え、そこから分解していくように意識してタスクリストを作成すると、結果的に詳細なタスクリストが完成しています。

小さくコツコツと修正を上乗せしていき、最終的に完成形に近づけていくような分解の仕方が良いでしょう。

大きな機能の実装担当になった際に、一度に全ての機能を実装するのではなく、小さい機能追加を何回も繰り返して結果的に大きな機能を完成させるようなイメージを持つと良いです。

まとめ

いかがでしたでしょうか?

実装コードを書く前の準備は非常に重要です。タスク分解の精度を上げることにより、結果的にスピード感を持った開発を行うことが出来るようになります。

現在、ファインディでは一緒に働くメンバーを募集中です。

興味がある方はこちらから ↓ herp.careers

2024年ふりかえり!Findy Tech Blogの人気記事まとめ

あけましておめでとうございます!

Findy Tech Blog編集長でソフトウェアプロセス改善コーチの高橋(@Taka_bow)です。

昨年2月末にスタートしたFindy Tech Blogが、なんと総PV数30万を突破しました!

ここまで成長できたのも、記事を読んでくださる皆さんのおかげです。本当にありがとうございます。

今日は2024年、特に人気を集めた記事をいくつかの視点からピックアップしてご紹介します。技術のトレンドから生産性向上テクニックまで、きっと皆さんの関心に響く記事が見つかるはずです。

それでは早速、ふりかえっていきましょう!

2024年下期トピックス

ITmedia NEWSの「IT企業デスクツアー」に取り上げて頂く

当ブログ人気シリーズ「【エンジニアの日常】エンジニア達の自慢の作業環境を大公開」で紹介した数々のデスク環境が、ITmedia様により改めて記事化して頂いてます!これは嬉しい!

「自慢の作業環境」の解説は、ブログの方が詳しいですのでぜひこちらもご覧ください。

下期では、Part5をリリースしております。

「修行をした話」から広がった新しい試み

2024年10月に公開した「プロダクト開発の修行をした話」シリーズが、新たな展開を見せました。弟子エンジニアと、師匠エンジニア、それぞれの視点で綴った2本のブログ記事が大きな反響を呼び、ついにはLTイベントの開催へと発展したのです。

このシリーズでは、実際のプロダクト開発現場で行われた「修行」の様子を、両者の生の声でお届けしました。技術的な学びはもちろん、メンターとメンティーの関係性の築き方、プロダクト開発を通じた成長の過程など、普段はなかなか表に出てこない貴重な体験が詳しく語られています。

そして、記事での反響を受けて実現したLTイベント。ブログには書ききれなかったエピソードや、視聴者から寄せられた質問への回答など、より深い内容をお届けできました。テックブログの新しい可能性を探る試みとなりました。

ブログでは語りきれなかった生の声を届ける、という新しいチャレンジをしました。

youtu.be

【2024年】年間総PV数ランキングTop3

ここからは、2024年一番アクセス(PV)のあった記事を紹介します!

第3位

\ 第3位 /19,305 PV

【エンジニアの日常】エンジニア達の人生を変えた一冊 Part3 - Findy Tech Blog

ファインディのエンジニアたちが自身の成長に影響を与えた一冊を語る人気シリーズ「エンジニア達の人生を変えた一冊 Part3」ランキング。

記事では、『マスタリングTCP/IP―入門編』や『ハッカーと画家 コンピュータ時代の創造者たち』、そして『UNIXという考え方』といった名著が取り上げられており、それぞれがどのようにエンジニアたちの視点やスキルに変化をもたらしたのかが語られています。

とても玄人なラインナップでしでしたが、とても読まれています。ぜひチェックしてみてください!

第2位

\ 第2位 /19,379 PV

【エンジニアの日常】エンジニア達の人生を変えた一冊 Part2 - Findy Tech Blog

第3位に続き、同じシリーズがランクイン!

この記事では、『SRE サイトリライアビリティエンジニアリング―Googleの信頼性を支えるエンジニアリングチーム』や『プログラマが知るべき97のこと』、そして『Clean Coder プロフェッショナルプログラマへの道』など、多くのエンジニアに愛読されている名著が取り上げられています。それぞれの書籍がどのように読者の成長を後押ししたのか、具体的なエピソードを交えて解説されています。

こちらも、ぜひチェックしてみてください!

第1位

\ 第1位 /20,108 PV

開発生産性指標を向上させるためにやってはいけないアンチパターン - Findy Tech Blog

2024年、最も多くの方に読まれた記事は「開発生産性指標を向上させるためにやってはいけないアンチパターン」でした。

開発現場で生産性向上に取り組む際、ついやってしまいがちな落とし穴について、実例を交えながら解説しています。デプロイ頻度やリードタイムといった指標を改善しようとするあまり、かえって本末転倒になってしまうケース。例えば、数字を上げるために無理にデプロイ回数を増やしたり、リードタイムを短くするためにコードレビューを省いたり...。一見、指標は改善されるものの、実は長期的に見るとチームの成長を阻害してしまう、そんな危険性を具体的に紹介しています。

「勝って兜の緒を締めよ」的、エンジニアの心構えを解いたブログです。

【2024年】はてなブックマーク数Top3

こちらでは、はてなブックマーク(はてブ)の数が多かったランキングをお届けします!*1

第3位

\ 第3位 /217 users

【エンジニアの日常】エンジニア達の人生を変えた一冊 Part1 - Findy Tech Blog

こちらでは「Part1」がエントリー!

記事では、ソフトウェアとビジネスの未来を描く『ソフトウェア・ファースト』や、組織運営とリーダーシップの重要性を説く『1兆ドルコーチ』、アジャイル開発の実践的な手法を学べる『アジャイルサムライ』、さらに長期的なコード品質を支える設計の重要性に触れた『Clean Architecture』が取り上げられています。

加えて、Appleのデザインを牽引したジョナサン・アイブ氏のキャリアや哲学を深掘りした『ジョナサン・アイブ』も紹介され、デザインとエンジニアリングの融合が生むイノベーションの重要性について考えさせられる内容が語られています。

第2位

\ 第2位 /218 users

開発生産性を上げるために開発をする前に考えていること - Findy Tech Blog

この記事では、開発をスムーズに進めるために、プロジェクト開始前に押さえておきたいポイントをまとめています。

プロジェクトのゴールをしっかり定めることはもちろん、ユーザー目線に立った設計の大切さ、既存の仕組みを上手く活用するコツ、将来の拡張も考えたシンプルな設計の進め方など、具体的な例を交えながら解説しています。段階的なリリースを通じて、ユーザーの声を活かしながら改善を重ねていく方法についても詳しく紹介されています。

日々の開発現場で使える知見が詰まっているので、プロジェクトの進め方を見直したい方や、開発の効率を上げたいと考えているエンジニア、マネージャーの方には、特に参考になるはずです。

第1位

\ 第1位 /328 users

IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却 - Findy Tech Blog

はてブが一番付いた記事は「IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却」でした!

2030年、日本のIT人材が約79万人不足するという衝撃的な予測をご存知でしょうか。この深刻な課題に対して、Findy Tech Blogでは「IT人材不足79万人の真因:生産性向上を阻む『人月の神話型請負』からの脱却」という記事を公開しました。 記事では、人材不足の根本的な原因として、日本のIT業界に根付いている「人月」という考え方と、ウォーターフォール型開発による従来の請負開発に着目。これらが開発現場の生産性向上を妨げ、人材不足を加速させている構造を丁寧に解き明かしていきます。 さらに、アジャイル開発の導入事例や新しい契約モデルの提案など、この課題を乗り越えるためのヒントも紹介しています。

おわりに

2024年に公開した73件の記事の中からほんの一部をご紹介させていただきました。

紹介しきれなかった記事もたくさんありますので、ぜひ他の記事もご笑覧頂ければと思います。 昨年は特に「【エンジニアの日常】シリーズ」に大きな反響をいただきました。これらのテーマは2025年も引き続き追求していきつつ、新しい技術への挑戦やファインディならではの爆速開発についても積極的に発信していきたいと思います。

そして何より、読者の皆さんとの対話を大切にしていきたい。記事へのコメントやSNSでの反応は、私たちの大きな励みになっています。

2025年も「面白い!」「参考になった!」と思っていただける記事をお届けできるよう、編集部一同張り切っていきますので、引き続きFindy Tech Blogをよろしくお願いします!


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers

*1:2024年12月31日時点で集計したランキングです。以後、増減する可能性はあります。

Findyのエンジニアおみくじの舞台裏を大公開!

新年、明けましておめでとうございます。

ファインディ株式会社でフロントエンドのリードをしている新福(@puku0x)です。

今年も「エンジニアおみくじ」の季節がやって参りました 🎉

企画の詳細につきましては↓の記事をご参照ください。

findy-code.io

今回はエンジニアおみくじ開発の舞台裏をお話ししようと思います。

エンジニアおみくじとは

エンジニアおみくじは Findy で毎年1月に開催しているイベントです。

期間中にFindyへログインし、引いたおみくじをシェアすると抽選でプレゼントがもらえます。

期間中は毎日おみくじを引けます。目指せ超大吉!

さらに今年はおみくじのパターンを増やしました。

その数、なんと 18万7,500通り !!

たくさんご用意しましたので是非お楽しみください。

舞台裏① 企画からエンジニアが関わる

ファインディでは、企画の段階からエンジニアがプロジェクトに参加しており、おみくじの内容に関してもエンジニアの監修が入っています。

エンジニアチームからは、用語やトレンドを共有したり、技術検証のフィードバックなどを行いました。運勢の一覧も皆でチェックしました。

おみくじにはエンジニアの監修が入っています

今年は年収やスキル偏差値などに加え、生成AIセキュリティといった項目が盛り込まれてあります。

中には思わずニヤニヤしてしまうものもあるでしょう。

面白い運勢が出ましたら「#Findyエンジニアおみくじ2025 」のハッシュタグを付けてシェアをお願いします。

舞台裏② おみくじパターンは18万通り以上

実は、これまでのエンジニアおみくじは「運勢別に固定の画像を返す」という仕様であり、画像作成の工数を抑えるため、60パターンしかありませんでした。

単純な構成だっため実装面では楽でしたが、画像を作成するデザインチームへの負担が大きいという課題がありました。また、おみくじを引き直した際に結果が重複する確率もそこそこあり、ユーザー体験の面からもパターンの増加は必須でした。

このような背景から、今回は運勢(6通り)、各項目(55通り)、コメント(10通り)からなる 6×5×5×5×5×5×10 = 187,5000 通りの組み合わせを用意することにしました。

すごい数ですね。ちなみに既存のやり方では休まず働いて15年かかる作成量であると試算されました。

すべての組み合わせの画像を手動で作成すると完成は...15年後!

ここはエンジニアチームの出番です💪

大量の組み合わせの画像を作成するのは現実的でないため、実装を根本から見直し、動的に画像へテキストを挿入する形式を採用しました。

// ※説明のためコードを一部変更しております
const textMaps = [
  // 年収
  {
    '超大吉': {
      0: '項目1',
      1: '項目2',
      2: '項目3',
      3: '項目4',
      4: '項目5',
    },
    '大吉': { ... },
    '中吉': { ... },
    :
  },
  // スキル偏差値
  {
    '超大吉': { ... },
    '大吉': { ... },
    :
// ※説明のためコードを一部変更しております
const noteMap = {
  '超大吉': {
    0: 'コメント1',
    1: 'コメント2',
    2: 'コメント3',
    3: 'コメント4',
    4: 'コメント5',
    5: 'コメント6',
    6: 'コメント7',
    7: 'コメント8',
    8: 'コメント9',
    9: 'コメント10',
  },
  '大吉': { ... },
  '中吉': { ... },
  :
// ※説明のためコードを一部変更しております
const ids = [...];
const index = '超大吉';
const texts = [textMaps[0][index][ids[0]], textMaps[1][index][ids[1]], textMaps[2][index][ids[2]], textMaps[3][index][ids[3]], textMaps[4][index][ids[4]]];
const note = noteMap[index][ids[5]];

return (
  <div style={{ backgroundImage: 'url(...)' }}>
    <span>{texts[0]}</span>
    <span>{texts[1]}</span>
    <span>{texts[2]}</span>
    <span>{texts[3]}</span>
    <span>{texts[4]}</span>
    <p>{note}</p>
  </div>
);

実装が新しくなったことで、将来的に運勢や項目が追加された場合でも柔軟に対応できるようになりました。

どのような内容になっているか気になった方は「#Findyエンジニアおみくじ2025 」でシェアされている投稿を是非ご覧ください。

まとめ

この記事では、Findyのエンジニアおみくじ実装の舞台裏をご紹介しました。

企画をより良いものにするためエンジニア、デザイナー、QA、マネージャーが一丸となって取り組んでおります。

過去に触ったことがあるという方におかれましても、これを機にアップデートされた「エンジニアおみくじ」をお試しいただければと思います 🙇‍♂️

findy-code.io

それでは、本年もよろしくお願いします。


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers

「改訂新版 良いコード/悪いコードで学ぶ設計入門」を使ったリファクタリングの事例

こんにちは!ファインディのプロダクト開発部でエンジニアをしているham (@hamchance0215)とEND(@aiandrox)です。 この記事はFindy Advent Calendar 2024 25日目の記事ということで、2人で共同執筆しています。

adventar.org

この記事について

ファインディでは日頃からお世話になっている皆さんに感謝の気持ちを込めて「Findyユーザー感謝祭 2024」を12/19に開催しました。

イベント中に、参加者の一人であるミノ駆動(@MinoDriven)さんが12/25発売の著書「改訂新版 良いコード/悪いコードで学ぶ設計入門」を参加者4名にプレゼントしてくださいました!

じゃんけんで勝った4名が書籍をゲットするルールであり、hamとENDがじゃんけんの強さを発揮して書籍をゲットし、なんやかんやあってこの記事を書くことになりました。

さらにサインも頂きました!

なんやかんや
なんやかんや

「改訂新版 良いコード/悪いコードで学ぶ設計入門」を使ったリファクタリングとは?

ユーザー感謝祭の懇親会でミノ駆動さんとお話しする機会があり、設計の知識を開発チームにインプットしていく方法について教えていただきました。

「改訂新版 良いコード/悪いコードで学ぶ設計入門」には、タイトルの通り「良いコード」だけではなく「悪いコード」の例もたくさん載っています。そこで、書籍に記載されている「悪いコード」をプロダクトのソースコードから探して「良いコード」にリファクタリングするという実践形式の学習をしているとのことです。

この学習方法、プロダクトのソースコードを使っていることから業務で活用できる生きた知識が身につくだけではなく、プロダクトがリファクタリングされて綺麗になっていくという一石二鳥な学習方法であり、とても興味を持ちました。

もっと知りたい方は、1/17にミノ駆動さん本人から紹介していただくイベントも企画されているのでぜひご覧ください!

findy.connpass.com

実践

それでは早速プロダクトのソースコードから「悪いコード」を探して「良いコード」へリファクタリングしていきます。

今回はFindy Team+のコードを使って実践しました。

実践1: 11.4 意図がわからない名前

実践1では「11.4 意図がわからない名前」に記載されている悪いコードを参考に探しました。

「意図がわからない名前」のデメリットについて、本著の一部を抜粋しました。

あいまいな変数名では、実際の意図に翻訳する作業が読むたびに必要になります。たとえば仕様変更の依頼があったとき、対応するメソッドや変数が何であるのか頭の中で翻訳作業が必要になります。また、チームに新しく参加したメンバーに対しての説明コストが増大します。

チーム開発において、コードは書くことより読むことの方が多いため、読み手に負担がかかっている状態は好ましくありません。

次のコードは、Team+で扱っている指標の1つである「LEAD_TIME_FOR_CHANGES_HOURS(変更のリードタイム)」を管理しているハッシュマップです。今回はこちらを対象にしました。

{
  statsType: 'LEAD_TIME_FOR_CHANGES_HOURS',
  expectData: {
    label: '変更のリードタイム',
    unit: 'h',
    negativePositive: true,
  }
}

各項目を見ていくと、labelは表示名でありunitは指標の単位であることが直感的にわかりますが、negativePositiveは何を意図しているかおわかりいただけるでしょうか?

negativePositiveは「値が小さいほど良い指標か?」を表すboolean型の変数です。 ただ、negative(値が小さいほど良い) or positive(値が大きいほど良い)を示そうとしているところまでは理解できますが、trueの場合にどちらなのかを変数名だけで判断するのは困難であり、実際の設定値などから意図を推測する必要がありました。

そこで、isLowerBetterへリネームしました。 下記が修正した箇所の差分の1つです。isLowerBetterに変更したことで「値が小さいほど良い指標」の場合、ifの中に入ることがコードから読み取れるようになりました。

- if(negativePositive) {
+ if(isLowerBetter) {
    // do something
  }

学習しながらリファクタリングしてマージまで完了!

merged

実践2: 7.1 ロジックの流用

Team+では、インポートに伴うさまざまな処理があり、それぞれを呼び出すBatchクラスも多く存在します。その中に、次のようなコードがありました。

module Batch
  class TransformXX < Batch::Base
    # @param [ActiveSupport::TimeWithZone] xx_after 存在する場合はXXの更新処理を行う
    def call(duration:, xx_after: nil)
      Transformer.call(duration:)

      # 実際にはここでXXをアップデートする処理が走る
      UpdateXX.call(start_at: xx_after) if xx_after
    rescue StandardError => e
      Rails.logger.error 'データ変換処理に失敗しました'
    end
  end
end

問題はこの引数です。

# @param [ActiveSupport::TimeWithZone] xx_after 存在する場合はXXの更新処理を行う

これは8.6 フラグ引数の節でも紹介されているものです。特に、Batchクラスでは引数によって処理を分岐しているものがちらほらあります。

フラグ引数付きのメソッドは、何が起こるか読み手の想像を難しくさせます。何が起こるのか理解するには、メソッド内部のロジックを見に行かなければなりません。可読性が低下し、開発生産性が低下します。

このBatchクラスは管理画面から呼び出される処理で、管理画面にチェックボックスがあるので、すぐにフラグを削除することは難しそうです。幸い、この条件分岐によってどう処理を行うかはクラスに切り出されており、可読性は悪くないと思われます。

問題は、このBatchクラスが管理画面を介する処理以外のいろんな箇所から呼ばれていることです。以下は一例です。

# Before
def transform_resources(start_at)
  Batch::TransformXX.call(duration: start_at..Time.current)
end

ここでは、xx_afterが指定されていないので、xx_afternilになっています。つまり、実際にはTransformerの処理しか行っていません。

ということで、不要な共通化をなくして直接実行クラスを呼び出すようにしました。このリファクタリングによって例外処理がなくなりましたが、ここでは例外処理を行う必要はなかったのでスッキリしました。

# After
def transform_resources(start_at)
  Transformer.call(duration:)
end

これにより、過度な共通化がなくなり、フラグ引数が散乱する懸念も少なくなりました。

実践3: 15.1.3 条件を読みやすくする

また、次のようにunlessnil?を使っている箇所がありました。

return unless user.nil?

二重否定となっていて読みづらかったため、次のようにリファクタリングしました。

return if user

注意するべき点としては、条件がfalseになりうる場合、nilと区別をする必要があります。そういった場合はunlessnil?を使う方がわかりやすいかもしれません。

まとめ

今回は「改訂新版 良いコード/悪いコードで学ぶ設計入門」を参考に、プロダクトのソースコードから「悪いコード」を探してリファクタリングしてみました。

本著では、さらに大きな「悪いコード」の事例についても紹介されており、実際に探してみるとそのようなコードもちらほらありました。短い時間だったため大きな設計変更はできませんでしたが、小さな変更でもコードの可読性が向上し、コードの意図が明確になることを実感しました。

また、なんとなく「悪いコード」と感じていた箇所が、本著を読んでみるとどのような問題があるのかが理解でき、リファクタリングの方向性が見えてきたのもよかったです。

今後も、本著を参考にしながら新規の設計やリファクタリングを行っていきたいと思います。


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers

GitHub Copilot in VS Code カスタムインストラクションの設定と効果検証【実践編】

こんにちは。

ファインディ で Tech Lead をやらせてもらってる戸田です。

弊社では開発生産性の向上のための投資、検証を継続して行っており、生成AIの活用にも取り組んでいます。

前回の記事で、導入編と題しましてGitHub Copilot in VS Codeのカスタムインストラクションの設定、利用方法を紹介しました。

tech.findy.co.jp

今回は実践編と題しまして、カスタムインストラクションに設定する内容の調整方法について紹介したいと思います。

それでは見ていきましょう!

まず叩き台を用意する

兎にも角にも、まず何かしらの叩き台を用意するのが良いです。一番手っ取り早いのは、開発組織におけるコーディングガイドラインを参考にすることです。

自分の場合は弊社のコーディングガイドラインのマークダウンテキストを丸っとコピペしてきました。カスタムインストラクションに渡す内容は日本語のテキストで問題なく動作するため、そのままコピペしてきても問題ありません。

.github/copilot-instructions.md を作成し、丸っとコピペしましょう。これを叩き台にして、Copilotが理解しやすい形に書き換えていきます。

Copilotが理解しやすい形に書き換えていく

コーディングガイドライン等から引用して、カスタムインストラクションに渡す内容の叩き台は用意できました。

次はその叩き台をCopilotが理解しやすい形に書き換えていきます。コーディングガイドラインは人間が理解しやすい形になっており、これをCopilot用に書き換えていきます。

※これから紹介する調整方法は、あくまで筆者の経験、調整内容に基づくもので、GitHubが公式に明言している内容ではありません。

不要なものは削除する

カスタムインストラクションに渡す内容は、正しい内容のみを簡潔に渡す方がCopilotから出力される内容がイメージに近いものになることが多かったです。

例えば、次のような内容があるとします。

## イベントハンドラの命名規則

- Component が受け取る Props は `on` + `アクション名` + `対象名`
- 関数そのものの名称は `handle` + `アクション名` + `対象名`

bad case
```tsx
export const HogeComponent = () => {
  const { onChangeHoge } = useHogeHooks();
  return <FugaComponent handleChangeHoge={onChangeHoge} />
}
```

good case
```tsx
export const HogeComponent = () => {
  const { handleChangeHoge } = useHogeHooks();

  return <FugaComponent onChangeHoge={handleChangeHoge} />
}
```

良い例と悪い例の両方をサンプルコードで説明しています。しかし、自分が色々調整した結果、Badケースの内容も取り込まれた生成されるコードになってしまうケースがありました。

これは仮説ですが、Copilot的には書いてある内容が正解であり、不要なケースは逆にノイズになるのではないかと思います。

そのため、次のようにBadケースやそこに至るまでの議論の内容などは全て削除し、結論のみを完結に記述するようにしました。

## イベントハンドラの命名規則

- Component が受け取る Props は `on` + `アクション名` + `対象名`
- 関数そのものの名称は `handle` + `アクション名` + `対象名`

```tsx
export const HogeComponent = () => {
  const { handleChangeHoge } = useHogeHooks();

  return <FugaComponent onChangeHoge={handleChangeHoge} />
}
```

これによりBadケースの内容が生成結果に反映されることはなく、生成されるコードがイメージに近いものになることが増えました。

長い文章よりも、簡潔な階層構造

カスタムインストラクションには、長文を渡すよりもマークダウンの階層構造で渡すほうが、Copilotが理解しやすいようでした。

例えば、次のような文章があるとします。

boolean型のPropertyを定義する場合、引数名には `is` をprefixで付け、それが共通コンポーネントの場合はoptionalにする。

このような文章の場合、次のようにマークダウンの階層構造で渡したほうがCopilotが理解しやすいようでした。

- boolean 型のProperty
  - 引数名に `is` を prefix で付ける
  - 共通コンポーネントの場合
    - optional にする

叩き台に長文が書かれていた場合、文章を分解し、マークダウン形式の段落構造などに書き換えるのをおすすめします。

曖昧な表現はNG

曖昧な言葉を使うと、Copilotはそれらを無視することが多かったです。

例えば次のような文章をカスタムインストラクションに渡すとします。

- 親コンポーネントからまとめてテストコードを書く
  - 子コンポーネントへの直接的なテストコードは不要

この場合、不要 という言葉が曖昧に受け取られ、この命令文を無視されることが多かったです。

こういったケースでは、次のように書き換えることでCopilotが理解しやすくなりました。

- 親コンポーネントからまとめてテストコードを書く
  - 子コンポーネントへの直接的なテストコードは書かない

不要書かない とシンプルに言い切ることによって、Copilotが理解しやすくなりました。

このようにCopilotが中々理解してくれないケースでは、言葉の表現を少し変えるだけで一気に理解度が上がることが多かったです。

確認用プロンプトでカスタムインストラクションに渡す内容を調整していく

ここまでで、ある程度の内容をカスタムインストラクションに渡すことが出来ているはずです。

次は、そのカスタムインストラクションの内容がCopilotにどのように理解されるかを確認していきます。

例えば、次のような内容をプロンプトとして用意します。

以下の条件を全て満たすコードを生成してください

- hooksである
- 引数は次の通り
  - カウント数の初期値
    - 任意項目
- 次の内容を変数で管理する
  - カウント数
    - 引数で受け取ったカウント数の初期値で初期化する
- 次の関数を用意する
  - カウント数をインクリメントする
  - カウント数をデクリメントする
- hooksから次の内容を返す
  - カウント数
  - カウント数をインクリメントする関数
  - カウント数をデクリメントする関数

このプロンプトをCopilotに渡して、生成されたコードを確認します。

import { useState } from 'react';

function useCounter(initialCount = 0) {
  const [count, setCount] = useState(initialCount);

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  return { count, increment, decrement };
}

export default useCounter;

プロンプトの内容を反映したコードが出力されました。ですが、これだけでは弊社のコードガイドラインと一致していない箇所がありました。そこでカスタムインストラクションの調整を行います。

次のような内容を .github/copilot-instructions.md に追記します。

## Hooks
- hooksから返す値は `as const` を付けてreadonlyにする

## イベントハンドラの命名規則

- Component が受け取る Props は `on` + `アクション名` + `対象名`
- 関数そのものの名称は `handle` + `アクション名` + `対象名`

```tsx
export const HogeComponent = () => {
  const { handleChangeHoge } = useHogeHooks();

  return <FugaComponent onChangeHoge={handleChangeHoge} />
}
```

この状態で先程のプロンプトを再実行すると、次のようなコードが生成されました。

import { useState } from 'react';

function useCounter(initialCount = 0) {
  const [count, setCount] = useState(initialCount);

  const handleIncrementCount = () => setCount(count + 1);
  const handleDecrementCount = () => setCount(count - 1);

  return { count, handleIncrementCount, handleDecrementCount } as const;
}

export default useCounter;

カスタムインストラクションに渡した内容通りに、関数名の変更と as const の追加が反映されました。更にここから何かしら調整を加えたい場合は、またカスタムインストラクションの内容を変更し、同じプロンプトを実行して新たに生成されたコードの内容をチェックする手順を繰り返します。

この作業を繰り返すことで、カスタムインストラクションの内容を調整していくことが出来ます。

まとめ

いかがでしたでしょうか?

今回は実戦編と題しまして、GitHub Copilot in VS Codeのカスタムインストラクションに設定する内容の調整方法について紹介しました。

カスタムインストラクションの説明や導入方法については次の記事を参考にしてみてください。

tech.findy.co.jp

弊社としましてもまだまだ検証段階ではありますが、カスタムインストラクションの内容を調整することで、Copilotのサジェスト内容や自動生成コードの質が向上したことを確認しています。

今回の記事が皆さんの開発生産性向上に少しでもお役に立てれば幸いです。

現在、ファインディでは一緒に働くメンバーを募集中です。

興味がある方はこちらから ↓ herp.careers

NxのGeneratorを活用した管理画面200ページのリニューアル事例

ファインディ株式会社でフロントエンドの開発をしております千田(@_c0909)です。

この記事はFindy Advent Calendar 2024 24日目の記事です。

adventar.org

転職サービス『Findy』の管理画面リニューアルプロジェクトで、約200ページ規模の開発をしました。

管理画面の機能は構成が似通っているため、NxのGeneratorによるコード自動生成を活用して画面作成の効率化を図りました。

本記事では、その取り組みについて共有させていただきます。

Nxについては以前の記事で紹介しておりますので、併せてご覧ください。

tech.findy.co.jp

Generator導入の背景

既存の管理画面は約50の機能で構成されています。

各機能には一覧・詳細・作成・編集の4種類の基本画面が必要となるため、合計で約200ページ(50機能 × 4画面)の開発が必要でした。

開発工数を試算したところ、コンポーネント作成、ロジック実装、テスト作成を含め、1画面あたり約160分の作業時間が必要になります。

これを単純計算すると、全画面の開発には約67日(160分/画面 × 200画面 ÷ 1日8時間)もの期間が必要という結果になりました。

そのため、構造が類似した200ページの開発の効率化を目指し、Generatorによるコードの自動生成を検討しました。

なぜNxのGeneratorなのか

冒頭でも書いたように、FindyにおいてはNxのGeneratorを選択しました。

その理由は既にNxを使っていたという背景に加え、次の技術的な利点があるためです。

Nxエコシステムとの親和性が高い

GeneratorがNxのコア機能として提供されているため、開発者は追加のセットアップの必要なく利用可能です。

公式やサードパーティのNxプラグインはGeneratorに対応しているものがほとんどであり、コンテキストスイッチの負荷を最小限にできます。

また、Nx ConsoleをIDEにインストールすれば、GUIからGeneratorを起動できます。

Nx Consoleはオプションの確認やコマンドのDry-runといった機能もサポートされているため便利です。

nx.dev

再利用性が高い

Generatorから他のGeneratorを呼び出すことができます。

これにより、Generatorの構成をシンプルに保つことができます。

export default async function(tree: Tree, schema: Schema) {
  // 設定ファイル群の追加
  generateFiles(
    tree,
    path.join(__dirname, 'files/feature'),
    `libs/projectName/src`,
    substitutions
  );

  // 特定のフィーチャーコンポーネントの追加
  generateFiles(tree, path.join(__dirname, 'files'), options.projectRoot, {
    ...names(options.name),
    importPath: options.importPath,
    projectRoot: options.projectRoot,
    ...
  });
}

nx.dev

Generatorに対するテストが書けるため、メンテナンスがしやすい

仮想ファイルシステムを利用してファイル生成の結果を確認できます。

例えば、次のようにJestでGenerateコマンド実行後のファイルの存在を確認できます。

import { Tree } from '@nx/devkit';
import generator from './generator';

it('should generate expected files', async () => {
  await generator(tree, defaultOptions);

  expect(tree.exists('/src/components/index.ts')).toBe(true);
});

どうやって対応したか

NxのGeneratorを使用したコード生成の実装について説明します。

実際にテンプレートファイルからファイルを生成するには、generateコマンドを利用します。

画面の雛形を生成するためのコマンドは次のように設計しました。

npx nx generate @findy-code/workspace-plugin:features user \
  --featureType=detail \
  --featureNameJa=ユーザー
  • user: 機能名(変数名やファイル名として使用)
  • --featureType: 画面タイプ(list/detail/create/edit)
  • --featureNameJa: 画面に表示する日本語名

これらの引数の設定はschema.jsonで行います。

{
  "$schema": "http://json-schema.org/schema",
  "properties": {
    "name": {
      "type": "string",
      "description": "The name of the feature (feature-<name>-{list,detail,create,edit}) .",
      "$default": {
        "$source": "argv",
        "index": 0
      },
      "x-prompt": "What name would you like to use?"
    },
    "featureType": {
      "type": "string",
      "description": "The mode of feature generation. Possible values are 'list', 'detail', 'create', 'edit', or leave empty to generate all types.",
      "default": ""
    },
    "featureNameJa": {
      "type": "string",
      "description": "The name of the feature in Japanese",
      "default": ""
    }
    ...
  }
}

次に、生成されるファイルのテンプレートを作成します。

例えば、 詳細画面用のカスタムフックのテンプレートは次のように実装しました。

export const use<%= functionName %>Detail = ({ <%= propertyName %>Id }: Props) => {
  const <%= propertyName %> = { id: <%= propertyName %>Id };
  // ここに詳細画面用のロジックを実装

  return {
    <%= propertyName %>
  } as const;
};

次のように展開されます。

export const useUserDetail = ({ userId }: Props) => {
  const user = { id: userId };
  // ここに詳細画面用のロジックを実装

  return {
    user
  } as const;
};

テンプレート内では<%= %>記法で動的な値を埋め込みます。

テンプレートファイルはsrc/__featureName__-detail.ts.templateという形式で作成し、ファイル名も可変にしています。

テンプレート内で使用するfunctionNamepropertyNameなどの変数は、Nxが提供する names関数を使用して適切な命名に変換します。

例えば、次のようにnames('my-name')と呼び出すことで、classNamepropertyNameconstantNameのように、よくある命名規則に従った文字列を作成できます。

names('my-name');
// {
//   name: 'my-name',
//   className: 'MyName',
//   propertyName: 'myName',
//   constantName: 'MY_NAME',
//   fileName: 'my-name'
// }

最後に、generateFiles関数を使用してファイルの生成を実装します。

この関数にテンプレートのディレクトリ、出力先のディレクトリ、そして置換する変数を指定することで、実際のファイル生成が行われます。

  const substitutions = {
    featureName: names(schema.name).name,
    featureNameJa: schema.featureNameJa,
    functionName: names(schema.name).className,
    ...
  };

  generateFiles(
    tree,
    path.join(__dirname, 'files/feature'), // テンプレートを定義しているファイルのディレクトリ
    `${options.projectRoot}/src`, // 生成したいディレクトリ
    substitutions // テンプレートで置換される変数
  );

これにより、コマンド1つで必要な画面の雛形を生成できるようになりました。

生成されるファイルには、カスタムフックの実装だけでなく、対応するテストファイルやコンポーネントなども対応しています。

今後やりたいこと

NxのGeneratorの導入により、画面を作り込むことは出来ましたが、新たな課題も見えてきました。

現在のGeneratorは画面のコードを一気に生成するため、ファイルの変更数が増えPull requestの粒度が大きくなり、レビューの負荷が高くなりました。

今後は、コード生成の粒度をより細かく制御できるように改善を進めていく予定です。

具体的には、画面を構成する要素ごとに生成を分割し、Componentの生成、ルーティング設定の追加、カスタムフックの実装といった単位でPull requestを作成できるようにすることで、レビューの負荷を軽減したいと考えています。

適切なPull requestの粒度については、既に以前の記事で紹介しておりますので、気になる方は是非ご覧ください。 tech.findy.co.jp

まとめ

この記事では、約200ページ規模の開発におけるNxのGeneratorを活用した事例をご紹介しました。

私自身、Nxを単にモノレポ管理ツールとして認識していましたが、今回のプロジェクトを通じてGeneratorという強力な機能の存在を知ることができました。

今回の取り組みを通じて、類似した構造を持つ画面を大量に開発する場合、NxのGeneratorが非常に効果的なツールとなることが分かりました。

この記事が皆様のプロジェクトにおける開発効率化のヒントになれば幸いです。

それでは、また次回の記事でお会いしましょう!


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers