SVN源代码管理规范

SVN源代码管理规范   【资料下载】 1. SVN 版本库结构构建 在大多数人眼中的Subversion,就是那个在代码里被叫做“Trunk”的东西。其实Subversion包含了更多的内容! 为了让你能够更加充分体会到Subversion的好处,本文将讨论如何搭建你的版本库结构。 正如你之前在Subversion的相关文章中看到的那样,Subversion最基本的结构由三个路径组成:branches,tag和trunk。 每个路径在Subversion里都可以单独签出。 1.1 Trunk 任何时候Trunk里包含的都是最新的开发代码。 这里的代码将会工作到你的下一个主要发布版本。 据我所见,几乎常常人们只使用trunk来存放他们的代码。发放了一个版本后继续在其上进行下一版开发。这不好,无论是对你还是你的产品。 Trunk应该只被用来开发将会成为你的下一个重要版本的代码。 不要给trunk加上版本号和发布名称。 仅需要保证trunk在任何时候都处于“开发模式”。 例子: https://svn.example.com/svnroot/project/trunk 1.2 Branches 这里有几种不同类型的分支。这里我会告诉你一些常见的类型。在branches的目录里,你可以为更多具体的目标创建路径,像即将发行版本。 正如我的文章“article on releasing software from Subversion”里讨论的那样,brahches路径包含了trunk在不同发展阶段的副本。 1.2.1 Release Branches 我们已经见过了 RB-x.x release branches。当trunk达到准备发布的阶段时(或者你想冻结新特色的添加时),你应该创建一个release branches。 Release branches只是你当前trunk的一个副本。 这个branches可以被单独的签出你也可以启动branches和基于此版本的项目。你还可以使用此分支在测试期间修复Bug。 这种方式能够保证trunk继续开发,而不会被发布某个具体的版本所干扰。 因此当你准备发布一个新版本时,这样不会影响你trunk增加新的功能。 1.2.2 Bug fix branches 分支也可以用于处理trunk或release branches里发现的严重的Bug。这些Bug很复杂,你不能在一次提交时就修复他们。因此为了集中精力修正此错误,你应该为此问题创建一个新的分支。这样就不会影响trunk 和 release branches的继续进行,并且你也不会因为发现新的Bug 和测试而干扰此Bug 的修复。 Bug 修复分支的命名通常遵循下列方式:使用你的缺陷管理系统分配给此Bug的ID。通常这是一个数字。如:Bug-3391。 当然,你也可以象其它分支一样访问你的Bug分支。 1.2.3 Experimental branches 有时你想将某个新技术引进项目。这很好,但是你当然不想赌上你的整个项目。想象一下,你想把你的Web程序从PHP4改为PHP5。你要花多少时间?在这期间你的trunk停止使用?直到你把所有到PHP5的转换做完! 这是实验,可能PHP5就像彩虹的另一端一样离你的程序太远了,你应该给他创建一个分支。 你可以在分支里进行更改,如果失败了,你在当前分支仍然有PHP4的代码。 如果失败了,实验分支可以抛弃。 如果成功,你可以很容易的将其合并到trunk并继续你的新技术。 实验分支命名遵循在面原则:为其名字加上前缀“TRY-”。 1.3 Tags 标签就像分支一样备份你的代码。 但是 Tag不被用来开发,他们只是用来标记你代码的状态。 1.3.1 Release tags Release Tags 标记你版本发布点的代码。 Release Tag 永远是相应发布分支的副本。 Release Tag命名规则:“REL-”前缀加上版本号。 1.3.2 Bug fix PRE and POST tags 当你创建了一个Bug fix分支,你想标记代码在BugFix之前和之后的状态。 这样你就很容易的引用你所做的更改,合并到trunk或Release branches。 命名规则:   “PRE-”加上Bug ID; “POST-”加上Bug ID。 2. SVN使用规范 先更新,再提交 SVN更新的原则是要随时更新,随时提交。当完成了一个小功能,能够通过编译并且自己测试之后,谨慎地提交。 如果在修改的期间别人也更改了svn的对应文件,那么commit就可能会失败。如果别人和自 己更改的是同一个文件,那么update时会自动进行合并,如果修改的是同一行,那么合并时会产生冲突,这种情况就需要同之前的开发人员联系,两个人一起协商解决冲突,解决冲突之后,需要两人一起测试保证解决冲突之后,程序不会影响其他功能。 在更新时注意所更新文件的列表,如果提交过程中产生了更新,则也是需要重新编译并且完成自己的一些必要测试,再进行提交。这样既能了解别人修改了哪些文件,同时也能避免SVN合并错误导致代码有错。 多提交 每次提交的间歇尽可能地短,以几个小时的开发工作为宜。例如在更改UI界面的时候,可以每完成一个UI界面的修改或者设计,就提交一次。在开发功能模块的时候,可以每完成一个小细节功能的测试,就提交一次,在修改bug的时候,每修改掉一个bug并且确认修改了这个bug,也就提交一次。我们提倡多提交,也就能多为代码添加上保险。 不要提交不能通过编译的代码 代码在提交之前,首先要确认自己能够在本地编译。如果在代码中使用了第三方类库,要考虑到项目组成员中有些成员可能没有安装相应的第三方类库。项目经理在准备项目工作区域的时候,需要考虑到这样的情况,确保开发小组成员在签出代码之后能够在统一的环境中进行编译。 每次提交必须书写明晰的标注 在一个项目组中使用SVN,如果提交空的标注或者不确切的标注将会让项目组中其他的成员感到很无奈,项目经理无法很清晰的掌握工作进度,无法清晰的把握此次提交的概要信息。在发现错误后也无法准确的定位引起错误的文件。所以,在提交工作时,要填写明晰的标注,能够概要的描述所提交文件的信息,让项目组其他成员在看到标注后不用详细看代码就能了解你所做的修改。 提交时注意不要提交本地自动生成的文件 例如eclipse中的.classpath文件,Windows生成的缩略图Thumbs.db,项目编译生成的临时文件.obj, .class等等。如果项目中没有进行这方面的配置来强行禁止提交这样的文件,请自觉不要提交这样的文件。提交了这样的文件后,别人在更新后就可能与本地的环境冲突从而影响大家的工作。 不要提交自己不明白的代码 代码在提交入SVN之后,你的代码将被项目成员所分享。如果提交了你不明白的代码,你看不懂,别人也看不懂,如果在以后出现了问题将会成为项目质量的隐患。因此在引入任何第三方代码之前,确保你对这个代码有一个很清晰的了解。 慎用锁定功能 在项目中要慎用锁定的功能,在你锁定了一个文件之后别人就无法继续修改提交该文件,虽然可以减少冲突的发生率,但是可能会影响项目组中其他人员的工作。平时只有在编辑那些无法合并的文件(例如图片文件,flash文件等)时,才适当的采用锁定操作。

阅读全文

怎样构建你的版本库

原文:How to structure your repository 地址:http://ariejan.net/2006/11/24/svn-how-to-structure-your-repository/ 你正在阅读的是一篇关于Subversion的文章。 这很好,这意味着你在思考使用版本管理来管理工程的好处。 在大多数人眼中的Subversion,就是那个在代码里被叫做“Trunk”的东西。其实Subversion包含了更多的内容! 为了让你能够更加充分体会到Subversion的好处,本文将讨论如何搭建你的版本库结构。 正如你之前在Subversion的相关文章中看到的那样,Subversion最基本的结构由三个路径组成:branches,tag和trunk。 每个路径在Subversion里都可以单独签出。 Trunk 任何时候Trunk里包含的都是最新的开发代码。 这里的代码将会工作到你的下一个主要发布版本。 据我所见,几乎常常人们只使用trunk来存放他们的代码。发放了一个版本后继续在其上进行下一版开发。这不好,无论是对你还是你的产品。 Trunk应该只被用来开发将会成为你的下一个重要版本的代码。 不要给trunk加上版本号和发布名称。 仅需要保证trunk在任何时候都处于“开发模式”。 例子: https://svn.example.com/svnroot/project/trunk Branches 这里有几种不同类型的分子。这里我会告诉你一些常见的类型。在branches的目录里,你可以为更多具体的目标创建路径,像即将发行版本。 正如我的文章“article on releasing software from Subversion”里讨论的那样,brahches路径包含了trunk在不同发展阶段的副本。 Release Branches 我们已经见过了 RB-x.x release branches。当trunk达到准备发布的阶段时(或者你想冻结新特色的添加时),你应该创建一个release branches。 Release branches只是你当前trunk的一个副本。 这个branches可以被单独的签出你也可以启动branches和基于此版本的项目。你还可以使用此分支在测试期间修复Bug。 这种方式能够保证trunk继续开发,而不会被发布某个具体的版本所干扰。 因此当你准备发布一个新版本时,这样不会影响你trunk增加新的功能。 Bug fix branches 分支也可以用于处理trunk或release branches里发现的严重的Bug。这些Bug很复杂,你不能在一次提交时就修复他们。因此为了集中精力修正此错误,你应该为此问题创建一个新的分支。这样就不会影响trunk 和 release branches的继续进行,并且你也不会因为发现新的Bug 和测试而干扰此Bug 的修复。 Bug 修复分支的命名通常遵循下列方式:使用你的缺陷管理系统分配给此Bug的ID。通常这是一个数字。如:Bug-3391。 当然,你也可以象其它分支一样访问你的Bug分支。 Experimental branches 有时你想将某个新技术引进项目。这很好,但是你当然不想赌上你的整个项目。想象一下,你想把你的Web程序从PHP4改为PHP5。你要花多少时间?在这期间你的trunk停止使用?直到你把所有到PHP5的转换做完! 这是实验,可能PHP5就像彩虹的另一端一样离你的程序太远了,你应该给他创建一个分支。 你可以在分支里进行更改,如果失败了,你在当前分支仍然有PHP4的代码。 如果失败了,实验分支可以抛弃。 如果成功,你可以很容易的将其合并到trunk并继续你的新技术。 实验分支命名遵循在面原则:为其名字加上前缀“TRY-”。 Tags 标签就像分支一样备份你的代码。 但是 Tag不被用来开发,他们只是用来标记你代码的状态。 Release tags Release Tags 标记你版本发布点的代码。 Release Tag 永远是相应发布分支的副本。 Release Tag命名规则:“REL-”前缀加上版本号。 Bug fix PRE and POST tags 当你创建了一个Bug fix分支,你想标记代码在BugFix之前和之后的状态。 这样你就很容易的引用你所做的更改,合并到trunk或Release branches。 命名规则: “PRE-”加上Bug ID; “POST-”加上Bug ID。

