完成了一个新程序

真是知道的越多,越能感受自己的无知。

近期要完成一样工作——对一个表格进行整理,原理挺简单,但手工绝对无法完成。表格所在的 CSV 文件体积有 13.2M 之多。由于需要对结果进行一些分析,我上周想着用 Rails 来做个网页,可以动态的显示数据的关联关系。这个工作在 Excel 里实际上是分类汇总,但如何对分类汇总的结果再来一遍分类汇总,我就不知道了。

然后上周大部分时间就做了这个。本来我觉得应该不是很难。Rails 虽然几年没写了,但基本原理我是知道的。MVC、ActiveRecord 组合起来的工具,可以方便的调取数据,获取结果。我觉得就算是操作数据库,写几个 SQL 就能完成的任务,让 Rails 来岂不是小菜一碟?结果跟我想的完全不一样。

首先就是 ActiveRecord 的问题,涉及的字段一多了,就复杂了,数据实在是让人头疼,有的时候就是不对。另一方面毕竟是七万四千多行的数据,效率也上不去。有的时候进行了一个调整,就看到 Rails 服务器后台的 SQL 语句不停的滚,我自己也能感受到效率的低下。

然后这个程序就陷入了死胡同。我上周五达到了这个进度,周末度过了忙碌的两天,一直也没有进展。到了昨天晚上,到了十点多,坐下来开始重新规划这个问题。这次我不用了 Rails,改用之前比较习惯的面向对象模拟,构建类,然后把每个单元对象放入数组中。分析的过程就是构建对象的过程,最后遍历一下数组,输出就得到了结果。一直做到凌晨两点半才简单的弄出了一个框架,这才睡下。

今天,把思路和结果给领导看了看,经过同意,就对输出进行调整。我还没有实验成功过让 Ruby 直接写 Excel 文件,所以还是输出的 HTML。当中表格换行的时机等等弄得我头昏脑胀,最后好不容易给弄好了,得到一个输出后有 3000 多页 A4 纸的表格。不过,我在导入到 Excel 中遇到了一些单元格合并的问题,看来之后还是要研究直接输出到表格。或者就是在办公电脑上用 Java 重写,不过那代码量估计会很多。

迟钝的编程

从上周一开始,我接到了一个任务,又是把系统里导出来的数据进行统计,输出结果。我用 Ruby 语言编写了一个简单的程序,来处理 Excel 导出的 CSV 文件。由于时间紧急,我没有仔细构思程序应该怎么设计,直接想到什么写什么,最终写出了程序,完成了任务。

之后的几天,我每天开心的用我的小程序来完成任务。尽管我心里想着为它加上直接解析 Excel 的功能,省得我要手动把文件导出成 CSV 格式。不过尝试了一下 parseexcel 包没有成功之后,我暂时就偃旗息鼓了。然后一直到了这周一,领导找到我,说数据不对,我一看果然差的很多,心里一下子紧张起来。然后手动计算,找问题出在哪里。结果发现原来从三天前,信息中心的人不声不响在系统输出的数据表里加了一列,我的程序当然出错了。于是急忙改正。

之后这周三我因为请假,于是就在周二下班后,把当天的结果给弄了出来。我们公司每天下午 4 点就结帐,停止生成新订单了,我觉得到了下班后来弄这个表应该万无一失(过去是次日得出本日的结果)。岂料到了周三下午,领导找到我说数据又不对。我心想怎么回事儿?结果领导指着一个相差比较大的数据给我看。我一看正好有印象,因为我前一天导出数据后,看到这家分部的数据量特别小,只有不到 20 行——这些数据无论如何不能得到领导算出的 80 多的结果。于是我重新导出数据,悲愤的发现原来下班后 1 小时后数据还没有计算完毕,所以发生了这种错误。

然后领导带着我一起手工算了一下,我在这个过程中发现了,原来系统导出的数据有各种各样的坑,一些不适合的数据也被放了进去。另外,我还发现了另外一种情况,也应该被算入结果之中,结果一开始因为它没有出现过,因此我就忽略了它,导致我得到的结果与正确结果有偏差。

