Open8

オブジェクト指向を理解するまでのつまづき、思い込み

hatada@espritahatada@esprita

オブジェクト指向でつまづいたところ、思い込みで理解を阻害したことなど。
同じようなつまづき、もやもやを感じている人の理解促進のヒントになればいいな。
なにがヒントになるかわからないので、私が実際につまづいていたしょうもないことも書く。

最終的には記事や無料本としてまとめたいが、とりあえず思い付きを書き出します。
ツッコミとかもやもやが現在進行形の人からのコメント等大歓迎です。

hatada@espritahatada@esprita

書こうと思っていることのとりあえずリスト

一つ一つ取り出して書いて、書いたら削除。

  • 思い込み
    • 抽象・インターフェースで実装しろというけどnewするときに具象クラスを知らないとダメじゃん
      • なんでクラス図にはその関連は書かれないの?
  • 理解を助けてくれたもの
    • テスト駆動
    • リファクタリング
  • その他
    • どんな人が書いてるかわからないと信用してよいかわからないだろうから簡単に自己紹介を書いた方が良いかも。
hatada@espritahatada@esprita

愚痴:オブジェクト指向の学問的雰囲気

オブジェクト指向を学ぼうと本やサイトを読むと、なんか論文を読んでいる気になるんですよね。
大上段からの堅苦しい説明が長々と始まる感じ。
結局何ができるのか、どこが良い所かがわかりにくい。

また、この学問的な側面から来るのかもしれないのですが、「間違ったことは許さない」という雰囲気を感じてました。
ちょっと間違った理解を話すと鼻で笑われる感じ。
私が学び始めたころの環境のせいかなとも思ったのですが、そういえばネット界隈でも厳しめに「あれは違う」というやり合いを見かけるので、一定程度はそうした傾向はある気がします。
それもあって、正面からオブジェクト指向について話をするのが怖い、と感じてました。

ホントは話したり、使ったりすることで理解が深まるのに、この雰囲気が理解の妨げになっているじゃないかなと。
少しぐらい間違っててもいいじゃんね。

まあ、間違った理解で設計・実装するとあらぬ方向に行ってしまう、というのがあるんだとは思うんですが、もう少し率直にオブジェクト指向なり設計なりを話せると「より良い設計・実装」を考える機会が増えるんじゃないかなと。

ということで、中途半端な知識でもよいから「自分はこう思う」ということを話してみるのがよい。
聞く側も頭から否定するんじゃなくて、理解を示した上で議論するような風土ができると良いと思います。

結局のところ「便利だから使ってる」ものなんだし。

hatada@espritahatada@esprita

思い込み:どこでも適用できる正しいモデルがある

「学問的」と私が感じていたからかもしれませんが、「数学的に正しいモデル」というものが存在し、それはどこでも使えると思ってました。
たとえば「車」というオブジェクトは正しいモデリングをして作成したら、その「車」モデルをどこでも使える、というような。

たとえば自動車の製造会社の「車」と販売会社の「車」。
一連の業務として同じ「車」を作って売るんだから、同じモデルでは?と思ってました。

実際には、どの業務で使うかによってまったく変わってきます。
製造会社であれば一つ一つの部品(ナットなど)も要素として出てきて、それをまとめて「車」となっているかもしれません。
販売会社は車種やオプションや価格の方が重要なので、そうした項目が登場し、細かい部品については出てこないようなモデルになりそうです。
一社の中で製造・販売している会社だとしても、同じ「車」に対してはそれぞれ別のシステムで処理し、各システムでの「車」は異なったモデルになっていると思います。

いずれにしろ、現実の「車」というオブジェクトは同じでも、システムが対象とする業種や業務(これを"ドメイン"といったりします)によっても全然違う設計になります。

なので、大事なのは「一般的にどうか」ではなく「その業務ではどんなものとして取り扱うべきものか」です。

学び初めのサンプルが原因?

これ、原因の一つに、オブジェクト指向の学び初めのサンプルがあるような気がします。
オブジェクト指向を最初に学ぶときに、「まずは車をモデリングしてみましょう」みたいな例が出されたりします。
そしてこんな図が出てきます。

継承とか多態性を説明するためにこうした図で説明されます。
が、これは説明のためのものであり、現実には意味がないモデルです。
このモデルの使いどころとなるシステムの内容が書かれていないからです。

