如何成为一个程序员:短,全面,个人摘要

本章转载至:http://samizdat.mines.edu/howto/HowToBeAProgrammer.html,部分内容并通过Google Translation翻译过来的,可能翻译的并不准确,特此说明!

罗伯特·L

版权 由罗伯特·L·阅读。 权限被授予复制,分发和/或修改本文件1.2版本或任何由自由软件基金会出版的更高版本的GNU自由文档许可证的条款下,有一个不变节的历史(截至2003年2月) ',没有封面文字和封底文字:“ 本文件的原始版本是由罗伯特·L·读没有的薪酬和致力于Hire.com程序员”。 许可证的副本包含在题为“GNU自由文档许可证 ”一节。

2002年


贡献

到程序员Hire.com。

目录

1 引言

(2) 初级
个人技能
学习调试 如何调试分割问题空间 如何删除错误 如何调试使用日志 如何了解性能问题 如何解决性能问题 如何优化循环 如何应对与I / O费用 如何管理内存 如何处理间歇性的错误 如何学习设计技巧 如何进行实验
团队技能
原因估计是重要的 如何估计编程时间 如何查找信息 如何利用作为信息来源的人 如何记录明智 如何与糟糕的代码 如何使用源代码控制 如何进行单元测试 难倒时,需要休息 如何识别何时回家 如何对付难缠的人
3。 中级
个人技能
如何保持动力 如何得到广泛的信任 如何权衡时间与空间 如何进行压力测试 如何平衡简洁与抽象 如何学习新的技能 学会打字 如何做集成测试 通信语言 重型工具 如何对数据进行分析
团队技能
如何管理开发时间 如何管理第三方软件风险 如何管理顾问 如何沟通适量的 如何诚实,不同意逃脱它
判决
如何权衡反对开发时间质量 如何管理软件系统的依赖 如何决定,如果软件是太不成熟 如何使采购与建设的决定 如何在专业上成长 如何评 ​​估受访者 如何知道什么时候申请花式计算机科学 如何与非工程师
4。 高级
技术判断
如何辨别真假从不可能的硬 如何利用嵌入式语言 选择语言
妥协的明智
如何争取进度压力 如何了解用户 如何获得晋升
为你的团队
如何培养人才 如何选择什么工作 如何获取从你的队友 如何划分问题 如何处理镗任务 如何收集项目的支持 如何成长系统 如何做好沟通 如何告诉人们事情,他们不希望听到 如何处理与管理的神话 如何处理组织混乱
词汇表 答: B. 历史(截至2月,2003年) C. GNU自由文档许可证
序言 适用性和定义 逐字的复制 复印数量 变通 合并文档 文档的合集 独立作品的聚集 翻译 终止 本许可证的未来修订 附录:如何为您的文件使用此许可证

第1章。 介绍

目录


要成为一个优秀的程序员是艰难和崇高。 最难的部分是真正的一个软件项目的集体愿景与自己的同事和客户打交道。 编写计算机程序是非常重要的,需要极大的智慧和技能。 但实在是孩子们的游戏相比一切,一个好的程序员必须做的一套软件系统,成功地为客户和无数的同事,对他们来说,她是部分负责。 在这篇文章中,我尝试尽量简洁,总结这些事情,我想有人向我解释说,当我是二十一。

这是很主观的,因此,这篇文章,是注定要成为个人和有些自以为是。 我只谈问题,程序员很可能是不得不面对在她的工作。 许多这些问题及其解决方案是一般人的条件,我可能会显得说教。 我希望,尽管这将是有益的,这篇文章。

在课程讲授计算机编程。 优秀的书籍:“实用主义程序员 [Prag99], 代码完成 [CodeC93], 快速发展 RDev96], 极限编程 [XP99]所有教计算机编程和更大的问题是一个好的程序员。 [PGSite]保罗·格雷厄姆的文章和埃里克·雷蒙德[ 黑客 ]当然应该读这篇文章之前或一起。 本文不同于那些强调社会问题,全面总结了一整套必要的技能,当我看到他们的优秀作品。

在这篇文章中一词指的老板谁给你的项目做。 除该业务蕴含赚钱,我用的话业务公司部落 ,同义,公司蕴含现代工作场所和部落一般是人与你分享的忠诚度。

欢迎部落。

第2章。 初学者

个人技能

学习调试

调试是程序员的基石。 动词调试的第一要义是消除错误,但真正重要的意义是通过检查进入执行程序 。 一个程序员,不能有效地调试是盲目的。

认为设计的理想主义者,或分析,或复杂的理论,或者诸如此类的东西,更根本的是没有工作的程序员。 工作的程序员并不住在一个理想的世界。 即使你是完美的,你所包围,并且必须与主要的软件公司,如GNU组织,和你的同事写的代码进行交互。 大部分代码是不完善和不完全记录。 没有能力获得进入执行这段代码的知名度丝毫的凹凸会罚你永久。 这能见度通常只能通过实验获得的,那就是,调试。

有关方案,而不是程序本身的运行调试。 如果你买的东西从一家大型软件公司,你平时不能看到的节目。 但仍然会出现的地方,那里的代码不符合的文件(整个机器崩溃,是一种常见的和壮观的例子),或者文件是静音。 更普遍的是,你创建一个错误,检查你写的代码,并没有错误可以如何发生的线索。 不可避免的,这意味着你做的一些假设是不太正确的,或某些条件时,你没有预料到的。 有时盯着到源代码的魔术作品。 当它没有,你必须调试。

进入执行程序,你必须能够执行代码,并观察它的东西的知名度。 有时候,这是可见的,像什么被显示在屏幕上,或两个事件之间的延迟。 在许多情况下,它涉及到并非是可见的,像里面的代码,这行代码实际上是正在执行的一些变量的状态,或某些断言是否举行跨一个复杂的数据结构的东西。 必须发现这些隐藏的东西。

进入执行程序的“ 内脏 ”的常用方法,可归纳为:

  • 使用调试工具,

  • Printlining ---一个临时的修改程序,通常加入打印出来的线条,

  • 记录---创建一个方案的执行将在日志的形式永久窗口。

调试工具是美妙时,它们是稳定和可用,但的printlining并记录更重要。 调试工具往往落后于语言发展,所以在任何时间点,他们可能无法使用。 此外,因为调试工具可能潜移默化地改变程序执行的方式,它可能并不总是实用。 最后,还有一些,如对一个大型的数据结构,需要编写代码和改变程序的执行断言检查,调试各种。 这是很好的,知道如何使用调试工具时,他们是稳定的,但关键是能够聘请其他两种方法。

一些初学者害怕调试时,它需要修改代码。 这是可以理解的---它是有点像探查手术。 但你一定要学会捅的代码,使其跳,你要学会试验,明白什么,你暂时做它会使情况变得更糟。 如果你觉得这种恐惧,寻求导师---我们失去了很多优秀的程序员,他们学习的微妙发病到这种恐惧。

如何调试分割问题空间

调试是有趣的,因为它开始是一个谜。 你认为它应该做的事情,而是它别的东西。 它并不总是那么简单---相比,有时在实践中发生的,我可以给任何例子将是做作。 调试需要的创造力和智慧。 如果有一个单一的调试的关键是使用分而治之技术的奥秘。

假设,例如,你创建了一个程序序列中应该做的十件事。 当你运行它,它的崩溃。 因为你没有编程崩溃,你现在有一个谜。 当输出看,你看,成功运行了7个序列中的第一事情。 最后三个是从输出中不可见的,所以现在你的神秘小:“ 这事情坠毁#8,#9,#10

你可以设计一个实验看到的事情,它坠毁,机上吗? 肯定。 您可以使用调试器,或者我们可以添加后,#8和#9 printline报表(或同等学历),你的工作在任何一种语言。 当我们再次运行它,将是我们的神秘小,如“ 这件事#9坠毁。” 我发现轴承在考虑到这一点,在任何时间点是什么神秘的,有助于保持一个专注。 当几个人一起在压力下工作问题,很容易忘记的最重要的奥秘是什么。

分而治之作为一种调试技术的关键是相同的,因为它是算法设计:只要你做好了分裂中间的奥秘,你会不会有分裂的次数太多,你会迅速进行调试。 但是,什么是中间的一个谜? 有真正的创造力和经验的用武之地。

一个真正的初学者,所有可能出现的错误的空间看起来像在源代码中的每一行。 你没有后,你会发展到看到该方案的其他方面,如执行线,数据结构,内存管理,互动与国外代码,这是很危险的代码空间,视觉,代码很简单。 这些其他方面的经验的程序员,形成所有可能出错的事情不完善,但非常有用的心智模型。 有了这样的心理模型是找到中间的奥秘有效的帮助。

一旦你已经均匀细分空间的所有可能出错的,你必须尝试,决定错误在于空间。 在简单的情况下,其中的奥秘是:“ 哪单个未知线,使我的程序崩溃 ”,你可以问自己:“ 是未知行此行之前或之后执行的,我判断在执行有关中间正在运行的程序?“ 通常,你会不会这么幸运了,知道该错误存在于一个单一的线,或者甚至一个单一的块。 经常神秘更像是:“ 无论是在该图的指针指向错误的节点,或我的算法,增加了在该图的变量不起作用。” 在这种情况下,你可以写一个小程序来检查,图中的指针是正确的顺序,以决定细分神秘的一部分,可以消除。

如何删除错误

我故意分开,修正错误的行为,从审查程序的执行行为。 但当然, 调试也并不意味着删除的bug。 理想的情况下,你将拥有完美的理解代码,并且将达到一个“A-哈!” 你完全错误和如何解决它。 但是,因为你的程序将经常使用记录不够系统融入其中,你有没有知名度,这是不是总是可行的。 在其他情况下的代码是如此复杂,不可能是十全十美的,你的理解。

在修复bug,你想以最小的变化,修复了这个bug。 您可能会看到其他的事情需要改进,但不解决那些在同一时间。 尝试运用科学的方法,改变一件事只有一件事一次。 此过程中最好的是要能够很容易地重现该错误,然后把你在的地方修复,然后重新运行程序,观察,不再存在错误。 当然,有时多个行必须改变,但你还是应该概念适用于单个原子的变化,以修复bug。

有时候,真的有几个看起来像一个错误。 它是由你来定义的错误,并解决他们在一次。 有时它是不明程序应做什么或原始作者的意图。 在这种情况下,你必须运用你的经验和判断,并指派自己的代码的意义。 决定应该做些什么,并提出意见或澄清它在某种程度上,然后使代码符合你的意思。 这是一个中级或高级技能,有时比写在首位的原有功能更难,但在现实世界往往是凌乱的。 您可能需要修复的系统,你不能重写。

如何调试使用日志

日志记录是写一个系统,所以它产生的信息记录的序列,称为日志。Printlining的做法只是制作一个简单的,通常是暂时的,日志。 绝对初学者必须了解和使用日志是有限的,因为他们的编程知识,系统架构师必须了解和使用日志,因为系统的复杂性。 日志提供的信息量应配置的理想,而在程序运行。 在一般情况下,日志提供了三种基本的优势:

  • 日志可以提供有用的信息有关的错误是很难重现(如发生在生产环境中,但不能在测试环境中重现)。

  • 日志可以提供统计资料和数据,如时间的推移,语句之间的有关性能,。

  • 当配置,日志允许以未预料到的具体问题进行调试,而无需修改和/或重新部署的代码只是为了应付这些具体问题的一般信息被捕获。

到日志的输出量,始终是一个信息和简洁之间的妥协。 太多的信息,使日志昂贵,产生滚动的盲目性 ,使得它很难找到你需要的信息。 信息太少,你需要什么,它可能不包含。 出于这个原因,使得输出配置是什么是非常有用的。 通常情况下,在日志中的每个记录将确定其位置在源代码中,线程执行,如果适用,精确的执行时间,以及常见的,如一些变量的值,其他有用的资料片,可用内存量,数据对象的数量,等等,这些日志语句散布在整个源代码,但尤其是在主要功能点和代码围绕风险。 每个语句可以被分配一个级别,只会输出一个记录,如果该系统目前配置输出水平。 你应该设计的日志报表来解决问题,您预期。 预计需要衡量绩效。

如果你有一个永久的日志,printlining现在可以进行日志记录,以及一些调试语句可能会被永久添加到测井系统。

如何了解性能问题

学习,了解正在运行的系统的性能,是出于同样的原因,学习调试是不可避免的。 即使你的代码完全准确地理解你写的代码的成本,将会使您的代码到其他软件系统的要求,你已经很少控制或能见度到。 然而,在实践中的性能问题有点不同,比一般的调试更容易一点。

假设,您或您的客户考虑一个系统或子系统太慢。 ,然后再尝试,使其更快,你必须建立一个为什么它是缓慢的心智模式。 要做到这一点,你可以使用分析工具还是不错的日志,找出时间或其他资源的真正花费。 有一个著名的格言,将在90%的时间花在10%的代码。 我想补充的输入/输出(I / O的)费用的性能问题的重要性。 往往大部分时间花费在I / O在这种或那种方式。 寻找昂贵的I / O和昂贵的10%的代码是一个很好的第一步,建立你的心智模式。

有许多尺寸的计算机系统的性能,并消耗许多资源。 衡量的第一资源,是墙-时钟的时间 ,通过计算的总时间。 记录挂钟时间,因为它可以了解其他分析是不切实际的情况下出现的不可预知的情况下显得尤为可贵。 然而,这可能并不总是代表全貌。 的东西,需要一点时间较长,但有时不烧了这么多处理器秒计算环境将大大更好,你确实有处理。 同样,内存,网络带宽,数据库或其他服务器访问可能在年底,远远超过昂贵的处理器秒。

同步共享资源的争用造成死锁和饥饿。 僵局是无法进行,因为同步不当或资源需求。 饥饿是未能妥善安排组件。 如果它可以在所有的预期,这是最好的,有一个测量你的项目开始从这一论点的方式。 即使争不会发生,这是非常有益的,可以断言,有信心。

