ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

PerlコミュのPerlプログラマの技量を測る

  • mixiチェック
  • このエントリーをはてなブックマークに追加
ハイこんにちは。 決められた時間にプログラムを実行するトピックで大変お世話になっております。イヤダです。

件のプログラムもそこそこにこんなトピックを立ててスイマセン。

http://blog.bmedianode.com/2005/04/zend_certificat.html

このような投稿を見かけ、こういうのやってみるの面白いなと思いました。

リンク先に飛んでいくのが面倒な方向けコピペ
−−−−−−−−−−−−−−−−−−−−−−−−−−
ちなみに私がPHPプログラマの技量を知りたい時には、ファイル数・構成は無制限で以下のような仕様のスクリプトを書いてもらいます。

・入力ページ、確認ページ、結果表示ページから成る
・入力ページでは郵便番号(7桁)の入力欄と送信ボタンを表示
・入力ページで送信ボタンを押した際、郵便番号欄の値を半角に変換してハイフンを除去
・郵便番号欄の値が「空文字列」または「7文字の半角数字以外」の場合は「郵便番号欄の値を保持」したまま入力ページを再表示
・入力ページを再表示する再、郵便番号欄の下に入力値に応じて「入力されていません」または「入力内容が正しくありません」と表示
・確認ページでは郵便番号、戻るボタン、次へボタンを表示
・確認ページで戻るボタンが押された場合は「郵便番号欄の値を保持したまま」入力ページを再表示
・確認ページで次へボタンが押された場合は結果表示ページに「入力された郵便番号はXXX-XXXXです」と表示
・ページデザインは後で差し替えるのでスクリプトとは別ファイルにしておく
・セッションは使わない

一見シンプルな仕様ですが、OOPが身に付いていない人を弾く程度には機能します。実際のところPHPプログラマとして報酬をもらうのであれば、この程度のスクリプトが設計・実装を合わせて一時間以内には書けないとマズいでしょうね(フレームワーク使えば20分くらい?)。
−−−−−−−−−−−−−−−−−−−−−−−−−

これはPHPでのお話ですが、入社試験とかにこういうのが出たらなかなか面白いですね。
OOP(オブジェクト指向)うんぬんのくだりは私のようなヘタレサンデープログラマの僕にはなんだかわかりませんが。。。

ということで、上手な方も下手な方もこの課題にチャレンジしてみませんか?
上手な方は是非寸評など頂けると、世の中のperlプログラマのレベル向上に役立つのではないかと思ったりします。

自動車の速度調節から飛行機の管制システム、医療機器全般、とにかく世の中プログラム、人の命を支えるプログラム、プログラマが賢くなれば世の中は素敵になるんじゃねえかな。しらねえけど。

そんな感じです。

コメント(12)

ヘタレ日曜スクリプタなのでまったく参考にならないと思いますが、イヤダさんが挙げられてるエントリが出た直後に、Perl で実装してみてたりします。

http://antipop.gs/mt/archives/001277.php

まぁ、問題の趣旨からするとおおげさというか、無駄な実装になってるなぁとは思いますが、お遊びということで。
ということで、早速人柱になってみます。

条件の
・ページデザインは後で差し替えるのでスクリプトとは別ファイルにしておく
についてはよくわからなかったのでガッツリ無視しました。

そして「郵便番号欄の値を半角に変換して」の部分をどうやってjcodeなしで実現するかで悩んで、結局50分くらいかかりました。
時間内に収めるためにjcode使えばいいじゃんよと妥協。
そこで悩まなければ30分くらいでできました。

−−−−−−−−−−−−−−−−−−−−−−−−−−−
#!C:/Perl/bin/perl

#┌──────────────────────────
#│ 技量を測ってみる
#└──────────────────────────

require './lib/cgi-lib.pl';
require './lib/jcode.pl';

&ReadParse(*in);

$css = "./css/main.css"; #cssファイルパス
$html_title = "実力を測る"; #HTMLタイトル
$my_file_name = "zip.cgi"; #このCGIの名前

#main:処理の振り分け

if($in{"action"} eq "check"){
&zip_check;
if($error eq ""){✓}
else{&input;}
}
elsif($in{"action"} eq "regist"){®ist;}
else{&input;}
exit;

#input:入力画面表示
sub input{
&html_head;
print<<HTML;
<FORM ACTION="$my_file_name" METHOD="POST">
<INPUT TYPE="text"NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$in{"zip"}">
<INPUT TYPE="hidden" NAME="action" VALUE="check">
<INPUT TYPE="SUBMIT" VALUE="送信">
</FORM>
$error
HTML
&html_foot;
}

