はじめに
本記事はごく私的なもので有り、記述する私自身が記憶を呼び覚ますためだけに存在する記事であることを先に述べておきます。
内容
オブジェクト指向でなぜ作るを読んで、オブジェクト指向とはもはやプログラミングの設計だけにとどまらず、より良いシステムを作成するための考え方としても活躍している。
今回の記事では、私自身により身近に考えなくてはいけないプログラムを書くときにオブジェクト指向的にはどのような記述を考慮すべきなのかという点に重きを置いて書いていく。
オブジェクト指向が誕生したきっかけ
従来のプログラミングの欠点を補うために用いられ考え方であるということ。
ここでいうところの従来のプログラミングとは、構造化プログラミングのことであり、この開発手法が解決したのはGOTO文の乱用によるスパゲッティコードの回避と共通サブルーチンによる再利用である。
逆に残された課題というのがグローバル変数と貧弱な再利用性の二点である。
この二つの問題を解決するためにオブジェクト思考が積極的に用いられることになった。
コード記述におけるオブジェクト指向プログラミング
上記に挙げたオブジェクト指向プログラミングが発足する前にあった二つの課題(グローバル変数と貧弱な再利用性)を解決した三つの具体的機能が以下になります。
- クラス
- ポリモーフィズム
- 継承
それぞれを簡単に解説する
クラスの役割
普段何気なく使用していたクラス(使っていただけて使いこなせていない)。本書によるとその目的とはまとめて、隠して、たくさん作る仕組みとのことです。
具体的になんなの?というと
- メソッドと変数をまとめる
- クラス内部だけで使う変数やメソッドを外部から隠す
- 一つのクラスからインスタンスを大量生産
①まとめる
まず以下のサンプルコードを見てください(Rubyで構造化プログラミングを表現しているので多分間違ってる)
fileNo = 10
def openFile(str)
省略
end
def readFile(str)
省略
end
def closeFile(str)
省略
end
みたいなコードがあったとする。これをオブジェクト指向のクラスを用いて記述すると以下のようになる
class FileReader
atter_reader :fileNo
def initialize(fileNo)
@fileNo = fileNo
end
def open(fileNo)
省略
end
def read(fileNo)
省略
end
def close(fileNo)
省略
end
end
普段何気なくクラスを使っていたのでありがたみというものがなかったのですが、この本によると無造作に羅列してあった変数とメソッドをまとめることができるようになってコードの整理整頓が飛躍的に楽になったとのこと。
どういうことかというとPCのマイフォルダにあるファイルが全てデスクトップにある状態ときちんとフォルダの中にファイル名がつけられたものが陳列してあるのとでは、どこにどのファイルがあるのかが容易に捜索することができる。
また、フォルダ名があってその中のファイルなので名前をつけるのも容易になる。(勉強フォルダの中のruby.rbと開発フォルダの中のruby.rbのように同じ名前をつけることができる)
極端に言ってしまえば無造作に100メソッドあるか10このクラスの中の10メソッドでは、後でコード修正する際、クラスでまとめられていた方が気持ちが軽くなる。
まとめのまとめ
- 部品の数が減る(メソッド100よりもクラスが10の方がいいよね)
- メソッドの名前が楽になる(名前空間が使えるから)
- メソッドが探しやすくなる
②隠す
これは単純に変数へのアクセス制限のことで、以前の構造化プログラミングの時代では変数を宣言してもどこからでもアクセスできるグローバル変数だったとのことです。これにより変数の値が知らず知らずのうちに意図していない値に変化していた場合、全てのコードから原因を洗いざらい探すしかなかった。
そこで登場したのがアクセス制限。クラスの中で定義した変数をprivateにすることでもし万が一、変数の値が変化していてもそのクラス内部だけを参照するだけで良くなった。つまり保守性が良くなったということです。
隠すのまとめ
・クラスに定義した変数やメソッドを他のクラスから隠すことでプログラムの保守性を向上させる
③たくさん作る
今回もオブジェクト指向プルグラミングが発足する前の話からなのですが、構造化プログラミングで全く同じ処理だけど使用するグローバル変数は異なるものを使用したい。という時は変数ではなく配列を使用して繰り返し文を用いてと、、かなり複雑な処理を記述する必要がありました。(使ったことがないので知らないですが)
そこでオブジェクト指向プログラミングのこのたくさん作る仕組みであるクラス>インスタンスの構造を用いることで解消できます。異なる変数を持たせたい場合は定義したクラスを用いてじゃんじゃんインスタンス化すればいい。ということです。
このパートはすんなり理解できたので詳細は以上です。
たくさん作るのまとめ
・一旦クラスを定義することでそこから異なった情報を持つインスタンスを作成することができる。
・初めから複数の情報を扱うという前提を考慮しなくていいのでロジックが簡略化できる。
ポリモーフィズム
この単語は正直あまり聞きなれない単語だったので理解がふわついています。
ポリモーフィズムをズバリ表現すれば、「共通メインルーチン」を作るための仕組みです。共通サブルーチンは呼び出される側のロジックを一つにまとめますが、ポリモーフィズムは反対に呼び出す側のロジックを一本化します。
とのことです。正直ここだけ聞いてもなんのことかピンと来ませんでした。私が普段見聞きしているのがRubyなので[Ruby ポリモーフィズム」と検索をして一番上に出て来た記事によるとRubyでいうところのポリモーフィズムはクラスとスーパークラスに関連しているとのこと。
class Foo
def run
省略
end
end
class Hoge < Foo
def run
省略
end
end
class Bar < Foo
def run
省略
end
end
h = Hoge.new
h.run
b = Bar.new
b.run
このように親クラスFooで定義してあるメソッドrunですが、子クラスのHogeでもBarでも同じように呼び出すことができる機能のことだそうです。
この辺はあまりにも自然にというか全く気にせずに使っていたのでまさかポリモーフィズムとかいうややこしい名前がついていたとは知りも知りませんでした。(勉強不足です...)
まぁこの機能により複数のクラスを継承していっても定義してある名前が被ってしまってバグが発生する?みたいなことを未然に防いでくれているのかなと勝手に解釈。(今後勉強していかねば、、)
継承
これもよく聞くやつですね。
共通する機能を一つのクラスにまとめ、その機能を使用してサブクラスに引き継がせることで無駄なコードの重複を省くことができます。
まさしくDRYの考え方に基づいていますね。
継承については容易に用途が理解できるので短めに、、
まとめ
これまで記述してきたクラス、ポリモーフィズム、継承が登場しました。
クラス
- メソッドと変数をまとめて一つの部品化する
- 目的 整理整頓
ポリモーフィズム
- メソッドの呼び出しを共通化する
- 目的 無駄を省く
継承
- 機能の共通化
- 目的 無駄を省く
以上がグローバル変数と貧弱な再利用性というオブジェクト指向プログラミングが流行する前の課題を解消した、具体的な技術だそうです。
なんというかこういったプログラミングの歴史を学んぶと、今の技術は先人の努力と発想の積み上げの上に成り立っているんだなと感謝しかありませんね。(特に黎明期の0と1でプログラミングしていたという話を聞いて)
終わりに
今回記述した記事の内容は
- オブジェクト指向でなぜつくるのか
という名著の本の一部分です。興味がある方は是非メルカリでもAmazonでも購入して読んでみることをお勧めします。