于是,从前天下午下班后,我就一个人留在办公室,思考这个问题。因为我的思路还是一开始的那样,所以陷入了一个死胡同中。一开始我是让程序直接模拟我思考的过程,心里怎么想的就让它怎么运行,结果是它完全模拟了一个人类的处理过程。有了不同的情况之后,程序需要判断各种不同的情况,按照这个思路,最简单的方法是程序在读取完一遍数据文件后,再重新读取一遍,用另一种方法来处理数据,最后把两次结果加起来,才得到最终结果。想到这么麻烦,我就感觉一阵绝望——就算我最终写出了程序,我也不敢确保它能正确执行,要调试起来也很麻烦。

到了昨天,我想预期要多次处理数据,不如把这些数据一股脑儿读到内存里去,开始时我觉得这样是一种折衷方法,后来慢慢的发现,这应该是处理问题的正确方法才对。我用两个哈希表,每个元素对应一个列表,来存储从两个视角来分析数据的结果,然后迭代每一个元素对应的列表,进行简单判断,然后就是加法运算计数了,整个解决问题的思路一下子变得如此清晰!

写完了程序之后,我略微反思了一下,其实程序本身没什么复杂的,只是需要把所有的可能情况考虑清楚了,这是最关键的地方。但说来容易,执行起来可不容易。在正常的软件开发中,TDD 是解决这个问题的良药。可我时间紧急,也没有经历来考虑所有可能发生的情况,这其实就给这次开发带来了弯路。另外一个教义,是不要害怕推倒重来。如果我到后来一直坚持一开始的思路,没有变更思路的话,我想就算我最终完成了程序,写的过程应该也非常难受。有趣的是,这样的一个教条,在《人月神话》中已经被提及了。如果正却的开发方法都无法被实行的话,我想最重要的一点,就是要保持冷静,让头脑放空、清晰,是写出正确代码的不二法门。

当然,Ruby 这样的快速开发语言帮了我很大的忙。我想,如果让我自己手工写哈希表,我一定不会这么快的找到解决问题;哪怕是 Java 这样的语言,有自己的数据结构库,使用起迭代来那繁琐的步骤,也很容易把我给绕迷糊了。

重拾 Perl

最近,我开始重新学习 Perl,尝试用 Perl 来完成日常的开发程序。

原因是前几天听第 27 期内核恐慌时,主持人提到了 Perl 6。然后吴涛说起 Perl 时,感情很复杂。我当时心想,我对 Perl 的感情也很复杂咯。首先是对今天的程序员来说,Perl 太原始了,与 Python 和 Ruby 等语言相比,更显古老。回想起来,自从我学习了这两种语言后,我就再没有正儿八经用 Perl 写过程序。而我真正有了属于自己的电脑,是在 2007 年,那个时候我正好开始学习 Python,之后就没有碰过 Perl。

而另一方面,Perl 又是我的启蒙导师。具体的科目不好形容,与 UNIX/Linux、开源等世界有关。在接触 Perl 之前,我对编程,还停留在 BASIC 语言、C/C++ 语言、Pascal 语言上面,对于脚本语言,我的理解只是 .bat。在当时的教科书上,获得的结论是编译型语言比解释型语言在执行上各种优秀,解释型语言只有在学习时才有优势。UNIX 世界繁荣的脚本语言与著名的 KISS 原则,我则一概不知。

记得我大概在高中的时候买过一本小册子,第一次让我接触了 Perl。小册子的内容是 FORTRAN、Pascal、C、Perl、PHP 这五种语言的诞生历史,正是我感兴趣的内容。FORTRAN 那一节看的我比较枯燥,Pascal 是参加 OI 的语言,我比较熟悉。C 我虽然没怎么入门,但也接触过,于是就一章一章的看下来了。Perl 的这一章,是 Larry Wall 写的历史,用女孩子的成长周期来形容每一个版本的 Perl,语言相当幽默风趣,浅显易懂,还有 Larry 在设计 Perl 时的心路历程。虽然我还没有读过一行 Perl 程序,但看完了这一章节,我对 Perl 有了极大的好感。我喜欢的,就是这种不羁的风格。务实、能用的思想,再加上一些宅男一样自娱自乐,不管旁人眼光的态度,让我十分痴迷。