#check:確認画面表示
sub check{
&html_head;
print<<HTML;
入力された内容は以下でよいですか?<BR>
$zip
<FORM ACTION="$my_file_name" METHOD="POST">
<INPUT TYPE="hidden" NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$zip">
<INPUT TYPE="hidden" NAME="action" VALUE="regist">
<INPUT TYPE="SUBMIT" VALUE="次へ">
</FORM>
<FORM ACTION="$my_file_name" METHOD="POST">
<INPUT TYPE="hidden" NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$in{"zip"}">
<INPUT TYPE="hidden" NAME="action" VALUE="">
<INPUT TYPE="SUBMIT" VALUE="戻る">
</FORM>
HTML
&html_foot;
}

#regist:結果表示
sub regist{
$zip = $in{"zip"};
$zip_1 = substr($zip, 0,3); #前半3桁を取り出す
$zip_2 = substr($zip, 3,4); #後半4桁を取り出す

&html_head;
print<<HTML;
入力された郵便番号は$zip_1\-$zip_2です<BR>
<A HREF="$my_file_name">戻る</A>
HTML
&html_foot;
}

#zip_check:チェック処理
sub zip_check{
$zip = $in{"zip"};
&jcode::tr(\$zip, '0-9A-Za-z−', '0-9A-Za-z-'); #全角を半角に変換
$zip =~ s/-//g; #ハイフン削除
$count = length $zip; #桁数を取得

if($zip eq ""){$error = "なにも入力されてないですよ";}
if($zip =~ /[^0-9]/){$error = "入力された郵便番号が変ですよ";}
elsif($count != 7){$error = "入力された郵便番号が7桁じゃないですよ";}
}

#--------------HTMLヘッダ--------------------
sub html_head{
省略
}
#--------------HTMLフッタ--------------------
sub html_foot{
省略
}
exit;
・ページデザインは後で差し替えるのでスクリプトとは別ファイルにしておく
というのはプログラムとデザインの分離を狙ってるんでしょうね。
PHPでいうとSmartyなどを使うということでしょうか。

