读《人月神话》有感
因为一个小小的契机,发现了自己在软件开发方面的不足,准确地说是在软件开发中项目管理时的不足。因此我便顺势去读了一下我计划中的一本书,这本书也是一本有名的关于软件工程管理的书籍——《人月神话》。
光看书名,甚至根本不会联想到这是一个关于管理类的书籍,甚至可能会以为这是一本关于神话故事的图书。但是如果把名字写成《人/月神话》的话,多少能联想到这是一个与“人/月”这个单位有关的书籍。
这是一本写在“近代计算机时代”(大型机)的关于探讨软件开发项目管理的书籍。里面很多内容充斥着时代感,例如为大型机开发主要是开发其操作系统,这想想看在现在,能够开发操作系统的人又有多少。虽然并不是没有,但是加上 Linux Kernel 和各种 Unix 发行版的 Contributor 而言,数量也依然是极少的。但是在那个时候,大部分高级程序员的工作,还真就是只有开发操作系统这一个选项。因此这么具有时代感的内容,其讲述的部分观点,肯定具有时空局限性,因此,在阅读时我也抱着一种尊敬并批判的态度去阅读,取其精华取其糟粕,辩证地看待每一个观点。
本书的读书笔记(其实是摘要),已经发布在这里: https://wiki.sotvokun.com/booknote:the_mythical_man_month:home
本文将谈谈我读过此书后的感想:
开发的一体两面:技术与管理
我曾经多多少少认为,做软件开发只需要技术就好了。但是当我与别人合作时才发现,管理能力是必须的,这种对于管理能力的需求,并不仅限于多人开发时,即使是一个人写代码写程序完成某项工作时,也仍然需要。
《人月神话》的第二章到第七章都是在讲如何进行项目管理的,但实际上其中有三章都是在讲如何开展一个好的项目,以及一个好的项目应该是什么样的。而非像是许多管理类的“鸡汤”书籍一样,只是疯狂输出对于人事管理或者时间管理的观点。
其中给我带来印象较为深刻的,则是第五章,作者提到在开发第二个系统时,总是会心态膨胀,从而加入许多修饰性以及不切实际的功能和想法。结果导致计划的时间无法完成,又或者是在实现时过于丑陋以至于难以使用和维护。我曾多少有过这样的体会,我曾编写了一个给别人使用的软件,而每每当我想重构时,总是希望它的功能是丰富的并且灵活的。我想我这也算是陷入了“第二个系统的陷阱”。重构(以客户的角度看则是大更新)以提升性能以及方便维护本是天经地义的事情,但是把本来简单的需求变得复杂化,也许并不能提高自己的技术能力,反而会陷入一种恶性循环。
文档的重要性,我自然是知道的,但是我并不爱写。大概多少是受到了一些网络上所谓的“大牛”的观点的影响,即只要代码可读性高,就没必要写文档或者注释。但实际上在优质的代码中,无论是比较早远的例如西木工作室的“CnC_Remastered_Collection”还是互联网公司谷歌的“leveldb”,它们都有很优秀的注释和健全的文档。我想写出好的文档和注释,即需要技术技能也需要管理技能。
不过,管理与技术不同,技术是一个靠个人钻研也多少能学点名堂的(但是与他合作,特别是与厉害的人合作,也能学得更多)。但是对于管理而言,管理自己与管理超过两个人,必然有所不同,因此实际的进行合作,从实际中学习管理并且想想自己的那些习惯可以用于团队管理上,在批判中学习。同时,这些管理技术,对于个人适用的,我认为也要坚持。
熵增的不可逆性
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程。
这是全书中给我带来较为震撼的一句话。它或许具有一定的时代局限性,但我认为它仍然适用于大多数软件。软件开发的目的是为了减少过多的信息带来的处理难题,例如文书过多,或者是数字过多需要处理。但是在软件维护过程中,不断产生的新的 bug 和用户对于新功能的需求,会导致一个软件会变得愈发膨胀,也就是说软件自身的熵值在不断增加,直到最后变得难以维护,或者需要投入大量的人员资金进行维护。
正如前面所说,随着软件工程的发展至今,这句话也有其局限性。现代化的工具和先进的管理方法,已经可以将这个过程的速度放到非常缓慢。但是我相信这个定律依然是存在的,即一个项目达到一个阶段时将不可避免的走向退化的被放弃的阶段。这时开发团队则会抽取最为重要的一部分代码在新的继承项目中使用,同时尽可能让用户体验保持一致。
一切皆为工具
我曾不止一次地陷入工具陷进中,不断地为工具带来的细微优势而惊喜,并对那些简易的且没有解决明确的问题的工具而嗤之以鼻,虽然最后都能从这种状态中恢复过来,但总是在迷茫时又陷入其中。
书中的第十六章“没有银弹——软件工程中的根本和次要问题”讨论了软件工程中的根本问题是什么,软件开发过程中的一些方法和工具解决的是根本问题还是次要问题。作者认为:软件工程的根本问题是与概念完整性相关的规格、设计和测试,而如何实现反而是次要问题。
因此在这种情况下所有的技术实际上大多数都是为了解决次要问题的工具,例如面向对象编程、函数式编程,而编程语言则更是工具。
答案很简单。因为OO和各种复杂语言的联系已经很紧密。人们并没有被告诉OO是一种设计的方法,并向他们讲授设计方法和原理,大家只是被告知OO是一种特殊工具。而我们可以用任何工具写出优质或低劣的代码。除非我们给人们讲解如何设计,否则语言所起的作用非常小。结果人们使用这种语言做出不好的设计,没有从中获得多少价值。而一旦获得的价值太少,它就不会流行。
但是这其中不乏一些优秀的工具,它们可以用来解决设计问题,而解决设计问题的根本就是快速的制作原型,因此 Python 是一个非常好的工具,丰富的库,使它可以快速地制作原型能够很好的解决设计问题。
任何一门工具其目的都只是更好地针对特定的项目进行设计,并用适合的工具进行实现,没有高低之分。如果需要一些看起来极其简陋的语言,也有其用武之地。
项目开发的启示
除了这些思想上的东西,书中提到的一些内容也给我在实际上的开发项目中许多启示和帮助。
文档——综合工作手册
在信息爆炸的时代,人们越来越难沉下心看一大段文字,但是另一方面,对于软件开发来说,要了解一个项目总是躲不掉查看大段大段的文档。
文档包括哪些内容?我觉得除了和代码有关的,还应该包括与项目有关的,例如会议记录,讨论的记录等等。虽然在软件开发中看起来这些繁杂的文本非常没有意义,特别是对于追求效率的公司而言,但实际上这些记录都可以追踪每一次改动,对于维护软件而言是有较大意义的。
将与代码有关的文档(如注释文档等)、接口说明(API)、使用说明和会议纪要等备忘录,整合,构成一份完整的文档。实际上在许多开源项目中,邮件列表也是文档的一部分,一些问题可以追溯到某一封邮件上。
概念性原型
原型(prototype)也是一个非常有必要存在的东西,原型可能只是一个壳子,甚至没有实现具体的内容,只是一个界面的设计。或者原型是一个模块的单一实现,可以通过自己给定输入来输出一个简单的效果。
版本管理
版本管理并不是必须要有实质性功能更新才需要迭代版本,每次修复了 bug ,确定下个版本的任务,在一定时间后冻结下个版本的任务,之后的任务由下个版本完成,同时每完成一个版本发布后,则冻结该版本。
增量式开发
在有条件的情况下,实现每日或者每周构建自己的项目,确保项目始终可以提供可以运行的发行版本。如果出现不能编译成功或者测试失败的情况,则需要考虑修复 bug,这样的设计可以减少在最终版本中的 bug 数量,从而减少二次开发的成本。
写在最后
如果从字数上看,不难看出来这篇文章多少有些虎头蛇尾。事实上在看完书之后,也没有太多想要写的内容,本来本文的标题应该是《开发的一体两面——技术与管理》但是光靠这个话题,似乎也没办法很好的概括全我从书中学到的所有内容。但是关于书中其他内容的编写的想法,并没有在脑中有所构想,这就导致了我对后面的内容的编写,完全是一边看着自己的读书笔记来写的。
虽然字不算多,但也确实是我真正学到的东西。