如何解决性能问题

大多数的软件项目可以用相对较少的努力10至100倍的速度比他们在他们第一次发布。 时间到市场的压力下,这是明智和有效的选择一个解决方案,获得简单,快速地完成了工作,但效率较低,比其他一些解决方案。 然而,性能是可用性的一部分,而且往往最终必须更仔细地考虑。

一个非常复杂的系统的性能改善,关键是要分析找到的瓶颈 ,或其中大部分的资源被消耗的地方不够好。 没有优化功能,只有1%的计算时间占多大意义。 作为一个经验法则,你做什么,除非你想使系统或至少快两倍,它的一个显着的一部分,它会之前应慎重考虑。 通常有办法做到这一点。 考虑测试和质量保证工作,你的改变将需要。 每一个变化,带来了它的测试负担,所以它要好得多,有几个大的变化。

当你在东西两倍的改善,你需要至少反思,并可能重新分析,发现在该系统下最昂贵的瓶颈,和攻击,获得另外两个倍的改善。

通常情况下,在性能上的瓶颈将是一个计数计数腿和除以4,而不是数人头奶牛的例子。 例如,我做了错误,如未能提供适当的指数与上一列,我期待了很多,这可能慢至少20倍的关系数据库系统。 其他例子包括做不必要的I /内环澳,调试报表不再需要的,不必要的内存分配,离开,特别是不熟练的使用,图书馆和其他子系统的性能方面往往不记录。 这种改善,有时也被称为低悬的果实 ,这意味着它可以轻松地挑选提供一些好处。

你做什么,当你开始运行低挂水果吗? 好了,你可以达到更高,或砍树。 你可以继续进行小的改进,或严重,你可以重新设计一个系统或子系统。 (这是一个伟大的机会,作为一个优秀的程序员使用你的技能,不仅在新的设计,而且在说服你的老板,这是一个好主意。)但是,在你认为重新设计一个子系统,你应该问自己是否或不是你的建议将使它更好的五到十年的时间。

如何优化循环

有时你会遇到循环,或递归函数,需要很长的时间来执行,并在您的产品的瓶颈。 在您尝试使循环快一点,但花几分钟考虑,如果有一种方法完全消除它。 不同的算法呢? 你可以计算,同时计算别的东西吗? 如果你不能找到它周围,那么你就可以优化循环。 这是很简单的,移动的东西了。 最终,这将需要不仅别出心裁,但也了解每个语句和表达的费用。 下面是一些建议:

  • 删除浮点运算。

  • Don't allocate new memory blocks unnecessarily.

  • Fold constants together.

  • Move I/O into a buffer.

  • Try not to divide.

  • Try not to do expensive typecasts.

  • Move a pointer rather than recomputing indices.

The cost of each of these operations depends on your specific system. On some systems compilers and hardware do these things for you. Clear, efficient code is better than code that requires an understanding of a particular platform.

How to Deal with I/O Expense

For a lot of problems, processors are fast compared to the cost of communicating with a hardware device. This cost is usually abbreviated I/O, and can include network cost, disk I/O, database queries, file I/O, and other use of some hardware not very close to the processor. Therefore building a fast system is often more a question of improving I/O than improving the code in some tight loop, or even improving an algorithm.

There are two very fundamental techniques to improving I/O: caching and representation. Caching is avoiding I/O (generally avoiding the reading of some abstract value) by storing a copy of that value locally so no I/O is performed to get the value. The first key to caching is to make it crystal clear which data is the master and which are copies . There is only one master---period. Caching brings with it the danger that the copy is sometimes can't reflect changes to the master instantaneously.

Representation is the approach of making I/O cheaper by representing data more efficiently. This is often in tension with other demands, like human readability and portability.

Representations can often be improved by a factor of two or three from their first implementation. Techniques for doing this include using a binary representation instead of one that is human readable, transmitting a dictionary of symbols along with the data so that long symbols don't have to be encoded, and, at the extreme, things like Huffman encoding.

A third technique that is sometimes possible is to improve the locality of reference by pushing the computation closer to the data. For instance, if you are reading some data from a database and computing something simple from it, such as a summation, try to get the database server to do it for you. This is highly dependent on the kind of system you're working with, but you should explore it.

How to Manage Memory

Memory is a precious resource that you can't afford to run out of. You can ignore it for a while but eventually you will have to decide how to manage memory.

需要坚持一个单一的子程序的范围之外的空间通常被称为堆分配 。 一大块内存是无用的,因此垃圾 ,没事的时候,是指它。 根据你使用的系统,您可能必须明确自己释放内存时,它是即将成为垃圾。 更多的时候,您可能能够使用,提供了一个垃圾收集系统。 垃圾收集器发现垃圾没有程序员所需要的任何行动,并释放其空间。 垃圾收集是美好的:它减少错误和提高代码简洁,简洁便宜。 使用它时,你可以。

但即使有垃圾收集,可以填补所有垃圾内存。 一个典型的错误是作为缓存使用一个哈希表,并忘记删除哈希表中的参考。 由于参考仍然存在,指涉是noncollectable的中看不中用。 这就是所谓的内存泄漏 。 你应该寻找和修复内存泄漏早期。 可能永远不会被耗尽,如果你长期运行的系统内存在测试中,但用户将耗尽。

任何系统上创建新的对象是中等昂贵。 然而,直接在子程序的局部变量分配内存,通常是便宜释放它的政策,因为可以很简单。 你应该避免不必要的对象创建。

一个重要的情况发​​生时,你可以定义对象的数量,您将需要在同一时间的上限。 如果所有这些对象都采取了相同数量的内存,您可能能够分配内存的单块,或缓冲区,以容纳所有这些。 你所需要的对象可以分配和释放这一套轮换模式的缓冲区内,所以有时也被称为一个环形缓冲区。 这是通常速度比堆分配。

有时候,你必须明确地释放分配的空间,因此它可以被重新分配,而不是依赖于垃圾收集。 然后,你必须申请详细情报每个分配的内存块,并设计一种方法,它必须在适当的时候释放。 为您创建的每个对象的方法可能会有所不同。 你必须确保每一个内存分配操作的执行是由一个操作最终解除分配内存匹配。 这是程序员往往只是简单地实现基本形式的垃圾收集,如引用计数,为他们做的那么难。

如何处理间歇性的错误

间歇性的错误的50英尺长的无形的蝎子从外空间的一种错误的表弟。 这个噩梦所以很少发生,这是很难去观察,但往往不够的,它不能被忽略。 你不能调试,因为你不能找到它。

虽然经过8个小时,你会开始怀疑,有间歇性的错误逻辑一切不服从同样的法律。 是什么使得它很难是,它只能在未知条件下发生的。 试图记录下,这个错误发生的情况,这样您就可以猜测真的是什么变异。 条件可能涉及到的数据值,如“ 这只是发生当我们进入一个值怀俄明州 。” 如果不是变异的来源,在未来的犯罪嫌疑人应该是不当同步并发。

尝试,尝试,尝试重现的bug,在可控的方式。 如果您不能重现它,为它建立一个记录系统,如果你有一个特殊的,可以登录你猜你需要的时候,它确实发生了一个陷阱。 自己辞职,如果错误只发生在生产,而不是在你心血来潮,这可能是一个漫长的过程。 从日志中获得的提示,你可能无法提供解决方案,但可能会给你足够的信息来提高记录。 改进测井系统可能需要很长时间才能投产。 然后,你必须等待的错误再次发生,以获得更多的信息。 这个周期可以继续一段时间。

我曾经创建的最愚蠢的间歇性错误,是在为一类项目的功能性编程语言的多线程实现。 我已经很小心正确的投保并发评价功能的程序,所有可用的CPU利用率(八,在这种情况下)。 我只是忘了同步垃圾收集器。 该系统可以运行很长一段时间,往往完成任何任务,我开始之前,任何明显出了错。 我很惭愧地承认,我开始怀疑我的错误,我恍然大悟之前的硬件。

在工作​​中,我们最近有一个间歇性的错误,我们花了几个星期才能找到。 我们有背后的Apache™Web服务器的多线程应用程序 Java™服务器。 保持快速翻页,我们做所有的I / O输入四个单独的线程翻页线程不同的小套。 每一次的,而这显然会得到' ',并停止做任何有用的,到目前为止,我们的记录让我们告诉了几个小时,。 因为我们有四个线程,这本身并不是一个巨大的问题---除非所有四个卡住了。 然后由这些线程清空队列会迅速填补所有可用的内存和我们的服务器崩溃。 这一个星期左右了我们这么多图,我们仍然不知道什么原因造成的,它何时会发生,甚至是什么线程时,他们得到了“ 卡住 ”。

这说明了与第三方软件相关的一些风险。 我们正在使用的代码持牌一块,从文本中删除HTML标签。 由于其产地,我们亲切地称为这个“ 法国脱衣舞。” 虽然我们的源代码(谢天谢地!),我们还没有研究仔细,直到我们的服务器上的记录,我们终于实现了在法国脱衣舞卡住的电子邮件线程。

剥离表现良好,除了一些长期的和不寻常的各种文本。 在这些文本,代码为二次或者更糟。 这意味着,处理时间为文本长度的平方成正比。 如果这些文本发生普遍,我们会发现错误。 如果他们从来没有发生在所有的,我们永远不会有问题。 因为它发生,我们花了几个星期,终于明白和解决问题。

如何学习设计技巧

要了解如何设计软件,研究导师的身体时,他们正在设计的行动。 然后,研究软件写得很好的作品。 之后,你可以读一些书上最新的设计技术。

然后,你必须自己做。 开始一个小项目。 当你终于完成后,考虑如何设计成功还是失败,以及如何从原始概念分歧。 他们转移到更大的项目,希望在与其他人一起。 设计是一个判断的问题,需要多年的收购。 一个聪明的程序员可以充分了解的基础知识,在两个月内,从那里可以改善。

这是很自然的和有利于发展自己的风格,但请记住,设计是一种艺术,不是一门科学。 谁写这方面的书籍的人有一个使得它似乎科学的既得利益。 不要成为特定的设计风格教条。

如何进行实验

已故的伟大的Edsger迪杰斯特拉雄辩地说明,是不是一门实验科学,计算机科学[ExpCS]和不依赖于电子计算机。 正如他所说的是指20世纪60年代[ ]

...做的危害是:被称为“ 计算机科学 ”的话题成为---,其实,是指像“ 刀科学 ”手术---它被牢牢地植入在人们的心目中,计算科学机及其周边设备。

规划不应该是一门实验科学,但大多数的程序员没有豪华从事Dijkstra算法计算科学手段。 我们必须努力在实验的境界,正如一些,但并非所有的物理学家做。 如果从现在开始的三十多年没有实验可以进行编程,这将是一个计算机科学的巨大成就。

各种实验,你将不得不进行包括:

  • 测试系统的小例子,以确认他们符合的文件或了解他们的反应时,有没有文件,

  • 测试小型代码更改,看看他们是否实际上修正错误,

  • 由于不完善的知识有性能特点,不同条件下测量系统的性能,

  • 检查数据的完整性,

  • 收集统计数据可能暗示在解决困难或难以重复的错误。

我不认为在这篇文章中,我可以解释实验设计,你将不得不学习和实践。 不过,我可以提供两个位的意见。

首先,尝试是很清楚你的假设,或断言,你正试图测试。 它还可以帮助写的假设下,特别是如果你找到了自己的困惑,或与他人合作。

你经常会发现自己有设计了一系列实验,其中每个从过去的实验中获得的知识为基础。 因此,你应该设计您的实验,尽可能提供最多的信息。 不幸的是,这是保持每个实验的简单的张力---你将不得不通过经验判断发展。

团队技能

原因估计是重要的

尽快得到一个工作在积极利用软件系统的要求,不仅规划发展,而且规划的文件,部署,市场营销。 在一个商业项目,它也需要销售和财务。 没有可预见性的开发时间,这是不可能的,这些有效的计划。

估计提供了良好的可预见性。 经理爱,以及他们应该。 事实上这是不可能的,无论在理论上和实践上,准确预测将软件开发多久,往往失去了经理。 我们要求所有的时间来做到这一点不可能的事情,我们必须正视它诚实。 然而,这将是不诚实的,不承认这个任务是不可能的,并在必要时,解释。 有很多房间有关估计误传,当人们一厢情愿地认为,这句话有一个惊人的趋势:

我估计,如果我真的理解这个问题,它是约50%的可能,我们将在五周内完成(如果没有人打扰我们在这段时间内)。

的真正含义:

我发誓从现在全部完成五个星期。

This common interpretation problem requires that you explicitly discuss what the estimate means with your boss or customer as if they were a simpleton. Restate your assumptions, no matter how obvious they seem to you.

How to Estimate Programming Time

Estimation takes practice. It also takes labor. It takes so much labor it may be a good idea to estimate the time it will take to make the estimate, especially if you are asked to estimate something big.

When asked to provide an estimate of something big, the most honest thing to do is to stall. Most engineers are enthusiastic and eager to please, and stalling certainly will displease the stalled. But an on-the-spot estimate probably won't be accurate and honest.

While stalling, it may be possible to consider doing or prototyping the task. If political pressure permits, this is the most accurate way of producing the estimate, and it makes real progress.

When not possible to take the time for some investigation, you should first establish the meaning of the estimate very clearly. Restate that meaning as the first and last part of your written estimate. Prepare a written estimate by deconstructing the task into progressively smaller subtasks until each small task is no more than a day; ideally at most in length. The most important thing is not to leave anything out. For instance, documentation, testing, time for planning, time for communicating with other groups, and vacation time are all very important. If you spend part of each day dealing with knuckleheads, put a line item for that in the estimate. This gives your boss visibility into what is using up your time at a minimum, and might get you more time.