Perlでやる場合には例えば<form action ...>や<input ...>と入れ替える
予約語のようなものを用意しておいて、HTMLを書く人は実際のタグの
代わりにそれを書いておいてもらい、プログラム中では予約語とそれを
入れ替えるという風になりますね。
というわけで、イヤダさんのをテンプレート対応に書き直してみました。
quick hackなので変かも知れませんが(--;
ちなみに、デザイナーは入力ページではFORMを開始すべき所に
<FACTION>、入力値を入れる所に<INPUTZIP>、登録釦の所に<SUBMIT>、
FORMを閉じるところで</FACTION>と書く必要があります。
他のページも同様に幾つかプログラム内で置き換えられる
予約語が指定されてます。

−−−−−−−−−−−−−−−−−−−−−−−−−−−
#!C:/Perl/bin/perl

#┌──────────────────────────
#│ 技量を測ってみる
#└──────────────────────────

require './lib/cgi-lib.pl';
require './lib/jcode.pl';

&ReadParse(*in);

$input_template = "input.template"; #入力ページテンプレート
$check_template = "check.template"; #確認ページテンプレート
$regist_template = "regist.template"; #結果ページテンプレート
$my_file_name = "zip.cgi"; #このCGIの名前

#main:処理の振り分け

if($in{"action"} eq "check"){
&zip_check;
if($error eq ""){✓}
else{&input;}
}
elsif($in{"action"} eq "regist"){®ist;}
else{&input;}
exit;

#input:入力画面表示
sub input{
&html_head;
open (FILE, "$input_template");
while(<FILE>) {
$_ =~ s/<FACTION>/<FORM ACTION="$my_file_name" METHOD="POST">\
<INPUT TYPE="hidden" NAME="action" VALUE="check">/g;
$_ =~ s/<INPUTZIP>/<INPUT TYPE="text"NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$in{"zip"}">/g;
$_ =~ s/<SUBMIT>/<INPUT TYPE="SUBMIT" VALUE="送信">/g;
$_ =~ s/</FACTION>/</FORM>$error/g;
print $_;
}
close(FILE);
}

#check:確認画面表示
sub check{
&html_head;
open (FILE, "$check_template");
while (<FILE>) {
$_ =~ s/<ZIP>/$zip/g;
$_ =~ s/<FNEXTACTION>/<FORM ACTION="$my_file_name" METHOD="POST">\
<INPUT TYPE="hidden" NAME="action" VALUE="regist">\
<INPUT TYPE="hidden" NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$zip">/g;
$_ =~ s/<NEXTSUBMIT>/<INPUT TYPE="SUBMIT" VALUE="次へ">/g;
$_ =~ s/</FNEXTACTION>/</FORM>/g;
$_ =~ s/<FBACKACTION>/<FORM ACTION="$my_file_name" METHOD="POST">\
<INPUT TYPE="hidden" NAME="zip" SIZE="10" MAXLENGTH="8" VALUE="$in{"zip"}">\
<INPUT TYPE="hidden" NAME="action" VALUE="">/g;
$_ =~ s/<BACKSUBMIT>/<INPUT TYPE="SUBMIT" VALUE="戻る">/g;
$_ =~ s/</FBACKACTION>/</FORM>/g;
print $_;
}
close (FILE);
}

#regist:結果表示
sub regist{
$zip = $in{"zip"};
$zip_1 = substr($zip, 0,3); #前半3桁を取り出す
$zip_2 = substr($zip, 3,4); #後半4桁を取り出す

open (FILE, "$regist_template");
while (<FILE>) {
$_ =~ s/<ZIPCODE>/$zip_1\-$zip_2/g;
print $_;
}
close (FILE);
}

#zip_check:チェック処理
sub zip_check{
$zip = $in{"zip"};
&jcode::tr(\$zip, '0-9A-Za-z−', '0-9A-Za-z-'); #全角を半角に変換
$zip =~ s/-//g; #ハイフン削除
$count = length $zip; #桁数を取得

if($zip eq ""){$error = "なにも入力されてないですよ";}
if($zip =~ /[^0-9]/){$error = "入力された郵便番号が変ですよ";}
elsif($count != 7){$error = "入力された郵便番号が7桁じゃないですよ";}
}

exit;
というか、単純に HTML::Template とかを使えってことで。 > 分離

Jcode.pm とかは、素直に使ってもいいんじゃないでしょうか。モジュールなしで Perl のコードを書くなんて、現実的に考えたらあり得ないですし、いかに有用なモジュールを組み合わせて素早く目的の物が作れるか、というのは言語関係なしに技量として評価できます。

Perl 的には、速度やメモリ消費量が想定になかったら却下かなぁ。
use strict; は言うまでもなく、という方向で。
私の場合はこんな感じでしょうか。ページデザインを分離するってのは勝手に解釈して、!this!、!zip!、!message!を予約後として置換するように実装してみました。

#!/usr/local/bin/perl
#Perl技能試験?

use strict;
use vars qw(%Var %CF);

#環境設定
$CF{this}="exam.cgi";
$CF{input}="input.html";
$CF{confirm}="confirm.html";
$CF{result}="result.html";

&decode;

if($Var{action} eq "confirm") { &confirm; }
elsif($Var{action} eq "res") { &result; }
else { &input; }

#input form
sub input {
open(IN, $CF{input});
my@form=<IN>;
close(IN);

my$message = $Var{action} ne "confirm" ? "" :
$Var{zip} eq "" ? "入力されていません<br>" : "入力内容が正しくありません。<br>";
print "Content-type: text/html\n\n";
foreach my$str (@form) {
$str=~s/\!this\!/$CF{this}/go;
$str=~s/\!message\!/$message/go;
$str=~s/\!zip\!/$Var{zip}/go;
print $str;
}

exit;
}

sub confirm {
my$zip=$Var{zip};
$zip=~s/-|−//;
$zip=~s/0/0/go;
$zip=~s/1/1/go;
$zip=~s/2/2/go;
$zip=~s/3/3/go;
$zip=~s/4/4/go;
$zip=~s/5/5/go;
$zip=~s/6/6/go;
$zip=~s/7/7/go;
$zip=~s/8/8/go;
$zip=~s/9/9/go;

my@form;
if($zip=~/^[0-9]{7}$/) {
open(IN, $CF{confirm});
@form=<IN>;
close(IN);
} else {
&input;
}

$zip=substr($zip, 0, 3)."-".substr($zip, 3);
print "Content-type: text/html\n\n";
foreach my$str (@form) {
$str=~s/\!this\!/$CF{this}/go;
$str=~s/\!zip\!/$zip/go;
print $str;
}

exit;
}

sub result {
open(IN, $CF{result});
my@html=<IN>;
my$zip=substr($Var{zip}, 0, 3)."-".substr($Var{zip}, 3);
print "Content-type: text/html\n\n";
foreach my$str (@html) {
$str=~s/\!zip\!/$zip/go;
print $str;
}

exit;
}

# decode
sub decode{
my $Bin;
if($ENV{'REQUEST_METHOD'} =~ /POST/i) {
read(STDIN, $Bin, $ENV{'CONTENT_LENGTH'});
} else {
$Bin = $ENV{'QUERY_STRING'};
}
for (split(/&/, $Bin)){
(my $_name,my $_value) = split(/=/);
$_value =~ tr/+/ /;
$_value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("H2", $1)/ego;
$Var{$_name} = $_value;
}
return;
}
http://antipop.gs/mt/archives/001277.php
この方が、元エントリ発表直後にPerlでの実装例をあげてますよ

と書こうと思ったらご本人が>>1番にレスされてますね。
まだ未見の方は是非読んでおくべきだと思います。未経験からPerlで業務経験二年半くらいの自分には非常にためになりました。
>>1のより巧みなる者さんのサンプルはとても興味深く見せていただきました。HTML::Templateなんて思いつきもしませんでした(苦笑) しかし、

> ・入力ページで送信ボタンを押した際、郵便番号欄の値を半角に変換してハイフンを除去
を半分満たせていないような気が…(^^;;
あー、思い違いしてたみたいです。

>入力ページで送信ボタンを押した際、郵便番号欄の値を半角に変換してハイフンを除去

これって、「123−4567」を「123-4567」に、つまり、「ー」も「-」にしなきゃならないってことなんですかね。数字のことしか考えてなかったです。そういうことであれば、不十分ですね。。。
>>1さんのプログラムはノーコメントだったからプログラムの字面を
追って行くのに苦労しました。クラス図はこんな感じですかね。
それにしても、PerlでここまでOOできるのかと感心してしまいました。
CGI::Applicationを使って書いてみました。

>・入力ページで送信ボタンを押した際、郵便番号欄の値を半角に変換してハイフンを除去
は実現してません。

かなり急いで作り、20分で一段落したが、
細かいところ修正してたら10分位経ち、
さらに直したいところあるけど、終了。


中途半端なところもありますが、頑張りました。

# webapp.cgi ##########################################
#!/usr/bin/perl

use strict;
use webapp;

my $webapp = webapp->new();
$webapp->run;

# webapp.pm ##########################################
package webapp;

use base "CGI::Application";
use strict;
use HTML::Template;

sub setup{
my $self = shift;
$self->start_mode('form');
$self->run_modes([qw(form confirm result)]);
$self->header_props(-type=>"text/html;charset=EUC-JP");
}

sub form{
my $self = shift;
my $errs = shift;
my $q = $self->query;

my $t = $self->load_tmpl("form.html",associate => $q);
$t->param($_ => 1) foreach @$errs;
return $t->output;
}

sub confirm{
my $self = shift;
my $q = $self->query;

if($q->param('zip') eq ''){
return $self->form(["no_input"]);
}elsif($q->param('zip') !~ /^\d{7}$/){
return $self->form(["bad_format"]);
}else{
my $t = $self->load_tmpl("confirm.html",associate => $q);
return $t->output;
}
}

sub result{
my $self = shift;
my $q = $self->query;
return $self->form unless $q->param('zip') =~ /^\d{7}$/;
my $t = $self->load_tmpl("result.html");
(my $zip = $q->param('zip'))=~ s/^(\d{4})(\d{3})$/$1-$2/;
$t->param( zip => $zip );

return $t->output;
}
1;

# form.html ##########################################
<TMPL_IF no_input>入力されていません</TMPL_IF>
<TMPL_IF bad_format>入力内容が正しくありません</TMPL_IF>
<hr>
<form>
<input type="text" maxlength="7" name="zip" value="<TMPL_VAR zip>">
<input type="hidden" name="rm" value="confirm">
<input type="submit">
</form>

# confirm.html ##########################################
<TMPL_VAR zip>
<hr>
<a href="?rm=form&zip=<TMPL_VAR zip>">戻る</a> | <a href="?rm=result&zip=<TMPL_VAR zip>">次へ</a>

# result.html ##########################################
入力された郵便番号は<TMPL_VAR zip>です
Catalystを使った実装例が掲載されてます。
http://www.lost-season.jp/mt/archives/2005/06/php_oop_catalys_1.html

Catalystは、PerlでMVCモデルを実装するフレームワークです。
PerlのWebアプリケーションフレームワークはOOPの進化とともに[CGI + DBI]→[CGI::Application + Class::DBI + HTML::Template]→[Catalyst]と進化して来たと思います。

PerlはOOP化にこだわり過ぎると実行速度がエラク遅くなるので、実用にはまだ躊躇してしまいますが、技術の研究という意味ではCatalystフレームワークは興味深いと思います。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Perl 更新情報

Perlのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング