uzullaがブログ

uzullaがブログです。

そのオブジェクト指向入門は間違っている(大げさ) - Webアプリエンジニア養成読本 AdventCalendar2014 25日目最終日!

はい、Webアプリエンジニア養成読本 AdventCalendar2014です。突然トリをやる事になってしまったので、どうしたもんかとおもいます…。
「最終日だぞ…ちゃんとかかないといけない…しかしネタはない…そうだリンク集を作ろう!」とか思ったんですが、そもそもアドベントカレンダーってリンク集だよねって気付いて愕然としているクリスマスの夜です。現在朝の4時、これを書き終えて寝たい。

さて…何を話そう

ここまでWebアプリエンジニア養成読本アドベントカレンダーということで続けてきました。そして今日は25日、ついに最終日です!

Webアプリエンジニア養成読本 Advent Calendar 2014 - Qiita

著者陣4名と読者の方1名が特に取り決めなく、めいめい好き勝手に書いてきました。皆さん、いかがでしたでしょうか?もしこのエントリにいきなり来た方は、後で他のエントリも是非ご覧ください!


さて、私の担当箇所は、繰り返しになりますが「Webアプリエンジニア養成読本では、初心者は入門できない」と、複数の方にいわれつづけたので(まあ、実際言語の入門ではないので、そういう本なのですが)、あの本に書けなかった多少初心者向けの事をかいてきました。いくらかでも初心者の皆さんのお役にたてていれば幸いです。ブクマは多少ついていて希望は持てます。


とはいえ、ミッシングリンクはまだまだ埋まっていないのが現実です。
ここで私が書いたエントリを振り返ってみましょう。

・PC初心者でもPHP言語を兎に角手軽に試す 
・超初心者プログラミング入門は「何」をやるべきか、主にPHPの場合。 
PHPだってアプリたい!
・コミュニティに参加してつまづき最小限、学び最大限に
・ライブラリをつかって効率的にプログラムを書くぞ!
PHP開発には単なるエディタだけでなく、もっと良い環境を

とりあえず、PHPをはじめて、コピペコードをかいて、分からない事があれば、誰かに聞く、ライブラリもつかってみよう、そしてエディタもPHPStormとかIDEをつかいだすようになった…、そうなったら次はなにか?

そうですね、わかってますよ…オブジェクト指向プログラミングです!!

オブジェクト指向言語入門…?

もう勢いでここまで書いてしまいました、後戻りはできない。

本当は書きたくなかったんですよ、こんなの終わるわけねえもん。

ただ、ちょっとだけ、本当にチョットだけ、私の偏見(?)あるオブジェクト指向入門についてお話ししたいとおもいます。


オブジェクト指向入門のごくごく一部しかお話しませんから、これだけをもってオブジェクト指向プログラミングだと思わないでください。*1

でも、…もし気付きがあった!とおもったら、是非ともブクマでもツイッターでも何でもいいので教えてください。今後人に聞かれたら、自信をもってこの話ができます。

あと、いまさらですが、識者の方々へ。「こんなふざけた事かきやがって!」と思うでしょう。ごめんニャンごめんニャン…((c)すがまさお)。

しかし、私は当時結構苦労しました。こういう気付きでの入り方もある、ということでご容赦いただければ幸いです…。あるいは、本当にすばらしいオブジェクト指向プログラミングへの道筋となる資料をお教えいただければ、全部このエントリを消して、それへのリンクにしてしまいたいとおもいます…是非お願い致します。

本題、オブジェクト指向プログラミング「入門」は、何がむずかしいのか

これは本やサイトそれぞれなんですけど、大抵の場合、一番最初に「動物クラスがあって、トリクラスがあって、鳩クラスに継承されます」みたいな典型的な説明があるわけですよ、一度でもオブジェクト指向プログラミングを勉強したことがあれば、かならずそういう比喩をみていると思います。

