開発ブログ一覧に戻る
開発ストーリー2026年3月19日

巨大ファイルを分割せよ — 保守性を高めるリファクタリング

一括採点の開発を続けるなかで、プログラムの「大掃除」を行いました。 1000行を超える巨大なファイルを分割し、使われていないコードを削除し、繰り返しのパターンを整理する。 今回は、この大規模なリファクタリングの裏側を、できるだけわかりやすくお伝えします。

なぜリファクタリングが必要だったのか

一括採点のようなソフトウェアは、機能を追加するたびにプログラムが大きくなります。 新しい機能を足すことに集中していると、気がつけば1つのファイルが1000行、1400行と膨れ上がっていることがあります。

これは、職員室の書類整理に似ています。 最初は1つの大きな箱に何でも入れていても困りません。 しかし書類が増えてくると、必要な書類を探すのに時間がかかり、間違った書類を取り出してしまうこともあります。 引き出しのない大きな箱は、中身が増えるほど使いにくくなるのです。

プログラムでも同じことが起きます。 1つのファイルにたくさんの処理が詰め込まれていると、「この部分を直したい」と思ったとき、関係のないコードをかき分けて目的の場所を探さなければなりません。 修正のつもりが、思わぬところに影響してバグを生んでしまうこともあります。

リファクタリングとは、ソフトウェアの動作は変えずに、プログラムの構造を整理し直すことです。 見た目や機能は変わりませんが、開発者にとっての「読みやすさ」「直しやすさ」が大きく向上します。

今回のリファクタリングでは、特に大きな2つのファイルが対象になりました。 APIの窓口となるpreload.ts(1251行)と、データベースの準備を行うdatabaseInitializer.ts(1432行)です。 どちらも一括採点の中核を担うファイルですが、あまりに多くの役割を抱えすぎていました。

preload.tsの分割 ― APIの窓口を整理する

preload.tsは、一括採点の画面側(ユーザーが操作する部分)と裏側(データの処理を行う部分)をつなぐ「窓口」の役割を持つファイルです。 学校でいえば、事務室の受付カウンターのようなものです。

ところが、この受付カウンターに「生徒の成績に関する問い合わせ」「答案用紙の管理」「試験の設定」「ファイルの書き出し」など、あらゆる業務が1か所に集中していました。 1251行もの長さになっていたのは、すべての業務を1人の受付係がこなしていたようなものです。

そこで、業務の種類ごとに窓口を分けることにしました。 具体的には、ドメイン(業務領域)ごとに別々のモジュールファイルを作り、それぞれが担当する業務だけを受け持つようにしました。

分割のイメージ
  • 生徒関連API:生徒の登録、検索、更新など
  • 試験関連API:試験の作成、設定の変更など
  • 答案関連API:答案用紙の取り込み、採点結果の保存など
  • ファイル関連API:PDFの出力、データの書き出しなど

あわせて、electron.d.ts(型定義ファイル)もドメイン別に分割しました。 型定義ファイルとは「この窓口ではどんな問い合わせを受け付けるか」を記した一覧表のようなものです。 窓口を分けたのに一覧表が1枚のままでは、結局探しにくいままですから、一覧表も業務ごとに分けたわけです。

databaseInitializer.tsの分割 ― 準備作業を分担する

databaseInitializer.tsは、一括採点が起動するときにデータベースを準備するファイルです。 学校の新年度準備に例えると、「教室の配置を決める」「名簿を作る」「時間割を組む」「備品を確認する」といった作業をすべてまとめて行う係のようなものでした。

1432行という長さは、新年度の全準備をたった1枚のチェックリストに書き込んでいるようなものです。 項目が多すぎて、どこに何が書いてあるのかわかりにくくなっていました。

これを「責務」ごとに分割しました。 テーブル(表)の作成、初期データの投入、バージョンアップ時の移行処理など、それぞれの作業を別のファイルに分けたのです。 新年度準備でいえば、「教室係」「名簿係」「時間割係」をそれぞれ決めて、担当を明確にしたイメージです。

また、Renderer側(画面に表示する部分)のコードもsrc/ディレクトリに統合しました。 これまであちこちに散らばっていたファイルを、1つのフォルダにまとめて見通しを良くした形です。