I know good engineers who pad estimates implicitly, but I recommend that you do not. One of the results of padding is trust in you may be depleted. For instance, an engineer might estimate three days for a task that she truly thinks will take one day. The engineer may plan to spend two days documenting it, or two days working on some other useful project. But it will be detectable that the task was done in only one day (if it turns out that way), and the appearance of slacking or overestimating is born. It's far better to give proper visibility into what you are actually doing. If documentation takes twice as long as coding and the estimate says so, tremendous advantage is gained by making this visible to the manager.

Pad explicitly instead. If a task will probably take one day---but might take ten days if your approach doesn't work---note this somehow in the estimate if you can; if not, at least do an average weighted by your estimates of the probabilities. Any risk factor that you can identify and assign an estimate to should go into the schedule. One person is unlikely to be sick in any given week. But a large project with many engineers will have some sick time; likewise vacation time. And what is the probability of a mandatory company-wide training seminar? If it can be estimated, stick it in. There are of course, unknown unknowns, or unk-unks . Unk-unks by definition cannot be estimated individually. You can try to create a global line item for all unk-unks, or handle them in some other way that you communicate to your boss. You cannot, however, let your boss forget that they exist, and it is devilishly easy for an estimate to become a schedule without the unk-unks considered.

In a team environment, you should try to have the people who will do the work do the estimate, and you should try to have team-wide consensus on estimates. People vary widely in skill, experience, preparedness, and confidence. Calamity strikes when a strong programmer estimates for herself and then weak programmers are held to this estimate. The act of having the whole team agree on a line-by-line basis to the estimate clarifies the team understanding, as well as allowing the opportunity for tactical reassignment of resources (for instance, shifting burden away from weaker team members to stronger).

If there are big risks that cannot be evaluated, it is your duty to state so forcefully enough that your manager does not commit to them and then become embarrassed when the risk occurs. Hopefully in such a case whatever is needed will be done to decrease the risk.

If you can convince your company to use Extreme Programming , you will only have to estimate relatively small things, and this is both more fun and more productive.

How to Find Out Information

The nature of what you need to know determines how you should find it.

If you need information about concrete things that are objective and easy to verify, for example the latest patch level of a software product, ask a large number of people politely by searching the internet for it or by posting on a discussion group. Don't search on the internet for anything that smacks of either opinion or subjective interpretation: the ratio of drivel to truth is too high.

If you need general knowledge about something subjective the history of what people have thought about it, go to the library (the physical building in which books are stored). For example, to learn about math or mushrooms or mysticism, go to the library.

If you need to know how to do something that is not trivial get two or three books on the subject and read them. You might learn how to do something trivial, like install a software package, from the Internet. You can even learn important things, like good programming technique, but you can easily spend more time searching and sorting the results and attempting to divine the authority of the results than it would take to read the pertinent part of a solid book.

If you need information that no one else could be expected to know for example, ' does this software that is brand new work on gigantic data sets? ', you must still search the internet and the library. After those options are completely exhausted, you may design an experiment to ascertain it.

If you want an opinion or a value judgment that takes into account some unique circumstance, talk to an expert. For instance, if you want to know whether or not it is a good idea to build a modern database management system in LISP, you should talk to a LISP expert and a database expert.

If you want to know how likely it is that a faster algorithm for a particular application exists that has not yet been published, talk to someone working in that field.

If you want to make a personal decision that only you can make like whether or not you should start a business, try putting into writing a list of arguments for and against the idea. If that fails, consider divination. Suppose you have studied the idea from all angles, have done all your homework, and worked out all the consequences and pros and cons in your mind, and yet still remain indecisive. You now must follow your heart and tell your brain to shut up. The multitude of available divination techniques are very useful for determining your own semi-conscious desires, as they each present a complete ambiguous and random pattern that your own subconscious will assign meaning to.

How to Utilize People as Information Sources

Respect every person's time and balance it against your own. Asking someone a question accomplishes far more than just receiving the answer. The person learns about you, both by enjoying your presence and hearing the particular question. You learn about the person in the same way, and you may learn the answer you seek. This is usually far more important than your question.

However, the value of this diminishes the more you do it. You are, after all, using the most precious commodity a person has: their time. The benefits of communication must be weighed against the costs. Furthermore, the particular costs and benefits derived differ from person to person. I strongly believe that an executive of 100 people should spend five minutes a month talking to each person in her organization, which would be about 5% of their time. But ten minutes might be too much, and five minutes is too much if they have one thousand employees. The amount of time you spend talking to each person in your organization depends on their role (more than their position). You should talk to your boss more than your boss's boss, but you should talk to your boss's boss a little. It may be uncomfortable, but I believe you have a duty to talk a little bit to all your superiors, each month, no matter what.

The basic rule is that everyone benefits from talking to you a little bit, and the more they talk to you, the less benefit they derive. It is your job to provide them this benefit, and to get the benefit of communicating with them, keeping the benefit in balance with the time spent.

It is important to respect your own time. If talking to someone, even if it will cost them time, will save you a great deal of time, then you should do it unless you think their time is more valuable than yours, to the tribe, by that factor.

A strange example of this is the summer intern. A summer intern in a highly technical position can't be expected to accomplish too much; they can be expected to pester the hell out of everybody there. So why is this tolerated? Because the pestered are receiving something important from the intern. They get a chance to showoff a little. They get a chance to hear some new ideas, maybe; they get a chance to see things from a different perspective. They may also be trying to recruit the intern, but even if this is not the case there is much to gain.

You should ask people for a little bit of their wisdom and judgment whenever you honestly believe they have something to say. This flatters them and you will learn something and teach them something. A good programmer does not often need the advice of a Vice President of Sales, but if you ever do, you be sure to ask for it. I once asked to listen in on a few sales calls to better understand the job of our sales staff. This took no more than 30 minutes but I think that small effort made an impression on the sales force.

How to Document Wisely

Life is too short to write crap nobody will read; if you write crap, nobody will read it. Therefore a little good documentation is best. Managers often don't understand this, because even bad documentation gives them a false sense of security that they are not dependent on their programmers. If someone absolutely insists that you write truly useless documentation, say ``yes'' and quietly begin looking for a better job.

There's nothing quite as effective as putting an accurate estimate of the amount of time it will take to produce good documentation into an estimate to slacken the demand for documentation. The truth is cold and hard: documentation, like testing, can take many times longer than developing code.

Writing good documentation is, first of all, good writing. I suggest you find books on writing, study them, and practice. But even if you are a lousy writer or have poor command of the language in which you must document, the Golden Rule is all you really need: ``Do unto others as you would have them do unto you.'' Take time to really think about who will be reading your documentation, what they need to get out of it, and how you can teach that to them. If you do that, you will be an above average documentation writer, and a good programmer.

When it comes to actually documenting code itself, as opposed to producing documents that can actually be read by non-programmers, the best programmers I've ever known hold a universal sentiment: write self-explanatory code and only document code in the places that you cannot make it clear by writing the code itself. There are two good reasons for this. First, anyone who needs to see code-level documentation will in most cases be able to and prefer to read the code anyway. Admittedly, this seems easier to the experienced programmer than to the beginner. More importantly however, is that the code and the documentation cannot be inconsistent if there is no documentation. The source code can at worst be wrong and confusing. The documentation, if not written perfectly, can lie, and that is a thousand times worse.

This does not make it easier on the responsible programmer. How does one write self-explanatory code? 那是什么,甚至是什么意思? 这意味着:

  • Writing code knowing that someone will have to read it;

  • Applying the golden rule;

  • Choosing a solution that is straightforward, even if you could get by with another solution faster;

  • Sacrificing small optimizations that obfuscate the code;

  • Thinking about the reader and spending some of your precious time to make it easier on her; and

  • Not ever using a function name like ``foo'',``bar'', or ``doIt''!

How to Work with Poor Code

It is very common to have to work with poor quality code that someone else has written. Don't think too poorly of them, however, until you have walked in their shoes. They may have been asked very consciously to get something done quickly to meet schedule pressure. Regardless, in order to work with unclear code you must understand it. To understand it takes learning time, and that time will have to come out of some schedule, somewhere, and you must insist on it. To understand it, you will have to read the source code. You will probably have to experiment with it.

This is a good time to document, even if it is only for yourself, because the act of trying to document the code will force you to consider angles you might not have considered, and the resulting document may be useful. While you're doing this, consider what it would take to rewrite some or all of the code. Would it actually save time to rewrite some of it? Could you trust it better if you rewrote it? Be careful of arrogance here. If you rewrite it, it will be easier for you to deal with, but will it really be easier for the next person who has to read it? If you rewrite it, what will the test burden be? Will the need to re-test it outweigh any benefits that might be gained?

In any estimate that you make for work against code you didn't write, the quality of that code should affect your perception of the risk of problems and unk-unks.

It is important to remember that abstraction and encapsulation, two of a programmer's best tools, are particularly applicable to lousy code. You may not be able to redesign a large block of code, but if you can add a certain amount of abstraction to it you can obtain some of the benefits of a good design without reworking the whole mess. In particular, you can try to wall off the parts that are particularly bad so that they may be redesigned independently.

How to Use Source Code Control

Source code control systems let you manage projects effectively. They're very useful for one person and essential for a group. They track all changes in different versions so that no code is ever lost and meaning can be assigned to changes. One can create throw-away and debugging code with confidence with a source code control system, since the code you modify is kept carefully separate from committed, official code that will be shared with the team or released.

I was late to appreciate the benefits of source code control systems but now I wouldn't live without one even on a one-person project. Generally they are necessary when you have team working on the same code base. However, they have another great advantage: they encourage thinking about the code as a growing, organic system. Since each change is marked as a new revision with a new name or number, one begins to think of the software as a visibly progressive series of improvements. I think this is especially useful for beginners.

A good technique for using a source code control system is to stay within a few days of being up-to-date at all time. Code that can't be finished in a few days is checked in, but in a way that it is inactive and will not be called, and therefore not create any problems for anybody else. Committing a mistake that slows down your teammates is a serious error; it is often taboo.

How to Unit Test

Unit testing, the testing of an individual piece of coded functionality by the team that wrote it, is a part of coding, not something different from it. Part of designing the code is designing how it will be tested. You should write down a test plan, even if it is only one sentence. Sometimes the test will be simple: ``Does the button look good?'' Sometimes it will be complex: ``Did this matching algorithm return precisely the correct matches?''

Use assertion checking and test drivers whenever possible. This not only catches bugs early, but is very useful later on and lets you eliminate mysteries that you would otherwise have to worry about.

The Extreme Programming developers are writing extensively on unit testing effectively; I can do no better than to recommend their writings.

Take Breaks when Stumped

When stumped, take a break. I sometimes meditate for 15 minutes when stumped and the problem magically unravels when I come back to it. A night's sleep sometimes does the same thing on a larger scale. It's possible that temporarily switching to any other activity may work.

How to Recognize When to Go Home

Computer programming is an activity that is also a culture. The unfortunate fact is that it is not a culture that values mental or physical health very much. For both cultural/historical reasons (the need to work at night on unloaded computers, for example) and because of overwhelming time-to-market pressure and the scarcity of programmers, computer programmers are traditionally overworked. I don't think you can trust all the stories you hear, but I think 60 hours a week is common, and 50 is pretty much a minimum. This means that often much more than that is required. This is serious problem for a good programmer, who is responsible not only for themselves but their teammates as well. You have to recognize when to go home, and sometimes when to suggest that other people go home. There can't be any fixed rules for solving this problem, anymore than there can be fixed rules for raising a child, for the same reason---every human being is different.

Beyond 60 hours a week is an extraordinary effort for me, which I can apply for short periods of time (about one week), and that is sometimes expected of me. I don't know if it is fair to expect 60 hours of work from a person; I don't even know if 40 is fair. I am sure, however, that it is stupid to work so much that you are getting little out of that extra hour you work. For me personally, that's any more than 60 hours a week. I personally think a programmer should exercise noblesse oblige and shoulder a heavy burden. However, it is not a programmer's duty to be a patsy. The sad fact is programmers are often asked to be patsies in order to put on a show for somebody, for example a manager trying to impress an executive. Programmers often succumb to this because they are eager to please and not very good at saying no. There are four defenses against this:

  • Communicate as much as possible with everyone in the company so that no one can mislead the executives about what is going on,

  • Learn to estimate and schedule defensively and explicitly and give everyone visibility into what the schedule is and where it stands,

  • Learn to say no, and say no as a team when necessary, and

  • Quit if you have to.

Most programmers are good programmers, and good programmers want to get a lot done. To do that, they have to manage their time effectively. There is a certain amount of mental inertia associated with getting warmed-up to a problem and deeply involved in it. Many programmers find they work best when they have long, uninterrupted blocks of time in which to get warmed-up and concentrate. However, people must sleep and perform other duties. Each person needs to find a way to satisfy both their human rhythm and their work rhythm. Each programmer needs to do whatever it takes to procure efficient work periods, such as reserving certain days in which you will attend only the most critical meetings.

Since I have children, I try to spend evenings with them sometimes. The rhythm that works best for me is to work a very long day, sleep in the office or near the office (I have a long commute from home to work) then go home early enough the next day to spend time with my children before they go to bed. I am not comfortable with this, but it is the best compromise I have been able to work out. Go home if you have a contagious disease. You should go home if you are thinking suicidal thoughts. You should take a break or go home if you think homicidal thoughts for more than a few seconds. You should send someone home if they show serious mental malfunctioning or signs of mental illness beyond mild depression. If you are tempted to be dishonest or deceptive in a way that you normally are not due to fatigue, you should take a break. Don't use cocaine or amphetamines to combat fatigue. Don't abuse caffeine.

如何对付难缠的人

You will probably have to deal with difficult people. You may even be a difficult person yourself. If you are the kind of person who has a lot of conflicts with coworkers and authority figures, you should cherish the independence this implies, but work on your interpersonal skills without sacrificing your intelligence or principles.