つまり**「モデル」は背景とか文脈(これをコンテキストと言います)がなければ本来は作れないもの**なのです。
そうした前提がなく「では乗り物と車・船をモデリングしてみましょう」と言われてもモデル作成はできないのです。

仕方がない事情もある

サンブル的な図を否定的に書きましたが、これは仕方がない部分があり、私もこうした図で説明することがあります。
なぜかといえば、「システムのコンテキスト」というのは実際にはとても複雑で、これを背景にして説明するのはとても難しいからです。

名著として名高い『エリック・エヴァンスのドメイン駆動設計』という本があるのですが、これは上記で説明した「コンテキストなしにモデルは存在しない」ことを徹底しています。そのため、実際にエリックさんが関わったプロジェクトでの例が出てきます。
が、これを理解するのがまず大変です。現実のシステムを題材にしているので、そもそもやろうとしていることが結構複雑です。その業務(ドメイン)に詳しい人が考えたモデルをまずは理解しなければならず、これがまずもって大変。
そのうえで「こうした方が良い」といったアイディアが紹介されていますが、そこにたどり着くまでに息絶え絶えになってしまい何度読むのを中断したことか...

といった事情があるので、初心者に説明するものとして先のUML図のようなものが出てきてしまうのは仕方がない部分があります。
ここでは、そうしたモデルは「説明のためのもの」と割り切って、本来のモデルは「文脈(コンテキスト)」がないと作れない、使えない、評価できない、ということを知っておくとよいと思います。

hatada@espritahatada@esprita

思い込み:オブジェクトはモノ

オブジェクト指向の学び始めの時に以下のようなオブジェクトの識別を習いました。

  • 特定のオブジェクトを思い浮かべて見ましょう(例:車)
  • そのオブジェクトを構成している要素を洗い出してみましょう(例:タイヤ、ブレーキ)
    • これが「属性」です。
  • そのオブジェクトの動作を洗い出して見ましょう(例:走る、曲がる)
    • これが「ふるまい」です。

これはこれで間違いではないのですが、私はこの例から物理的に存在する「モノ」だけが「オブジェクト」だと思い込んでしまいました。
なので、実際にJavaの実装でnewするオブジェクトがたくさんでてきますが、これらが何なのかがずっとよくわかりませんでした。

この思い込みを見直すきっかけは「デザインパターン」でした。

Strategyパターンというのがあります。
ここでは初期のドラクエを例にしますね。

ドラクエで戦うときに「ガンガンいこうぜ」「命大事に」など、戦略を選ぶことができます。
これを選んでおくとそれにふさわしい行動を行ってくれます。
Strategyパターンはこの「ガンガンいこうぜ」「命大事に」といった戦略をそれぞれ「オブジェクト」としておきます。
そしてそのオブジェクトを切り替えることで戦略を変えた戦いを実現できます。

これを学んだときに「あれ?オブジェクトって別に具体的な「モノ」だけじゃないんだ」ということに思い至ります。
そこから色々考えてみて、結局のところ、「オブジェクト」は「人間が考える概念的なまとまり」を表現するもので、それは物理的な「車」のようなモノでもいいし、「ガンガンいこうぜ」という戦略でもいいし、「処理ツール」といったソフトウェアでもいいんだ、というように思えるようになりました。
要はなんらか整理するためのまとまりであれば「オブジェクト」と考えて良いのかな、と。

私はこう捉えることによって「オブジェクト」を柔軟に(というか適当に)考えられるようになりました。
厳密にはなんらか定義があって、本来の定義とはずれがあるかもしれませんが、通常の設計・開発で使う分にはこのくらいの適当さで「オブジェクト」を捉えておく方が設計・実装には使いやすいと思います。

hatada@espritahatada@esprita

思い込み:「モデル」は「図」

ここまでの説明でも「モデル」という言葉を使っていますが、この「モデル」という言葉はとても便利でいろいろな使われ方をしています。
その「いろいろ」がわからず、私は長いこと「UMLで表現された図」といったイメージから抜け出せませんでした。
なので「モデリング」というと「UML図で設計すること」という感じ。