后来,我在新华书店买到了一本《Perl 语言入门》,一本薄薄的小册子。虽说《Perl 编程语言》才是真正权威的教材,但我还是抱着试试水的想法,买了更薄、也更便宜的“小骆驼书”。事实证明,这对我来说是一个极端正确的选择——这本书实在是太棒了!哪怕到了十多年后的今天,我还是认为这本书是编程语言教材中的 No. 1!或许是这本书的作者们都是常年培训 Perl 的老师,他们讲起 Perl 来头头是道、语言风趣、深入浅出。虽然我在阅读的时候,手边没有一台电脑给我来实践,但随着阅读和书中的示例,我很容易的就理解了书中的内容。书中用虽然没有涵盖 Perl 的方方面面,但其中 Perl 的 20% 的内容,就可以解决 80% 的问题。同时,书本的内容引起了我的一些思考,以及计算机世界眼界的变化,带给我的影响是巨大的。

另外,之所以说先看“小骆驼书”是个极端正确的选择,是因为后来我出于对 Perl 的喜爱,还购买了更贵、也更厚重的“大骆驼书”,也就是《Perl 语言编程》。不知道是书的本来风格与我不合的原因,还是翻译水平的原因,我总是无法对这本书产生喜欢的情绪。到最后还是把它当成了 Perl 的 Reference Manual。

出于对于 Perl 的这种复杂的感情,当我听吴涛给没有接触过 Perl 的听众介绍说“Perl 是一种‘只写’的编程语言”的时候,我忽然想到了,我日常工作中要分析的数据,虽说我用 Ruby 和 Java 分别实现了相关版本,但时常又被告知需要其它方面的结果。与其这时候再来该程序,不如尝试用 Perl,来快速的写一些只写的脚本来工作?

于是我这个周末开始了尝试。因为已经很久没有碰 Perl 了,我只好找出了《Perl 语言入门》来,从头看起,然后通过运行示例程序,来恢复过去的知识。有了一点心得后,就马上尝试来写我日常需要的一个功能。现在我发现,Spreadsheet 这个模块很有用,用来分析我们系统导出的 Excel 表中的数据,可以比较方便的提取数据,而且写起来比 Java 上的 jxl 模块要简单方便的多。

只是时间长了,有些东西还是很生疏。比如我需要用到 switch 语句,就去搜索语法,得到的结果居然是 Perl 核心中没有 switch!然后有用其它技术来实现的,还有一些模块。确实是 Perl 的“怪”的体现。不过我还有时间,这个过程也很好玩就是了。

最后,对比起 Python 和 Ruby,我觉得 Perl 有更强烈的“顺手”这个特性。它没有很完美严格的“世界观”,不会执着于把一切都弄的很漂亮,它只是你手头的一件趁手的工具,甚至你用完了随意一丢也不怕摔坏。在 Perl 里,class 关键字可没有其它语言中这么方便。

Java and Ruby

我的日常工作之一是统计非法走私信息,在国家级的行业信息系统上有一些数据,但不是我们要的格式。我们要把每个走私案件统计下来,包括走私的产品、数量、案值金额、还有涉及到哪个下属单位等信息。过去用眼镜跟手再加上 Excel 来整理实在是太麻烦了,于是我就写了一个 Ruby 程序,把导出的数据整理成我们需要的格式,输出成 HTML,大大减轻了工作量。

不过这个程序是在我的 MacBook Pro 上写的,而我们的信息系统只有内网能访问。每次使用的时候我只好导出数据,转换成 CSV 格式,然后用电子邮件发给自己,从 MacBook Pro 上收取邮件,转换编码,转换成 UNIX 格式,然后再运行程序,把生成的 HTML 页面再通过电子邮件来发回去,再进行整理。这样一来很繁琐,而来这样只有我自己才能干这件事,我休假时也没法委托别人去做。

所以前几天我考虑了一些比较适合在 Windows 上使用的编程语言,把我的 Ruby 程序移植过去。最后我选择了 Java,因为它比较容易在 Windows 上安装,而且我之前上学时还做过两个 GUI 程序,我也希望把程序做的友好一点,可以推荐给同事用。

我没有进行别的什么设计,只是简单粗暴的对照着之前的 Ruby 程序,逐行翻译过来。断断续续的调试了两天,目前弄了个大差不差的版本,只是这次我的输入输出直接是 Excel 文件,省下了转换格式、编码的步骤。我对于操作 Excel 还没有了解多少,所以还有些合并单元格、修改字体、宽度高度什么的需要加上,其它数据方面今天总算是调试成功了。

