2008/03/30

OOP再考

■ところで私、OOPについて理解していないんじゃん?

VB6.0→VB.NET(VS2003)へ移行した当初は、OOP関連の書籍を読んだりして、わりとマジメにモヤモヤしていたものの、いつの間にかVB.NETでの表面的な書き方にすっかり慣れてしまって、

  • クラスは機能単位にまとめられてベンリだし
  • スコープの管理もなんだかラクチンだし
  • 全てをクラスで書くというシンプルさがいいではないの

というあたりで満足してしまっていたわけですが…。

移行当初に「差分プログラミングだ!」と思って、Formを継承するという大技にでて苦い思いをして以来(「VisualBasic」なのにVisualな環境ではなくなってしまい、ボタンの位置をズラしたくても、ソースに戻らねばならず大変なことに…。理屈を考えるとそりゃそーなんですけど)、すっかり懲りて、自分自身がコードを書く際には、継承、抽象クラス、Interfaceという三種の神器は、私の中ではまとめて「なかったこと」になっていたんですね。せいぜいヘルプを読む際に、その知識を生かす程度でした。

ところが最近、別件でサーフィンをしていたら、「俺のOOPの理解がどう間違っていたかのふりかえり」の記事がふと目にとまり、

クラス = 構造体 + 関数みたいにムリに構造化プログラミングの考え方で見ようとしてはいけない。でないと、オブジェクトを入れ替えることで実装を切り替えられる、という技術によって非常に柔軟なコードが書けるようになる不思議が中々理解できないんじゃないかと思う。

という一節が妙にココロに引っかかってきたんですね。私もクラス = 構造体 + 関数って捉えてない?捉えているよね?と自問自答…。

あらためて「OOPってナンだっけ。とりあえずデザインパターン本あたりから読んでみる?」という気になって、数年前に挫折したあたりからのやりなおし計画発動です。

■OOPやりなおし計画発動 ~ デザインパターン本を読む

4774115797
技術評論社 2002-09
売り上げランキング : 24748
おすすめ平均 star

Amazonで詳しく見る

やりなおし計画の第一歩として、「Javaデザインパターン徹底攻略 」とうい本を手にとってみました。

サンプルソースはホントにパターンの骨だけが書かれているこの書籍。非常に短いセンテンスでパターンを紹介しているので、読みやすく、それぞれのクラスの関係性については、よく見えてくる本でした。

ただサンプルソースは短いだけあって、ホントに骨だけ。具体性には欠けていて、この本を読んだからといって、すぐさま「おお、確かにこういうシーンで使うと超ベンリだよね!」という感じにはなれませんでした。

前半のパターンでは「こんなコードを、デザインパターンでこんな具合にシンプルに!」という、デザインパターン以前のサンプルソースがついていて、ナットクしやすかったのに、後半では何故かデザインパターン以前のサンプルを端折りだしていますしね…。このAfter、Beforeの対比は、是非、全部のパターンにつけて欲しかったですね。

というわけで、パターンの作りは見えたものの、この本を読んだからといって「すぐさまデザインパターンを自分のソースに…!」とはならず、「まー、いずれ使うかもね…」くらいの感じではあったわけですが…。

23パターンをつらつらと見ていて、強く印象づけられたのは次の2点。

  • ポリモーフィズムを使いまくり。
  • ポリモーフィズムを利用して、IF文での判定を減らしている。

「IF文って嫌われている?まぁ処理に名前はついてないからね…」と思いながら、ひたすらポリモーフィズムを利用するパターンを読み続けているうちに、今更ながらに、「ポリモーフィズムってこういう風に使うのか…」という「気づき」はありました。ポリモーフィズムを利用した書き方なら、結構ラクに今の自分の書き方に取り入れられるかも…、という「気づき」でもあります。

■ポリモーフィズムについて実践考

ポリモーフィズムを使うことを前提に、一つの機能について大雑把に整理しなおしてみると、次の3つの階層に切り分けることができます。

  1. データを具体的に加工したりする階層
  2. Aのレベルのクラスのメソッド等を順序よく操る階層
  3. Button.Clickのイベントの辺りで書いたりするクライアントプログラムの階層。

A階層のデータを操る部分は、データが変わるたびにソースを書かざるをえません。でもB階層は単なるメソッド呼び出しの手順なので、意外と一緒だったりすることが多いんですよね。データは変わっても、それを扱う順序は変わらない。

もともと汎用的なツールを作っているときは、データ(画像とか)を直接処理するAの部分は固定で、Bの部分を作り変えることが多く、自然とこの 3階層に切り分けて書くことが多かったわけなのですが…(とはいえ、この場合は、Bの部分の書き換えなので、ポリモーフィズムは利用できませんが…)。

それとは逆の場合には、これまで主に2階層で書いていました。業務によって仕様の違うデータを処理する部分では(値を加工してテーブルを入れたり出したりするような作業とか)、A+Bが一体となっているクラスαを作って、Cからαクラスの、順序を管理しているメソッドを呼び出す…、という書き方です。Button1のクリックに対応するのはαクラス、という1対1の関係で、αクラスのメソッドを順番にみていけば、ストーリーの大筋は終えてしまう、という書き方。

