レガシーコードを「見える化」する:ESLintカスタムルールによる技術負債の防波堤
大規模なJavaScript/TypeScriptプロジェクトにおいて、最も恐ろしいのは「見えない依存関係」です。特に、何年も前に作られた巨大な「神クラス(BaseClass)」を無秩序に継承し続けることは、コードの柔軟性を奪い、修正のたびに予期せぬ副作用を生む爆弾を埋め込んでいるのと同義です。
今回は、単なるフォーマットチェックではない、「アーキテクトの視点でコードの依存関係を制御する」ための、ESLintカスタムルールの実装術を伝授します。これを導入すれば、チームメンバーが誤って危険なクラスを継承しようとした瞬間、IDE上で「待った」をかけることができます。
—
1. なぜ「静的解析」で継承を制御するのか?
多くの現場では、リファクタリングを「個人の努力」や「規約(ドキュメント)」に頼っています。しかし、人間は忘れる生き物です。
ESLintのカスタムルールは、コードを単なる文字列ではなく、AST(抽象構文樹:Abstract Syntax Tree)として解析します。ASTの世界では、`class Child extends LegacyBase` というコードは、「クラス宣言ノード」の中に「継承(SuperClass)」という情報が明確に保持されています。これを利用すれば、特定のクラスを継承するコードを、ビルド前に即座に摘発できるのです。
—
2. 基盤となる環境セットアップ
まず、ESLintのプラグイン開発環境を準備します。既存プロジェクトに直接書き込むのではなく、`eslint-plugin-local-rules` のような構成にするのが、管理の鉄則です。
プロジェクト直下にルールを格納するディレクトリを作成
mkdir -p eslint-rules/rules
次に、ルールを読み込ませるための設定です。`.eslintrc.js` に以下のように記述します。
module.exports = {
// ローカルルールを読み込むためのプラグイン設定
plugins: [“local-rules”],
rules: {
// 警告レベルを ‘error’ に設定することで、CI/CDで確実にブロックする
“local-rules/no-legacy-base-class”: “error”
}
};
—
3. 【核心】危険な継承を特定するカスタムルールの実装
`eslint-rules/rules/no-legacy-base-class.js` を作成します。これが、あなたのプロジェクトを守る「門番」となります。
module.exports = {
create(context) {
return {
// ClassDeclaration(クラス宣言)をASTから抽出
ClassDeclaration(node) {
// extends句がないクラスは無視
if (!node.superClass) return;
// 継承先のクラス名が ‘LegacyBaseService’ であるかを判定
if (node.superClass.name === ‘LegacyBaseService’) {
context.report({
node,
message: “警告: ‘LegacyBaseService’ の継承は非推奨です。新規クラスではCompositionパターンを使用してください。”
});
}
}
};
}
};
このコードがやっていること
1. ASTの走査: プロジェクト内の全クラス定義をスキャンします。
2. 型ではなくノードで判定: `node.superClass.name` を見ることで、型定義ファイル(.d.ts)の読み込みを待たずに、名前ベースで即座に継承関係を検知します。
3. コンテキストによる通知: `context.report` を呼ぶことで、VS Codeの波線警告やCLI上のエラーとして表示させます。
—
4. 動作確認:HelloWorldならぬ「WarningWorld」
実際に、意図的にレガシーなクラスを継承するコードを作成してみます。
// 修正対象のコード
class NewFeatureService extends LegacyBaseService {
// ここでESLintがエラーを吐く!
}
このファイルを保存した瞬間、VS Codeの「問題」パネルに、先ほど設定した警告メッセージが表示されます。これで、「後で直そう」という技術負債の温床が、生まれた瞬間に可視化されることになります。
—
5. アーキテクトからのアドバイス:運用を成功させる鍵
この仕組みを導入する際、最も重要なのは「いきなり厳しくしすぎないこと」です。
- 段階的導入: まずは `warn` レベルでCIに流し、チーム内で「どのクラスが継承を禁止すべきか」をコンセンサスを取ってください。
- 代替案の提示: ルールのエラーメッセージに「代わりに `BaseCompositionService` を使ってください」とリンクを貼るのが、最高に親切な設計です。
コード品質をツールで制御することは、チームから「細かい指摘」の負荷を減らすことに繋がります。人間はコードのロジックに集中し、退屈な規約チェックは機械に任せる。これこそが、開発効率を極限まで引き上げるための第一歩です。
明日から、あなたのチームのコードベースに「守護神」を配置してみませんか?きっと、数ヶ月後のコードの健全性が驚くほど変わっているはずですよ。