第1回 PHPでオブジェクト指向実践1 - OOP講座

PHPセキュリティ

がる先生のOOP講座

Lecutures on PHP

第1回 PHPでオブジェクト指向実践1 (その2)

 このエントリーをはてなブックマークに追加

1.まずは「まとめられるもの」をまとめてみよう

ある日。上司からこんなメッセージが届きました。「命令が下った」と言い換えても、たぶんきっと差し支えはありません。

<<メール>>
今は書いた人のハンドル名とタイトルと本文だけで、ちょっとわかりにくいところがある。とりあえず"話題にしているジャンル"を増やしたいので、一つ項目を増やしてくれ。

なるほどなるほど。ここだけでしたらまぁ、気持ちはわかります…が…書き込むところと表示の部分と、いくつか変更が入りそうで嫌な予感がしないでもないです…ってところで、そのメールの下の方に書いてある文章に目が止まりました。

<<メール>>
ほかにもいくつか項目が追加になると思うので、それはまた追って連絡する。

がる先生………えと?
なんですと???
「後で」「いくつか」追加する?
すみませんそれは「いつ」仕様が決まって「いつまでに」実装しなきゃいけないんでしょうか?
っつかとりあえずまず、実装した後に「やっぱり違うのがいいや」とか言い出さないんでしょうか?


結構おっかない話ではあるのですが。正直なところ、こういった話が現場で出てくることは、決して稀ではないのではないかと思うのですが如何でしょうか?
場合によっては「予告もない」なんてことも、ごく稀には。頻度が本当に「稀」なのかどうかは置いておきまして…。

出来るのであれば「もう少し話を整理してから」とか思うところは多々あるのですが…とはいえ、いずれどこかで修正をすることになるのは必須です。
であれば。
なにがしか「修正追加が楽な方法」を考えたほうが建設的だと思いますが如何でしょうか。

こういう時は、少し頭を切り換えてみます。
筆者は「レイヤー」とか「粒度」とかって単語が好きなのですが、それを「抽象度」という単語にしたりするのもよいかもしれません。
「書き出し」と「読み込み(表示)」の二箇所に変更が及ぶのですが、とりあえずまず「書き出し」の方を先に考えて、後で「読み込み(表示)」について考察する事にしましょう。

書き出しは、現在概ねこんな処理が書いてあります。

list 1

write.php より

  1    /* cgi requestから情報を受け取る */
  2    // 取得対象を決定する
  3    
$targets array('email''handle''title''body');
  4    
// formデータから情報を受け取る
  5    
$data array();
  6    foreach(
$targets as $target) {
  7      
// XXX エラー抑止演算子は後で再考察
  8      
$data[$target] = @$_POST[$target];
  9    }
 10  
 11    
/* ファイルに書き込む */
 12    // データを合成する
 13    
$wk array();
 14    
// エスケープ処理
 15    
foreach($data as $key => $val) {
 16      
// 文字列内のダブルクォートを二重にした上で、全体をダブルクォートで囲む:rfc4180
 17      
$wk[$key] = '"' str_replace('"''""'$val) . '"';
 18    }
 19    
// 文字列を,で連結する
 20    
$write_string implode(','$wk) . "\n";
 21    
 22    
// 書き込む
 23    
file_put_contents($bbs_data_filename$write_stringFILE_APPEND);

ただ。これをもうちょっと「レイヤーをあげて / 荒い粒度で / 抽象度を高く:つまりは"よりアバウトに"」捉えますと。


list 2

write.php より

  1    // formデータ(cgi requestデータ)から「掲示板の1メッセージの情報」を受け取る
  2  
  3    // 「1メッセージの情報」をファイルに書き込む

という風にまとまります。また。“1メッセージの情報”については「どこか一箇所で定義しておく」と、変更があってもなにやら「一箇所の変更である程度どうにかなるのではなかろうか」と思われるような感じになります。

そうして、こんな風に「ひとかたまりの情報」がある場合、それを「クラス」として定義すると、比較的よい塩梅になる事が多いです。


がる先生では、具体的に「class化」してみましょう。

まず、class化する時は、対象のclassに対する「設計」を行います。
いくつか設計には方法があるのですが。普段私が勧めているのは「使う側をまず考えてみる」事です。
お料理は食べる人が主役です。classは使ってくれる人が主役です。作り手よりもまずは使い手の事を考えてみると、結果的に案外と「作りやすい」ものになることが多いです。

では、その辺を考えて、list 2に少し肉付けをしてきましょう。日本語で書くのは「これから実装するよ」っていう目印になります。

list 3

write.php より

  1    //
  2    // formデータ(cgi requestデータ)から「掲示板の1メッセージの情報」を受け取る
  3    // -----------------------------
  4    // 「掲示板の1メッセージの情報」をhash配列にする
  5    
$data 掲示板の1メッセージの情報->make_to_hash();
  6  
  7    
// 「1メッセージの情報」をファイルに書き込む
  8    
書き込み情報をファイルに書き出す($data);

さらに、冷静に考えてみると、そも「$data」の変数って、こちら側で受け取る必要があるんでしょうか? って疑問にぶち当たります。
こんな風には書けないですかね?


list 4

write.php より

  1    //
  2    // formデータ(cgi requestデータ)から「掲示板の1メッセージの情報」を受け取る
  3    // -----------------------------
  4    // 「掲示板の1メッセージの情報」をクラスの中に入れる
  5    
掲示板の1メッセージの情報->set_from_cgiform();
  6  
  7    
// 「1メッセージの情報」をファイルに書き込む
  8    
掲示板の1メッセージの情報->write();

ちなみに、「情報をクラスの中に入れて書き出す」までを1つの関数(classだとメソッドと言います)にまとめてもよいのですが。
追って別の回で追加をしていきますが、一端は「個々の機能ごと」にある程度分割をしておいたほうが、後々楽が出来る事が多いです。
その辺のさじ加減は最終的には「経験によるもの」にはなってしまうので。色々と皆さんも試していただければと思います。



Pick Up Q&A

Q
PHPのHTML埋め込み記述について
 このエントリーをはてなブックマークに追加 
A
$_POST["data"] == "男" ? $val = "checked" : $val = "" ; の意味は以下と同じです。 if($_POST["data"] == "男"){ $val = "checked; } e...

>>続きを読む

kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)