ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

PHP等で画面とプログラムの分離&アジャイルっぽく開発(テストファースト、ユニットテスト)の例

2005-11-21 20:58:06 | PHP

 前のブログで、Webにおける画面とプログラムの分離方法の、問題がある方法についてかきましたけど、それで、具体的にはどうなるのか?という話と、これによって、アジャイルっぽくやると(テストファーストとかユニットテストとか)、どうなるかのお話です。

 なお、このあとに紹介予定のカオル姫方式でも、アジャイルっぽくできます。




 で、まず、具体例。

 ここでは、以下のサイトで、ボタンを押して、gamen1.php画面にいくとします。

<HTML>
<HEAD><TITLE>てすとだぴょん</TITLE></HEAD>
<BODY>
<Form action="gamen1.php "method="post">
    Name:  <input type="text" name="username"><br>
<input type="submit" name="submit" value="実行">
</form> 

(全角<>は、実際には半角です)

このファイルをtest.htmとします。

で、その場合、画面用PHPであるgamen1.phpと、同時に、gamen1_cnt.phpを作ります。

■■(1)gamen1.phpは、まずはじめに、こう書きます。
1.まず、HTMLファイルを作成します。
 HTMLエディタでもOK.デザイナーさんが作るのかなあ
 →で、ここで、プログラム的に文字が入るところに、$$$item1$$$とか、分かるマークを入れておいてもらうと、あとの作業が楽かもお。。

2.あたまに(HTMLタグの前でOK)、だまって、こうかきます。
<?php
	include("gamen1_cnt.php");
	gamen1_cnt_init();
?>

(全角<>は、実際には半角です)

3.ファイル名が、XXXX.HTMだったら、gamen1.phpになおしておきましょう。

ここまでで、gamen1.phpの内容は、こうなります
<?php
	include("gamen1_cnt.php");
	gamen1_cnt_init();
?>

<HTML>
<BODY>
表
<table border=1>
<tr><td>$$$list1['item1']$$$</td><td>$$$list1['item2']$$$</td></tr>
</table>
<Form action="gamen2.php "method="post">

    Name:  <input type="text" name="username" value=$$$name$$$><br>

<input type="submit" name="submit" value="実行">
</BODY>
</HTML>

(全角<>は、実際には半角です)
なお、$$$list1[item1]$$$とかいてあるのは、List1の中に、複数レコードが入っていて、そのレコードのitem1を表示しろという意味です。ここは、複数レコードのところなので、繰り返しになります。

■■(2)gamen1_cnt.phpは、まずはじめに、こう書きます。
1.関数gamen1_cnt_initを宣言し、中身空でかきます。
<?php
function gamen1_cnt_init()
{
}
?>

(全角<>は、実際には半角です)

■■(3)この時点で、test.htmでボタンを押しても、gamen1.phpのHTMLが表示されるだけで、なにもおこりません(ね、テストファーストっぽいでしょ ^^)

■■(4)ここで、文字がはいるところに、print文をいれます。
gamen1.phpで、処理結果の文字が入るところ($$$item1$$$とか、マークをいれておいてもらっているところ)に、print文で、セッションの値がはいるようにします。
1項目、1つの値が入るところは、
print $_SESSION['name']
のように(例の場合は項目名nameの値)表示されるように書きます。

1項目に、複数レコードのところ(繰り返し)のところは
foreach($_SESSION['list1'] as $rec)と、繰り返しの範囲のところを書いて、
レコードのある項目の値を入れるところは
print $rec['item1']
のように、書きます($recに1レコード分入っているから)
結果として、gamen1.phpは、こんなかんじです(これで画面側はOK)
<?php
	include("gamen1_cnt.php");
	gamen1_cnt_init();
?>

<HTML>
<BODY>
表
<table border=1>
<? foreach($_SESSION['list1'] as $rec){ ?>
<tr><td><? print $rec['item1'] ?></td><td><? print $rec['item2'] ?></td></tr>
<? }?>
</table>
<Form action="gamen2.php "method="post">

    Name:  <input type="text" name="username" value="<? print $_SESSION['name']?>"><br>

