2020.10.061年を経過したので内容の本質を変えずにできるだけ丁寧な説明になるよう更新しました。
2021.01.23 「デザインパターンは有効だったか」を追加しました。
2022.01.31 「クラスの抽出(作成)と構成等について」を追加しました。
はじめに
Javaによるオブジェクト指向が始まってから二十数年経過しました。
システム開発分野では一応浸透したと言ってもよい状況かと思います。
とはいえ、Java言語自体は明確なのですが、オブジェクト指向についてはまだスッキリしないという方も多いのではと思います。
そもそもオブジェクト指向は、問題領域の世界を「もの」という視点で捉え、それら「もの」同士がメッセージを送り合ってシステムを動作させよう、というものでした。
ただ視覚可能な対象だと分かりやすいのですが、概念や抽象的な対象となると曖昧となりこれが混乱した一因にもなりました。また説明や紹介が現実の対象とズレていたものが多かった事も曖昧さや理解の困難さを大きくし混乱してしまいした。
そして、メッセージを送って動作させるという説明もより現実的には呼び出して使用するという表現の方が適切でした。
ということで、これまでの経過をもとに今一度オブジェクト指向について振り返って理解してみたいと思います。なお、以下の記述は個人的な主観にもとづく部分もありますので予め了承の程お願い致します。
本文で使用しているオブジェクト指向特有の語句については後尾部分に簡単な説明を記述していますので参考にして下さい。
オブジェクト指向とは何だったのか?
オブジェクト指向はそもそも人の認識や考え(概念)をベースにしているため明確な正解を決定できるというものではありません。
この前提をしっかり把握していないと種々の決断がつかない状況に陥ることになります。
結論から言えば、オブジェクト指向はシンプルにいうとデータ群と操作群(処理群)の整理・分類・構造化方法の1つだったということになります。
まぁ単に整理術・分類術・構成術です。
オブジェクト指向の基本(何だったのか)を例をあげて説明したいと思います。
(今さらという方は☆ここから☆~☆ここまで☆という範囲でパスして下さって結構です。)
--- ☆ここから☆ ---
ネットにも多くありますが、やはりわかりやすくするためにここでも簡単な例をもとに説明していきます。
例は壮大な料理の作成で、以下の手順となります。
1.富豪のお客様が壮大な料理を注文。
2.料理長を中心に多量のレシピを作成。
3.料理長を中心に多量の材料と道具を調達。
4.多量の材料と道具を使いやすいように整理箱を使って整理。
5.大勢の料理人が調理。
6.壮大な料理が完成。
という具合に壮大な料理を完成させるのですが、オブジェクト指向はこの内4.の項目に相当します。(もう少し広く扱うと2.~5.になります。)
それぞれの単語が持つオブジェクト指向上の意味合いは以下のようになります。
壮大な料理:システムあるいはプログラム群
料理人:開発メンバー
材料:データ
道具:操作あるいは処理・機能
整理箱(整理タンス)の名前:クラス名
レシピ:業務分析書、ユースケース記述、機能説明書など
調理:プログラム開発あるいは実装
4.の項目をじっくり考えると、いくつかの課題や疑問が湧いてくるかと思います。
(1)材料(データ)と道具(操作)はどのようにして集めるの?
これは多量のレシピから分析しどのような材料と道具が必要かを判断して決めていきます。
整理箱は予め作成しておき、何を入れたかわかるような名前をつけ、これを記載した
ラベルを貼っておきます。
(2)整理箱はどのくらい作成するの?
これは調理人が回りにある物を確認したり、他の料理人の意見を聞いたりしてこんな種類で整理しようという事で決めていきます。
余り数が多いと区分けが大変になり、反対に少ないと適切に区分けできない事になります。
また、基本的に1つの調理(1種類)は1つの整理箱で対応させます。
(3)どの整理箱に入れようかな?
これは当然の事ですが、
・この物(材料や道具)はどの整理箱にいれようかな?
・同じ種類の整理箱がいくつもできたのでこれらは整理タンスに収納しようかな?
というような事が課題として想定されます。
当然ながらグループ間や料理人間で整理の仕方が異なります。
日本中の料理人間でこの物は必ずこの整理箱にいれるという定義は当然ながら決める事はできません。
料理人間でまぁこんなもんかな?
という程度で妥協するのが現実的な整理方法になるのではないでしょうか。
しかし講釈をたれ細かな整理の仕方を押し付ける料理人が出てくるとやっかいで無駄な時間が浪費されてしまいます。
所詮は整理術です。ぐだぐだ言う前にさっさと片付けて料理を始めた方が良いのに決まっています。
(4)整理箱に入れる判断や基準は?
材料と密に関連する道具を同じ整理箱に入れます。
材料や道具を複数入れても構いません。
整理箱の中に更に整理箱を入れても構いません。
整理箱に他の整理箱への依頼書を入れても構いません。
(5)整理・調理のやり方は?
整理・調理は料理人がやります。
料理人は整理箱にある材料と道具を使用して調理していきます。
少し属性の異なる材料を調理する必要がある場合は中に入っている別な整理箱の中の道具を使用する事も可能です。
そして最終的に完成した料理一品が出来上がります。
これをいくつものグループで実施して壮大な料理を完成させていきます。
--- ☆ここまで☆ ---
(6)まとめると
単語を元に戻してまとめると、オブジェクト指向は、
・経験・知識・ドキュメント等から必要なデータ群や操作群(処理群)を識別。
・データ群と操作群(処理群)の整理・分類・構造化を実施。
・整理・分類・構造化は定義したクラス(整理箱)に密に関連するデータ(材料)と操作(道具)をアサインして実施。
たったこれだけの事でした。
クラスというものの本質
以上の説明の中でそれまでの開発手法(やプログラム)と異なる点の1つはクラスという整理箱ができた事でしょうか。
このクラス(整理箱)というものを少し説明しておきたいと思います。
クラスは関連するデータ群(材料)と操作群(道具)を入れるJavaプログラム上の基本単位(整理箱)になります。
また例をあげて説明しますと、例えば「スパゲティ」という整理箱(クラス)を考えてみると、
ペペロンチーノ、ミートソース、ボロネーゼ、ペスカトーレ、アラビアータ、
アマトリチャーナ、カルボナーラ、アルフレッド、ジェノベーゼ、トラパネーゼ、
ナポリタン、たらこスパゲティ、明太子スパゲティ、・・
というスパゲティに関する材料や道具を入れ込む事ができます。
オイルソース、トマトソース、クリームソース、バジルソースといった種類別に分けた整理箱をスパゲティの整理箱の中に入れても良いかもしれません。
オイルソースであればペペロンチーノを、トマトソースであればミートソース、ボロネーゼの材料と道具を種類別整理箱に入れることになります。
そして、気をつける事は「スパゲティ」がいつもクラスになるとは限らないという事です。
「食物」というクラスを考えるとスパゲティは材料(データ)になるという判断も可能となります。また、ペペロンチーノも材料(データ)ではなく、トッピング等を考慮すると整理箱(クラス)になる可能性があります。
つまり、どういう問題をどういう視点でとらえるかという事で整理・分類が違ってくることになります。当然人によっても変わります。
なのでどのようなクラスを定義しても万人から正解と評価されるようなものにはなりえず常に曖昧性を持つものとなります。
この部分が比較的判断や認識齟齬の元となり、多くの人が関係する程混乱する原因となっていきます。どれが正解という事が判断できる訳ではないので間違いでなければ次へと進んで行った方が良いと思います。
そして、具体的に要求もされていない拡張性に配慮したクラスをわざわざ作成したりするのは避けるべきです。
曖昧さが増すばかりです。
クラスの抽出(作成)と構成等について
オブジェクト指向で重要なテーマとしてクラスの抽出(作成)、命名及び構成(他クラスとの関係付け)があります。(クラスはオブジェクト指向での「もの」を表現・定義したものです。)
このテーマに関しての個人的な指向や考え方を以下に記述してみました。
クラスの抽出(作成)、命名及びその構成は開発規模、採用する開発手法やアーキテクチャの選択等によって影響されます。
開発規模で言えば個人開発と大規模開発とでは対応や捉え方が異なり、個人開発ではどのようなクラスを作りどのように命名しどのようなクラス関係を構築しようが開発者自身が納得・認識できるものであればソースを公開しない限り特に問題が発生することはありませんが、多人数で開発する場合は通常ある程度のルール作りが行われるのでそれに制約されることになり、ルールから外れた作業結果が問題となる場合があります。
オブジェクト指向が注目され始めた当初のクラス抽出はユースケースを含めたUML(静的・動的)を作成し、それらを用いてクラスを作成していくというアプローチでした。ただ現在では開発環境が進歩したこともあって工数削減のためあえてUML作成を省略して行う方法を取ることも可能ではないかと思います。この場合は仕様書等からクラスを直接抽出する方法となります。
基本的に仕様(orUML)等から抽出・作成したクラスは分析クラス(日本語で定義)となり、それをもとに設計工程以降でより具体化・詳細化して実装していくことになります。
クラスの初期的な抽出はその名前が名詞となり、システム上何らかの役割を持ち、主要属性とそれを処理する操作を内在させるという視点で行います。一般的にそれ以外に確定的な抽出ルールは見当たらないので、結果としてクラスの抽出は曖昧な作業となります。
極端に言えば、サブシステムを1つのクラスで実現させることも可能であり、また細部の処理を1つのクラスとすることも可能ですが、実際にはクラスの規模制限や役割は持つが複数の混在した役割は持たせないという観点から決められていくことになります。
クラスは分析クラス→設計クラス→実装クラスと具体化・詳細化していきますが、この過程においてはクラスの規模(行数)に注意し、規模が大きくなれば分割し、肥大化することを防いでいきます。規模を分析や設計工程で見通せれば予め対応できるのですが、予測が難しい面もあります。
一般的には属性に対する操作(メソッド)部分は多くなり、このため肥大化を防ぐ目的で分離していきますが、分離したクラスは機能ベースのクラスとなっていく可能性が高いのですが、分離クラスを含めた該当部分としてデータと操作が一体化していれば余り気にする必要はないのではと個人的には思っています。
つまり、作成したクラスの構成はクラスの肥大化を避けるため、あるいは役割の明確化のため分割(場合によっては統合)しつつ、かつお互いが複雑に関係し合うことは避るというバランスのうえで決めていくことになります。
最終的にはかなり多くのクラスを関連させてシステム機能を構築していくので単純な作業とはならず、全体としてクラス作成やその構成については繰り返しの推敲が結果的に求められることになります。
このようにクラス抽出・作成・構成は比較的曖昧な作業なのでルールを作っても大勢の開発者に徹底・統一することは難しく、クラスの抽出・命名・構成は出来る限り先行してテンプレートを作り具体的なサンプル情報を多く開発者に提供した方が労力はかかりますが結果的には統一性が向上するのではと思われます。また予め基盤的な共有クラスの情報提供をしておくことも開発者のクラスに対する作業を軽減するのに有効となります。
そして現在では何らかのフレームワーク(やライブラリ)を使用するのが普通であり、この場合クラス抽出・作成・命名のかなりの部分は半自動的に決まっていき、開発者が作成・命名するのは大部分がドメイン領域(ビジネスルール・ロジック)が中心となります。
クラスの命名については大規模システムになる程詳細なルールは避け必要最小限とした方がよいと思います。詳細ルールを規約として決めると開発物が納品物であればその規約を保証しなくてはいけなくなり、何らかの強制・チェックツールが必要となってしまいますので注意が必要です。
抽出・作成したクラスはパッケージに属することになりますが、クラス及びパッケージとも一般的な原則(「オブジェクト指向原則」)があり、これを参考として抽出・作成・構成していくという点にも留意が必要です。この原則はクラスとパッケージともに複雑さを避けつつ、再利用可能な構成にするという視点で考えられています。ただ、再利用という視点についてはプロジェクト毎に判断することでもあり、必ずしも「オブジェクト指向原則」を守らなければいけないというものでもありません。
以上のように クラスやパッケージの抽出・定義・構成は各工程毎に繰り返しの見直しが必要となり、分析や設計以降である実装段階でも変更(リファクタリング)しなければいけなくなる状況も多々発生しますが、より良くなるのであれば時間が許す範囲で改善を行う方が良いと思います。ただ正解は無いと思って対応する事が前提となります。
オブジェクト指向の特徴とその必要性
オブジェクト指向の輪郭が把握できたのではないかと思います。
次にその特徴に視点を移して更に理解を深めていきたいと思います。
オブジェクト指向の特徴として、インスタンス化と三原則(カプセル化、継承とポリモフィズム)というものがあります。
これらの特徴により、
(1)概念(クラス)からの実体化・具象化(インスタンス化)による同時複数処理への対応。
(2)同じ実装内容を複数個所で記述せず一か所に整理。
(3)実インスタンス(オブジェクト)を出来る限り隠蔽してその独立性をより高める。
を実現することができると言われています。
(インスタンス化について)
ではまず初めに、なぜインスタンス化が必要なのでしょう。
インスタンス化とはわかりやすく言えば、クラスのコピー・クローンを作成し、メンバー変数に値を設定する事を意味します。インスタンス化はマルチスレッド環境(同時複数処理)や継承・ポリモフィズムを使用する場合に一般的に行われます。継承・ポリモフィズムについては後述にして最初にマルチスレッド環境及びスレッド内環境でのインスタンス化について以下記述します。
マルチスレッド環境では同時に同一処理(データは異なる)を行う可能性があるためクラスを実体化・具象化(インスタンス化)し、各スレッド毎に異なるデータを内蔵する同種オブジェクトを生成して処理する事が一般的です。この方法により各スレッドは対象とするデータをすばやく適切に処理できるようになります。
ただマルチスレッド環境では必ずインスタンス化が必須という訳ではなく、単にクラスの存在だけでよい場合にはインスタンス化の必要性はありません。
現にライブラリなどはstaticメソッドを使用してかなりの部分インスタンス化を必要としてはいません。
一方、同一スレッド内でも同一クラスのインスタンス化されたオブジェクトを同時に複数存在させている場合があります。典型的な例としては、検索結果をもとに生成したオブジェクト毎(一般的には行毎)にそのオブジェクトデータを用いて何かの処理を行う場合があります。
例:売上明細毎に合計金額算出。
このケースの場合には、単に合計金額算出程度であれば上位の売上クラスで行っても良いのではという視点は当然としてあります。つまり該当複数オブジェクト生成の必要性が必ずしも必須ではないということになります。
そして、このようなオブジェクトのタイプとしてはユーザクラスとコレクション(ListやMap等)の2種類があり、ユーザクラスは実質処理メソッドを含んだ本来のものと含まないもの(Bean、DTO:DataTransferObjectやVO:ValueObject)の2種類があります。
どのタイプを使用するかという視点では、売上明細データ(DB)の状態を変える(値を変える)処理のような場合にはやはり売上明細クラス(ユーザクラス)で処理を行った方が良いというのは適切な視点です。
つまり、保持すべきデータがあり(一時的なデータではない)、その値を変更するような処理がある場合にはデータを保持するユーザクラスで処理した方が良い(そのようなクラスを作成すべき)という事になります。しかし、その値を変更するような特段留意するような処理がない場合にはコレクション、Bean、DTOやVOのようなクラスでも良い(カプセル化の必要性が薄い)と思われます。
また、検索結果が文字列リストで戻ってくるようなケースではあえて新規にオブジェクト群に入れ直さず文字列リスト(コレクション)を渡していけば良いと思われます。
以上のことから、同時複数処理において全体的にユーザクラスを設計してインスタンス化を行い処理することは可能(有効)ではあると言えますが、スレッド内環境も含めて必ずしも必須ではなく、臨機応変に対応していけばよいということになります。
つまり、オブジェクト指向(OOPも含め)において最も基礎的機能のインスタンスですが、現状をみると当時のキャッチフレーズ程の必要性は無いと思えます。
ただ、インスタンス化の特徴がオブジェクト指向の必要性・妥当性への説得にある程度寄与したのではと思っています。
(三原則について)
次に三原則であるカプセル化、継承とポリモフィズムについて説明したいと思います。
まずは各用語について説明します。
<カプセル化>:
データ(メンバ変数)とそれを処理する機能(メソッド)をクラスというカプセルに閉じ込め、これらに対するアクセスレベルを適切に設定して、データの損失や意図しない変更を避ける方法です。クラスの独立性をより高めることができるようになります。
<インヘリタンス>:
インヘリタンス(継承)は別のクラス(親クラス)のデータやメソッドを引き継ぐことができる仕組みで、「is a」関係つまり「子クラスは親クラスである」という関係が成り立ちます。
そして子クラスは親クラス名を使用して扱えるので使用クラスとの間が疎結合となり独立性をより高めることができるようになります。
<ポリモーフィズム>:
ポリモーフィズムは抽象クラスやインターフェースを利用してメソッドの呼び出し方法を共通化し、さらにオーバーライドさせることで同じメソッドを呼び出しても実インスタンス毎にその挙動を変化させることができる仕組みです。
更なる詳細は専門書やネット情報で容易に取得できますのでそちらを参考にして下さい。
次に、この三原則が実際に役に立つのかという視点をこれまでの経験をもとに評価・説明してみたいと思います。
(1)これら三原則を活用することによりプログラムはより独立性の高い簡潔なものとすることが出来るというのは確かなことだと思います。
(2)特に基盤機能(フレームワークや共通機能相当部分)開発ではこれら三原則はより有効になると思われます。
(3)オブジェクト指向分析・設計での整理・分類という流れから実装へのスムースな展開が期待できる仕組みと言えます。
(4)オブジェクト指向という言葉に捉われずに三原則のような仕組みを用いて必要な範囲で設計・実装していくことは現実的で有効かと思われます。
(5)ただ、これらの仕組みを必要以上に活用して設計やプログラム構造を複雑化させてしまうと生産性が低下していく可能性があるので注意が必要です。
上述のように、この三原則の志向はJavaオブジェクト指向だけが出来るというものでなく、多くの他の開発環境でも実践可能なものです。
最後に時々話題になっていたモジュールとの比較を説明したいと思います。
「オブジェクト」でできること(処理)が「関数」/「モジュール」でできないということは基本的には無いと思います。もちろんプログラム長、メモリー長や処理速度等を考慮せずにという事が前提となりますが。
「オブジェクト」の特徴として同時に複数個存在させることができるということがありますが、他方「関数」や「モジュール」では同時複数存在させることはできません。ただ、これも複数処理を実現できる機能を組み込めば「関数」や「モジュール」でも実質的に可能ということになります。
キャッチフレーズ的に言えば、「・・・をオブジェクト指向だから実現することができる。」というより「・・・を比較的容易にオブジェクト指向で実現できる。」というトーンなのではないかと思います。
少し先鋭したキャッチフレーズも混乱した原因だったかなと思っています。
以上のような説明を経て、はたしてオブジェクト指向は必要だったのでしょうか・・?
個人的にはオブジェクト指向は基本レベルで代替の無い新機能はほとんど無かったのではないかと思われ、この点から言えば必須であったとは思いませんが、それは有効であり、その登場により生産性向上や品質向上に一定の効果があったとは言えるのではないかと思っています。
なので、後述の利用に際しての注意点に留意して採用している分には一定の効果が期待できものと思われます。
オブジェクト指向での失敗
当時オブジェクト指向で開発したら失敗したという話を度々聞いたことがありました。では、そもそもオブジェクト指向で開発とは一体何を指していたのでしょうか。そして何を実施した結果として何が破綻してしまったのでしょうか。
Java言語を採用したために失敗したのでしょうか。Java言語は現在でも現場で第一線で活躍しており、致命的な何かがあったとは思えません。
筆者はシステム開発における一般的な事項での原因がそのほとんどではなかったかと思っています。失敗要因(費用・期限・品質において)としては以下の項目が挙げられます(受注者・開発者視点です)。
・適正な見積もりをしていない。
受注するために安易に価格を下げた。
価格に重点をおいてしまい、経験、技術、体制といった現実の視点を軽視した。
・仕様決定能力が低い・決定権限が低い。
開発にあたっては非常に多くの仕様を臨機応変に決定しなくてはなりません。
発注者側や開発側においてその能力や権限が低すぎたため適切な判断・決定が出来なかった。
・コミュニケーション能力が低い
発注者側と開発側の間、発注者側内部間、開発者側内部間での意思疎通が悪い。
とにかく責任を回避し他者へ作業・責任を転嫁する姿勢が強い。
・成功意志が低い。
発注者側及び開発側にとにかく成功させるという意思が弱い。
特にメンバーに時間作業者(他社社員で責任が問われないため)が多いとこの傾向が強くなる。
・経験が浅い。
開発基盤の技術や言語、ミドルウェアなど必要とする経験者の数が少ない。
ドメインの知識がないメンバーが多い。
これらをクリアして、はじめてオブジェクト指向で失敗という言葉が使える可能性が出てくるのではと思っています。
では、どのような事項がオブジェクト指向での失敗原因としてあるのでしょうか。
・分析や設計において本来の仕様ではなく、オブジェクト指向のための議論に多くの時間をさいてしまっていた。
・分析や設計においてオブジェクト指向のためのドキュメント作成に多くの時間をさいてしまっていた。
・クラス粒度を不必要に小さくしかつ複雑で深度のある構造としたためかえって開発に時間がかっていた。
・そもそもOOPをほとんど経験したことがないようなメンバーが多数いた。
・経験の少ない開発方法論を実践しようとした。
このようなところでしょうか。
このような事は本質的ではなく比較的容易に回避可能な事項だったと思えます。
前述のようにオブジェクト指向のための議論は必要最小限とし、本来の仕様決定に多くの時間を割くべきだったでしょう。オブジェクト指向への必要以上の依存・片寄りはコストパフォーマンスとしては良くないと考えるべきだったでしょう。
次に失敗という視点で開発方法論を振りかえってみたいと思います。
現在でもそうであるように当時も開発方法論があれこれ提案されていました。
これら種々の開発方法論が話題となり、オブジェクト指向と一体と認識され、これがまたオブジェクト指向に対する混乱の一因ともなりました。主として、従来のウォーターフォール型タイプからイタレーション型タイプ(アジャイル系も含め)への変更提案でありました。
では、現在イタレーション型タイプは主流になったのかといえばそうではなく基本はやはりウォーターフォール型タイプのままとなっています。
この開発方法論を混合した混乱がオブジェクト指向で失敗したという話の一因にもなっているのではないかと思われます。オブジェクト指向と開発方法論は基本的に区別して取り扱う必要があったのではと考えています。多くの技術者や顧客がこの時期においてソフトベンダー等に大いに貢献したのではないでしょうか(笑)。
では、ドキュメントについてはどのような対応にすべきだったのでしょうか。オブジェクト指向特有のドキュメントとして以下のものがあります。
概念モデル図、ユースケース図、ユースケース記述、パッケージ図、分析クラス図、
分析シーケンス図、設計クラス図、設計シーケンス図、設計アクティビティ図など
このようなドキュメントを律儀に作成していくことはコストパフォーマンスの視点から疑問である事は間違いありません。大きな規模の開発ではそもそも書ききれないのではないでしょうか。最近のUML図作成ツールは性能が向上していますが、やはり規模の大きいシステムでは図を書くことには無理があると思います。
必要な項目を適切な量で記述でき、有効活用でき、変更にも容易に対応でき、新たなツールを必要とせず、成果物としても利用できるようなドキュメント作成を指向するのが適切でしょう。ただ基盤的共通機能(ミドルウェアではないアプリレベルのフレームワーク)の開発においては一時的なドキュメントとしてクラス図等を作成することは有効と思われます。
オブジェクト指向でのドキュメントはUMLといった図主体ではなくエクセル表形式等で整理する方が時間的にも変更にも優位であることは確かでしょう。かつ必要な内容を的確に指示できるというメリットもあると思います。
初期画面についてはHTMLや画面デザインツール等で作成し、その後実装工程前に画面遷移を含めて実装なしでプロトタイプを作成確認し、実装工程で活用すればよいと思います。
なぜオブジェクト指向で開発するの
オブジェクト指向で開発する理由の1つとして、「それは変更に対して柔軟に対応できるためです。」という事が当時もっとらしく説明されていました。
変更箇所はホットスポットと呼ばれていました。勿論OOPによって意識して全体実装すればこの要求に対応することも可能でしょう。しかし、よく考えれば変更推定箇所は何百万、何千万ステップというプログラムの至る所に存在します。
変更の可能性が「高い箇所」という判断基準を導入するならその基準をどう明確化・具体化するのかというテーマにぶつかります。また、高い低いを誰が判断し、そのコストをどこが持つのかという事も問題となります。
運用業務を必ず受託できる見通しがあれば開発業務でリスクを多少負う事も可能でしょうが、近年ではそのような形態はめずらしくなってしまっています。
また、どのような変更が発生するのかを明確にせず推測でむやみにOOPすることは無駄で非現実的です。従って変更対応を行うためには予め変更仕様の明確化と決定、設計、プログラミング、テストという手順を踏む必要があります。つまり変更に対応できる仕組みを構築しなければいけないという事になります。この仕組み構築部分においてオブジェクト指向の特徴が大きな生産性や重要性を発揮するかといえばそれほどでも無いのではと認識しています。全体でみれば他の開発方法・手段と大差ないのではないでしょうか。
やはり、前述のように要求仕様書に明記し、費用と期間を計上できる環境で実現した方が良いでしょう。
デザインパターンは有効だったか
オブジェクト指向という単語が認知し始められた頃(20年弱以前)からデザインパターンという語句も広がり始め、多くのJava関係者が高価な書籍を何冊も購入した時代がありました。
当時の書籍はサンプルテーマ、UML図、サンプルプログラム、説明に関して完全な整合性がとれているとはいえず説明も十分ではなくわかりずらいものでした。
にもかかわらずJava関係者はとにかくGoF23パターン等を理解しようと一生懸命読んでいたのではないでしょうか。
このデザインパターンのメリットは「再利用性の高い柔軟な設計ができる」、「技術者どうしの意思疎通が容易になる」というものでした。
さて今振り返ってみてどうだったでしょうか、デザインパターンは効果的だったのでしょうか。
(1)再利用性の高い柔軟な設計ができる
そもそも再利用するにもクラス設計(クラス図など)自体をシステム全体に渡って行われていたのでしょうか。
おそらく納期・予算の関係上そのような事は少なく、サブシステム以下の詳細機能仕様や処理仕様を定義した後はプログラマーに任せていたのではないでしょうか。
デザインパターンはその上に乗る・連結・利用する対象が不特定なフレームワーク等の開発作業であれば有効な部分もあるのですが、具体的な仕様が決まっているシステム開発では柔軟性・再利用性の目的のためにあえて適用していけばかえって煩雑・複雑化していくので、活用する頻度・範囲は少なかったのではないでしょうか。
また、標準的デザインパターンを単に流用している範囲を超えて、自作のデザインパターンを作りそれを再利用していくという事はそれほど簡単なものではなく、またコストパフォーマンスも良くないと判断できます。
(2)技術者どうしの意思疎通が容易になる
「この処理にはこのパターンを使おう」という意思疎通が行えて有効というものでしたが、そもそも処理単位で担当者にプログラミングが任されていくので、そのような意思疎通の必要性は少なかったのではないでしょうか。
そもそもクラス設計に対する確認ミーティングを実施するという事も余りなかったのではないしょうか。
さて、ここまでの記述ではデザインパターンのメリットは余り無いという事になるのですが、今当時を振り返ると宣伝メリットとは別の利点があったのではないかと思われます。
(1)デザイン(クラス設計)にパターンを定義・活用できるという認識がされたこと。
(2)インターフェイスや継承の利用・活用といったオブジェクト指向と結びついた基本的なプログラミング手法を確認・習得できたこと。
つまり、デザインパターン自体よりもそれが含む技術的要素が役に立ったという事ではないかと判断しています。
最後のまとめ
以上これまでを振り返って思いついた事を記述しましたが、最後にこれら振り返りの結果から、今後オブジェクト指向を実践する場合において気をつける事項を挙げてみました。
参考にしてみて下さい。
- オブジェクト指向は整理・分類・構造化術の1つと捉え、それ以上の期待は避けた方がよいでしょう。
- オブジェクト指向に関する言葉定義や技術的事項に余り固執せず、普通にやるべき要求と仕様の確定をしっかりやることの方がプロジェクト成功の王道でしょう。
- オブジェクト指向を採用したからといって汎用的な変更対応を試みず、変更対応は顧客要求として確定し、予算と期間を明確化したうえで設計・実装対応することの方が良いでしょう。
- オブジェクト指向でのドキュメントとしては、UML図ではなく、エクセル等の更新・変更が容易で仕様書として利用できるものを採用した方がよいでしょう。UML図が必要であればシステム完成後成果物として1回だけ作成する方が良いでしょう。
- どのような開発方法にするかは顧客との契約によることになりますが、イタレーション型タイプよりはウォーターフォール型タイプにプロトタイプ作成行程を付加する方が全体として現実的と思われます。
イタレーション型タイプを採用する場合は契約形態や成果物への特段の配慮・注意が必要となるでしょう。
本記事中のオブジェクト指向に関係する語句の簡易説明
・概念
概念とは「物事に共通している特徴」という意味の言葉です。
共通した性質をもつ物事が複数ある場合に共通点によってそれらを同種類と捉え
て形づくられるイメージ。
例:猫の概念(猫のイメージ)、車の概念(車のイメージ)、etc
分類という違う視点で言えば上位の分類とも言えます。
・オーバーライド
親クラスで定義されたメソッドを子クラスで再定義することを指します。
・オーバーロード
同一クラス内でメソッド名が同一で引数の型、数、並び順が異なるメソッド
を複数定義することを指します。