当前位置: 首页 > news >正文

[人月神话_5] 兵器库 | 整体部分 | 祸起萧墙

目录

兵器库(Sharp Tools)

整体部分(The Whole and the Parts)

最佳实践

搭建充分的测试平台

测试辅助的形式

控制变更

关键步骤

一次添加一个构件

好处

注意事项

阶段(量子)化、定期变更

目的

实践建议

祸起萧墙(Hatching a Catastrophe


一次添加一个构件

兵器库(Sharp Tools)

翻译版本将此章标题译为“干将莫邪”

但是综合文义和编程实践将其调整为“兵器库”,更切题合理。

打造通用兵器库

软件项目的工具管理现状常常类似于一家五金店,每个开发者都拥有一套自己精心挑选的工具集,这成为了他们个人技能的象征。

  • 然而,这种方法对软件项目的成功构成了障碍。
  • 首先,个性化工具阻碍了团队内部的沟通与协作,因为每个成员使用的工具不同,难以实现标准化的工作流程。
  • 其次,随着技术的发展,这些个性化工具很快就会过时,导致频繁的工具更换和学习成本上升。
  • 因此,开发和维护一套通用的编程工具对于提升团队效率至关重要。

为了更好地管理工具,建议每个软件开发团队配备一名工具管理员

  • 这名管理员负责管理和指导团队成员使用通用工具,同时也能根据项目需求定制特定的专业工具。
  • 项目经理应当制定相应的策略,为通用工具的开发分配资源,同时也要认识到专业工具的重要性,不应对此类工具的投资过于吝啬。


辅助机器与数据服务

在软件开发项目中,辅助机器和数据服务扮演着至关重要的角色,尤其是在目标机器是新产品的情况下。这里有几个关键点:

  • 仿真装置:对于新开发的目标机器,仿真装置提供了一个早期的调试平台。
    • 即使新机器已经生产出来,仿真装置依然可以作为一个稳定的调试环境。
    • 这是因为新机器在初期可能不稳定,硬件故障往往是间歇性的,这使得基于新硬件的调试变得更加困难。
    • 相比之下,仿真装置提供了更稳定的工作环境,有助于提高开发效率。
  • 编译器和汇编平台:编译器和汇编软件需要运行在一个可靠的平台上,以便为目标机器生成目标代码。
    • 在目标机器上进行全面测试之前,辅助机器上的编译器可以完成大量的代码调试和测试工作,确保代码质量。
  • 程序库和管理:一个成功的辅助机器应用是程序库的维护。
    • 通过建立一个中央程序库,可以有效管理不同开发阶段的代码版本。
    • 开发人员在自己的开发库中自由工作,而集成经理则控制进入系统集成库的代码版本。
    • 这种做法不仅提高了代码的质量,还促进了版本控制和团队协作。
  • 编程工具:除了基本的编程工具外,还需要一系列实用程序来支持日常开发活动
    • 比如磁带走带、磁盘拷贝、文件打印等。
    • 这些工具的完善和维护对于提高开发效率至关重要。
  • 文档系统:高效的文本编辑系统对于编写清晰、易于理解的文档极为重要。
    • 良好的文档不仅是项目知识的载体,还能极大地提高团队成员之间的沟通效率,减少误解和错误。
  • 性能仿真装置
    • 开发一个性能仿真装置可以帮助团队提前了解软件在目标机器上的表现,这对于优化性能和解决潜在的问题非常有帮助。
    • 通过早期的性能测试,团队可以及时调整设计,确保最终产品的质量和稳定性。

合理配置和利用辅助机器与数据服务,能够显著提升软件开发项目的效率和成功率。

这不仅需要先进的技术和工具支持,更需要团队之间良好的沟通与协作。


高级语言和交互式编程

在过去的十年里,虽然高级语言和交互式编程这两种系统编程工具并未得到广泛的应用,但它们的重要性日益凸显。以下是这两项技术的关键点及其对现代软件开发的影响:

  • 高级语言
    • 功能限制:尽管有人认为高级语言无法完成复杂的任务,但实际上,只要投入足够的时间和精力,几乎所有的任务都可以用高级语言实现。
    • 代码体积:新的优化编译器已经解决了代码体积过大的问题,并且还在不断改进。
    • 运行速度:优化编译器生成的代码通常比手动编写的代码更高效。即使在某些情况下需要手动优化,也只需要对一小部分代码进行调整。
    • 生产率和调试速度使用高级语言可以显著提高开发效率。它不仅减少了代码中的错误数量,还简化了错误查找的过程。
      • 高级语言通过避免低级语言中常见的语法和语义错误,如不当使用寄存器等,提高了代码的可靠性。
    • 传统反对意见
    • 推荐语言:PL/I 是目前较为合适的选择,它提供了丰富的功能集,与操作系统环境兼容,并且有多种编译器可供选择。
  • 交互式编程
    • 调试效率:交互式编程通过减少调试周转时间,显著提高了开发效率。
      • 传统的批处理系统在调试过程中需要等待长时间的编译和运行,而交互式系统允许开发人员即时查看和修改代码。
    • 成功案例
      • MIT 的 Multics 项目是交互式系统开发的一个经典案例,展示了多用户共享、保护机制和库管理等方面的强大功能。
    • 实际效果:Bell 实验室的 John Harr 提供的数据表明,使用交互式编程的系统软件开发生产率至少是传统方式的两倍。

批处理和交互式编程生产率的对比

高级语言和交互式编程是现代软件开发不可或缺的工具。它们不仅提高了开发效率,还增强了代码的可靠性和可维护性。尽管这些技术在早期遇到了一些阻力,但随着技术的进步和实践的验证,它们的优势已经得到了广泛认可。未来的软件开发将越来越依赖这些工具,以应对日益复杂的系统需求。


整体部分(The Whole and the Parts)

系统整体与其组成部分之间的关系,特别是如何有效地管理和集成这些部分,以构建一个成功的软件系统。

  • 系统不是简单部分的总和一个复杂的软件系统不仅仅是其各个部分的简单叠加,系统的行为和性能受到各个部分之间交互的影响,这些交互往往是非线性的,难以预测的。
  • 在设计和开发过程中,应该从整体的角度出发,考虑系统的全局优化,而不是仅仅已关注单个部分的最优解。(所以 不要“贪心”😗)

剔除 bug 的设计

  • 详尽的体系结构设计是预防bug的关键。
  • 这包括细致的功能定义、详细的规格说明和规范化的功能描述。
  • Bell实验室的安全监控系统项目负责人V.A.Vyssotsky指出,许多失败案例的根本原因在于产品定义不够精确。
  • 因此,确保产品定义的准确性和完整性,是减少bug数量的第一步。

测试规格说明

测试规格说明的实践也至关重要。

  • 在编写任何代码之前,规格说明应当由专门的测试小组进行审查,以确保其完整性和明确性。
  • 这是因为开发人员可能会倾向于自己解决疑惑,而非主动寻求澄清,这可能导致误解和错误的发生。

自顶向下的设计

自顶向下的设计方法为减少bug提供了一种有效的途径。

  • 这种方法首先从高层次的任务定义和解决方案入手,然后逐步细化到更具体的层面。

(还是 我们 先干再说的思想)

  • 每个细化步骤都可以独立进行,这不仅有助于识别和纠正早期的设计缺陷,还能确保每个阶段的测试都能集中在适当的问题上。

通过这种方式,自顶向下的设计帮助保持了设计的清晰度和模块的独立性,从而降低了系统级别的bug风险。


结构化编程

  • 结构化编程技术也是防范bug的重要手段。
  • Dijkstra等人提出的结构化编程理念主张使用循环和条件判断等控制结构来替代无限制的goto跳转,以此来构建逻辑清晰、易于理解和维护的程序。
  • 虽然这一方法在实践中可能需要一些灵活的应用,比如合理使用多路分支和异常处理等附加控制结构,但其核心思想——将系统的结构视为控制结构来考虑——无疑是软件开发领域的一大进步。

构件单元调试

  • 程序调试的历史演变充满了反复,但其核心目标始终未变——提高效率与准确性。

本机调试

  • 早期调试受限于简陋的输入输出设备,如纸带和磁带,导致调试过程繁琐且耗时。
  • 为此,程序员们精心规划调试流程,包括设定断点、检查内存状态及制定应对策略,这一阶段的调试工作几乎占据项目开发的一半时间。
  • (再次 强调了 检查的重要性)


内存转储

  • 随着技术进步,内存转储成为主流,尽管这种方式在减少计算机使用时间上表现出色,但增加了人工分析的复杂度。内存规模的增长促使快照技术的诞生,它允许选择性地保存程序状态,大大简化了调试流程。

交互式调试

  • 进入交互式调试时代后,得益于多任务操作系统和高级语言的支持,程序员能够实时调试代码,同时保持机器的高利用率。
  • 然而,研究指出,首次交互往往比后续交互更能推动问题解决,这表明预先规划的重要性并未因技术进步而减弱。
  • 实际上,有效的调试实践建议,每两小时的终端调试应配以相同时间的桌面工作,包括整理日志、分析异常和准备下一阶段的测试计划。这一流程确保了调试工作的连续性和效率。

系统集成调试

  • 系统集成调试是软件开发过程中一个关键且复杂的环节
  • 它不仅考验开发者的技能,还需要一套完备的系统化方法来确保调试过程的有效性和效率。
  • 本文将探讨几种有效的系统集成调试方法,帮助开发者克服常见的挑战。

使用经过调试的构件单元

常见误区

  • “合在一起尝试”:这种做法看似能提早暴露系统层面的问题,但实际上会使调试变得更加困难,因为多个bug同时出现,使得问题的定位和解决变得复杂。
  • 相互测试:虽然这种方法可以减少构建测试环境的时间,但可能会引入额外的问题,尤其是当被测试的组件本身就有缺陷时。
最佳实践
  • 确保构件质量:在集成之前,每个构件单元都应经过严格的测试,以确保其功能正确无误,这样可以显著减少系统级别的bug数量,提高整体调试效率。
  • 文档化bug:对于那些不可避免的、已知的bug,应该详细记录下来。
  • 这样,在进行系统测试时,可以优先已关注新出现的问题,而不是重复处理已知的问题。

搭建充分的测试平台
测试辅助的形式
  • 构件:为了模拟尚未完成的系统部分,可以使用伪构件来提供必要的接口和测试场景,确保其余部分的测试不会受到影响。
  • 微缩文件:通过创建含有典型记录的小文件,可以有效地验证文件格式的正确性。
  • 伪文件:在特定条件下,使用伪文件代替真实文件进行测试,有助于简化测试过程。
  • 辅助程序:开发专门的辅助工具,例如数据生成器和特殊打印输出程序,以满足特定的测试需求。

控制变更

关键步骤
  • 专人管理:指派专人负责构件单元的变更管理和版本控制,确保变更过程的有序进行。
  • 系统受控拷贝
    • 最终锁定版本:这是用于构件单元测试的稳定版本。
    • 测试版本:专为修复缺陷而设计的版本。
    • 安全版本:其他开发人员可在此基础上独立开展工作。
  • 变更记录:所有变更,无论是快速补丁还是正式修改,都应详细记录,确保每个修改都经过了充分的测试并文档化。
一次添加一个构件
好处
  • 逐步排查:每次只添加一个构件,有助于逐步识别和解决系统级别的bug。
  • 回归测试:在引入新构件后,重新执行之前的测试用例,确保系统的稳定性和一致性。
注意事项
  • 避免诱惑:不要因为急于求成或过于乐观而跳过此步骤。
  • 系统测试的核心在于假设系统中可能存在大量错误,并通过系统化的方法逐一排除。
阶段(量子)化、定期变更
目的
  • 稳定周期:通过定期发布新的系统版本,确保每位用户都能获得一个稳定的生产环境。
  • 减少混乱避免频繁变更带来的混乱,保持开发流程的有序性。
实践建议
  • 大而稀疏的阶段:研究表明,相较于小而频繁的迭代,大而稀疏的开发阶段更有利于维持系统的长期稳定。
  • 紫色线束技术:在每个版本发布前,先应用快速补丁解决问题;随后,在下一个主要版本中,将所有经过测试和文档化的补丁整合进去。

祸起萧墙(Hatching a Catastrophe

增加更多的人手到一个已经延期的项目中往往不会加快项目的进度,反而可能使情况变得更糟。

  • 项目进度的细微延迟往往难以察觉,但它们却能悄无声息地累积起来,最终对整个项目的完成时间造成重大影响。
  • 昨天,一位关键成员因突发疾病未能出席重要会议;今天,一场突如其来的雷暴导致公司供电系统受损,所有设备因此陷入瘫痪;而明天,由于供应商那边出现了预料之外的延误,原定用于磁盘例程测试的新硬盘无法按时到位。
  • 此外,还有不可预见的天气变化、紧急任务的插入、个人突发事件、与客户的紧急沟通需求以及管理层的临时审查——这些因素无一不在悄悄消耗着宝贵的时间资源。
  • 尽管每次看起来只是半天或一天的小耽误,但日积月累之下,整个项目的推进速度开始逐渐放缓,直到落后于最初的计划安排。

(莫名呼应,上一篇中所提到的“唯一不变的 就是变化”

里程碑还是沉重的负担?

精心设计的里程碑实际上为团队提供了支持,使他们能够向项目经理提出合理请求;而模糊的里程碑则成为负担。

  • 在计划中,每个关键节点被称为“里程碑”,并配有明确的时间点。
  • 选择这些时间点需要基于技术评估,并且通常依赖于过往的经验。
  • 里程碑的选择原则是:它们必须是具体、特定且可度量的事件,能够被清晰地定义。
  • (自己平时做事时,也可以借鉴“里程碑法则”)

例如,避免使用模糊表述如“编码完成90%”或“调试接近尾声”,因为这样的描述缺乏精确性。相反,应采用诸如

  • “架构师与实现人员已签署规格说明书”
  • “100%源代码开发完毕并已录入磁盘库”
  • “所有测试用例均通过验证”等具体指标作为里程碑。

这些明确的里程碑有助于区分那些界限不甚分明的阶段,比如规划、编程和调试。

  • 清晰界定的里程碑不仅便于上级审核,更重要的是它们减少了团队成员自我欺骗的可能性。
  • 当里程碑的具体要求无法被轻易篡改时,人们更倾向于诚实报告进展状况。
  • 反之,如果里程碑含糊不清,则容易导致报告失真,因为没有人愿意主动传递坏消息。

针对大型项目的估计工作,政府承包商的研究揭示了以下几点:

  • 在活动开始前就进行初步估计,并定期(每两周)更新调整,这样即便最终情况不佳,也能保持一定的预见性。
  • 活动初期往往对所需时间过于乐观,但随着活动推进,这种乐观情绪会逐渐减少。
  • 相反,低估的情况在整个过程中变化不大,直到接近截止日期前三周左右才显现出来。

“其他的部分反正会落后”

当项目进度落后一天时,我们可能会想:“这没什么大不了的,反正其他部分也落后了。”

  • 然而,这种态度忽视了一个重要事实:每一天的滞后都可能成为潜在风险的累积。
  • 在棒球运动中,队长明白进取心对于优秀队员和团队的重要性。同样,在软件开发中,进取心也是不可或缺的。它促使团队成员追求更快、更高效的工作表现,并为应对不可预见的问题提供缓冲空间。

但是,过于乐观地看待时间安排也会带来负面影响。

  • 如果团队因为预计可以轻松赶上进度而放慢脚步,那么小问题可能会演变成大麻烦。因此,我们必须对每天的滞后保持警惕,因为它们可能是导致重大延误的前兆。

并非所有的滞后都会造成灾难性后果,但准确判断哪些偏差是关键的至关重要。

这时,PERT(Program Evaluation and Review Technique)或关键路径方法就显得尤为重要。

这些工具可以帮助识别哪些任务处于关键路径上,以及它们的延迟将如何影响整个项目的完成日期。

  • 此外,它们还能指出一个非关键任务可以在不影响最终期限的情况下允许的最大滞后时间。
  • 尽管PERT技术要求对每个事件进行三次估计,以考虑不同可能性下的完成时间,但这额外的工作量是为了获得更加精确的计划。
  • 实际上,准备PERT图的过程——包括展开网络结构、确定任务依赖关系、评估各个任务链——本身就是一项极具价值的工作。
  • 第一份PERT图可能会让人感到有些畏惧,但通过不断努力和完善,我们可以制作出更加实用的图表。

随着项目的推进,PERT图能够帮助我们回答诸如“其他部分反正会落后”的借口。

  • 它不仅显示了为了使某项工作远离关键路径需要提前多少时间,还提供了补偿其他部分失去时间的方法。
  • 这样,我们就能够更好地管理项目进度,避免由于个别任务的滞后而导致整体项目的延误。

地毯的下面

当一线经理发现团队的工作偏离了原定计划时,他通常不会立即向上级报告这一情况。

  • 经理们往往倾向于自己解决这些问题,避免给高层带来额外的烦恼。
  • 从某个角度来看,这似乎是一个合理的做法,因为处理这类问题是他们的职责所在。
  • 然而,这种做法却隐藏了一个潜在的问题:所有的问题都被掩盖在地毯之下,而没有得到及时的曝光。

实际上,老板需要两类信息:一类是关于需要采取行动的具体问题;另一类是用来分析项目状态的数据。

为了有效地管理项目,老板必须对所有开发队伍的情况有全面的了解。

  • 但要获取这些真实的状态信息并不容易,因为一线经理和老板之间存在利益冲突。
  • 经理可能担心如果汇报了问题,会导致上级介入,从而削弱自己的权威或打乱现有的安排。
  • 因此,只要经理认为自己能够独立解决问题,他就不太愿意向老板透露问题的存在。

为了解决这个问题,有两种方法可以揭开地毯下的污垢:

  • 减少角色冲突,鼓励透明度:
    • 老板需要明确区分需要立即采取行动的信息和仅用于分析的状态信息。
    • 他们应该控制住自己不对每个问题都做出反应,尤其是在审查状态报告时不应直接干预。
    • 通过这种方式,项目经理会逐渐感到放心,开始提供更加真实的评估结果。
    • 此外,将会议明确标记为状态检查或问题-行动会议,并且保持相应的行为规范,可以帮助建立一个更健康的沟通环境。
  • 强制性的状态评审机制:
    • 即使是在合作良好的情况下,也需要有一个可靠的系统来揭示项目的实际状态。
    • PERT图和频繁设立里程碑是这种评审的基础。
    • 对于大型项目,可能需要每周对部分工作进行评审,大约每个月进行一次整体评审。
    • 关键文档如里程碑进度和实际完成情况的报告,对于识别潜在问题至关重要。
    • 例如,在一次会议上,报告指出手册批准时间与产品测试开始时间存在冲突,这就需要产品构件经理准备解释延迟原因、预计结束时间以及所需的任何支持措施。

通过这两种方法的结合使用,可以确保管理层及时获得准确的信息,从而促进更有效的决策制定和项目管理。

这样的透明度不仅有助于解决问题,还能增强团队之间的信任和协作。

相关文章:

  • Nginx配置与命令
  • ubuntu中已经存在python3.12.3, 如何安装python3.10.8且命令python3版本切换为python3.10.8
  • 得力标签打印机系统集成方案的技术应用与场景实践
  • 02 Nginx虚拟主机
  • 如何畅通需求收集渠道,获取用户反馈?
  • 软考IPSEC案例分析
  • Linux进程信号(三)之信号产生2
  • 短剧小程序系统开发源码上架,短剧项目市场分析
  • 考研数学积分学
  • 渗透测试核心技术:内网渗透与横向移动
  • 类魔方 :多变组合,灵活复用
  • Estimation(估算):业务分析师的“不确定性对抗术”
  • Python黑魔法与底层原理揭秘:突破语言边界的深度探索
  • 【VMware】开启「共享文件夹」
  • 软件架构之-论软件系统架构评估以及应用
  • 批量下载AlphaFold结构
  • 2.1.2
  • LORA 微调 - LoRA 介绍与 LoRA 微调指南
  • vue3 elementplus tabs切换实现
  • 程序代码篇---python获取http界面上按钮或者数据输入
  • 河南通报部分未检疫生猪流入:立案查处,涉案猪肉被封存
  • 瑞幸首度牵手成都国际非遗节,用一杯饮品将非遗之美推向全国
  • 无人机企业从科技园区搬到乡村后,村子里变得不一样了
  • 从《缶翁的世界》看吴昌硕等湖州籍书画家对海派的影响
  • 九江银行落地首单畜牧业转型金融业务,助推传统农业绿色智能
  • 民间打拐志愿者上官正义遭人身安全威胁,杭州公安:已立案