🐳 📖

《代码大全》阅读笔记之一:打好基础

📆 2021-04-14

来源:《代码大全》

🏷 编程阅读

🖍 世界上只有两种程序员,一种是看过《代码大全》的,另一种是没看过的。

🏂 正文 👇

世界上只有两种程序员,一种是看过《代码大全》的,另一种是没看过的。我正在从第二种奔向第一种的路上。我一直觉得入门乃至精通一种技艺最大的捷径就是找到业内最头部的那部分人,向他们学习,同时进行大量刻意练习。毫无疑问,《代码大全》就是这样一本由业内顶级专家写就的干货满满的大牛货,随着那些流动于字里行间的智慧和幽默,作者手把手带你领略真正的高手眼中的编程世界。这本获得行业公认的好书,即使被翻译了一个蹩脚的中文名称(给人一种仿佛是各种编程语言片段大杂烩的错觉),也不能掩盖它的光芒。这本书主要着力于软件开发过程中的构建部分,作者希望通过向行业中一般商业实践人员普及学术期刊和专家的优秀编程实践,从而加速缩小两者之间的差距,于是就有了这样一部参考手册般全面而详细的集大成之作。

本书第一部分主要讲构建的概念及软件开发过程中在构建之前需要完成的前期准备工作,为构建打好基础。“构建”(construction)是指建设的过程,是创造事物过程中动手的那些部分。计算机软件开发现在已经是一个复杂的过程了。一般包括:定义问题,需求分析,规划构建,软件架构,详细设计,编码与调试,单元测试,集成测试,集成,系统测试,保障维护等阶段。构建活动主要关于编码与调试,但也包含详细设计,单元测试,集成测试及其他活动的一部分。同时构建也就是“编程”(Programming),是绝大多数患有 WISCA 综合症或者 WIMP 综合症(Why Isn't Sam Coding Anything? 或者 Why Isn't Mary Programming?)的老板最喜闻乐见程序员所正在进行的活动。软件构建是软件开发最核心的部分,整个开发过程中整再多花里胡哨的前期准备,或者事无巨细的后期测试,项目的最终结果都是体现在源代码上。构建活动是唯一一项确保会完成的工作,甚至很多小型项目可能省略到只有构建活动一个过程了。对“如何进行构建”的理解程度,决定了一名程序员的优秀程度。

隐喻是帮助我们理解复杂事物的有力工具。通过把你不太理解的东西和一些你较为理解,且十分类似的东西作比较,降低对理解更陌生,更抽象的概念的难度,以达到更深刻的理解。隐喻在其他学科屡建奇功。同样,一个恰当的隐喻也可以帮我们更好的理解软件开发。隐喻是启发式的,而不像是算法那样精确,我们应该用隐喻来提高对编程问题和编程过程的洞察力,帮助我们思考编程过程中的活动,想象出更好的做事情的方法。软件开发常见的隐喻有如下一些:写作代码(Writing Code),这一隐喻暗示着开发一个程序就像是写一封信,所以程序员也会提到“程序的可读性”。但是这个隐喻没有完整充分地刻画软件开发工作,仿佛软件开发是种一次性的工作,忽略了“写完”软件之后占更大工作量的维护阶段;培植系统(Growing System),像是播种和耕作一样,每次做一点,直到取得代码大丰收。但是软件耕作这一隐喻的弱点在于它暗示了人们将无法对开发软件的过程和方式进行任何直接的控制。这是因为像农民,教师,医生这类职业,不同于建筑师,面包师之类会“生产出”可见的产品。他们能做的是辅助他们的“产品”更好的生长;系统生长(System Accretion),软件的生长,我们每次为软件系统增加一个小部分,让其“增量的”,“迭代的”,“自适应的”,“演进的”,逐渐成型。增量式开发的隐喻奠定了如今敏捷编程方法的基础;建造软件(Building Software),它和软件生长的概念相通,且提供了更详细的指引。建造软件这一说法,暗示了软件开发中存在诸多阶段,并且根据所建造软件的不同,这些阶段的种类和程序可能会发生变化。这就意味着构建方法要与建造规模相适应。同时这一隐喻也可以向许多其他地方引申,很多常见的软件开发术语都是从建筑这一隐喻中衍生出来的:软件架构(建筑学,architecture),支撑性测试代码(脚手架,scaffolding),构建(建设,construction),基础类(foundation classes),以及分离代码(tearing code apart)等;智慧工具箱(The Intelectual tool)隐喻,技术并不是规矩,它只是分析工具,好的工匠知道完成某项工作要用哪样工具,也知道如何正确地使用;隐喻之间并不相互排斥,你也可以组合使用它们。

