第1回【IT技術系コラム】オブジェクト指向設計-オブジェクト指向言語の特徴
オブジェクト指向設計―はじめに―
オブジェクト指向、今さらながらのテーマですが、改めて再考してみたいと思います。
弊社はシステムベンダーでありますので、よりよいシステムをお客様にご提供できるよう日々研鑽を重ねています。
弊社は主にMicrosoft様の.NET Framework環境においてC#言語を中心としたシステム開発を行っておりますが、拡張性に富んだ柔軟性の高いシステムを製作するには、業務・技術の背景、基礎となる考え方をしっかりと習得したうえで臨まなければならないと考えております。
そして、システム開発技術の基礎・背景という観点からは「オブジェクト指向の考え方・設計原則」は避けて通れない、開発者全員が共通言語として理解している必要のある領域だと考えており、社内の新入社員研修等でも過去何度となく取り上げているテーマであります。
技術系コラムを開始するにあたり、まずは基本に立ち返り、これら「オブジェクト指向」をテーマとして数回に分けて掲載してゆきたいと考えます。初学者の方等の理解の一助になれば幸いです。
オブジェクト指向言語の3つの特徴
現在のシステム開発現場ないしプログラミング環境において、オブジェクト指向言語は広く一般的に利用されていると思います。本コラムでは特に歴史をひも解くことは行いませんが、ざっと流行を振り返ってみると、古くは1970年代のSmalltalk、1980年代のC++、1990年代のJava,Ruby、2000年代のC#と、それぞれがオブジェクト指向型言語としての性能を備え、広く利用されていることはご存じの通りかと思います。
それでは、これらオブジェクト指向言語が兼ね備えるべき性能(特徴)とは何でしょうか?一般的に以下の3つがあげられており、簡単に整理したいと思います。
- カプセル化(Encapsulation)
- 継承(Inheritance)
- 多態性(Polymorphism)
1.カプセル化(Encapsulation)
一言では、「データ(変数)と処理(関数)をひとまとめにする」特性が「カプセル化」といえます。
従前の手続型プログラミング言語では、例えばグローバル変数(データ)というものを1箇所に定義しておき、処理(関数)によってこのグローバル変数を書き換える、というプログラミングが延々と行われていました。
単純なプログラムにおいては問題ないかもしれませんが、プログラムが大規模・複雑化していくと、変数を書き換える処理が散在し、非常に見通しが悪く、メンテナンス性が低くなってしまいます。
状態を示すデータ(変数)と、それに影響を与える処理(関数)の論理的な距離(意味、思考過程上の距離)・物理的な距離(データと処理の間の単純なコード行数の距離)が離れてしまうことによる混乱といえるでしょう。
ここではクラス(型、タイプ)とオブジェクト(実体、インスタンス)の説明は省きますが、オブジェクト指向言語においてはクラスによって「データと処理がひとまとめに定義」されていることはご理解いただけると思います。また通常、データにはクラスで定義された処理(メソッドやプロパティと呼ばれることもあります)からしか読み出し・変更出来ないように設計されます(オブジェクトはこれらの呼び出し、つまり「メッセージ」によって自己の責任範囲内で動作します)ので、このクラスの存在によって、データと処理の論理的・物理的な意味が近接した「カプセル化」が行われることになります。先ほどのグローバル変数のように、どこから変更されているのか分からない、という状況とは大きく異なります。
2.継承(Inheritance)
一言では、「差分プログラミングを実現する」特性が「継承」といえます。
クラスBはクラスAから「継承」して定義された場合、クラスBはクラスAの性質(カプセル化されたデータ及び処理)を引き継ぎます。一般的にクラスAは基底クラス、クラスBは派生(拡張)クラスと呼ばれます。
よくあるプログラミングの悲劇として、「コピー&ペーストプログラム」があります。(同じ処理を再利用したいので、誘惑に負けてプログラム・ソースコードをそのまま切り貼りしてしまう。。。)
自明ですが、誘惑に負けたこのプログラマは、後に処理の仕様変更が生じた際、切り貼りした全ての処理を注意深く修正しなければならない羽目に陥ります。
「継承」は、この悲劇を回避するための1つの特性と言えます。
クラスの階層構造において、基底クラスで処理を定義することで、派生クラスでそれを自然に再利用できます。
また通常、派生クラスは基底クラスの性質を引き継ぎながら、追加の特性(振る舞い)を持つことになります。
「継承」機構によって、基底クラスの特性を引き継ぎつつ、派生クラスにおいて必要になったデータ及び処理を追加定義するという差分プログラミングが実現できます。
一方で、「継承」には以下のようなトピックもあり、単純なようで奥が深いテーマではあります。
- 「差分プログラミング」は結果であって、「差分プログラミングを実現するために継承を使用するべきではない」という意見・経験則。(「派生クラスB "IS-A" 基底クラスA」の関係ではない場合に継承を使用すべきではない。こういった場合、オブジェクト・コンポジションやユーティリティクラスを使用する等のテクニックがありますが、これは別の機会に触れたいと思います。)
- さらに、IS-A関係であればすべからく継承を利用すべきかというとそうとも言えないことを、後のオブジェクト指向設計原則(LSP:リスコフの置換原則)にて説明したいと思います。
3.多態性(Polymorphism)
一言では。。。なかなか表現しづらいですが、「同一の命令に対して異なる振る舞いを実現する」特性が「多態性」といえます。
Polymorphism=poly(多くの。ポリエステルやポリマー等の「ポリ」。)+morphe(形態)による造語のようです。
例えば、私が「電気機器」オブジェクトを所有していて、朝のルーチンワークとしてオブジェクトの「スイッチを入れる」という行為を日課としているとしましょう。
- オブジェクトが「テレビ」であれば、めざましテレビを見ることが出来ます。
- オブジェクトが「パソコン」であれば、OSが起動してメールチェックが出来るでしょう。
- オブジェクトが「電動歯ブラシ」であれば、歯を磨くことが出来ます。
テレビ、パソコン、電動歯ブラシともに「電気機器」から派生するクラスの実体(オブジェクト)ですが、同一の「スイッチを入れる」という命令に対して、異なる振る舞いをします。
「継承」とも関連しますが、通常このような仕組みは、「電気機器」基底クラスにおいて仮想的な「スイッチを入れる(TurnOn)」という命令の存在のみが定義されていて、各派生クラスにおいて具体的な振る舞い(画面が映る、OSが起動する、振動を開始する)が定義されることで実現することができます。このような異なる振る舞いの実現を「多態性」と呼んでいます。
また、本例のような「朝起きてすること=アルゴリズムの骨格」を定めておき、その具体的な実装を派生クラスに任せる設計手法は、"Template Method"デザインパターンと呼ばれています。
デザインパターンはオブジェクト指向設計における偉大な先人(Gang of Four(GoF):Erich Gamma,Richard Helm,Ralph E. Johnson,John Matthew Vlissidesの4氏)により類型化された再利用可能なオブジェクト指向設計手法であり、23パターンが定義されています。こちらも別の機会に触れたいと思います。
オブジェクト指向とは何であり、何のために必要とされるのか?
今回はオブジェクト指向言語が備えるべき3つの特徴について簡単にまとめましたが、最後に、オブジェクト指向とは結局何であり、何のために必要とされるのか、についての私見で締めくくりたいと思います。
- 何なのか:階層化・抽象化のための表現技術で、複雑化した関係構造を整理整頓するための技術
- 何のため:人間の思考過程になじみやすいから
先ほど述べたカプセル化・継承・多態性によって、階層化・抽象化されたオブジェクト・ネットワークを構築することが出来ます。
また、我々人間は一般的に物事を階層化して整理することに慣れているのではないでしょうか。例えば書籍は章立てで整理されますし、巻末にはアイウエオ順の用語索引があります。
我々のビジネス領域における会計分野においても、実務上の会計処理を帰納的に整理するかIFRSのように原理原則から演繹的に整理するかはともかく、資産は流動資産と固定資産等のように階層化分類されます。XBRLにおけるタクソノミ(Taxonomy)という用語は分類(学)という意味を持っています。XBRLはXMLをベースとした技術ですが、XMLではタグの階層構造で意味を表現します。(XBRLでは若干異なりますが。)タグの階層構造もまたオブジェクト指向になじみやすいものだとも考えます。
そして、我々はこういった構造を図式化して、線でつなげて整理するのも好きです。線で繋げるためには、繋げるモノ(オブジェクト)の境界がはっきりしていなくてはなりません。カプセル化は、この境界をはっきりさせるのに役立ちます。
というわけで、オブジェクト指向と我々の思考過程とは自然な形でフィットしやすいものであり、だからこそ広くシステム開発の現場で受け入れられている技術なのだとも思います。
また、オブジェクト指向言語(C#等)はより高度なユーザビリティを追及して進化し続けているようにも思います。(例えばジェネリクス、ラムダ式等。)
我々は主にC#を使用していることもあり、今後、C#での実装例等も織り込みながら、オブジェクト指向設計原則、デザインパターン、最新の実装技術等、順次コラムで整理していきたいと考えています。
取締役副社長 CTO 公認会計士 森貞裕文









