This can be very disturbing to some programmers who have no experience in this sort of thing and whose previous life experience has taught them patterns of behavior that are not useful in the workplace. Difficult people are often inured to disagreement and they are less affected by social pressure to compromise than others. The key is to respect them appropriately, which is more than you will want to but not as much as they might want.

Programmers have to work together as a team. When disagreement arises, it must be resolved somehow, it cannot be ducked for long. Difficult people are often extremely intelligent and have something very useful to say. It is critical that you listen and understand the difficult person without prejudice caused by the person. A failure to communicate is often the basis of disagreement but it can sometimes be removed with great patience. Try to keep this communication cool and cordial, and don't accept any baits for greater conflict that may be offered. After a reasonable period of trying to understand, make a decision.

Don't let a bully force you to do something you don't agree with. If you are the leader, do what you think is best. Don't make a decision for any personal reasons, and be prepared to explain the reasons for your decision. If you are a teammate with a difficult person, don't let the leader's decision have any personal impact. If it doesn't go your way, do it the other way whole-heartedly.

Difficult people do change and improve. I've seen it with my own eyes, but it is very rare. However, everyone has transitory ups and downs.

One of the challenges that every programmer but especially leaders face is keeping the difficult person fully engaged. They are more prone to duck work and resist passively than others.

第3章。 中间

个人技能

How to Stay Motivated

It is a wonderful and surprising fact that programmers are highly motivated by the desire to create artifacts that are beautiful, useful, or nifty. This desire is not unique to programmers nor universal but it is so strong and common among programmers that it separates them from others in other roles.

This has practical and important consequences. If programmers are asked to do something that is not beautiful, useful, or nifty, they will have low morale. There's a lot of money to be made doing ugly, stupid, and boring stuff; but in the end, fun will make the most money for the company.

Obviously, there are entire industries organized around motivational techniques some of which apply here. The things that are specific to programming that I can identify are:

  • Use the best language for the job.

  • Look for opportunities to apply new techniques, languages, and technologies.

  • Try to either learn or teach something, however small, in each project.

Finally, if possible, measure the impact of your work in terms of something that will be personally motivating. For example, when fixing bugs, counting the number of bugs that I have fixed is not at all motivational to me, because it is independent of the number that may still exist, and is also affects the total value I'm adding to my company's customers in only the smallest possible way. Relating each bug to a happy customer, however, is personally motivating to me.

How to be Widely Trusted

To be trusted you must be trustworthy. You must also be visible. If know one knows about you, no trust will be invested in you. With those close to you, such as your teammates, this should not be an issue. You establish trust by being responsive and informative to those outside your department or team. Occasionally someone will abuse this trust, and ask for unreasonable favors. Don't be afraid of this, just explain what you would have to give up doing to perform the favor.

Don't pretend to know something that you don't. With people that are not teammates, you may have to make a clear distinction between ``not knowing right off the top of my head'' and ``not being able to figure it out, ever.''

How to Tradeoff Time vs. Space

You can be a good programmer without going to college, but you can't be a good intermediate programmer without knowing basic computational complexity theory. You don't need to know ``big O'' notation, but I personally think you should be able to understand the difference between ``constant-time'',``n log n'' and ``n squared''. You might be able to intuit how to tradeoff time against space without this knowledge, but in its absence you will not have a firm basis for communicating with your colleagues.

In designing or understanding an algorithm, the amount of time it takes to run is sometimes a function of the size of the input. When that is true, we can say an algorithm's worst/expected/best-case running time is ``n log n'' if it is proportional to the size ($n$) times the logarithm of the size. The notation and way of speaking can be also be applied to the space taken up by a data structure.

To me, computational complexity theory is beautiful and as profound as physics---and a little bit goes a long way!

Time (processor cycles) and space (memory) can be traded off against each other. Engineering is about compromise, and this is a fine example. It is not always systematic. In general, however, one can save space by encoding things more tightly, at the expense of more computation time when you have to decode them. You can save time by caching, that is, spending space to store a local copy of something, at the expense of having to maintain the consistency of the cache. You can sometimes save time by maintaining more information in a data structure. This usually cost a small amount of space but may complicate the algorithm.

Improving the space/time tradeoff can often change one or the other dramatically. However, before you work on this you should ask yourself if what you are improving is really the thing that needs the most improvement. It's fun to work on an algorithm, but you can't let that blind you to the cold hard fact that improving something that is not a problem will not make any noticeable difference and will create a test burden.

Memory on modern computers appears cheap, because unlike processor time, you can't see it being used until you hit the wall; but then failure is catastrophic. There are also other hidden costs to using memory, such as your effect on other programs that must be resident, and the time to allocate and deallocate it. Consider this carefully before you trade away space to gain speed.

How to Stress Test

Stress testing is fun. At first it appears that the purpose of stress testing is to find out if the system works under a load. In reality, it is common that the system does work under a load but fails to work in some way when the load is heavy enough. I call this hitting the wall or bonking [ 1 ] . There may be some exceptions, but there is almost always a ' wall '. The purpose of stress testing is to figure out where the wall is, and then figure out how to move the wall further out.

A plan for stress testing should be developed early in the project, because it often helps to clarify exactly what is expected. Is two seconds for a web page request a miserable failure or a smashing success? Is 500 concurrent users enough? That, of course, depends, but one must know the answer when designing the system that answers the request. The stress test needs to model reality well enough to be useful. It isn't really possible to simulate 500 erratic and unpredictable humans using a system concurrently very easily, but one can at least create 500 simulations and try to model some part of what they might do.

In stress testing, start out with a light load and load the system along some dimension---such as input rate or input size---until you hit the wall. If the wall is too close to satisfy your needs, figure out which resource is the bottleneck (there is usually a dominant one.) Is it memory, processor, I/O, network bandwidth, or data contention? Then figure out how you can move the wall. Note that moving the wall, that is, increasing the maximum load the system can handle, might not help or might actually hurt the performance of a lightly loaded system. Usually performance under heavy load is more important than performance under a light load.

You may have to get visibility into several different dimensions to build up a mental model of it; no single technique is sufficient. For instance, logging often gives a good idea of the wall-clock time between two events in the system, but unless carefully constructed, doesn't give visibility into memory utilization or even data structure size. Similarly, in a modern system, a number of computers and many software systems may be cooperating. Particularly when you are hitting the wall (that is, the performance is non-linear in the size of the input) these other software systems may be a bottleneck. Visibility into these systems, even if only measuring the processor load on all participating machines, can be very helpful.

Knowing where the wall is is essential not only to moving the wall, but also to providing predictability so that the business can be managed effectively.

How to Balance Brevity and Abstraction

Abstraction is key to programming. You should carefully choose how abstract you need to be. Beginning programmers in their enthusiasm often create more abstraction than is really useful. One sign of this is if you create classes that don't really contain any code and don't really do anything except serve to abstract something. The attraction of this is understandable but the value of code brevity must be measured against the value of abstraction. Occasionally, one sees a mistake made by enthusiastic idealists: at the start of the project a lot of classes are defined that seem wonderfully abstract and one may speculate that they will handle every eventuality that may arise. As the project progresses and fatigue sets in, the code itself becomes messy. Function bodies become longer than they should be. The empty classes are a burden to document that is ignored when under pressure. The final result would have been better if the energy spent on abstraction had been spent on keeping things short and simple. This is a form of speculative programming . I strongly recommend the article ``Succinctness is Power'' by Paul Graham[ PGSite ].

There is a certain dogma associated with useful techniques such as information hiding and object oriented programming that are sometimes taken too far. These techniques let one code abstractly and anticipate change. I personally think, however, that you should not produce much speculative code. For example, it is an accepted style to hide an integer variable on an object behind mutators and accessors, so that the variable itself is not exposed, only the little interface to it. This does allow the implementation of that variable to be changed without affecting the calling code, and is perhaps appropriate to a library writer who must publish a very stable API. But I don't think the benefit of this outweighs the cost of the wordiness of it when my team owns the calling code and hence can recode the caller as easily as the called. Four or five extra lines of code is a heavy price to pay for this speculative benefit.

Portability poses a similar problem. Should code be portable to a different computer, compiler, software system or platform, or simply easily ported? I think a non-portable, short-and-easily-ported piece of code is better than a long portable one. It is relatively easy and certainly a good idea to confine non-portable code to designated areas, such as a class that makes database queries that are specific to a given DBMS.

How to Learn New Skills

Learning new skills, especially non-technical ones, is the greatest fun of all. Most companies would have better morale if they understood how much this motivates programmers.

Humans learn by doing. Book-reading and class-taking are useful. But could you have any respect for a programmer who had never written a program? To learn any skill, you have to put yourself in a forgiving position where you can exercise that skill. When learning a new programming language, try to do a small project it in before you have to do a large project. When learning to manage a software project, try to manage a small one first.

A good mentor is no replacement for doing things yourself, but is a lot better than a book. What can you offer a potential mentor in exchange for their knowledge? At a minimum, you should offer to study hard so their time won't be wasted.

Try to get your boss to let you have formal training, but understand that it often not much better than the same amount of time spent simply playing with the new skill you want to learn. It is, however, easier to ask for training than playtime in our imperfect world, even though a lot of formal training is just sleeping through lectures waiting for the dinner party.

If you lead people, understand how they learn and assist them by assigning them projects that are the right size and that exercise skills they are interested in. Don't forget that the most important skills for a programmer are not the technical ones. Give your people a chance to play and practice courage, honesty, and communication.

Learn to Type

Learn to touch-type. This is an intermediate skill because writing code is so hard that the speed at which you can type is irrelevant and can't put much of a dent in the time it takes to write code, no matter how good you are. However, by the time you are an intermediate programmer you will probably spend a lot of time writing natural language to your colleagues and others. This is a fun test of your commitment; it takes dedicated time that is not much fun to learn something like that. Legend has it that when Michael Tiemann [ 2 ] was at MCC people would stand outside his door to listen to the hum generated by his keystrokes which were so rapid as to be indistinguishable.

How to Do Integration Testing

Integration testing is the testing of the integration of various components that have been unit tested. Integration is expensive and it comes out in the testing. You must include time for this in your estimates and your schedule.

Ideally you should organize a project so that there is not a phase at the end where integration must explicitly take place. It is far better to gradually integrate things as they are completed over the course of the project. If it is unavoidable estimate it carefully.

Communication Languages

There are some languages, that is, formally defined syntactic systems, that are not programming languages but communication languages ---they are designed specifically to facillitate communication through standardization. In 2003 the most important of these are UML, XML, and SQL. You should have some familiarity with all of these so that you can communicate well and decide when to use them.

UML is a rich formal system for making drawings that describe designs. It's beauty lines in that is both visual and formal, capable of conveying a great deal of information if both the author and the audience know UML. You need to know about it because designs are sometimes communicated in it. There are very helpful tools for making UML drawings that look very professional. In a lot of cases UML is too formal, and I find myself using a simpler boxes and arrows style for design drawings. But I'm fairly sure UML is at least as good for you as studying Latin.

XML is a standard for defining new standards. It is not a solution to data interchange problems, though you sometimes see it presented as if it was. Rather, it is a welcome automation of the most boring part of data interchange, namely, structuring the representation into a linear sequence and parsing back into a structure. It provides some nice type- and correctness-checking, though again only a fraction of what you are likely to need in practicen.

SQL is a very powerful and rich data query and manipulation language that is not quite a programming language. It has many variations, typically quite product-dependent, which are less important than the standardized core. SQL is the lingua franca of relational databases. You may or may not work in any field that can benefit from an understanding of relational databases, but you should have a basic understanding of them and they syntax and meaning of SQL.

Heavy Tools

As our technological culture progresses, software technology moves from inconceivable, to research, to new products, to standardized products, to widely available and inexpensive products. These heavy tools can pull great loads, but can be intimidating and require a large investment in understanding. The intermediate programmer has to know how to manage them and when they should be used or considered.

To my mind right some of the best heavy tools are:

  • Relational Databases,

  • Full-text Search Engines,

  • Math libraries,

  • OpenGL,

  • XML parsers, and

  • 电子表格。

How to analyze data

-

Data analysis is a process in the early stages of software development, when you examine a business activity and find the requirements to convert it into a software application. This is a formal definition, which may lead you to believe that data analysis is an action that you should better leave to the systems analysts, while you, the programmer, should focus on coding what somebody else has designed. If we follow strictly the software engineering paradigm, it may be correct. Experienced programmers become designers and the sharpest designers become business analysts, thus being entitled to think about all the data requirements and give you a well defined task to carry out. This is not entirely accurate, because data is the core value of every programming activity. Whatever you do in your programs, you are either moving around or modifying data. The business analyst is analyzing the needs in a larger scale, and the software designer is further squeezing such scale so that, when the problem lands on your desk, it seems that all you need to do is to apply clever algorithms and start moving existing data.

并非如此。

No matter at which stage you start looking at it, data is the main concern of a well designed application. If you look closely at how a business analyst gets the requirements out of the customer?s requests, you?ll realize that data plays a fundamental role. The analyst creates so called Data Flow Diagrams, where all data sources are identified and the flow of information is shaped. Having clearly defined which data should be part of the system, the designer will shape up the data sources, in terms of database relations, data exchange protocols, and file formats, so that the task is ready to be passed down to the programmer. However, the process is not over yet, because you ? the programmer ? even after this thorough process of data refinement, are required to analyze data to perform the task in the best possible way. The bottom line of your task is the core message of Niklaus Wirth, the father of several languages. ?Algorithms + Data Structures = Programs.? There is never an algorithm standing alone, doing something to itself. Every algorithm is supposed to do something to at least one piece of data.

