SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

翔泳社の本(AD)

新刊『データ指向プログラミング』から「はじめに」を公開! オブジェクト指向との対比も語られる

  • このエントリーをはてなブックマークに追加

 プログラムをデータと処理に分解し、データの流れに沿って設計するデータ指向プログラミング(DOP)の方法を解説した書籍『データ指向プログラミング』(翔泳社)から、「本書に寄せて」と「まえがき」と「はじめに」を掲載します。データ指向プログラミングのメリットや特徴のほか、オブジェクト指向プログラミング(OOP)との比較も語られており、本書がどんな内容なのかを掴める内容となっています。

  • このエントリーをはてなブックマークに追加

 本記事は『データ指向プログラミング』の「本書に寄せて」「まえがき」「はじめに」を抜粋したものです。掲載にあたって一部を編集しています。

※本書はYehonathan Sharvitの『Data-Oriented Programming』(Manning Publications、2022)の邦訳版です。

本書に寄せて MICHAEL T. NYGARD
『Release It!: Design and Deploy Production-Ready Software』の著者

 すべてのプログラミング原理、すべての設計法、すべてのアーキテクチャスタイル、さらにはほとんどの言語の機能は、適応を受け入れながら複雑さを体系化するものである。2009年のClojure、そして最近ではYehonathan Sharvitの『Data-Oriented Programming』に私が引き寄せられたのは、イミュータブルなデータと、プログラムの各部分をプログラム自体のデータに変えることという2つの特徴があったからだ。

 2005年、私は気の置けない仲間の何人かとお気に入りのプロジェクトの1つに取り組んでいた。それはJavaプロジェクトだったが、当時のJavaコミュニティでは一般的でなかった2つのことを行った。まず、基本的なデータ値をイミュータブルにした。簡単なことではなかったが、非常にうまくいった。多くのクラスでcloneメソッドとdeepCloneメソッドを独自に作成した。

 その見返りは途方もなかった。ほんの一例として、ユーザーがインスタンス化するテンプレートドキュメントが必要だとしよう。オブジェクトツリー全体をコピーできる場合、それがテンプレートデータなのかインスタンスデータなのかをオブジェクトを「知っている」必要はない。その判断を下すのは、参照を持っているオブジェクトである。比較についても大きな利点があった。値がイミュータブルである場合は、IDが等しければ値が等しいことになるからだ。このため、等価のチェックを非常に高速に行うことができる。

 私たちが次に行ったのは、汎用的なデータを利用することだった―――もちろん、Yehonathanが本書で示すものとは比べものにならないが。あるレイヤにクラス階層がある場合、その隣のレイヤではそれらをより汎用的なクラスのインスタンスとして表すことになる。あるレイヤにおいてメンバ変数であるものは、別のレイヤではマップのフィールドとして表される。このスタイルがチームのSmalltalker(Smalltalkでプログラミングをする人)の影響を受けていたことは間違いない。さまざまな設定でオブジェクトの合成や再合成を行うことができたため、効果はすぐに現れた。

 本書で説明しているように、データ指向プログラミング(DOP)は、偶発的な複雑さを軽減し、作業の抽象化のレベルを引き上げることを約束する。プログラムで繰り返される振る舞いが不自然なものに見えてきたあなたは、ジェネリック関数をクラスに刻み込む。するとどうだろう、それらのクラスはプログラムの値の一部(インスタンス)だけを操作する小さな名前空間のように機能し始める。そうした値のほとんどはマップとリストに「まとめる」ことができる。メンバの名前(リフレクションAPIを使って苦労しないと手に入らないデータ)をマップのキーに変えることができる。そのようにすると、コードが徐々になくなっていく。これが悟りの第一段階である。

 ここで読者は、そうしたメンバ名はコンパイル時にコンパイラが正確さのチェックに使うものだと反論するかもしれない。たしかにそうである。だが信じてほしい。Yehonathanが悟りの次なる段階に読者を導くことを。コンパイル時のチェックは、値に対して実行できる正確さのチェックのごく一部にすぎない。正確さのチェック自体をデータにすることだってできるのである。スキーマをプログラム内の値にしたければそうすることができる。さらに、型システムの最前線にいる研究者らが依然として解明に取り組んでいる基準を適用することもできる。これが悟りの第二段階である。

 DOPが特に効果を発揮するのは、Web APIを使っているときである。ネットワーク上にシステムの類いはいっさいないため、リクエストペイロードをドメインクラスに直接マッピングしようとすれば、脆弱で複雑な実装になることは目に見えている。データはデータのままにすれば、コードがより単純になり、数百メガバイトのフレームワークライブラリに頼る機会がずっと少なくなる。

 さて、OOPの長所であるカプセル化、継承、ポリモーフィズムにいったい何が起きたのだろうか。これらを分解して、どれでも好きなものを選べることがわかったのだ(私の見解では、最初に教わることが多い実装の継承は、この中で最も重要性が低いものである。私はプロトコルと共通の関数のシグネチャを使ってインターフェイスを継承するようになった)。DOPは「従来の」ポリモーフィズムを提供する。つまり、最初の引数の型に基づいて、多くの関数の中から1つにディスパッチする(OO言語では、thisはメソッドの第1引数のもう1つの姿であり、たまたま”.”の前にあるにすぎない)。ただし、スキーマのチェックと同様に、DOPはさらなるダイナミズムを可能にする。最初の2つの引数の型に基づくディスパッチ、あるいは引数の「誕生日」フィールドに今日の日付が含まれているかどうかに基づくディスパッチを思い浮かべてみよう。これが悟りの第三段階である。

 カプセル化に関しては、プログラムの構成ロジックに適用しなければならない点は変わらない。ただし、カプセル化するのは値ではなく、サブシステムである。このカプセル化は、David Parnasの決定の隠蔽を体現している。サブシステムの中では、クラスが押し付けるばらばらの名前空間にデータを閉じ込めるのをやめることができる。Alan Perlisの言葉を借りれば、「10個の関数で10種類のデータ構造を操作するよりも、100個の関数で1つのデータ構造を操作するほうがよい。」  エントロピーとの終わりなき戦いにおいて、DOPを使って管理するコードの量を減らせるだけではなく、抽象化のレベルを引き上げてプログラムのロジックと意味を正確かつ明確にすることもできる。その道のりを楽しみ、新たな台地にたどり着くたびに足を止め、景色を堪能し、「ただのデータだ」と自分に言い聞かせてほしい。