谈谈使用 Java 的感想。

我在 2010 年的时候写过一篇文章,记载着是一次用 Java 语言完成作业的经验,我那时候花了一夜完成了那一周的作业,实现了几个数据结构并且排序。那时候我用 Java 还比较熟练,有些东西不需要像现在一样查文档,结果没怎么调试居然成功了,让我对 Java 好感大增。不过这次跟 Ruby 比起来,Java 就显得太繁琐了。

过去我对 Java 的一些比较“高级”的用法不大了解,因此一些迭代器呀什么的也用的不多。这次因为在 Ruby 程序里用了很多迭代,感觉比自己苦兮兮的写数组来说方便太多了,因此就用了不少的迭代,结果每次新建一个迭代器实例,再用 hasNext()next() 函数来遍历,比起 Ruby 的一个 each 就搞定实在是繁琐。这样的另一个后果就是多了一堆代码,我在 NetBeans 里面看的眼都乱了,调试的时候直接找不到头绪。最终搞定了我是觉得没问题的,但是搞定前费的功夫实在是大。所以近年来,要完成一些任务,我绝对是偏爱脚本语言。

写到这里,不禁感叹,如果我们公司用的是 UNIX 操作系统该有多好,可惜绝对不现实呀。

过去对这方面的感触不深,但通过对比就觉得 UNIX 的编程方式实在是太方便太先进了,比起 Windows 的模模糊糊好了不知道多少倍。可惜 Ruby 在 Windows 下执行不大方便,做成可执行的 EXE 就更不容易了,简直没有头绪。

这个程序目前的输出方面,还有一些功能需要添加,不过这个 Excel API 弄得我写起来还是不顺心,也许有一个更好的用法,反正正常的写程序绝不应该是像现在这样遇到输出就一个单元格一个单元格的写,运算逻辑和输出逻辑都没有分开,之后要加点功能,处理其他格式的数据,肯定远比我过去用 Ruby 输出 HTML 时来的困难。

用 Rails 重写 Tweets Page

今天我用 Rails 重写了 Tweets Page 程序。这算是我的第一个正式的 Rails 程序。

写这个程序的目的就是为了真正的用 Rails 来写一个小网站。这个程序的作用仅仅是保存 Twitter 上我的内容到自己的数据库里,然后可以在自己的网站上访问,这样在国内不需要翻墙也可以访问我的 Twitter 页面。它比一个博客程序可简单多了,所以我挺早之前就计划用它来练手了。

最近因为看了一些 RubyConf 上的视频,也更加的激发了我使用 Ruby 和 Rails 的兴趣。一个这么活跃的社区被展现在了我的面前,而我却不得而入,是一件非常讨厌的事情。面对这么活跃的社区,不说可以切身参与进去,至少看别人的演讲可以激发起共鸣才行。

其中有一个视频我特别喜欢,我把它下载下来看了很多次。题目是 The Ruby Code Review, a play in three acts。其中 Jim Weirich 和 Chris Nelson 模拟了一个咨询的过程,Chris 代表咨询人,Jim 作为服务人员帮助 Chris 给他们的程序解决问题。其中 Chris 展示了一些让人忍俊不禁的错误,把 Jim 给逗的没脾气。不过视频中确实展示了 Rails 的很多方便的地方,尤其是对于数据库操作的封装,简直不需要程序员去构思那些 SQL 语句,用 Ruby 的语法自然而然的就操纵了。

我用 Rails 写这个 Tweets Page 程序其中的一个问题就是数据库的操作。我首先需要把数据给导入到数据库中去,怎样完成,我需要考察,如何能从外部导入到数据库中,而让 Rails 也识别出来,是我要解决的。

下午我打算去超市买西瓜,但我都穿好衣服了,但头发因为刚睡起来而一直翘着,怎么弄都弄不平,我怎么好意思就这么出门呢?于是我只好弄条毛巾压在头上一会,好把头发压平。因为没事做我干脆坐下来研究程序,听着 John Mayer 的 Friends, Lovers, or Nothing,不知不觉间就把程序给写成了。

我找到了在 Rails 环境下执行程序的方法,在 Rails 3 中,运行 rails r my_script.rb 就可以了。我很快把我旧的导入程序改了一下,就可以运行了。从这里我很深刻的感受到 Rails 的方便。我的旧程序中使用了 Sequel 来操作数据库,在这里完全不需要,通过 ActiveRecord 可以非常方便的用 Ruby 来操纵数据库,一点 SQL 都不需要,程序简短清晰了许多。