<input type="submit" name="submit" value="実行">
</BODY>
</HTML>

(全角<>は、実際には半角です)

■■(5)この時点で、表示できるかどうかみてみます。
 見ても、値ははいってこないはずです。まだかいてませんから。

■■(6)つぎに、ダミーの値をいれます。
gamen1_cnt.phpの関数gamen1_cnt_initで、セッションをスタートさせ、ダミーの値をいれておきます。これで、テストができるようにします。
 レコードの場合は、$rec[カラム名]=値のように、1レコード分セットして、そのレコードを
 $data[レコード番号]=$recというかんじで、レコードをセットし、最後に
 $_session[項目名]=$data
 の形で表全体をセットします。

こんなかんじです。
<?php

function gamen1_cnt_init()
{
	session_start();  	//	セッション開始

	$_SESSION['name'] = "aaa";

	$rec['item1'] = "1行目1項目目の値";
	$rec['item2'] = "1行目2項目目の値";
	$data[1] = $rec;

	$rec['item1'] = "2行目1項目目の値";
	$rec['item2'] = "2行目2項目目の値";
	$data[2] = $rec;

	$rec['item1'] = "3行目1項目目の値";
	$rec['item2'] = "3行目2項目目の値";
	$data[3] = $rec;

	$_SESSION['list1'] = $data;
}

?>

(全角<>は、実際には半角です)

■■(7)こうした状態で、test.htmからボタンをクリックすると、ダミーの値が表示されるはずです。

■■(8)あとは、コントロールの中gamen1_cnt_initの中を書けばいいことになります。




 逆に、gamen1_cnt_initの中だけ出来ている場合などは、セッションの値をprintすることにより、gamen1_cnt_initの中が、正しく出来ているかどうか、確認できます。

 なお、今回は、gamen1_cnt_initに渡す値がありませんでしたが、

■■ ※ test1.htm(呼び出し画面)からの値を渡したい場合
gamen1.phpの冒頭、gamen1_cnt_initを呼ぶ前に、session_startさせて、
foreach(@_POST as $key=>$val)
{
$_SESSION[$key]=$val;
}
(で、あってるかな?確認してないけど)みたいなかんじで、セッションに、画面の値を入れてしまってください。gamen1_cnt_initでは、そこから、値をとってきて、処理します。
 なので、test1.htmとgamen1_cnt_initで、同じセッションに値をいれて、重なってしまってまずい場合は、テキトーに命名規約をつくって、重ならないようにしてください。


 ということで、画面ができてなくても、こんなかんじで、ユニットテストできます

■■ ※画面をつかわずにユニットテストするには
gamen1_cntをインクルード
セッションをスタート
セッションに、呼び出し元でセットされるはずの値をセットする
gamen1_cnt_initを呼び出し
セッションの中身を全部表示

というPHPプログラムを作成する




っていうかんじで、画面とプログラム部分(コントロールとモデル部分)を分けて、画面だけを、ダミーの値を入れてテストしたり、プログラム部分だけを画面なしでテストしたりすることが可能になります。で、テストファーストっぽく徐々に、初めは何も怒らないところから作るので、
ね、アジャイルっぽいでしょ。

 今回はPHPでやりましたけど、CGIでも、JSPでも、まったく同じ方式でできるはずだと思います。

 でも、これだと、画面を複数切り替えられないので、つーか、もっと簡単に分離する方式を、気が向いたら、しめします(それがカオル姫方式。なぜカオル姫なのか(CMから取っている)は、その中で示される)


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Webにおける画面とプログラムの分離を単純に行い、わざと問題点をだしてみる。

2005-11-21 17:45:57 | PHP

 先ほどのブログにあった、Webプログラム(PHPなど)における画面とプログラムの分離を、規約によって行う方法について、ものすごーい単純な規約を使って、わざと問題点をだしてみます。

 この程度なら、たぶんテンプレートを使ったほうがよいと思われるでしょう。

 実際は、このやり方とは、違うやり方をします(それは、次回以降のブログで説明する)。

 ただし、このやり方を説明しておかないと
