成为卓越程序员的三大支柱:意识、理解与责任
作者:Max Kanat-Alexander
发布日期:2017年12月20日
成为或成长为卓越程序员有三个关键因素:意识、理解与责任。
关于“理解”这一主题我已经讨论了很多。事实上,我最近的一本书就命名为《理解软件》。我特别多次指出,你对某事物理解得越深入,你就越能做好它。
然而,除了理解之外,还有另外两个因素共同作用,才能造就一位优秀的软件开发人员。简而言之,如果你没有意识到问题的存在,就谈不上理解;如果你不采取行动去解决问题(这始于承担责任),那么你也无法改变现状。
不过,关于这每一点都有很多值得探讨的地方,它们也是审视如何成为更好软件开发者的关键点。因此,我想在这里与你更深入地探讨每一个要素。
意识
在某种程度上,这是理解的一种专门形式。“意识”本质上意味着你能够感知到某事物并知道它的存在。这在编程中有很多应用方式。
让我们举一个最简单的例子:如果你没有意识到一个Bug的存在,你就不可能修复它。
有时,人们利用这一点来逃避处理问题。他们认为,只要自己没有意识到问题,就不需要为此做任何事情。这种想法可能对也可能错,但事实是,问题确实存在,无论你个人是否知道。如果你的系统存在一个影响数百万用户的Bug,那么你应该意识到它。否则,你的用户将会受苦。他们的痛苦并不会因为你对他们的痛苦不知情而变得合理——也就是说,仅仅因为你不知道,并不意味着问题在宇宙中就突然变得可以接受了。
还有更微妙形式的意识。例如,有些人实际上并没有意识到代码复杂性。他们没有意识到自己刚写的代码很复杂。有时,他们甚至没有意识到复杂性本身是个问题,或者没有意识到其他必须阅读他们刚写代码的程序员会持何种观点。他们没有看到代码缺少注释、难以阅读,或者存在另一种解决问题的方法。所有这些都是程序员意识的各个方面。
作为程序员,提高意识最简单的方法就是愿意走出去,阅读你通常控制范围之外的代码。也就是说,也许你日常工作是处理视频编码的代码。但视频也有其来源——用户将其上传到你的系统中。如果你在视频如何进入编码器的过程中遇到问题,那么也许你应该选择去看看那部分代码实际上是如何工作的。
这听起来简单,但对许多人来说,在情感上可能相当困难,有时甚至包括我自己。人们很容易想:“那边的那些人都是白痴,这糟透了,我只能想办法绕过它。”但如果你没有看过他们的代码,你怎么知道情况就是这样呢?也许你会学到一些对你有帮助的东西。
意识也可以指了解你可以在代码中使用的库、框架或工具的存在。也许你对最新的Web开发库并不完全了解,但如果你是一名Web开发人员,你至少应该知道它们的存在。这样,当你需要决定使用哪个框架时,你就知道该去考察哪些选项。
总的来说,提高意识可以通过愿意体验新的编程语言、新的设计模式、测试思想、新框架等来实现。我个人希望了解新的编程系统和方法。当我听说一种新的语言很流行时,我会去至少阅读其网站的主页,有时甚至会深入研究其文档。这样我至少知道这个东西存在,并且如果需要,我可以了解更多。如果我不知道解决问题的不同方法,那么作为一名软件工程师,我所能使用的工具就会少得多。以这种方式提高意识,可以增加我在面对困难情况时的选择。
这一切听起来可能过于简单,但非常真实:你可以通过提高对编程和程序的认识来提升自己作为程序员的能力。
理解
正如我在别处提到的:你对某事物理解得越好,你就越能做好它。
意识是第一步——你知道某个事物存在。之后,你需要理解它才能做得好。让我用一个虚构的伪代码语言举个例子:
|
|
你认为这个程序是做什么的?看起来它清除了终端,然后打印了单词“Hello”。但老实说,我只是在猜测。我还没有查看clear_screen或write_hello的文档或代码。如果我查看了代码,我会发现clear_screen实际上是把整个屏幕变成白色,而write_hello则是用十五种不同的语言和颜色在屏幕上打印出“HELLO”这个词。但如果不通过实际查看某些东西来理解它,我永远不可能知道这一点。
这似乎是一个过于简化的例子,但在编程中这种情况一直发生。现在我知道了clear_screen的功能,我就可以在其他地方使用它,而不需要思考或花时间重写它。我可以编写一个符合我意图的程序,而不是一个有Bug的程序。我可以为它编写一个有意义的测试。所有这些加起来就是简单性、稳定性以及我们认为是“良好编程”的所有其他品质。而这一切都源于理解。
还有其他形式的理解,我在几篇文章中已经讨论了很多,尤其是《为什么程序员很烂》。这确实是决定一个程序员成败的关键点。还有其他有用的技能——快速打字、良好沟通、恰当管理优先级等等。但关键点是理解。没有理解,你可能是世界上编程速度最快的人,但只能写出糟糕、难以维护的系统。你可能是团队中最有魅力的人,但却完全无法写出一行能工作的代码。我并不是说速度快或有魅力不好——这些也是有用的技能——但没有理解,它们无法让你成为伟大的开发者。
责任
我在第一本书出版后不久在O’Reilly博客上写的一篇文章中稍微谈到了这一点,但我不确定有多少codesimplicity.com的读者读过那篇文章,尽管这实际上是成为伟大程序员的一个非常关键的点。
首先,我想澄清一点。这里所说的“责任”,并不是指“为出了问题的某事承担责任”。那是责任的常见定义,但不是我这里使用的意思。在这种情况下,我所说的“责任”是指“愿意对某事物处于起因地位,或对其进行控制的意愿”。例如,如果我对我的房间负有责任,我愿意清理它。这并不意味着我必须清理它,只是说我完全愿意清理。而且不仅仅是“哦,是的,我完全愿意清理我的房间”这样的大张旗鼓的声明,然后跑去在混乱中躺三个小时。不,我的意思是真正地、实际地愿意。就像,你愿意吃你最喜欢的甜点吗?那就是愿意。我不是说你必须对每件事都像对你最喜欢的甜点那样兴奋,我只是说必须涉及实际的意愿。
那么,这如何应用于编程呢?唉,我经常遇到这种反面例子:
“我不想重构那段代码,因为我不拥有它。”
这很傻。你能编辑它吗?你能阅读源代码吗?你被允许向所有者发送修改吗?那么理论上你是有能力修复它的。这并不意味着你应该随时随地修复全世界的所有代码,因为有时就你的开发目标而言,这样做的时间权衡并不合适。但即使这句话我也不愿意说出口,因为人们也经常以此为借口不去清理东西:
“我不能花任何时间清理那个团队的代码,因为那会使我的项目耗时更长。”或者,“嗯,清理我依赖的这段代码不在我们团队的目标之内。”
好吧,这些理论有两个缺陷。(请相信我,它们真的只是理论——不是事实。)
第一个缺陷是,通常,当你依赖糟糕、混乱或复杂的代码时,正确地做某事反而需要更长时间。通常,重构然后编写你的功能,实际上比尝试在某个混乱或糟糕的、完全不符合你需要的库之上编写你的功能所花的时间更少。所以,你通常并不会为你的目标增加很多额外时间。之所以看起来像是增加了时间,是因为你没有考虑“完成”某事和“真正完成”某事之间的区别。
我说的“真正完成”是什么意思?嗯,我指的是它能工作,不会总是充满Bug,你可以轻松维护它,它不会耗尽你作为开发人员的全部生命,并且你可以继续做其他有成效的事情。
这样想这个问题。想象一下你正在砌一堵墙,你从底部开始用了一些劣质的砖块。然后你在上面又砌了几层砖。但当你砌到大约第四层时,底部的劣质砖开始破裂。于是你去找来一些劣质的木材覆盖在那些砖上进行修补。你又加了几层砖,现在墙开始倒塌了。所以你用一些生锈的铁条撑住它,然后继续工作。如果你继续这样下去,你将花费一生的时间仅仅是为了维护这堵墙。它将成为你生活中的一个巨大问题。你最终很可能会放弃它,留给别人一个可怕的烂摊子墙,他们现在必须维护它,但他们甚至无法理解它,因为它看起来像是一个由劣质建筑材料组成的疯狂混合物,任何理智的人都不会把它们组合在一起。老实说,这相当残酷。
当你在底层依赖中对糟糕的代码进行“ Hack ”或“打补丁”时,你构建软件的方式就像砌那堵墙一样。这不太明显,因为程序没有巨大的物理结构会砸到你的脸上。但尽管如此,同样的构建原则适用——当你通过在上面增加一个复杂性来解决底层复杂性时,你增加了系统的复杂性。而当你解决底层复杂性时,你降低了系统的复杂性。
我想指出的是,最初是谁让事情变得复杂并不重要。“别人做的”这个事实并不会改变上述任何规则。现在谁拥有这个复杂性也不重要。如果你绕过它进行 Hack ,你会使系统更复杂。如果你修复它,你会使系统更简单。你正在做出选择——你拥有这种力量,你可以负责任。是的,有时这涉及到让别人来修复它。但根据我的经验,更多时候它涉及到你愿意自己做出改变。
当然,也许你都知道这些。但你仍然可能想,“哦,好吧,这次我可以就让这一小块变得复杂一点点,因为我只做这一件事。”你知道,有时候你可能是对的,特别是如果你遇到某种真正的紧急情况,必须在短时间内 Hack 出某个东西。但更多时候,你实际上是在为一个巨大的、破碎的墙添砖加瓦,这将成为你和其他所有人维护的噩梦。正是这些小小的复杂性,这些选择不负责任的小决定,最终累积成了没人愿意处理的大烂摊子。
所以,当我以这种方式说“责任”时,我很大一部分意思是“愿意改变你正常范围之外的事物”。它不必是无限的范围。你可以在某处划一条线,说:“超出这个点,就真的是别人的问题了。”例如,在我的项目中,我经常划一条线,说:“好吧,我不会花太多功夫在完全来自公司外部的代码上,因为那样利用我的时间效率不高。”但我不时地甚至会做到向编程语言提交Bug报告,或者向开发工具发送补丁,当我认为它们导致了复杂性或让我的生活更困难时。我的意思是,见鬼,我实际上成为了Bugzilla的首席架构师,因为我认为它有很多需要修复的地方。我不是说每个人都应该做到那种程度。但我要说的是,通过接受项目范围之外的一些代码的责任,你会成为一个更好的程序员。而且你把这个范围扩展得越广,你就会成为越好的程序员。
哦,顺便说一下,我说过上面的理论有两个缺陷。第二个缺陷是你实际上属于一个群体,即使那个群体只是人类。你不是唯一存在的人。为别人的代码做贡献是可以的。我们实际上某种程度上都在同一个团队里。
如果你为一家公司工作,当你遇到这些问题时修复它们,你就是在帮助整个公司。如果你只是世界上一个独立的开发者,当你修复某个广泛使用的库、某个流行工具或网络上某处糟糕的示例代码时,你就是在为其他每个程序员让世界变得更好一点点。而且老实说,这让你成为一个更好的程序员。这就是我在这里所说的全部重点。我认识的最好的程序员,是那些最愿意承担广泛责任以确保一切顺利的人,无论他们需要接触哪段代码,或者需要与哪个团队沟通才能完成任务。我告诉你这些是因为它会对你有帮助。
顺便说一下,作为库或API的使用者,通常你处于重构它的最佳位置,因为你比作者更清楚应该如何消费那个库或API。至少,向代码提交一个Bug报告,说明你遇到的问题。否则作者怎么会知道存在问题呢?你可能期望他们神奇地知道,但相信我,很多时候他们并不知道。你的经验对他们可能非常宝贵,谁知道呢!
总结
总的来说,如果你想成为一个更好的程序员,要问自己的问题是你应该提高意识、理解还是责任,然后在一段时间内专注于那一点。如果你不确定,从意识开始,然后过渡到理解,最后承担更多责任。反过来做非常困难——你很难对你不理解的东西承担责任(那会非常困惑,而且你也不会做得很好),而理解你未意识到的东西是不可能的。所以意识、理解、然后是责任是正确的顺序。
如果你应该提高的是意识,只需阅读一些新代码,找一个新的编程博客,浏览一下书籍标题,与其他程序员聊聊最新技术——任何能帮助你更多地意识到问题、解决方案、知识、模式、人员、组织、原则或任何其他对你的工作有帮助的事物。
如果你想专注于理解,那么多读一些文档,花更多时间理解每个函数的工作原理,多向你的程序员同伴提问,查字典了解一些词汇,阅读一些关于你正在使用的技术的文章,或者读一本书——任何能够让你对与工作相关的某些知识达到完全和充分理解的方法。
最后,责任主要通过决定承担更多来实现。当问题出现时,决定解决它而不是拖延。当团队外部出现困难时,决定帮助解决它而不是成为问题的一部分。还有一种特殊类型的责任——当别人有问题需要解决时,愿意帮助他们,或者,如果他们应该自己解决,愿意让他们自己去解决。责任不仅仅意味着你必须做所有事情。它也可以意味着愿意帮助别人完成任务。
做到以上几点甚至不难——只要你以简单的、单独的步骤进行。你不必一夜之间意识到整个宇宙。你不必明天就理解所有已编写程序的每个字。你也不必仅仅因为读了这篇博客文章就愿意改变现存的所有软件。从一件小事开始。然后继续做下一件,再下一件,再下一件,随着时间的推移,你会成为你想要的那样优秀的程序员。
享受编程吧。
-Max