《人月神话》(The Mythical Man-Month)1 看清问题的本质:如果我们想解决问题,就必须试图先去理解它...

news2025/2/27 8:16:31

809174e2b44ca6cd1bbb5152c3d458ab.png

第一章 焦油坑(The Tar Pit)

史前史中,没有比巨兽在焦油坑中垂死挣扎的场面更令人震撼的了。上帝见证着恐龙、猛犸象、剑齿虎在焦油中挣扎。它们挣扎得越是猛烈,焦油纠缠得越紧,没有任何猛兽足够强壮或具有足够的技巧,能够挣脱束缚,它们最后都沉到了坑底。

No scene from prehistory is quite so vivid as that of the mortal struggles of great beasts in the tar pits. In the mind's eye one sees dinosaurs, mammoths, and sabertoothed tigers struggling against the grip of the tar. The fiercer (猛烈)the struggle, the more entangling the tar, and no beast is so strong or so skillful but that he ultimately sinks.

过去几十年的大型系统开发就犹如这样一个焦油坑,很多大型和强壮的动物在其中剧烈地挣扎。他们中大多数开发出了可运行的系统——不过,其中只有非常少数的项目满足了目标、时间进度和预算的要求。各种团队,大型的和小型的,庞杂的和精干的(wiry),一个接一个淹没在了焦油坑中。表面上看起来好像没有任何一个单独的问题会导致困难,每个都能被解决,但是当它们相互纠缠和累积在一起的时候,团队的行动就会变得越来越慢。对问题的麻烦程度,每个人似乎都会感到惊讶,并且很难看清问题的本质。不过,如果我们想解决问题,就必须试图先去理解它。

Large-system programming has over the past decade been such a tar pit, and many great and powerful beasts have thrashed (挣扎)violently in it. Most have emerged with running systems—few have met goals, schedules, and budgets. Large and small, massive or wiry, team after team has become entangled in the tar. No one thing seems to cause the difficulty—any particular paw can be pulled away. But the accumulation of simultaneous and interacting factors brings slower and slower motion. Everyone seems to have been surprised by the stickiness of the problem, and it is hard to discern the nature of it. But we must try to understand it if we are to solve it.

因此,首先让我们来认识一下软件开发这个职业,以及充满在这个职业中的乐趣和苦恼吧。

Therefore let us begin by identifying the craft of system programming and the joys and woes inherent in it.

编程系统产品的演进(The Programming Systems Product)

7b132fbccb23b45cd6f6df6ecc4574b6.png

程序(Program)。它本身是完整的,可以由作者在所开发的系统平台上运行。

09e1cc85612f1a3db52a4a549446a24a.png

水平边界以下,程序变成编程产品(Programming Product),测试、修复和扩展的程序。它可以运行在多种操作系统平台上,供多套数据使用。要成为通用的编程产品,程序必须按照普遍认可的风格来编写,特别是输入的范围和形式必须扩展,以适用于所有可以合理使用的基本算法。接着,对程序进行彻底测试,确保它的稳定性和可靠性,使其值得信赖。这就意味着必须准备、运行和记录详尽的测试用例库,用来检查输入的边界和范围。此外,要将程序提升为程序产品,还需要有完备的文档,每个人都可以加以使用、修复和扩展。经验数据表明,相同功能的编程产品的成本,至少是已经过测试的程序的三倍。

回到图中,垂直边界的右边,程序变成编程系统(Programming System)中的一个构件单元。它是在功能上能相互协作的程序集合,具有规范的格式,可以进行交互,并可以用来组装和搭建整个系统。要成为系统构件,程序必须按照一定的要求编制,使输入和输出在语法和语义上与精确定义的接口一致。同时程序还要符合预先定义的资源限制——内存空间、输入输出设备、计算机时间。最后,程序必须同其它系统构件单元一道,以任何能想象到的组合进行测试。由于测试用例会随着组合不断增加,所以测试的范围非常广。因为一些意想不到的交互会产生许多不易察觉的 bug,测试工作将会非常耗时,因此相同功能的编程系统构件的成本至少是独立程序的三倍。如果系统有大量的组成单元,成本还会更高。

图 1.1 的右下部分代表编程系统产品(Programming Systems Product)。情况不同的是,它的成本高达九倍。然而,只有它才是真正有用的产品,是大多数系统开发的目标。

