Dirty Approach正反两例(1)

来源:互联网 发布:程序员语言 编辑:程序博客网 时间:2024/06/05 06:32

前两天跟霍炬聊起软件开发,谈到所谓Dirty but Fast的做法,即为了更快完成某种功能、不惜使用“不太优雅”的模式(非Design Pattern)或代码实现。霍炬给这种方式起了一个英文短语,叫做dirty case;从遣词上看,dirty but fast approach更为贴切,不过dbfa太长,而且有时也并非为了“快”而dirty,而是为了堵住常规方法很难堵住的漏洞,例如霍炬写到的Unix体系中root远程登录的case。所以,不妨还是叫做dirty case,或者dirty approach。

编写代码,如文艺创作一般,也是有境界高下的。没入门的自然没办法,刚入门的用笨办法,提高一些后开始用正规的办法,高手敢于使用脏办法,而大师则已是无法即有法、“从心所欲而不逾矩”了。我不是高手,更不是大师,不过我懒,所以常常会选择不太好(dirty)但可能有效的实现方式。凡事不可太过,过犹不及,如果用得不是地方,dirty but fast恐怕就要变成dirty and slow了。下面两个例子,一正一反,讲述前不久在开发Blog电子报功能时发生的故事。

例一:反例

Blog电子报,有点类似blogline那样的rss聚合服务,但更偏向于“编辑自己的报纸,聚合给别人看”。在存储结构上,blog_Groups用来存放电子报列表,blog_Group_RssUrl存放Rss地址列表,blog_Group_GroupRss存放Group和RssUrl之间的多对多关系,而blog_Group_RssContent则存放Rss中每篇文章的条目信息(标题,作者,摘要,链接等)。

在考虑电子报的分页体系时,一时懒劲发作,觉得做分页查询太麻烦,想找一个投机取巧的办法。一琢磨,电子报->报纸->日报->日期,按日期阅读估计成!分页时不用考虑太多东西,选取特定日期的条目出来就好。于是吭哧吭哧搞半天,把按日期阅读的功能做好了。

上线测试后,发现两个问题,一个问题能解决,另一个问题没法解决。先说能解决的那个:选定日期没有文章。电子报是RSS的聚合,如果一份电子报所有RSS作者在某天都没有写文章,结果就是当天电子报页面空白。这实在有点郁闷。于是我又想了一个办法——找有文章的最近一天,显示这一天的文章列表。一阵好干,这个特性也实现了。虽然感觉怪怪的(类似:输入http://blog.csdn.net/group/experts/20050403.aspx却出来4月4日的文章),不过好歹不是空白一片。

第二个问题紧跟着跳出来。当天没文章好办,到有文章的最近一天就行,如果当天文章量很少怎么办呢?例如,只有一篇文章……惨了,页面上还是大片空白。其实页面有空白不是最要紧的,要紧的是这种方式让读者很不爽!我没有想清楚电子报和日报之间的相同和不同之处。关键在于:日报虽然是按天出版,不过它的内容量是一定的,文章写作日期可以不一样,但出版的时候,一定是同时出来。“保证在版面上有定量内容”就是关键。而“按日期导航”违反了这个原则。

当然,按日期导航也有用处,毕竟增加了一个入口点,且为“找特定某天的文章”提供可能。最后我还是保留了这种导航方式,只是将它作为第二导航方式,第一方式还是采用传统的每页固定数量列表方式。

 

例二:正例

电子报是一种RSS聚合服务,“抓取外部RSS、解析和保存内容”自然就是其中最基本的特性。当RSS数量变得庞大起来是,效率就会有问题。这里不说多线程、分布式,假设硬件带宽资源有限,怎么解决效率问题?

答案就是“尽量减少抓取、解析、保存次数”。矛盾之处在于,当RSS地址越多,抓取程序就应该运行越频繁,这样才能保证“及时更新”。试问读者,你会怎么处理?我的处理方法是:对RSS最后更新日期、和文章URL/更新日期进行判断。

对于每个RSS,有两个关键时间点:1、整个RSS的最后更新时间 2、每篇文章的最后更新时间。至于HTTP返回的“Not Modified”不能作为关键要素,除非是第一次取这个RSS。

在第一次取RSS时,我会把LastModified(RSS规范中的一个属性)记入该RSS在数据库中的条目信息,下次轮到取这个RSS的时候,把保存的LastModified和远程RSS的对应字段进行对比,如果RemoteRss.LastModified>LocalRssInfo.LastModified,才会解析RSS。RSS是XML格式,做一次解析虽然耗时不多,但加起来就可观了。

请注意上段中的“轮到”,读者应该已经猜到,我不会每次都把所有RSS地址从数据库拿出来、到远程抓一遍。网络上一个roundtrip成本太高了。所以我用一种dirty的算法,来判断程序本次运行应该抓哪些RSS。现在隆重介绍这种“算法”——

1、在解析一个RSS时,记录每篇文章之间的发表时间间隔,假设是x1,x2,x3……xn
2、在解析整个RSS完成后,求x1,x2,x3……xn的平均值,假设是y
3、RemoteRss.LastModified+y是下次新文章可能出现的日期

细节不作描述,原因不作解释,道理很简单,读者可以自己研究。也许有读者会提出,数据库中保存的每个RSS的所有文章发表日期间隔的平均值,是不是该更接近距离下次更新文章的日期?其实似是而非,因为Blog发表文章,未见得会长期维持稳定发表量,不同时期内的发表量会有变化。所以,最近15篇文章的发表间隔平均值,比较有可能接近距离下次发文章的日期。

当然,还有一种情况,就是下次发表文章的日期大大提前了。事属正常,不过它似乎违反了我们的规则。发生这种事时,这个可怜的RSS就有可能轮不上被及时抓取。漏抓结果可能很严重——因为如果一篇文章信息从RSS中消失,可能你就再也无法通过RSS得到它了。在系统资源有限的情况下,可以安排一些随机的“幸运RSS”,无论是否“当值”,都去尝试抓一下。

(待续)

原创粉丝点击