« 法线贴图的压缩格式比较 | 返回首页 | 资源文件的转换问题 »

程序员应该怎样提高自己

经常有小(我 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 就够了。它是进入开源世界的敲门砖。一个能力超强的程序员,如果不融入同样顶尖的团体,就是在浪费自己的人生。

Comments

感谢分享~

任意普通程序员浮于表面不了解的领域,顶尖程序员都是百倍千倍的效率

我只是好奇什么东西 顶尖程序员可以百倍生产力于普通程序员 谢谢。

说点个人以往的见解:多学习,多交流,总归没错。 但是造不造轮子,这事取决于轮子适不适合。没有轮子适合,那就只能自己造了,这个没啥办法。而且啊,如果自己遇到需求的话,也没办法和作者沟通并说服作者的。一个是功能deadline的存在,一个是作者不一定会因为特殊需求而开发。 不过通用的可以考虑和作者沟通,甚至提交pr。

感谢云风大大的分享

可以对文中有不同的意见嘛,但不能以此攻击人!@呵呵

在游戏行业67年了,一直处于迷茫状态,虽然未有频繁的跳槽换工作,但也不甘于"养老",想做点什么总感觉欠缺了很多,希望能从云风你这里找到自己的目标,希望三五年后自己还在这个行业。

想转载到个人公众号,不知可否?

我转载一下可以吗大神

一切有为法,如梦幻泡影,如露亦如电,应作如是观。

赞同。学习这事,总是闭门造车是走不远的。

另,回个评论:
@达米安
git 对二进制文件也具备相当不错的可用性,只是需要配套的 diff 工具。
参考:
https://git-scm.com/docs/gitattributes Performing text diffs of binary files
https://github.com/ewanmellor/git-diff-image

常看大佬话,方知差异,多自省。我是学物理出身的,成为程序员,是因为喜欢这一行。用代码做一些事情让人欢喜。如何提高自己,我很赞同云风。我自己认为,在实际开发过程中,重点是高效的完成任务,解决问题。在项目完成后,应该做一些总结,将自己曾经困惑的地方,细化,刨根问底。提高,我想是在一次的一次的碰壁中完成的。多看书,多了解新知识,新领域,也是提高自己的方法!

云风高论,深有同感。

受益匪浅,该写篇大神觉得有用的git经验谈了

我什么时候才能理解:对于新手 没有bug的代码就等于白写!

每个人对编程的兴趣源自不同,我喜欢在虚拟世界里创造,看到代码结构里诞生具体物,控制,观察,预测,有时来自于直观映射,有时发现不同事物之间联系,将之抽象,有时还有意外bug/feature的惊喜,...程序员常常将编码浪漫化,实则恶臭,我总不能说,我常在在屎山中开辟道路,有时误以为那里闪耀着金子般的价值,而离美妙的实践还差得远


越来越感受到解决问题能力的重要性,有时候靠的是经验,但更多的是凭嗅觉!

越是读到类似大神写的这种文章,越是觉得自己似乎不适合做程序员,或者一个快乐的程序员,因为自己连第一步的境界都不曾达到,但自己在技术这条路上始终提醒自己:基础很重要,有了稳固的基础才有可能写出高质量的代码。感觉需要自己做的还有太多。

在豆瓣上看《UNIX编程艺术》书评时,看到前辈的书评,时间时06年,这么久了,还以为链接会失效了,点进来一开,哇,前辈的博客一直在更新,我要订阅了

谢谢blog分享,评论区也有许多分享,很多值得深思

大神最后直切要点啊~其实实体设计也一样有类比的~本来挺高端的产品~最终却让一群人给搅和得乱七八糟~惨不忍睹~

"会用轮子"的难度,不单指读读文档正确使用。我想指的是,在用开源方案的时候,肯定有不如意的地方。说服维护者按你的想法改造;或是放弃自己的想法,改造自己的使用方法;或是两者的中间点。这是比自己按自己的想法造轮子(或 fork 出去自己改)难很多的。

但收益也大很多。你可以吸收顶尖开发者的思想,提高自己的眼界,从更广阔的视角看问题。

各种工具的参数,我是真的觉得头疼。

是也乎,( ̄▽ ̄)
无法同意更多, 10多年前, 开始面试时, 就将 卫斯理 小说是否算科幻小说, 列为面试问题之一...

最令俺共鸣的是:
> ...造轮子固然有趣,会用轮子却更为重要

追求代码的效能/优雅, 没错,
但是, 开发语言是为了减少软件开发时不必要的心智消耗而创造出来的,
进一步的, 所有开发语言多年积累聚集的生态, 更加是各行各业解决各种实际问题后, 程序猿自发自觉的将经验抽象为对应模块/库/工具/...

所以, 如果发现自己的开发乐趣不在代码本身,
而在代码形成软件解决的问题上....

那么, 也没什么问题, 专注快速完成 MVP, 在实际使用过程中持续优化,
这种成就感, 一点也不亚于从一开始就用完备宏观整体性思维设计/构建出简洁优雅又强力的代码来的成就感差...

所以, 在俺来看, 程序猿提高自己, 无非是增广见识,
无论在技术领域, 还是在现实领域...

总之, 反复在一个领域/岗位作事儿,
很容易退缩到只有当前领域工程的优雅/效率/功能/...上来,
而, 一但领域行业发生变化,
是真的没什么储备技能来面对天翻地覆大变化的...

所以, 最简单的开始就是:

- 坚持写技术/学习/思考/...笔记
- 并持续公开出来...
+ 输出是更残酷的输入...
+ 很多时候只有在书写时, 才知道自己哪儿没真正理解...
- 也只有输出/公开出来, 才可能有机会将自己的思考纳入到其它能人圈子里
- 当然, 现在新人想通过自己专有网站来吸引注意力, 从而进入圈子太难
+ 流量基本被巨头控制住了
+ 除非象云风这种固定域名/模板/格式, 坚持 10年以上稳定输出...
+ 否则, 建议同步在 微公众号/简书/知乎/... 并链接回自己的 blog
+ 进行, 一点儿人肉 SEO 吧...

PS:
以及如何高速提高表达能力?

交个女朋友
或者是养条狗

逼自己张开始嘴, 才能知道如何言说了...


最近有遇到一些瓶颈,感觉写代码越来越重复且没意思了,和感谢云风大佬的这篇好文。

顺便反对楼上几位的观点,学习主流的知识在大部分场景是够用了,但很快就会遇到瓶颈的。。。

在遇到犄角旮旯的问题时,却没有犄角旮旯的知识,你就知道会有多痛苦了。很多问题不仅谷歌没有,连开源社区都找不到答案时,你就后悔没学这些犄角旮旯的知识了。。

和语言一样,不同的IDE也是面对不同的场景的,vs在我写unity,写c#时很爽;vim在我用c/c++写底层库时很爽;goland在我写golang时很爽;vscode+插件用以应付其他场景。。

就轮子而言,固然有很多重复的轮子,但是难道就没有下个普世而有用的轮子嘛?比如提到的git其实是一个未完成的杰作,包括git submodule在内,一些功能确实并不好用,请你们做一个更好用的,我一定捧场。。

正是网易这种伪大佬,用他的狭隘,处处传递和散播扭曲的编程价值观,才导致码农界鄙视链越来越严重。最求些犄角旮旯,并引以为傲,在大局观上毫无建树,在宣扬命令行比IDE更具优越等感这种低端的观点上绞尽脑汁,悲哀啊

还有优化,它仍然很重要,但软硬件的发展,程序员在这上面的投入比越来越少,是件好事情,程序员有更多精力思考完备性,可维护性,选择正确的算法,和更加熟悉业务,可以不仅仅满足于修好一个精致的小木屋,而能够构建钢铁的苍穹


程序今天是个很大的领域,不应以一个角度去判断是否优秀,
比如,有理论角度的程序员,他并不对某个具体编译器参数熟悉,比如cl得有经验,gcc要简单得多,而clang的则不查手册很少人清楚使用,在在他的领域里工具够用的情况下,他没这样的需求,他甚至只需要python这样几无参数的解释器,

而另一方面,有体验角度的程序员,他热衷于体验各种上层IDE,甚至像特效非线编辑美术工具unreal,unity这样的软件,目的是学习这些软件的设计方式,但他对vim,make这些可能一无所知,

我想在今天做技术,每个人某种意义都是畸形的,领域太大,生态丰富,都拜工程师创造的奇形怪状的历史轮子(非贬义),不像数理,大家都在一套体系下,

说起git, 它是极好的东西,但离开代码文本(除代码文本,还有很多结构化的东西啊),它立刻缺少可用性,他有晦涩的概念,以至于外行很难接受,谨举一例,stage(暂存区)我认为不是一个直观且必要的概念,

未来也许会改变,程序会变成更加标准化,精简可用,但我相信会是一个更加高层的概念,因为其他领域,哪怕一个轮子(字面意思),几乎没人完整地知道如何制造出来

深感认同。

鄙人一直在小公司干游戏开发,一些原因导致没有在大公司学习的机会,所以游戏也没做过什么大项目,很想学习下大公司的大型游戏项目框架,云风大哥编程这么多年了,大型项目开发了不少,能不能开源一个您的游戏项目源码,让我学习学习。

不是程序员,但经常玩 git clone 😏

这应该是程序员一辈子的追求,不管今后是不是写代码,升华自己优化自己是逃不了的命题;
每个年轻的程序员应该常常总结自己,我现在想做的是commit to starter

虽然不是程序员,但也从你的分享中学习到了一些精华。谢谢云风!

谢谢大佬的分享!

"作为一个程序员该怎样提高自己" 这其实是个大问题,就像“我想提高英语水平”这样的念头每个人都有,但是不知道入手点和评估是否达到目标了,“写出更高效的代码”就是个很具体的入手点和评估标准。

棒棒哒,云风大大写的很棒,如何分解复杂问题,确实很考验人的能力

Post a comment

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