よくあるアンチパターン
よくあるアンチパターン
Section titled “よくあるアンチパターン”TypeScriptでよくあるアンチパターンと、実際に事故った構造を詳しく解説します。
A. メモリリーク
Section titled “A. メモリリーク”実際に事故った構造
Section titled “実際に事故った構造”// ❌ アンチパターン: メモリリーク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() });}// メモリ使用量が増加し続けるなぜ事故るか:
- 参照の保持: データが削除されず、参照が保持される
- ガベージコレクションの失敗: 参照が保持されているため、ガベージコレクションが動作しない
- ブラウザのクラッシュ: メモリ使用量が増加し続け、ブラウザがクラッシュする
設計レビューでの指摘文例:
【指摘】メモリリークが発生しています。【問題】データが削除されず、参照が保持されています。【影響】メモリ使用量の増加、ブラウザのクラッシュ【推奨】不要なデータを明示的に削除するB. イベントリスナーのリーク
Section titled “B. イベントリスナーのリーク”実際に事故った構造
Section titled “実際に事故った構造”// ❌ アンチパターン: イベントリスナーのリークfunction setupScrollHandler() { // 問題: イベントリスナーが削除されない // 問題: クロージャーで参照が保持される window.addEventListener('scroll', () => { const element = document.getElementById('target'); if (element) { element.style.top = window.scrollY + 'px'; } });}
// 複数回呼び出されると、複数のイベントリスナーが追加されるsetupScrollHandler();setupScrollHandler();setupScrollHandler();// 3つのイベントリスナーが追加され、メモリリークが発生なぜ事故るか:
- イベントリスナーの重複: 同じイベントリスナーが複数回追加される
- 参照の保持: クロージャーで参照が保持される
- メモリリーク: イベントリスナーが削除されず、メモリリークが発生
C. DOMノード数の増加
Section titled “C. DOMノード数の増加”実際に事故った構造
Section titled “実際に事故った構造”// ❌ アンチパターン: 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個になり、レンダリングパフォーマンスが低下なぜ事故るか:
- DOMノード数の増加: 大量のDOMノードが作成される
- レンダリングパフォーマンスの低下: DOMノード数が増加すると、レンダリングパフォーマンスが低下する
- メモリ使用量の増加: DOMノードはメモリを消費する
設計レビューでの指摘文例:
【指摘】DOMノード数が過剰です。【問題】すべてのアイテムを一度にレンダリングしています。【影響】レンダリングパフォーマンスの低下、メモリ使用量の増加【推奨】仮想スクロールを使用してDOMノード数を制限するD. 型安全性の欠如
Section titled “D. 型安全性の欠如”実際に事故った構造
Section titled “実際に事故った構造”// ❌ アンチパターン: 型安全性の欠如function processData(data: any) { // 問題: any型を使用し、型安全性が失われる return data.value + data.amount;}
// 使用例const result = processData({ value: '10', amount: 20 });// 実行時エラー: "1020" (文字列連結) が返されるなぜ事故るか:
- 型安全性の欠如: any型を使用し、型安全性が失われる
- 実行時エラー: コンパイル時にはエラーが検出されず、実行時にエラーが発生する
- デバッグの困難: 実行時エラーはデバッグが困難
設計レビューでの指摘文例:
【指摘】型安全性が欠如しています。【問題】any型を使用し、型安全性が失われています。【影響】実行時エラー、デバッグの困難【推奨】適切な型定義を使用するよくあるアンチパターンのポイント:
- A. メモリリーク: データが削除されず、参照が保持される → ブラウザのクラッシュ
- B. イベントリスナーのリーク: イベントリスナーが削除されない → メモリリーク
- C. DOMノード数の増加: 大量のDOMノードが作成される → レンダリングパフォーマンスの低下
- D. 型安全性の欠如: any型を使用し、型安全性が失われる → 実行時エラー
これらのアンチパターンを避けることで、安全で信頼性の高いTypeScriptアプリケーションを構築できます。
重要な原則: 「正常に動く」よりも「異常時に安全に壊れる」ことを優先する。