2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるオブジェクト設計:データ vs 振る舞い・POJO・クラス構造・責務の分離と再利用

Posted at

概要

オブジェクト設計とは、「この塊は何を表していて、何ができるのか」を言語化する行為である。
JavaScriptでは、関数・オブジェクト・クラス・プロトタイプと複数の表現手段があり、柔軟ゆえに混乱しやすい
だからこそ、「構造」「振る舞い」「責務」を明確に分離・設計することが、メンテナブルなコードの前提となる。


1. POJO(Plain Old JavaScript Object)による構造設計

const user = {
  id: 'u01',
  name: 'Toto',
  isAdmin: false
};
  • ✅ シリアライズしやすく、状態のスナップショットとして機能
  • ✅ 特に状態管理(Redux等)やAPI通信との親和性が高い
  • ❌ 振る舞い(関数)を内包し始めると構造が曖昧に

2. クラス設計:意味のある「型」として構築する

class User {
  constructor(id, name, isAdmin = false) {
    this.id = id;
    this.name = name;
    this.isAdmin = isAdmin;
  }

  displayName() {
    return `${this.isAdmin ? '[ADMIN] ' : ''}${this.name}`;
  }
}
  • ✅ データと振る舞いを一つの意味としてパッケージ化
  • ✅ 再利用・拡張しやすく、テスト対象としても明確
  • ❌ 状態と副作用を混在させると破綻しやすい

3. クラス vs ファクトリ関数:選定基準

✅ クラスで設計すべきケース

  • “型”の意味が明確(User, CartItem, Timerなど)
  • newによるインスタンス制御が自然
  • instanceofによる型判定を活用する場合

✅ ファクトリ関数で構築すべきケース

  • 状態のみが必要で、プロトタイプ継承は不要
  • データをベースに“加工”する関数が主
  • インスタンスを隠蔽し、純粋関数として扱いたい場合
function createUser(id, name) {
  return {
    id,
    name,
    isAdmin: false,
    displayName() {
      return `${this.name}`;
    }
  };
}

4. 振る舞いを責務単位に分割する

class Cart {
  constructor() {
    this.items = [];
  }

  add(item) {
    this.items.push(item);
  }

  total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}
  • ✅ データ保持(items)と操作(add/total)を意味ある単位で提供
  • ✅ クラスが「文脈と機能の集合体」であることを明示する設計

5. 合成 vs 継承:再利用の構造的選択

❌ 継承を多用すると依存関係が崩壊しやすい

class AdminUser extends User {
  deleteUser() { ... }
}

→ ✅ 再利用の基本は「合成(Composition)」による柔軟な設計

function withLogger(obj) {
  return {
    ...obj,
    log() {
      console.log(`[${obj.name}]`);
    }
  };
}

6. 設計的判断のフレームワーク

目的 手法
状態だけを扱いたい POJO
意味ある型と動作を束ねたい クラス or ファクトリ関数
動作を切り替え可能にしたい Strategyパターン + 合成
インスタンス制御したい クラス構文 + instanceof
動作だけ再利用したい 関数 or Mixin

よくあるミスと対策

❌ オブジェクトに処理と状態が無秩序に混在

→ ✅ クラスを導入 or 関数を分離し、意味の単位で設計する


❌ 継承で「is-a」関係が破綻(例:AdminUser → GuestUser)

→ ✅ 共通機能は合成(has-a)で再利用


❌ どこからでも直接プロパティを参照してしまう

→ ✅ アクセサを導入し、内部構造を隠蔽

get isLoggedIn() {
  return !!this.token;
}

結語

オブジェクトとは、データではなく「概念の実体化」である。
それは構造であり、振る舞いであり、意味を持った単位で再利用可能にする設計の中心である。

  • POJOで構造を定義し
  • クラスで意味を定義し
  • 合成で振る舞いを再利用する

JavaScriptにおけるオブジェクト設計とは、
“意味と再利用を両立させるための、最小構成の建築技法”である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?