## プロジェクト要約
製造企業向けに、製造業で必要となるさまざまな業務(製造管理・債権債務・受発注・在庫管理など)を一元的に支援する基幹システムを開発しています。プロジェクトは2020年に発足し、2022年5月に参画しました。
## プロジェクト体制
- 開発に関わる人数:約50人
- チーム体制:製造管理・債権債務などの業務カテゴリごとのチームに分かれて開発(リポジトリは共有)
## 技術スタック
- フロントエンド:JavaScript, React 17, React Router 5, Redux 4, Redux Form, redux-saga, Reactstrap, Tailwind CSS 2, FullCalendar, Prettier
- バックエンド:PHP 7.4, Laravel 8, Docker
- データベース:MySQL 8
- 開発支援ツール:GitHub, Slack, Notion, Jira, Confluence
## 配属チーム情報
1. 製造管理系の機能を開発するチーム
- **配属期間**:2022年5月 〜 2023年7月
- **人数**:4〜6人(時期により変動)
- **役割**
- フロントエンドおよびバックエンドの開発
- テスト仕様書作成・テスト実施
- 仕様が煮詰まっていない担当機能の設計(自ら顧客と話し合いながら仕様を固めていくこともありました)
- **担当した主な開発内容**
- カレンダーライブラリを用いた月別・日別の製造スケジュール管理画面の開発
*〜人員補充のため、製造管理系の開発を中断し、以下のチームに参画〜*
2. 債権債務系の機能を開発するチーム
- **配属期間**:2023年8月 〜 現在
- **人数**:約15〜20人(時期により変動)
- **役割**
- フロントエンドおよびバックエンドの開発
- **担当した主な開発内容**
- 既存の債権債務機能の不具合修正
- 債権債務で必要な帳票(PDF, CSV, Excel)のデータ作成・出力機能の開発
- ~各債権債務機能のインボイス対応(これから本格的に実施)~(スケジュールを見直した結果、2024年3月ごろから実施予定)
3. 共通・マスタデータ系の機能を開発するチーム
- **配属期間**:2023年8月 〜 2023年9月中旬(債権債務チームと掛け持ちでしたが、債権債務系の機能開発により人員を割く方針となり、そちらに注力することになりました)
- **人数**:4人
- **役割**
- フロントエンドおよびバックエンドの開発
## 担当業務抜粋
1. カレンダーライブラリを用いた製造スケジュールの管理用の機能開発
- **機能説明**
日々の製造の情報(製品名・工場ライン・担当者・作業時間・作業内容など)を確認できる製造業務の担当部署向けの機能で、以下の3種類の画面を実装しました。
1. 月単位で情報を表示する画面(Googleカレンダーの月単位表示のようなレイアウト)
2. 日単位で担当者別に情報を表示する画面(Googleカレンダーの日単位表示のようなレイアウト)
3. 日単位で工場ライン別に情報を表示する画面(Googleカレンダーの日単位表示で、列が工場ラインになったようなレイアウト)
- **実装方法**
カレンダーの機能を1から実装するのは大変なため、チームでカレンダーライブラリを選定しました。様々なライブラリのサンプルを確認しながら、要件を最も実現できそうなFullCalendarを使って実装することにしました。
- **課題**
FullCalendarは幅広い機能を提供していますが、それでも、画面の要件を満たすためにはかなりのカスタマイズが必要でした。このため、各画面を実装するのに必要なコード量が大きくなり、1画面を1つのコンポーネントで実装すると、そのコンポーネントのコードが複雑化し、見通しを悪くする可能性がありました。
- **取り組み(工夫点)**
カレンダーの構成要素を別コンポーネントに切り出したり、各画面で共通の処理をカスタムフックに切り出したりして、コードを細かく分割しました。例えば、以下のように切り出しました。
- カレンダーのヘッダーや1列の表示を別コンポーネントとして切り出し
- APIから必要なデータを取得し、加工する処理をカスタムフックとして切り出し
この工夫により、1コンポーネントで実装すると約3,000行ものコードが必要だった画面でも、多くのファイルが300行未満、最大でも約500行のファイルに分割することができました。これにより、1ファイル内のコードの複雑化を防止することができました。
2. 顧客向け開発講習の実施
- **要約**:顧客がシステムの運用・保守を行うため、開発講習を実施
- **期間**:2023月4月〜2023年10月(週1回の頻度)
- **体制**:フロントエンド担当(私)とバックエンド担当の2人体制
- **講習の内容**
基幹システムの開発で必要となる以下のスキルを習得できるように指導しました。
- フロントエンド / バックエンドの開発環境の構築
- CRUD機能を備えたAPIの実装
- 検索画面・詳細画面・編集画面・および編集内容の最終確認画面の実装
- **実施形式**
- Discordを使用し、顧客の1人が画面を共有しながらハンズオン形式で実施。
- Discordの複数人が同時に画面を共有できる利点を生かし、行き詰まった人がいれば、その都度画面共有していただきながら、一緒に問題解決するようにしました。
- **工夫点**
- 週1回の講習では十分なスキル習得が難しいと考え、毎回課題を提供することで、自己学習の機会を作りました。
- ハンズオンの内容をConfluenceに記載して共有することで、後からでも各々が振り返りやすいようにしました。
- 最後にリファクタリング手法(コンポーネント分離やReduxのセレクタ関数の切り出しなど)について簡単に紹介し、コードの可読性を意識する機会を作りました。
## 改善活動
1. コード品質向上のためのコードレビュー文化の構築
- **課題**
製造管理チームでは、コードレビューがチームリーダーに一任されており、負荷が集中したときに十分なレビューが行われないことが問題でした。その結果、品質や可読性が不十分なコードがマージされることがしばしばありました(実装経験の浅いメンバーが多かったのも要因の1つだと思います)。この状況が、不具合の修正や機能追加を困難にし、開発効率に悪影響を及ぼしていました。
- **取り組み**
チームメンバーもレビュアーとして参加する提案をしました。この提案を行ったのは、チームメンバーがコード実装に深く関わっていることから、特に実装方法やコードの書き方のチェックが強化できると考えたためです。最終的に、1つのプルリクエストを2〜3人でレビューする文化を根付かせることができました。
- **工夫点**
少しずつ慣れてもらうことを意識して、以下のような取り組みを行い、徐々にコードレビューの文化を作っていきました。
- 意欲のある私が積極的にコードレビューに参加し、より良い実装方法がありそうなら積極的に提案しました。これにより、レビュアーの活動内容を理解してもらいました。
- 私が担当するタスクに関しては、その領域に知見があるメンバーや、(改修タスクの場合は)以前この機能を実装したメンバーにレビューを依頼しました。これにより、まずはレビューしやすいところから取り組んでもらい、レビュアーの役割に段階的に慣れてもらいました。
2. OPcacheの導入方法の調査と提案を行い、APIの高速化に貢献
- **課題**
日々のシステム開発において、他のサービスと比較してAPIの動作がかなり遅く、個人的にストレスを感じていました。そのため、開発体験の向上のために改善したいと考えました。
- **取り組み**
多くのAPIが遅い状況だったため、個別のAPIの実装方法ではなく、全体に影響する設定に焦点を当てて情報収集しました。そして、OPcacheが、実装コードの変更なしで高速化を実現できる仕組みであることを知りました。最初に、チーム内で試しに導入してみて、高速化が実現できることと、システムの動作に問題がないことを確認しました。その後、インフラチームに提案し、AWSにデプロイしている各環境にも導入することができました。
- **工夫点**
OPcacheの導入がAPI全体に影響を及ぼすことから、単に勧めるだけでは受け入れられない可能性も考慮し、インフラチームへの提案方法を工夫しました。まず、OPcacheが実装コードをコンパイルするだけで、処理内容には影響を与えないという仕組みを伝え、導入に対する懸念を解消しました。さらに、事前にOPcacheの設定項目をブラッシュアップしておき、提案時にはその構成や各設定の効果を共有することで、スムーズに導入してもらえるようにしました。提案後から導入まで時間がかからなかったため、これらの工夫が功を奏したと感じています。
- **成果**
ローカル環境で約1,000msかかっていた処理が約20msに短縮され、開発体験とユーザ体験が向上しました。
3. バックエンド側のCI導入
- **課題**
定期的な内部ミーティングにおいて、Swaggerドキュメントの生成時やテストコードの実行時にエラーが発生する報告が何度もありました。この問題は、プルリクエストのチェックリストに記載されているにもかかわらず繰り返し発生しており、人手による不確実性が高いチェック方法では問題だと感じていました。また、ローカル環境でテストコードを実行するには、テストDBのマイグレーションやシーダーの実行が必要で、計30分以上の時間がかかっていました。この間は、他の開発を進めることも出来ず、時間を効率的に使えない問題がありました。
- **取り組み**
問題が繰り返し発生していることから、人手によるチェックでは解決が難しいと判断し、GitHub Actionsを活用して自動化されたチェックシステムを導入しました。具体的には、既にあるプルリクエストのチェックリストを参考にして、次のチェックを導入しました。
- PHPのPSR-4エラーチェック
- Swaggerドキュメント生成時のWarningやシンタックスエラーのチェック
- マイグレーションの動作確認
- シーダーの動作確認
- テストコードの動作確認
- **成果**
変更をマージする前に、確実に問題を発見できるようになりました。また、以前はローカル環境で30分以上かかっていた確認作業が、GitHub上で自動的に実行できるようになりました。このため、開発者はコード変更をプッシュした後、他のタスクを実施できるようになり、開発効率が向上しました。
4. フロントエンド側のCIにコードのフォーマットチェックを追加
- **課題**
プロジェクト全体で、各開発者がファイル保存時の自動フォーマットを設定するルールになっていましたが、それでもフォーマットされていないコードがマージされることがありました。それを、後から自動フォーマットの設定を行っている人が変更すると、プルリクエストの変更差分にフォーマットされただけの行がたくさん表示され、レビューしづらい問題がありました。
- **取り組み**
CIにPrettierによるフォーマットチェックを追加し、フォーマットされていないファイルがあるとCIが失敗するようにしました。これにより、フォーマットされていないコードがマージされるのを防止しました。
- **工夫点**
Prettierでフォーマットした結果、稀に処理内容が変わってしまうことがあるため、単に全てのファイルを一括でフォーマットすると、不具合が発生してしまう恐れがありました。これを防止するために、CIではそのプルリクエストで変更したファイルのみをチェック対象にしました。これなら、変更したファイルについては、各開発者がそのタスク自体の動作確認を行う中で、自然とフォーマットされた状態で動作することも確認できるため、追加の手間をかけない形で導入することができたと考えています。
5. DBのコードマスタのコードをまとめたJavaScriptオブジェクトを自動生成するスクリプトの実装
- **課題**
フロントエンドからDBのコードマスタテーブルの値を取得する際、値を特定するためのコードをハードコーディングしていたことが課題でした。これにより、コードを変更した場合、ハードコーディングされた部分を探し出して、同時に修正しなければならない課題がありました。
- **取り組み**
この問題に対処するため、DBに接続してコードマスタの情報を自動的に取得し、`CodeKey.<コード分類>.<コード>`という形式でコードを取得できるJavaScriptオブジェクトを生成するnpmスクリプトを作成しました。これにより、コードマスタテーブルに変更があった場合も、フロントエンド側はこのスクリプトを実行するだけで最新の情報を取得できるようにしました。
- **工夫点**
JavaScriptオブジェクトを生成する際、ORDER BYによる順番の固定化とPrettierによるフォーマットを適用しました。これにより、コードが変更された以外での変更差分が検出されないようにし、変更を容易に追跡できるようにしました。
## その他で自発的に取り組んだこと
1. 勉強会の実施
- 製造管理系のチームは、多くのチームメンバーが同時期に入社し、ほぼその入社したメンバーで構成されていました。React開発の経験がない人もいたため、JavaScript, React, Reduxの基本的な使い方や、Mac, VSCodeの便利なショートカットキー・拡張機能を紹介しました。
- チームでのテストコードの書き方に問題があると感じていたため、「[単体テストの考え方/使い方](https://book.mynavi.jp/ec/products/detail/id=134252)」という本を読んだ上で、内容をピックアップして紹介しました(AAAパターンや、各テストケースが互いに影響しないように実装することなど)。
- ChatGPTを使い、開発業務の効率が上がったと感じたため、基本的な使い方・うまく使うためのコツ・注意点などを紹介しました。
2. Notionでの情報共有(これまでに30ページ以上を共有)
- 開発環境構築の手順書作成
- プロジェクトのディレクトリ構成や利用パッケージの紹介
- 自分が実装する上で行き詰まった箇所の解決方法の共有
3. 開発体制の改善
- マージされていないPRを毎日リマインドするSlackのbotを、Google Apps Scriptで開発