« 还真是休息不下来 | 返回首页 | X 下的鼠标滚轮消息的处理 »

感觉好多了

其实我并没有用 lua 亲手写过什么大规模的项目。超过 5 千行代码的项目几乎都是 C 或是 C++ 写的。这几天算是做了点复杂的玩意了。几经修改和删减,最后接近完工的这个东西统计下来不多不少 3000 行(误差在十位数)。其中用 C 编写了基础模块 900 多行(仅仅是 socket api 的封装和 byte 流的编码解码),剩下的都是用 lua 设计并实现的。

好吧,我承认 2000 多行代码也只是一个小东西。不过用 lua 实现的一个 wiki 系统,sputnik 还不到 2000 行呢。lua 有一种特质,用的久了就容易体会到。它和 python ruby 这些更为流行的动态语言是不同的。曾经,我把选择 lua 的理由,肤浅的停留在了更轻便更高效上,虽然这些也很重要,但抓住语言的特质才是更关键的。

没有一所学校会教授 lua 这种小语言。教学语言多为 C C++ java (或者更古老一些的 fortran lisp ?)。近年来有听说教 python 的,不过我想 lua 很难进入教学领域。所以大多数用 lua 的程序员,基本上都是半路出家,用过别语言。其中以 C/C++ 为多。我想这是因为 lua 不像 python 有太多成熟的库可以直接使用,要用之到实际项目中去,用 C 为它写扩展必不可少。

或许日后,lua 的扩展库会越来越丰富,lua 程序员不再需要亲自操刀写扩展模块。但就现状来说,我认为也不是坏事。毕竟自己实现的东西最熟悉,(包括 lua 本身的 source code ,规模也不算大,值得一读),知道其性能要点,怎么使用最适宜。

lua 的语言相当简洁,数据类型也少到了极致,真是增一分便觉多余,减一点就有缺陷。这样,我们便不用再把语言用的不好归结到语言的设计本身上。深刻理解它就能用起来游刃有余。

几乎每个 lua 程序员独立写出来的代码都风格迥异。因为我们既可以以面向对象的形式来构建系统,又能够把它当函数式语言实用,还可以直接来描述数据(这是 lua 1.0 的最初用途)。虽然这样,会给大规模项目的多人合作造成一些困扰。但我们能面对多大的项目呢?让我们项目的构架师去把项目划成更小的独立组件,然后用 lua 快乐的实现它。让原本用别的语言需要上万行的工作用 lua 在两三千行中解决。

lua 中复杂的对象类型只有 table 和 userdata 两个。

userdata 往往比较单一,只用来处理效率紧要的数据。这些是放在 C 层次中做的,很容易隔离开。(当然,用之不慎也会出许多问题。不过多为新的 lua 程序员缺乏经验,把 lua 简单看成一个 C 代码粘合剂所致。)

真正复杂的只有 table ,它回相互链接,构成复杂的生存依赖关系。而另外跟垃圾收集有关的类似,比如 string 和 closure (以及后来增加的 thread )则不会带来太多的复杂度。

强调数据类型的复杂度,是关系到垃圾收集的过程。我们知道,lua 这类语言中,不存在 C 语言里的指针越界和内存泄露问题。但是,我不相信垃圾收集就是万能药,在不成熟或有疏漏的设计中,问题只是被隐藏起来了。

所以在 C 或 C++ 中,我们关注数据的内存布局,和内存管理;到了 lua 中,我们也应该关心数据何种情况下诞生,何种情况下消亡。怎样减少垃圾收集器的工作压力。后者并不比前者容易,因为前者往往会引起系统崩溃,给开发人员预警;而后者,表象可能仅仅是系统资源占用过大而已。不引起程序崩溃的失误才是最可怕的。

如果,有性能追求的程序员了解到,每次创建一个新的 table ,构造一个新的 closure ,用连接符连接一个新的 string ,都有新的对象诞生。哪怕它只是临时用几个 circle ,也会给事后的垃圾收集模块造成压力。那么,当他在设计上尽量减少这些事情的发生,且尽量维持着代码规模不至于过大。那么,稳定的系统自然而生。这也是我最近半个月用 lua 编程的感受。

语言,看似是软件设计中枝梢末节的部分。但是语言同样深刻的影响着设计师的思维方式。作为程序员,对单一语言过分依赖的时候,就应该引起自己的警觉,该试点新的思路了。


换个角度再写点别的。

最近很忙,而今天有时间写这么大一篇,纯属无奈。手头一个项目,我自己的部分都做完了。剩下的依赖其他同事一起工作,需要做一些通讯协议上的修正。不过今天是周末,我带团队的原则是,不到万不得已,绝不要求别人加班。写完今天最后一行代码前,已经想过了可以提前写的代码,能做的都做了,剩下的只能等周一继续。

把大项目拆分成独立的二进制模块,分配到不同的人来做。是我最为(也是唯一)认可的中型软件项目的合作开发模式。在游戏客户端这边,基本上是独立模块,留出极少的 C 接口;服务器那边则干脆做成一个个独立进程,之间用通讯协议来协同运行。

经历了太多事情,让我对源码级上的合作失去了信心。或许 XP 的结对编程会好一些,不过前几年尝试的经历让我感觉那样太累。还是一个人对着电脑做东西好。当然前提是个人能力要达到一定的程度,并对编程这件事有足够良性的态度,才能保证代码质量。

代码质量如何保证?我的私人药方是,把一切事情简单化,尽量把代码写短(保持每个独立源文件不超过 500 行),删掉和缩减一切不必要的东西。让 bug 无处发生,比小心的回避它们要容易的多。不行就重写,而不要过多调试。不要在一块代码上耽误太多时间,速战速决。如果花了太多时间去实现它,那么一定有设计问题。世界上有许多复杂的事情难以解决,但绝对不包括实现一个有特定需求的模块 :D 。

怎样高效的完成一个软件项目?选择最好的程序员,不要太多,不要觉得小题大作。把他们放在一起,在一两个月内完成它。如果做不到,比如找不到最好的程序员,只要你相信自己就是最好的,那么即使一个人单干也好过雇一大堆平庸的人去做。当然,再好的程序员也不能同时做两件事情。所以,设定好计划,一件事一件事的来。

程序员们总是高估计自己的能力,而低估问题的复杂度。在多个合作的项目中更为突出。一个人两周的工作,即使两个同样优秀的人一起干,也不会把工期缩短到一周(甚至加到 3 个人也做不到)。道理看上去大家都懂,但是事到临头还是会为多人合作的效率低下而懊恼。可惜,许多许多的现实项目,在不至于引发疲倦的工期内,靠一个人是写不完程序的。何况,像我所处的游戏开发行业内,一个项目不仅仅是靠程序实现。我们还是得面对合作开发这个问题。

Comments

“误差在十位数”??是误差在两位数吧?

lua 有一种特质,用的久了就容易体会到。它和 python ruby 这些更为流行的动态语言是不同的。
========================
是指pil中“Lua的另一个目标是灵活性,提供程序员元机制,通过他你可以实现很多不同的机制”吗?

云风哥的观点(关于程序员合作,和开发上的一些问题)太到位了!我也是这么想的。

要是能用每一种会的语言写10000行代码就好了

~~~

看了小兵故事和将军的故事,觉得这是两个极端。从管理角度上来说,都是不可取的。我觉得应该从实际的情况出发,理智地采取相应的措施才是比较好的办法。比如,有丰富的资源,有好的程序员,不妨让他们自己发挥,自己在后面控制整体质量,如果资源有限,人才不足,那也需要自己赤膊上阵。总之,法无定法,因时因势而动才是好的。

晦涩的代码,牵强的设计,会破坏别人的辛苦努力,特别是和屡教不改还带有个人情绪的同事在一起工作真的很难受,相信云风也是迫不得已。裁人总是让人尴尬和难受的,当然如果是那种缺德的上司自然会感觉很爽...

代码质量如何保证?我的私人药方是,把一切事情简单化,尽量把代码写短(保持每个独立源文件不超过 500 行),删掉和缩减一切不必要的东西。让 bug 无处发生,比小心的回避它们要容易的多。不行就重写,而不要过多调试。不要在一块代码上耽误太多时间,速战速决。如果花了太多时间去实现它,那么一定有设计问题。世界上有许多复杂的事情难以解决,但绝对不包括实现一个有特定需求的模块 :D 。

-----------------

有的时候,感觉马上就要抓到了,就在指尖,这时候如果推倒重来,有些不甘心。

上一篇文章刚说辞退了一个程序员,这篇就说宁愿单干也不要平庸的程序员,这是变相的骂人么?

云风最近开始变的有点骄傲了

您老再不快点出个游戏就对不起党,对不起人民了!

哎,今天进天下2的内测了~这咋感觉还没有回炉前的好呐???
帮忙问问他们小组吧~

还有很多东西没有加?细节优化中?还是的确是糙了?

可是第一次失望啊~

看到这篇文章突然联想到以前看到的一句话:“Iris was a lot like most engineering organizations, most of the good work was done by handful of talented people, the others often produced barely functional crap that would need to be cleaned up someday.”

真是越来越有趣了.

呵呵,这是个度的问题,但最难的是如何把握好这个度。

小兵的故事

从前有个小兵,因为战功被提升为队长,手底下终于有几个人可以指挥了。但他的梦想是当将军。

在一次战争中,他的小队遭遇了敌人的袭击。他奋力指挥他的队伍抵抗敌军,打的很辛苦。

当入伍的新兵在快抵挡不住的时候,向他投过求助的目光。而他站在身后木然说道,我已经不是士兵了,我的任务是指挥战斗,而不是帮你杀敌。

而后,队形的一角崩陷了。整个队伍除了他之外全部阵亡。只有他凭借着高超的武功保全了性命。战斗结束后便换了个东家,在敌人的阵营中向着将军的位置继续奋斗。

从前有个将军, 带领士兵出去打仗.

将军本来也是被皇帝从小兵提拔上来的,骄傲的不得了.

他看着小兵在前线,暗自笑道:一群笨蛋,一个人还杀不了几个人,怎么混的.

他大喝一声:滚开,我来杀!!!
将军冲到前线杀敌去了.为了显示他骄傲的杀敌本领,用尽力气,用尽武功,再凭借他多年的杀敌经验,确实杀的比小兵更快.

不过有时候,小兵也会冲上去和将军并肩,对将军说:你这么杀下去,战争迟早会输的,人是杀的多了,但是不代表其他敌人军队我们也能打赢啊. 将军,你还是去指挥吧.将军哈哈大笑: 滚开,你个小鬼懂什么, 战争不就是杀人吗?不杀人怎么打赢呢?

小兵被将军一把推到后面.
后面的士兵都坐下来不打了,看着将军杀敌,因为他们知道,将军以一抵百啊.不用他们操心.

战斗暂时结束了,将军满脸血迹,回过头来,看着这群坐下的小兵,再看着前方,更多密密麻麻的军队冲了过来,将军大喊:都给我起来!给我去杀敌!

一个坐在最前边的士兵被将军一刀砍死: 你个混蛋! 叫你站起来杀敌却不听我命令.你还叫士兵吗?
士兵们都怕了,开始站起来,冲向敌人,可是正在这个时候,将军又一次冲在了前面:你们小鬼好好看着我是怎么杀敌的!


士兵们开始逃窜,他们不知道将军是不是脑残,也不知道他们何时会丧命,但是他们知道,只要在这里,迟早是一个死.不是死在敌人手里,就是死在将军刀下.

我所说的数学并非指数学分析之类, 而是离散数学, 代数理论, 形式化理论等.

而一般理解的数学和计算机并没多大相关, 而是面向具体科学工程领域.

怎样高效的完成一个软件项目?选择最好的程序员,不要太多,不要觉得小题大作。把他们放在一起,在一两个月内完成它。如果做不到,比如找不到最好的程序员,只要你相信自己就是最好的,那么即使一个人单干也好过雇一大堆平庸的人去做。当然,再好的程序员也不能同时做两件事情。所以,设定好计划,一件事一件事的来。

云风这里只举了2种很少出现的情况,不适应于大多数情况,即:即找不到最好的程序员,自己也不是很优秀。这时怎么办?

代码质量如何保证?我的私人药方是,把一切事情简单化,尽量把代码写短(保持每个独立源文件不超过 500 行),删掉和缩减一切不必要的东西。让 bug 无处发生,比小心的回避它们要容易的多。不行就重写,而不要过多调试。不要在一块代码上耽误太多时间,速战速决。如果花了太多时间去实现它,那么一定有设计问题。世界上有许多复杂的事情难以解决,但绝对不包括实现一个有特定需求的模块 :D 。

-----------------
赞一个

数学是显性的、社会化的表达方法和思考工具,程序语言也是。从这个角度看,我觉得把一种表达方式映射到另一种表达方式并不能更好的解决问题。一个错误的论点,不管翻译成哪国文字都不能改变其错误。错误的问题不管用什么符号系统回答都是没有意义的。多研究研究人类认识世界和思考问题的方法才是重要的,特别是把这些方法和陷阱显性地表达出来,并且通过交流而社会化。

高手寂寞啊...

怪不得很多顶级的项目都是一个人完成的

我想讨论一下语言,有点虚,不过我觉得是值得讨论的, 有类似兴趣的朋友自然能看出点什么.

lua说到底,比其它语言的优势在于, 规模特性不大,源码也不算复杂, 可控性好.lua, python, ruby可以说是同一族语言能力的不同语法糖形式.这几者只有在高阶(function is first class object)上类似于函数式语言(且只得益于这一点),实际上,函数式语言有着较精确的定义和特征,比lua之类语言要丰富的多.

我认为技术上的巨大进步,将会出现在语言(和人机界面)上面,而不是什么软件工程的新潮流,软件工程是为了弥补开发手段和能力的不足,而物化人的因素.

程序将越来越向数学本质和业务本质进化.程序员今天仅仅是在低水平(机器, 和缺乏表达能力的代码)上思考业务, 逻辑抽象.

什么时候我们像归结求解线性方程一样地, 容易地抽象出业务逻辑结构,并有一套模式化的方法.也许才真正解决软件开发复杂性问题.

对于程序员的能力, 要求有点太广泛,比如说有些人3D图形数学或编辑不错,可是可能拙于写业务逻辑.有些人有足够的理论基础和业务思维,但也不代表他能比对框架熟悉的人更能解决问题.好的程序员实在难定义.

被电话叫到公司里来弄点东西。弄完了顺便看看 blog 的留言 :D

我是想说,我对 lua 的感觉好多了。当然以前也用的很顺手。

至于 lua 的控制权问题,我认为是一个优势。小巧的东西不适合太多人参合。

我对计算机编程语言的认识还是感觉太肤浅,还得多看一些,多用一些才有感觉。

或者下一步得深入的用一些纯的函数式语言做点实际的东西试一下。lua 的可爱也正在于它有很深的函数式语言的血统。

啥感觉好多了。好像跑题了

听君一席话,获益匪浅!想到个主意,不知云风是否愿意。如果搞个游戏开发连载的形式,都是用最新的技术,制作一款游戏DEMO,这样应该能吸引更多人来这里吧!

嗯,我以前也非常喜欢Lua,也分析过源代码,当然虽然也想过实现一个,但是最终没有像云风大哥那样做出来。用Lua写了好几次的作业(我是学测绘的),感觉很顺手把。但是后来有些事情让我放弃了(当然不是毅然决然地),Lua 5.1.2貌似有一个内存的Bug,当时我实现的一个小的神经网络的程序,table里面的double莫名其妙的变成了无穷大。当然那个时候我的设计是有问题的(收敛不了,会往坏的方向发展,但不至于突变),但是突变的值比较莫名其妙(可能是我的问题,但是后来没去研究,代码也没留)。另外的问题是Lua与C交互的那个思路有点小不方便,我想是我没有习惯吧,但我真的想改进那个基于栈的设计(虽然有很多Wrappers,但是大多用了Boost,或者用特殊的预处理器。一个组的人,我不能强求别人和我一样喜欢C++,喜欢模板)。后来院里的开发越来越多转到.NET,老师要求我们用C#。先前我用C#做了一个简单的程序(用带GPS模块的PDA采集数据,用网络发送给主机,并显示到Google Earth上),所以对Visual C#中从头到尾的Code Intelligence很喜欢(我很Lazy)。反思Lua,的确目前还是作为嵌入主程序的控制部分较好,从库,IDE还有对.NET支持等诸多方面来说都有些不利因素。马上又有一个做遥感数据处理的项目,组里坚决要求用C#实现,没办法,由于属于教学性质,不要求极高的性能,也就将就了。
虽然Lua开源,但是我认为,Lua有点类似当年的MINIX,控制权太集中了,也许云风大哥可以贡献些新的设计,毕竟你的代码和设计经历过大项目的历练呀。
衷心祝Lua顺利发展。
P.S. 套个近乎,我也是武汉人,呵呵。

"它和 python ruby 这些更为流行的动态语言是不同的。"
希望看到更详细的解释。

云凤的新作什么时候问世啊,期待ing

Post a comment

非这个主题相关的留言请到:留言本