在构建活动开始之前,准备工作要做周全。使用高质量的实践方法是那些能创造高质量软件的程序员的共性。这些高质量的实践方法在项目初期,中期,末期都强调质量。而初期强调质量就是重视构建前的准备工作,以降低风险。但是一个困难之处在于,那些分配去做前期准备活动的开发人员可能并不具备完成这一任务的专业技能。当开发人员不知道如何进行这些前期工作的时候,建议“做更多的前期工作”就完全没有用。也有一些程序员确实知道进行前期工作,但是他们并没有做,因为他们不能够抵抗“尽快开始编码”的欲望。最后一个原因是,管理者对那些“花时间进行构建活动的前期准备的程序员”的冷漠已经到了人神共愤的程度。良好的准备工作可以让我们防止浪费时间,金钱,精力去建造错误的东西。在一开始就把事情做好是最划算的。如果错误在所难免,发现错误的时间要尽可能接近引入该错误的时间。否则,越往后进行非必要的改动的代价越高昂。据统计,“调试连同相应的返工”,在典型的软件开发周期中,会占据大约 50%的时间。同时,不同种类的软件项目,需要在“准备工作”和“构建活动”之间做出不同的平衡,迭代开发法并不能显著降低由于前期准备工作不足导致的总体成本的增加,而是在项目过程中一点点地吸收消化返工,使得总体成本相对于序列式开发较低。所以当项目的需求比较稳定,设计明确,开发团队非常熟悉该领域,项目风险小,而且后期改变需求,设计和编码的代价很可能较昂贵的时候,就应该采取序列式开发,否则更加迭代的方法则是更好的选择。

为了判断项目前期准备工作是否已经到位,就需要分别对问题定义,需求分析,和架构设计进行客观的评判。这里作者给出了可以帮助判断的核对表。花费在问题定义,需求分析,软件架构上的时间,依据项目的需要而变化,一般来说,一个运作良好的项目会在需求,架构以及其他前期计划方面投入 10%~20%的工作量和 20%~30%的时间,且不包括详细设计的时间————那是构建活动的一部分。

一旦你能确定构建的基础已经打好,那么准备工作就转变为针对特定“构建”的决策了。例如,决定选择何种编程语言。编程语言的选择可以从多个方面影响生产率和代码质量,使用高级语言的程序员比使用低级语言的程序员能达到更好的生产率和质量。另外,高级语言比低级语言的表达力更强,某些语言更擅长表达编程中的各种概念。同时,程序员也会受所用编程语言的影响,甚至编程语言可能决定了程序员能表达怎样的思想。

在开始之前确定好构建的编程约定,例如变量名称,格式约定,注释约定等。假如没有一种统一的风格,你造出来的东西就会充斥着各种风格,这些不同的风格将使你的大脑承受沉重的负担,无法专注于那些真正需要关注的变化。同时,应该秉持着“深入一种语言去编程”的态度,而不只是“在一种语言上编程”。语言是表达思想的工具,贫乏的语言会限制思想的表达。如果自己没有能力或者见识看到更高层次的编程思想,那么就会受到单一编程语言的限制。所以应该意识到编程思想是比具体的编程语言更高层次的存在,用语言表达思想,而不是思想去适应蹩脚的语言,就要有能力在某种程度上突破特定语言的限制。

林林总总的罗列了书中第一部分的主要内容。但是诚如作者在前言中承诺的一样,这是一本绝无刻意掺水的,干货满满的诚意之作。并且读起来一点都不会枯燥。这样的一个总结,可能会抓住一些我所认为的宝藏中最大最璀璨的珍宝,但是同时相对于原文也损失了太多的可读性。所以还应该时时回顾原文,去感受作者精心准备的这顿属于程序员的饕餮盛宴。

👐 The End 🎉

上一篇 《代码大全》阅读笔记之二:创建高质量的代码🏠下一篇我现在所理解的生活 

👇 💬