导入数据之后是更新。Ruby 的 Twitter 库升级后给我带来了一些麻烦。我的旧程序中用的是 2.3.0,需要后去 tweets 直接拿就可以了,反正我只要公开的数据;而现在的 Twitter 库版本为 4.7.0,要获取数据必须要认证,明明这些数据都是公开的麻。结果没办法,只好在 Twitter 注册了一个 app,获取了 OAuth 数据,才让我正常获取数据。讽刺的是旧版本的程序运行的好好的,如果用旧版本的 Twitter 库什么问题都没有。不过新版本的程序多了 6 行代码,也就罢了。

到这里程序在本地运行没问题了。我依旧没有实现分页功能,等之后找资料再看吧。我目前导入的 tweet 条目有 11000 多行,因此一下子全部显示出来非常的慢。

之后就是在服务器上部署了。我用的是 Apache+Passenger 来做,不过在根域名下运行正常,而我想把程序部署到子目录下就出问题了,浏览器显示 403 错误,查看 Apache 的错误记录说是没有访问链接的权限。这方面我还没有照到资料,只好日后再试验了。

后来我发现 Rails 的 ID 字段的长度不够,在这里找到了解决方案。

这个程序一点都不复杂,不过作为我的第一个比较正式的 Rails 程序,让我一下子有了种豁然开朗的感觉,我突然对 Rails 有信心了,默认的程序我也敢于自己动手改改了,不错。

Jim Weirich 讲 Y Combinator

Jim Weirich 是 Ruby 社区中我最喜欢的讲师。首先他的体型会给人很深刻的印象,听他演讲时不断传出的喘气声,给人一种他随时可能一口气没上来就累死的感觉。但他的演讲十分的吸引人,流畅、生动,如果在大学里,他绝对是最受学生喜爱的教授类型。

Jim 在 Ruby 社区中非常活跃,他的作品可以用“脍炙人口”来形容,比如 Rake。几乎每届的 RubyConf 都有 Jim 的演讲。相比起 Matz 那典型的日本人的演讲,Jim 的演讲远比作为 Ruby 语言的创始人 Matz 的演讲更有趣。

过去自从 2007 年,每届的 RubyConf 我都关注。去年开始比较忙,编程方面用心少了,于是最近的 RubyConf 我没有看。昨天正好想起来,就补了以下。今天我看了 Jim 在 2012 年的 RubyConf 上的演讲,标题是“Y Not — Adventures in Functional Programming”,讲的内容就是 Y Combinator,涉及的内容包括不动点、Lambda Calculas、递归等一些数学上的理论。Jim 这次的演讲中不包含 Ruby 知识,只是用了 Ruby 程序来演示了 Y Combinator 的内容。在演讲中,Jim 用 Ruby 中的匿名函数来写了一个阶乘函数,从最简单的开始,通过类似 LISP 语言中宏展开的方式,像证明一道数学题一样推导出了 Y Combinator 的 Ruby 代码。虽然到后期的各种替换,因为不是亲自操作,非常容易被绕迷糊,但 Jim 还是非常优秀的把总体含义给讲清楚了。

Jim 到最后也没有说出来这次的内容对于底下的 Ruby 程序员们有什么帮助,因为确实没有。这些知识就好像微积分对于文科生的作用一样,可以锻炼思维,但没有直接的影响。

我过去以为欧美国家里的计算机科学课程应该非常高深,比如过去我听说很多大学的计算机入门课程都是 MIT 的 6.001 教材《Structure and Interpretation of Computer Programs》,这本书用 Scheme 语言,讲述了计算机计算领域的很多初级问题。比如 Y Combinator 在书开头不久就在注释中被提到了,书上也给出了计算函数的不动点的程序。后来我自己来读了以下加拿大的大学中的计算机系后,发现随着时间的推移,很多东西都被舍弃了。毕竟现在人们需要的更多的是 IT 人才,而不是计算机科学家。MIT 自己也不再用 Scheme 语言来给学生入门,而是选择了更流行的 Python。所以很多欧美程序员,对这些过去的入门知识并不了解。因此在演讲的开始 Jim 询问听众有多少听说过 Y Combinator 的,结果回应的人很少。