本書に寄せて RYAN SINGER
『Shape Up: Stop Running in Circles and Ship Work that Matters』の著者

 私が本書を手にしたのは、まさにちょうどよいタイミングだった。私は20年近くオブジェクト指向フレームワークでWebアプリを構築してきた。自分をエキスパートプログラマだと思ったことは一度もないが、一般的なビジネス問題を調べて、大まかなデータモデルを作成し、MVCスタイルのアプリを構築して仕事を終わらせるのに自分の技能が十分であることは知っていた。

 どのプロジェクトも出だしはスリリングだった。要素をつなぎ合わせていくときの感覚や、アプリが動き出すのを見るのはたまらないものがある。しかし、アプリの運用を開始すると、いくつかの問題にぶつかった。他のすべてのモデルを考慮に入れなければ、1つの部分を変更することができなかった。テストを書かなければならないことはわかっていたが、テストする価値があると思えないもののために、非常に多くの状態を準備しなければならなかった―――変更するのが難しいコードをそれ以上書くのはごめんだった。コンソールでちょっとしたコードを実行するのでさえ億劫だった。そのメソッドを呼び出すためにデータベースの状態を作成しなければならなかったからだ。自分のやり方が間違っているという見当はついていたが、高度なテストフレームワークといった自分が知っている解決策は、事態を好転させるどころか、かえって複雑にするように思えた。

 そんなある日、YouTubeでClojureの作成者であるRich Hickeyの講演を見た。Hickeyは関数型プログラミングを説明していて、OOと対比させていた。OOのことをあざけるように「場所指向プログラミング」と呼んでいた。Hickeyが正しいのかはわからなかったが、「君のせいではない、言語のせいだ」という隠れたメッセージに引き付けられた。探し出せる動画を片っ端から観て、Clojureが答えになるかもしれないと思い始めた。

 それから数年が経ち、私はあいかわらずClojureの動画を観ては、関数型の原則をできるだけ適用するようにしていた。しかし、新しいプロジェクトに取りかかるときは決まって、慣れているフレームワークにすがりついていた。ライブラリのエコシステムがまったく異なる別の言語に切り替えるのは、荷が重すぎて思い切りがつかなかった。

 その後、新しいプロジェクトに取りかかろうとしていたときに、本書を見つけた。タイトルの「データ指向」を見てピンときた。Clojureの動画に出ていたプログラマが同じ用語を使っているのを聞いたことはあったが、どういう意味なのかはよく理解していなかった。カスタムオブジェクトの代わりに(マップや配列のような)データリテラルを操作するシステムを構築するほうがいかに簡単かに関する何かだと思っていた。私が知っていた言語はデータリテラルを十分にサポートしていたので、私がClojureに切り替える奇跡の日が訪れるまで、私を引き留めておく何かを学べるかもしれないと思った。

 初めてひらめいた瞬間は、本書の「はじめに」を読んでいるときだった。Yehonathanは最初の数ページで、Clojureを10年あまり書いてきたが、本書は特定の言語に向けたものではなく、サンプルはJavaScriptで書かれていると説明している。ちょっと待った、と私は思った。プログラムの書き方を徹底的に改善するために言語を変える必要がないなんてことが、本当にあり得るのだろうか。

 この見通しに興奮した私は、本書をむさぼるように一気に読んだ。ずっと目の前にあったものが初めて目に飛び込んできた。もちろん、私のコードはテストしにくいものだった。私が使っていたORMのせいで、すべての機能が多くのデータベース状態を前提とするオブジェクトで書かれていたのだ。本書がサンプルを使って何ひとつも略さずに説明しているのを見たとき、それが脳裏から離れなくなってしまった。新しい言語なんて必要ない。ただ、プログラミングのアプローチを変えるだけでよかったのだ。

 私がすばらしいと思っている設計者は皆同じことを指摘する―――よい設計とは、物事を切り離すことである。どれほど醜悪であろうとコードが動けばよい、ということではない。各部分のもつれを解きほぐし、何かを1つ変更すると他の部分がすべて動かなくなる、ということをなくすことなのだ。

 本書はコードとデータを引き離す。その先にあるのは驚くほどすばらしい結果である。私の場合はそれだけではなく、特定の言語からプログラミングのやり方を引き離してくれた。私がClojureに乗り換えることはないかもしれないし、もはやその必要があるとも思えない。本書は、私が知っている言語や、毎日のように登場する新しいフレームワークで、新たな可能性を見出す手助けをしてくれた。