阅读全文

获取wp文章或分类的根分类

没有废话,直接上代码 function get_category_parents_ID( $id ) { $parent = &get_category( $id ); if ( is_wp_error( $parent ) ) return $parent; if ( $parent->parent && ( $parent->parent != $parent->term_id ) ) { return get_category_parents_ID( $parent->parent); } return $parent->term_id; } /// function get_post_root_category_ID( $id ) { $category = get_the_category( $id ); if( $category[0]->category_parent == '0' ) { return $category[0]->cat_ID; }else{ return get_category_parents_ID( $category[0]->cat_ID ); } }

阅读全文

com初谈

>>发表于csdn @ 2003年08月29 先请看看下面几个问题: 什么是com ? 什么是com对象? 什么是接口? 先说第一个,com全称是组件对象模型(compoment object model),他是一组规范,是MicroSoft创建的一组二进制和网络标准,用于解决两个组件之间的通信,可以说MicroSoft目前差不多所有的战略都是建于其上,从1993年com 首次被推出,他就注定了MicroSoft的发展的命运…… 什么是com对象 com是面向对象的软件模型,com对象的概念有点类似于C++中对象的概念。在com规范中,没有com对象的严格定义,com组件提供给客户的是以对象形式封装起来的实体,客户与组件交互的实体是com com对象有自己的属性和方法,但这些都被com封装了起来,客户只有通过接口才能对com的方法进行调用,接口是com 什么是接口 上面已经说过了,接口就是com 与外界通信的唯一途径。他的定义是com 下图表了接口和com对象的关系 com组件主要由两部分组成,一部分是接口的定义,另一部分是com对象的实现,在com规范中接口的定义和com 接口的定义 ——接口的定义遵循MIDL,他是MicroSoft针对OSF的DCE(Distributes Computing Enviroment)规范中IDL语言扩展。从上图可以看出,接口就是包含了一组函数的数据结构,他只负责定义函数。在对象创建后,他就是包含了接口指针和一个虚函数表,接口指针指向虚函数表(该函数表就成了一组函数指针的集合),每个函数指针指向“com对象实现”里相应的函数的实现。接口规范并不建立在任何编程语言基础上,任何具有足够数据表达能力的语言,都可以对接口进行描述。 com对象的实现 —— 包含com COM整体模型 根据com规范所建立的应用是基于Client / Server 模型的,一个完整的com应用包括以下几个部分:com服务器,服务器方com库,客户方com com服务器      —— 就是一个容器,此容器用来装所有的com com库  —— 可以看作是容器的管理者,负责从容器中找出相应的com com库    —— 连接员,负责把客户请求传送到服务方,负责客户com com 1. 客户程序通知com库,向com库指出他要调用的com对象的GUID或IID; 2. 客户端com库接受客户要求,向服务器端发送该要求,在客户进程内建立该com DLL(以后客户就同该代理DLL 3. 服务器com库接受请求,从com库中找出com对象,建立该com dll dll与客户端的存根dll 4. 客户程序调用代理dll 5. 代理dll把请求接口、方法、参数、数据,打包列集(marshalling);发送给存根dll 6. 存根dll接收来自代理dll的数据包,散集(Unmarshalling) 7. 组件程序处理数据,返回给存根dll 8. 存根dll列集(marshalling),发送给代理DLL 9. 代理DLL [ 注:对于存根和代理,请关注后续文章 ] com对象的创建 com库是如何创建com com对象的生产基地,每个com对象都有一个相应的类厂。类厂本身也是一个com对象,他支持一个接口IClassFactory,该接口的函数CreateInstance(…)用于构造com com 1. 客户向com库,给出com对象的GUID 2. com库调用CoGetClassObject(...)函数获取com对象的类厂,创建com对象. CoCreateInstance(...)函数,也是通过在其内部调用CoGetClassObject 暂时

阅读全文

C++0x特性:Lambdas,auto, static_assert

[ 引用 ] 系列文章分成三部分: VC2010 中的C++0x特性 Part 1:Lambdas,auto, static_assert VC2010中的C++0x特性 Part 2:右值引用 VC2010中的C++0x特性 Part 3:decltype Microsoft Visual Studio 2010 九月社区技术预览版 (CTP)所带的Visual C++编译器对四个C++0x语言特性提供了支持,也就是 lambdas,auto,static_assert,以及 rvalue references (右值引用,译注:后面不再对这个词进行翻译)。今天,我将详细介绍前三个特性。(很快我将贡献一整篇幅的文章来解释右值引用,仅仅是因为再在这里解释的 话将会加大这篇已经很长的文章的篇幅)

阅读全文


开源VOIP 软件清单

2011年5月22日 由 阿波 没有评论 »

http://www.voip-info.org/wiki/view/Open+Source+VOIP+Software

SVN源代码管理规范

2011年4月17日 由 阿波 没有评论 »

SVN源代码管理规范   【资料下载

1. SVN 版本库结构构建

在大多数人眼中的Subversion,就是那个在代码里被叫做“Trunk”的东西。其实Subversion包含了更多的内容! 为了让你能够更加充分体会到Subversion的好处,本文将讨论如何搭建你的版本库结构。 正如你之前在Subversion的相关文章中看到的那样,Subversion最基本的结构由三个路径组成:branches,tag和trunk。

每个路径在Subversion里都可以单独签出。

1.1 Trunk

任何时候Trunk里包含的都是最新的开发代码。 这里的代码将会工作到你的下一个主要发布版本。

据我所见,几乎常常人们只使用trunk来存放他们的代码。发放了一个版本后继续在其上进行下一版开发。这不好,无论是对你还是你的产品。

Trunk应该只被用来开发将会成为你的下一个重要版本的代码。 不要给trunk加上版本号和发布名称。 仅需要保证trunk在任何时候都处于“开发模式”。

例子:

https://svn.example.com/svnroot/project/trunk

1.2 Branches

这里有几种不同类型的分支。这里我会告诉你一些常见的类型。在branches的目录里,你可以为更多具体的目标创建路径,像即将发行版本。 正如我的文章“article on releasing software from Subversion”里讨论的那样,brahches路径包含了trunk在不同发展阶段的副本。

1.2.1 Release Branches

我们已经见过了 RB-x.x release branches。当trunk达到准备发布的阶段时(或者你想冻结新特色的添加时),你应该创建一个release branches。 Release branches只是你当前trunk的一个副本。

这个branches可以被单独的签出你也可以启动branches和基于此版本的项目。你还可以使用此分支在测试期间修复Bug。 这种方式能够保证trunk继续开发,而不会被发布某个具体的版本所干扰。 因此当你准备发布一个新版本时,这样不会影响你trunk增加新的功能。

1.2.2 Bug fix branches

分支也可以用于处理trunk或release branches里发现的严重的Bug。这些Bug很复杂,你不能在一次提交时就修复他们。因此为了集中精力修正此错误,你应该为此问题创建一个新的分支。这样就不会影响trunk 和 release branches的继续进行,并且你也不会因为发现新的Bug 和测试而干扰此Bug 的修复。

Bug 修复分支的命名通常遵循下列方式:使用你的缺陷管理系统分配给此Bug的ID。通常这是一个数字。如:Bug-3391。

当然,你也可以象其它分支一样访问你的Bug分支。

1.2.3 Experimental branches

有时你想将某个新技术引进项目。这很好,但是你当然不想赌上你的整个项目。想象一下,你想把你的Web程序从PHP4改为PHP5。你要花多少时间?在这期间你的trunk停止使用?直到你把所有到PHP5的转换做完!

这是实验,可能PHP5就像彩虹的另一端一样离你的程序太远了,你应该给他创建一个分支。 你可以在分支里进行更改,如果失败了,你在当前分支仍然有PHP4的代码。

如果失败了,实验分支可以抛弃。 如果成功,你可以很容易的将其合并到trunk并继续你的新技术。 实验分支命名遵循在面原则:为其名字加上前缀“TRY-”。

1.3 Tags

标签就像分支一样备份你的代码。 但是 Tag不被用来开发,他们只是用来标记你代码的状态。

1.3.1 Release tags

Release Tags 标记你版本发布点的代码。 Release Tag 永远是相应发布分支的副本。 Release Tag命名规则:“REL-”前缀加上版本号。

1.3.2 Bug fix PRE and POST tags

当你创建了一个Bug fix分支,你想标记代码在BugFix之前和之后的状态。 这样你就很容易的引用你所做的更改,合并到trunk或Release branches。

命名规则:   “PRE-”加上Bug ID;

“POST-”加上Bug ID。

2. SVN使用规范

先更新,再提交
SVN更新的原则是要随时更新,随时提交。当完成了一个小功能,能够通过编译并且自己测试之后,谨慎地提交。
如果在修改的期间别人也更改了svn的对应文件,那么commit就可能会失败。如果别人和自 己更改的是同一个文件,那么update时会自动进行合并,如果修改的是同一行,那么合并时会产生冲突,这种情况就需要同之前的开发人员联系,两个人一起协商解决冲突,解决冲突之后,需要两人一起测试保证解决冲突之后,程序不会影响其他功能。
在更新时注意所更新文件的列表,如果提交过程中产生了更新,则也是需要重新编译并且完成自己的一些必要测试,再进行提交。这样既能了解别人修改了哪些文件,同时也能避免SVN合并错误导致代码有错。

多提交
每次提交的间歇尽可能地短,以几个小时的开发工作为宜。例如在更改UI界面的时候,可以每完成一个UI界面的修改或者设计,就提交一次。在开发功能模块的时候,可以每完成一个小细节功能的测试,就提交一次,在修改bug的时候,每修改掉一个bug并且确认修改了这个bug,也就提交一次。我们提倡多提交,也就能多为代码添加上保险。
不要提交不能通过编译的代码
代码在提交之前,首先要确认自己能够在本地编译。如果在代码中使用了第三方类库,要考虑到项目组成员中有些成员可能没有安装相应的第三方类库。项目经理在准备项目工作区域的时候,需要考虑到这样的情况,确保开发小组成员在签出代码之后能够在统一的环境中进行编译。
每次提交必须书写明晰的标注
在一个项目组中使用SVN,如果提交空的标注或者不确切的标注将会让项目组中其他的成员感到很无奈,项目经理无法很清晰的掌握工作进度,无法清晰的把握此次提交的概要信息。在发现错误后也无法准确的定位引起错误的文件。所以,在提交工作时,要填写明晰的标注,能够概要的描述所提交文件的信息,让项目组其他成员在看到标注后不用详细看代码就能了解你所做的修改。
提交时注意不要提交本地自动生成的文件
例如eclipse中的.classpath文件,Windows生成的缩略图Thumbs.db,项目编译生成的临时文件.obj, .class等等。如果项目中没有进行这方面的配置来强行禁止提交这样的文件,请自觉不要提交这样的文件。提交了这样的文件后,别人在更新后就可能与本地的环境冲突从而影响大家的工作。
不要提交自己不明白的代码
代码在提交入SVN之后,你的代码将被项目成员所分享。如果提交了你不明白的代码,你看不懂,别人也看不懂,如果在以后出现了问题将会成为项目质量的隐患。因此在引入任何第三方代码之前,确保你对这个代码有一个很清晰的了解。
慎用锁定功能
在项目中要慎用锁定的功能,在你锁定了一个文件之后别人就无法继续修改提交该文件,虽然可以减少冲突的发生率,但是可能会影响项目组中其他人员的工作。平时只有在编辑那些无法合并的文件(例如图片文件,flash文件等)时,才适当的采用锁定操作。

warning:cannot pass objects of non-POD type

2011年2月8日 由 阿波 没有评论 »

移植代码到Linux下,运行总是崩溃(在windows下正常)。
调试发现问题出在下列语句:
wxString szSiteHead = wxString::Format( wxT(““), file.GetName() );
查看编译记录有下列警告信息
warning: cannot pass objects of non-POD type ‘class wxString’ through ‘…’; call will abort at runtime|
提示在运行时会异常。

查找 POD type定义如下:

POD stands for Plain Old Data – that is, a struct (or class) with no members except data members. Wikipedia goes into a bit more detail and defines a POD in C++ as “A Plain Old Data Structure in C++ is an aggregate class that contains only PODS as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type.”

代码更改后OK。
wxString szSiteHead = wxString::Format( wxT(““), file.GetName().c_str() );

一段删除临时文件的脚本

2011年2月8日 由 阿波 没有评论 »

下面是一段删除临时文件的脚本,使用时请存为wsf类型文件

<!--Autor: Lava_sdb (舒定波)-->
<!--Descr: Delete the template File (删除指定的临时文件)-->

<Job ID="Delete the template File">
<Script LANGUAGE="VBSCript">

Sub DelTempFiles(folderspec)
Dim fso, f, f1, fc, s,foldc,f2
'Add the file type name that you want del
Dim Delfiletype()
dim typeCout,temptype
typeCout=9
ReDim Delfiletype(typeCout)
Delfiletype(0)="obj"
Delfiletype(1)="pdb"
Delfiletype(2)="pch"
Delfiletype(3)="res"
Delfiletype(4)="bsc"
Delfiletype(5)="idb"
Delfiletype(6)="ilk"
Delfiletype(7)="sbr"
Delfiletype(8)="exp"
Delfiletype(9)="ncb"
'
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder(folderspec)
Set fc = f.Files
For Each f1 in fc
temptype=Right(f1.name,3)
dim i
for i=0 to typeCout
if temptype=delfiletype(i) then
f1.delete true
'msgbox f1.name
end if
next
next

Set foldc=f.SubFolders
For Each f2 in foldc
if f.attributes and 2 then

else
DelTempFiles(f2.path)
end if
next

End Sub

</Script>

<Script LANGUAGE="JSCript">
var WshShell = WScript.CreateObject("WScript.Shell");
DelTempFiles(WshShell.CurrentDirectory);
WScript.Echo(" 临时文件删除完成");
</Script>

</Job>

trac安装步骤

2011年2月7日 由 阿波 没有评论 »

原文

如何安装trac

1. 安装Trac
1.1 安装 python 2.6.6
1.2 安装 setuptools-0.6c11.win32-py2.6.exe
1.3 安装 Genshi-0.6.win32.exe
1.4 安装 Babel-0.9.5.win32.exe
1.5 安装 Trac-0.12.1.win32.exe
1.6 安装trac常使用的插件
1.7 配置 trac
2. 安装 svn 相关
3. 安装apache2.2

python下载地址

2011年1月15日 由 阿波 没有评论 »

python主页上下载链接被墙。找到另一官方地址。http://www.python.org/ftp/python/

ubuntu10.10 编译 freeswitch

2011年1月2日 由 阿波 没有评论 »
[摘自]http://wiki.freeswitch.org/wiki/Quick_Start
/////
sudo su
apt-get install git-core subversion build-essential autoconf automake libtool libncurses5 libncurses5-dev (**5 mins**)
apt-get install libjpeg62-dev #otherwise make fails with [mod_spandsp.la] Error 1
cd /usr/src
wget http://www.freeswitch.org/eg/Makefile
make   ( **55 mins**)
make install (**2 mins**)
cd freeswitch.git
make uhd-sounds-install (**2 mins**)
make uhd-moh-install   (**2 mins**)

python资源

2010年12月25日 由 阿波 没有评论 »

VimPythonTDD

VimPython

PyIDEguider

Boost Phoenix 入门

2010年12月9日 由 阿波 没有评论 »

Boost Phoenix 入门(1)

Boost Phoenix 入门(2)

Boost Phoenix 入门(3)

Boost Phoenix 入门(4)

(转)惰性函数定义模式(Lazy Function Definition Pattern)

2010年12月9日 由 阿波 没有评论 »

这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function Definition)。我不止一次发现这种模式在JavaScript中大有用处,尤其是编写跨浏览器的、高效运行的库之时。
热身问题

