[关闭]
@Rays 2018-01-17T01:23:42.000000Z 字数 4426 阅读 1376

《理解软件》作者Max Kanat-Alexander访谈

文化&方法


摘要: 去年十月,Max Kanat-Alexander出版了他的新书《理解软件》(Understanding software)。该书深入地介绍了如何保持软件的简洁性,以及如何避免生成缺乏维护的复杂软件。读者可以在InfoQ上看到对本书的评论。最近,InfoQ就本书中的部分内容采访了Kanat-Alexander。

作者: Roland Meertens

正文:

去年十月,Max Kanat-Alexander出版了他的新书《理解软件》(Understanding software)。该书深入地介绍了如何保持软件的简洁性,以及如何避免生成缺乏维护的复杂软件。读者可以在InfoQ上看到对本书的评论

InfoQ就本书中的部分内容采访了Kanat-Alexander。

InfoQ:您为何决定要撰写《理解软件》一书?

Max Kanat-Alexander:我在这本书的引言部分,部分回答了这个问题。根本上说,我只是希望本书能有助于人们成为更好的程序开发人员。我希望能确立一些编程的基本原则,进而分享给更多的人。此外,我还想分享自己从这些原则中学到的一些内容。例如,我们应该如何运用这些原则?将这些原则长期应用于大型组织后,我们能会从中学到什么?诸如此类。

InfoQ:本书面向哪些读者?

Kanat-Alexander:本书面向的是每位程序开发人员。可能一些做程序开发周边工作的人也会对本书有兴趣,例如工程经理和产品经理等。但是,本书的内容主要聚焦于程序开发人员。

InfoQ:书中并未添加大量的示例代码。您这样做是否出于一些特定的考虑?

Kanat-Alexander:是的。通常我并不会在我的书中加入过多的示例代码,因为我希望书中的内容能是通用的。我尽量聚焦于那些在任何场景下都适用于程序开发人员的原则。我并不想看到书中的内容会变得过时,也不想因为使用了特定的编程语言示例而使书中的内容局限于某一语言上。有时我在举例时,也会使用一些通用的编程语言,或者有点类似于Python的语言。

我避免使用具体示例的另一个原因在于,有时我会论及大规模系统的重构问题。这是我们在大规模系统上工作时会真实遇上的问题。在此情况下,即使给出数千行的代码,也很难对整个系统给出一个很好的示例。类似地,如果不能展示出整个系统,那么我们很难以仅通过一个示例就了解重构大规模系统的优点所在。我采用了另一种做法,通过故事和比喻来引出一些原则和示例,让程序开发人员通过在真实系统上应用这些原则而提升自身的经验。

InfoQ:在本书中,您论及了“观察的循环周期”。您能详细介绍一些这个原则吗?

Kanat-Alexander:当然。从编程的角度看(或者出于做任意一件事情的目的),我们必须要做出观察,然后才能给出决定,进而根据该决定采取行动。我特别针对编程问题指出这一点,其原因在于作为软件工程师,观察是与使用工具的方式密切相关的。在编写代码后,我们需要查看代码的情况,例如代码的输出、代码的内容、测试的结果等。然后才能根据自身观察到的情况做出决定。最终,我们需要根据这个决定采取一些行动,例如改进代码、编写新的测试等。观察是从细微之处着手(即编写一行代码后,就需要对该行代码做观察,然后决定如何写一行新的代码,周而复始),一直延伸到整个系统(即我们观察到一个问题,决定写程序去解决该问题,然后开始编写程序)。

总而言之,此原则的内容包罗万象,书中很好地涵盖了对这些内容。

InfoQ: 对于使用测试驱动开发作为维持观察循环周期最小化的一种做法,您个人的观点是什么?

Kanat-Alexander:这种做法完全可以接受,但并非唯一的做法。在我看来,一些TDD(测试驱动开发)的倡导者可能会对此深感困惑。我们需要观察很多事情,可以选择采取多种措施有效地获得观察、做出决定并采取行动。TDD有时是有效的,有时其它方法才会有效。我们所需要的是一种能够在采取行动后迅速获得正确反馈的方法。如果TDD是有效的,不会让我们停下来考虑很长一段时间仍没有得到新观察,那么我完全支持使用TDD。

InfoQ:您是否可以推荐一些现成可用的产品,适用于增加每位程序开发人员的生产率?

Kanat-Alexander:我很难做出推荐。这很大程度上取决于开发人员所使用的编程语言,以及想要采取的编程方式。我想要指出的是,合适于开发人员的工具类型很多。可能我们想要的是一种好用的编辑器或IDE,以我们所希望的方式快速的工作。对于需要构建或编译的语言,可能我们需要的是一种很好的构建工具,例如bazel这样的。我们还可能希望能具有一个好的测试框架,以及一种好的测试运行工具。特别是对于团队而言,我们需要的是像Jenkins这样的持续集成系统。

据我所知,仍有一些开发人员所需要的工具,但目前为止尚未有发布任何现成可用的版本。例如,能处理发布过程的系统无疑是非常有帮助的。近来,大多数公司似乎都在自行建立这样的系统。如果能发布一种这样的通用系统,绝对可以填补市场的一个空白。

当然,我们还会需要一种检查工具(Linter),在提交代码前就告诉我们其中是否存在一些愚蠢的错误或样式问题。

在一些较大的项目中,具有某种自动化的重构工具无疑是一件好事。通常,IDE会支持我们使用最常用的方式实现这一点。例如,有的系统支持我们重命名类或方法,并更新所有的调用者去使用新的命名。