今の私なら、言ってる意味は分かります。そう、言ってることはわかるんですけど、これ分かってる人からの目線なんですよね。いままで関数と変数で勉強してきたのに、いきなりトリとかカプセルとかでてきても困るじゃないですか!そっ閉じ回避不可能ですよ!

はい、これで困らない方は本当に有り難うございました、このつつましいエントリは貴方のお役にたてません、すみません。

「トリ未満」のオブジェクト指向プログラミング

まず、あなたが変数と関数でPHPのプログラミングが多少できると仮定します。すみませんが、変数と関数の解説はしません。
もしそれらも分からなければ、まずは変数と関数のプログラミングをおぼえてからで遅くありません、一回もどって勉強して、いつかまたこのエントリにもどってきてください。


さて、オブジェクト指向プログラミング(以後OOP)は、「クラス」っていうのと「インスタンス」っていうのだけが特に新しい概念です。

「…オブジェクトってどこいったの?」そうですね、それはわすれてください、マジで。*2

これの他にも絶対にでてくるのが「プロパティ変数」と、「メソッド」ってのがあるんですが、これは「変数」と「関数」だと思ってください、マジで。

クラスとは?

クラスってのは基本的に「一つのプログラム」です。

「なにいってんだこいつ」とおもわないでください、そういう風に捉えると、理解が早い、という話です。

クラスというのは、基本的に「プロパティ変数(以後プロパティ)」と「メソッド」でできています。前述の通り、これは「変数」と「関数」です。


ここでOOPでないコードを以下に書いてみます。変数と関数でできてますよね?わかりますよね?

<?php
$text = "hello world!";
function say($text){
    echo $text;
}
say($text);

このように、普通のPHPプログラムは、変数と関数をつかってつくられています。…わかりますよね?


さて、いきなりですが、OOPのクラスは、たとえばHelloWorldのプログラムを、プログラムの中に詰め込んだものです。

…どういうことかわからないですかね、ちょっとコードかいてみます。HelloWorldをするOOPのコードです。

<?php
class HelloWorld{
    public $text = "hello world";
    public function echoHello(){
        echo $this->text;
    }
}

これがクラスでかかれたHelloworldプログラムです!!!(ババーン

では、これを実行すると…なにもおこりません。なぜなら、これはクラスを定義した、つまりプログラムを作成しただけで実行していないからです。実行はこうやります。

<?php
class HelloWorld{
    public $text = "hello world";
    public function echoHello(){
        echo $this->text;
    }
}
// ここから下が実行している所
$helloworld = new HelloWorld();
$helloworld->echoHello();

実行すると、「hello world」と表示されます!

さて、これはHelloWorldという「クラス」を「インスタンス化」して、echoHello「メソッド」を呼び出しています。インスタンス化、というのはまあプログラムを起動だとおもってもらってさしつかえないです。

$helloworld = new HelloWorld();

このように書くと、$helloworld変数の中に、インスタンス化されたHelloworldクラス(プログラム)、つまりHelloWorldのインスタンスが起動されて、保存されます。
で、インスタンスに「->」という記号をつけると、その中にあるメソッド(関数)を呼び出せます。

$helloworld->echoHello();

このようにかくと、$helloworld変数の中にあるHelloWorldクラス(プログラム)の、echoHello()というメソッド(関数)を呼び出す事ができるのです。
どうです?なんとなくわかりますか?


ここで、あらためてよくわからない気がするHelloWorldクラスをみてみましょう。HelloWorld{〜}でかこまれているのと、まだ「public」ってキーワードはまあよくわからないかもしれませんが、変数ぽいのがあります、functionってのはあきらかに関数宣言っぽい、そうなんですよ、実はこれは変数と関数です。

「…あれ?なんだ?OOPというけど、たんなる変数と関数でできてるじゃないか?」とおもったら、まあその通りなのです。


ちょっとクラスに関数(メソッド)を増やしてみましょう、こんな風になるかもしれません

<?php
class HelloWorld{
    public $text = "helloworld";

    public function echoHello(){
        echo $this->text;
    }

    public function echoHelloWithName($name){
        echo $name."さんこんにちは!";
    }
}

$helloworld = new HelloWorld();
$helloworld->echoHelloWithName("太郎");

こうやると…想像つきますよね?「太郎さんこんにちは!」と表示されます。

書き方はちがいますけど、これってまったく普通の関数を追加作成しているのとかわらないとおもいませんか?実際その通りです!


変数の方もちょっと書き換えてみましょうか、以下のようにしたら?

<?php
class HelloWorld{
    public $text = "helloworld";

    public function setText($text){
        $this->text = $text;
    }

    public function echoHelloWithName($name){
        echo $name."さん".$this->text;
    }
}

$helloworld = new HelloWorld();
$helloworld->setText("こんにちは");
$helloworld->echoHelloWithName("太郎");

setTextというメソッドに「こんにちは」という文字列をわたして、「$helloworldインスタンスの中にある」$textプロパティ(変数ですね!)に代入して、それをechoしているわけですね。


どうです?おわかりいただけるのではないでしょうか?

これで、クラスってのが、PHPのコードの中にかける、「プログラム」だというのがわかっていただけたのではないでしょうか?どうですかね?わからない?

「プログラムの中にプログラムってなんだよ…」って思うかもしれません。プログラムってことは、いくつも同時に起動ができるのです。

<?php
class HelloWorld{
    public $text = "helloworld";
    public function setText($text){
        $this->text = $text;
    }
    public function echoHelloWithName($name){
        echo $name."さん".$this->text;
    }
}

$helloworld1 = new HelloWorld();
$helloworld2 = new HelloWorld();
$helloworld1->setText("こんにちは");
$helloworld1->echoHelloWithName("太郎");
$helloworld2->echoHelloWithName("太郎");

このようにかくと、$helloworld1と$helloworld2で、二つHelloWorldクラスがインスタンス化(起動)されます。

そんで、1の方だけ、「こんにちは」とsetTextして、2はなにもせずにechoHelloWithName()を読んでいます。

これがどうなるか…想像つきますか?

太郎さんこんにちは
太郎さんhelloworld

こうなるわけです!このように、インスタンス(実行されているプログラムみたいなもの)は、それぞれが別の(プログラム)実行(みたいなもの)とされるので、1つのPHPコードの中で、同時に同じプログラム(クラス)を衝突することなく動かす事ができるわけです!*3


どうですか?これで

・クラスがちっちゃいプログラム
インスタンスはクラスをプログラムの中でクラスをプログラムみたいに起動したもの
・複数インスタンスをつくれば、それぞれ別の実行で、それぞれのインスタンスは衝突せず

ということがわかるのではないでしょうかね?

ここまでくると、最初の「クラスはちっちゃいプログラム、普通のPHPコード同様に、中には変数と関数がはいって出来てる」というのもなんとなくまあ言ってる意味はわかっていただけるのではないでしょうか。

これが私がお伝えしたかった事です!以上!!お疲れ様でした!!

…なんだこれは

以上です、これが原始的なOOPです。

「えっ…、こんなのがOOPなの?なにが嬉しいの?」と思うかもしれません。実際こんなの関数と変数でかけることです。たとえば

<?php
$text = "こんにちは";
function echoHelloWithName($name, $text){
    echo $name."さん".$text;
}

echoHelloWithName("太郎", $text);

こうやって書けばよい、その認識は猛烈に正しいです。

OOPは、猛烈に新しい「結果」ができる魔法ではない

そうなんですよ、OOPをつかわなくても、Hello worldは作れます!!びっくりしましたか!?


「じゃあなんで、OOPOOP!って世の中は叫んでるの…?」

そこで!やっと!ハトとか!トリとか!継承とか!カプセル化とか!ああいうなんかオブジェクト指向プログラミングでやたらと解説される話がでてくるのですよ!

ここらへんはキリがないので、ここでは解説しません!それに「どういう利点があるか」というのはあらゆる本で語り尽くされていますので、本を読んでみてください。

実際のところ、OOPの様々な機能(というか可能になる事)は、スゴイ便利なんですよ!(まあ、ここまでの説明ではOOPが全く便利に見えないと思いますが…)

OOPをつかうだけの人もいる

余談みたいですが、クラスを一切書いた事がなくても、知らず知らずの内にOOPを使う人もいます。

たとえば、(ウェブアプリケーションフレームワークとか、ああいうのをつかうと強制的にOOPをつかわされたりします。いまどきはOOPでないフレームワークはレアですからね。あれは「フレームワーク」のインスタンス(プログラム)を起動して、チョイチョイと色々操作して、まあうまいことウェブサイトが効率的につくれるようになっている。

クラスになっているから簡単につかえる。クラスになっているから膨大なフレームワークがもっている関数や変数と、自分がつくった関数や変数がぶつかることを心配しなくてもプログラムが書けたりするのです。


フレームワークでなくても、まあ、メール送信ライブラリとかツイッターAPIを叩くライブラリとか、そういうのもOOPでつくられていたりします。まあ、関数しかないライブラリとかもまだまだありますけど、大分減ってきてるかなとおもいますね。

OOPがわからずに使う時は「->ってなんだ?」と思いつつも、コピペすればなんとなく変数と関数の世界のPHPでもつかえたりします。それはOOPでかかれていることで、そのライブラリの中身の膨大なコードがうまく閉じ込められているからで、ぱっとコピペで良い感じに便利につかえたりするのです。便利ですね。

ここまで読んで「やっぱりOOPはいらないのではないか?」という話

実際、「関数と変数のPHPでできるじゃん?OOPとかいらないよ!」というのは、ある意味正しいんですよ、PHPでできることなんてタカがしれてますからね。
HTMLがちゃんと返せればいいだけですので、それには関数と変数で十分な事も多いんですよ。速いし*4

ただ、前述の通り、ライブラリをつかうときにはOOPをつかってたりする事もあるわけです。
で、そういう便利なライブラリってのは、大抵(入門者の自分よりは)スゴイ人が書いてるものじゃないですか?そうですよね?そう言う人がこぞってOOPで書いてる、そういう事実はありますよね?
つまりスゴイ人がつかっているのだから、スゴイんじゃないか?と素直に思うのも大事な事です。

私の実感としても、OOPってのは慣れてくるとすっごい便利なのは間違いないんですよ。難しく書くためにあるわけではなくて、実際に便利なんです。ただ、「○○が便利!」ってのは実際つかってみないと分かりづらい所です…。


一応、一つだけ具体的にどのように便利かここで書いておきます。
既に何回か述べていますが、「クラスはプログラム」という文脈でいえば、関数とか、変数をクラスの中だけに閉じ込めておけるわけです。普通、プログラムの外からは変数とかみえませんからね(そんなのできたら、セキュリティ的に最悪だ!*5)。

そうなると、いろんなところにそのクラスをもっていっても、既存のコードの関数や変数と衝突することがないので、色々な所でつかいまわすのにめっちゃ手軽!安全!便利!という所ですね。
(入門書とかでよくあるMyClassなんてクラス名は生涯一度位しかつかうべきではなく、Uzulla\Util\HelloWorldとかにすべきです。毎回絶対に世界で衝突しないユニークなクラス名を付ける必要があるのですが、やってみると割とどうにかなります)

これは、自分でライブラリを作り始めると、本当に意味があるんですよね。さらに、先日紹介したIDEとかつかいだした日には「うわぁ!スッゴイ!」ってなるんですよ、補完とかで、本当に。

まとめ

とにかくですね、OOPってのはなんてこたーないんですよ!

しかしながら、最初に「OOPがいかにすばらしく、何ができて世界が救われるか」という紹介が先行しすぎていて、自身がもっている知識とのつながりが完全にたたれてしまう事が多いので辛い(と思う!)!
…ということでこのエントリを書きました。

なんかもう雑な文章で、推敲したら10行くらいにできそうですが、言いたい事は書きました。クリスマスなので勘弁な!


さて、PHP入門はOOPまでおぼえれば、入門完了!と言えるとおもいます。

あとは好きなライブラリを探したり、PHP以外の言語でもよまれるようなデザインパターンとか(まあこれは賛否ありますが)をおぼえて、「PHP言語」の入門をこえた、プログラミングの勉強を進めていと言う事になります。もうこうなったら入門者とはいってられないですよね!


で、ですよ。ここまでくれば?…そうですね!このアドベントカレンダーのタイトルでもある、Webエンジニア養成読本を読む事もできますね!!ぱちぱちぱち!!やったぜ!是非ご購入ください!!

本当の最後に、しなければならない宣伝

さて、宣伝タイムです。帰らないで下さい。

まず再度の書籍の宣伝です、本アドベントカレンダータイトルの書籍です。

このエントリが役立った方には、その翌月か翌々月くらいには多分おやくだつのではないかな!と思います。

即座に買えとはいいませんが、いつかは買って欲しいです。まあ、本屋にいって他の書籍のついでに立ち読みしてみるのも良いでしょう、買って欲しいですが。

もし、この書籍の内容が理解できれば、おそらく仕事でもなんとかやっていけるレベルにいるのではないでしょうか。そのようなベンチマークとしても役立つと考えております。つまりは買っていただきたい!ということです。

本当の最後に、しなければならない宣伝2

来年の夏に開催されるYAPC::Asia Tokyo 2015についてです。

YAPC::Asia Tokyo 2015

YAPC::Asia Tokyoは世界最大級のエンジニアの手による草の根技術カンファレンスです。これまで9回開催され、様々な技術に関する発表そして技術者同士の出会いを生んできました。

「なんかエンジニアコミュニティってきいたことがあるけど…」「カンファレンスってどんなの?いったことない」という人でもきっと新しい発見があるイベントとなりますので是非ともチェックしてください。

f:id:uzulla:20141201013416p:plain

YAPCPerlのカンファレンスと思われがちですが(実際そうなのですが)、どんな言語の人でも、きっとPHPの人でも楽しめるイベントになっております。なにせ去年のベストトーク賞はPHPトークでした*6


来年は10年目かつ、今の運営における最後の開催となり、規模も、話題のバリエーションも間違いなくパワーアップしますので、是非来年のスケジュールにいれておいてはいかがでしょうか?

f:id:uzulla:20141201013436p:plain


…といっても、来年の話では忘れてしまうでしょう。冒頭にも記載しましたが、メール通知サービスが開始されました!是非ご登録下さい!

YAPC::Asia Tokyo 2015



やった!!ゴール!ゴールだ!!

最終日、多少のごたごたはございましたが、 無事、アドベントカレンダーゴールです!!

これでネタを必死に考えなくても済むようになります!年末はゆっくり眠りたいとおもいます!!

みなさんメリークリスマス!!そして良いお年を!!!エントリ書いた皆さんもお疲れ様でした!!皆さんのハッピーPHP(等)ライフを祈っております!


こちらからは!以上です!!!

*1:たとえば、「スタティックおじさんだ!」って笑われます

*2:オブジェクトの概念は、インスタンスとイコールで語られる事が多いと思いますが、結局クラスとも一部イコールで語られるので、初心者は戸惑う様です。

*3:ここでは説明しませんけど、スタティック変数をつかえばわざと衝突させる事もできますが

*4:変数と関数だけのPHPより、OOPをつかうほうがほんのわずかながら遅い、とはいえOOPしないとすぐにごちゃごちゃしたコードになるので、そっちのほうがよっぽどつらい(あなたはどうあれ、そういうことに世の中的にはなっています)

*5:register_globals?しらない子ですね…?

*6:というか私です