目次
- オブジェクト指向の目的
- 良い実装の条件
- 良い実装を達成するための手法
- まとめ
- あとがき
オブジェクト指向の目的
プログラミングの目的は何らかの目的を達成するための機能を作成することである。
では、目的が達成しさえすれば作成したプログラムは放置で良いのだろうか。
もちろんバグもなく機能追加などもなければそれで終わりでよいが、大抵の場合そうはならない。
バグが発生した点を特定し、修正する必要がある。
まとめ
オブジェクト指向はバグが起こった際、機能追加が発生した際の修正範囲を必要最小限に抑えるための手法である。
良い実装であるための条件
では、良い実装である条件とは一体どこにあるのか。
良い実装の条件は人間の尺度によって定められる。具体的には以下に示すようなことが挙げられる。
- 予期せぬエラーが発生しない。堅牢性
- システムの停止や機能不全が発生しにくい。信頼性
- 処理内容を自分で書くよりもモジュールを利用、改造、追記したほうが簡単。再利用性や保守性
これらの条件についてまとめたものが凝縮度と結合度である。
まとめ
上記の記事にも書かれているが重要な点は機能によって凝縮度の種類を使い分けることである。
個人的には凝縮度の使い分けは以下のようにすると良いのではないかと考えている。
- 再利用性が高い機能。->機能的凝集
- 機能的凝縮を管理する機能。->逐次的凝集
- コードの読みやすさを目的とする機能。->通信的凝集、手順的凝集
良い実装を達成するための手法
良い実装を達成するための手法として以下がある
- オブジェクト
- カプセル化
- インターフェース
- 動的ディスパッチ
- 継承
オブジェクト
オブジェクト指向ではこのオブジェクトを用いて
ダンボール箱を想像する。ダンボール箱は荷物を詰めて運ぶためのモノである。
- 荷物を格納する
- 格納した荷物とともに運搬できる
これがダンボール箱の持つ振る舞いと言える。
また、ダンボールに書かれた宛名や名前、中に入っている荷物などはそのダンボールの状態と言える。
まとめ
オブジェクトは振る舞いや状態などを一つにまとめたもののことである。実体の有無は問わない。
カプセル化
ダンボールに荷物を詰めたので配達をしたい。
この時、荷物を運搬する配達員はダンボールの中身を開いて詳細に知ることが可能だろうか。
荷物を運搬する振る舞いを持つ配達員にとってダンボールの中身は重要ではない。精密機械や冷凍食品など特別な処置が必要か判断するための情報があれば良い。
逆に配達を依頼する際、配達員に配達のルートや荷物を積み込む位置、荷物を配達する配達員の名前を指定など配達という振る舞いをやり遂げるために重要でないことについては初めから依頼できないようにしておくほうが面倒でない。
このように詳細な設計を隠し、必要最小限な情報のみを開示する仕組みがカプセル化であり、ゲッター関数、セッター関数の役目である。
まとめ
カプセル化では必要最小限な情報のみに絞って示すことで実装時のミスと外部からの操作による予期せぬエラーや機能不全を未然に防ぐことができる。
インターフェース
荷物を預けられた配達員は配達という振る舞いを行う。この配達員に求められる振る舞いは配達の他にもある
- 配達
- バイクの運転
- 自動車の運転
- 配達先に対する配達料金の請求
- 配達結果の報告 etc..
このような配達員の持つべき振る舞いをまとめたものがインターフェースであり、この振る舞いができない場合は配達員として出勤させることができないといった機能である。新人教育の内容 + 一般的な人間の持つ機能がこれに当たるだろうか。
インターフェースを持つことの利点
インターフェースを持つことの一番の利点はモジュールを利用する人が知っておかなければならないことが減ることにある。
- システムが持つ重要な側面についてだけ深く理解すればよい
- バグが紛れ込む余地が減る。
- 無関係なモジュールの調査の必要が無くなる
- バグの特定が容易
まとめ
インターフェースではクラスに求められる振る舞いを事前に定義することで再利用を行う際の実装漏れを防ぐことができる。
動的ディスパッチ a.k.a 動的束縛
自分好みのお酒がランダムに届くサービスを頼むとダンボール箱の中にお酒数種類とチラシが入っていた。
届いたお酒の種類と飲み方は一緒に届いたチラシとそのチラシに添付されていたWebページに書いてある。
このようにオブジェクトに自身の型や実行方法を添付しオブジェクトを開いた先で柔軟に処理が行える手法が動的ディスパッチである。自身の型はお酒の種類、実行方法はWebページに書かれた飲み方のように考えるとよい。
まとめ
動的ディスパッチはオブジェクト自身で完結しているためコードの膨張を防ぎ、読みやすさの向上につなぐことができる。
継承
顧客が好んだお酒をランダムに届けるサービスとして、3本以上届けるベーシックなプランがある。
この会社はベーシックなプランに加えて、高級な種類のお酒から選んで届けるプランを新たに作ることにした。
この場合、3本以上届けるプランと高級な種類のお酒を届けるプランで振る舞いを変更する必要はあるのだろうか。
実際には変数やお酒の絞り込みを行う処理を変更して加えるだけで良いだろう。
つまりベーシックなプランと高級なプランでは同じ振る舞いをする部分が多く、販売までの流れを再利用できる。
このようにベースとなるクラスを再利用して新しいクラスを作る仕組みが継承である
継承の利点
継承では継承元の関数を上書きし、同じ名前の関数で継承先の振る舞いに合わせた処理が可能である。これをオーバーライドと呼ぶ。
- 仕様の変更、バグの修正などにより変更の必要が現れた場合に修正する箇所を減らすことができる
まとめ
継承は親となるクラスを再利用して子クラスを作ることでコードの重複を防ぎ、バグの抑止につなぐことができる。
まとめ
オブジェクト指向は以下のことを前提としていると考えられる。
- 人間が作成したコードにはバグが存在する
- コードの作成者とバグの修正者は同じとは限らない
- 機能に再利用できる点が存在する
- 将来的に機能追加の予定がある
今後は人間にとって理解しやすいコードの作成を心がけ、バグの修正が容易な分割の仕方を模索して行きたい
あとがき
私は他人のコードを読むことがとても苦手である。この記事を纏めるきっかけになったのは他人のコードをリファクタリングする機会に恵まれ、オブジェクト指向に基づいたコードの作成を行いたいと感じたからである。この記事をまとめた結果、私に足りていなかった、設計書に基づいたコードの作成や必要最小限の情報でのオブジェクト間のやり取り、オブジェクトの特徴をうまく扱った実装についての基礎知識を得ることができた。
今後は今回の知識を活かして設計の考案やテスト内容のチェック、実装を行っていく。