ただこのB的な「順序を管理しているメソッド」の大部分は、別のクラスからのコピー&ペーストの世界です。このコピー&ペーストのメソッド部分を、別クラスに出して、3階層で切り分けてみると、A階層のクラスをひたすら作り変えている、というカタチになるなぁ、と今回改めて気がついたわけです。


もう少し具体的に考えていきましょう。たとえば、CSVファイルのDBへのインポート機能を考えると、

  1. ファイルのパスをゲット。
  2. テーブルにデータを突っ込む。
  3. インポートしたデーターのエラーチェックを行なう。
  4. エラーがあればレポートの出力。

シチュエーションによって多少の差異は出てくるにしろ、大筋はこんな流れになります。

ということは…。

  1. 定型的なメソッドをInterfaceで宣言
  2. A階層のクラスでInterfaceをImplements。
  3. B階層のクラスはInterfaceで宣言したクラスを操作する。
  4. クライアントプログラムとなるC階層では、BのクラスをNewするときか、別メソッドを作るかして、Bのクラスへ、引数としてAのクラスを渡す。

InterfaceをImplementsしているA階層のクラスを、データに沿ったカタチで複数作っていけばいいわけですね。クライアントプログラムでは、扱いたいデータを処理しているA階層のクラスをひとつ選んで、ひたすらBのクラスへ引数として渡せばいい…。

データを入れたり出したりのバッチ処理は、頻繁に書いているものの、フローのバリエーションはいくつかに絞れそうですし…。そのバリエーションの数だけ Interfaceを作って、Interfaceを操作するBも作ればいいわけですから。作ってしまえば、あとはひたすらAの部分を書いていくだけ、と。

ポリモーフィズムを連荘で見せつけられて、自分の今のソースへの当てはめ方も見えてくると、「なーんだ、そっかー、簡単じゃん」という気になってきました。…私、騙されています?それとも、今更…、ってところなのでしょうか。

memo

VBユーザーだけどOOPならJava本でしょ、やっぱり

私はVB2005ユーザーですが、OOP本はなにかとサンプルソースがJavaの本が多いので、「Javaをある程度読めないと、OOP本は読めないぞ」と思って、VB6.0→VB.NET(VS2003)への移行当時、覚悟を決めてJavaの入門書を一通り通読しました。で、Javaの入門書を読みながら思ったことといえば、

VB.NETの参考書よりも、Javaの参考書を読んだ方が、クラスのお作法についても、なんだかわかりやすい」(ナニソレ)

Java本が質・量とともに豊富なのに比べて、.Net系の良い参考書は、今でも「コレ!!」といったものがないですからね。VBユーザーといえども、Javaの簡単なサンプルソースくらいは読めないとツライご時世なのです。

とはいえ、今回私が読んだ「Javaデザインパターン徹底攻略」程度の簡単なサンプルソースであれば、わざわざJavaの入門書まで戻らなくても、ある程度、クラスのお作法に慣れている人であれば、非Javaユーザーの人でもつらつらと読めるのではないかと思います。共にOOP志向の言語で、大筋は似ていますから…。

ちなみにVB2005とJavaとの差異の部分は、VBという言語仕様のOOP志向への中途半端さ加減を感じる部分でもあります。例えばVBの場合、Interfaceにアクセス修飾子をつけられます。「ちょっとマテ。そこでpublic以外のアクセス修飾子をつけられる余地があるのは、どういうことなのさ?ポリモーフィズムを利用しようと思っても、不完全な可能性が…」この種の方向性の中途半端さ気がつくとなんだか気持ち悪くてムズムズしてきます。…あぁ神サマ、どーして私はVBユーザーなのでしょーか。この気持ち悪さを忘れるくらいの、自分の言語に対するLoveが欲しい。

memo2

Matzのにっき→2003年のOOPの記事リスト

Rubyは触ったことがないのですが、内容的にはなるほどなるほど。「オブジェクト指向は難しい」のオブジェクト指向の嬉しさの違いや、「(その2)」のオブジェクト指向のシンプルさについては、拙い書き方ながらも、これまでクラスを書きはじめてから感じていたことだったので、「あぁこの嬉しさの違いは私にもわかるなぁ」と共感(嬉)。

「継承は悪か」のま2さんのツッコミ記事は今の自分にはタイムリー(2003年の記事で、世間的には5年も前の議論なわけですが…)。

4. で実際問題として,手続きが変わるより,データ形式が変わることの方が多い。したがって,実際問題としてオブジェクト指向の方が威力を発揮する。

オブジェクト指向は「データ中心」の産物で,「データ中心世界」では強い。そこでプログラミングの対象が「データ中心世界」なのか「手続き中心世界」なのかが重要だということです。結局オブジェクト指向とは「ものの見方」なのですね

まさに!!ってところですね。

0 件のコメント: