无比美好的新学期驾着五彩祥云飞来了。如果通讯原理补考顺利的话,这将是本科的最后一个学期。
要学着让生活规律些,多锻炼身体,把去年积累的一身肥肉减下来。考过通讯原理,做好毕设,不要留什么遗憾。不能老在实验室过夜。
愿这个学期过得充实愉快。
无比美好的新学期驾着五彩祥云飞来了。如果通讯原理补考顺利的话,这将是本科的最后一个学期。
要学着让生活规律些,多锻炼身体,把去年积累的一身肥肉减下来。考过通讯原理,做好毕设,不要留什么遗憾。不能老在实验室过夜。
愿这个学期过得充实愉快。
从工程角度看这次的电脑鼠项目,得失参半。因技术外的因素耽搁的时间的确不少。毕竟大家都没有很多的工程经验,虽上过软件工程课,但课本上的教条不经自己实践验证,实难理解深刻。这次项目中的得失,我想,对每个人,都会有所启迪。
1、从简单入手,逐步优化
这次项目一开始,我就致力于重新搭建一套实时控制系统,以代替样例中的控制逻辑。经过两周的调研与设计,我终于构建出了一组自以为完美的框架。在我的设计中,事件处理机制,使得系统能在第一时间对外部环境的变化做出相应;基于虚拟机的控制层逻辑,简化了控制过程的编写。
于是,在之后的周会上,我做了一个PPT,饶有兴致的向小组展示了我的设想。听完我云天雾地的描述,每个人都懵懵懂懂。这时,梁老师上来讲了另一个实时系统的模型。在我看来,他的系统从性能上讲要比我的慢不少,但最大的特色,就是代码编写极其简单,能让人把更多的精力放在现实问题的建模上。
结果在我真正着手搭建新系统时,还是采用了梁老师的设计。因为我最初的想法太复杂,在很多算法都未经验证的时候,选择一个复杂的编程模型,就像在黑暗中行进,身着重装铠甲,每一步都迈得异常艰难。而简单的设计,就像是武侠小说里的夜行衣,灵活轻便。
并不是复杂的设计一定不好,只是任何一个项目只有从简单入手,逐步优化,才能稳步发展。这其实正是软件工程中所说的Iterative Development。
2、从架构开始,层层细化
写程序,最怕拘泥于细节。回想我们做电脑鼠的过程,有一段时期,我们遇到了不少问题。存储器不足,红外线不准等等。小组会后,分下任务,几个人尝试压缩代码,几个人测试红外。后来的一周,每个人的工作都有一些进展,但之后的问题是,如何把大家的代码拼合起来。(事实上,就连最终版本都没有完全用上压缩后的代码)造成这种结果,我想主要的原因是,一开始大家没有从整体上把握设计。虽然有分工,但分工不够明确。
现在想来,当时的做法是:a、划分模块,规定每个模块的接口;b、压缩代码的同学的任务,应定义为:优化一些模块的代码,使其编译后占用更少的Flash空间,同时保持每个模块的接口不变;c、调整红外的同学的任务,应定义为:修改读写红外模块代码,调整硬件参数,使得红外线检测结果更加精确,并保持红外线模块接口不变。
如果当时能够这样做,大家修改过后的代码,就可以直接拼起来使用了。
我们从一开始学编程,就知道自定向下的分析方法,但在实践中却常常忽视。想要更高效的完成项目,一定要先从整体上把握设计,然后分工也好,单挑也好,每个模块各个击破。
3、协同工作,接口至上
在开发程序时,常常把大的项目分成几个部分,分别由不同的人完成。在协同工作时,模块间的接口定义至关重要。一旦接口定好,任何人都不应轻易地去修改它 ,因为接口的修改,可能会对其他组的工作造成毁灭性的打击。如果模块接口设计上的缺陷已经严重影响了内部设计,到了非修改不可的地步,一定要广泛交流,接口设计各方都能够接受修改才行。
在电脑鼠项目的中后期,大家讨论制定了算法模块与运动控制模块间的详细接口,对项目起到了很大的推动作用。
4、如果写不出正确的代码,就先写文档吧
好像大家都比较喜欢先写代码,再写文档(或者不写文档)的开发方式。但有时候,代码并没有我们想象的那么简单,可能几次三番都写不对。面对这种情况,一个开拓局面的做法是先写一片设计文档。
这篇文档可以简略粗糙,它最大的作用在于帮助自己理清思路,写出正确的代码。这种方法对于算法复杂,思路抽象的程序最有效。电脑鼠项目中,运动控制模块就属此类。
我现在在写的摄像头平面定位程序也是这样,数学公式比较复杂,先写出篇文档把所有的公式都计算总结好,让代码编写事半功倍。
5、统一格式,编写优美的程序
这是老话题了,具体的原意不用冗述。代码浅显易懂,结构优美,对提高工作效率大有裨益。
6、一定要有版本管理!!
这个,没有吃过苦头的人永远都不会理解的~当你一不小心改错了代码的时候,当你找不到之前某个可行版本的时候,你就会发现版本管理软件是多么有用的工具啊!好在我们现在有了SVN服务器,以后恐怕想吃这样的苦都不容易了,呵呵!
电脑鼠项目做完,我觉得自己最大的收获在技术以外。与几位师兄愉快的合作,让我体会到团队精神的真谛。这是我得到最大的一笔财富。回想起来,其实没有什么系统的理论,只是下面几个零零散散的小贴士:
谈到合作,我首先想到的却是它的对立面。当我们的教育越来越强调协作的时候,大家似乎忘记了有一种精神叫“英雄主义”。然而,近来的经历让我越来越深刻得认识到,没有单挑的勇气,人往往不会懂得合作。
这要从我和同学办交大开源社区说起。在社区申报之前,我们几个创始人需要起草几份文件,主要是制定社团章程,设计活动方案。这几份文档让我们头疼了好久,因为当时觉得,既然是开源公社,就应该发扬开源精神,这些文件应该让所有成员联合拟定。但无论我们如何宣传,回应的人寥寥无几。当时我还有些失望,难道大家对这个社区一点热情都没有吗?
后来,我们只好亲自把这些文件写出来,并发给所有关心社区的朋友们审阅。这之后,我们竟陆陆续续收到不少回复,有的表示支持,更有的提出了很好建议。
这次经历让我明白,在一个相互不怎么熟悉的新团队里,头脑风暴这样的合作方式往往是不能奏效的。而且,更重要的是,一件创造性的工作,例如一个文件的撰写,一个方案的设计,在起步阶段一定需要“英雄”独立完成。别人能帮你审阅,提议,但不能替你完成工作。合作的目是集合智慧,而不是分摊责任。
在这次电脑鼠项目刚开始的时候,我毛遂自荐要编写上层算法,但我发现下层控制逻辑的接口写得不好,让我难以动工。于是我就催促一个熟悉底层代码的师兄帮忙修改一下接口。但那个师兄有自己的事情要做,无暇顾及,我便在一直等在一边。后来过了很久,我才下定决心,自己阅读底层代码,制定接口,才使得工作再有所进展。现在回想那段时间浪费得可惜,没能默契地合作,是因为自己当时太乏独当一面的气概了。
虚心诚恳,接受意见,是值得尊敬的品质,但在自己被说服之前,一定要坚持主见,不可做那墙头小草。
其实每个人心中多多少少都会有些权威观念。对于来自下级,来自同辈、后辈的批评难以接受;而对来自上级、师长的指示,却不加思索。后一种行为,和前一种一样会让合作畸形。我们向老师学习,尊重老师的意见,是因为老师见多识广,他提出的想法往往让我们豁然开朗;而绝不只是因为他是老师,是长辈。正所谓,真理面前人人平等。
在这次项目的中后期,大家的讨论特别热烈。但并不是每次讨论都能有所建树的。我印象很深刻,有一次两个师兄为了一处错误是谁的原因造成的争执了一个晚上。这让我思考,讨论的真正价值是什么?我们要在何时,为何事,发起讨论?
记得有一次在小组会上,我提出了一个在迷宫中选择路径的算法。结果遭到了大家许多质疑:算法会不会太复杂,致使存储器放不下?内存空间会不会不够用?等等。当我一一回答这些问题时,我发现,我对自己算法的理解更加深刻了,同时,一些自己之前不曾考虑到的问题也浮现出来。会后,我继续思考,才发现当初的设计确实漏洞百出,于是又进一步修改了算法。反复几次讨论后,选路算法终于定稿,几个方案被作为备选,这时这些方案都已经考虑得很成熟了。
所以,我觉得,讨论是一个发现问题的过程。把自己的想法拿来让大家审核挑错,才能让设计更加健壮。但要解决问题,更多的还是要靠自己独立思考,讨论能解决的问题,仅限于有人做过相关工作,已知答案的情况。不然,一个全新的问题,不管拿给谁,都是要花一些时间才能搞定的。
回想开源软件的历史,Linux诞生的过程正印证了这一点。Richard M. Stallman提出GNU构想好多年,开源界都没有拿出一个像样的开源系统来,倒是Linus以一己之力在做学校的课程设计时,完成了最早的Linux内核。后来,Linux被无数的高手改写,缝缝补补,终于成了一个伟大的操作系统。Linux是写出来的,不是讨论出来的,但却是在大家的讨论中日臻完善,终成大器的。
这一条其实是对上一个标题的补充。既然探讨的目的是接受大家的批评,讨论之前,自己一定要做好准备。要有自己的想法,要把自己的想法表达得尽量清楚,有时做一个演示文稿也是必要的。切忌漫无目的的开会,那只能是浪费大家的时间。
在这次项目当中,我常说一句话:“不怕100次尝试失败,只怕江郎才尽1个可试的方案都没有。”比赛前的最后几天,有个师兄紧张得不得了,总觉得这样做不行,那样做不好。但很多时候,一个方案未经实践,谁也不知道是否可行。这时,我们实践的代价不过是多劳动几分钟,而不做尝试这几分钟也只能在郁闷的思考中度过。于是,我总是固执得实践自己的想法,虽然很多时候尝试失败,但也有些问题是被这样解决掉的。起码在新的尝试中,常常会发现些新的线索,虽然实验失败了,但新的线索常会帮助我们打开思路。
在今天的小组会上,一个师兄提到了我们在准备比赛时的一个轶事。
还是在做选路算法的时候,我提出的算法被大家认为过于复杂,实现可行性不高。但我当时并没有被这种理由说服,而是相大家保证,我能把这个算法实现出来。结果当晚,我花了一夜的时间,和另外一个师兄写出了我所构想的程序,并编写了测试代码,向大家展示运行效果。面对这样的事实,再没有人说这个方案不可行了。
实践是检验真理的唯一标准。当你无法让大家相信自己时,拿出实验结果来,拿出自己的成果来,向大家证明你是对的。这胜于一切苦口婆心的劝说。
在NBA的赛场上,往往会出现这种情况:某个队员忽然手热,连投连中,这时他的队友都尽量传球给他,让他进球得分。在做项目时也是如此,当一个伙伴有了主意,而自己却没什么更好的办法时,最好的做法是尽力支持他。
在这次项目当中,我是那个一直手热的球员。几位师兄没有因为我是小字辈,忽略我的建议,而是肯定我的想法,并给予我最大的支持,这让我非常感动。
我想在今后与人合作的过程中,我可能还会遇到类似的场景,可能还扮演MVP,也可能扮演他的队友。定要记得,在合作中不看辈份,不谈资历,如果手热,就勇敢地秀出来,如果队友发挥出色,就慷慨地传球给他。
周日电脑鼠的比赛尘埃落定,如大家所料,我们的小老鼠在决赛里表现得一塌糊涂,十次尝试都没有能走对第一个岔口。然而,能挺进决赛,已经大大出乎我们的预料了,毕竟与那些参赛多年,积淀丰厚的队伍相比,我们一个月的努力实在显得过分单薄。
比赛过后,小组的每一个成员都特别兴奋,这兴奋来自于不期而至的奖励,更来自于对自我的肯定——看着自己多日的努力终于结出了硕果,还有什么事比这个更长人信心呢?
今天的组会,梁老师有事没来,大家却已然摩拳擦掌,准备启动新的项目了。这种氛围,哪怕在ACM班,我也是未曾体会过的。从大家自信的笑容,我看得出我们的小组正渐入佳境。
莫犹豫,莫彷徨,勤实践,多思量。愿每个人都能借此东风展翅高飞,释放出自己最大的能量。
最近忙得一塌糊涂。后天要去参加一个电脑鼠走迷宫的比赛,可我们的程序还有很多问题,这两天都在调试它了。
尽管对这次比赛不抱很大希望,但整个项目的开发过程让我收获颇多,技术方面和非技术方面的。等比赛完了,要好好记一笔。
夜半,与某师兄gmail灌水。
师兄:之前面试经常说太多。这次面,记住了尽量少说。他说我C++不够好,我也直接说"恩",不多说一个字。后据信说:你的诚恳给我们很深的印象...
我: 汗~如果是我,我会说:"嗯。但我想你知道,有一类人写文章,词藻华丽,引经据典,但逻辑混乱,思想浅薄。也有一类人,写出的东西遣词朴素,洗净铅华,而才思敏捷,蕴大智慧。比较这两种文章,别人我不敢说,我肯定愿意研读后者。我认为程序也是这样,语言是设计思想的载体,却不是设计本身。使用高妙的语法固然让人起敬,但这样的程序只有语言功底同样深厚的人才能读懂;而且过多关注语言的细节,会让人没有足够的精力从宏观上把握设计。非大志者所为也~所以,我在学程序时,也就着眼枝干,不拘细节,把学习的重点放在算法和设计模式上~"
其实,我想的这些话,不只是面试时的申辩,也是我自己对程序设计语言的认识。
何谓语言?何谓设计?语言是训马,设计是骑手,设计指导语言;语言是素描,设计是风景,语言体现设计。语言是果,设计是因;语言是表,设计是本。语言是Java,是C++,是汇编代码,是UML;设计是算法,是架构,是数据结构,是Design Pattern。语言是设计的载体,设计是编程之道。
每一个计算机系的学生都要接触到许多编程语言,C/C++,Java,x86汇编语言,各种各样的脚本。但我们真正要学的并不是这些语言本身。学C/C++是为了实现各种算法和数据结构;学习Java,是为了体会面向对象设计的思想;学习汇编语言,是为了更好地理解体系结构;学习脚本,是为了用最快捷的方式解决现实问题...如果学习时只是局限在语法细节上,那就太狭隘了。
随着时间刷洗记忆,我可能记不清虚基类对象的存储模型,但我知道菱形继承的问题和解决方法;我可能不记得匿名内嵌类的定义格式,但我理解了Builder设计模式;我可能忘光了各种寻址方式的隐含寄存器,但8086编程模型我了然于胸。我想这就可以了。
书要先读厚再读薄,学程序最终要达到无语之境。编程之道在心中,任它东南西北风。
PS:我说的可不是那本搞笑的《程序设计之道》哦~
某公司要给我调剂!话说这个职位怎么让人觉得跟做网管似的。我不喜欢。谁逼我做网管,我就T之~~哼唧~~
不过话说回来,看来我是逃不过进京的命运了。如果接受了这个“网管”的职位,一样要到北京复职。唉,定数啊!听天命了~其实北京也不错,真的。
朋友不少,中关村的氛围也很好。离家还近一些,离叔叔那儿也近。不用怕人说听不懂的方言。东西也比上海便宜,尤其是房子~~交通虽然糟了点,但便宜是王道。何况上海的交通也强不到哪儿去。
北京的小吃妙得紧——西门烤翅确实很爽啊——据说开复曾写过一篇北京小吃的杂录,届时一定要好好淘一把。
好玩的地方也多,有山有水有园林,还有连成一片的大学。其实大学才是最美的园林,犹记清华园里落叶银杏铺满径金黄,未名湖畔残荷映柳藏一树秋蝉~
人言,改变可以改变的,接受不可改变的~呵呵~“圣人之治,虚其心,实其腹,弱其志,强其骨”个人修为亦然。不奢望,所以快乐。
又逢周一,晚上实验室例会时来了位学工商管理的同学,招募创业伙伴。基本的意思是,想开发一个网络游戏,觉得别人没有搞过,想来软件学院找一批懂技术的人一起创业。他从头到尾强调了两点:启动资金有办法募集到,开发难度应该不大。
其实,他的出发点还挺现实,如何迈出第一步考虑得相当周到。但当我们问及这个项目为什么有利可图时,他却张口结舌答不上来。只是说,上海市现在有大学生创业基金什么的。给人的感觉,像是要糊弄一下上面,骗几个投资似的。不过,管钱的人也都是有脑子的,连盈利模式都没有的创业计划谁敢投啊。
这让我想起了上周的电子商务课的课程设计答辩,有一个小组的情况跟他们刚好相反,写了大段的策划书,假想自己已经运营着一个成功的商务网站,拥有一大堆的社会资源,什么与跨国公司密切合作,与各大高校关系紧密;在此基础上,他们谈了各种圈钱方式。可这个小组忽略了一个重要的问题,在真正成功之前,他们假设的那些资源是根本得不到的。
这两个案例,正是创业的两个极端:前者目光短浅,毫无远虑;后者好高骛远,不切实际。
在学校,我偶尔也跟同学们讨论创业话题。正想假今日之事总结一下自己的想法。因无实践印证,有的观点幼稚浅薄,还需朋友们多多批评。
1、为什么创业
人各有志,猪星星同学总说,在别人开的公司工作,就得受人剥削,因为不愿被剥削,所以要创业。
我不觉得他错,但在我的哲学里,创业有不同的意义。《道德经》说:“圣人后其身而身先;外其身而身存。非以其无私邪?故能成其私”。人要获得自身的利益,就要心在身外,考虑如何为别人带来福祉,以无私之心处世,赢得自身利意的丰收。用经济的观点看,这正是发现需求,填补需求的过程。所以,在我看来,创业就是一个人在发现某种社会需求后,努力填补需求的“善举”(当然,老子不认为这种行为是善:“天下皆知善之为善,斯不善已”),它的初衷就是行善积德。怀善心创业,不作恶,才能修成正果。
2、创业的条件
如前所述,创业的第一个条件,就是发现需求。这和做研究不一样。科学家只要觉得一件事情有趣,就可以去研究它;而创业者必须确保自己的项目是有用的。
创业的另一个条件,就是要有足够的能力来启动项目。俗话说,没有金刚钻,莫揽瓷器活。不现实的项目,无论多么美丽,都只是童话而已。我理想中的创业能力应包括技术水平,人脉关系,公关技巧,组织能力。它们就像一个团队的四条腿,瘸了哪个都跑不起来。
创业的第三个条件,就是要有一定的经济基础。毕竟起步阶段一定是赔钱的。社会上的风险投资,政府的创业基金,包括个人积蓄,总之有一样就行。现在上海的创业环境不错,倒是有不少人在打这个大学生创业基金的主意,但没什么确切可行的想法,想空手套白狼是肯定不行的。
嗯,貌似主要的想法也就这两点。可能随着时间的推移,经历的增加,这些想法会天翻地覆吧~到时候回看今日所思,定要再增几分感慨,呵呵~
记得联读班的时候,程序设计课的大作业是写一个计算二十四点程序。那时,枚举所有解的程序大家都会写,而困难的是如何从这些解中筛选出通过等价变形得到的重复解。同学们绞尽脑汁,设计方案千差万别,写了复杂的代码,但没有几个效果特别好的。(我记得那时文野的程序貌似是最成功的一个,但想不起他用的什么算法了)。
前些时,我在某家公司校园招聘的笔试中,邂逅这道题目。(不得不再次感慨他们的题出的火星到一定的境界了。)只是没有剔出重复的要求。不过这次我倒是想到了一个不错的消除重复的好办法——用随机算法。
其实原理很简单。一个如果两个表达式是等价的,那么无论我如何选择参数,它们计算出来的数值都应该相等。如果两个表达式只是碰巧在这么一组参数上算得等值(24),那么当我改变参数,很大可能性会算出不同的数值。
根据这个原理,我写了一个简单的24点计算程序。下面的frame里是一个javascript版。
已经在IE和Firefox浏览器中测试通过。跑起来可能会有些慢。
随着offers陆续到来,求职工作接近尾声。总的来说,我人生中这首次求职经历还算比较成功的。面试了三家公司,两家已发录用通知,还有一家大概这周就会出结果。大概总结一下这几次面试的体会,或许对同道朋友们会有所帮助。
求职场景:
1、我投的三家企业两家是跨过公司,一家是国内同行中的佼佼者,企业文化都是相对自由,强调创新的。
2、我在学校是计算机科学与技术专业,准备将来走技术路线,所以我申请的职位都是软件工程师。
3、我所接受的面试,都是技术面试。
经验总结:
1、争做一个好同事
参加技术面试,面试官一般自己就是工程师。对他们而言,面试不是在招下属,而是在招同事。所以,一个人在面试中所有的表现就是要证明一点:我是一个好同事。
你可以向面试官展示自己的技术能力,让他觉得你很能干;也可以适度和面试官调侃,让他觉得你很可亲。但你不能作秀,不能拍马,因为没有人愿意跟一个带着假面具过活的人合作。
“争做一个好同事”,我想这是应对技术面试的基本思路。要判断面试中的某个行为是否得体,只要套在这个标准上一量,就能知道个十之八东篱把酒黄昏后九。
2、自信是胆不是皮
参加面试自信很重要,但如果对自信理解不当,反而会产生不好的效果。我现在感觉,对面试者而言,自信是胆子,而非脸皮。
有的人在面试时会刻意地把自信写在脸上,程序化的微笑,上扬的语调。态度方面,对自己的话笃信不疑,就算出了差错,也能很快为自己挽回面子。我觉得,这样做不是上策。因为这样很容易让人觉得此人浮躁,自负,不可靠。
其实以平常心去对待面试就好了。试想如果有一天,一个同学来问你一道题目,你会如何应对呢?该皱眉思考,就皱眉思考,理解不清的地方就虚心请教,真要是想不出来,也不必找理由,把自己想到的都告诉他,然后说:“不好意思,我只能想到这些了。”面试也就是这样。
总之,自信是用来定心的胆子,不是吸引人的脸皮。
3、外语是表交流为本
如果面试官的是老外,而自己的英文又不好,那就不要讲太多蹩脚的英文。(当然,我是指在技术面当中。)对软件工程师而言,我们有太多的交流方式。UML图,伪代码,程序都可以帮助你把思路表达清楚。技术面试,面试官想考察的是分析解决问题的能力,和表达自己思想的能力。所以,尽量选择自己擅长的方式进行交流。大不了在最后补充说:“My English still need improvement.”
当然,如果本来外语就很好,那就更是锦上添花了。
4、把握时间当断则断
这是我在一场面试出的问题。一道题目没想清楚,又不肯放手,结果拖了很久,以至于后边的题都没时间做了。一般情况下,面试官都会注意时间的,觉得在一道题目上花的时间太久了,他们会打断的。但有时他们也会忘记。所以应聘者本人最好心中有数,不要在一棵树上吊死。
5、准备几个聪明的问题
通常在面试的最后,面试官会给你一个提问的机会。这个是可以之前准备的。深刻的问题可以让人觉得你有见地。但也不可太刁钻,叫人回答不了。
我一般问一些公司文化相关的问题,这种话题面试官一般会谈得比较开心。
而且这种问题最好多准备几个。记得我在某公司面试,一次连上三场,三个人最后都让我提问。面到第三场,我实在没什么好问了,只好有跟他探讨了一下面试中的一道题目。
6、功夫在诗外
最后一句话,“功夫在诗外”。我经历的这些面试,问的都是很基础的知识,考的都是最基本的能力。只要平时专业课认真学了,知识消化了,面试问题都不难。所以,好好学习,勤于实践才是王道。