まえがき

 私は2000年からソフトウェアエンジニアをしている。私にとって、2012年「以前」と「以降」は明確に分かれている。なぜ2012年なのか。2012年は私がClojureを発見した年だからだ。Clojureを発見する前は、プログラミングは私の仕事だった。Clojureを発見してからは、プログラミングは私が情熱を傾けるものになっている。

 数年ほど前、私はふと考えた。このプログラミング言語のどの機能が私をこれほど楽しませてくれるのだろう。そこで、私と同じようにClojureに情熱を抱いているClojureコミュニティの他のメンバーに、この質問をぶつけてみた。そして、特別なのは機能ではなく原則だということで意見が一致した。

 Clojureの基本原則を抜き出そうとしていた私たちは、実際には、それらの原則を他のプログラミング言語に応用できることに気づいた。本書の構想が沸いてきたのはそのときだった。私がClojureでとても気に入っている点を世界中の開発者コミュニティに伝えたかった。そのためには、Clojureのことを知らない開発者にはほとんどなじみのない発想を、明確に表現する手段が必要だった。

 私は昔からストーリーを考えるのが好きだが、私が考え出した会話仕立ての説明をプログラマは真剣に受け止めてくれるだろうか。たしかに、プラトンは「ソクラテスの対話」で師の教えを伝えるために物語を考え出している。同様に、イェフダ・ハレヴィはユダヤ教の基礎を教えるためにハザールの王の物語を考え出している。しかし、これら2つの作品は実践に関するものではなく、思想に関するものだ。

 そこで思い出したのが、数年前に読んだ『The Goal』(North River Press、2014)というマネジメントの本だった。同書で、著者であるエリヤフ・ゴールドラットは、制約理論の原理のおかげで工場をどうにか救うことができた工場経営者の物語を考え出している。アイデアをストーリー仕立てで伝えたいという私の突拍子もない願いを、プラトン、イェフダ・ハレヴィ、エリヤフ・ゴールドラットが正当化してくれた。

はじめに

 本書は開発者が構築するシステムの複雑さを軽減することを目的として書かれている。本書で紹介するアイデアは、フロントエンドアプリケーション、バックエンドWebサーバー、Webサービスなど、情報を操作するシステムにほぼ適用できる。