Therefore, since algorithms don't spin their wheels in a vacuum, you need to analyze both the data that somebody else has identified for you and the data that is necessary to write down your code. A trivial example will make the matter clearer. You are implementing a search routine for a library. According to your specifications, the user can select books by a combination of genre, author, title, publisher, printing year, and number of pages. The ultimate goal of your routine is to produce a legal SQL statement to search the back-end database. Based on these requirements, you have several choices: check each control in turn, using a "switch" statement, or several "if" ones; make an array of data controls, checking each element to see if it is set; create (or use) an abstract control object from which inherit all your specific controls, and connect them to an event-driven engine. If your requirements include also tuning up the query performance, by making sure that the items are checked in a specific order, you may consider using a tree of components to build your SQL statement. As you can see, the choice of the algorithm depends on the data you decide to use, or to create. Such decisions can make all the difference between an efficient algorithm and a disastrous one. However, efficiency is not the only concern. You may use a dozen named variables in your code and make it as efficient as it can ever be. But such a piece of code might not be easily maintainable. Perhaps choosing an appropriate container for your variables could keep the same speed and in addition allow your colleagues to understand the code better when they look at it next year. Furthermore, choosing a well defined data structure may allow them to extend the functionality of your code without rewriting it. In the long run, your choices of data determines how long your code will survive after you are finished with it. Let me give you another example, just some more food for thought. Let's suppose that your task is to find all the words in a dictionary with more than three anagrams, where an anagram must be another word in the same dictionary. If you think of it as a computational task, you will end up with an endless effort, trying to work out all the combinations of each word and then comparing it to the other words in the list. However, if you analyze the data at hand, you'll realize that each word may be represented by a record containing the word itself and a sorted array of its letters as ID. Armed with such knowledge, finding anagrams means just sorting the list on the additional field and picking up the ones that share the same ID. The brute force algorithm may take several days to run, while the smart one is just a matter of a few seconds. Remember this example the next time you are facing an intractable problem.

Team Skills

How to Manage Development Time

To manage development time, maintain a concise and up-to-date project plan. A project plan is an estimate, a schedule, a set of milestones for marking progress, and an assignment of your team or your own time to each task on the estimate. It should also include other things you have to remember to do, such as meeting with the quality assurance people, preparing documentation, or ordering equipment. If you are on a team, the project plan should be a consensual agreement, both at the start and as you go.

The project plan exists to help make decisions, not to show how organized you are. If the project plan is either too long or not up-to-date, it will be useless for making decisions. In reality, these decisions are about individual persons. The plan and your judgment let you decide if you should shift tasks from one person to another. The milestones mark your progress. If you use a fancy project planning tool, do not be seduced into creating a Big Design Up Front (BDUF) for the project, but use it maintain concision and up-to-dateness.

If you miss a milestone, you should take immediate action such as informing your boss that the scheduled completion of that project has slipped by that amount. The estimate and schedule could never have been perfect to begin with; this creates the illusion that you might be able to make up the days you missed in the latter part of the project. You might. But it is just as likely that you have underestimated that part as that you have overestimated it. Therefore the scheduled completion of the project has already slipped, whether you like it or not.

Make sure you plan includes time for: internal team meetings, demos, documentation, scheduled periodic activities, integration testing, dealing with outsiders, sickness, vacations, maintenance of existing products, and maintenance of the development environment. The project plan can serve as a way to give outsiders or your boss a view into what you or your team is doing. For this reason it should be short and up-to-date.

How to Manage Third-Party Software Risks

A project often depends on software produced by organizations that it does not control. There are great risks associated with third party software that must be recognized by everyone involved.

Never, ever, rest any hopes on vapor . Vapor is any alleged software that has been promised but is not yet available. This is the surest way to go out of business. It is unwise to be merely skeptical of a software company's promise to release a certain product with a certain feature at a certain date; it is far wiser to ignore it completely and forget you ever heard it. Never let it be written down in any documents used by your company.

If third-party software is not vapor, it is still risky, but at least it is a risk that can be tackled. If you are considering using third-party software, you should devote energy early on to evaluating it. People might not like to hear that it will take two weeks or two months to evaluate each of three products for suitability, but it has to be done as early as possible. The cost of integrating cannot be accurately estimated without a proper evaluation.

Understanding the suitability of existing third party software for a particular purpose is very tribal knowledge. It is very subjective and generally resides in experts. You can save a lot of time if you can find those experts. Often times a project will depend on a third-party software system so completely that if the integration fails the project will fail. Express risks like that clearly in writing in the schedule. Try to have a contingency plan, such as another system that can be used or the ability to write the functionality yourself if the risk can't be removed early. Never let a schedule depend on vapor.

How to Manage Consultants

Use consultants, but don't rely on them. They are wonderful people and deserve a great deal of respect. Since they get to see a lot of different projects, they often know more about specific technologies and even programming techniques than you will. The best way to use them is as educators in-house that can teach by example.

However, they usually cannot become part of the team in the same sense that regular employees are, if only because you may not have enough time to learn their strengths and weaknesses. Their financial commitment is much lower. They can move more easily. They may have less to gain if the company does well. Some will be good, some will be average, and some will be bad, but hopefully your selection of consultants will not be as careful as your selection of employees, so you will get more bad ones.

If consultants are going to write code, you must review it carefully as you go along. You cannot get to the end of the a project with the risk of a large block of code that has not been reviewed. This is true of all team members, really, but you will usually have more knowledge of the team members closer to you.

How to Communicate the Right Amount

Carefully consider the cost of a meeting; it costs its duration multiplied by the number of participants . Meetings are sometimes necessary, but smaller is usually better. The quality of communication in small meetings is better, and less time overall is wasted. If any one person is bored at a meeting take this as a sing, that the meeting should be smaller.

Everything possible should be done to encourage informal communication. More useful work is done during lunches with colleagues than during any other time. It is a shame that more companies do not recognize nor support this fact.

How to Disagree Honestly and Get Away with It

Disagreement is a great opportunity to make a good decision, but it should be handled delicately. Hopefully you feel that you have expressed your thoughts adequately and been heard before the decision is made. In that case there is nothing more to say, and you should decide whether you will stand behind the decision even though you disagree with it. If you can support this decision even though you disagree, say so. This shows how valuable you are because you are independent and are not a yes-man, but respectful of the decision and a team player.

Sometimes a decision that you disagree with will be made when the decision makers did not have the full benefit of you opinion. You should then evaluate whether to raise the issue on the basis of the benefit to the company or tribe. If it is a small mistake in your opinion, it may not be worth reconsidering. If it is a large mistake in you opinion, then of course you must present an argument.

Usually, this is not a problem. In some stressful circumstances and with some personality types this can lead to things being taken personally. For instance, some very good programmers lack the confidence needed to challenge a decision even when they have good reason to believe it is wrong. In the worst of circumstances the decision maker is insecure and takes it as a personal challenge to their authority. It is best to remember that in such circumstances people react with the reptilian part of their brains. You should present your argument in private, and try to show how new knowledge changes the basis on which the decision was made.

Whether the decision is reversed or not, you must remember that you will never be able to say ' I told you so! ' since the alternate decision was fully explored.

判决

How to Tradeoff Quality Against Development Time

Software development is always a compromise between what the project does and getting the project done. But you may be asked to tradeoff quality to speed the deployment of a project in a way that offends your engineering sensibilities or business sensibilities. For example, you may be asked to do something that is a poor software engineering practice and that will lead to a lot of maintenance problems.

If this happens your first responsibility is to inform your team and to clearly explain the cost of the decrease in quality. After all, your understanding of it should be much better than your boss's understanding. Make it clear what is being lost and what is being gained, and at what cost the lost ground will be regained in the next cycle. In this, the visibility provided by a good project plan should be helpful. If the quality tradeoff affects the quality assurance effort, point that out (both to your boss and quality assurance people). If the quality tradeoff will lead to more bugs being reported after the quality assurance period, point that out.

If she still insists you should try to isolate the shoddiness into particular components that you can plan to rewrite or improve in the next cycle. Explain this to your team so that they can plan for it.

NinjaProgrammer at Slashdot sent in this gem:

Remember that a good design will be resillient against poor code implementations. If good interfaces and abstractions exist throughout the code, then the eventual rewrites will be far more painless. If it is hard to write clear code that is hard to fix, consider what is wrong with the core design that is causing this.

How to Manage Software System Dependence

Modern software systems tend to depend on a large number of components that may not be directly under your control. This increases productivity through synergy and reuse. However, each component brings with it some problems:

  • How will you fix bugs in the component?

  • Does the component restrict you to particular hardware or software systems?

  • What will you do if the component fails completely?

It is always best to encapsulate the component in some way so that it is isolated and so that it can be swapped out. If the component proves to be completely unworkable, you may be able to get a different one, but you may have to write your own. Encapsulation is not portability, but it makes porting easier, which is almost as good.

Having the source code for a component decreases the risk by a factor of four. With source code, you can evaluate it easier, debug it easier, find workarounds easier, and make fixes easier. If you make fixes, you should give them to the owner of the component and get the fixes incorporated into an official release; otherwise you will uncomfortably have to maintain an unofficial version .

How to Decide if Software is Too Immature

Using software other people wrote is one of the most effective ways to quickly build a solid system. It should not be discouraged, but the risks associated with it must be examined. One of the biggest risks is the period of bugginess and near inoperability that is often associated with software before it matures, through usage, into a usable product. Before you consider integrating with a software system, whether created in house or by a third party, it is very important to consider if it is really mature enough to be used. Here are ten questions you should ask yourself about it:

  1. Is it vapor? (Promises are very immature).

  2. Is there an accessible body of lore about the software?

  3. Are you the first user?

  4. Is there a strong incentive for continuation?

  5. Has it had a maintenance effort?

  6. Will it survive defection of the current maintainers?

  7. Is there a seasoned alternative at least half as good?

  8. Is it known to your tribe or company?

  9. Is it desirable to your tribe or company?

  10. Can you hire people to work on it even if it is bad?

A little consideration of these criteria demonstrates the great value of well-established free software and open-source software in reducing risk to the entrepreneur.

How to Make a Buy vs. Build Decision

An entrepreneurial company or project that is trying to accomplish something with software has to constantly make so-called buy vs. build decisions. This turn of phrase is unfortunate in two ways: it seems to ignore open-source and free software which is not necessarily bought . Even more importantly, it should perhaps be called an obtain and integrate vs. build here and integrate decision because the cost of integration must be considered. This requires a great combination of business, management, and engineering savvy.

  • How well do your needs match those for which it was designed?

  • What portion of what you buy will you need?

  • What is the cost of evaluating the integration?

  • What is the cost of integration?

  • What is the cost of evaluating the integration?

  • Will buying increase or decrease long term maintenance costs?

  • Will building it put you in a business position you don't want to be in?

You should think twice before building something that is big enough to serve as the basis for an entire other business. Such ideas are often proposed by bright and optimistic people that will have a lot to contribute to your team. If their idea is compelling, you may wish to change your business plan; but do not invest in a solution bigger than your own business without conscious thought.

After considering these questions, you should perhaps prepare two draft project plans, one for building and one for buying. This will force you to consider the integration costs. You should also consider the long term maintenance costs of both solutions. To estimate the integration costs, you will have to do a thorough evaluation of the software before you buy it. If you can't evaluate it, you will assume an unreasonable risk in buying it and you should decide against buying that particular product. If there are several buy decisions under consideration, some energy will have to be spent evaluating each.

How to Grow Professionally

Assume responsibility in excess of your authority. Play the role that you desire. Express appreciation for people's contribution to the success of the larger organization, as well as things as that help you personally.

If you want to become a team leader, instigate the formation of consensus. If you want to become a manager, take responsibility for the schedule. You can usually do this comfortably while working with a leader or a manager, since this frees them up to take greater responsibility. If that is too much to try, do it a little at a time.

Evaluate yourself. If you want to become a better programmer, ask someone you admire how you can become like them. You can also ask your boss, who will know less but have a greater impact on your career.

Plan ways to learn new skills, both the trivial technical kind, like learning a new software system, and the hard social kind, like writing well, by integrating them into your work.

How to Evaluate Interviewees

Evaluating potential employees is not given the energy it deserves. A bad hire, like a bad marriage, is terrible. A significant portion of everyone's energy should be devoted to recruitment, though this is rarely done.

There are different interviewing styles. Some are torturous, designed to put the candidate under a great deal of stress. This serves a very valuable purpose of possibly revealing character flaws and weaknesses under stress. Candidates are no more honest with interviewers than they are with themselves, and the human capacity for self-deception is astonishing.

You should, at a minimum, give the candidate the equivalent of an oral examination on the technical skills for two hours. With practice, you will be able to quickly cover what they know and quickly retract from what they don't know to mark out the boundary. Interviewees will respect this. I have several times heard interviewees say that the quality of the examination was one of their motivations for choosing a company. Good people want to be hired for their skills, not where they worked last or what school they went to or some other inessential characteristic.

In doing this, you should also evaluate their ability to learn, which is far more important than what they know. You should also watch for the whiff of brimstone that is given off by difficult people. You may be able to recognize it by comparing notes after the interview, but in the heat of the interview it is hard to recognize. How well people communicate and work with people is more important than being up on the latest programming language.

A reader has had good luck using a ' take-home ' test for interviewees. This has the advantage that can uncover the interviewee that can present themselves well but can't really code---and there are many such people. I personally have not tried this technique, but it sounds sensible.

Finally, interviewing is also a process of selling. You should be selling your company or project to the candidate. However, you are talking to a programmer, so don't try to color the truth. Start off with the bad stuff, then finish strong with the good stuff.

How to Know When to Apply Fancy Computer Science

There is a body of knowledge about algorithms, data structures, mathematics, and other gee-whiz stuff that most programmers know about but rarely use. In practice, this wonderful stuff is too complicated and generally unnecessary. There is no point in improving an algorithm when most of your time is spent making inefficient database calls, for instance. An unfortunate amount of programming consists of getting systems to talk to each other and using very simple data structures to build a nice user interface.

When is high technology the appropriate technology? When should you crack a book to get something other than a run-of-the-mill algorithm? It is sometimes useful to do this but it should be evaluated carefully.

The three most important considerations for the potential computer science technique are:

  • Is it well encapsulated so that the risk to other systems is low and the overall increase in complexity and maintenance cost is low?

  • Is the benefit startling (for example, a factor of two in a mature system or a factor of ten in a new system)?

  • Will you be able to test and evaluate it effectively?

If a well-isolated algorithm that uses a slightly fancy algorithm can decrease hardware cost or increase performance by a factor of two across an entire system, then it would be criminal not to consider it. One of the keys to arguing for such an approach is to show that the risk is really quite low, since the proposed technology has probably been well studied, the only issue is the risk of integration. Here a programmer's experience and judgment can truly synergize with the fancy technology to make integration easy.

How to Talk to Non-Engineers

Engineers and programmers in particular are generally recognized by popular culture as being different from other people. This implies that other people are different from us. This is worth bearing in mind when communicating with non-engineers; you should always understand the audience.

Non-engineers are smart, but not as grounded in creating technical things as we are. We make things. They sell things and handle things and count things and manage things, but they are not experts on making things. They are not as good at working together on teams as engineers are (there are no doubt exceptions.) [ 3 ] Their social skills are generally as good as or better than engineers in non-team environments, but their work does not always demand that they practice the kind of intimate, precise communication and careful subdivisions of tasks that we do.

Non-engineers may be too eager to please and they may be intimidated by you. Just like us, they may say ' yes ' without really meaning it to please you or because they are a little scared of you, and then not stand behind their words.

Non-programmers can understand technical things but they do not have the thing that is so hard even for us---technical judgment. They do understand how technology works, but they cannot understand why a certain approach would take three months and another one three days. (After all, programmers are anecdotally horrible at this kind of estimation as well.) This represents a great opportunity to synergize with them.

When talking to your team you will, without thinking, use a sort of shorthand, an abbreviated language that is effective because you will have much shared experience about technology in general and your product in particular. It takes some effort not to use this shorthand with those that don't have that shared experience, especially when members of your own team are present. This vocabulary create a wall between you and those that do not share it, and, even worse, wastes their time.

With your team, the basic assumptions and goals do not need to be restated often, and most conversation focuses on the details. With outsiders, it must be the other way around. They may not understand things you take for granted. Since you take them for granted and don't repeat them, you can leave a conversation with an outsider thinking that you understand each other when really there is a large misunderstanding. You should assume that you will miscommunicate and watch carefully to find this miscommunication. Try to get them to summarize or paraphrase what you are saying to make sure they understand. If you have the opportunity to meet with them often, spend a little bit of time asking if you you are communicating effectively, and how you can do it better. If there is a problem in communication, seek to alter your own practices before becoming frustrated with theirs.

I love working with non-engineers. It provides great opportunities to learn and to teach. You can often lead by example, in terms of the clarity of your communication. Engineers are trained to bring order out of chaos, to bring clarity out of confusion, and non-engineers like this about us. Because we have technical judgment and can usually understand business issues, we can often find a simple solution to a problem.

Often non-engineers propose solutions that they think will make it easier on us out of kindness and a desire to do the right thing, when in fact a much better overall solution exists which can only be seen by synergizing the outsiders view with your technical judgment. I personally like Extreme Programming because it addresses this inefficiency; by marrying the estimation quickly to the idea, it makes it easier to find the idea that is the best combination of cost and benefit.



[ 1 ]to hit

第4章。 先进

Technological Judgment

How to Tell the Hard From the Impossible

It is our job to do the hard and discern the impossible. From the point of view of most working programmers, something is impossible if either it cannot be grown from a simple system or it cannot be estimated. By this definition what is called research is impossible. A large volume of mere work is hard, but not necessarily impossible.

The distinction is not facetious because you may very well be asked to do what is practically impossible, either from a scientific point of view or a software engineering point of view. It then becomes your job to help the entrepreneur find a reasonable solution which is merely hard and gets most of what they wanted. A solution is merely hard when it can be confidently scheduled and the risks are understood.

It is impossible to satisfy a vague requirement, such as ' Build a system that will compute the most attractive hair style and color for any person. ' If the requirement can be made more crisp, it will often become merely hard, such as ' Build a system to compute an attractive hair style and color for a person, allow them to preview it and make changes, and have the customer satisfaction based on the original styling be so great that we make a lot of money. ' If there is not crisp definition of success, you will not succeed.

How to Utilize Embedded Languages

Embedding a programming language into a system has an almost erotic fascination to a programmer. It is one of the most creative acts that can be performed. It makes the system tremendously powerful. It allows you to exercise her most creative and Promethean skills. It makes the system into your friend.

The best text editors in the world all have embedded languages. This can be used to the extent that the intended audience can master the language. Of course, use of the language can be made optional, as it is in text editors, so that initiates can use it and no one else has to.

I and many other programmers have fallen into the trap of creating special purpose embedded languages. I fell into it twice. There already exist many languages designed specifically to be embedded languages. You should think twice before creating a new one.

The real question to ask oneself before embedding a language is: Does this work with or against the culture of my audience? If you intended audience is exclusively non-programmers, how will it help? If your intended audience is exclusively programmers, would they prefer an applications programmers interface (API)? And what language will it be? Programmers don't want to learn a new language that is narrowly used; but if it meshes with their culture they will not have to spend much time learning it. It is a joy to create a new language. But we should not let that blind us to the needs of the user. Unless you have some truly original needs and ideas, why not use an existing language so that you can leverage the familiarity users already have with it?

Choosing Languages

The solitary programmer that loves his work (a hacker) can choose the best language for the task. Most working programmers have very little control of the language they will use. Generally, this issue is dictated by pointy-haired bosses who are making a political decision, rather than a technological decision, and lack the courage to promote an unconventional tool even when they know, often with firsthand knowledge, that the less accepted tool is best. In other cases the very real benefit of unity among the team, and to some extent with a larger community, precludes choice on the part of the individual. Often managers are driven by the need to be able to hire programmers with experience in a given language. No doubt they are serving what they perceive to be the best interests of the project or company, and must be respected for that. However, I personally believe this the most wasteful and erroneous common practice you are likely to encounter.

But of course, things are never one-dimensional. Even if a core language is mandated and beyond your control, it is often the case that tools and other programs can and should be written in a different language. If a language is to be embedded (and you should always consider it!) the choice of language will depend a lot on the culture of the users. One should take advantage of this to serve your company or project by using the best language for the job, and in so doing make work more interesting.

Programming languages should really be called notations in that learning one is not at all as difficult as learning a natural language. To beginners and to some outsiders ``learning a new language'' seems a daunting task; but after you have three under your belt it's really just a question of becoming familiar with the available libraries. One tends to think of a large system that has components in three or four languages as a messy hodgepodge; but I argue that such a system is in many cases stronger than a one-language system in several ways:

  • There is necessarily loose coupling between the components that are written in different notations (though maybe not clean interfaces),

  • You can evolve to a new language/platform easily by rewriting each component individually,

  • Its possible that some of the modules are actually up-to-date.

Some of these effects may only be psychological; but psychology matters. In the end the costs of language tyranny outweigh any advantage that it provides.

Compromising Wisely

How to Fight Schedule Pressure

Time-to-market pressure is the pressure to deliver a good product quickly. It is good because it reflects a financial reality, and is healthy up to a point. Schedule pressure is the pressure to deliver something faster than it can be delivered and it is wasteful, unhealthy, and all too common.

Schedule pressure exists for several reasons. The people who task programmers do not fully appreciate what a strong work ethic we have and how much fun it is to be a programmer. Perhaps because they project their own behavior onto us, they believe that asking for it sooner will make us work harder to get it there sooner. This is probably actually true, but the effect is very small, and the damage is very great. Additionally, they have no visibility into what it really takes to produce software. Not being able to see it, and not be able to create it themselves, the only thing they can do is see time-to-market pressure and fuss at programmers about it.

The key to fighting schedule pressure is simply to turn it into time-to-market pressure. The way to do this to give visibility into the relationship between the available labor and the product. Producing an honest, detailed, and most of all, understandable estimate of all the labor involved is the best way to do this. It has the added advantage of allowing good management decisions to be made about possible functionality tradeoffs.

The key insight that the estimate must make plain is that labor is an almost incompressible fluid. You can't pack more into a span of time anymore than you can pack more water into a container over and above that container's volume. In a sense, a programmer should never say ' no ', but rather to say ' What will you give up to get that thing you want? ' The effect of producing clear estimates will be to increase the respect for programmers. This is how other professionals behave. Programmers' hard work will be visible. Setting an unrealistic schedule will also be painfully obvious to everyone. Programmers cannot be hoodwinked. It is disrespectful and demoralizing to ask them to do something unrealistic. Extreme Programming amplifies this and builds a process around it; I hope that every reader will be lucky enough to use it.

How to Understand the User

It is your duty to understand the user, and to help your boss understand the user. Because the user is not as intimately involved in the creation of your product as you are, they behave a little differently:

  • The user generally makes short pronouncements.

  • The user has their own job; they will mainly think of small improvements in your product, not big improvements.

  • The user can't have a vision that represents the complete body of your product users.

It is your duty to give them what they really want, not what they say they want. It is however, better to propose it to them and get them to agree that your proposal is what they really want before you begin, but they may not have the vision to do this. Your confidence in your own ideas about this should vary. You must guard against both arrogance and false modesty in terms of knowing what the customer really wants. Programmers are trained to design and create. Market researchers are trained to figure out what people want. These two kinds of people, or two modes of thought in the same person, working harmoniously together give the best chance of formulating the correct vision.

The more time you spend with users the better you will be able to understand what will really be successful. You should try to test your ideas against them as much as you can. You should eat and drink with them if you can.

Guy Kawasaki[ Rules ] has emphasized the importance of watching what your users do in addition to listening to them.

I believe contractors and consultants often have tremendous problems getting their clients to clarify in their own minds what they really want. If you intend to be a consultant, I suggest you choose your clients based on their clear-headedness as well as their pocketbooks.

How to Get a Promotion

To be promoted to a role, act out that role first.

To get promoted to a title, find out what is expected of that title and do that.

To get a pay raise, negotiate armed with information.

If you feel like you are past due for a promotion, talk to your boss about it. Ask them explicitly what you need to do to get promoted, and try to do it. This sounds trite, but often times your perception of what you need to do will differ considerably from your boss's. Also this will pin your boss down in some ways.

Most programmers probably have an exaggerated sense of their relative abilities in some ways---after all, we can't all be in the top 10%! However, I have seem some people who were seriously unappreciated. One cannot expect everyone's evaluation to perfectly match reality at all times, but I think people are generally moderately fair, with one caveat: you cannot be appreciated without visibility into your work. Sometimes, do to happenstance or personal habits, someone will not be noticed much. Working from home a lot or being geographically separated from your team and boss makes this especially difficult.

Serving Your Team

How to Develop Talent

Nietschze exaggerated when he said[ Stronger ]:

What does not destroy me, makes me stronger.

Your greatest responsibility is to your team. You should know each of them well. You should stretch your team, but not overburden them. You should usually talk to them about the way they are being stretched. If they buy in to it, they will be well motivated. On each project, or every other project, try to stretch them in both a way that they suggest and a way that you think will be good for them. Stretch them not by giving them more work, but by giving them a new skill or better yet a new role to play on the team.

You should allow people (including yourself) to fail occasionally and should plan for some failure in your schedule. If there is never any failure, there can be no sense of adventure. If there are not occasional failures, you are not trying hard enough. When someone fails, you should be as gentle as you can with them while not treating them as though they had succeeded.

Try to get each team member to buy in and be well motivated. Ask each of them explicitly what they need to be well-motivated if they are not. You may have to leave them dissatisfied, but you should know what everybody desires.

You can't give up on someone who is intentionally not carrying their share of the load because of low morale or dissatisfaction and just let them be slack. You must try to get them well-motivated and productive. As long as you have the patience, keep this up. When your patience is exhausted, fire them. You cannot allow someone who is intentionally working below their level to remain on the team, since it is not fair to the team.

Make it clear to the strong members of your team that you think they are strong by saying so in public. Praise should be public and criticism private.

The strong members of the team will naturally have more difficult tasks than the weak members of the team. This is perfectly natural and nobody will be bothered by it as long as everyone works hard.

It is an odd fact that is not reflected in salaries that a good programmer is more productive than 10 bad programmers. This creates a strange situation. It will often be true that you could move faster if your weak programmers would just get out of the way. If you did this you would in fact make more progress in the short term. However, your tribe would lose some important benefits, namely the training of the weaker members, the spreading of tribal knowledge, and the ability to recover from the loss of the strong members. The strong must be gentle in this regard and consider the issue from all angles.

You can often give the stronger team members challenging, but carefully delineated, tasks.

How to Choose What to Work On

You balance your personal needs against the needs of the team in choosing what aspect of a project to work on. You should do what you are best at, but try to find a way to stretch yourself not by taking on more work but by exercising a new skill. Leadership and communication skills are more important than technical skills. If you are very strong, take on the hardest or riskiest task, and do it as early as possible in the project to decrease risk.

How to Get the Most From Your Teammates

To get the most from your teammates, develop a good team spirit and try to keep every individual both personally challenged and personally engaged.

To develop team spirit, corny stuff like logoized clothing and parties are good, but not as good as personal respect. If everyone respects everyone else, nobody will want to let anybody down. Team spirit is created when people make sacrifices for the team and think in terms of the good of the team before their own personal good. As a leader, you can't ask for more than you give yourself in this respect.

One of the keys to team leadership is to facilitate consensus so that everyone has buy in. This occasionally means allowing your teammates to be wrong. That is, if it does not harm the project too much, you must let some of your team do things their own way, based on consensus, even if you believe with great confidence it is the wrong thing to do. When this happens, don't agree, simply disagree openly and accept the consensus. Don't sound hurt, or like you're being forced into it, simply state that you disagree but think the consensus of the team is more important. This will often cause them to backtrack. Don't insist that they go through with their initial plan if they do backtrack.

If there is an individual who will not consent after you have discussed the issues from all appropriate sides, simply assert that you have to make a decision and that is what your decision is. If there is a way to judge if your decision will be wrong or if it is later shown to be wrong, switch as quickly as you can and recognize the persons who were right.

Ask your team, both as a group and individually, what they think would create team spirit and make for an effective team.

Praise frequently rather than lavishly. Especially praise those who disagree with you when they are praiseworthy. Praise in public and criticize in private; with one exception: sometimes growth or the correction of a fault can't be praised without drawing embarrassing attention to the original fault, so that growth should be praised in private.

How to Divide Problems Up

It's fun to take a software project and divide it up into tasks that will be performed by individuals. This should be done early. Sometimes managers like to think that an estimate can be made without consideration of the individuals that will perform the work. This is impossible since the productivity of individuals varies so widely. Who has particular knowledge about a component also constantly changes and can have an order of magnitude effect on performance.

Just as a composer considers the timbre of the instrument that will play a part or the coach of an athletic team considers the strengths of each player, the experienced team leader will not usually be able to separate the division of the project into tasks from the team members to which they will be assigned. This is part of the reason that a high-performing team should not be broken up.

There is a certain danger in this given that people will become bored as they build upon their strengths and never improve their weaknesses or learn new skills. However, specialization is a very useful productivity tool when not overused.

How to Handle Boring Tasks

Sometimes it is not possible to avoid boring tasks that are critical to the success of the company or the project. These tasks can really hurt the morale of those that have to do them. The best technique for dealing with this is to invoke or promote Larry Wall's programmer's virtue of Laziness. Try to find some way to get the computer to do the task for you or to help your teammates do this. Working for a week on a program to do a task that will take a week to do by hand has the great advantage of being more educational and sometimes more repeatable.

If all else fails, apologize to those who have to do the boring task, but under no circumstances allow them to do it alone. At a minimum assign a team of two to do the work and promote healthy teamwork to get the task done.

How to Gather Support for a Project

To gather support for a project, create and communicate a vision that demonstrates real value to the organization as a whole. Attempt to let others share in your vision creation. This gives them a reason to support you and gives you the benefit of their ideas. Individually recruit key supporters for your project. Wherever possible, show, don't tell. If possible, construct a prototype or a mockup to demonstrate your ideas. A prototype is always powerful but in software it is far superior to any written description.

How to Grow a System

The seed of a tree contains the idea of the adult but does not fully realize the form and potency of the adult. The embryo grows. It becomes larger. It looks more like the adult and has more of the uses. Eventually it bears fruit. Later, it dies and its body feeds other organisms.

We have the luxury of treating software like that. A bridge is not like that; there is never a baby bridge, but merely an unfinished bridge. Bridges are a lot simpler than software.

It is good to think of software as growing, because it allows us to make useful progress before we have a perfect mental image. We can get feedback from users and use that to correct the growth. Pruning off weak limbs is healthful.

The programmer must design a finished system that can be delivered and used. But the advanced programmer must do more. You must design a growth path that ends in the finished system. It is your job to take a germ of an idea and build a path that takes it as smoothly as possible into a useful artifact.

To do this, you must visualize the end result and communicate it in a way that the engineering team can get excited about. But you must also communicate to them a path that goes from wherever they are now to where they want to be with no large leaps. The tree must stay alive the whole time; it cannot be dead at one point and resurrected later.

This approach is captured in spiral development. Milestones that are never too far apart are used to mark progress along the path. In the ultra-competitive environment of business, it is best if the milestones can be released and make money as early as possible, even if they are far away from a well-designed endpoint. One of the programmer's jobs is to balance the immediate payoff against future payoff by wisely choosing a growth path expressed in milestones.

The advanced programmer has the triple responsibility of growing software, teams, and persons.

A reader, Rob Hafernik, sent in this comment on this section that I can do no better than to quote in full:

I think you under-emphasize the importance here. It's not just systems, but algorithms, user interfaces, data models, and so on. It's absolutely vital as you work on a large system to have measurable progress toward intermediate goals. Nothing is as bad as the special horror of getting down to the end and discovering that the whole thing just isn't going to work (look at the recent debacle of the Voter News System). I would even go further and state it as a law of nature: no large, complex system can be implemented from scratch, it can only be evolved from a simple system to a complex system in a series of intentional steps.

To which one can only reply Fiat lux !

How to Communicate Well

To communicate well, you have to recognize how hard it is. It is a skill unto itself. It is made harder by the fact that the persons with whom you have to communicate are flawed. They do not work hard at understanding you. They speak poorly and write poorly. They are often overworked or bored, and, at a minimum, somewhat focused on their own work rather than the larger issues you may be addressing. One of the advantages of taking classes and practicing writing, public speaking, and listening is that if you become good at it you can more readily see where problems lie and how to correct them.

The programmer is a social animal whose survival depends on communication with her team. The advanced programmer is a social animal whose satisfaction depends on communication with people outside her team.

The programmer brings order out of chaos. One interesting way to do this is to initiate a proposal of some kind outside the team. This can be done in a strawman or white-paper format or just verbally. This leadership has the tremendous advantage of setting the terms of the debate. It also exposes you to criticism, and worse, rejection and neglect. The advanced programmer must be prepared to accept this, because she has a unique power and therefore a unique responsibility. Entrepreneurs who are not programmers need programmers to provide leadership in some ways. Programmers are the part of the bridge between ideas and reality that rests on reality.

I haven't mastered communicating well, but what I'm currently trying is what I think of a four-pronged approach: After I have my ideas in order and am fully prepared, I try to speak verbally, hand people a white-paper (on real paper, as well as electronically) show them a demo, and then patiently repeat this process. I think a lot of times we are not patient enough in this kind of difficult communication. You should not be disheartened if your ideas are not immediately accepted. If you have invested energy in there preparation, no one will think poorly of you for it.

How to Tell People Things They Don't Want to Hear

You will often have to tell people things that will make them uncomfortable. Remember that you are doing this for a reason. Even if nothing can be done about the problem, you are telling them as early as possible so they will be well-informed.

The best way to tell someone about a problem is to offer a solution at the same time. The second best way is to appeal to them for help with the problem. If there is a danger that you won't be believed, you should gather some support for your assertion.

One of the most unpleasant and common things you will have to say is, ' The schedule will have to slip. ' The conscientious programmer hates to say this, but must say it as early as possible. There is nothing worse than postponing action when a milestone slips, even if the only action is to inform everyone. In doing this, it is better to do it as a team, at least in spirit, if not physically. You will want your team's input on both where you stand and what can be done about it, and the team will have to face the consequences with you.

How to Deal with Managerial Myths

The word myth sometimes means fiction. But it has a deeper connotation. It also means a story of religious significance that explains the universe and mankind's relationship to it. Managers tend to forget what they learned as programmers and believe in certain myths. It would be as rude and unsuccessful to try to convince them these myths are false as to try to disillusion a devoutly religious person of their beliefs. For that reason, you should recognize these beliefs as myths:

  • More documentation is always better. (They want it, but they don't want you to spend any time on it.)

  • Programmers can be equated. (Programmers vary by an order of magnitude.)

  • Resources can be added to a late project to speed it. (The cost of communication with the new persons is almost always more taxing than helpful.)

  • It is possible to estimate software development reliably. (It is not even theoretically possible.)

  • Programmers' productivity can be measured in terms of some simple metric, like lines of code. (If succinctness is power, lines of code are bad, not good.)

If you have an opportunity, you can try to explain these things, but don't feel bad if you have no success and don't damage your reputation by confronting these myths belligerently. Each of these myths reinforces the manager's idea that they have some actual control over what is going on. The truth is that managers facilitate if they are good, and impede if they are bad.

How to Deal with Organizational Chaos

There are often brief periods of great organizational chaos, such as layoffs, buyouts, ipos, firings, new hirings, and so on. These are unsettling to everyone, but perhaps a little less unsettling to the programmer whose personal self-esteem is founded in capacity rather than in position. Organizational chaos is a great opportunity for programmers to exercise their magic power. I've saved this for last because it is a deep tribal secret. If you are not a programmer, please stop reading now.

Engineers have the power to create and sustain.

Non-engineers can order people around but, in a typical software company, can create and sustain nothing without engineers, just as engineers typically cannot sell a product or manage a business effectively. This power is proof against almost all of the problems associated with temporary organizational mayhem. When you have it you should ignore the chaos completely and carry on as if nothing is happening. You may, of course, get fired, but if that happens you can probably get a new job because of the magic power. More commonly, some stressed-out person who does not have the magic power will come into your cube and tell you to do something stupid. If you are really sure that it is stupid, it is best to smile and nod until they go away and then carry on doing what you know is best for the company.

If you are a leader, tell your people to do the same thing and tell them to ignore what anybody else tells them. This course of action is the best for you personally, and is the best for your company or project.

词汇表

This is a glossary of terms as used in this essay. These do not necessarily have a standardized meaning to other people. Eric S. Raymond has compiled a massive and informative glossary[ HackerDict ] that rather surprisingly can pleasurably be read cover-to-cover once you can appreciate a fraction of it.

unk-unk

Slang for unknown-unknown. Problems that cannot presently even be conceptualized that will steal time away from the project and wreck the schedule.

老板

The person or entity that gives you tasks. In some cases this may be the public at large.

printlining

The insertion of statements into a program on a strictly temporary basis that output information about the execution of the program for the purpose of debugging.

记录

The practice of writing a program so that it can produce a configurable output log describing its execution.

分而治之

A technique of top-down design and, importantly, of debugging that is the subdivision of a problem or a mystery into progressively smaller problems or mysteries.

Illusionary and often deceptive promises of software that is not yet for sale and, as often as not, will never materialize into anything solid.

老板

The person who sets your tasks. In some cases, the user is the boss.

部落

The people with whom you share loyalty to a common goal.

low-hanging fruit

Big improvements that cost little.

企业家

The initiator of projects.

垃圾

Objects that are no longer needed that hold memory.

商务服务

A group of people organized for making money.

公司

A group of people organized for making money.

部落

A group of people you share cultural affinity and loyalty with.

scroll blindness

The effect of being unable to find information you need because it is buried in too much other, less interesting information.

wall-clock

Actually time as measured by a clock on a wall, as opposed to CPU time.

瓶颈

The most important limitation in the performance of a system. A constriction that limits performance.

A unique piece of information from which all cached copies are derived that serves as the official definition of that data.

heap allocated

Memory can be said to be heap allocated whenever the mechanism for freeing it is complicated.

垃圾

Allocated memory that no longer has any useful meaning.

garbage collector

A system for recycling garbage.

内存泄漏

The unwanted collection of references to objects that prevents garbage collection (or a bug in the garbage collector or memory management system!) that causes the program to gradually increase its memory demands over time.

极限编程

A style of programming emphasizing communication with the customer and automated testing.

hitting the wall

To run out of a specific resource causing performance to degrade sharply rather than gradually.

speculative programming

Producing a feature before it is really known if that feature will be useful.

信息隐藏

A design principle that seeks to keep things independent and decoupled by using interfaces that expose as little information as possible.

object-oriented programming

An programming style emphasizing the the management of state inside objects.

communication languages

A language designed primarily for standardization rather than execution.

boxes and arrows

A loose, informal style of making diagrams consiting of boxes and arrows drawn between those boxes to show the relationships. This contrast with formal diagram methodologies, such as UML.

lingua franca

A language so popular as to be a de facto standard for its field, as French was for international diplomacy at one time.

buy vs. build

An adjective describing a choice between spending money for software or writing it your self.

mere work

Work that requires little creativity and entails little risk. Mere work can be estimated easily.

programming notation

A synonym for programming language that emphasizes the mathematical nature of programming language and their relative simplicity compared to natural languages.

稻草人

A document meant to be the starting point of a technical discussion. A strawman may lead to a stickman, tinman, woodman, ironman, etc.

wite-paper

An informative document that is often meant to explain or sell a product or idea to an audience different than the programmers of that product or idea.

Bibliography/Websiteography

书籍

[ Rules00 ] Guy Kawasaki , Michelle Moreno , and Gary Kawasaki . 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services .

[ RDev96 ] Steve McConnell . 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules .

[ CodeC93 ] Steve McConnell . 1993. Microsoft Press. Redmond, Wash. Code Complete .

[ XP99 ] Kent Beck . 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change .

[ PlanXP00 ] Kent Beck and Martin Fowler . 2000. 0201710919. Addison-Wesley. Planning Extreme Programming .

[ Prag99 ] Andrew Hunt , David Thomas , and Ward Cunningham . 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master .

[ Stronger ] Friedrich Nietzsche . 1889. Twilight of the Idols, "Maxims and Arrows", section 8. .

网站

[ PGSite ] Paul Graham . 2002. Articles on his website: http://www.paulgraham.com/articles.html. All of them, but especially "Beating the Averages" .

[ Hacker ] Eric S. Raymond . 2003. How to Become a Hacker . http://www.catb.org/~esr/faqs/hacker-howto.html.

[ HackDict ] Eric S. Raymond . 2003. The New Hacker Dictionary . http://catb.org/esr/jargon/jargon.html.

[ ExpCS ] Edsger W. Dijkstra . 1986. How Experimental is Computing Science? . http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF.

[ Knife ] Edsger W. Dijkstra . 1984. On a Cultural Gap . http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF .

Appendix B. History (As Of February, 2003)

Request for Feedback or Extension

Please send me any comments you may have on this essay. I consider all suggestions, many of which have already improved this essay.

I have placed this essay under the GNU Free Documentation License. This license is not specifically designed for essays. Essays are usually intended to be coherent and convincing arguments that are writtien from a single point of view in a single voice. I hope this essay is a short and pleasant read.

I also hope that it is instructive. Although not a textbook, it is broken into many small sections to which new sections can be freely added. If so inclined, you are encouraged to expand upon this essay as you see fit, subject to the provisions of the License.

It may be arrogance to imagine that this document is worthy of extension; but hope springs eternal. I would be joyous if it were extended in the following ways:

  • The addition of a comprehensive reading list to each section,

  • The addition of more and better sections,

  • Translation into other languages, even if only on a subsection-by-subsection basis, and/or

  • Criticism or commentary in-lined into the text.

  • The ability to build into different formats, such as palm formats and better HTML.

If you inform me of your work, I will consider it and may include it in subsequent versions that I produce, subject to the provisions of the License. You may of course produce your own versions of this document without my knowledge, as explained in the License.

谢谢。

Robert L. Read

原始版本

The original version of this document was begun by Robert L. Read in the year 2000 and first published electronically at Samizdat Press(http://Samizdat.mines.edu) in 2002. It is dedicated to the programmers of Hire.com.

After this article was mentioned on Slashdot in 2003, about 75 people sent me email with suggestions and errata. I appreciate them all. There was a lot of duplication, but the following people either made major suggestions or were the first to find a bug that I fixed: Morgan McGuire, David Mason, Tom Moertel, Ninja Programmer (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark Howe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, Andrew Wu, David Jeschke, and Tom Corcoran.

Finally I would like to thank Christina Vallery, whose editing and proofreading greatly improved the second draft, and Wayne Allen, who encouraged me to initiate this.

Original Author's Bio

Robert L. Read lives in Austin, Texas, with his wife and two children. He is currently a Principal Engineer at Hire.com, where he has worked for four years. Prior to that he founded 4R Technology, which made a scanner-based image analysis quality control tool for the paper industry.

Rob received a PhD from the University of Texas at Austin in 1995 in Computer Science related to database theory. In 1987 he received a BA in Computer Science from Rice University. He has been a paid programmer since the age of 16.

附录C GNU自由文档许可证

Version 1.2, November 2002

Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

序言

本许可证的目的是使手册,教材或其他功能和有用的文件,“自由”的自由感,以确保每个人都有效的自由复制和重新发布,或不修改它,无论是商业或不能盈利。 其次,这个许可保留作者和出版者对他们的工作方式来获得信贷,而不是被认为是他人的改动负责。

这个许可证是一种的“copyleft”,这意味着文档的衍生作品本身必须是在同一意义上的自由。 它补充,这是一个自由软件设计的copyleft许可证的GNU通用公共许可证。

我们设计了这个许可证,以免费软件使用手册,因为自由软件需要自由的文档:一个免费的程序来提供相同的自由软件的手册。 But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. 我们建议本授权主要工程,其目的是指导或参考。

适用性和定义

本许可证适用于任何手动或其他工作,在任何介质,它包含由版权持有人可以根据本授权条款分发放置了一个通知。 这样的通知,授予一个全球性的,免版税的许可,在时间无限,使用本文所述的条件下工作。 “文件”,下面,是指任何这样的手册或工作。 任何公众成员是持牌人,被称为“您”解决。 你接受许可协议,如果你复制,修改或分发的工作中需要根据著作权法许可的方式。

“改良版”的文件意味着包含文档或它的一部分的任何工作,无论是逐字复制,修改和/或翻译成另一种语言。

1名为附录或1的文档前面的问题部分,涉及专门的出版商或文档的作者与文档的总体主题(或相关事宜)的关系和包含什么,可能属于直接一个“中学组”在那个整体主题。 (因此,如果文件的部分内容是数学教科书,中学组可能无法解释任何数学。)的关系可能是一个主题或相关事宜与历史连接的问题,或法律,商业,哲学,伦理对于他们的政治立场。

“恒常章节”的某些次要章节,其被指定,作为恒常章节,在通知中说,该文件是根据本许可证发布的标题。 If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. 该文件可能包含不变章节。 如果文件并没有确定任何恒常章节,那么就是没有。

“封面文字”有一定的短期上市,封面文字或封底文本在通知中说,该文件是根据本许可证发布的文字段落。 前端封面文字可能是最多的5个字,一个备用封面文字可能是最多25个字。

“透明”的文件的副本是指一个机器可读的拷贝,代表的格式,其规格是向公众提供,这是适合直截了当地用通用文本编辑器或修改的文件(像素组成的图像)​​通用涂料方案(图)一些广泛使用的绘图编辑器,是适用于输入到文字格式化或自动翻译各种格式适合于输入到文字格式化。 A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. 一个是不“透明”的拷贝称为“不透明”。

透明拷贝的合适格式的例子包括没有标记的纯ASCII码,Texinfo输入格式,LaTeX输入格式,SGML或XML使用一个公开的DTD,并符合标准的简单HTML,PostScript或PDF为人类改造设计。 透明的图像格式包括PNG,XCF和JPG。 不透明的格式包括专有格式,可以读取和编辑只有通过专有的文字处理器,SGML或XML的DTD和/或处理工具不是一般可用,以及一些文字处理器所产生的机器生成的HTML,PostScript或PDF只有输出的目的。

“标题页”的意思,印刷的书,扉页本身,加上需要持有,清晰,本许可需要出现在标题页的材料如以下页面。 对于作品在没有任何此类的标题页的格式,“标题页”指附近工作的标题最突出的外观文本,正文开始之前。

A段“标题为XYZ”是指命名的文件,其标题要么是精确的XYZ或包含XYZ的文字转换另一种语言XYZ后的括号亚基。 (这里,XYZ代表一个特定的下面一节中提到的名称,如“致谢”,“贡献”,“背书”,或“历史”,)“保存”的标题,这样一节,当你修改的文件时,意味着仍然一节“标题为XYZ”根据这一定义。

该文件可能包括通知指出,本许可证适用于文档的免责声明。 这些免责声明被认为是包含在本许可的职权,但只作为放弃担保:这些免责声明,可能有任何其他含义,是无效的,并具有对本许可证的含义没有影响。

逐字的复制

您可以复制和分发的文件在任何媒介,无论是商业或不能盈利,只要在所有副本中复制本许可证,版权声明和许可声明,称此许可证适用于文档,你没有任何其他条件本许可证。 你可能不使用技术手段阻碍或控制阅读或进一步复制您制作或分发的副本。 然而,你可以接受在复制品的交易补偿。 如果你分配一个足够大的拷贝数量,​​你还必须遵循第3条中的条件。

您可能还借出拷贝,上述相同条件下,你可以公开显示的副本。

复印数量

如果你出版印刷副本的,通常有印刷封面的媒体的拷贝文档,编号100多个,和封面文字文档的许可通知,你必须附上封面携带的副本,清楚且易读,所有这些封面文字:封面文字上的封面,封底文本在封底。 这两种封面也必须清楚和清晰地识别这些复制品的出版者。 封面必须出示完整的标题,标题同样突出,可见所有单词。 除了封面上,你可以添加其他材料。 复制仅限于封皮的变化,只要它们保存文件的标题,并满足这些条件,可以作为治疗在其他方面的逐字复制。

如果所需要的文字或者盖太浩繁,以适应清楚,你应该把实际盖(多达符合合理)上市的第一,并继续休息,到相邻的页面。

如果你出版或分发不透明副本编号100多个文件,你必须包括沿每个不透明拷贝机器可读的透明拷贝,或是在每个不透明拷贝计算机网络位置从一般的网络状态使用公共访问下载使用公共标准的网络协议,一个完整的文档透明拷贝,补充材料。 如果你选择后者,你必须采取合理的审慎步骤,当你开始分发不透明拷贝数量,​​以保证这个透明拷贝,从而保持在规定的位置,直到至少一年后的最后一次,你分发不透明副本(直接或通过代理商或零售商),向公众版。

据要求,但不是必需的,你联系以及之前重新分配任何大数量的拷贝,给他们一个机会,提供的文件的更新版本,您的文件的作者。

变通

第2和第3段的条件下,您可以复制和分发的文件的修改版本,提供您正是这种许可下发布修改版本,填补文件的作用与改进的版本,从而许可分配和修改修改版本给任何拥有它的一个副本。 此外,你必须在修改版本做这些事情:

  1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). 你可以使用以前的版本相同的标题,如果该版本的原始出版者允许。
  2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.
  3. State on the Title page the name of the publisher of the Modified Version, as the publisher.
  4. Preserve all the copyright notices of the Document.
  5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
  6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
  7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.
  8. Include an unaltered copy of this License.
  9. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
  10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
  11. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
  12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. 部分数字或相当于不被视为章节标题的一部分。
  13. Delete any section Entitled "Endorsements". 这样的部分可能不包括在修改版本。
  14. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section.
  15. Preserve any Warranty Disclaimers.

如果修改版本包括新的前端问题的部分或合乎作为次要章节的附录,并包含从文件复制没有材料,你可以在你选择指定的部分或全部这些章节为恒常。 要做到这一点,将它们的标题修改版本的许可声明中恒常章节的列表。 这些标题必须不同于任何其它章节标题。

You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

您可以添加最多的一段话作为前封面文字五个字,并通过了多达25字作为封底文本,修改版本的封面文字列表的末尾。 前封面文字和封底文字之一,只有一个通道,可能会增加(或通过所作出的安排)的任何一个实体。 如果文件已经包含了先前由你或你是代表相同的实体安排的补充,在同样的封面封面文字,你可能不添加另一个;明确许可,但你可能会取代旧人,从先前出版者的旧。

作者(S)和出版商(S)的文档不给本授权许可使用的宣传,为他们的名字或断言或暗示任何修改版本背书。

合并文档

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

合并后的工作只需要包含一个本许可证的副本,并且重复的恒常章节可以取代单一副本。 如果有多个名称相同但内容不同的恒常章节,每个这样的部分独特的标题,通过添加在它结束,括号中,该条原作者或出版者的名称,如果知道的话,或其他唯一的编号。 联合工作许可声明中的恒常章节列表章节标题相同的调整。

组合中,你必须结合各种原始凭证的任何部分题为“历史”,形成了一节题为“历史”;同样结合名为“致谢”的任何部分,任何部分题为“献给”。 You must delete all sections Entitled "Endorsements".

COLLECTIONS OF DOCUMENTS

你可根据本许可证发布的文件及其他文件组成的集合,并在单一副本,包括在收集的各种文件中取代本许可证的个人副本,只要您遵循本许可证的规则在所有其他方面的文件逐字复制。

从这样一个集合,您可以提取一个单一的文件,并单独在本授权下,只要你提取的文件插入这一许可证的副本,以及关于该文件的逐字复制的所有其他方面遵循本许可证。

独立作品的聚集

汇编的文件或与其他单独的和独立的文件或作品,或在储存或分发介质的体积及其衍生物,被称为“聚合”,如果不使用著作权由汇编限制的合法权利编译的用户超出了个人作品允许。 当文件被包含在聚合,本授权不适用于聚集在于其本身并非文件的衍生作品的其他作品。

如果在第3封面文字要求是适用于这些文档的副本,然后文档是否是整个聚集的不到一半文档的封面文本可能被放置在封面支架总额内的文档,或在如果文件以电子形式,电子占地面积相当于。 否则它们必须出现印刷封皮整个聚集。

翻译

翻译被认为是一种修改,所以你可能第4条的条款下分发的文件的翻译。 用翻译更换恒常章节需要从他们的版权持有人的特别许可,但你可能包括部分或所有恒常章节的翻译,除了这些恒常章节的原始版本。 您可能包括本许可证的翻译,文档中的所有许可声明,并提供您还包括本许可证,这些声明与放弃的原始版本的英文原版任何免责声明。 In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

如果在文档的部分题为“致谢”,“贡献”,或“历史”的要求(第4),以保持其标题(第1),将通常需要改变的实际称号。

终止

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. 然而,你收到的副本,或者权利,根据本许可的当事人不会因此终止,只要各方仍完全遵守其牌照。

本许可证的未来修订

自由软件基金会可能会发布新版本的GNU自由文档许可证不时修订。 这种新的版本将是精神,以目前的版本类似,但在细节上可能有所不同,以解决新的问题或疑虑。 See http://www.gnu.org/copyleft/.

许可证的每个版本被赋予了不同的版本号。 如果文档指定一个特定的编号“许可证”或更新的版本版本适用于它,你有选择的或者指定的版本或任何更新的版本已发布的条款和条件(不作为草案)由自由软件基金会。 If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

附录:如何为您的文件使用此许可证

使用本许可证,你有书面文件,包括文件中的许可证的副本和标题页后,把下面的版权和许可声明:

Copyright (c) YEAR YOUR NAME. 权限被授予复制,分发和/或修改本文件1.2版本或任何由自由软件基金会出版的更高版本的GNU自由文档许可证的条款下,不附带恒常章节,没有封面文字,并没有回封面文字。 许可证的副本包含在题为“GNU自由文档许可证”一节。

如果你有恒常章节,封面文字和封底文字,取代“...的文本。” 与此线:

with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

如果您有没有封面文字,或一些其他三个组合恒常章节,合并这两个备选方案,以适应形势。

如果您的文件包含程序代码的非平凡的例子,我们建议并行释放这些例子中,根据您选择的自由软件许可证,如GNU通用公共许可证,允许其使用自由软件。

后记

This work is licensed under the GNU Free Documentation License. It was originally written in LaTeX, then ported to DocBook. It is available in transparent copy in the DocBook/XML format. A build system and special instructions on processing are part of the transparent copy package, though building from the source is system dependent. The source can be built into either HTML or PDF format, and extension to other formats should be possible and is encouraged.

The original version of this document was written by Robert L. Read without renumeration and dedicated to the programmers of Hire.com.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值