作者归档:admin

关于编码规范

当提到编码规范,自然而然就会想到约束,没错,编程规范本来就会约束开发人员的编码风格。 但是约束并不是所期望的最终目的,约束只是一种表现形式,关键在于建立编码过程中的一种秩序, 以及团队编码风格的统一和稳定,从而提高编码质量,进而提高产品的质量。

当下的我们处于一个需要团队协同作战的世界,一个项目可能需要几个人、十几个人或几十几百人的技术团队,而在产品的生命周期中可能会经历多个项目, 在此期间,人来人往,人走人留,当新来的团队成员在读他的前任留下的代码时,如果团队内部没有一个统一的规范,可能会出现一系列的问题。如: 不知道变量名的意思,莫名其妙的函数定义,搞不清的类实现等等。这些问题会让新来的成员相当纠结难过, 从而给他们一种挫败感,他们熟悉项目代码的时间就会比较长,比较辛苦。 这只是没有编码规范所带来的一个比较显著的问题而已。

每个公司,每个团队都有其文档化或潜规则的编码规范,这里我们不谈具体的规范,只谈“风月”。 我们认同在编码过程中应该遵循的两条原则:

  1. 代码不仅仅是写给计算机看的,更重要的是是写给人看的。
  2. 注意破窗户,细节决定成败。

写给计算机看的代码往往追求的是运行结果的正确和满足需求的执行效率。这样的代码可能是乱糟糟的,没有注释,没有空格,没有排版,没有可以理解命名…. 除了刚写完的那会儿,我们知道我们所写的代码是啥意思。当过了十天半个月回来可能就连自己也不知道当初那会儿是怎么想的了, 更不用说如果这样的代码移交到其它同事,他那张纠结的小脸了…

代码到最后都是写给人看的,首先是给自己看的,然后是给使用这段程序的人,最后是其他与这段代码现在或将来相关的人。 这里所谓相关的人包括:

  • 可能会阅读这段代码的人
  • 可能会修改这段代码的人
  • 可能会下载/复制这段代码的人
  • 可能会走读这段代码的人
  • 测试人员
  • ……

从这个点出发,我们才能理解为什么要有编码规范,为什么会有若干文档。 我们所做的这些都是为将来做的,所谓“前人栽树,后人乘凉”,大致就是这个意思。

《程序员修炼之道》有这样一条:不要容忍破窗户(Don’t Live with Broken Windows)。 当我们遇到“破窗户”: 如低劣的设计、错误决策、或糟糕的代码,要及时的处理,如果不能马上修改代码,也请在有问题的地方写上注释,说明问题。 因为一旦有了第一个破窗户,不久后就会有第二个,第三个……直到整个系统满目疮痍、崩溃。 这里的“破窗户”可以理解为一些细节的问题,虽然我们经常会听到“细节决定失败”,在现实中也确实有些因为细节而成功的案例。 但是细节并不是每个人都可以看到的,有些人对于一些有问题的细节可以视而不见,这不是因为他们不想去改, 而是他们根本就不知道这些细节是不是正确的,感知细节也是一种能力,这需要在实践中不断的学习,不断的思想,不断的阅读好的代码,最好还有此中高手的指导。 这些细节决定了我们代码的成败,虽然结果不是马上显现的。

回到我们所用的语言-PHP,在编码规范这块,PHP本身就有一些问题,如函数的命名,PHP既有使用骆驼命名法的,也有类似于C中的以下划线隔开。 但是这种不规范中也有它的规范,所有的函数的命名都是以下划线隔开,所有的PHP提供的类中的方法都是骆驼命名法。 PHP以一种包容和开放的心态来处世,但是是否失去了自己特色呢?虽然PHP的有一些语言特点与一些商业的运作有关, 但是应该有自己的坚持,应该建立属于自己的规则。

PHP中的函数嵌套层数限制

函数嵌套,这个名字有点纠结,也许不太好理解。一个比较常见的函数嵌套特例:递归函数,即函数自己嵌套自己。 一直以为在PHP中不能有太多的函数嵌套,这是因为在以前某些时候不小心用到了递归,在递归的深度达到100时, 即函数嵌套的层数达到100时,程序会报一个 Fatal error。如下示例:

function rt() {
    static $i;
    echo $i++, '<br />';
    rt();
}
rt();
die();

在我的win7 + php5.3的环境下报错如下: Fatal error:Maximum function nesting level of ’100′ reached, aborting!

一直以为是PHP本身的限制,直到某一天切换到liunx环境下以命令行的模式运行,发现,程序限入了死循环。 不同的环境下有不同的结果,为什么呢?好吧,我们直接在源码中查找报错信息,发现没有相关内容,直接debug整个执行过程,也没有在win下的报错。 什么原因?再次切换到win下,再次查找,发现在xdebug中看到了报错信息。在xdebug.c文件的1242行开始:

XG(level)++;
if (XG(level) == XG(max_nesting_level)) {
    php_error(E_ERROR, "Maximum function nesting level of '%ld' reached,
         aborting!", XG(max_nesting_level));
}

这表示什么?之前的函数嵌套的层数限制是xdebug扩展加上的,为什么会有这个限制了呢?在xdebug中,xdebug中会记录每次函数调用, 包括嵌套的函数调用,函数调用中的内存,时间等值,这些值在分析程序性能时有大用。如果没有这个限制,当嵌套的层数太多,机器会内存耗尽。 如果这是一台生产环境的服务器,那么就会有部分服务不可用,当然生产环境下是不会添加这个扩展的。但是在多人共用的开发服务器上就可能有这个扩展, 如果因为一个开发人员的程序错误导致机器不可用,从而使所有的开发人员不能工作,我想这也许是添加限制的原因吧。

如果我们需要把这个限制的层数加大,怎么办呢?改源码,重新编译xdebug扩展?不需要,在xdebug的配置项中有一项叫做xdebug.max_nesting_level, 默认情况下,在php.ini中这个配置项是被注释了的,去掉注释,将这个值成你所需要的值,200?不够,那500吧,但是这个值还是不要太大, 如果递归太多,对程序的性能有很大的影响,此时,以栈的形式实现递归或者用循环替换递归会是一个更好的方案, 如:斐波那契数列(Fibonacci)的实现,用循环来实现会更快。

结论:PHP本身的函数嵌套是没有限制的,如果说有限制,也是最大栈空间的限制。

感谢鸟哥指出结论的错误,有些想当然了。


TIPI儿童节版发布

少年智则国智,少年富则国富,少年强则国强,少年独立则国独立,少年自由则国自由,少年进步则国进步……

各位自认为是儿童的,不是儿童的;扮萌的或已成为大叔的同学,儿童节快乐! TIPI团队选择在这个应该纯粹一点的节日里,发布努力了两个月的成果。 自最近一次的版本发布(2011-04-01)以来,关注的同学可能会注意到网站上 没有新的变化,其实这段时间我们并没有减缓TIPI项目的进度,在第一次项目发布之后我们收到了很多的反馈, 经过团队的讨论,我们决定暂缓新章节的编写,把精力集中在现有章节的改良上。 总体来讲有如下变化:

  • 重构现有章节。将现有一些章节的内容进行了丰富。当然这并不是终点,我们会持续对内容进行优化。
  • 完成了第五章的编写。上次发布时发布了第五章类的第一二小节,这次我们完成了所有的内容。

上次发布时我们提供了PDF版本的下载, 这次的发布没有带来新格式的下载,不过不要着急, CHM版本的下载将会在近期提供。

TIPI入口>>>