看了一会视频,我发现 Jim 讲的内容并没有什么深奥难懂的东西,二这些东西基本上都在过去的教材中出现过,今天拿出来再讲一次,这不是把旧知识重学一遍吗?确实在计算机行业中有过一句话,大意是今天的编程语言就是把当年的 LISP 重新实现一遍。于是在前几年的某个时间点之后,大大小小的语言设计者们开始往他们的作品中加入 lambda……

我对早期的编程语言非常的感兴趣,因此也很容易产生迷惑。我在大学中学的第一门 3000 等级的课就是讲述各种类型的编程语言的一门课,内容包含了函数式语言、LISP、PROLOG 以及 APL 语言的后裔 J,这门课的成绩是我所有学过的 3000 等级的课程中最好的之一,那时我主修的 2000 等级的课程才刚开始不久。让我在学这门课的时候如鱼得水的原因就是我对那些传统编程语言的兴趣。因为觉得这些奇特的表达方式非常有趣,因此我就更加的想了解,了解了之后就是困惑,这些优秀的东西为什么在今天都被主流排斥在外呢?为什么它们看起来如此的优美,但在今天却不再实用了呢?它们是花瓶吗?结果今天的主流语言开始模仿起了老前辈,但老前辈依然在各个小众领域中苟延残喘。或者偶尔能够诞生出一个后裔,在特定的领域绽放一点光芒,比如 Erlang。

最后说一句,看 Jim 写代码是一件非常享受的事情,因为他的头脑似乎特别清晰,不把东西给弄乱。而且他用的编辑器正是我喜欢的 Emacs,几十年的编程经验让他真正的把代码“玩弄于股掌之间”,让我觉得非常意犹未尽。

成功设置 Crontab

前天写了个程序用来生成一个静态的 twitter timeline 页面,但最后一步没有完成,也就是设置 crontab 让这个程序隔一段时间执行一次。否则需要我手动登陆服务器来运行程序就太蠢了。

过去我用过 crontab,但次数不多,而且这种东西都是设置一下就不再碰的,所以相关的东西我早就忘记了。而且我印象里也没有设置过需要调用第三方库的程序,因此周一的时候就配置失败了。

过去我尝试 crontab 的时候,系统会把程序的输出结果发到我的邮箱里。这次却一直没有动静。我怀疑过是不是系统本身的问题,但安装系统的时候我都是走的标准流程,crontab 相关的东西碰都没碰。但为什么一直收不到邮件让我非常费解。

后来我考虑到是不是邮件被发送到服务器本地去了。于是去了我的 Maildir 目录下看看,果然几封邮件都在这里。这让我比较奇怪,我设置的 Exim 4 应该运作正常才对,我的服务器上的 WordPress 程序就可以正常发送电子邮件。后来看了一下收件人地址,发现是 liufeng@li413-79.members.linode.com,这或许就是问题,看来有那个相关的地方我没有设置好。

看了一下邮件的内容,果然说是找不到 twitter gem,看来运行的时候 crontab 找不到 RVM 安装的东西。搜索了一下,经过几次尝试后,发现这篇文章里讲的东西十分有用。文章中的方法是通过运行 bash 读取相关的变量设置,然后像普通执行程序时一样运行这个程序。评论中有人反对这种方法,原因是 crontab 的特点之一就是不登陆而运行程序,这个方法和宗旨不符。后来我发现 RVM 自己也提供了给 crontab 调用的 wrapper,但我测试后不成功。于是还是使用了运行 bash 的方法。

目前这个程序基本上完备了。或许有工夫有心情的时候我会写个 css 美化一下页面,毕竟我看 Rails 里也用上了 SCSS,我想学一下。然后看看能不能提取出一个模版,把模版写在主程序里面挺难看的,也不符合风格。

生成 Twitter 静态网页

我从 2009 年就想写一个程序,把我的 Twitter 记录生成为静态的网页,放在我的服务器上,可以让墙内的人浏览。这样,在国内的父母也可以像 Twitter 被封锁前那样通过我的 Twitter 来了解我的生活情况。

当时我完成了一个小程序,但仅仅是做实验用的,有相当多的小问题。当时用的是 twitter4r 库,很多东西都不大成熟,用它写程序挺麻烦的。当时也遇到了各种问题,都在上面的文章中描述过。后来的代码总结在这篇文章里

