use base? use parent;

Perl 里面要继承某个类,一般的写法是:

use base qw/BaseClass/;

最近注意到流行用 use parent 的写法:

use parent qw/BaseClass/;

那么,区别何在?

  • parent 比 base 更轻量级。看 source 即知。
  • 如果要用 use fields; 就只能用 use base; 因为它们来自同一个 package: http://search.cpan.org/dist/base/
  • use parent; 可以用 -norequire 选项跳过寻找外部文件。

一般用起来应该没什么差别,哪个都无所谓。不过个人觉得用 parent 比较酷,嘿嘿。

怎样写 pod 文档

我想说的不是 pod 文档的格式。有关格式的可以看 perldoc perlpod 或者阅读 fayland 很久以前写的《怎么写POD》

先说动机。偷懒是天性,是事物发展的源动力,是进化的产物。写程序本身就是搞个自动干活的傀儡来反复偷懒。所以写完程序没有文档在情在理。程序员还有一个常见的现象,喜欢推到重来。因为原来写得太复杂了,就算是以前自己写的,也不能当下一眼洞穿,还不如重写更舒服。有时候这是正确和必要的,叫重构,但大多时候并不需要。

但有文档就不同,它帮你回到过去。我经常在 search.cpan.org 上看模块的用法,然后照着例子用。我最近看很久以前写的东西,朦朦胧胧,七兜八拐,晕头转向。这种情况已经不止一次了,如果有个速查手册或者简单的帮助提示,于人于己都会方便不少。

敏捷开发不提倡写文档,因为要消耗时间和精力。但这不等于走向极端化说万万不要写文档。敏捷方式提倡开始时不写,因为需求还未定型。定了型的要写,但可以简单一点。这个是时机问题,也是优先级问题。就像写 Perl 模块,开始 alpha 版本的时候可以给一个实际用例,等接口都稳定下来了再写每个方法的用法。

下面简单快速列几点:

  • 文档是写给未来自己的情书。对自己好点~
  • 文档如同性,有高潮最好,就算一般也比没有强。
  • 现在写总比以后写更快更容易,不是吗?
  • 写还是不写,想想看自己是专业的还是业余的。
  • 集中写在末尾 __END__ 下面,用 vim 的 :vs 垂直分两屏,左边代码右边文档。
  • 随时 pod2html 阅读输出版本,像用户一样读和思考。
  • 读文档的人只关心怎么用,所以写文档的目的是告诉他们怎么用;如果关心实现细节,只管由他去看源代码好了。
  • 多举例子和实际的 use case。这最直观,也最容易学用。
  • 维护 FAQ。用的人都会问些什么问题,直接列出来问答。
  • 请人来读。读不懂的地方就是白写了,立即整改。
  • 还没写的要占个位子先。这样就算出去上趟厕所心都是定的。
  • 跑个测试检查文档覆盖率。看看还有哪些位子没占到。

Google Ads

写读书笔记

现在学而时嘻之上的文章我几乎每篇必读,并且颇有受益。今天在路上读了关于读书笔记的文章(),颇有共鸣。

最近读过的一本书,就是用蓝色圆珠笔在上面乱涂乱写。以前我很注意保持书页平整干净,就算写也尽量用铅笔。上个月我刚想通,书是自己的,买纸书来看的目的就是可以随时记下一闪而过的各种只言片语,回过头来只需要看有颜色的部分。注记也无非是提纲挈领,点画出实质和因果关系,没有现成的就自己概括,用自己的话来说,甚至自己画上关系图。碰到有疑惑的或者有质疑的就把问题写下来。就算后面马上看到有相关的解释,这种注记也是必要的,它体现了思维的过程,以后 review 就一清二楚了。实际上,写注记等于是整理思维脉络。看别人怎么说是客观被动观察,自己说出来是主观能动表达,调动的是大脑里不同的工作机制和流程。hoho,说到这里,才意识到这就是为什么我能听懂英文却讲起来不地道的原因。

如果读完一本书,别人问起来说了些什么而答不清楚,这本书就等于没读。用不了多久就会依稀记得大致几个朦朦胧胧的画面。所以人们常说,如果你会教别人书中的知识,就说明你真的学会了。教就是系统整理知识再按照逻辑关系因果关系表述清楚的过程,这个过程需要强力阅读后思考很多为什么怎么会的问题,理清脉络把握重点之后,才能有先有后,有详有略地教别人。教的前提是在自己大脑里作笔记。写下来的就是备课提纲。

我承认我有迂腐的藏书习惯,很多没有系统看完只是摆在书架上。想到时间不够,又并非全都现在用得上,基本上用来翻翻查查。不过现在我喜欢涂写概括复述,然后扔掉这本书。一堆纸而已,无可留恋,谁需要送给谁。只要提起这本书,能如数家珍摆出其中的精华就行。