编写一个函数foo,它返回的是Date对象,这个对象保存的是foo首次调用的时间。
方法一:上古时代的技术

这个最简陋的解决方案使用了全局变量t来保存Date对象。foo首次调用时会把时间保存到t中。接下来的再次调用,foo只会返回保存在t中的值。
var t;
function foo() {
if (t) {
return t;
}
t = new Date();
return t;
}

但是这样的代码有两个问题。第一,变量t是一个多余的全局变量,并且在 foo调用的间隔期间有可能被更改。第二,在调用时这些代码的效率并没有得到优化因为每次调用 foo都必须去求值条件。虽然在这个例子中,求值条件并不显得低效,但在现实世界的实践例子中常常会有极为昂贵的条件求值,比如在if-else-else-…的结构中。
方法二:模块模式

我们可以通过被认为归功于Cornford 和 Crockford 的模块模式来弥补第一种方法的缺陷。使用闭包可以隐藏全局变量t,只有在 foo内的代码才可以访问它。
var foo = (function() {
var t;
return function() {
if (t) {
return t;
}
t = new Date();
return t;
}
})();

但这仍然没有优化调用时的效率,因为每次调用foo依然需要求值条件。

虽然模块模式是一个强大的工具,但我坚信在这种情形下它用错了地方。
方法三:函数作为对象

由于JavaScript的函数也是对象,所以它可以带有属性,我们可以据此实现一种跟模块模式质量差不多的解决方案。
function foo() {
if (foo.t) {
return foo.t;
}
foo.t = new Date();
return foo.t;
}

在一些情形中,带有属性的函数对象可以产生比较清晰的解决方案。我认为,这个方法在理念上要比模式模块方法更为简单。

这个解决方案避免了第一种方法中的全局变量t,但仍然解决不了foo每次调用所带来的条件求值。
方法四:惰性函数定义

现在,这是你阅读这篇文章的理由:
var foo = function() {
var t = new Date();
foo = function() {
return t;
};
return foo();
};

当foo首次调用,我们实例化一个新的Date对象并重置 foo到一个新的函数上,它在其闭包内包含Date对象。在首次调用结束之前,foo的新函数值也已调用并提供返回值。

接下来的foo调用都只会简单地返回t保留在其闭包内的值。这是非常快的查找,尤其是,如果之前那些例子的条件非常多和复杂的话,就会显得很高效。

弄清这种模式的另一种途径是,外围(outer)函数对foo的首次调用是一个保证(promise)。它保证了首次调用会重定义foo为一个非常有用的函数。笼统地说,术语“保证” 来自于Scheme的惰性求值机制(lazy evaluation mechanism)。每一位JavaScript程序员真的都应该学习Scheme,因为它有很多函数式编程相关的东西,而这些东西会出现在JavaScript中。
确定页面滚动距离

