08年07月22 - 21:41 分类: 技术沙龙
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/226
今天因为去银行做培训,结束之后闲来无事,又不能上网,于是在笔记本上把下载已久却一直无暇钻研的Python3.0beta1安装看了一看。
最让我眼前一亮的是Python 3.0的帮助文档。与Python 2的相比可以算是脱胎换骨了。在Library Reference中,结构被组织得更加清晰,非常容易阅读。再加上新增加的例子代码,我想对学习和使用会有相当大的帮助。我特地查阅了re(正则表达式)一章。以前那种迷糊的感受一扫而空。而从头至尾大致翻阅之后,我又发现了很多以前不知道的东西。
非常常用的print使用方法做了较大的调整。现在的print完完全全是一个函数而不像以前那样看起来像个命令。实际使用中,在命令行下输入感觉“不爽”了很多。然而增加的sep、end、file参数对程序的开发是有很大帮助的。
字符串处理增加了format函数,是对以前%格式化方法的一个增强。这种增强我觉得是非常方便的,比如对对象属性的引用等等。但是很显然这种增强针对的是程序开发而非命令行。
内部的字符串完全以Unicode做处理,并且string和bytes不再兼容。这个改变造成了我的一些程序在向wb方式打开的文件中写字符串时遇到了麻烦。
一些库被增强了,一些库被取消了。一些库中的函数或方法被改变了。这些改变造成了我相当多的程序无法在新版Python中运行通过。看来程序的迁移将不会是一个小动作。
还有很多列在What's New中的改进及增强还没有来得及试验,不过从描述来看,都是些很好的改变。
总的来说,我觉得Python 3.0做了一些非常好的增强,这些增强是很值得期待的。然而我的感觉是Python 3.0有了一些蜕变,它不再满足于做一个“脚本语言”,它希望变成一个真正的“开发语言”。从对命令行便利性方面的削弱,以及对大规模程序方面的增强就可以明显看得出来。然而我最早认识Python,是作为一门“方便的脚本语言”的。我平时在python的交互模式下的应用也不算少。因此,它的这种改动,是好是坏,我还真的难以下定论。另外,一些不向下兼容的改动,造成了代码迁移方面的很大工作量,虽然有2.6版做过渡,我仍然觉得这是很糟糕的体验。
只能在充满矛盾的心情中,期待Python 3.0正式版的到来。
08年07月17 - 10:27 分类: 技术沙龙
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/225
我的工作电脑,每天开机的时候要加载一大堆的东西,速度很慢。本来想精简一下,可是想来想去,没什么可以精简的:
- 邮件得收吧,Foxmail不能省。
- 工作得联系吧,MSN不能省。(当然,顺大便把gtalk也启动了,这个某种意义上对我而言更重要)
- Total Commander,已经习惯了,不能没有它,所以一定要开的。
- Firefox……
- 笔记本自带的启动程序,不想去动它了
- 工作需要的很多服务...
所以最后还是决定使用bblean,替换explorer。别说,用bblean之后启动速度的确是提高了相当多。不过有了一些新的不方便:
- 以前TaskBar的右键菜单没有了,于是呼不出任务管理器
- 没有Quick Launch栏。我的很多启动方式都是放在Quick Launch里的
- 最大化窗口会被bbSystemBar遮住
- 笔记本的音量条件按键失效
这几个问题还是挺影响使用的。所以一度又曾经放弃过bblean,但在忍受了几天explorer的龟速之后,我还是决定重新使用bblean,并且解决掉这些问题。
Google一番之后,终于还是都找到了解决之道。
任务管理器的问题其实很容易解决——只是我原先没有想到而已。bbLean自己有一个菜单,可以在bbSystembar的任意位置右键呼出,这个菜单是可以编辑的。只要在上面加入任务管理器的项就可以了。
我现在是使用Process Explorer代替Task Manager的,所以就配置成:
[nop]
[exec] (TaskManager) {"d:\Program Files\ProcessExplorer\procexp.exe"}
Quick Launch的问题,我增加了bbIconBox插件,它可以在桌面上增加指定目录的菜单面板。我增加了一个QuickLaunch的面板,放在侧边栏,自动隐藏,需要的时候鼠标晃过去就可以操作了。另外我还装了一个Lauchy软件,可以热键呼出之后输入几个字母就可以启动程序,避免打开开始菜单,更加方便了。我使用Launchy的原因是因为它是自动扫描软件项目而不需要手工配置,尤其适合我这样的懒人。呵呵
最大化窗口的问题原来是设置问题,只要将blackbox.rc里的session.screen0.fullMaximization: 由true改成false就行了
音量按键的问题有点麻烦,后来发现很多人都是装了一个叫做bbkeyhook的插件解决了。于是去找了一个,装上,果然OK了。
我现在的bblean使用了bbKeys、bbSystemBar、bbIconBox和bbKeyHook,去掉了bbSkin。我并不是想搞什么美化,只是想加快启动速度而已,所以操作习惯还是尽量跟Windows原来的接近。
08年07月15 - 09:29 分类: 梦中呓语
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/224
忙了这么久,终于感觉黎明的到来。
正好群里的项目也重新激活了。
Fighting Fighting!
08年07月04 - 23:24 分类: 梦中呓语
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/223
因为小虫的缘故,找了三字经大概看了一看。顿时汗如雨下。
虽然说三字经是一本国学入门书,从内容上看也确实如此。但我居然也还有好多典故解不出来。
枉我还号称钻研过历史。无地自容ing。
08年07月02 - 12:43 分类: default
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/222
最近因为工作忙已经错过了太多值得记录的事情。但如果把这件事也遗漏,就未免太说不过去了。
奥运新项目:俯卧撑。
08年06月23 - 12:07 分类: 梦中呓语
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/221
今天早晨坐公车上班,下车的时候下意识的摸了一下口袋,钱包没了。
共计损失现金若干,银行卡若干,可报销的发票若干,其他不记名代币卡若干,公司证件一张,饭卡一张,身份证一张,小虫照片一张。
现金损失也就算了,证件和卡后续的手续让我感觉很头大。
心情沮丧。
其实平时坐车已经很小心了,今天不知怎么就大意了。
唉。
08年06月16 - 14:52 分类: 技术沙龙
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/220
最近一直比较忙,很久没有更新blog了。
今天收到一封信,问了我一个问题:
关于你提出的几点:1. 单元测试是一种测试,它不是代码的一部分;2. 单元测试是最低层级的测试,它只保证函数的可靠性,不保证其它;3. 单元测试应该能保证每一个函数的可靠性。
当今前端测试的问题在于仅仅对函数的输出进行验证并不能很好的确认其行为。因为js还需要对DOM进行操作,需要对CSS进行操作,IE,FF显示效果不一致等等。使得前端开发程序员不得不人肉进行测试,查看程序是否符合预期的显示效果。你们认为如何才能提高前端单元测试的有效性呢?
说实话这个问题是我刚刚接触单元测试的时候,也一直被困扰的一个问题,那就是,GUI界面如何单元测试?我记得在几年前,我还就这个问题特地咨询过gigix,当时他告诉我说“测试能测试的”。但是当时我对单元测试一知半解的时候,对于这个答案也是不甚了了。
今天我不敢说对这个问题已经理解得非常透彻了,但是我想把我的想法说出来,大家讨论一下。
在解释这个问题之前,我想重复一下我对单元测试的理解:单元测试是最底层的测试,它只保证函数的可靠性。
但是这里有一个重要的概念,我们需要进一步的说两句:什么叫“函数”?
从语法而言,函数就是语言概念上的一个语句块,这个语句块接收0个至多个输入,产生0个至多个输出。但是,所有的语言都没有规定函数需要有怎样的“语义”。于是,我们也不能在解释器或编译器层面阻止一个“坏函数”的诞生。例如,下面这两个函数,如何测试?
x = 1;
function a()
{
global x = x+1;
if (x < 10)
setTimer(100, b);
}
function b()
{
feed = time.now();
diff = random(feed).getInteger(10);
global x = x - diff;
}
函数a严重依赖于函数b,以及平台相关的定时器和一个状态未知的全局变量x。而函数b也依赖于平台相关的函数time和一个状态未知的全局变量x。这样两个函数要进行测试,难度是非常高的。简单的说,a几乎可以认为是无法测试的,因为它并不是一个我们所谓的“输入-处理-输出”函数,而是依赖于定时器这样的平台相关操作,定时器这种东西是很难模拟的,就算模拟出来意义也不大,因为真实的定时器几乎可以肯定不会跟模拟的定时器有相同的表现——而这个表现,正是我们编写这个函数的目的。函数b倒是可以测试,但你必须事先为它模拟好一个时间函数(类),一个随机数函数(类),和一个确定状态的全局变量x——这些工作在一些语言里可以做到但要付出很大的代价,在另一些语言里几乎可以说是不可能的任务。
那么,接下来的工作倒也变得很简单了:我们就要做一个价值上的衡量,我花很多时间精力去实现这些测试基础框架(对了,这些基础框架也需要测试),跟我整个系统的测试工作本身相比到底值不值?
其实在大部分时候,这个答案是“不值”。如果为了一个系统的单元测试要做如此多的工作,其难度不亚于开发一个新系统,那我们当然会选择不测试。
上面的例子说明了两点:1、函数并不是天然可测试的;2、不是所有的“函数”都是需要测试的。
等一下,我记得你说过“单元测试必须保证每一个函数的可靠性”这样的话?
对。所以我们必须明确一下单元测试里函数的定义,它跟语言上的函数稍有不同,实际上,是多了一段语义限制:函数,指的是接收0个至多个输入,进行逻辑处理,并产生0个至多个输出的代码块,它的输出受且仅受输入的影响。
符合这种定义的函数,是“可测试函数”,测试它们不需要花额外的精力。不符合这种定义的函数,则是“不可测试函数”。不可测试函数又分两种,一种是无法测试的,比如系统所需的回调函数(尤其是线程、定时器之类的回调)、随机函数等等,它的输出严重依赖于系统当时的状态,而这种状态难以复现,所以对他们的测试可以说是没有任何意义的。另一种是难以测试的,它也是输入-处理-输出这样的,但它的输出除了依赖于输入之外,还依赖于系统的状态,但这种状态是可以复现的。
对于可测试函数,我们没什么好说的,单元测试教材上这样的例子比比皆是。但我们必须说,现实远没有这样理想化,完全不依赖外部环境的函数,非常少见。难道说我们就没有办法做单元测试了不成?
当然也不是这样。但是正如我上面提到,函数并不是天然可测试的。随随便便的拿一个系统就要对它做单元测试,要么是不可能的,要么是难度很大的。为了让一个系统可测试,可单元测试,我们还是要做一些工作的。
最重要的一件工作,当然就是让函数尽可能变成可测试的,再不济也应该是难以测试的,而尽量减少无法测试的函数。这些无法测试的函数,留作功能测试去测(使用人工手段或者其他的测试手段)。
举个例子来说,按上面的定义,线程回调函数是无法测试的,因为它严重依赖调用时的时间点和当时系统状态。如果你把所有的业务逻辑都直接写在回调函数中,那么整个业务逻辑就变成了无法测试的。但是这些逻辑里肯定是有一些是可以剥离出来作为固定输入固定输出的逻辑,那么就把它剥离出来,这样,至少这一部分就变成可测试了,这个经过测试的部分就可以做到一定的保障,减少上一层功能测试的压力。
第二件工作,就是做好Mock Object。纯可测试的函数是很少见的,绝大部分函数都会像上面的那个函数b一样,多多少少要用到一些基础设施,比如时间、随机数、数据库、网络等,这些东西在真实环境中是不稳定的,我们需要构造一个“虚假的”环境,为测试提供一个稳定的基础(稳定的基础当然包括“稳定出错”的情况),这样才可以为测试提供一个稳定结果。这个Mock的工作通常也是很大的,有很多东西需要虚拟,如果是一个小的系统,我们不值得去构造这样一个虚拟环境,可以尽量把其中环境依赖的部分剥离出来,对环境独立的部分单独测试,对环境依赖的部分用人工测试。然而在一个大的系统中,环境依赖部分太多,人工测试变得不可能,这时我们还是有必要认真做一下Mock这个工作的。
当然还有其他的一些工作,包括对软件过程的制定,项目配置,都会随着单元测试的引入而需要做变动,但这不是我们这次讨论的重点,暂且忽略。
说了这么多,总结一下:像显示效果这样的测试,靠单元测试是做不到的,只能用人工或者其他测试手段。但是如果你的系统是按照易于测试的原则实现的话,可以测试那些能够测试的部分,这样会给你的人工测试减轻很多压力,因为很多东西通过单元测试之后,人工测试就可以认为他们一定是正确的了。这就是我前一篇文章所提到的“分层测试”原则。
另外,测试并不是万能良药,对任何系统都可以简单而方便的实施。为了做到易于测试,还是需要在前期(如需求阶段、编码阶段)做一番努力的。
08年06月08 - 00:30 分类: 技术沙龙
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/219
Simpblog,一个用Pylons搭建的简易blog系统。初步完成了。
使用的框架是Pylons+SQLAlchemy+SQLite3。
前台使用Mako渲染,使用了Jonas John创作的CSS风格模版。
管理界面使用AuthKit做权限验证。
没有使用可视化的编辑器,使用了CreoleWiki语法,并使用MoinMoin的Creole Wiki分析脚本及HTML generator产生对应的HTML代码。
RSS使用PyRSS2Gen生成。
目前该系统还在内部测试阶段,如果发现bug,欢迎及时回报。
------------这是胡言乱语的分割线-------------
Pylons的开发还算是很快捷的,我从打算到开始动手到测试不过几天的时间。当然这跟SimpBlog的模型简单也有关系。
最初的设想是做一个庞大的框架,可是真正动手的时候,想法变了很多,我希望这个东西是能够尽快出来然后边测试边修改边增强功能,如果实现太复杂太庞大,可能在我激情消退之前都还出不来。于是就尽量快的写了一个。说它是原型也好,如果真的投入使用,也是可以不断调整的──事实上在开发过程中数据模型和想法已经做了很多改变──改变并不是坏事,我觉得。
这次在开发中尝试了AuthKit。发现AuthKit并没有想像中的复杂。如果使用得当,是可以轻易的实现很强大的授权和验证工作的。我喜欢。
Pylons的部署和开发,真是两个完全不同的概念。为了简化部署动作,我在服务器端也安装了完整的Pylons环境及其它支撑库。然后通过svn直接check代码到目标路径,用一个脚本自动运行。这样做的确是省了很多事,但令我意想不到的是,使用lighttpd的proxy之后,由于不是根目录,我的很多代码出现了问题。
首先需要解决的是一个共性问题:如何将带路径的url自动映射。幸好Pylons使用的部署工具PasteDeploy已经考虑到了这个问题。只要在development,ini的[app:main]小节增加
filter-with=proxy-prefix
并增加[filter:proxy-prefix]小节:
use = egg:PasteDeploy#prefix
prefix = /testblog
就可以了。
但是不久就发现还是有很多路径错误,原来Pylons里所有的路径都必须经由h.url_for封装,才能被prefix过滤器处理,直接写的URL是不会被处理的。于是又将模版中所有路径改写成h.url_for形式的。终于大功告成。
08年06月04 - 08:45 分类: 时事乱评
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/218
对于19年前的事,真的不想多说什么。是非对错后人评吧。
写出来只是提醒自己别忘记这件事的存在。
08年06月02 - 23:45 分类: 技术沙龙
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。转载请保留本声明,并注明原作者:令狐虫及本文原始出处:
http://ch-linghu.3322.org/blog/entry/217
今天因为genshi的擅自修改代码的问题,以及搜索资料后发现的令人吃惊的渲染速度,我决定关注一下mako。
我想启动一个小项目:写一个简单的blog系统,来尝试一下mako模版。
根据我自己对现有blog的使用来看,很多功能其实我是不用的,比如上传文件/照片的功能,tag功能,等等。而有些功能我并不满意,比如我在群里不止一次抱怨过的编辑器。
所以我想借这次机会,实现一个我心目中的单人blog。
- 它要很简单,只有写blog的功能,其它什么也没有──我不需要一个完整的CMS,只要一个能写文字的东东。其它的东西,我会将它们分布到我认为合适的服务上──他们更专业。
- 它要有足够的扩展性,当我突然想需要一个功能的时候,我不需要到处折腾,只要修改或增加一点儿代码就能做到。
- 它要足够快,起码不能比现在的慢──其实我也是想看看pylons+mako到底能快到什么地步。
- 它要有一个对我来说好用的编辑器:不需要写一堆的<p></p>,但我想加HTML tag的时候,请给我这样的自由而不需要额外的工作。
- 支持回复并有效阻止垃圾评论。
- 纯文本,没有数据库。
当然,目前而言这肯定是一个试验性质的项目,我仅仅考虑自己的需求,而不会考虑任何产品化方面的易用性需求。但是,不排除如果真的还不错的话,我也许真的会用它替换掉现在这个,并且好好的产品化它。