本書の対象読者

 本書は、Java、C#、C++、Ruby、Pythonといった高水準プログラミング言語を何年か経験しているフロントエンド開発者、バックエンド開発者、フルスタック開発者を対象としている。オブジェクト指向プログラミング(OOP)開発者にとって、本書で紹介するいくつかのアイデアは、開発者を安全地帯から引っ張り出し、居心地のよいプログラミングパラダイムをいくつか手放すことを要求するかもしれない。本書の内容は関数型プログラミング(FP)開発者のほうが少し理解しやすいが、うれしい驚きもいくつかあるはずだ。

本書の構成:ロードマップ

 本書では、DOPの価値と、その原則を現実の本番環境のシステムに適用する方法を、ストーリー仕立てで説明する。ストーリーを追いながら、各章を最初から順番に読んでいくことをお勧めする。ただし、特に興味を引かれる章がある場合、Part 2とPart 3の内容を理解するには、Part 1と第7章の内容が必要であることに注意しよう。

 本書では、ジェネリック関数を使ってデータを操作する方法を具体的に示すために、Lodash2を使っている。サンプルコードを読んでいてよく知らないLodash関数が使われていた場合は、その関数の仕組みを付録Dで調べることができる。

 「Part 1 柔軟性」は6つの章で構成されている。従来のOOPの課題にスポットライトを当て、DOPをステージの中央に立たせた上で、DOPの基本原則を適用することで柔軟なシステムを構築する方法を明らかにする。次に、各章の内容をまとめておく。

  • 「第1章 オブジェクト指向プログラミングの複雑さ」では、OOPの複雑さについて考える。そこから、DOPの冒険が始まる。シニア開発者のTheoと、将来有望な同僚のDaveの会話に耳を傾けよう。OOPの複雑さに悪戦苦闘するTheoの立場に立って考え、別のプログラミングパラダイムを試す絶好の理由を発見しよう。
  • 「第2章 コードとデータの分離」では、我らがTheoが、システムの複雑さを軽減し、柔軟性を向上させるソリューションを探し求めている。Theoの仕事は危機に瀕している。そして、その答え(DOP)を持つ経験豊富な開発者Joeが登場する。DOPの原則#1が情報システムの複雑さを軽減するのにどのように役立つのかを発見しよう。
  • 「第3章 基本的なデータ操作」では、DOPの原則#2を適用することで、クラスでの厳重なカプセル化からデータを解放し、ジェネリック関数を使って自由に操作できるようにする方法を調べる。革命万歳!
  • 「第4章 状態管理」では、システムを以前の状態に戻すことで時間をさかのぼれるようにする、マルチバージョンアプローチを使った状態管理を調べる。DOPでは、状態はデータにすぎない。DOPでは、タイムトラベルは現実である。
  • 「第5章 基本的な並行性制御」では、楽観的な並行性制御戦略を適用することで、並行システムでスループットの高い読み書きを実現する。バラ色のメガネはいらない。
  • 「第6章 単体テスト」では、Joeとコーヒーを飲む。我らがJoeは、データ指向コードの単体テストがコーヒーショップで実行できるほど簡単なことだと証明する。コーヒーを片手に、DOPの単体テストをJoeと一緒に書きながら、(ミューテーションの単体テストであろうと)なぜそんなに簡単なのかを学ぼう。

 「Part 2 スケーラビリティ」では、データ検証、マルチスレッド環境、大きなデータコレクション、データベースアクセス、Webサービスに焦点を合わせた上で、大規模なDOPシステムを構築する方法について説明する。システムをスーパーサイズにする必要がある? お安い御用だ!

  • 「第7章 基本的なデータ検証」では、万一の場合に備えて、システムがやり取りするデータが有効であることを確認する方法を学ぶ。Joeが言うように、DOPではデータ検証は強制されないが、必要なときに行うことができる。検証するかしないか、それが問題だ。
  • 「第8章 高度な並行性制御」では、我らがJoeがアトムメカニズムの実装を細かく解体した後、ロックをいっさい使わずに、システム全体の状態をスレッドセーフな方法で管理する方法を学ぶ。アトム(原子)から複雑さを思い知らされることはない。 安心して取りかかろう!
  • 「第9章 永続的なデータ構造」では、大学を舞台に、データをイミュータブルに保つためのより安全でスケーラブルな方法の詳細なメカニズムと、このメカニズムを効率的に実装する方法を我らがJoeが明らかにする。さあ、授業の始まりだ!
  • 「第10章 データベースの操作」では、データベースのデータを表現し、アクセスし、操作するためのより柔軟な(そして予想どおり、複雑さを抑えた)方法を学ぶ。
  • 「第11章 Webサービス」では、Webサービスとのやり取りの単純さを実感できる。Joeが言う「システムの外部を構築するのと同じように内部を構築すべきである」という状況がどのようなものであるかを学ぶ。

 「Part 3 保守性」では、DOPでの高度なデータ検証、ポリモーフィズム、雄弁なコード、バッグ手法という次なるレベルに進む。これらはチームで作業を行うときに不可欠なものだ。DOPチームへようこそ!

  • 「第12章 高度なデータ検証」では、何かの形状をどのようにして明らかにするのかを学ぶ。システム内を流れるデータを検証し、関数の引数と戻り値に期待される形状を定義すれば、開発が容易になる。ここでは、その方法を学ぶ。
  • 「第13章 ポリモーフィズム」では、TheoとDaveが田舎でセッションを行う。マルチメソッドを使って動物とたわむれ、オブジェクトを使わずにポリモーフィズムを学ぶのにぴったりの場所だ。
  • 「第14章 高度なデータ操作」では、DaveとTheoがJoeの思慮深いアドバイスに従い、データ操作ツールを独自に作成しながら何の変哲もないコードを雄弁なコードに変える方法を見ていく。「馬の前に荷車をつなぐ」もJoeからの貴重なアドバイスである。
  • 「第15章 デバッグ」では、DaveとTheoを科学博物館へ連れていき、バグを再現して修正するための革新的なソリューションを作成しながら、有終の美を飾る。

 本書には4つの付録も含まれている。

  • 「付録A データ指向プログラミングの原則」では、Part 1で詳しく説明するDOPの4つの原則を要約し、それぞれの原則をFPとOOPの両方の言語にどのように適用できるのかを具体的に見ていく。また、各原則の利点と、それぞれの原則に従うときのコストについても説明する。
  • 「付録B 静的型付け言語での汎用的なデータアクセス」では、JavaやC#のような静的に型付けされるプログラミング言語で汎用的なデータアクセスを実現するさまざまな方法を紹介する。
  • 「付録C データ指向プログラミング」では、DOPのインスピレーションの源となったアイデアやトレンドを探り、どのような発見によって本番環境の大規模なシステムにDOPを適用できるようになったのかを調べる。
  • 「付録D Lodashリファレンス」では、本書で使っているLadash関数をまとめている。本書では、データを変更することなく、ジェネリック関数を使ってデータを操作する方法を具体的に示すために、Ladash関数を使っている。

