TypeScript中級

中級 TypeScriptで学ぶリファクタリング|アンチパターン編

導入

リファクタリングは、コードの可読性や保守性を向上させるための重要な手法です。しかし、実務ではしばしばアンチパターンに陥ることがあります。本記事では、TypeScriptを用いた具体的なシチュエーションを通じて、よく見られる失敗例とその改善策を探ります。

教科書レベルの解説(リファクタリング)

重要な概念の整理

リファクタリングは、機能を変えずにコードを改善するプロセスです。これにより、コードが理解しやすくなり、将来的な変更が容易になります。アンチパターンは、リファクタリングの効果を損なう行動や設計のことを指します。これらを避けることが、効果的なリファクタリングには欠かせません。

コード例(TypeScript)


class User {
    constructor(public name: string, public age: number) {}
}

class UserManager {
    private users: User[] = [];

    addUser(name: string, age: number) {
        const user = new User(name, age);
        this.users.push(user);
    }

    getUsers() {
        return this.users.filter(user => user.age >= 18);
    }
}

コードの行ごとの解説

  1. クラスUserは、ユーザーの基本情報を保持します。
  2. UserManagerクラスは、ユーザーの管理を行いますが、データのフィルタリングのロジックがgetUsersメソッド内に直接記述されています。
  3. addUserメソッドは、ユーザーを追加するシンプルな機能を持っていますが、年齢制限のロジックが別の場所に埋もれています。

アンチパターン編

このコードには、複数のアンチパターンが見受けられます。まず、ロジックの分散です。ユーザーのフィルタリングがgetUsersメソッドに直接書かれているため、異なる条件でのフィルタリングが必要な場合、コードの再利用性が低下します。また、責務の不明確さも問題です。UserManagerクラスがユーザーの追加とフィルタリングを同時に行うため、クラスの責務が曖昧になります。

これらの問題を解決するためには、フィルタリングのロジックを別のメソッドに分けることが有効です。例えば、以下のように改善できます。


class User {
    constructor(public name: string, public age: number) {}
}

class UserManager {
    private users: User[] = [];

    addUser(name: string, age: number) {
        const user = new User(name, age);
        this.users.push(user);
    }

    getUsersByAge(minAge: number) {
        return this.users.filter(user => user.age >= minAge);
    }
}

このようにすることで、getUsersByAgeメソッドを通じて年齢によるフィルタリングが明確になり、他の条件でも簡単に再利用できるようになります。

まとめ

  • リファクタリングはコードの改善に不可欠である。
  • アンチパターンを理解し、避けることでリファクタリングの効果が高まる。
  • ロジックの分散や責務の不明確さを見直し、明確なメソッドを設計することが重要である。