・あまりに唐突なやり方になってしまう。
・今回説明する方法でいいのでは?という意見が出る
ために、前もって説明しておいてしまいます。




 単純に、PHPとか(まあ、CGIでもJSPでもいいんだけど)で、画面と、プログラム部分を分離しようとすると、つまり、MVCモデルを実現しようとすると、こんなことでできます。

(1)画面部分は、
・コントロール部分のソースをインクルードする
・そこで、コントロールのモジュールを呼び出す
・(画面表示の値は、コントロール側でどこかにセットしておき)
  画面表示では、表示するだけにする。

(2)コントロール側では
・呼び出されるモジュールをつくり、そこで、モデルを呼び出す
・表示する値が求まったら、画面表示の値をどこかにセットする。




 今回は、画面表示の値を入れておくところを、セッションとしましょう
(セッション以外でもぜんぜんかまわないんだけど、次回以降の話のために、セッションに入れる)

そうすると、規約としては、

(1)画面表示側
・プログラム名はXXXX.PHP
・はじめに、コントロールのインクルードをして、次の行で、XXXX_cnt_init()を呼び出す。
・値を表示するためのプログラムしか、書いては、いかん。
 クリックされたら、ある処理を動かしたい場合、動かす処理を、XXXX_shoriYY(ひきすう)YYは数字という関数を呼び出すようにして、その関数は、コントロールファイルの中に書くようにする。

 値表示は、
  文字、数字のように、1項目に1つの値のときは、print $_SESSION['項目名']で
  表のように、1項目につき、複数行あり、その行が、複数のカラムを持つ場合は、
  foreach($_SESSION['項目名'] as $rec)で、1行分を$recの中にいれ
   各行につき、 print $rec['カラム名']で表示する
  リストのように、1項目につき、複数の値あるときは、表で、複数行、1カラムしかないものとして処理する。

(2)コントロール側は、
・プログラム名はXXXX_cnt.PHP
・XXXX_cnt_init()という関数を作成し、その関数の中で、セッションをスタートし、セッションの中に、表示させたい値を入れる。値の設定の仕方は、上記のとおり。
・もし、それ以外に、画面のほうで、関数を呼び出したいときには、ここにその関数を書く




ひえー、時間がなくなっちゃったんで、具体的例は、またこんど。

で、これの問題点。

いろいろあるけど、時間ないので、致命的なのを1個だけ。
エラー画面を表示したいときなどに別画面に遷移させにくい(させると、プログラム複雑になる)

この問題を解決した方法を、今度、書こうと思っています。

なずけて、カオル姫方式。

時間がないので、このへんで。



  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Webシステムのほうが、画面部分と、プログラム部分を分けたいはず。人件費の理由で。

