很多年前我认为编程是简单的,后来我意识到编程并不简单,因为在我思考什么是编程和程序员做的事情的过程中慢慢有了转变。
最开始我认为编程只需要告诉计算机做什么,这部份编程还是相对容易的。在实践了二十年后我认为这部份编程也很容易。
定义 1:程序是将输入转化成输出的东西
程序员就是编写程序的人,编写程序是一门艺术。
现在给程序的定义添加一些限制。
定义 2:程序是将输入转化为输出的东西,需要遵循一下限制:
- 程序的输出是优美的。
- 程序的输入是优美的。
- 程序是优美的。
- 程序的输入是完整正确、文档化的。
- 程序是被测试和证明正确的。
- 问题解决的结果是具体说明的。
- 问题是具体说明的。
添加了这些限制之后编程变得相当困难了。
对于一个特定的问题,这些限制可是适当放宽。
一些常见的场景是这样的:
不需要维护的程序
我们经常要写只需要一次输出结果的程序,在这样的情况下,在以后程序不需要维护,所以程序不需要特别优美和描述清楚。
我的 Erlang 书就是一个例子,一旦这本书出版了,维护输入和制作这本书的程序就没有必要了,结果看起来很好,很多的 XML 文件和一些测试程序将来不需要维护。
这本书的勘误表,以及在重新复印过程中的必要的修改,只需要涉及到很少的改变,这样的输入修改是很容易的,即使程序的输入不是文档化的。
需要维护的程序
对于有些需要维护的程序,程序的输入以及程序本身必须是优美的以及良好文档化的。
之前我也一位开发 Web 应用的顾问聊天,他说只要程序的输出看起来是正确的(比如网页看起来正常,程序运行正常。),顾客将会认为这个项目已经结束了,项目经理将着手进行接下来的其他项目。
没有时间和理解这样的观点:不仅仅是网站看起来正常,而且在开始下个项目前产生这个网站的代码也要清楚冗余和文档化。这是为所有将来需要维护的项目制定的要求。
其他使编程变得困难的事情
还有其他三件事情使编程变得困难:
- 修复本不应该损坏的东西
- 没有时间学习新的东西
- 恶劣的编程环境
这些都是“时间小偷”
修复不应该损坏的东西
我经常需要使用别人的软件,我不是非常理解为什么它能解决一个特定的问题。
最好的情况,我需要使用的程序由一个准确的描述告诉我如何使用,但是经常发生的情况是程序没有描述或者由一个错误的描述。
当文档告诉你说 ”执行 XYZ 然后 PQR 就会发生“,但是当你照做了 ”XYZ“ 但是 ”PQR“ 没有发生时你怎么做?如果你幸运的话写这个程序的人在你周围那你就能够掐死他们,如果失败了那你也能在 Google 上搜索试试运气,又或者看看源代码试着找到答案。
用 Google 搜索去解决一个 bug 和赌博一样十分令人沮丧,我 Google 搜索了一阵,发现一篇帖子,一个可怜的人也遇到了和我一模一样的问题 ,我高兴极了,点开链接……什么都没有,问题还留着。
为什么有些修改对有的人有效但对我没用,是不是怀有恶意的上帝在盯着我,或者我所在的大学的一块地方的物理定律暂时改变了?两台机器的初始环境不一样,所以在一台机器的一种环境中解决了一个问题,到另一台不同环境的机器上就不能使用同样的方法。
就像我希望我们都写 Smalltalk 程序,我们都用相同的环境,Smalltalk 程序员必须呆在一个天堂似地环境中,但这是不可能的,当他们的程序需要和其他程序通讯的时候他们就明白了。
修复损坏的东西是让人双倍沮丧的事情,即使你解决了一个 bug ,你也不能真正知道你为解决这个问题或者使之生效的最后一个修改是什么。
这些事情我估计占据我百分之六十至七十的时间。一次我花了一周的时间尝试使一个损坏的 LDAP 服务器恢复工作,我的老板禁止我实现自己的 LDAP 服务器,但是经过一周的时间与这个用 C 实现,没有良好的文档,损坏的 LDAP 服务器折腾之后,我意外忘记了我的老板说的话,在午休的间隙从零开始实现了一个服务器。
实话说这不是一个完整功能的 LDAP 服务器,但我也不需要一个完整功能的,我只需要一些功能能够正常工作,这非常容易解决。
现在我不会对于实现那些古董级协议感到兴奋了,但从零开始重新实现的最快的方法。
解决了问题但是没有学到什么
我很烂,最擅长与偷懒。但当我想在 LaTex 中插入一个图标时,我不想去读一个 391 页长的手册。现在我知道你会假设我是一个懒惰的不靠谱的性格的人,我也知道我应该先去阅读手册,但我想要在十分钟之内就把图表插入到我的文档中,阅读 391 页长的手册实在不是一个好方法。
当要解决一个问题的时候我会去找一个快速的解决方案,但长期来看,这将是灾难性的。
将文档带到真正的生产环境中,我在 Tex/LaTex 和 XSLT-FO 以及我自己的 Erlguten 之间犹豫。
每三年一次我就有种强烈的冲动想要用后记的方式重写我的所有文档,然后我就会深呼吸直达这种感觉消失。
我猜 Giambattista Bondoni 在 1818 年制作 Manuale Tipografico 是没有特别关心制作排版一页需要耗费一周时间,但我们现在有更多的时间因为我们有机器帮助完成枯燥且危险以及我们不能做正确的事情。
我问过我的老板,他是否需要漂亮的幻灯篇来演讲。他说需要,要我在明天事前做好给他。这就没留给我时间去学习 Tex(我才可能需要一年),没时间实现自己的排版语言(需要 5-10 年),没时间把它记录下来(一周时间),最终我只能用 PowerPoint 了。
恶劣的编程环境
如果你在这种情形下,你将理解我所说的编程是相当困难的。因为办公室就是设计成是编程变得更加困难。我们有开放式的工作空间,噪杂的环境破坏了专注力,手机影响我们,互联网也会分散我们的注意力。
幸运的是我们还好似有地方不被打扰的,那就是睡觉。很多的编程问题就是在睡觉的时候解决的。
这么做有两种方法,在睡觉前记住很多问题,然后睡觉,第二天你醒来就发现一些问题就解决了,很容易。
第二种方法就是在睡觉前将你的问题贴到网上,发条 tweet,第二天已经有人将解决方案告诉你了。
要成为一个优秀的程序员需要很长时间,你需要学习很多很多的东西,你需要知道当你在一个问题上卡住了能够请教谁。
令人吃惊但是是真的
当我写完这篇文章,我想要检查内容的拼写,emacs-ispell 罢工了,我一直使用的拼写检查程序,没有发现 aspell。
我的 emacs 拼写检查器在这台机器上忠实工作了好多年,就在我抱怨我花了太多时间维护修改本不应该坏的东西的时候 emacs 拼写检查器决定崩溃。
我不相信上帝有恶意,也不相信我房间里面左手变得沙发和右手边的沙发的物理定律不同,但有直接证据证明是不通的。
我不明白我的拼写检查器会不工作,所有东西都是正常的,我没有修改任何东西。我安装了一个新版本的 Erlang 以及安装了 Julia,并写了一些讲义自从上次使用拼写检查一个文档。
幸运的是十一分的 Google 搜索起作用了。第二个建议关于如何解决问题以及他们最终起作用了,我也不知道为什么 emacs 不能找到 aspell,没有时间去找到答案。
我猜有些事情我们永远都不知道答案。