オブジェクト指向と「物」と「モノ」、そして「問題領域」に関する考察メモ

オブジェクト指向」の定義

本稿における「オブジェクト指向」とは、一般的にオブジェクト指向がどのように認知されているかを筆者なりに想定したものであり、厳密な定義に基づくものではありません。まぁ、そんなに堅苦しい話でもないですし。

「物」の定義

本稿では、「物」を「自然界における物質」と定義します。
「物」の特性は、物理特性のみとします。
例えば、「ネジ」の物理特性は、「ネジ」を建築資材として利用しても、芸術作品として利用しても変わることはありません。

「モノ」の定義

本稿では、「モノ」を「問題領域内に存在する意味のある情報」と定義します。
情報として抽象化されるため、「色」や「気分」のようなものも定義できます。
「モノ」の特性は、問題領域によって定義されます。
例えば、ある問題領域では「ネジ」が建築資材としての特性を持っているかもしれませんが、他の問題領域では芸術作品としての特性を持っているかもしれません。「モノ」の特性は、「モノ」自体ではなく、「モノ」を扱う側によって定義されるということもできます。

オブジェクト指向の対象は「物」か「モノ」か?

いきなり結論ですが、オブジェクト指向が対象としているのは「モノ」です。物理的な「物」は、物理特性全てを記述することが可能であれば、クラス定義はできるかもしれませんが(不可能だと思いますが)、複数のインスタンスを生成するという考え方は適用できません。また、そのようなクラスは何の役にも立ちません。
オブジェクト指向は、問題領域に最適化された「モノ」を対象にするからこそ意味があると言えます。

問題領域を意識する重要性

オブジェクト指向は、問題領域を強く認識することにより大きな効果を発揮します。例えば、問題領域中で「ネジ」が建築資材として認識されているのであれば「留める」「外す」という手続きや、「規格」「値段」等の属性が定義されることになります。
しかし、あらゆる問題領域で使用可能な汎用的な「ネジ」を考えると大変なことになります。建築資材として、芸術作品として、材料として、武器として、黒豆を煮る際のツヤ出し用アイテムとして、等々無限に考え続けることになります。問題領域が無限に存在することから、そのような汎用的な「ネジ」の定義は不可能です。つまり、問題領域が「モノ」の特性を定義する場所である言えます。
上記から、オブジェクト指向では問題領域を意識することが重要であることがわかります。しかし、実際の現場では、プログラミング言語を意識したとたんに大局が見えなくなるケースが多いようです。

問題領域を意識しない例

業務問題領域のBeanをDTOとして扱い、手続きは各サービスで実装すべきだという意見をたまに耳にしますが、具体的には以下ような考え方がベースのようです。

  • Beanのデータに対する手続きは各サービスで決定すべきことであり、Beanに定義するのはおかしい。
  • あるサービスに対して、あるBeanに対する手続きを増やしたい場合に、Beanに対してそれを行うと変更箇所が2箇所になる。

前者については、前提が間違っています。業務問題領域のBeanに対する手続きは各サービスではなく業務問題領域によって決定されます。業務問題領域がBeanに求める手続きは、業務問題領域中のクラスがBeanに求める手続きの最小公分母となります。Bean内部で完結できない手続きはBeanに記述されることはありません(永続化とか、Bean外の情報を用いた計算とか)ので、各サービスに記述されるのは問題ありません。
後者については、複数のサービスが同一の手続きを必要とする場合に冗長なコードが分散する可能性や、そのような手続きの仕様変更の際には複数のコードに同一の修正を加えなければならない問題の方が大きいでしょう。また、そのような冗長なコードはユーティリティクラスにまとめればよいといった反論も聞いたことがありますが、だったらそのままBeanに書いたほうがよいでしょう。無駄なクラスが1つ減りますから。

業務問題領域中のクラスの再利用性について

私の経験上、異なる業務問題領域に対する業務問題領域クラスの再利用は、避けたほうが良いと思います。業務問題領域は、業務仕様の変更に応じて常に最適化され続ける必要があるため、異なる業務問題領域間でのクラス再利用は適切ではありません。

業務問題領域以外のクラスの再利用について

アプリケーションをプレゼンテーション層、アプリケーション層、ドメイン層(業務問題領域層)、インフラストラクチャ層に分けて考えたとすれば、インフラストラクチャ層のクラスは再利用可能性が高いと言えます。Hibernateのようなツールや、jakarta commonsのようなライブラリ、社内ライブラリ(インフラ系)などがこれに該当します。
理由は、インフラストラクチャ層の問題領域は、多くのプロジェクトで共通だからです。金融系システム開発プロジェクトと流通系システム開発プロジェクト間では、ドメイン層はまったく異なりますが、インフラストラクチャ層(DBアクセスやロギングというレベルの問題領域)は重なるからです。

構造体を用いた手続き型開発か? オブジェクト指向か?

構造体(setter/getterのみのDTO)を用いた手続き型開発を行うか、オブジェクト指向で開発を行うかは、開発者のスキルセットに依存します。通常のエンタープライズシステム開発であれば、後者より前者が方法論として適している場合はほとんどありませんが、開発メンバーに十分なスキルがない状態ででは前者を選択すべきでしょう。後者は方法論として前者よりも難易度が高く分割統治も難しいが、プロジェクト規模や業務ロジックの増大、長期ライフサイクルの長期化に対しての耐性が高い。そのため、大規模案件ではメンバーのスキルを十分調整したうえで、オブジェクト指向を用いた開発を積極的に推進したほうがよいでしょう。