オブジェクト指向を再解釈してみた
背景
- オブジェクト指向プログラミングとは、「オブジェクト」という概念に基づいたプログラミングパラダイムの一つである。オブジェクトは、システムが扱おうとする対象を表現したものである。例えば、オンラインショッピングシステムにおける「ショッピングカート」・「顧客」・「商品」などのオブジェクトがある。
- 「カプセル化」は、オブジェクト指向プログラミングにおいて、データとそのデータを操作する関数を結び付け、両者を外部からの干渉や誤用から守ることである。
「オブジェクト指向」の教科書的な説明はこうです(wikipedia参考)。
あんまり分かりません。「ふーん、そうなんだ」で止まってしまう。カプセル化にいたってはなぜ「外部からの干渉や誤用から守る」ことになるかの理解までがあまりにも遠い。
ですが「オブジェクト指向」の考え方が重要で、軽視して良いものではないことは経験的になんとなく分かります。
なので「開発実務経験を一定積んだ今、オブジェクト指向をあらためて解釈してみよう」という趣旨の記事になります。
再解釈
Q1. オブジェクトとは何?
A.
インスタンス、クラス、インターフェースのことです。
1-1 "オブジェクトの範囲"
更に、オブジェクトは「フィールド」と「メソッド」に分解できます。
1-2 "フィールド・メソッド"
フィールド・メソッドとオブジェクトの関係をもう少し詳しくすると下表です。
インターフェース | クラス | インスタンス | |
---|---|---|---|
フィールド | - | 抽象 | 具象 |
メソッド | 抽象 | 具象 | 具象 |
インターフェースはクラスの抽象化であり、クラスはインスタンスの抽象化です。
クラス⇔インスタンスでフィールドは抽象⇔具象の関係にある、というのがポイントです。
1-3 "二段階の抽象化"
伝統的にはオブジェクト=インスタンスなのでしょうが、
そう捉えるとこのプログラミングパラダイムの本質を捉えづらくなると考えました。
オブジェクト=インスタンス・クラス・インターフェース
と解釈すると「今使用している言語は確かにオブジェクト指向だなあ」と思えます。
Q2. なぜ抽象化する?
A.
再利用可能性を高めるためです。
例えば1つのUserクラスを実装したなら、それは無数の利用者の無数回の動作を実現したことになります。
2-1 "1個のクラスと無数のインスタンス"
1つのRepositoryインターフェースを書いたなら、それは将来発生しうる無数の実装クラスの変遷を他のオブジェクトから利用可能にしたことになります。
クラスの変遷はパフォーマンス改善を見込んだSQLの修正によるかもしれないし、ORMの破壊的変更によるかもしれないし、DBインフラの構成変更によるかもしれない。こういった変更があっても抽象メソッドの呼び出し元のコードには何も影響がありません。
2-2 "1個のインターフェースと無数の実装クラスの変遷"
このように1個のオブジェクトを作ることが無数の具象の動作を開発することになるため、再利用可能性を高めることは「生産性を高める」という至上命題に対する、真っ当なアプローチと言えるでしょう。
余談ですが再利用可能性の強力さは科学進歩の歴史にも見受けられます。ガリレオやニュートンの時代、16, 17世紀ごろから科学革命と呼ばれる急速な科学進歩のムーブメントがありました。このブレイクスルーは紙の発明でも筆記道具の流通でもなく、「活版印刷の発明」の直後に起こりました(参考)。
Q3. カプセル化とはどういう手法?
A.
端的に言うなら、責務分離の局所最適化的側面です。
カプセル化は「オブジェクト指向の特徴」ではあっても、「開発者が考えるべきこと」としてはややズレていると考えています。
開発者が真に意識すべきことは責務分離であって、その結果としてカプセル化という手段を取ることになる。
では責務分離とは何かと言うと、何のことはない、大きなシステムを構築する上でごく一般的に取られる手法です。流通システム、生産システム、会社組織など、大きなシステムが持続的に機能するためには小さな単位毎に責務・役割を分担することが不可欠です。大きなシステムをたった1つの責務で構築して長期的に運用することをイメージしてみてください。
3-1 "責務分割のとても素朴な例"
プログラムもこれら例に違わず責務分離が有用だから、責務分離という言葉が出てきただけです。
責務分離は大域的な概念です。1機能全体を通してどれだけのクラスが関わり、どのように責務を分割するか、の問題です。1つのクラスだけに着目して適切な責務領域を出すことは一般的にはできません。
にも関わらずカプセル化は1つのクラスをどう設計するかの話で、局所的です。これがカプセル化がピンとこない理由だと考えています。局所的にはカプセル化を用いてクラス毎に実装を切り分けて、それを適切な依存関係で貼り合わせて全体を構成して初めて責務分離が実現します。
3-2 "責務分割とカプセル化のスコープ"
以上から最初の結論につながります。カプセル化は責務分離という「より上位の目的」を達成するための手段なのです。
最後に
オブジェクト指向は多くの人に長く使われ続けてきた手法でありながら
- クラスやインターフェースといった概念が選ばれ続ける必然性は何か?
- カプセル化による隠蔽の指針は何なのか?なぜカプセル化すると保守性が高まるのか?
といった疑問はなかなか解消できずにいました。
今回の考察を通じて、再利用可能性や責務分離という、普遍的な合理性に従った最適化の結果と思うことでこれらの疑問に対する一定の解答を得ることができました。
ボリュームの都合で触れることはできませんでしたが、ポリモーフィズムやSOLID原則といったオブジェクト指向の他のトピックに関しても再解釈の余地は大いにあると考えています。
こういった用語を「よく考えるとどういう意味だろう?」と一度立ち止まって一段階ブレイクダウンすることには価値があると考えていて、この記事でもしそれを共感してもらえたなら幸いです。
私たち BABY JOB は、子育てを取り巻く社会のあり方を変え、「すべての人が子育てを楽しいと思える社会」の実現を目指すスタートアップ企業です。圧倒的なぬくもりと当事者意識をもって、こどもと向き合う時間、そして心のゆとりが生まれるサービスを創出します。baby-job.co.jp/
Discussion