Curated Tech Reading Map

次に読むべき技術書が見つかるサイト

ブログ記事

「クラス」を手放す発想――Yehonathan Sharvit『データ指向プログラミング』が問うカプセル化の是非

著者: DevBookPath 編集部公開日: 更新日:

データとロジックを一つのクラスに閉じ込める「カプセル化」は、本当に複雑さを減らしているのか。

Yehonathan Sharvit著『データ指向プログラミング』(翔泳社、2023年)は、この前提そのものを問い直す。関数型言語Clojureの設計思想を土台に、Java・Python・TypeScriptといったオブジェクト指向言語でも適用できる4つの原則を形式化し、物語形式の対話を通じて設計判断とトレードオフを追体験させる構成をとる。

1. カプセル化と決別する――データとコードを分離する

ビジネスの成長に合わせてユースケースが増えると、一つのクラスに無関係なコンテキストのメソッドが群がり、コードベースは密結合化していく。DOPはこのカプセル化を放棄し、データ構造と操作ロジックを明確に切り離す。ロジックは状態を持たないステートレスな関数群として定義し、すべての入力は引数として渡す。

この分離により、データの状態変化による予期しない副作用を気にする必要がなくなり、単体テストもモックやDIコンテナなしに、対象のロジックに必要な汎用データを用意するだけで完結できる。

2. クラスを作らない――汎用データ構造がもたらす境界の俊敏性

DOPの第二の原則は、UserOrderのような専用のビジネスエンティティクラスを作らず、文字列キーのマップや汎用配列でシステムを構築することだ。専用クラスを乱立させないことで、データベース・Webサービス・フロントエンドといった層をまたいでデータを転送する際の、DTOへの変換やキャストが不要になる。

データ構造に新しいキーが追加されても、それを使わない既存の関数には影響が及ばない。要件変更の頻度が高いアジャイル開発において、この柔軟性は強みになる。

3. 更新ではなく新しいバージョンを作る――イミュータブルの徹底

データとロジックを切り離しただけでは、システムは無秩序な手続き型に逆戻りしかねない。そこでDOPは、すべてのデータをイミュータブルとして扱う。状態変更が必要な場合は既存データを直接書き換えず、差分を反映した新しいバージョンのデータを生成する(永続データ構造)。

flowchart LR
    subgraph OOP["オブジェクト指向"]
        A["User クラス\nデータ + メソッドを内包\n直接更新(ミューテーション)"]
    end
    subgraph DOP["データ指向プログラミング"]
        B["汎用マップ(不変)"] --> C["ステートレスな関数群"]
        C --> D["新しいバージョンのマップ\n(差分反映・元は変更しない)"]
        E["JSON Schema\n(データ表現から分離)"] -.->|"境界でのみ検証"| B
    end
    style A fill:#fce8e8,stroke:#e53935
    style B fill:#e8f4fd,stroke:#4a9eda
    style C fill:#e8f8e8,stroke:#4caf50
    style D fill:#e8f8e8,stroke:#4caf50

この設計により、並行処理におけるレースコンディションやスレッド競合の懸念は根本から減り、過去の状態をスナップショットとして保持・再現できるため、デバッグ時に過去の状態を丸ごと追跡することも可能になる。

4. 検証はデータ構造から切り離す――境界でのスキーマ検証

専用クラスを排除したことによる安全性の低下を補うのが、データ定義や整合性ルール(JSON Schemaなど)をデータ表現そのものから切り離して管理する第四の原則だ。クラスで型を固定する設計とは異なり、開発者は「どのポイントでデータを検証すべきか」を柔軟に選べる。Web APIの受信部分や永続化直前など、信頼が必要な境界だけで厳格なチェックを走らせ、内部の高速な処理中は検証をスキップする、といった運用が可能になる。

この本が解決できる具体的な状況

オブジェクト指向言語で3年以上業務システム開発を経験し、ビジネスルールの変更を共通クラスの継承ツリーに組み込み続けた結果、クラス関係図が複雑化して身動きが取れなくなっている――この状況に、本書は「データとロジックを分離する」という代替パラダイムを提示する。フロントエンドの不変状態管理とバックエンドAPIの両方を担当し、サービス間でデータをやり取りするたびに冗長なDTO変換を繰り返している開発者にも、軽量な契約設計のヒントになる。

こんな人に向いている

  • 巨大なドメインオブジェクトが乱立し、テスト駆動開発を進めるにもモック作成に多大な時間を奪われている保守フェーズの開発者
  • Reactなどで不変状態管理のパターンは理解しているが、バックエンドAPIとの境界でのスキーマ変更や型の不整合に悩むフルスタックエンジニア
  • 複雑性管理の別解として、DDD的なオブジェクト設計と対比しながら設計の前提を相対化したいアーキテクト

逆に向いていないケース

  • 静的型付けとIDEの支援を重視するプロジェクトの開発者: 文字列キーのマップ中心の設計は、コンパイル時の型チェックや自動補完の恩恵をほぼ手放すことになる。型安全性を優先するチームでは全面採用は難しい
  • DBのユニーク制約のような、状態と密に絡み合う実務的バリデーションを厳密に扱う必要がある人: ステートレスなJSON Schemaと不変データの枠組みだけでは、こうした検証の統合方法が具体的に示されていない
  • クラス設計に慣れていて、置き換える動機がまだない人: パラダイムの転換自体にコストがかかるため、既存設計に明確な痛みがない段階では効果を実感しにくい

知っておきたい限界

批判として押さえておきたい点が二つある。

一つは、静的型チェックとIDE支援を手放す代償だ。文字列キーのマップによるデータ表現は、コンパイルエラー検知や自動補完といった開発環境の恩恵をほぼすべて放棄することを意味する。過去のWeb開発における「インスタンス化せずに連想配列ですべてを引き回す」設計への回帰にすぎないのではという懸念も指摘されている。データが不変であっても、その参照がどこで発生しどの処理に流れているかの把握は難しくなり、フロントエンドのProps Drilling(バケツリレー)に似た状態を生み、ファイル数の増加(従来の1.5〜2倍という指摘もある)と相まって、トラブル調査を複雑にする懸念がある。

もう一つは、状態と密に絡み合う実務的なバリデーションの扱いだ。データベースのユニーク制約検証のように、ステートレスな関数と不変データの枠組みだけでは表現しづらい検証をどう美しく統合するか、具体的な解法は本書の中で十分に示されていない。

同じテーマの本との比較

ドメインをオブジェクトで表現する設計を学んだ人には、対照的なアプローチとして本書が効く。『ドメイン駆動設計をはじめよう』のようにオブジェクトでドメインモデルを表現する手法と、コードとデータを分離し不変データで複雑性を抑えるDOPの発想を並べると、設計の前提そのものを相対化できる。

複雑性管理の一般原則を先に押さえておきたいなら『A Philosophy of Software Design』が助けになる。同じ目的(複雑性の抑制)に対して、本書はその具体的な処方箋の一つという位置づけになる。

データを不変として扱う発想は、分散システムでの一貫性やイベント履歴の議論と地続きだ。『データ指向アプリケーションデザイン』はログ中心アーキテクチャやイベントソーシングを扱っており、不変データの発想を分散基盤の文脈へ拡張してくれる。

逆にRDBのテーブル設計を先に学んでおくと、『達人に学ぶDB設計徹底指南書』の正規化思想とアプリ側のデータモデリングが地続きであることが見えやすくなる。

まとめ

クラスをやめてマップに倒すという主張は極端に聞こえるが、本質は「データとロジックの分離」「不変性」「境界での検証」という3つの部分原則に分解できる。全面採用が難しくても、部分的に取り入れられる余地は大きい。

筆者の体験から

TypeScriptでフロントエンドとバックエンドの両方に関わる中で、あるドメインを表すクラスに、本来関係のないユースケースのメソッドが少しずつ増えていき、そのクラス1つを直すたびに影響範囲を全部洗い直す必要がある状態になった時期があった。クラス設計そのものをやめる発想がないか探していて本書に行き着いた。

文字列キーのマップにすべてを倒すのは、TypeScriptの型システムを手放すことになるため現実的ではないと判断して見送った。その代わり、本書から抜き出して実践したのは2点だけだ。ひとつは、状態更新のときに既存オブジェクトを直接書き換えず、新しいオブジェクトを作って差し替える書き方を徹底したこと。もうひとつは、外部から入ってくるデータをアプリケーションの境界だけで厳格にスキーマ検証し、内部の処理では信頼して通す、という検証の配置を意識するようになったことだ。

ただし、この2点を取り入れても「クラスをやめる」という本書の核心的な主張までは実行できていない。ドメインの型をインターフェースやクラスで表現すること自体はやめておらず、本書が提示する変化の大きさに対して、自分が実際に持ち帰れたのは一部分にすぎない、というのが正直なところだ。

DevBookPath のマップで確認する

この本の学習パス上の位置づけ・前後の読書順は、DevBookPath のグラフで辿れます。

👉 データベースの地図を見る / 👉 ソフトウェア設計の地図を見る

📖 Amazon で購入する


本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。

この記事を共有

この地図を共有