编程的乐趣(The Joys of the Craft)

编程为什么有趣?作为回报,它的从业者(practitioner)期望得到什么样的快乐?

Why is programming fun? What delights may its practitioner expect as his reward?

首先是一种创建事物的纯粹快乐。如同小孩在玩泥巴时感到愉快一样,成年人喜欢创建事物,特别是自己进行设计。我想这种快乐是上帝创造世界的折射,一种呈现在每片独特、崭新的树叶和雪花上的喜悦 。

First is the sheer joy of making things. As the child delights in his mud pie, so the adult enjoys building things, especially things of his own design. I think this delight must be an image of God's delight in making things, a delight shown in the distinctness and newness of each leaf and each snowflake.

其次,快乐来自于开发对其他人有用的东西。内心深处,我们期望其他人使用我们的劳动成果,并能对他们有所帮助。从这个方面,这同小孩用粘土为“爸爸办公室”捏制铅笔盒没有本质的区别。

Second is the pleasure of making things that are useful to other people. Deep within, we want others to use our work and to find it helpful. In this respect the programming system is not essentially different from the child's first clay pencil holder "for Daddy's office."

第三是整个过程体现出魔术般的力量——将相互啮合的零部件组装在一起,看到它们精妙地运行,得到预先所希望的结果。比起弹珠游戏或点唱机所具有的迷人魅力,程序化的计算机毫不逊色。

Third is the fascination of fashioning complex puzzle-like objects of interlocking moving parts and watching them work in subtle cycles, playing out the consequences of principles built in from the beginning. The programmed computer has all the fascination of the pinball machine or the jukebox mechanism, carried to the ultimate.

第四是学习的乐趣,来自于这项工作的非重复特性。人们所面临的问题,在某个或其它方面总有些不同。因而解决问题的人可以从中学习新的事物:有时是实践上的,有时是理论上的,或者兼而有之。

Fourth is the joy of always learning, which springs from the nonrepeating nature of the task. In one way or another the problem is ever new, and its solver learns something: sometimes practical, sometimes theoretical, and sometimes both.

最后,乐趣还来自于工作在如此易于驾驭的介质(tractable medium)上。程序员,就像诗人一样,几乎仅仅工作在单纯的思考中。程序员凭空地运用自己的想象,来建造自己的“城堡”(castle)。很少有这样的介质——创造的方式如此得灵活,如此得易于精炼和重建,如此得容易实现概念上的设想。(不过我们将会看到,容易驾驭的特性也有它自己的问题。)

Finally, there is the delight of working in such a tractable medium. The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures. (As we shall see later, this very tractability has its own problems.)

然而程序毕竟同诗歌不同,它是实实在在的东西;可以移动和运行,能独立产生可见的输出;能打印结果,绘制图形,发出声音,移动支架。神话和传说中的魔术在我们的时代已变成了现实。在键盘上键入正确的咒语,屏幕会活动、变幻,显示出前所未有的或是已经存在的事物。

Yet the program construct, unlike the poet's words, is real in the sense that it moves and works, producing visible outputs separate from the construct itself. It prints results, draws pictures, produces sounds, moves arms. The magic of myth and legend has come true in our time. One types the correct incantation on a keyboard, and a display screen comes to life, showing things that never were nor could be.

编程非常有趣,在于它不仅满足了我们内心深处进行创造的渴望,而且还愉悦了每个人内在的情感。

Programming then is fun because it gratifies creative longings built deep within us and delights sensibilities we have in common with all men.

职业的苦恼(The Woes of the Craft)

然而这个过程并不全都是喜悦。我们只有事先了解一些编程固有的烦恼,这样,当它们真的出现时,才能更加坦然地面对。

Not all is delight, however, and knowing the inherent woes makes it easier to bear them when they appear.

首先,必须追求完美。因为计算机也是以这样的方式来变戏法:如果咒语中的一个字符、一个停顿,没有与正确的形式一致,魔术就不会出现。(现实中,很少的人类活动要求完美,所以人类对它本来就不习惯。)实际上,我认为学习编程的最困难部分,是将做事的方式往追求完美的方向调整。

First, one must perform perfectly. The computer resembles the magic of legend in this respect, too. If one character, one pause, of the incantation is not strictly in proper form, the magic doesn't work. Human beings are not accustomed to being perfect, and few areas of human activity demand it. Adjusting to the requirement for perfection is, I think, the most difficult part of learning to program.