最近我看了一些关于 Rails 的文档,写了一些程序,受到了一些启发,于是觉得可以重新写一写这个程序了。现在很多东西也变了,有了 twitter 库,获得记录的方法也更方便了。我如今也不再执着于把所有的 tweets 都保存下来了。另外,我对于数据库方面的了解更多,所以没有干巴巴的用 sqlite 接口来写 SQL,而是用了 Sequel 库,在本地用 Sqlite 3 调试,在服务器上就用 MySQL。结果程序很快就出来了,在纸上做设计,把要做的步骤考虑清楚了之后,很容易的就完成了代码。当中遇到的困难之一是对 Ruby 的不熟悉,很多东西我都需要查找例子,这是练习不足的原因。困难之二就是在 Sequel 的文档搜索信息费了我很多功夫。很多东西都不能想当然,我需要摸索着试验。比如说查看一条 tweet 是不是已经在数据库中有了,只要找找有没有相同的 id 就可以了,这个操作就让我费了很长时间来试验才知道正确的用法。

我过去从来没有写过 MySQL 程序的经验,因此在服务器方面也遇到了问题。首先是 MySQL 本身的启动问题,这个放在下一篇文章中专门谈,其次是安装 mysql 的 gem 时的问题,系统在哦年时提示:

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

只是说缺少依赖,但并没有说具体少什么。后来我找到这篇文章,知道了原因,安装了 libmysql-ruby 和 libmysqlclient-dev 库之后就没问题了。

最后是让程序自动运行,我用 crontab 完成。但我平时很少用到这个,因此从网上找了配置的写法,让它每 12 小时运行一次,但现在还不知道我的配置写的是否正确,等到了凌晨的时候看看运行情况。

最后,程序代码在我的 Github 中:link。生成的页面在这里这里这里,我没怎么做美化,毕竟我不擅长这个,等有时间再看看。

Ruby学习

programming-ruby五个月的假期基本上快过去了。在假期中一直想对自己的技术做一下突破,一直想学点东西。针对自己的时间条件考察了一下,当初把目标定位在Ruby上。

我第一次知道Ruby是在一次如厕中在手中用来消遣的《程序员合订本》里看到的。哪一年已经忘了,那时一个小系列的文章,介绍了Ruby这一语言的语法等等。当时我看了一下,感觉就是把对象做的很足的脚本语言,没有什么稀奇的,还是日本人发明的,估计不会有多大作为,因为那时感觉Perl、Python已经把脚本语言搞的快饱和了,虽然那时Python的应用也远不如现在。那时还没有Rails,要么就是有了但国内还没听说过,因此那时Ruby也不如近年来这么火。于是我也没有多在意。

后来就是听说了Rails,但更多的方面是Ruby本身吸引了我。虽然我那时候没有系统的读过Ruby的书,也没有觉得有什么非要学Ruby的必要。毕竟它的语法和脚本语言类似,我也不觉得学起来会很难。

真正激起我学Ruby的兴趣的是在2007年圣诞节的时候从pluskid的blog上看到了RubyConf2007的视频下载。当时正在寒假中,没什么事情做,这些视频也很不错,于是我就用Python写了一个脚本,把高清的视频都下载下来看。那些视频看的我很激动,给我的最大冲击倒不是演讲的内容,而是这样一个活跃的社区。看了几个视频后,我不禁仰天长叹:“为什么在Perl和Python领域没有这样的conference视频可以看呢?”因此从那时,我就对Ruby的社区印象特别深刻。

现在想起来,这和语言以及语言的发明者的特色性格有一定关系的。Larry崇尚自由散漫,而且Perl5语言在这几年已经熟透了,因此有一个CPAN收集大家的模块就OK了。散漫的社区的公开技术讨论就不多了。Python是在近几年才开始流行的,但我看过的寥寥几个关于Python的视频,都是Guido在Google讲的。Python的社区也跟语言的语法一样,很稳重,不怎么活跃。Ruby则更年轻一些。另一个角度上,语言的扩展上来看,似乎也有这方面的体现。Python没有流行的模块集中管理工具,下载下来的模块,要么手工拷贝,要么运行模块自带的setup.py。Perl的CPAN shell则好了一些,但相对于Ruby的Gem来说就落后、麻烦多了。很明显,从Python到Perl再到Ruby,它们的模块管理工具是从松散到集中发展的。我觉得这也在一方面体现了社区的紧密程度。

