JavaScript中級

中級 JavaScriptで学ぶオブジェクト指向設計|アンチパターン編

導入

オブジェクト指向設計は、ソフトウェア開発において非常に重要な手法ですが、実務ではさまざまなアンチパターンに遭遇することがあります。特に中級レベルのプログラマーは、基本的な概念を理解しているものの、実際のプロジェクトでの適用において注意が必要です。本記事では、JavaScriptを用いた具体的なアンチパターンを取り上げ、どのように改善するかを考察します。

教科書レベルの解説(オブジェクト指向設計)

重要な概念の整理

オブジェクト指向設計は、データとその操作を一つの単位にまとめることで、コードの再利用性や可読性を高める手法です。クラス、オブジェクト、継承、ポリモーフィズムといった概念は、オブジェクト指向プログラミングの基礎を形成します。これらの概念を正しく理解し、適切に適用することが求められます。

コード例(JavaScript)


class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
    }
}

const user1 = new User('Alice', 30);
user1.greet();

コードの行ごとの解説

  1. class User { – Userというクラスを定義します。
  2. constructor(name, age) { – コンストラクタでユーザーの名前と年齢を受け取ります。
  3. this.name = name; – 受け取った名前をインスタンスのプロパティに設定します。
  4. this.age = age; – 受け取った年齢をインスタンスのプロパティに設定します。
  5. greet() { – ユーザーの挨拶を行うメソッドを定義します。
  6. console.log(…); – 挨拶のメッセージをコンソールに出力します。
  7. const user1 = new User(‘Alice’, 30); – Userクラスのインスタンスを作成します。
  8. user1.greet(); – インスタンスの挨拶メソッドを呼び出します。

アンチパターン編

オブジェクト指向設計においては、特定のアンチパターンが存在します。ここでは「God Object」パターンを取り上げます。これは、全ての機能を一つのクラスに詰め込むことで、クラスが肥大化し、管理が難しくなる問題です。

例えば、次のようなコードを考えてみましょう。


class App {
    constructor() {
        this.users = [];
        this.posts = [];
    }

    addUser(user) {
        this.users.push(user);
    }

    addPost(post) {
        this.posts.push(post);
    }

    showUsers() {
        console.log(this.users);
    }

    showPosts() {
        console.log(this.posts);
    }
}

このクラスは、ユーザーと投稿の管理を一手に担っています。将来的に機能が増えると、さらに多くの責任を持つことになり、可読性や保守性が低下します。

改善策としては、責任を分割することが挙げられます。次のように、ユーザー管理と投稿管理を別々のクラスに分けることが望ましいです。


class UserManager {
    constructor() {
        this.users = [];
    }

    addUser(user) {
        this.users.push(user);
    }

    showUsers() {
        console.log(this.users);
    }
}

class PostManager {
    constructor() {
        this.posts = [];
    }

    addPost(post) {
        this.posts.push(post);
    }

    showPosts() {
        console.log(this.posts);
    }
}

このように分割することで、各クラスの責任が明確になり、保守性や再利用性が向上します。

まとめ

  • オブジェクト指向設計では、クラスの責任を明確に分けることが重要です。
  • 「God Object」パターンを避け、機能ごとにクラスを分割することで、可読性と保守性が向上します。