46

程序员应该怎样提高自己

 4 years ago
source link: https://www.tuicool.com/articles/Fj6RfaR
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

经常有小(我 20 岁左右的)朋友问我,作为一个程序员该怎样提高自己。每个人的经历不同,所处环境不错,其实这个问题很难具体回答。不如好好写一篇总结,以后就不必每封 email 都重新写一次了。

纵观我近 30 年的编程生涯,在每个时期,我看到的东西都不同。想必再过 10 年还会有变迁。我只能写写当下眼界所及之处。

引我爱上编程,并乐此不疲的学习,是“我能写出更高效的代码”这种乐趣。如果一个人在学习编程开始,不努力让自己的代码变得更高效,发现不了优化的乐趣,我想他很难爱上编程。Don Knuth 说,Premature optimization is the root of all evil ,这句话背后的道理,不必一开始就强行接受。evil 最能蛊惑人心,但是我们需要它引入门。

朝着优化这条路走下去,你会有自发的动力去了解计算机的本质架构,理解操作系统,理解内存模型,理解新的软硬件技术(它们大多数都是为了让程序跑的更快而发明出来)。否则,现在去学习这些东西,并不会体会到现实的意义。软件开发在今天,大部分的工作都在很高的层次了,大部分人的日常都在完成一些琐碎的业务,用不到这些。但实际上,你在融汇贯通后,可以在很高的层面凭经验就能从蛛丝马迹判断出底层发生的问题;可以从一些代码片段,判断出整个模块的设计意义。这些是无法作为单独的技能学会的。

精通一门语言是最基本的要求。所谓精通,就是要了解这门语言的各种阴暗角落。用每一样语言特性的背后的代价。知道在面临各种问题时用这门语言解决该问题的惯用法。大部分通用语言都会有设计缺陷,表现在具体方面就是面对某些问题,写起来直接了当,而另一类问题时却要绕很多弯弯,这些绕弯弯的部分就需要用某种模式去弥补。我认为,所谓编程的设计模式,并不是跨语言而独立存在的,它们是强烈依附于编程语言的。《设计模式》这本书,我读过的版本是基于 C++ 的,设计模式被谈论的更多的是在 Java 社区。这类模式都有很深的语言烙印。我们学习设计模式其实学的就是一门语言的惯用法。

初次学习设计模式时,肯定会有豁然开朗的感觉。但不应把自己陷入其中。为了提高一次层次,就必须精通至少第二门的语言。我的第一语言是 C ,第二语言是 Lua 。但对于许多人,肯定会有很多更好的选择。多看看不同的语言下解决问题的不同方式,有助于提高编程技能。

在我谈论程序员的编程技能的时候,我指的通常是两类能力:一是运用熟悉的编程语言,用在该语言下最高效的方法解决需求的能力;二是领域知识,尽量多的了解工作所处领域前人的积累,已存在的软件层次的接口,接口背后的代价。这两者缺一不可。不要用自己学习能力强为借口,认为随时可以进入一个新语言,一个新领域,而不会比别人差。不管是一门语言的使用,还是对一个领域的了解,都是需要长期的实践刻意积累的。

以上,都是我认为一个程序员对自己最基本的要求。这些东西多么精进都不为过。但还有一些更高层面的东西。

那就是分解问题,保持简洁的能力。也可以说是规划和构架的能力。这是超出编程语言,具体问题领域的,不过绝不能绕开它们。如果一个程序员编码很粗糙,或是对所在领域一知半解,我绝对不会信任他做的设计。

Keep It Simple, Stupid 谁都会说,但不受优化的蛊惑,我觉得很难。因为完全对优化代码免疫的人,我觉得他很难成为一名优秀的程序员。迈不过第一步,就谈不上在下一步有什么成就。大部分软件问题,本质上都是怎么把复杂问题分层次,分模块,化繁为简的过程。底层开发、基础设施建设为什么吸引了很多自命热爱编程的人,不是因为它们有挑战,相反,它们更纯粹,更简单,更容易做取舍。精益求精的人更容易做出成绩。

带着把各方各面都做到精益求精的心,跨越多个层次去看整个问题。奉着此心做取舍,知道封装和简化带来的代价,随时审视代价到底值不值。我很难总结出教条,这似乎真的只能用个人品味去解释:为什么这里要保持更朴素的数据结构,而牺牲高效的算法;那里为了少定义一个 api ,却让一件简单的任务变得更繁琐。

另一方面,规划不仅仅是针对代码,也包括了开发过程的一切。你不仅需要规划问题怎样划分,还要规划每个部分花多少时间和精力,区分轻重缓急。顺便谈谈超时工作的问题,我在前段谈996 的时候就写过,超时工作其实反应的是规划的失误。找到正确的方法做事,最终需要投入的人力能有 10,100 倍的差距;而延长工作时间却无法超过 3 倍工时。提高自己的规划能力,应该先尽力减少超时工作。

前段时间有人问我,现在让你去面试程序员,你会考察些什么。我想了想,最近几年,我越发的不会做面试了。越来越不喜欢用具体技术问题考验面试者。

相比编写代码、调试代码、阅读代码、这些硬能力;我可能更为看重对各类工具掌握的软能力。比如有些人对 C++ 的犄角旮旯了解的一清二楚,却对 C++ 编译器的命令行参数一知半解,只会使用 IDE 开发,我觉得这样的技术栈是非常畸形的。软件的构建流程绝不仅仅是写好代码,就全部交给自动化工具去完成。即使仅局限于写代码,那么用代码生成代码,设计 DSL 解决领域问题,也是必备技能。这些在 meta 层面解决问题的方式,离不开你对构建工具的了解。

我们在日常工作中面临的很多琐碎,大部分都有现成的工具解放你的时间。分析日志 ,加工数据、收集信息,等等。都有很多途径去做。有笨拙的手工方法,有工具语言方便你编写脚本批处理,有现成的工具待你去发掘学习。看看你的工具箱里是不是只有一把锤子?

开源逐渐成为主流,我认为是现代软件开发方式的重大变迁。程序员群体可能是为数不多的,顶尖个体的生产力能够百倍千余于平均水平的人群了。世界范围的开源开发,使得最顶尖的人可以把精力聚焦在不同的点,极大的放大他们的价值。所以造轮子固然有趣,会用轮子却更为重要。但大多数情况下,我们不能像搭乐高积木一样的组装软件——虽然那一定是每个开源模块的努力方向——理解和沟通的能力就显得格外重要。

有一段时间我在招聘应届毕业生时甚至觉得,考察写的代码好不好一点都不重要。真不如看看他写的文章,写的东西简单还是复杂不重要,就看有没有能力把事情说清楚。

在开源的世界中,不是你有能力读懂别人的代码就够了。如果你想使用,就必然面临你特有的需求,也有极大的可能性遇到别人没有遇到的问题。和作者沟通,和开发社区建立起良好的关系,说服维护者按你的想法推进这个软件的发展,或是吸纳别人的想法修正自己的设计,这是非常重要的技能。而弄个 fork 自己随心所欲的修改,甚至重起炉灶自造轮子,自己的层次就很难进一步突破了。

谈到这里,不得不提的是, git 绝对是软件行业近二十年最伟大的发明之一。它值得每个程序员正儿八经的学习,绝不应满足于会 commit push pull 就够了。它是进入开源世界的敲门砖。一个能力超强的程序员,如果不融入同样顶尖的团体,就是在浪费自己的人生。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK