レガシーの鎖を断ち切る:ESLintカスタムルールによる「継承の可視化」戦略
大規模プロジェクトにおいて、最も恐ろしいのは「どこで誰が作ったのか分からない神クラスを継承した、肥大化した子クラス」です。これらは依存関係のクモの巣を作り、テストの難易度を跳ね上げ、修正のたびに予期せぬ副作用を生みます。
多くの現場では、これを「リファクタリングしたいね」という精神論で片付けますが、我々アーキテクトがやるべきは、「人間ではなくルールにコードを監視させる」こと。今回は、ESLintのカスタムルールを駆使し、レガシーな基底クラスへの依存を静的解析で「強制的にあぶり出す」方法を伝授します。
—
1. なぜ「継承」を静的解析で縛るべきなのか
継承関係は、静的解析ツールにとって最も検出しやすい「強結合」のシグナルです。
`extends BaseLegacyClass` と書かれた瞬間、そのクラスは基底クラスのすべてのメソッドと暗黙的な状態を共有することになります。この依存関係をCI/CD上で阻止できなければ、負債は指数関数的に増殖します。
我々のゴールは「今すぐ全てを直す」ことではなく、「これ以上、負債の穴を深く掘らせない」こと。この一点に尽きます。
—
2. 「継承の禁じ手」を実装する:ESLintカスタムルールの作成
`eslint-plugin-local-rules` を使用し、特定の基底クラスを継承しようとした瞬間にエラーを吐くルールを実装します。
// eslint-rules/no-legacy-inheritance.js
module.exports = {
meta: {
type: ‘suggestion’,
docs: { description: ‘レガシーな基底クラスの継承を禁止する’ },
messages: {
noLegacy: ‘警告: {{name}} を継承することは非推奨です。依存関係を分離し、コンポジションへの移行を検討してください。’
}
},
create(context) {
// 継承を禁止したいクラス名のリスト
const FORBIDDEN_CLASSES = [‘LegacyBaseController’, ‘AbstractOldService’];
return {
ClassDeclaration(node) {
if (node.superClass && node.superClass.type === ‘Identifier’) {
const className = node.superClass.name;
if (FORBIDDEN_CLASSES.includes(className)) {
context.report({
node,
messageId: ‘noLegacy’,
data: { name: className }
});
}
}
}
};
}
};
このルールを導入するだけで、CIの静的解析フェーズで「レガシー継承」が即座にブロックされます。開発者は「なぜダメなのか」をコードレビューではなく、エディタ上で即座に理解することになります。
—
3. 生産性を極限まで高める:開発環境のベストプラクティス
単にルールを導入するだけでは不十分です。開発者の「体験」を変えなければ、ルールは形骸化します。
神プラグイン・構成設定
1. ESLint `lint-staged` の徹底活用:
コミット時に全ファイルを走査するのは時間の無駄です。`husky` + `lint-staged` で「変更したファイルのみ」を対象に、プリコミットフックで弾くのが鉄則。
// .lintstagedrc.json
{
“.{js,ts,tsx}”: [
“eslint –fix”, // 自動整形とルールチェックを同時に実施
“prettier –write” // スタイルの一貫性を強制
]
}
2. VS Code設定の共有(.vscode/settings.json):
チーム全員の環境で「保存時に自動でESLintを走らせ、継承エラーを可視化する」設定を強制します。
{
“editor.codeActionsOnSave”: {
“source.fixAll.eslint”: true // 保存の瞬間にクリーンなコードへ
},
“eslint.validate”: [“javascript”, “typescript”]
}
隠れたキーボードショートカット(VS Code)
- `Ctrl + .` (Cmd + .): Quick Fix。エラー箇所にカーソルを合わせ、即座に「ルールを無視する(// eslint-disable)」か「修正する」かを選択。思考を止めないために必須です。
—
4. アーキテクトからの提言:負債とどう付き合うか
このカスタムルールを導入すると、現場から必ず「既存のコードでエラーが出て困る」という声が上がります。ここで真価が問われます。
- 段階的移行のロジック:
最初は `type: ‘suggestion’`(警告)として導入し、CIは通る状態にします。
次に、週単位で `type: ‘error’`(エラー)へ昇格させるチーム目標を立てる。
これにより、「リファクタリングをタスクとして積む」のではなく、「日々の作業の中で少しずつ削り出す」という開発文化が醸成されます。
結び
コード品質とは、綺麗なコードを書くことではなく、「崩壊を防ぐガードレールをどれだけ賢く設計できるか」にあります。ESLintは単なる構文チェッカーではありません。チームの規律を守るための、最強の「自動化されたテックリード」です。
今日からこのルールを導入し、レガシーの呪縛からチームを解放してください。次にコードを開くとき、そこには「これ以上悪化させない」という確固たる意志があるはずです。