これが間違いだとはっきり気づいたのは「ドメイン駆動開発」を読んでからです。
この本では「モデルは「蒸留された知識(意訳:設計して選んだ概念やその関係性)」であって図のことではない(P.1あたりとP.34あたり)」とはっきり書いてあります。
(わざわざこう書いてあるということは私と同じような勘違いをしている人が結構いるということかなと思ってちょっと安心したりしました)

つまり「モデル」というのは「システムを分析して整理した概念とその関係性」。
それを「UML図」で表現するのがオブジェクト指向の作法になっていますが、実際にはUML図で表現しきれない部分は自然言語などで補足したり、独自の図で表現したりしてもよい、というものでした。

なので私の思い込みの「UML図で設計すること」というのは関係性が逆で、正しくは「設計すること、設計したものがモデル。それを書くための表記法の一つがUML」という感じです。
ただの言い換えに思えるかもしれませんが、こう捉え直すことで設計が楽になりました。
具体的にはUML図で表現しきれないなあ、と思っていた部分は、別に文章でもExcel文書でも良いから表現するのが大事、と思えるようになったからです。

アジャイル開発でもドメイン駆動開発でもユーザを巻き込むことを推奨しているのですが、「ユーザにUML図をそのまま読ませるのは無理だよなあ」と思っていました。
でも、大事なのは「設計内容をなんらかの形で伝えて共有すること」であり、UML図にこだわる必要はないのでした。

もちろん、実装する上で技術者間で理解を共有するのにはUMLはとても有用で、これも積極的に使っていけばいいものです。
ただ、「このクラス図がよくわからない」のは、読み手側の技術不足ではなく、書き手側の説明不足という場合も多いというのが大きな発見でした。

hatada@espritahatada@esprita

思い込み:再利用性・拡張性を考えて設計・実装しないといけない

オブジェクト指向のメリットとして「再利用性」「拡張性」という言葉が出てきます。
が、これがくせ者。
「再利用性」「拡張性」ということなので、「別のところでこう使われるはず」とか「将来こんな機能が必要になるだろう」などと想定しながら開発しなければいけない気がしていました
でも、目の前のシステムを設計するのにいっぱいいっぱいなのにそんなの難しくないですか?
また、経験が浅い頃は「将来こんな機能が必要」なんて想像ができないので、オブジェクト指向で設計できる気がしませんでした。

私の場合、この思い込みを払拭してくれたのは「アジャイル開発」でした。
アジャイル開発では、上記のような「予測型」の作り方ではなく、現在必要な機能を「シンプル」に開発することを求めます。
必要なものが「シンプル」に作ってあれば、いざ新機能が必要となったときに余分なものがないので機能追加がしやすい、という「適応型」の考え方です。

この考え方に出会ってからとても楽に考えることができるようになりました。
現在必要な要件・設計に集中して開発しておくことが結果的に「再利用性」「拡張性」につながるからです。

実際には、この「シンプル」に作ることは、これはこれで難しい部分があります。
そのあたりはまた別途書きたいと思っていますが、ともあれ「目の前のことに集中することが再利用性・拡張性につながる」という発想の転換はオブジェクト指向を使う上での大きなポイントでした。

hatada@espritahatada@esprita

余談:オブジェクト指向とアジャイル開発

「オブジェクト指向」と「アジャイル開発」はそれぞれ独立したものとして語られることも多いですが、実際にはとても関係が深いと思っています。

私が体験的に感じていた雰囲気は以下のような感じ。

  • 「データと処理を別々に考えてそれぞれ設計する」という既存の設計技法に対する不満から「オブジェクト指向」の考え方が生まれる。
    • 単純な例としては広域変数がシステムの不具合の温床になりやすいことがわかってきた、とか
  • この「オブジェクト指向」を使って開発を行ってみるとウォーターフォールのような「予測型」の開発手法だとオブジェクト指向を生かしたシステムが作りにくかった。
    • 設計の深いところがわかってくるのは開発の後半。それを設計に組み込むとよりよい設計にできそうだがウォーターフォール型だと作りこめない
  • そこから、オブジェクト指向の良さを生かすために「アジャイル開発」という作り方が提起された。

というような流れだと感じています。

もちろん「アジャイル開発」の考え方自体だけでオブジェクト指向の設計・言語でなくても使える部分はありますが、やはりオブジェクト指向の柔軟性によって最大限に生かせるように思います。