データ指向プログラミング(DOP) ≠ データ指向デザイン(DOD)
まず、ここで言及しているデータ指向プログラミングはYehonathan Sharvit氏によって提唱されている概念で、本人が自分の著書Data-Oriented Programmingで度々DOPとして略称されています(邦訳「データ指向プログラミング」は翔泳社さんによって出版されています)。
一方、データ指向デザイン(よくDODとして略称されます)はゲーム開発の際によく言及されている概念です。ゲームの特性上、プログラムの高いパフォーマンスが求められているため、メモリからデータを読み取るプロセスの頻度を控え、CPUのキャッシュを活用できるように、並列配列(Parallel Array)を多用するアプローチです。
ちなみに、データ指向と言えば「データ指向アプリケーションデザイン」という名書もありますが、それと混同しないでください。
データ指向プログラミングのゴール
データ指向プログラミングはシステムの複雑性(Complexity)を減らすために提案されているそうです。ここでいう複雑性はシステムを理解や変更するための認知負荷と言い換えて良いと考えます。それらを実現するために、データをFirst-Class Citizenとして取り扱う必要がありますが、First-Class Citizenと言っても抽象的なので、具体的には下記の4つの原則を実践する必要があると提案されています。
データ指向プログラミングの4つの原則
原則1 データとロジックを分離
簡単にいうと、ロジック(関数/メソッド)とデータ(プロパティ/メンバー)を分離することです。例えば人を表現したい時、一般的なOOPでは `Person (firstName: string, lastName: string, fullName(): string = '${this.firstName} ${this.lastName}' )` のようにプロパティ(firstNameとlastName)と関数(fullName)が同じ構造体に共存しているでしょう(説明しやすくするためにこのメモでは存在し得ない擬似コードを使ってます)。DOPの場合 `PersonData ( firstName: string, lastName: string); PersonFun(fullName(): string = '${this.firstName} ${this.lastName}' )` にするわけです。
このようにすることで、下記のメリットが得られます。
コードを再利用しやすくなる
テストがしやすくなる
コードがわかりやすくなる(ロジックとデータを分けて理解することができるため)
対して、カプセル化で実現される隠蔽ができなくなるので、アクセス制限がなくなることは大きなデメリットだと言えるでしょう。
原則2 汎用データ構造を利用
こちらは最も賛否両論になる原則でしょう。つまり、型定義した構造体ではなく、MapやArrayなどを多用することです。シリアライズが行いやすくデータ構造の変更もやりやすいメリットがあります。一方で、当然ながらPrecompileや本コンパイル時のチェックが行えなくなり、間違いに気づきにくくなります。一応こういうデメリットは後述のスキーマ活用によって緩和されます。
原則3 データを不変(イミュータブル)に取り扱う
イミュータブルデータのメリットはFPの中でもよく言及されてますが、スレッドセーフが担保しやすく、ロジックエラーが発生しにくいです。原則3で強く言及したのは状態管理(State Management)のやりやすさです。不変にすることで状態の巻き戻しがやりやすいことは一大メリットとして挙げられています。
ただ、イミュータブルにする際のパフォーマンスコストが意識されているため、都度都度ディープコピーというより、専用のライブラリを使うなどして、不必要なコピーを避けるべきだと言われています。
原則4 データ表現とデータスキーマを分離
DOPの中で、データはJSONとして表現できるため、Ajvのようなスキーマチェッカーを活用すれば、ニーズに応じた柔軟かつ高度なスキーマチェックが可能だということです。JSONスキーマの活用が推奨されています。
静的型付け言語のコンパイル時チェックはなくなるが、動的になった分、チェックするかどうか、どこまでチェックするかはプログラマによって判断可能になります。もちろん、Programaticなスキーマチェックが動的に実施することも考えられます。
私の所感
ちょっと過激的ではあるがシンプルで面白いアプローチだと感じました。挙げられたペインはシステム作りをよく経験している人からすればみんな実感できると思います。特にAPI変更の激しいシステム作りにおいて、データ構造の変更によって発生する改修コストが大きな割合を占める為、より柔軟に取り扱いたいニーズがよく出てきます。
ただし、Yehonathan SharvitさんはDOPはOOPやFPと併用できるパラダイムでJavaやScalaなどでも適用可能だと主張していますが、現実問題OOPやFP主軸の静的型付け言語はデータを動的に取り扱うことが煩雑で、気持ちよくDOPを実現することが難しいと感じます。特に型定義を撤廃する考え方はコードの堅牢性と引き換えて柔軟性を得るアプローチなので、スキーマチェックの言語レベルのサポートの有無によって実用性が大きく異なるでしょう。
ちなみに、DOPを調べている時、Turbo 8からTypeScriptをドロップする話が思い浮かびました。DHHがブログに書かれているように、堅牢性は大事ではあるものの、動的だからこそもたらせるパワーを無視してはいけないと思いました。
データ指向プログラミングの学習リソース
近年Yehonathan Sharvitさんご本人がいろんなPodcastやイベントに参加し、概念のエバンジェリストをやっていますので、名前を検索すれば関連リソースが出てきます。私は最初にGOTOのPodcastでDOPの概念を初めて触れ、その後書籍やブログ、他の講演内容などを通して詳細を調べていた感じです。ただし、2023年年末現在、日本語の資料は限られています。
書籍
ビデオ
Podcast
ブログ
論文