[路杨Perl随笔]为什么你的Perl程序维护困难

| 2 Comments | 0 TrackBacks | WebBlog Articles

提记:最近老有人抱怨自己的Perl程序越来越难维护,也在抱怨Perl的执行效率低下,特写下自己的不成熟的体会,和同好者共勉之。

1。你的程序使用 use strictuse warnings 了吗?
不得不承认,Perl语法的随意性虽然很灵活多变,但有时间给维护和效率都带来了很大麻烦,如果碰见自己的糟糕的编程习惯和随意的语法,那么太长的代码就意味着一场噩梦,但是幸好我们有 use strictuse warnings . 有了这个,我们可以很快的找到变量的拼写错误(类似“$xxx 只使用了一次”的提醒),use strict 迫使你的语法变的严谨。当然如果你是维护别人的旧代码,而原始作者又是习惯使用 全局变量(Global symbol ) 的家伙,那么,加上 use strict 将让你陷入更大的维护危机(除非你想全部重写他的代码)。加 use strictuse warnings 困难吗? 不,你只需要在 你的程序的开头 '#!/usr/local/bin/perl' 后面加上下句就行:

use strict;
use warnings;

我的建议:
养成良好的编程习惯,尽管 Perl 语法允许你灵活和随意,新写的程序一定要加上use strict 和 use warnings .这样可以迫使你定义变量的范围,免避以后出现的效率低下和变量污染(一般都是Global symbol惹的祸 )

2。你使用模块了吗?
噢。。懒惰是 Perl 文化中的美德,难道是我们要使用现成模块而少写大量的代码的原因?我的回答是:不全是。
合理的使用Perl的标准模块或者CPAN上的成熟模块能让你的程序的后期维护变的简单,而且还可能(一般是肯定)使你的程序变的健壮和运行效率提高。
说的简单的例子,在国内的的多如牛毛的Perl在线资料(不知道经过多少次转载的东西了,叹息)中不乏有这样的 Perl CGI应用之CGI提交变量获取:

if ($ENV{'REQUEST_METHOD'} eq "POST") {
read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
} elsif ($ENV{'REQUEST_METHOD'} eq "GET") {
$buffer=$ENV{'QUERY_STRING'};
}
@pairs = split(/&/, $buffer); #(注1)

foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$forms{$name} = $value;
}


OK,我承认这段 code 很经典,但是有必要吗? 如果对于一个大的网站的CGI实现,每个需要处理提交参数的脚本程序都在前面加上这段话,不说其他的,就是不小心写错一个字符,也估计是维护人员的噩梦吧?不抱怨才怪。
另外,看见我标明 #(注1) 红色的代码吧?这段代码只能识别以 & 为分割的参数,而现在多数流行以 ; (分号)为分割的参数,如果要改的话,对维护人员也是个头疼的事情吧。
再分析,这段代码只能处理 key1=val1&key2=val2 这样格式的参数,如果要处理key=val1&key=val2 ( 即一个变量多个值的情况)就无能为力了:)
其实这段代码完全可以用 CGI.pm 改写,只需要以下代码:

use CGI;
$my $query =CGI->new();
my %forms = map { $_ =>$query->param($_) } $query->param(); #(注2)

就可以了,不单解决了维护人员的代码噩梦,而且可以完全处理分号隔离和一键多值问题。更可贵的,CGI.pm是Perl的标准模块(无须安装),运行效率有兴趣的朋友可以测试下,效率绝对要高的多:)

OK,关于代码维护困难的问题就简单的说这些,一家之言,只是我在学习使用Perl中的一点体会而已,请各位斧正。下次有时间,我准备和大家探讨下Perl程序效率低下的原因。



#(注2): 其实这句还是存在这安全漏洞,就好象原来的那段长代码也存在安全隐患一样,在正式的程序,还需要对获取的变量进行安全处理(比如过滤掉特殊的字符),防止产生 WebShell,让Cracker有机可乘。
办法也很简单:
my %forms = map { $_ => mysub($query->param($_)) } $query->param();

其中 mysub() 就是自定义的安全过滤函数:)
另外, 加上 my 是我的习惯,也是为了符合 use strict;,如果要彻底和上面的那一长段code等价的话,去掉这个就是了。

引用通告|TrackBacks (0)

本日志的TrackBack URL: http://easun.org/cgi-bin/mtos/tb_mt_41.pl/147.

本文相关评论|Comments (2)

对初学者的确很有用的
希望能有更多好的文章

欢迎 nsnake 来串门:)
不成熟的体会,别贻笑大方就行。呵呵。

发表该文评论|Leave a comment

最近发表|Recent Entries

[MT Tips]如何让某个日志在Blog首页固顶?

貌似最简单的办法就是修改日期到一个很遥远的日期,比如 AnySQL 那样:) 但是带来的问题的很多,比如导致Feed阅读器犯糊涂或者影响搜索引擎的收录等等,更糟糕的是对于 日志来说,最主要的就是发布日期。也许大家都已经发现了,我的主页模仿 MT Forum 搞了一个固顶日志(也是为了风格统一)出来,这个固顶日志是后台通过自己设置实现的。是怎么设置的。答案是利用 <mt:Entries> 的tags 功能。 具体概念代码如下:<mt:Entries tag="@top" sort_by="authored_on" sort_order="descend" limit="1" blog_ids="1,5"> dosthing.....</mt:Entries> 这样我们只要要在固定的主题 加上…

北京 Perl Workshop 2008 网站开张 - 接受大会注册,演讲报名

网站开张了, 地址是 http://conference.perlchina.org/bjpw2008/ 由 PerlChina 和 Postgresql China 合办,2008 年 11 月 8 号举行的 Beijing Perl Workshop 是一个免费的 Perl 交流会,向所有对…

好玩的 MT Forum 的按作者归档

Perl Forum 用 MT4 的 MT Forum 的功能搭建起来了好几天了,一直没有发现什么意外,今天突然发现 按作者按月归档 貌似找完了整个发布完的 Perl Forum 也没有找到 link ,查看作者个人信息貌似也没有 link ? 真是好玩的 归档方式。从后台看,给每个用户(作者)都建立了按月的归档页面,估计是为了便于各用户归档自己的文章吧? 后台抓图如下:…