这一点错,那一点错,错到一起就是大错。 ——《我是特种兵之利刃出鞘》 |
编程是一项聪明人玩的游戏,它既是对智力的考验,也是对习惯的考验,智力的好坏取决于父母的基因,人们无从左右,但习惯的好坏却是可以不断培养。一项由美国芝加哥大学国家研究组织进行的综合社会调查,公布了“十大最痛苦工作”排行榜,其中IT主管成了最让人痛苦的职业。程序员如何才能让自己的“痛苦”的职业不那么痛苦呢?
世间少有天才,所谓天才,只不过是把别人喝咖啡的功夫都用在工作上了。所以,对于绝大多数还称不上天才的程序员而言,以下这些编程的好习惯都是无数前人智慧的结晶,具有相当意义的参考价值。
(1) 估算解决问题所需要的时间。为自己定一个时间限制,如果在这期间未能解决问题,那就去寻求帮助,或到网上找答案,而不是尝试去做“超级堆码员”,因为很多问题,你很少会是这个世界上唯一一个遇到的人。站在别人的肩膀上,会让你的形象变得高大、伟岸。
(2) 理解编程语言的原理。三流的人才懂应用,二流的人才懂开发,一流的人才懂原理,要想学好一门编程语言,掌握语言的原理是必不可少的。各种语言之间存在相似之处,你所选择的语言,你应该觉得“舒服”,并且能够写出有效(而且简洁)的代码。最重要的,让语言去适应项目,反之亦然。
(3) 重视,但不过于注重程序的设计模式。在大中型系统中,引入设计模式,往往能极大地提高系统研发的效率。但设计模式并非万金油,有时候,写一个简单的算法,要比引入某种模式更容易。如果一个100行就能写完的脚本,最终却使用了8个类,10个接口,外加一大堆范式和标记符,结果导致97%的代码不做任何事情,这种优化又有什么意义?在多数情况下,程序代码应是简单易懂,而不应该是老太婆的裹脚布—又臭又长。
(4) 做好版本控制,并及时备份代码。编码时,最痛苦的事情不是有多少bug没解决,而是突然停电了,一天的工作却没有保存。版本控制时,最好使用版本控制软件。无论什么时候改变自己的程序,它们都会将其保存为.bak文件。
(5) 对项目文件归类保存。可以把项目文件放到SOURCE、HEADERS、MAKE、EXES等不同的文件夹中。如果工程包含多个源文件,则可以建立一个README文件,注明每个源文件、数据文件、临时文件以及日志文件(如果有的话)的作用。还可以注明编译和运行步骤。
(6) 动手编码之前,先做好分析和设计。项目开始之初,不要急于编码,而应该做好详细的需求与设计。做需求确实很难,不然也不会有程序员发出这样的牢骚:需求无非两种,一种是“你妹的,这还用做?”,另一种是“你妹的,这也能做?”不仅如此,实践和分析设计过程也可存在很大的矛盾,但是好的分析会避免过早走向一个错误的方向,好的设计可以避免混乱,否则,很有可能忙活了很久,最后发现方向错了或是架构错了,需要不断的监测、修改与调试,甚至是完全推翻以前的工作,重新设计,工作的成果看起来更像一个三岁小孩的涂鸦,而不是意见艺术作品,“捡了芝麻却丢了西瓜”。永远不要在没有任何设计的前提下就开始编码,除非所编代码不重要。
(7) 多向其他优秀程序员学习。你有一个苹果,我也有一个苹果,我们交换苹果,你我还是有一个苹果;你有一种思想,我也有一种思想,我们交换思想,你我就有了两种思想。其实,一个人能走多远,要看他与谁同行;一个人有多优秀,要看他有谁指点;一个人有多成功,要看他有谁相伴,更何况“一山总比一山高”。休息放松固然重要,但需要适可而止,生命不息,奋斗不止,尤其是年轻的时候,更是如此。时间的强大是不可逆转,再繁华的都会归于尘土,与其把大把大把的时间浪费在打dota、玩三国杀或是无聊发呆上,还不如与其他优秀程序员坐在一起边喝咖啡边交流或是研究他们编写的代码,吸收他们的经验转化为自己所用。在与这些人的沟通中,学习他们解决和自己相同的任务时所使用的方法,在此过程中所学知识可能会帮你省下几个星期的时间。我们不赞成与臭棋佬下棋,棋会越下越臭的观点,但不可否认这样一个事实:和什么样的人在一起,就会有什么样的人生,和勤奋的人在一起,你不会懒惰;和积极的人在一起,你不会消沉;与智者同行,你会不同凡响;与高人为伍,你能登上巅峰。
(8) 优化代码。优雅的代码非常的易读,所以如果时间允许,应该尽可能地优化代码,对时间和空间进行合理分配与使用。之前声明的一些变量,现在可能没用了。同样,并不依赖循环的一些声明可以移到循环模块之外去。否则后续开发或是技术提供会比较困难。但也需要注意,优化后的代码并不是越简短越好,用的语法越偏僻越好,因为晦涩的代码,维护成本会非常高,而且好的代码不但要实现功能,更要好维护,最好是A写的代码让B能很轻易的理解和修改。
(9) 加强测试。测试的重要性并不亚于开发,所以要非常注重程序自测试。测试时,一般使用工具为主,人工为辅的策略,工具包括用单元测试,assert语句,代码测试容器,人工指用 print 和debugger 一行一行跟踪。
(10) 使用输出日志。打印输出函数可以跟踪变量的执行,但频繁地插入打印会使得屏幕的输出很乱,而写一个日志函数,可以保证 Debug 的时候的输出以一种统一的,可管理的方式出现,这样在最后发布稳定版本的时候,只需要简单的几行命令就可以从代码中剔除所有的日志打印行。
(11) 检查代码。代码要经常检查(包括自查和其他同事检查)。在提交代码前,找个同事一起坐下来,向他解释代码做了哪些修改。这样做的过程中通常能够发现代码中的错误,而不需要同事说一句话。这比自己审查自己的代码要有效的多。将代码的bug发现的越早,成本越低。
(12) 回顾代码。在看到自己以前的代码时,通常会有两种矛盾不同的想法:第一种:我怎么写了这么烂的代码;第二种,我写的代码还是挺有成就感的。其实,经常回顾以前的代码,往往会触发新的想法,以及对以前编码更深层次的思考。
(13) 编码不能想当然,任何时候都要严谨。一个简单的项目,表面上看可能可以轻松完成,其实不然,一个使用Microsoft Access的、只有3个页面的网站,最后很有可能会变成一个有30个页面并使用SQL Server作为数据库的网站。所以除非有一个类、组件或者一段已经写好的代码,并且在现有的项目已经测试通过,否则,切不可掉以轻心。
(14) 任何软件都会有BUG。BUG像幽灵一样,它是永远也改不完的,所以关键是要修复严重的、影响业务的、显眼的Bug。一个软件项目,参与的人数越多,并不代表软件可靠性越好,相反,“人多手杂”,而且需求越变更,潜在的Bug会越来越多,很多时候,也许只是修改了一行代码,其很有可能影响到很多关键流程的执行。
(15) 养成耐心、冷静的好习惯。作为一名程序员,不能像普通人一样被计算机掌控,而应该作为计算机的主人,去掌控计算机。所以,一定要有足够的耐心,当程序运行不正确时,要冷静下来,站在计算机的角度去看问题、分析问题。
(16) 遵循编程规范。例如“==”与“=”的区别;合理使用缩进;使用循环和条件语句时,先把左右括号对应起来,然后再在里面写其他语句;避免使用幻数(magic numbers);使用有意义的变量和函数名称,例如,使用‘radius’来代替圆的半径,而不是用‘r’来表示。
(17) 了解底层知识。优秀的程序员不会只关注程序如何实现,而会深层次地剖析其实现机理,所以,程序员要对自己的操作系统和硬件要有足够的了解,从CPU的执行方法,到操作系统的运转,到程序的编译链接,到代码的加载与运行,到程序的调试,最后到实现的功能这一整套的内容,只有做到这样,才能真正提高。
(18) 要聪明但不要“小聪明”。不反对走捷径,但是一定要论证充分,否则,可能会产生很多潜在的bug。编码中走捷径也许能够提高程序的可读性以及效率,但是如果论证不充分,不能把所有的潜在问题考虑周全,很有可能犯了丢了西瓜拣了芝麻的错误。最好的论证方法是多和他人商量,请别人检查自己的工作,将问题提早暴露。所以,不要为了做成某件事却忽略过程的连带效应,也许有一天你会为你当初的“小聪明”买单。
(19) 要有创新的想法。对于大型企业而言,离开了创新,就等于失去了生命力,对于程序员个人而言,离开了创新,就等于停止了进步的脚步。虽然说天下学术全是抄,俨然一副“君不见创新项目一大堆,都被抄死化成灰”架势,但是不能因此而放弃创新,因为大地不可以因为有畜牲吃草而不复生机,山泉也不会因为有王八偷水而不冒活水。所以,无论工作有多忙,生活有多艰辛,都要尽可能地保持有一颗生机灵动的心。因为这个东西是别人偷不走的,也是最大的财富。即使暂时不具备这个东西,也要在生活中用心经营、好好培养。创新不一定要是改变全世界的大举,也不一定非得是世界上第一个做这件事的人,任何一种能改善生活的行为都可以认为是一种创新。例如写一个脚本去改变重复劳动或是采用什么方式解放自己。
(20) 对待知识要刨根问底,要有“打破沙锅问到底”的决心。“知识就像内裤,看不见却很重要”,在工作中,不能只知其然,不知其所以然,要不懈追求对细节一丝不苟的实干作风与敬业精神,而不是浮于表面,满足于填鸭,满足于考试交差或随便应付,请记住,这个世界牛逼的人少,装逼的人多,要从深层次去想其背后的思想和原理是什么。任何行业都有核心技术,掌握某一项核心技术,就可以让你进入这个行业并在其中生存,反之仅仅浅尝辄止,就会让你遭遇失败,抱怨不公。例如学会了C++面向对象程序设计,就应该弄清楚一个对象在编译后,在汇编代码中是如何被初始化的;就应该弄清楚这个对象的各个成员在内存中是如何存放的;就应该弄清楚当一个成员函数被调用时,编译器在汇编代码中加入了哪些额外的动作;就应该弄清楚虚函数的调用是如何实现的,而这些东西没有人强迫你去弄懂,只有你自己。想得多了,自己的层次才有可能提高,如果只是停留在被动的接受,那很难有所提高。
(21) 尽可能复用成熟代码。如果有现成的允许使用的经过测试的代码或程序库,并且有人维护或维护成本可以接受,程序员应该尽量使用现有代码和库来节省时间和开发测试成本。
(22) 多一份追求完美的执着。人是不完美的,但人们都在追求完美,程序也一样,所以程序员要去追求完美。追求完美的人更容易出色、更具责任心,做事往往也显得更专业。
(23) 不要心存侥幸,可能出错的地方一定会出错,偶尔发生偶尔不发生的问题就是大问题。所以,对于一些常见的问题,一定做到防微杜渐:每个变量都做初始化;每个函数都做声明;引用每个参数都会做有效性检查;在可能出错的每个地方都会做边界条件检查等等。这样开发出来的程序一定会稳固很多,就是出错也会很容易修改。而一些没经过正规培训或是半路出家的所谓的高手,一般开发速度很快,三下两除二的就开发完成了,结果很可能出现“功能大体实现,bug总是在变”的情况,最后花费很长的时间来修改代码中的bug,总时间甚至会大大延期。而真正的高手,追求的境界是零缺陷代码。
每个人的路都在自己的脚下,自己过得怎么样,也只有自己心里明白。要想让自己的编程变得快乐有趣,还是应该努力培养一些好的习惯。也许上面的这些好习惯,要想都能在实际生活中落实并不是一件容易的事情,恐怕只有“大牛”们才能完全做到了,但只要你不断地朝着那个方向努力,相信你也会在这个努力的过程中得到长足的进步。