Oracle Certified Java Programmer認定試験の問題集(いわゆるJava黒本)の著者である志賀澄人さん(@betteroneself)が解説する「オブジェクト指向の基礎」の動画がとても分かりやすかったので、個人のメモがてら共有します。
動画の再生リストは以下でご覧になれます
https://www.youtube.com/playlist?list=PL0BiAlg8j4ZuDSu9GLU73-CVFgenU8T2P
なお、動画は全部で12本あるのですが、どれも6~10分ほどでサクッとみることができます。
この記事は自分のメモがてらでかなり端折っていますが、動画では図も交えて分かりやすくなっているので、全編見てみることをお勧めします。
なお、以下からは 動画タイトル | 副題
という見出し構成で書きますが、副題は私の方で勝手につけたものです。
オブジェクト指向の話1 | オブジェクト指向の定義と、なぜ設計が必要なのか
オブジェクト指向の定義を一言でいうと?
設計手法のうちの一つ
オブジェクト指向設計以外にも、構造化設計、などがある
設計とは何か
分割と結合を考える行為
なんのために設計するのか
どうやったら開発や保守のコストを減らせるか考え、コスト削減するため
オブジェクト指向の話2 | ソフトウェア開発における2つのコスト
開発コストと構造化設計
開発コスト= サービスをリリースするまでのコスト。イニシャルコスト
ソフトウェア開発という仕事ができた初期、まだソフトウェアエンジニアの数が少なかったので、いかに開発コストを下げて簡単に早く開発するか、に焦点を当てていた
保守コストとオブジェクト指向設計
保守コスト = リリースしたサービスを長期にわたり運用しながら仕様変更を加えるコスト。ランニングコスト
構造化設計で生まれたコードに変更を加えるのが大変で、保守コストをいかに下げるかが注目されるようになった
開発コストと保守コストの相反関係
開発コストを下げると保守コストが上がる
保守コストを下げると開発コストが上がる
その中でもオブジェクト指向は、保守コストを下げつつ、開発コストもなるべく下げるように工夫されてきた
何を重視するかによってソフトウェアの開発手法は異なり、全てのケースに対応できる銀の弾丸は存在しない
オブジェクト指向の話3 | 構造化設計とオブジェクト指向設計の考え方の違い
設計をする時に考えること2つ
- どんな処理をするのか
- どんなデータを扱うのか
どちらの順番を優先するかで手法が分かれる
構造化設計は、「どんな処理をするのか」を先に考え、それに基づいたデータの扱い方を考える
オブジェクト指向設計は、「どんなデータを扱うのか」を先に考え、それに基づいた処理の仕方を考える
プレゼンテーション/ビジネスロジック/データアクセス の3層構造
ソフトウェアの処理は、P(Presentation)/BL(Business Logic)/DA(Data Access)の3層で考えることができる
構造化設計のメリットとデメリット
構造化設計は、最も仕様変更の多い不安定なプレゼンテーション(外側)を起点に考え、それに合わせて、内側のビジネスロジックやデータアクセスを考える
メリット
- 見た目を元に作るので、分かりやすい、作りやすい
デメリット
- 見た目が変わると裏側の処理も変える必要が出てくる
- そしてその見た目はしょっちゅう変更される
オブジェクト指向の話4 | オブジェクト指向設計のメリット
Outside In Principle と Inside Out Principle
構造化設計は、外側の見える部分を元に内側の見えない部分を作るので、Outside In Principle
オブジェクト指向設計は、内側の部分を元に外側の部分を作るので、Inside Out Principle
Business Logicとは
ビジネスのルール、データの扱い方のルール
どんな順番でどんなデータをどう扱うのか
オブジェクト指向は、このBusiness Logicとそのデータの取得方法から考える
オブジェクト指向設計のメリットとデメリット
メリット
- 画面に依存しない作り方なので、Presentation層が変わってもBusiness Logic層やData Access層への影響を減らすことができる
デメリット
- 画面以外の、視覚的に見えない部分を色々と考えないといけないので、難解で、失敗もしやすい
オブジェクト指向の話5 | オブジェクト思考の4つの原則と、カプセル化・前編
オブジェクト指向の4つの原則
- カプセル化
- データ隠蔽
- 抽象化
- 情報隠蔽
仕様変更に強いとは何か
オブジェクト指向は保守コストを下げること、つまり仕様変更への強さに重点を置いた設計手法である
仕様変更に強いとは、以下の2つを満たすことである
- 影響範囲をすぐに特定できる
- 変更自体が容易である
影響範囲をすぐに特定できるように、関係するデータを一つにまとめるのが、カプセル化
影響範囲をすぐに特定できるように、関係するデータをまとめて、意味のある一つの単位を作り見分けやすくするのがカプセル化である
意味のある単位とすることで、「このまとまりはこんな役割があるから、他にもこういう所に影響してそうだよね」と推測することができる
単なるName
というオブジェクトだと、どこで使われているのか推測がしにくく、影響範囲の特定が難しい
カプセル化の2つのステップ
- 関連するデータを一つにまとめる
- 関連するデータを扱う処理を一つにまとめる
オブジェクト指向の話6 | カプセル化・中編
オブジェクトとは
関連するデータとその処理を一つにまとめた部品がオブジェクト
部品の最低単位をオブジェクトと呼ぶのであって、現実世界の物事を考えるのがオブジェクト指向というわけではない
カプセル化により、データに変更があった時の影響範囲を特定することができる
以下の画像でいうと、真ん中の丸い部分がデータで、その周りの四角がデータを扱う部分。それらをひとまとめにカプセル化することで、内部のデータが変わった時の影響範囲をそのカプセル内に閉じることができる
カプセル化の難しさ
オブジェクトBのある処理がオブジェクトAのデータにアクセスしてしまっている場合、オブジェクトAのデータの変更の影響範囲がオブジェクトBにも及んでしまう。
そうならないようにオブジェクトBの当該の処理をオブジェクトAに移すと、オブジェクトBの関連するデータや処理もオブジェクトAに移動する必要が出てきたりする。そうしていくうちに、オブジェクトAとBが互いに密結合してしまったり、肥大化してしまう。
オブジェクト指向の話7 | カプセル化・後編
getter/setterを使わないのが原則
オブジェクトのフィールドに直接アクセスしないように、フィールドはprivateにして、getter/setterを使ってフィールドにアクセスしましょう、という考え方がある
しかし、この考えには危険もある。
まずsetterだが、これは結局直接フィールドに値をセットしていることと変わらない
次にgetterだが、オブジェクトのような参照型をgetする場合、そのフィールドのデータがあるメモリ番地を渡しているので、結局、理論的にはフィールドの値に直接アクセスしているのと同じことになる。
なので、getterもsetterも使うべきではないのが原則
ただし、プレゼンテーションレイヤーやデータアクセスレイヤーでは必要なシーンもある
一方で、ドメインロジック層でgetter/setterを使っている場合はカプセル化を壊している可能性がある
オブジェクト指向の話8 | データ隠蔽
オブジェクト内部のデータを外部から隠すのがデータ隠蔽
あるオブジェクトのデータが他のオブジェクトから参照されていると、そのデータを持つオブジェクトに変更が加わるときに、「さらに他のオブジェクトからも参照されているかもしれない」とその他の影響範囲を探す必要性が出てくる
データ隠蔽の目的は、カプセル化を維持すること
カプセル化自体の目的は、仕様変更が出てきたときに、影響範囲を絞るための単位を作ること
一方で、データ隠蔽の目的は、カプセル化を維持すること
なので、カプセル化とデータ隠蔽は目的が異なる
オブジェクト指向の話9 | 抽象化
オブジェクト同士の共通点だけ見て異なる点を無視して表現することを、抽象化という
抽象化をしないと、オブジェクト同士の関係性が複雑になる
設計というのは分割と結合の行為だが、できるだけシンプルな結合を作る技法の一つが抽象化である
オブジェクト指向の話10 | 抽象化とポリモーフィズム
オブジェクトの扱い方とその実装を分ける考え方を、ポリモーフィズムという
一つのものだが、実装によりいろんな形態を持っているので、多態性(ポリモーフィズム)と呼ぶ
扱い方と実装を分けることで、実装が変わっても扱い方は変わらず、扱い方を使う側も仕様変更を受けずに済む。仕様変更に強くなる
オブジェクト指向の話11 | 情報隠蔽・前編
劣化することを想定した作りにすべきである
カプセル化や抽象化を使ってオブジェクト同士をシンプルな設計、仕様変更に強い設計にしても、長年運用される中で、後からプロジェクトに入ってきた人などによって、オブジェクト同士の関係性が劣化する可能性がある
データ隠蔽と情報隠蔽の違い
- データ隠蔽は、オブジェクト内部のインスタンスを隠し、カプセル化を維持するのが目的
- 情報隠蔽は、公開クラスと非公開クラスを分けたり、クラスの中で公開するとこと非公開のとこを分ける
オブジェクト指向の話12 | 情報隠蔽・後編
情報隠蔽を実際のコードで説明
- クラスA、クラスB、インターフェースSを共通のパッケージにし、インターフェースSを実装するクラスAとクラスBは非公開にする
- インターフェースにstaticなcreateメソッドを生やしてクラスAのインスタンスを返すことで、使う側はクラスAの実際のコードのことは一切知らずに済む
以上が、志賀澄人さん(@betteroneself)の「オブジェクト指向の基礎」の動画のまとめです。
志賀さん、記事上でのお礼になりますが、とてもわかりやすい動画を作ってくださり、大変ありがとうございます。
各動画はこちらの再生リストからご覧になれます。どれもわかりやすく、かつ短くまとまっていますので、ぜひご覧ください。
https://www.youtube.com/playlist?list=PL0BiAlg8j4ZuDSu9GLU73-CVFgenU8T2P