其次,是由他人来设定目标,供给资源,提供信息。编程人员很少能控制工作环境和工作目标。用管理的术语来说,个人的权威和他所承担的责任是不相配的。不过,似乎在所有的领域中,对要完成的工作,很少能提供与责任相一致的正式权威。而现实情况中,实际(相对于正式)的权威来自于每次任务的完成。

Next, other people set one's objectives, provide one's resources, and furnish one's information. One rarely controls the circumstances of his work, or even its goal. In management terms, one's authority is not sufficient for his responsibility. It seems that in all fields, however, the jobs where things get done never have formal authority commensurate with responsibility. In practice, actual (as opposed to formal) authority is acquired from the very momentum of accomplishment.

对于系统编程人员而言,对其他人的依赖是一件非常痛苦的事情。他依靠其他人的程序,而往往这些程序设计得并不合理,实现拙劣,发布不完整(没有源代码或测试用例),或者文档记录得很糟。所以,系统编程人员不得不花费时间去研究和修改,而它们在理想情况下本应该是可靠完整的。

The dependence upon others has a particular case that is especially painful for the system programmer. He depends upon other people's programs. These are often maldesigned, poorly implemented, incompletely delivered (no source code or test cases), and poorly documented. So he must spend hours studying and fixing things that in an ideal world would be complete, available, and usable.

下一个烦恼——概念性设计是有趣的,但寻找琐碎的 bug 却只是一项重复性的活动。伴随着创造性活动的,往往是枯燥沉闷的时间和艰苦的劳动。程序编制工作也不例外。

另外,人们发现调试和查错往往是线性收敛的,或者更糟糕的是,具有二次方的复杂度。结果,测试一拖再拖,寻找最后一个错误比第一个错误将花费更多的时间。

The next woe is that designing grand concepts is fun; finding nitty little bugs is just work. With any creative activity come dreary hours of tedious, painstaking labor, and programming is no exception.

Next, one finds that debugging has a linear convergence, or worse, where one somehow expects a quadratic sort of approach to the end. So testing drags on and on, the last difficult bugs taking more time to find than the first.

最后一个苦恼,有时也是一种无奈——当投入了大量辛苦的劳动,产品在即将完成或者终于完成的时候,却已显得陈旧过时。可能是同事和竞争对手已在追逐新的、更好的构思;也许替代方案不仅仅是在构思,而且已经在安排了。

现实情况比上面所说的通常要好一些。当产品开发完成时,更优秀的新产品通常还不能投入使用,而仅仅是为大家谈论而已。另外,它同样需要数月的开发时间。事实上,只有实际需要时,才会用到最新的设想,因为所实现的系统已经能满足要求,体现了回报。

The last woe, and sometimes the last straw, is that the product over which one has labored so long appears to be obsolete upon (or before) completion. Already colleagues and competitors are in hot pursuit of new and better ideas. Already the displacement of one's thought-child is not only conceived, but scheduled.

This always seems worse than it really is. The new and better product is generally not available when one completes his own; it is only talked about. It, too, will require months of development. The real tiger is never a match for the paper one, unless actual use is wanted. Then the virtues of reality have a satisfaction all their own.

诚然,产品开发所基于的技术在不断地进步。一旦设计被冻结,在概念上就已经开始陈旧了。不过,实际产品需要一步一步按阶段实现。实现落后与否的判断应根据其它已有的系统,而不是未实现的概念。因此,我们所面临的挑战和任务是在现有的时间和有效的资源范围内,寻找解决实际问题的切实可行方案。

Of course the technological base on which one builds is always advancing. As soon as one freezes a design, it becomes obsolete in terms of its concepts. But implementation of real products demands phasing and quantizing. The obsolescence of an implementation must be measured against other existing implementations, not against unrealized concepts. The challenge and the mission are to find real solutions to real problems on actual schedules with available resources.

这,就是编程。一个许多人痛苦挣扎的焦油坑以及一种乐趣和苦恼共存的创造性活动。对于许多人而言,其中的乐趣远大于苦恼。而本书的剩余部分将试图搭建一些桥梁,为通过这样的焦油坑提供一些指导。

