Skip to content

よくあるアンチパターン

TypeScriptでよくあるアンチパターンと、実際に事故った構造を詳しく解説します。

// ❌ アンチパターン: メモリリーク
class DataManager {
private data: any[] = [];
addData(item: any) {
// 問題: データが削除されず、メモリリークが発生
this.data.push(item);
}
// 問題: データを削除するメソッドがない
}
// 使用例
const manager = new DataManager();
for (let i = 0; i < 1000000; i++) {
manager.addData({ id: i, value: Math.random() });
}
// メモリ使用量が増加し続ける

なぜ事故るか:

  1. 参照の保持: データが削除されず、参照が保持される
  2. ガベージコレクションの失敗: 参照が保持されているため、ガベージコレクションが動作しない
  3. ブラウザのクラッシュ: メモリ使用量が増加し続け、ブラウザがクラッシュする

設計レビューでの指摘文例:

【指摘】メモリリークが発生しています。
【問題】データが削除されず、参照が保持されています。
【影響】メモリ使用量の増加、ブラウザのクラッシュ
【推奨】不要なデータを明示的に削除する
// ❌ アンチパターン: イベントリスナーのリーク
function setupScrollHandler() {
// 問題: イベントリスナーが削除されない
// 問題: クロージャーで参照が保持される
window.addEventListener('scroll', () => {
const element = document.getElementById('target');
if (element) {
element.style.top = window.scrollY + 'px';
}
});
}
// 複数回呼び出されると、複数のイベントリスナーが追加される
setupScrollHandler();
setupScrollHandler();
setupScrollHandler();
// 3つのイベントリスナーが追加され、メモリリークが発生

なぜ事故るか:

  1. イベントリスナーの重複: 同じイベントリスナーが複数回追加される
  2. 参照の保持: クロージャーで参照が保持される
  3. メモリリーク: イベントリスナーが削除されず、メモリリークが発生
// ❌ アンチパターン: DOMノード数の増加
function renderList(items: any[]) {
const container = document.getElementById('list')!;
// 問題: すべてのアイテムを一度にレンダリング
items.forEach(item => {
const element = document.createElement('div');
element.textContent = item.text;
container.appendChild(element);
});
// 10,000個のアイテムがある場合、10,000個のDOMノードが作成される
}
// 使用例
const items = Array.from({ length: 10000 }, (_, i) => ({
id: i,
text: `Item ${i}`,
}));
renderList(items);
// DOMノード数が10,000個になり、レンダリングパフォーマンスが低下

なぜ事故るか:

  1. DOMノード数の増加: 大量のDOMノードが作成される
  2. レンダリングパフォーマンスの低下: DOMノード数が増加すると、レンダリングパフォーマンスが低下する
  3. メモリ使用量の増加: DOMノードはメモリを消費する

設計レビューでの指摘文例:

【指摘】DOMノード数が過剰です。
【問題】すべてのアイテムを一度にレンダリングしています。
【影響】レンダリングパフォーマンスの低下、メモリ使用量の増加
【推奨】仮想スクロールを使用してDOMノード数を制限する
// ❌ アンチパターン: 型安全性の欠如
function processData(data: any) {
// 問題: any型を使用し、型安全性が失われる
return data.value + data.amount;
}
// 使用例
const result = processData({ value: '10', amount: 20 });
// 実行時エラー: "1020" (文字列連結) が返される

なぜ事故るか:

  1. 型安全性の欠如: any型を使用し、型安全性が失われる
  2. 実行時エラー: コンパイル時にはエラーが検出されず、実行時にエラーが発生する
  3. デバッグの困難: 実行時エラーはデバッグが困難

設計レビューでの指摘文例:

【指摘】型安全性が欠如しています。
【問題】any型を使用し、型安全性が失われています。
【影響】実行時エラー、デバッグの困難
【推奨】適切な型定義を使用する

よくあるアンチパターンのポイント:

  • A. メモリリーク: データが削除されず、参照が保持される → ブラウザのクラッシュ
  • B. イベントリスナーのリーク: イベントリスナーが削除されない → メモリリーク
  • C. DOMノード数の増加: 大量のDOMノードが作成される → レンダリングパフォーマンスの低下
  • D. 型安全性の欠如: any型を使用し、型安全性が失われる → 実行時エラー

これらのアンチパターンを避けることで、安全で信頼性の高いTypeScriptアプリケーションを構築できます。

重要な原則: 「正常に動く」よりも「異常時に安全に壊れる」ことを優先する。