至于注记工具,Google Notebook 就很不错,我经常用来铺写零散的思绪,然后整理归纳,非常方便,只管集中注意力思考并打字记录下来。不过在纸上写字画图更快速更直观也更流畅,不容易打断思路。另外像 CPAN 网站若干年前推出一个 Annotated CPAN,帮大家对 CPAN 上 Perl 模块文档的每个段落(或者代码)加上旁注。这其实也是读书笔记,如果大家都来质疑就成了头脑风暴。就像强力研读中说的,是不是需要建个网站分享读书笔记呢?应该会很有用的。知识精华的快速传播和分享,推动起来意义非凡。

其实不光是读书,任何载体形式的内容都应该有这样一个概括归纳的过程。看强力研读的博客文章如是,看完就应该概括下,记下来,假设要再说给别人听。而写 blog 本身也是一个“读后感”,也是一个归纳思考的过程。

以往坏就坏在读书的读字上了,流于读的形式之后,就忘了读的目的和诉求。

Planet PerlChina

突然心血来潮,看到 planet.perlchina.org 有些简陋,想自己动手。以前没用过 Plagger,快速上手熟悉了下。cpan 上的版本 0.7.17 还是 2006 年发布的,十分老旧,github 上 Plagger 项目倒还是在持续开发,下来 make test 许多通不过,只好用 “stable” 版,安装时需要手工下载安装老的 XML::Feed 模块。plagger 就是一个命令行工具,读取给定的配置文件,从网上抓 feeds 处理之后生成静态网页,保存到指定目录。

So, 我自己建了个 planet.chunzi.me,并找了一堆写 perl 文章的 blog,配好架起 planet.chunzi.me/perl。可以说是 planet.perlchina.org 的克隆吧。所采纳的 feed 一般限于 perl 标签的 feed。所以这个聚合仅仅关心 perl。如果你对作者感兴趣,请直接订阅 blog。当然,plagger 聚合出来的也是可以订阅的。plagger 号称是 feed 的 pipe,我很喜欢 pipe。

在最下方列出了订阅列表。如果有版权问题,或者想增加你的 blog 或者推荐 feed,都请给我邮件:chunzi@gmail.com

目前手动生成页面,稍后改用 cronjob,再把相关代码配置放到 github 上去。

chinese-perl-book

虽然 fayland 自己没提,不过我忍不住要提一下了,这位兄弟在 github 上正在撰写关于 Perl 的中文书,叫做 chinese-perl-book

Fayland 结合自己的开发经验,介绍了几个现今比较流行的模块的使用,特别是 Moose,值得花时间拜读学习。从目前完成的一部分内容来看,更多的是理念的分享,这点非常难能可贵。模块的使用总会过时,行事的思想和方法却一直可以受用。

和书籍本身开源一样,相互协作带来的好处绝不是单方面的。Fayland 鼓励大家 fork 他的项目来共同推进。如果学到了什么,请对他道声感谢;如果有不明白的地方,请立即向他提问,这会有助于改善此书,以及更多将来有类似问题的读者。

数据驱动测试框架 Test::Base

写测试时,经常会遇到一堆类似的输入和输出要循环迭代同一组功能。简单点的,可以先构造几个数据数组,然后在循环中依次套数据。稍微复杂点看起来就乱哄哄的。

今天看到这个模块,简单易用,条例清晰,扩展方便。

use strict;
use warnings;
use utf8;
use Test::Base;
use URI::Find::UTF8; 
 
filters { raw => 'chomp', uri => 'chomp' };
plan tests => 2 * blocks;
 
run {
    my $block = shift;
 
    my $f = URI::Find::UTF8->new(
        sub {
            my($uri, $orig) = @_;
            is $uri->as_string, $block->uri, "$uri";
            is $orig, $block->raw, "raw path";
        },
    );
    $f->find(\$block->input);
}
 
__DATA__
 
===
--- input
アンサイクロペディアのホームページはhttp://ja.uncyclopedia.info/wiki/メインページ foo bar
--- raw
http://ja.uncyclopedia.info/wiki/メインページ
--- uri
http://ja.uncyclopedia.info/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8
 
===
--- input
Home page <URL:http://www.google.com> Google
--- raw
http://www.google.com
--- uri
http://www.google.com/

要测试的数据放在 __DATA__ 块内,三个等号标志一个 block。然后三个减号定义一项数据的名字,下接其内容。看程序,use Test::Base; 后,就有 filters, plan, blocks, run 这几个方法可用。

filters 定义提取数据时,要做的休整操作。blocks 在 scalar context 返回定义了多少 block,因为每组 block 将要在 run 里面做两次 is 测试,所以 plan 要做的测试总数为 2 * blocks。接下来 run 定义了一个匿名 subroutine,在其内部接受 Test::Base 传来的 block 对象,然后依次测试,访问 block 数据就直接用定义好的数据名字,清爽。

这里是 cpan 上的连接

blog 重生

原来的服务器不能再用,于是找了个新地方。借这个机会用上最新的 WordPress 2.3, 虽然还是 RC-1 俄。这次选用了 Nicky 的 iBlue theme,感觉大方舒适些,内容的组织上也更加合理科学。

原来的地址是 blog.chunzi.org 这次改为 chunzi.org/blog 。究竟选择哪一种,我想了很久。利弊各半,再说了。

顺便还 rsync 了 cpan 站点,放在 chunzi.org/cpan 下。

jQuery.js 和 Prototype.js

实在忍不住要写点什么了。我被这两个 JavaScript 搞死了。它们都让我又爱又恨。

Prototype.js 出来得早,随着 Rails 的开发而逐渐扩大影响力,成为 Rails 框架下御用 JS 框架。所以秉承了 Ruby 语言的一系列概念,非常清晰地用组织良好的类,对象扩展的方式,增加了各种常用的 handy 函数或者方法。所以叫做原型么。学习曲线低,顺手拈来。

不过这种循规蹈矩的做法很快让书写它们的人感到厌倦。很多操作都要加上类名,繁复、生硬、罗嗦。于是 jQuery.js 得以进化为,用最自然的,类似伪代码的形式,完成相同的功能,并具有更好的可读性。比如:

$(".rborder").corner("5px").parent().css('padding', '1px').corner("round 5px");

一气呵成,痛快极了。想象不出还有什么写法可以比这个更简洁达意。而 jQuery 的哲学就是:写最少的代码,做最多的事情。

而这种写法,像极了 shell 下面使用管道符串联起来的一系列命令,简单、优雅、强大、灵活。喜欢用 Perl 写代码的一个原因,也是因为其中的 map 和 grep 组合所构造出来的类似效果,清晰、流畅、自然。所以 jQuery 是很讨开发者的欢心的,用起来舒服。

用起来舒服,这件事本身没什么伟大的,可一舒服,写程序的人就兴奋起来了,就会很高兴地去发明些什么,这种内在激发的驱动力一爆发,就造成了现在 jQuery 插件遍天下的格局。这和 Rails 本身敏捷而富有艺术性的气质所带来的全球影响力的爆发是一致的。

不过这带来了一个问题。插件满天飞,怎么保证质量和兼容?自由带来的多样性是件好事,太多了就分不清楚谁是谁了。虽然 jQuery 提供了统一的 svn 仓库,不过各式的插件的文档,测试,演示等等,各自为政,颇为凌乱。或许需要一个类似 CPAN 一样的统一管理介质?

jQuery 对 DOM 对象的操作很容易--主要是很舒服,可要处理数据的时候,就不那么舒服了。我总是对 prototype.js 中的 inspect(), join() 念念不忘,可 jQuery 没有,好不容易看到一个 Array 的插件,提供的功能也是捉襟见肘。所以我目前的结论是,对页面元素的控制上,用 jQuery,对数据的处理上,用 Prototype.js 。

还好,jQuery 只是在自己的命名空间里面东奔西跑,按照标准的方式,两者可以共存。不过 jQuery 为了 write less,默认情况下,将自己的类捆绑到 $ 函数上,于是,这一强大的内激效应让一些插件的作者忘掉了这只是一个快捷方式,只要在插件内部也使用这种写法,就会和 prototype 冲突。比如说:ThickBox 3.1

开会去了…

Catalyst 在 modperl2 里的怪问题: Can’t store CODE items

本来在 Catalyst 的原生 web 服务下跑得很好的,在 Ubuntu 上装了 apache2 和 modperl2 之后,虽然能起来,但刚登录就出错,看日志发现:

[error] Caught exception in engine "Can't store CODE items at ../../lib/Storable.pm (autosplit into ../../lib/auto/Storable/_freeze.al) line 290, at /usr/local/share/perl/5.8.8/Object/Signature.pm line 19"

查了下 Google 未果。今早一问 Fayland,一语中的:

$ cpan install Tie::RefHash

升级一下搞定。很困惑为什么 Catalyst::Engine::Apache 的文档中不提一下呢,搞得我昨天很郁闷,一直到睡觉前。

labs.chunzi.org/imgred

看到一则新闻说,有个网站提供图片的转发。因为如果你写 blog 的时候引用了人家网站上的图片,又如果人家嫌你无谓地耗去了带宽资源,于是禁止对他自己以外的站点的引用,那你的这张图片就不再能显示了。所以这个 ImgRed 网站很大方的提供了这样一种方式,如果你在要引用的图片的连接之前加上 http://imgred.com/ 就可以让它帮你提供图片资源。第一次访问之后,ImgRed 就会缓存这张图片,以后都直接由它自己提供。非常大方呀。而今天有看到它更大方地拿出自己的代码和大家分享。

虽然看不到什么可以赚钱的地方,不过这种创意还是比较有意思的。没想到过。不过每个 Image URL 再加上 ImgRed 的头,貌似很长的样子,如果用 tinyurl 之类的缩短一下就好了。就这样一想,不经意间就有了一个新的 Meshup。多简单阿,做个工具页面,你给出图片的 URL 然后我给你短小精悍的 URL ,然后旁边放个 Google 广告,用的资源都不需要我自己提供。

于是花了一点点时间,做了这个:http://labs.chunzi.org/imgred/

代码很简单,使用 WWW::Shorten 模块来实现缩短 URL,使用这篇文章提示的方法自动把结果保存到剪贴板。最后加上 Digg 图标。