编写跨浏览器的JavaScript, 经常会把不同的浏览器特定的算法包裹在一个独立的JavaScript函数中。这就可以通过隐藏浏览器差异来标准化浏览器API,并让构建和维护复杂的页面特性的JavaScript更容易。当包裹函数被调用,就会执行恰当的浏览器特定的算法。

在拖放库中,经常需要使用由鼠标事件提供的光标位置信息。鼠标事件给予的光标坐标相对于浏览器窗口而不是页面。加上页面滚动距离鼠标的窗口坐标的距离即可得到鼠标相对于页面的坐标。所以我们需要一个反馈页面滚动的函数。演示起见,这个例子定义了一个函数getScrollY。因为拖放库在拖拽期间会持续运行,我们的getScrollY必须尽可能高效。

不过却有四种不同的浏览器特定的页面滚动反馈算法。Richard Cornford在他的feature detection article文章中提到这些算法。最大的陷阱在于这四种页面滚动反馈算法其中之一使用了 document.body. JavaScript库通常会在HTML文档的加载,与此同时docment.body并不存在。所以在库载入的时候,我们并不能使用特性检查(feature detection)来确定使用哪种算法。

考虑到这些问题,大部分JavaScript库会选择以下两种方法中的一种。第一个选择是使用浏览器嗅探navigator.userAgent,为该浏览器创建高效、简洁的getScrollY. 第二个更好些的选择是getScrollY在每一次调用时都使用特性检查来决定合适的算法。但是第二个选择并不高效。

好消息是拖放库中的getScrollY只会在用户与页面的元素交互时才会用到。如果元素业已出现在页面中,那么document.body也会同时存在。getScrollY的首次调用,我们可以使用惰性函数定义模式结合特性检查来创建高效的getScrollY.
var getScrollY = function() {

if (typeof window.pageYOffset == ‘number’) {
getScrollY = function() {
return window.pageYOffset;
};

} else if ((typeof document.compatMode == ’string’) &&
(document.compatMode.indexOf(‘CSS’) >= 0) &&
(document.documentElement) &&
(typeof document.documentElement.scrollTop == ‘number’)) {
getScrollY = function() {
return document.documentElement.scrollTop;
};

} else if ((document.body) &&
(typeof document.body.scrollTop == ‘number’)) {
getScrollY = function() {
return document.body.scrollTop;
}

} else {
getScrollY = function() {
return NaN;
};

}

return getScrollY();
}
总结

惰性函数定义模式让我可以编写一些紧凑、健壮、高效的代码。用到这个模式的每一次,我都会抽空赞叹JavaScript的函数式编程能力。

JavaScript同时支持函数式和面向对象便程。市面上有很多重点着墨于面向对象设计模式的书都可以应用到JavaScript编程中。不过却没有多少书涉及函数式设计模式的例子。对于JavaScript社区来说,还需要很长时间来积累良好的函数式模式。

原文:Lazy Function Definition Pattern. 转载没有我的信息没有关系,但你一定得写上原文信息,谢谢。

更新:

这个模式虽然有趣,但由于大量使用闭包,可能会由于内存管理的不善而导致性能问题。来自FCKeditor的FredCK改进了getScrollY,既使用了这种模式,也避免了闭包:
var getScrollY = function() {

if (typeof window.pageYOffset == ‘number’)
return (getScrollY = getScrollY.case1)();

var compatMode = document.compatMode;
var documentElement = document.documentElement;

if ((typeof compatMode == ’string’) &&
(compatMode.indexOf(‘CSS’) >= 0) &&
(documentElement) &&
(typeof documentElement.scrollTop == ‘number’))
return (getScrollY = getScrollY.case2)();

var body = document.body ;
if ((body) &&
(typeof body.scrollTop == ‘number’))
return (getScrollY = getScrollY.case3)();

return (getScrollY = getScrollY.case4)();
};

getScrollY.case1 = function() {
return window.pageYOffset;
};

getScrollY.case2 = function() {
return documentElement.scrollTop;
};

getScrollY.case3 = function() {
return body.scrollTop;
};

getScrollY.case4 = function() {
return NaN;
};