《编程匠艺》读书笔记之八

第十章 代码构建

  • 将经过处理的高级语言转换成为可以发布的可执行程序的工作,通常称为“构建代码”。
  • 构建代码是我们的工作中一个基本的组成部分。
  • 许多开发人员都依赖于IDE来构建系统,但是你不能因此而不去了解构建是如何进行的。
  • 编程语言有很多中,每一种语言都有其从源代码来构造可执行程序的过程,某些构造模型比其他模型复杂,每种模型都有自己的优势。
  • 编程语言从构建的角度来看可以分为三类:解释型语言、编译型语言和字节编译型语言。
  • 我们经常将构建软件和建造房屋进行类比,好处在于:在开始之前,都需要执行一个收集需求和认真设计体系结构的过程;不好的方面:软件世界提供了比物理世界更多的原型设计和探索的机会。
  • 解释型语言:不需要经历一个专门的构建过程,解释程序将对指令进行实时的解析和操作。
  • 解释型语言的优势:它的开发速度很快,由于没有任何中间的编译过程,可以快速的对每个更改进行测试。
  • 解释型语言的缺点:它的执行要比同等的编译型程序慢得多,这是因为语言运行时必须对每条代码语句进行读取、分析、解释等操作。
  • 脚本语言通常都是解释型语言。常被用作以更便利的方式调用其他工具的手段。
  • 编译型语言:使用一个构建工具链,将你的源代码文件转换为将在目标平台上本地执行的机器指令。
  • 大型项目的编译要经历几个阶段,每个源文件都会被编译成为一个中间对象文件,然后再将这些对象文件链接到一个最终的可执行文件中。
  • 编译型语言的构建过程要比解释程序复杂得多,所以出现故障的几率也要大很多。
  • 最流行的编译型语言是C和C++。
  • 字节编译型语言:介于解释型语言和编译型语言之间。
  • 字节码是一种伪机器语言,可以由虚拟机来执行。
  • 一种常见的错误想法:字节码的执行一定比同等的已编译二进制文件的执行速度慢,JIT优化程序可以对代码作出明智的决策,从而使其运行的更快。
  • 在构建的过程中,我们需要使用的工具:make,它将为你处理所有的中间对象文件和编译规则,更为重要的是,它还会跟踪文件之间的依赖关系。
  • 从本质讲,任何软件构建的过程都是采用一个或多个源文件作为输入,并在另一端生成可执行程序。
  • 构建和编译的区别:“编译”只是构建过程中的一个步骤,而“构建”则描述了整个构造过程。它还包括为UI创建国际化的字符、把图形文件从原始分辨率转换成某种目标格式等。
  • 将构建系统看作是整个源码树的一部分,而不是一个单独的事物,这一点非常重要。

    作为一个优秀的构建系统,它应该具有以下品质:
  • 简洁。1. 易于学习;2. 易于设置;3. 不让人感到意外。
  • 一致。一个项目中所有的程序员都必须使用相同的构建系统,否则,就不是在构建同一个软件。
  • 可重复和可靠。构建必须是确定的和可靠的,对相同的文件集分别执行两次独立的构建,应该得到相同的可执行文件;如果一个构建过程会生成不可重复的二进制文件,这会让人非常担心;构建必须在任何时候都可以正常运行,它必须是可靠的;构建过程应该是几乎不可见的,你唯一需要关心的是如何转动开关,并且应该保证最后可以得到正确的东西。
  • 原子性。在进行构建时,应该不存在任何必须执行的特殊步骤;一个良好的构建应该只有一步;构建代码与获取代码是相互独立的,相同的构建指令可以创建出软件的任意版本,这取决于你使用的源代码的版本。
  • 能够应付错误。1. 在出现错误时,构建系统不应该继续进行;2. 当某个构建步骤失败时,构建系统应该移除任何不完整的对象;3. 构建不应该生成警告信息。
  • 为你的软件设立一个自动构建,使用它来确保你的代码库出于一种前后一致的状态。

    自动构建的好处:
  • 每天早晨都会有一份体现了工作进展情况的最新的副本。
  • 它可以较早的确定构建问题,而不需要你做额外的工作。
  • 你可以在通宵构建后加入自动的回归测试和压力测试。
  • 通宵构建可以被用作项目进度的准绳。
  • 你可以从通宵构建生成真正的产品版本。
  • 它可以证明你是否真正了解如何构建软件,以及构建过程是否真的是原子性。
  • 通宵构建已经成为很多项目开发的心脏。1. 不要破坏源代码树中的任何东西,如果在通宵构建期间签入有破坏作用的代码,就应该受到非常严厉的惩罚;2. 如果构建被破坏,将会是所有人的问题,如果通宵构建失败,所有的开发人员都必须停下他们手头的工作,直到构建可以再次运行。
  • 持续集成:源代码库一被更改就执行一次构建。
  • 一个优秀的构建系统允许你为每次的构建进行一些特定的设置。
  • 如果构建系统是精心制作的,那么就不应该存在任何为版本构建做任何额外准备的必要。

    版本构建的主要问题:
  • 构建应该总是从原始的源码树开始进行,而不是从某人构建了一般的开发树进行。
  • 在构建前,应该有一个特定的步骤来确定在这个版本中要包含哪些源代码和哪些特定的文件版本。
  • 每个版本构建都具有一个用于标识它的特定的名称,有时会是一个很酷的代号,而有时只是一个版本构建号。
  • 在代码构建完毕后,也许会有一个额外的打包阶段。
  • 每个版本都应该被存档并存储,以便将来使用。
  • 你应该保留构建日志,这些日志使你可以回顾旧的构建。
  • 每个版本都有一个发行说明,以描述进行了哪些改动。
  • 当执行版本构建时,你必须选择正确的编译器开关集。尽量减少版本构建与开发构建之间的区别。
  • 为产品制作值得信任的版本构建,是一项需要投入更多精力的工作,它需要一套完备的方法和一个定义良好的过程。
  • 对于真正大型的项目来说,GUI构建工具并不能很好的适应,而且用处很小。你应该为具体的工作选择合适的工具,在简化和集成与强大和可扩展性之间进行权衡,每次都选择必须的工具。
  • 构建脚本是代码的一部分,并且与任何其他源文件一样,也需要维护和谨慎的扩展。这些时间对于代码库的未来的一种投资。
  • 优秀的程序员:1. 明白他们的构建系统如何工作、如何使用以及如何扩展;2. 创建简单的、原子性的构建系统,并且将其与源代码一起维护;3. 尽可能使构建操作自动化;4. 使用通宵构建来查找综合性的问题。
  • 糟糕的程序员:1. 轻视构建系统的机制,结果被愚蠢的构建问题难住;2. 不在乎他们的构建系统有多么不安全和不可靠;3. 以一种几乎是敌对的方式,期望信赖的人掌握他们复杂古怪的构建过程;4. 随意的创建版本构建,而不遵循规定的发布过程。
posted @ 2008-10-27 22:19  李潘  阅读(436)  评论(0编辑  收藏  举报