#はじめに#
オブジェクト指向設計が分からず挫折を繰り返した私が、習得のための考え方をご紹介します。
自分が挫折した経験を踏まえて書きますので、現状うまくオブジェクト指向が消化できていないという方にこそ読んで頂きたいです。
#オブジェクト指向設計の方法論については既にQiitaに優れた記事がたくさんあるので、ここでは語りません。
#私はWindowsに囲われた悲しきSIerなので、用語は.Net Framework基準になります。ご了承ください。
#オブジェクト指向に正解はない#
私がオブジェクト指向を覚えはじめた頃、社内のレビューで「どうしてこの設計にしたの?なぜ?」とかなりキツめに問い詰められました。
その時私は、自分が間違った設計をしていて怒られていると考えてしまいました。オブジェクト指向には私の知らない正解があるはずだと悩みました。
そして正解を求めて勉強を重ねるうち、ある言葉に出会いました。**「オブジェクト指向設計がどうあるべきかは設計者の視点で変わる」**と。
レビュアーは私が「どう考えて、どういう理由でこの設計したのか?」を知りたかっただけで、問い詰める意図はなかったのです。
オブジェクト指向設計は100人やれば100通りのクラス図ができると言われます。
設計原則さえ守られていれば、あとは正否ではなくプロジェクトが求める保守性と拡張性を達成できているかどうかの問題になります。
大事なのは自分がどう考えて設計したのか、はっきり説明できるようにしておくことです。
**オブジェクト指向設計に正解はありません。**アナタのソフトがどんな設計であるべきか、決めるのはアナタです。
できうる限りのケースを想定し、改造対してオープンで修正に対してクローズな設計を作りましょう。
考えに考え抜いた事実があれば、レビューの場でも自信を持って説明できるはずです。
#コンピューター世界をデザインしよう#
オブジェクト指向設計を説明する際に「現実世界をそのまま設計する」と表現している本やサイトは非常に多いです。私は、これはあまり良くないと考えています。
なぜなら、我々が作るプログラムはコンピューター世界に他ならないからです。
現実世界にデータベースはありません。フォームもテキストボックスも、演算子もありません。これらはコンピューター世界の住人です。
実際のオブジェクト指向設計では動物や車ではなく、架空の責務や概念をオブジェクトと捉えることがほとんどです。
現実世界の~は取っ掛かりの初心者へ説明するための比喩と理解し、発想の羽を広げてコンピューター世界をデザインしましょう。
#オブジェクト指向設計の宣伝文句を鵜呑みにしない#
頭の良い人たちは、しばしば不都合な真実を当たり前の認識として隠し、メリットのみを主張します。
頭の悪い私は言葉を額面通りに受け取り、え??そうなの?分からない・・と悩まされました。
かつて私が悩まされた宣伝文句をご紹介します。
###オブジェクト指向設計をすると、if文が無くなってシンプルなコードになる###
本当でしょうか?嘘です。
ソフトの仕様として「~の場合は~する」と書かれている以上、プログラムのどこかにif文は存在します。
ただ、手続き型に比べると、if文の書かれる場所が変わってくるのです。
FactoryパターンやStrategyパターンはif文を生成側で持つことにより、結果としてビジネスロジックのif文を減らしています。
###オブジェクト指向設計をすると、改造ではクラスを追加するだけで済む###
本当でしょうか?嘘です。
クラスを追加すると、当然生成のためにFactoryクラスなどにも改造が入ります。
そうツッコむと「それは当たり前でしょ」と流されますが、なら追加する「だけ」とか言うな(怒
※他にもあれば、是非コメントでお寄せください!
#レビューをしよう!#
設計ができたら。どんどんレビューで人から意見を募りましょう。
様々な視点からアイデアを出し合うことで設計は洗練されていきますし、設計テクニックの引き出しも増えます。
アナタの設計が、必ずしも他の人に理解できるとも限りません。
アナタのソフトを受け継ぐ後任者のためにも、人が見てすんなり理解できるような設計にしておくことが大事です。
レビュアーがオブジェクト指向設計に精通していなくても構いません。
自分の考えを言葉にするだけでも客観視できるようになり、設計の良い部分や足りない部分に気づくことができます。
何より、知らない人に教えるというのは、最高のスキルアップ手段になります。
#責務集約のコツ#
最後にちょっとだけ技術的な話をします。
特に手続き型からオブジェクト指向に挑戦した人が苦しむポイントです。
電卓を例に説明します。
手続き型の人が、オブジェクト指向的に設計すると以下のようなクラス分割になります。
(関連やメソッドの引数などは省略します)
演算子ごとのクラスと演算処理クラスに分ける形ですね。
一見、良いクラス図に見えますが、これはNGです。
なぜなら、演算子クラスがすでに存在するのに、重複した責務を持つ演算クラスが存在するからです。
これは単一責務の法則に反します。
クラスの責務を単一にすることを考えると、以下のようなクラス図になります。
演算子クラスにそのまま計算メソッドを持たせてしまうのです。
これにより、足し算という責務はPlusクラスに集約されました。
手続き型でのプログラミングをしていると、処理で分ける癖がついてしまい、データと操作を一緒にするという考え方になかなか慣れないと思います。
私自身この考え方の違いには苦労しました。
たくさん設計して感覚を変えていきましょう。
#まとめ#
・オブジェクト指向に正解はない。自分の考えをしっかり説明できることが大事。
・現実世界に囚われず、自由な発想で設計する。
・宣伝文句に惑わされない。
・レビューはどんどんやる。
・過去の設計手法に囚われず、感覚を変えていこう。
以上。お読み頂き、ありがとうございました!