2005-11-21 15:14:37 | PHP

 Javaだと、MVCとかで、画面のView部分と、プログラミング部分の(主に)Model部分を分けるという考えが浸透していると思う。
 PHPでも、HTMLテンプレートとか、Smartyとか、PEARのテンプレート機能を使うとかで、画面とプログラム部分を分離できるみたいですよね(こんなことしなくても、ちょっとしたコーディング規約を使うだけで、もっと柔軟に、分けることができると思う。それについて、今実験中)。

 で、ここで、いいたいのは、何で、画面とプログラム部分を分けるかという話。

 そうすると、MVCモデルがなんとかかんとか。。。っていう話になっちゃうけど、もっと、重大な話がある。

 デザイナーの単価と、プログラマーの単価が違うのだ。

 今日は、その話。

 で、その観点から考えると、できるだけ、簡単に画面と分離したい(つまり、デザイナーさんが、ちょっとしたマーカーをいれて、自動的とまではいかなくても、テンプレートにできるようなかんじ)けど、それについて、PHPだと、こういう規約を決めればいいじゃん!っていうのは、今、実験中なので、今度、実験がすんで、気が向いたら披露します。

 実は、「PHPだと」と書いたのは、はじめ、ウィリアムのいたずらは、この規約をJSP用に考えていた。しかし、JSPだけでなく、PHPでも、なんでも基本方針的には、応用できるじゃん!(そーいう点で、PHPを利用する立場とはちがう。この考え方さえ守れば、新しい言語がでてきても、応用できるという点で)つーものなんですけどね。でも、今日はその話じゃなくって、その前提の、なんで、こんな話をするのかということ。




 Web系において、デザイン部分と、プログラム部分を分けたいって言うのは、結構現実的な大きな理由として、デザイナーの単価と、プログラマーの単価の違いっていうのがあるんじゃないかな?って思うんですよ。

 デザイナーの単価は、「はっきり言って安い!」。

 1画面1万円くらいでも、やってくれるんじゃないかにゃー。
 (もっと、安いかな・・)

 そのうえ、この分野には、新規参入者が多い。
 ちょっとデザインのお勉強をして、起業しちゃう人なんかもいる。

 そのため、単価がどんどん安くなっている。




 一方、プログラマは、いくら、フリーには安い人がいるといっても、1日稼動して、数万円っていうのは、当たり前の世界なのよ。

 さらにだ、ちょっと大きくなると、マネージャーなんつーのも出てくる。
 マネージャーは、プログラムもホームページも作らないけど、しっかりお金を取っていくわけだ。

 で、じゃあ、実際にどれくらいになるか。。。というと、マネージャーが動くと、マネージャーは、たいてい正社員なので、年収400万円以上になっちゃうのよ。そーすると、月40万でしょ。
会社は上乗せするから(会社分の社会保険もはらうし、その他もろもろお金かかるし)結局月60万くらい。

 ところが、ECサイトなんかだと、中小企業の場合、2ヶ月で、100万くらいで作りたい!っていう場合もあるのよ。マネージャーさんにお金をだして、おわっちゃう(>_<!)

 マネージャーが2つも3つも掛け持ちすればいいじゃん!と考えるかもしれないけど、デザイン事務所のマネージャーならともかく、開発会社で、3つの案件を同時に掛け持つって、大変なのよ。
 マネージャーって、会議に出て、結構時間つぶれちゃうんで。

 なので、掛け持ちできる仕事が少なかったりする。

 プログラマーなら、もっと安いけど、デザイナーほどではない。

 とにかく、中小企業の感覚、100万でECサイト作って!とか言う場合、デザイナーにお金を払って、あと、データ入力をパンチャーにしてもらって、その他いろいろはらうと、この時点で、もう、お金たりないのよ。なので、プログラマーを動かしたくないわけ。

 それ以外のものでも、中小企業なんかが絡んできたり、小規模イベントの場合、プログラマーを動かすお金まで回らない。ましてやマネジャーつけて、大規模に開発することはできない。
(マネージャーつけるレベルになると、400万程度以上の案件になる。ソフトハウスが「部隊を動かして」請ける案件は、一般的にそれ以上のことが多い。それ以下のものは、プログラマだけでやったり、フリーにまわしたり、さらに零細ソフトハウスに紹介したり。。)




 ところが、デザイナーは安いのよ(それが社会的にいいことか悪いことかは別問題)。
 「アルバイトの」求人雑誌のなんかで、Webデザイナーの値段をみてね!

 なので、デザイン部分と、プログラム部分を分離し、プログラム部分をデザイナーがちょっと変形すればできる程度にしたい。。。と、いう感じだと思う。

 つまり、単価の立場から見て、デザイン部分(画面 Viewの部分)と、プログラム部分(モデル部分)を分けたいわけ。で、デザイン部分は、あるていど複雑/修正あってもかまわない(人件費安いから)けど、プログラム部分は、あんまり複雑にしないで、できれば、デザイナーさんがちょこちょこっといじって、プログラマ使わなくても終わり!にしたいわけ。

 つーので、フォームメールがウケたりするわけだ。あれなら、フォームメールCGI(共用サーバーでだいたい提供してくれる)を呼び出すだけだからねえ。。デザイナーでも対処可能。



  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする