PHPについて適当に

RedLine Magazine : PHP

デザイナの@red_hippyさんがPHPを勉強しているとのことなので適当に。ちなみに僕はあまりPHPを書けないのでバリバリPHPを書いてる人からみたらおかしいところがあるかもしれないけど、なるべくそういうのないよう頑張ります。

そもそもオブジェクト指向でやる必要はあるのか

これは個人的な意見だけど、本職のプログラマでもない限り無理にオブジェクト指向でやる必要はないと思ってる。特に学びはじめのデザイナさんならそこまで複雑なものを作らないだろうし。@red_hippyさんがどの程度のものを作ってるかわからないから一概には言えないけど、掲示板やお問い合わせフォームレベルのものだったらオブジェクト指向である必要はない。

プログラマの人が「PHP5ならオブジェクト指向っすよ!」とか言っても信じちゃいけません! 本当にオブジェクト指向が必要だと思って言ってるのか少し疑問。初心者の人妻にHaskellやらSICPやらすすめる人もいるし、困ったもんだ。

とりあえず、最初は愚直に処理の順番通りに書いていって、「なんかこのコード何回も書いてるなー」ってのが出てきたらそこを関数にするとかで十分。

とは言うものの、@red_hippyさん自身が楽しんでればそれでいいと思うし、Twitterを見る限り楽しんでそうなのでオブジェクト指向の話もちゃんとします。

追記: これを書いてる途中に@red_hippyさんから、「プログラマさんが勉強するようなことをちゃんとやりたい。」と言われたので上の話はなかったことに。

オブジェクトってなんぞ

では、オブジェクトって何でしょう。

データとそのデータを操作する手続きをまとめたものを「オブジェクト」と呼び、オブジェクトの定義(雛形)を「クラス」と呼びます。PHPでは、オブジェクトは変数(データ)と関数(手続き)をまとめたものです。

@red_hippyさんのブログでも書かれてるけれど、説明的にはこれでOK。これだけでわかる人もそういないと思うけど。 この説明だけだとわかりづらいので「ブログの記事」を例に説明してみる。

まず、「ブログの記事」が持つデータについて考えてみよう。とりあえず思いつくのを適当にあげると「タイトル」「本文」「投稿日」「投稿者」などが考えられる。そしてそのデータを操作する手続きについてはそのデータの保存と取得が考えられる。いわゆるsetter/getter。アクセサとも言う。これを実際のコードに置き換えてみよう。

データがprivateな変数としてあって、それの操作としてsetTitleやgetTitleがあるのがわかる。簡単な例ではあるけど、オブジェクトがデータとそれの手続きをまとめたものというのはこういうこと。ちなみにこの変数のことをメンバ変数の他にインスタンス変数、フィールドとか言ったりする。これは言語によって違うかも。Rubyだと大抵インスタンス変数と言う。

ちなみにマジックメソッドを使ってもいいと思うけど、これはprivateな変数に対してアクセサを作ってしまうので注意が必要。下手すると隠蔽の意味がなくなる。個人的には必要なものだけをアクセスできるようにしたいので、マジックメソッドは使わない。

getter/setterの意味

で、なぜ一々getter/setterを作るのか。一言で言うと、直接データにアクセスされると困る場合が多いから。

まず、困る例を。以下のコードはSquare(正方形)というクラスにもかかわらず、直接データをいじれてしまう為、縦と横で一致しないデータを入れることが出来てしまう。

これを防ぐにはsetterでうまく処理をする必要がある。

heightもしくはwidthに値を保存したら、もう片方にも値をいれることで同じ値になるようにした。メンバ変数をprivateにすることで、この関数を通してでしか値を保存することが出来ない為、縦と横でデータが一致しないということはなくなる。しかし、これはこれで縦を指定しているにもかかわらず、横もかわってるという気持ち悪さが残る。これをもう少し改良して、値の保存はgetLengthという名前にする。これなら関数の名前から縦・横が変わっていても違和感ないだろう。

これと似たような話で、例えばあるデータには数値だけ、文字列だけ入れたいというチェックもsetterでやることができる。

基本的にクラスの中の変数や関数は本当に必要なもの以外privateでいい。別に1つのメンバ変数に対して必ずsetter/getterがいるというわけじゃない。むしろそういうのはよろしくないので、いくつかのメンバ変数をまとめて処理して1つの関数で出力するというのも全然あり。

例えば、prefecture(都道府県)、city(市区町村)、street(通り)というメンバ変数があったら、それぞれpublicにするより、getAddressという関数を作ってその中でそれらを連結して返すという方がいい場合もある。この方が例えば仕様変更でcityがなくなった時に修正する部分が少なくて済むという利点もある。このあたりは抽象化とかデータ構造の分離とかそういう話になるんだけど、ちょっと難しくなりそうなのでこの辺でやめとく。

ちなみにPHPでsetter/getterをちゃんとやってるコードをあまりみない(全部public)なのは、元々オブジェクト指向の言語ではなかったし、そこらへんあまり考えない・知らない人が多いからだと思う。

MVCについて

MVCについてだけど、個人的にはとりあえずフレームワークを使ってしまった方がイメージがつくので理解しやすくなるかと。最初のうちはフレームワーク使わない方がいいって人もいるけど、個人的にはフレームワークを使って疑問に思ったところ、気になったところを調べる方が理解が早い気と思う。

どのフレームワークがオススメとかは正直わからないんだけれど、日本語のドキュメントが多くて有名なのを使っておくのが無難かと。

まとめ

オブジェクト指向は難しいと思います。未だに僕も勉強中だし、ちゃんと理解してないプログラマも多いし。 多分、理解するには人のコードを読んで、自分でコードを書いて、それを誰かにレビューしてもらうというのが早いと思うんだけど、とりあえず1つ1つ理解していくしかないと思うのでじっくり頑張ってください。