还有很多其它的工具可用,但是书中只选择介绍其中的一少部分。

InfoQ:在尽管首个小型系统可以优雅的实现,但是二次开发通常会生成一个过度设计的臃肿系统。您是否能给出一些建议,防止出现这样的“二次系统开发效应”?(译者注:“Second-system effect”在《人月神话》中翻译为“画蛇添足”。)

Kanat-Alexander:一个小建议就是,不要重写你的系统。我们几乎永远不会需要如此。系统总是可以重构的。建议翻翻我撰写的第一本书《代码简洁性》(Code Simplicity),其中列出了一个清单。读者可以根据这个清单,决定对系统采取重构,或是重写。

InfoQ:您先前撰写了《代码简洁性:软件之基》(Code simplicity: the fundamentals of software)一书。您推荐读者从最新出版的书读起,还是从上一本书读起?

Kanat-Alexander:我想,这取决于读者的需求。我的第一本书针对的是一系列软件开发中的基本规律,并给出了非常详细的阐述。该书从首个基本原理开始,直到阐明了简洁性最为重要的原因所在。

我的新书《理解软件》,是将一系列更高层次的文章组织在一起成书。这些文章的内容是基于我们应用《代码简洁性》一书中介绍的原则所获得的经验。有些读者可能会发现,《理解软件》一书的内容要比《代码简洁性》更实用。

我推荐从《理解软件》一书读起。当然如果读者愿意,也可阅读《代码简洁性》。

InfoQ:书中介绍了您在衡量程序开发人员生产率中所使用的一些方法。我想知道,对于软件团队中的其它人员,例如架构师或管理人员,您会使用什么样的指标?

Kanat-Alexander:好的。这一切都取决于这些人员的产品是什么。就架构师而言,他们的产品是否仅是对规划新的软件项目,或是一个实际完成的软件?如果是后者,那么我们可以使用程序开发人员一样的方法去衡量他们的输出。有的架构师领导着整个技术团队,这时我们需要从整个技术团队层面衡量他们,而不能仅针对某个人。

对于管理者而言,他们必须知道自己的产品是什么。产品会因团队不同而有所差异。如果我管理的是一个编写内部开发人员生产力工具的团队,那么我的成功标准可能会不同于管理一个针对个体用户编写基于Web的会计软件的团队。如果我的工作部分涉及招聘或培养一个团队,那么我的指标也会部分涉及人员方面。我并不擅长于此,因此也无法就此提出一些具体的指标。我只能说,如果想知道生产率的具体情况,我们应该明确自己在衡量何种类型的产品。

InfoQ:您碰到过的最糟糕的代码是什么?您采取了什么重构方法?

Kanat-Alexander:呵呵,对此我心知肚明。一次是面对一个开源项目,在此我并不想点名,因为我希望能继续充当好人,以免对开发人员造成不良影响。另一次是面对我所任职公司内部的一个闭源产品,我也不想特别指明产品的具体名称。但在此我可以介绍一些这两个产品是如何重构的。

对于上述的开源项目,可以说我参与了全程,是从如何整体理解项目着手的。该项目主要在一个文件中,我审阅了整个文件,确定其中可以分为几大块。对此我添加了一些注释,并将代码分割为多个部分,然后在文件顶部写了一个简短的描述,介绍了整个程序的操作顺序。那应该是我的首次提交。然后,我再次整体阅读了代码,找出其中我们能理解并易于修复的部分,然后修复了其中的一些小问题。一以贯之,最终给出了相当不错的结果。

对于上述的闭源产品,我根据《代码简洁性》一书中给出的清单逐项检查,这是我唯一需要重写的一个项目。所以我们在不做其它更改的情况下逐项重写了功能。也就是说,如果将重写比喻为做实验,那么在一次实验中只更改其中的一个变量。在重写的代码和原始的代码中,我们保持了外部接口完全不变(尽管我对其中的一些错误和性能问题做了大量的更改)。令人惊讶的是,重写最终受到了大家的欢迎,因为其中基本消除了软件缺陷,而且速度更快。

InfoQ:过去的几年中,您看到在编程生产率上最有意义的进展是什么?

Kanat-Alexander:在我看来,持续测试运行工具的引入是过去几年中我所看到的最引人注目的进展。这类工具会在开发人员每次保存文件时,对代码做重新编译,并重新运行测试。这极大地改变了软件开发的文化。当然,对于JavaScript或Python等解释型语言,这类工具的效果也不错,因为其中也不存在编译步骤。此外,它们在Java和Go中运行得也很好。我想要指出的是,如果持续测试运行工具能达到在文件保存后两秒内完成所有任务,这对于提升开发人员的生产率无疑是可遇而不可求的工具(Holy Grail)。设想一下,开发人员每次保存文件后,都能清楚地整个系统是否可以工作(具有清晰的反馈,以及易于调试的测试失败)。这会对我们的测试文件造成多么大的影响?对系统的稳定性会产生什么样的影响?难道开发人员没有感觉到重构更加自由了?无论如何,该类工具会显著地影响团队文化。

本书作者简介

Max Kanat-AlexanderGoogle代码健康技术负责人。他的博客是codesimplicity.com。他已撰写了《Understanding Software》和《Code Simplicity》两本书。读者可以使用Twitter通过@mkanat联系到他。

查看英文原文: Q&A with Max Kanat-Alexander, Author of "Understanding Software"

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注