はじめに
プログラマのバイブル「コード・コンプリート」で紹介されている「テーブル駆動方式」。
古典的なテクニックながら、コードをシンプルに保つことができる強力な手法…。
ですが、PHP の世界ではあまり紹介されている記事を見かけません。
ましてPHP を使ったサンプル記事となると、意外にこれが(大げさにいえば)、国内初なのでは?
ざっと Google 先生に聞いてみて、結果の少なさにそう感じた次第です(2016年10月現在)。
まず、テストやデバッグと同様、初心者向けの書籍で紹介されることは、ほとんどないのではないでしょうか。
しかし、最初に間違った道に進まないよう、初心者にこそ教えてもらいたいというのは私だけではないと思います。
※古典的かつ強力な手法ですので、Java や C の世界では普通に使われていそうですが。
PHP初心者の方にこそ、この方式で、整理された読みやすいロジックを書いて快適なコーディング生活を送ってもらいたいと思います。
テーブル駆動方式を使わない制御構文の場合
※ ここではエラーチェックは無視して、ロジックが理解しやすく書いています。
やたらと if がつらなる、何を意味しているのか分かりにくいコードです。
初心者の頃、こういうコードを書いて怒られたものです。
「コード・コンプリート」を読むまでは、switch 文で書いたりしていました。
分かりやすくなるのですが、switch は遅くなるという欠点があります。
function getProductName($category, $price){
if($category === "meat"){
if($price === 10000){
return 'gyuu';
}elseif($price === 500){
return 'buta';
}
}
if($category === "fish"){
if($price === 2000){
return 'maguro';
}
if($price === 100){
return 'aji';
}
}
}
echo getProductName("fish", 100); // aji が出力
メンテもしにくそうです‥。
カテゴリが「fish」で、価格が「100」のものは、「aji」が出力、というパターンが出ています。
もうひとつカテゴリがあり、「meat」の場合で、それぞれ2つずつ金額の異なるパターンがあります。
これだけのパターンならまだいいですが、カテゴリが10個と増えたら?
※データベースを使うまでもないパターンです。
テーブル駆動方式を使う場合
function getProductNameFromTable($table, $category, $price){
$count = count($table);
for($i=0; $i<$count; $i++){
if( ($table[$i][1] === $category ) and ($table[$i][2]=== $price) ){
return $table[$i][3];
}
}
}
これだけです。
と、関数をたたく前に、以下の配列、テーブル的な構造を作っておきます。
ここが、この記事のキモとなる、テーブルです。
// 「テーブル型」データ
$table[] = [1,'meat',10000,'gyuu'];
$table[] = [2,'meat',500, 'buta'];
$table[] = [3,'fish',2000, 'maguro'];
$table[] = [4,'fish',100, 'aji'];
echo getProductNameFromTable($table, "fish", 100); //aji
echo getProductNameFromTable($table, "meat", 10000); //gyuu
何を意図しているデータなのか、一目瞭然で、これならメンテもしやすいですね。
パターンがいくら増えても、プログラムは変更する必要がないというメリットがあります。
単純にデータの「テーブル」を作って、
2列目のカテゴリ、3列目の数値が、それぞれ引数と一致するものを出力しています。
こんな表を作って、PHPに2列目、3列目を検索させているわけです。
複雑なロジックを書くことなく、さまざまなパターンを書けそうです。
ものすごく遅い、配列のキーを検索する組み込み関数を使う必要もありません。
また、この方法ならデータベースからの戻り値を何度も取りなおすのではなく、
取得するのは最初の1回だけで、検索やページングを
PHP に任せてしまうこともできそうです。
同様なことは、もちろん JavaScript でもできるので、
JSONデータの取扱にも役立ちそうです。
以上です。