后来我在上《面向对象》这门课中,老师除了用Java和C++作为讲解对象外,还讲了Ruby中的对象。这时我也发现,在加拿大的人们,对于Ruby似乎比Python更热衷一些。我周围的同学中还没有遇到过平时用Python来解决问题的,多数是用Ruby。而老师们也相对于Python更愿意用Ruby来作为用例来讲解课程。

因此在这个假期中,我着重在看《Programming Ruby》。英文版为主,中文版辅助。看了一点新东西,就用来把过去的一些实际例子用Ruby来重写一遍。对于此类图书,我更愿意在床上看,而不是在计算机上看电子版。之前的文章我也写过不打算买纸质图书了,因此也没买这本书。其实就算买,我也不是很想买这种看一遍就OK的语言类图书。

说道语言类书籍,除了过去买的有用的和没有用的C/C++/Java等书,在脚本语言中我一共买过三本──《Learning Perl中文版(第二版)》、《Programming Perl中文版》和《Python 2.1宝典》。这样的顺序也是我对这三本书的评价等级:第一本是最爱;第二本限于我的水平还没有完全利用;第三本对我基本上没有用。《Learning Perl》是我看过的最好的讲解编程语言的书──风趣、好用、印象深刻。当初买这本书是一个意外,那时我看了一篇对与Perl的介绍,其中书籍部分自然首推《Programming Perl》,然后是《Learning Perl》。那时还沉浸于“高大全”思想的我自然就去书店搜索《Programming Perl》,结果没有,只好退而求其次,买了《Learning Perl》这本。当时看到薄薄的一本还不大想买,觉得是不是不够用的。结果从前言开始看就无法收拾,不管手中有没有计算机来实践,我总能看得津津有味,我至今都觉得我的Perl知识都是从这本书上来的。后来我一直惦记着那篇介绍Perl的文章中说《Programming Perl》多么精彩,于是就去书店订了这本书,请书店专门为我进这门一本。后来拿到手上看,觉得也不过尔尔。而那本《Python 2.1宝典》是我想学Python的时候买的。那时候Python的权威资料不多,国内也没有基本O’Reilly的书籍,于是我就找了当时能找到的最好的来看。后来也没有什么感觉。最后我的Python是在加拿大的时候看《Dive into Python》电子版学会的,那本书真是不错。现在我因为对买了后看不上的书比较恐惧,因此没有买Ruby图书的念头,尽管《Programming Ruby》人人都说好。

这种学习开始时感觉不错,但后来还是遇到了瓶颈,和我学习Python的时候如出一辙。当时我学Python的时候,总觉得学不下去,远没有当初看《Learning Perl》时的那股劲头。后来感觉是因为对Perl用熟了后,总是用Perl的思想来体会Python,自然学的慢。后来看《Dive into Python》的时候也是强逼着自己把Perl的思想压下去,才慢慢的看下去的。现在似乎是同时有Perl和Python的两种思想来影响我学Ruby。这样的结果是Ruby的语法学起来没有难度,而Ruby的思想则无法接受。现在我用起Ruby来总是觉得别扭,就是这样。

至于Ruby的语言结构,我觉得和Python有的一拼。如果Python是拘谨的,那我觉得Perl和Ruby是各自的在自由散漫上的两个方向,当然Perl走的更远一些。虽然Ruby有借鉴Perl的语法,但用Ruby更容易写出严格缩进的、配对的代码来。Ruby的复杂在于语法的复杂,块啊、元编程之类的总让我有些困惑,必须打起精神来才能看懂;而Perl则纯是自由、没有规矩的代码书写造成的,但是语法与C非常相向,因此一旦把代码排版好了,理解上是很容易的。

在前几天中,我一直看《Programming Ruby》,还比较不错。但还没有构筑好Ruby的思想。同时,我也希望能有一本类似《Learning Perl》那样的书,这样学习起来会更容易一些。我觉得80/20规则在Ruby上一样适用──“你日常中遇到的80%的问题用语言的20%就能解决”。《Learning Perl》自己就说到它的面向就是这20%。现在Ruby的书也不少了,我还不知道有哪本书可以胜任。