This then is programming, both a tar pit in which many efforts have floundered and a creative activity with joys and woes all its own. For many, the joys far outweigh the woes, and for them the remainder of this book will attempt to lay some boardwalks across the tar.

5c53267a3282ac919eae237b61ee4319.png

【更多阅读】

  • 在平时的工作中如何体现你的技术深度?

  • Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!

  • 程序员职业生涯系列:关于技术能力的思考与总结

  • 十年技术进阶路:让我明白了三件要事。关于如何做好技术 Team Leader?如何提升管理业务技术水平?(10000字长文)

  • 当你工作几年就会明白,以下几个任何一个都可以超过90%程序员

  • 编程语言:类型系统的本质

  • 软件架构设计的核心:抽象与模型、“战略编程”

  • 【图文详解】深入理解 Hbase 架构  Deep Into HBase Architecture

  • HBase 架构详解及读写流程原理剖析

  • HDFS 底层交互原理,看这篇就够了!

  • MySQL 体系架构简介

  • 一文看懂MySQL的异步复制、全同步复制与半同步复制

  • 【史上最全】MySQL各种锁详解:一文搞懂MySQL的各种锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA注释配置程序员信息(带完整截图步骤,超级详细)

1.配置类注释的程序员信息 效果图 配置截图 模板 (可根据需要进行位置调整及个数删除) /***BelongsProject: ${PROJECT_NAME}*BelongsPackage: ${PACKAGE_NAME}*ClassName ${NAME}*Author: XUXIAN*CreateTime: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINU…

这可能是最权威、最全面的Go语言编码风格规范了!

每种编程语言除了固定的语法之外,都会有属于自己的地道的(idiomatic)写法。其实,自然语言也不例外,你想,你用心想想是不是这样。语言的设计者们希望开发人员都能编写统一风格的地道的代码,这样不仅代码可读性好&#x…

细分图中的可到达节点 : 常规最短路运用题

题目描述 Tag : 「最短路」、「单源最短路」、「Dijkstra」、「SPFA」 给你一个无向图(原始图),图中有 n 个节点,编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链,每条边之间的新节点数各不相同。 图用…

[前端框架]-VUE(上篇)

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面&#xff0…

链表经典算法题目

1.回文链表 编写一个函数,检查输入的链表是否是回文的。 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 笔试的写法 重点是快速code,不考虑空间复杂度…

蒙特卡洛法(Monte Carlo)电动汽车负荷预测matlab程序设计

电动汽车充电负荷的时间分布预测 规模化电动汽车充电负荷在未来某一天随时间特性的分布规律是研究电动汽车发展对配 电网影响以及充电站选址定容问题的前提与基础。电动汽车充电负荷的分布情况与车主的行 为特征有关,不同类型的电动汽车车主出行规律以及充电习惯不…

<Linux系统复习>信号

一、本章重点 1、什么是信号? 2、查看信号列表 3、信号捕捉 4、信号产生的5种方式 5、介绍CoreDump 6、信号处理的方式 7、如何理解信号产生到处理的过程 8、sigpending、sigprocmask、sigaction函数的使用 9、信号处理的时机 10、SIGCHLD信号 11、可重入函数 01 什…

Codeforces Round 836 (Div. 2) A - C

A:SSeeeeiinngg DDoouubbllee 题意&#xff1a;给定一个字符串&#xff0c;每个字符串的字符可以出现两次&#xff0c;要求通过重新排列构造一个回文串。 思路&#xff1a;直接暴力可以&#xff0c;每个字符头部一个尾部一个。 #include<cstdio> #include <iostream…

不使用实体类的情况下接收SQL查询结果、@Autowired注入为null解决

目录 一、场景 二、环境 三、使用 1、数据库表以及数据准备 2、项目导入必要依赖 3、添加连接数据库配置文件 4、编写测试方法 5、执行结果 四、将SQL单独提取出来 2.1 定义查询接口方法 2.2 测试 2.3 测试结果 五、问题记录&#xff1a; Autowired注入失败/null的…

b、B、KB、Kib、MB、MiB、GB、GiB、TB、TiB的区别

1024这个数字&#xff0c;想必计算机行业从业人员应该不会陌生&#xff0c;甚至10月24日还被当做程序员日&#xff0c;如果你问一个程序员1GB等于多少MB,他大概率会不假思索回答:1024。 没错&#xff0c;对于稍微对计算机或者网络有了解的人&#xff0c;一般都认为1024是数据容…

最短路算法 - dijkstra

最短路算法 - dijkstra1. 算法介绍2. 实战2.1 Reachable Nodes In Subdivided Graph3 参考1. 算法介绍 算法目的&#xff1a;求图中某点 s 到其余各点的最短距离 算法步骤&#xff1a; 初始化距离数组 dis 和优先级队列&#xff0c;其中 dis[i] 表示 s 点到当前 i 点的最短距…

树莓派上搭建SVN服务器

目录 一、服务端安装步骤 1.安装svn 2.创建目录 3.创建版本仓库 4.修改配置&#xff08;authz,passwd,svnserve.conf&#xff09; 5.启动服务 二、tortoisSVN客户端安装 三、结束 一、服务端安装步骤 1.安装svn sudo apt-get install subversion 2.创建目录 sudo m…

品RocketMQ 源码,学习并发编程三大神器

这篇文章&#xff0c;笔者结合 RocketMQ 源码&#xff0c;分享并发编程三大神器的相关知识点。 1 CountDownLatch 实现网络同步请求 CountDownLatch 是一个同步工具类&#xff0c;用来协调多个线程之间的同步&#xff0c;它能够使一个线程在等待另外一些线程完成各自工作之后&…

selenium--获取页面信息和截图

获取页面信息namecurrent_urltitlecurrent_window_handlewindow_handlespage_source简单用法—— 判断页面截图1.get_screenshot_as_png2.get_screenshot_as_file获取页面信息 主要方法如下图&#xff1a; 介绍一下常用的方法&#xff1a; name 获取浏览器名字 current_u…

Packet Tracer 实验 - 排除多区域 OSPFv3 故障

地址分配表 设备 接口 IPv6 全局单播地址 IPv6 本地链路地址 默认网关 ISP GigabitEthernet0/0 2001:DB8:C1:1::1/64 FE80::C1 不适用 ASBR GigabitEthernet0/0 2001:DB8:C1:1::2/64 FE80::7 不适用 Serial0/0/0 2001:DB8:A8EA:F0A::1 FE80::7 不适用 S…

如何通过 kubectl 进入 node shell

概述 假设这样一个场景&#xff1a; 生产环境中&#xff0c;Node 都需要通过堡垒机登录&#xff0c;但是 kubectl 是可以直接在个人电脑上登录的。 这种场景下&#xff0c;我想要通过 kubectl 登录到 K8S 集群里的 Node&#xff0c;可以实现吗&#xff1f; 可以的&#xff…

LinkedList与链表

目录 1.链表 2.链表的模拟实现 3.LinkedList的模拟实现 4.LinkedList的使用 4.1 什么是LinkedList 4.2 LinkedList的使用 5.ArrayList和LinkedList的区别 我的GitHub&#xff1a;Powerveil GitHub 我的Gitee&#xff1a;Powercs12 (powercs12) - Gitee.com 皮卡丘每天学…

机器人十大前沿热点领域(2022-2023)

中国电子学会嵌入式系统与机器人分会主任委员、北京航空航天大学机器人研究所名誉所长、中关村智友研究院院长王田苗博士出席大会闭幕式&#xff0c;并现场发布《机器人十大前沿热点领域(2022-2023)》。归纳出2022-2023年机器人十大前沿技术&#xff1b;并结合我国国情和机器人…

自动化项目倍加福测距仪QSM WCS RS485 与西门子S7 200通信

1、程序流程图 2、WCS位置数据处理流程 第一步&#xff1a;设置S7-200的RS485的通讯波特率19.2kbps&#xff0c;通讯格式&#xff08;8&#xff0c;1&#xff0c;E&#xff09;&#xff1b; 第二步&#xff1a;PLC向WCS发送请求码&#xff1a; A0A1为0&#xff0c;表示读码器地…

现代密码学导论-16-选择明文攻击和CPA安全

目录 PCA不可区分实验 DEFINITION 3.21 PCA安全的加密方案 LR预言机实验 DEFINITION 3.22 多明文PCA安全的加密方案 THEOREM 3.23 定义3.21和定义3.22等价 PCA不可区分实验 通过运行G(1^n)获得密钥k敌手A被给定输入1^n并拥有访问预言机Enck()的权利&#xff0c;敌手A输出一…