「オブジェクト指向」
何年プログラムを書いていても、わかりやすく説明するのが難しい言葉ですよね。
最近、私なりにひとつの答えにたどり着いたので、
コードを交えて書いてみたいと思います。
オブジェクト指向って何というか、実装の方法論というより哲学みたいなもので、
オブジェクト「指向」というより、「志向」なんじゃないかと思います。
たとえば、ある男女の生涯を記録するという仕様があったとして、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$human_model = new HumanModel(); $working_model = new WorkingModel(); $relation_model = new RelationModel(); $man_data = ['name' => 'Will', 'sex' => HumanModel::MALE, 'birthday' => '1968-09-25']; $man_id = $human_model->create($man_data); $working_model->save($man_id, 'Actor'); $working_model->save($man_id, 'MC'); $woman_data = ['name' => 'Jada', 'sex' => HumanModel::FEMALE, 'birthday' => '1971-09-18']; $woman_id = $human_model->create($woman_data); $working_model->save($woman_id, 'Actless'); $relation_data = ['man' => $man_id, 'woman' => $woman_id, 'created' => '1994-09-19']; $relation_id = $relation_model->create($relation_data); $relation_model->update($relation_id, ['married' => '1997-12-31']); $child_data = ['name' => 'Jaden', 'sex' => HumanModel::MALE, 'birthday' => '1998-07-08', 'parents' => $relation_id]: $child_id = $human_model->create($man_data); $working_model->save($child_id, 'Actor'); $relation_model->update($relation_id, ['expired' => '9999-12-31']); |
のようなコードが書きたいか、
それとも、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$man = new Man('Will'); $man->born('1968-09-25'); $man->workAs('Actor'); $man->workAs('MC'); $woman = new Woman('Jada'); $woman->born('1971-09-18'); $woman->workAs('Actless'); $couple = $man->meets($woman, '1994-09-19'); $couple->married('1997-12-31'); $child = $couple->haveBaby('1998-07-08')->asBoy(); $child->named('Jaden'); $child->workAs('Actor'); $couple->forever(); |
のようなコードを書きたいか。
各クラス各メソッドの実装がどうなっているとかは、とりあえず考えないでください。
どっちのコードが読みやすいとか、使いまわしが利くとか、実装が楽とか、そういう話ではないんです。
圧倒的な「ストーリー感」の差なんです。
前者のコードは、せいぜいこうです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$human_model = new HumanModel(); $working_model = new WorkingModel(); $relation_model = new RelationModel(); //男のデータを作成 $man_data = ['name' => 'Will', 'sex' => HumanModel::MALE, 'birthday' => '1968-09-25']; $man_id = $human_model->create($man_data); $working_model->save($man_id, 'Actor'); $working_model->save($man_id, 'MC'); //女のデータを作成 $woman_data = ['name' => 'Jada', 'sex' => HumanModel::FEMALE, 'birthday' => '1971-09-18']; $woman_id = $human_model->create($woman_data); $working_model->save($woman_id, 'Actless'); //男女の関係データを作成 $relation_data = ['man' => $man_id, 'woman' => $woman_id, 'created' => '1994-09-19']; $relation_id = $relation_model->create($relation_data); //結婚日を更新 $relation_model->update($relation_id, ['married' => '1997-12-31']); //子供のデータを作成 $child_data = ['name' => 'Jaden', 'sex' => HumanModel::MALE, 'birthday' => '1998-07-08', 'parents' => $relation_id]: $child_id = $human_model->create($man_data); //子供の職業データを更新 $working_model->save($child_id, 'Actor'); //夫婦データを更新 $relation_model->update($relation_id, ['expired' => '9999-12-31']); |
後者のコードからは、自然とこんなストーリーが見えてきませんか?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//男の名はウィル。1968年生まれ。俳優・ラッパーとして活動 $man = new Man('Will'); $man->born('1968-09-25'); $man->workAs('Actor'); $man->workAs('MC'); //女の名はジェイダ。1971年生まれ。女優として活動 $woman = new Woman('Jada'); $woman->born('1971-09-18'); $woman->workAs('Actless'); //男は1994年のある日、女と出会った $couple = $man->meets($woman, '1994-09-19'); //2人は1997年の大晦日に結婚 $couple->married('1997-12-31'); //翌年、2人は男の子を授かり、ジェイデンと名付けた。 $child = $couple->haveBaby('1998-07-08')->asBoy(); $child->named('Jaden'); //子供もまた、俳優になった $child->workAs('Actor'); //2人はいつまでもおしどり夫婦として幸せに暮らしました $couple->forever(); |
男は生まれ、働き、出会ったり結婚したりするものです。
カップルは子供を授かったり、絆を深めたりするものです。
そう、そういう「もの」なのです。
この「もの」こそがオブジェクトです。
前者のコードでは、これらは全て、単なる変数、配列、レコードないしIDでしかありませんでした。
しかし、全ての「もの」には、それぞれ意味や役割があり、行動や変化があります。
その「もの」の種類を1つのクラスとして、
性質や状態をプロパティとして、行動や変化をメソッドとして表現するのが、
オブジェクト指向(志向)の出発点です。
この思想でコードを書けば、プログラムはとてもストーリーテリングになります。
男が女に出会う、という出来事(処理)が、
1 |
$man->meets($woman) |
そのまま “man meets woman” と書けるのです。
自然と、クラスは主語となり、メソッドは述語となり、引数は目的語となります。
そして、その結果何か(ここではカップル)が生まれるなら、それが戻り値になります。
実装レベルで考えると、
前者のコードの HumanModel, WorkingModel, RelationModel クラスを実装するのと、
後者のコードの Man, Woman, Couple クラスを実装するのとでは、
おそらく前者のほうが圧倒的に楽かもしれません。
オブジェクト指向にも具体的なメリットはあると思いますが、
それはやはり言葉で伝えるのは難しいです。
たくさんコードを書くしかないと思います。
ただ、そういうコードを書いてみようというモチベーションのひとつとして、
このような、オブジェクトが綴る「ストーリー感」を感じてもらえればいいなと思いました。