IPCハンドラの共通化 ― 同じ手順書をまとめる

一括採点では、画面側と裏側のやりとり(IPCと呼びます)が数多く存在します。 それぞれのやりとりには「エラーが起きたときの対処」を書く必要があるのですが、その書き方がほぼ同じパターンの繰り返しになっていました。

学校の業務で考えると、「出席簿の記入手順」「健康観察の記入手順」「給食の配膳手順」など、それぞれに「困ったときは教頭先生に連絡する」という同じ一文を書いていたようなものです。 手順書が10個あれば10回同じことを書き、20個あれば20回書く。もし連絡先が変わったら、すべての手順書を修正しなければなりません。

そこで、共通する「エラー処理」の部分をユーティリティ(便利な道具箱)として1か所にまとめました。 各手順書には「エラー時の対応は共通マニュアルを参照」と書くだけで済むようになり、修正するときも1か所を直せばすべてに反映されます。

同じコードが何度も繰り返されている状態を、開発者は「コードの重複」と呼びます。 重複が多いと、修正漏れによるバグが発生しやすくなります。 共通化することで、こうしたリスクを減らすことができます。

デッドコードの削除 ― 使わない道具を片付ける

プログラムを書き換えていくと、以前は使っていたけれど今は使われていない関数や変数が残ることがあります。 これを「デッドコード」と呼びます。

教室の道具箱に例えると、もう授業で使わなくなった古い教材がそのまま入っている状態です。 道具箱の中身が多すぎると、今使いたい道具を探すのに手間がかかります。 使わないものは思い切って片付けることで、本当に必要な道具がすぐに見つかるようになります。

今回は、未使用の関数や変数を一括で洗い出し、削除しました。 カスタムフック(画面の部品が共通で使う仕組み)の中にも、呼び出し元で使われていない返り値がありましたので、あわせて整理しています。

削除したものの例
  • 以前の機能で使っていたが、仕様変更で不要になった関数
  • デバッグ用に追加したまま残っていた変数
  • フックから返しているが、どの画面でも使われていない値

コードの量が減ることで、ファイルが読みやすくなるだけでなく、「この関数はまだ使われているのだろうか」と悩む時間もなくなります。

リファクタリングの効果

今回のリファクタリングは、一括採点の使い勝手が変わるものではありません。 先生方がお使いになるうえで、見た目や操作方法に違いはありません。 では、なぜこのような作業を行うのでしょうか。

それは、開発の速度と品質に直結するからです。 整理された職員室では書類がすぐに見つかり、仕事が速く進みます。 同じように、整理されたプログラムでは新しい機能の追加やバグの修正がスムーズに行えます。

  1. 開発速度の向上:ファイルが小さく分割されているので、目的の場所をすぐに見つけられます。 1400行のファイルを上から下まで読む必要がなくなりました。
  2. バグの減少:責務が明確に分かれているため、ある部分の修正が思わぬ場所に影響するリスクが下がります。 エラー処理の共通化により、修正漏れも防げます。
  3. 将来の拡張のしやすさ:新しい機能を追加するとき、適切なファイルに適切な量のコードを書くだけで済みます。 1つのファイルが際限なく膨らんでいく問題を防げます。
今回の作業まとめ
  • preload.ts(1251行)をドメイン別のAPIモジュールに分割
  • databaseInitializer.ts(1432行)を責務ごとに分割
  • IPCハンドラの重複try-catchパターンをユーティリティに集約
  • 未使用の関数、変数、デッドコードを一括削除
  • electron.d.tsの型定義をドメイン別に分割
  • Renderer側コードをsrc/ディレクトリに統合

リファクタリングは、部屋の片付けと同じです。 片付けたからといって部屋が広くなるわけではありませんが、必要なものがすぐ見つかり、生活がスムーズになります。 一括採点も、こうした地道な整理を続けることで、これからも安定して新しい機能をお届けできるようにしていきます。

関連記事

一括採点を使ってみませんか?

最新版をダウンロードして、採点作業を効率化しましょう。

最新版をダウンロード

一括採点

中学校の先生が、全国の先生のために作った、採点ツール。

© 2023-2026 KeppyNaushika. AGPLv3 オープンソースソフトウェアとして開発しています。