保守性の高い開発スキルを身につけ、それを周りの人にも共有していきたい!
自身の経験から、保守性の低い開発アプローチが不具合の特定を難しくし、新規実装や修正の効率を低下させることを痛感したからです。
特に、テストコードを実装し、リグレッション(デグレーション)を回避することが重要だと思っています。ただし、単にテストコードを実装していくだけでは、テスト実行にかかる時間が増えたり、プロダクトのコードをリファクタリングするだけで失敗するようなテストコードになったりして、次第にメンテナンスされない環境になる可能性もあります。そのため、テストに関するスキルを高めていくとともに、徐々に周囲の人々にもテストの重要性や実装方法を広めていきたいと考えています。現在も、「単体テストの考え方/使い方」や「フロントエンド開発のためのテスト入門」という本を読みながら、個人開発プロジェクトに取り入れて、自己研鑽に努めています。
1〜3年で、開発環境に合わせて効果的なテストコードが設計できるように成長し、チームメンバーにも知見を共有していきたいです。3〜5年後には、効果的なテストコードの実装をはじめとして、チーム全体が保守性の高い開発を行えるようにサポートできるエンジニアになりたいです。
製造企業向けに、製造業で必要となるさまざまな業務(製造管理・債権債務・受発注・在庫管理など)を一元的に支援する基幹システムを開発しています。プロジェクトは2020年に発足し、2022年5月に参画しました。
〜人員補充のため、製造管理系の開発を中断し、以下のチームに参画〜
債権債務系の機能を開発するチーム
共通・マスタデータ系の機能を開発するチーム
カレンダーライブラリを用いた製造スケジュールの管理用の機能開発
機能説明
日々の製造の情報(製品名・工場ライン・担当者・作業時間・作業内容など)を確認できる製造業務の担当部署向けの機能で、以下の3種類の画面を実装しました。
実装方法
カレンダーの機能を1から実装するのは大変なため、チームでカレンダーライブラリを選定しました。様々なライブラリのサンプルを確認しながら、要件を最も実現できそうなFullCalendarを使って実装することにしました。
課題
FullCalendarは幅広い機能を提供していますが、それでも、画面の要件を満たすためにはかなりのカスタマイズが必要でした。このため、各画面を実装するのに必要なコード量が大きくなり、1画面を1つのコンポーネントで実装すると、そのコンポーネントのコードが複雑化し、見通しを悪くする可能性がありました。
取り組み(工夫点)
カレンダーの構成要素を別コンポーネントに切り出したり、各画面で共通の処理をカスタムフックに切り出したりして、コードを細かく分割しました。例えば、以下のように切り出しました。
この工夫により、1コンポーネントで実装すると約3,000行ものコードが必要だった画面でも、多くのファイルが300行未満、最大でも約500行のファイルに分割することができました。これにより、1ファイル内のコードの複雑化を防止することができました。
顧客向け開発講習の実施
コード品質向上のためのコードレビュー文化の構築
課題
製造管理チームでは、コードレビューがチームリーダーに一任されており、負荷が集中したときに十分なレビューが行われないことが問題でした。その結果、品質や可読性が不十分なコードがマージされることがしばしばありました(実装経験の浅いメンバーが多かったのも要因の1つだと思います)。この状況が、不具合の修正や機能追加を困難にし、開発効率に悪影響を及ぼしていました。
取り組み
チームメンバーもレビュアーとして参加する提案をしました。この提案を行ったのは、チームメンバーがコード実装に深く関わっていることから、特に実装方法やコードの書き方のチェックが強化できると考えたためです。最終的に、1つのプルリクエストを2〜3人でレビューする文化を根付かせることができました。
工夫点
少しずつ慣れてもらうことを意識して、以下のような取り組みを行い、徐々にコードレビューの文化を作っていきました。
OPcacheの導入方法の調査と提案を行い、APIの高速化に貢献
課題
日々のシステム開発において、他のサービスと比較してAPIの動作がかなり遅く、個人的にストレスを感じていました。そのため、開発体験の向上のために改善したいと考えました。
取り組み
多くのAPIが遅い状況だったため、個別のAPIの実装方法ではなく、全体に影響する設定に焦点を当てて情報収集しました。そして、OPcacheが、実装コードの変更なしで高速化を実現できる仕組みであることを知りました。最初に、チーム内で試しに導入してみて、高速化が実現できることと、システムの動作に問題がないことを確認しました。その後、インフラチームに提案し、AWSにデプロイしている各環境にも導入することができました。
工夫点
OPcacheの導入がAPI全体に影響を及ぼすことから、単に勧めるだけでは受け入れられない可能性も考慮し、インフラチームへの提案方法を工夫しました。まず、OPcacheが実装コードをコンパイルするだけで、処理内容には影響を与えないという仕組みを伝え、導入に対する懸念を解消しました。さらに、事前にOPcacheの設定項目をブラッシュアップしておき、提案時にはその構成や各設定の効果を共有することで、スムーズに導入してもらえるようにしました。提案後から導入まで時間がかからなかったため、これらの工夫が功を奏したと感じています。
成果
ローカル環境で約1,000msかかっていた処理が約20msに短縮され、開発体験とユーザ体験が向上しました。
バックエンド側のCI導入
課題
定期的な内部ミーティングにおいて、Swaggerドキュメントの生成時やテストコードの実行時にエラーが発生する報告が何度もありました。この問題は、プルリクエストのチェックリストに記載されているにもかかわらず繰り返し発生しており、人手による不確実性が高いチェック方法では問題だと感じていました。また、ローカル環境でテストコードを実行するには、テストDBのマイグレーションやシーダーの実行が必要で、計30分以上の時間がかかっていました。この間は、他の開発を進めることも出来ず、時間を効率的に使えない問題がありました。
取り組み
問題が繰り返し発生していることから、人手によるチェックでは解決が難しいと判断し、GitHub Actionsを活用して自動化されたチェックシステムを導入しました。具体的には、既にあるプルリクエストのチェックリストを参考にして、次のチェックを導入しました。
成果
変更をマージする前に、確実に問題を発見できるようになりました。また、以前はローカル環境で30分以上かかっていた確認作業が、GitHub上で自動的に実行できるようになりました。このため、開発者はコード変更をプッシュした後、他のタスクを実施できるようになり、開発効率が向上しました。
フロントエンド側のCIにコードのフォーマットチェックを追加
課題
プロジェクト全体で、各開発者がファイル保存時の自動フォーマットを設定するルールになっていましたが、それでもフォーマットされていないコードがマージされることがありました。それを、後から自動フォーマットの設定を行っている人が変更すると、プルリクエストの変更差分にフォーマットされただけの行がたくさん表示され、レビューしづらい問題がありました。
取り組み
CIにPrettierによるフォーマットチェックを追加し、フォーマットされていないファイルがあるとCIが失敗するようにしました。これにより、フォーマットされていないコードがマージされるのを防止しました。
工夫点
Prettierでフォーマットした結果、稀に処理内容が変わってしまうことがあるため、単に全てのファイルを一括でフォーマットすると、不具合が発生してしまう恐れがありました。これを防止するために、CIではそのプルリクエストで変更したファイルのみをチェック対象にしました。これなら、変更したファイルについては、各開発者がそのタスク自体の動作確認を行う中で、自然とフォーマットされた状態で動作することも確認できるため、追加の手間をかけない形で導入することができたと考えています。
DBのコードマスタのコードをまとめたJavaScriptオブジェクトを自動生成するスクリプトの実装
課題
フロントエンドからDBのコードマスタテーブルの値を取得する際、値を特定するためのコードをハードコーディングしていたことが課題でした。これにより、コードを変更した場合、ハードコーディングされた部分を探し出して、同時に修正しなければならない課題がありました。
取り組み
この問題に対処するため、DBに接続してコードマスタの情報を自動的に取得し、CodeKey.<コード分類>.<コード>
という形式でコードを取得できるJavaScriptオブジェクトを生成するnpmスクリプトを作成しました。これにより、コードマスタテーブルに変更があった場合も、フロントエンド側はこのスクリプトを実行するだけで最新の情報を取得できるようにしました。
工夫点
JavaScriptオブジェクトを生成する際、ORDER BYによる順番の固定化とPrettierによるフォーマットを適用しました。これにより、コードが変更された以外での変更差分が検出されないようにし、変更を容易に追跡できるようにしました。
保守性の高い開発を学び、実践する場としてショッピングサイトを開発しています。
業務を通じて次のような思いが募り、この開発を始めました。
また、以下の理由から、開発の対象としてショッピングサイトを選びました。
効果的なテストコードの実装
課題
業務で初めてテストコードを実装する経験をしたのですが、それがリグレッション(デグレーション)を防止することに貢献している感覚がありませんでした。そして、実際に不具合が多発しました。この経験から、単にテストコードを実装するだけでなく、良いテストコードがどんなものか判断する考え方を身につける必要があると感じました。
取り組み
「単体テストの考え方/使い方」という本を読み、良いコードを書くための考え方を身につけました。また、本を読み進めながらこのプロジェクトで実践しました。
工夫点
効果的なテストコードを実装できるように、以下の工夫を行いました。
コード自動生成による実装の効率化
課題
これまでの開発を通じて、同じような情報を多重に管理することは、変更時にすべての場所を同時に更新しなければならないことから、保守性の観点で課題だと感じました。その一例として、APIのリクエスト・レスポンスの型を、フロントエンドとバックエンドの両方で管理することが挙げられます。
取り組み
APIのリクエスト・レスポンスの型をなるべく一元管理できるように、1箇所の情報から必要なコードを自動生成する仕組みを作りました。
具体的には、次のパッケージを導入し、バックエンド側に書いたコメントから、各エンドポイントと接続するReactフックを自動生成できるようにしました。
工夫点
以前から、API側のデータを扱うライブラリの中でも、TanStack Queryは使いやすく、コードもシンプルに保てるライブラリだと思い、好んで使っていました。そのため、今回の自動化を行う中でも、なるべくTanStack Queryを用いた場合と同じような実装ができるものを探しました。Orvalは、TanStack Queryライクに使えるReactフックを生成できる数少ないライブラリであり、最近もしっかりとメンテナンスされていることから、採用することにしました。
静的型付け言語の採用
課題
動的型付け言語(JavaScript, PHP)を使った大規模なシステム開発を経験する中で、エラーの早期発見が難しいことや、型が明示されていない他人のコードを理解するのが難しいことなどを課題に感じました。
取り組み
静的型付け言語を使用することで上記の問題は軽減できると考え、フロントエンド開発にTypeScript、バックエンド開発にGoを採用し、静的型付け言語の強みを体験することにしました。その結果、オブジェクトのプロパティや関数の引数などを変更した際に、ビルドエラー等で付随箇所の修正漏れに気づくことができ、安心してデプロイできるようになりました。また、採用した副作用として、静的型付け言語を使用すると、コードエディタの「定義/参照に移動」が適切に機能し、開発効率自体も大きく向上することが分かりました。
Astroファイルのimport文をソートするprettier-plugin-astro-organize-imports
というPrettierプラグインを開発しました。このプラグインはnpmパッケージとして公開されており、実際に利用することができます。
プロジェクト全体でコーディングスタイルを揃えることは、コードの書き方における個人差を小さくし、可読性を向上させる上で重要だと考えています。それは、import文の順序においても言えることだと考えています。そこで、個人開発におけるTypeScriptプロジェクトでは、prettier-plugin-organize-importsというPrettierプラグインを活用し、import文をフォーマットしています。
ところで、私は、高速な静的サイトを構築できるAstroというフレームワークを使った開発を行っています(リンク)。Astroは独自の言語を持っており、.astro
という拡張子のファイルとして作成されます。この言語は、HTMLやJavaScriptの文法に似ており、import文も存在しますが、上記のPrettierプラグインは対応していません。そこで、Astro用のプラグインを開発することにしました。
他のPrettierプラグインと併用できる仕組みづくり
課題
開発したプラグインは、Prettierプラグインの本来の仕様とは異なりました。通常、Prettierプラグインは、標準でサポートされていない言語向けにフォーマッタを提供するために設計され、1言語に1つのフォーマッタを持つことが一般的です。しかし、今回のプラグインは局所的な用途(import文のソート)を持つため、Astro用の他プラグインとも併用して使えることが重要だと考えました(特に、Astroの公式フォーマッタがプラグインとして公開されているため、このプラグインと併用できることはマストだと思います)。
取り組み
仕組みが似ている以下の既存プラグインのソースコードを参考にしながら開発を進めました。
工夫点
import文をソートするというシンプルなプラグインのため、Astro用の他プラグインと併用可能であるとともに、単独でも動くようにしました。
Prettier 3のサポート
課題
このプラグインは、Prettierの最新バージョンが2系のときに開発しました。しかし、公開後にPrettier 3がリリースされ、そのバージョンでは動作しない問題が発生しました。
取り組み
Prettier 3の環境で動作するように、以下の流れでプラグインをアップデートしました。