コードについて

 本書のコードのほとんどはJavaScriptで書かれている。JavaScriptを選択した理由は2つある。

  • JavaScriptは、FPスタイルとOOPスタイルを両方ともサポートしている。
  • JavaScriptをよく知らなくてもJavaScriptコードを擬似コードであるかのように読めるという意味において、JavaScriptの構文は読みやすい。

 読者が普段どのプログラミング言語を使っていてもコードを簡単に読めるようにするために、本書では基本的なJavaScript構文だけを使っており、アロー関数やasync表記のような高度な言語機能はあえて使わないようにしている。静的に型付けされる言語にアイデアを適用する上で概念的な課題がある場所では、Javaのコードを追加している。

 本文やコードリストのコードには等幅フォント(fixed-width)を使っている。多くの場合、元のソースコードの体裁は変更されており、ページに収まるように改良を加えたり、インデントを調整したりしている。重要な概念を目立たせるために注釈を追加しているコードもある。実行可能なコードは本書のGitHubリポジトリからダウンロードできる。

https://github.com/viebel/data-oriented-programming

データ指向プログラミング

Amazon  SEshop  その他

 
データ指向プログラミング

著者:Yehonathan Sharvit
翻訳・監修:株式会社クイープ
発売日:2023年4月19日(水)
定価:3,960円(本体3,600円+税10%)

本書について

本書は、Java、C#、C++、Ruby、Pythonなどの高級プログラミング言語で2年以上の経験を持つ、フロントエンド、バックエンド、フルスタック開発者向けの本です。「情報システム開発の複雑さ」を軽減し、見通しが良く仕様変更にも柔軟に対応したい開発者に、新しい視座とパラダイムを提供します。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
翔泳社の本連載記事一覧

もっと読む

この記事の著者

渡部 拓也(ワタナベ タクヤ)

 翔泳社マーケティング課。MarkeZine、CodeZine、EnterpriseZine、Biz/Zine、ほかにて翔泳社の本の紹介記事や著者インタビュー、たまにそれ以外も執筆しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/17502 2023/04/26 11:30

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング