准时化生产(Just In Time)是精益生产(Lean Production)和丰田生产系统(Toyota Production System)中的概念,早在 1936 年便被丰田汽车的创始人丰田喜一郎所提出,它强调在合适的时间生产合适数量的满足客户需求的产品。这充分体现了从客户价值出发组织生产运营系统的观点,是一种先进的生产方式,为包括丰田、戴尔等众多世界级企业的成功奠定了基础。
软件开发组织从一开始就在向制造业借鉴和学习,并形成了各种不同的开发方法。敏捷开发与准时化生产中的很多观点和实践是一致的,精益思想作为精益生产背后的指导思想也正在积极地影响着软件开发领域,向其中不断注入创新与活力。
一. 准时化生产与大规模生产
丰田在接到客户订单后 3 天时间内就可以生产出满足客户需求的汽车。戴尔在接到客户订单后 4 天内就可完成组装生产并将电脑送到客户手中。也许有另外一家利用经 销商分销的电脑生产厂家 3 天就可以调货到客户手中,但有多少有价值的生产活动是发生在这 3 天中呢?如果计入该厂家持有的电脑元部件发生贬值的成本、厂家为 其产品降价给经销商存货带来损失而进行的补偿成本(价格保护成本)、退货成本、产品淘汰成本和存货持有成本等(这些成本最终都要客户买单),可想而知客户 为此这次采购最终付出的代价。很多采用大规模生产方式的企业也都声称自己能够“及时”地回应客户,但做法却是保持超量库存。这种策略风险很大,因为这样并非真正回应客户需求,反而会增加库存成本,减弱了企业对市场的敏感性,隐藏了企业内部各种问题并带来库存淘汰的风险。
准时化生产强调零库存,通过减少各个环节的库存,将浪费暴露出来,并通过持续地消除浪费,消除各个工序之间的等待,使得产生价值的活动能够连续流动起来,在尽量短的时间内开始交付产品。
大规模生产方式根据加工的步骤来划分部门并尽量优化部门的生产能力。它通过将半成品大批量地在部门间传递最终完成产品的生产。它与准时化生产是对立的,它们的区别并不在于生产的量,而在于生产的方式。敏捷开发类似准时化生产,而瀑布式开发则像是大规模生产方式,不难看出它们向不同的工业生产思想借鉴和学习的影子。
二. 库存与交付
库存就是指部分完成的工作,广义上讲就是指已经开始但尚未给客户创造价值的全部工作。我们可以认为,尚未被开发过程验证的设计工作是库存;没有被提交的代码是库存;已经“做完了”,但还没有通过验收的开发工作,包括相关联的分析和设计工作都是库存;库存说明了什么叫“完成”,只有将库存交付出去,并得到了肯定的反馈才能叫“完成”。没有后续步骤的反馈,更进一步讲,没有最终用户的反馈就说自己的工作已经完成了只能被认为是一种假象和误导。严格地讲,软件开发中的库存量是一次交付中的全部工作量。 这可能是 1 个月的工作量,也可能是半年,甚至是一年的工作量。减少库存可以有效降低因持有大量未交付工作所带来的各种风险。减少库存还便于强化开发过程中 各个角色的“用户价值意识”,使每项工作都以用户可识别的价值为目标。可以设想一下,如果在一个星期之内就能完成从对某项功能的分析到向用户演示该功能的 过程,那么使各个角色围绕这一用户价值展开工作也就变得很现实了;而如果要半年或一年后用户才能看到可以运行的功能的话,强调用户价值意识只能是一句空话。
频繁交付是减少库存的有效方法,以用户可识别功能为单位的迭代式开发是实现频繁交付的必要手段。交付周期缩短的极限就是“每次提交代码都产生交付就绪的软件”,这就是零库存。像很多精益生产中的概念一样,绝对的零库存是做不到的,因为每次提交代码后或许会产生可以运行的软件,但距离可交付的状态很可能还有段距离,可是这不影响我们以此作为持续改进的目标。
真的有必要这么频繁的交付吗?这取决于客户的要求。只是有些客户还没有意识到频繁交付不仅是一个合理的要求, 而且很可能是对客户和开发团队双方都有利的一件事情,这涉及到了合同、项目类型、软件商业价值的积累、开发模式和部署等议题,值得单独撰文探讨。这里想要 表明的是,即使由于种种原因客户只需要每半年交付一次,我们在内部开发时也要模拟频繁的交付过程,减少库存,强化用户价值意识。
准 时化生产在交付上也会有类似的问题。丰田公司每周到供应商处取一次货,但却要求供应商每 2 个小时就要将一定量的成品从总装区运送到装货区(很多供货商第一 次听到这个要求时都难以理解),这就是两阶段库存,是均衡化生产的一个实践,目的是为了做好发货准备的同时实现虚拟客户,模拟每 2 个小时提出需求拉动整个生产的过程,使每个生产环节能够感受到自己的工作是如何配合上下游的工序迅速实现用户需求的。敏捷开发虽说可能仅需要每几个月才交付一次,但在内部也通过 迭代实现了模拟客户频繁提出需求的过程。每一次迭代都模拟了一次客户提出需求并最终验收的全过程。重点是要尽量按照交付的标准来要求迭代,即使用户不需要 我们真正去交付。
维持频繁交付、减少库存还有一个重要的作用就是迫使问题和浪费从隐藏状态浮现出来。比如代码的简单性, 很难想象复杂难懂的代码能支持频繁交付。当代码中有很多重复的逻辑,或是实现过于复杂时,代码的质量就可能很差,并且增加新功能也会变的十分困难,这使得 团队难以实现短期交付的目标。可见,在频繁交付的环境下,代码中的复杂性更易形成明显的阻碍,迫使我们及时发现和处理这些问题。如果交付周期很长,这些问 题就不那么明显了。
均衡化生产是准时化生产的一个重要概念,它强调每个生产单元每天生产每种型号的产品,而不是像大规模 生产方式那样集中力量生产完某一型号的产品后再去生产下一个型号的产品。这个近乎疯狂的观点有效地减少了库存,增加了灵活性,提升了交付能力。为了尽快交 付一个用户故事,减少库存,敏捷开发弱化了各个阶段,也打破了软件模块的所有权。一个开发人员在一天中可能担当了分析、设计、编码和测试等多个角色,并可 能触动了客户端、服务器端以及数据库等多个模块。
准时化生产环境中,当生产流程稳定,平安无事的时候,团队可能会通过调 离 10% 的人员,或是调整节拍时间(生产一件产品需要的工时数,后面会有介绍)来迫使现有流程出现混乱,让以前不显眼的问题暴露出来,让很少量的库存也成 为阻碍迅速流动的障碍。团队会解决这些暴露出来的问题和浪费,持续地改进工作流程。为了消除浪费,任何事情都可以改变,即使这会触及到已经成文的规定或是 根深蒂固的观念。
三. 拉动生产与看板
准 时化生产采用“拉动”的方式传递信息和生产指令,它替换了传统的通过物料资源计划系统(Material Resource Planning)向各单位发送信息和生产指令的“推动”方式。拉动生产强调前一道工序仅在后一道工序提出要求时才开始生产,以此类推,最后一道工序是客 户。可见,在拉动的过程中,信息流动的路径是从客户开始的,经过后道工序到达前道工序。“看板”作为拉动生产的一个重要工具,记录了客户的需求或是后一道 工序对前一道工序的生产需求,它经常被拿来与敏捷开发中的用户故事卡做比较。在敏捷开发中,客户借助用户故事在一个迭代 的过程中将软件价值小批量地从团队中拉动出来。典型的开发过程是以这样的顺序进行的:发现新需求 - 用户故事卡 - 用户验收测试 - 单元测试 - 开发,这就是测试驱动开发的过程。故事卡是第一道看板,在开发过程中,看板是以测试的形式存在的,只有在建立了看板,也就是在看到失败的测试的时候才开始 编码。软件中的看板是可运行的,当所有验收测试运行通过后,用户故事也就做完了。敏捷开发综合运用增量式需求探索、用户故事、测试驱动开发以及演进式设计 等技术,确保客户可以将软件功能一个一个地从团队中拉动出来。
瀑布式开发采用“推动”的策略,依赖集中的分析和任务分 配,并通过执行已经制定的计划,将“部分完成的工作”在部门之间批量地进行传递来达到目标。这种信息流动方式容易牵一发而动全身,最终会导致决策的行政化。而拉动过程的信息链是松散的,它更注重实质的流程而非形式,员工清楚自己工作的目标(可识别的客户价值),因此可以自己决定很多事情,便于形成自发性 的系统。
前面提到了节拍时间(Takt Time),它等于可用工作时间除以客户需求数量,是生产一件产品需要的工时数。节拍时间确定了每一工位的工作节奏,超过和不足都不合适。比如,按照客户 的需求,1 天要生产 80 件产品,每天 8 小时工作时间,那么每 6 分钟就应该生产出一件成品。生产速度是属于整个团队的,它建立在完成的成品数量之上,没有必 要去考核每一个工位的加工速度,因为这个对整体没有意义,每个工位的加工速度都由节拍时间来决定。继续上面的例子,如果一件成品需要 2 个某一型号的零件, 则该型号零件的节拍时间就是 3 分钟(6 分钟 /2),快了会产生多余的库存,慢了会影响成品的速度,因此重点不在于优化对这一零件的生产,而是使成品的生产 速度刚好满足客户的需求。
准时化生产强调在节拍时间到来的时候看是否生产了一个合格的成品,而不是如传统生产方式那样强 调某个工位有没有按照工单上的要求加工完至少 200 个零件,越多越好。同样,敏捷注重稳定的开发节奏。开发的速度属于整个团队,它建立在完成的用户故事数 之上,强调持续、稳定地完成一个个对用户有价值的,经过集成的可用功能,而不是看是否做完了全部的设计工作,或是试图测量开发人员每天编写了多少行代码、 测试人员测了多少个 Bug。如果那样做就像是在传统大规模生产方式下测量工人在工位上加工了多少零件是一样的,是局部优化而非着眼全局优化整体。
四. 内建质量(Build Quality In)
准时化生产与“有人工参与的自动化(Autonomation)”并称为丰田生产方式的两大支柱,前者着重强调如何让有价值的步骤迅速流动起来,实现快速交付;而后者强调在第一时间、第一现场发现缺陷,分析根本原因并彻底解决问题,以此实现零缺陷的目标。“ 有人工参与的自动化”认为质量产生于工序中,而非依赖后期检测,并认为后期检测是一种浪费。工人被授权在出现问题的时候停止生产线,分析和解决问题,同时 广泛应用自动化的检测设备在生产线上及时发现加工中的缺陷。操作员不能将本工序的缺陷传递到下一个工序,他们要清楚质量的含义,而且有能力验证它。如果暂 时不能取消后期检测,那么检测人员与加工工人应在一起工作,第一时间实施检测,而非像大规模生产方式那样将他们分到两个不同的部门。
软件的质量产生于分析、设计和编码的过程中,而非依赖后期人工测试。人 工测试固然暂时不可缺少,但敏捷开发更强调尽可能将重复的测试过程自动化,并通过自动化验收测试和单元测试的形式集成到开发过程中,频繁地执行,及时发现 错误。测试驱动开发的意义在于它改变了设计和编码的过程,向其中注入了质量。现在,质量是整个团队共同的任务而非只是 QA 才关心的事情,团队中的每位成员 都需要了解质量的含义并具有共同的质量意识。
大规模生产与准时化生产在如何保证质量上有不同的认识,这里有一个有趣的比 较:一家德国汽车厂以生产高质量汽车闻名,在它生产线的末端停着很多汽车,大批工人在那里检测并修理遇到的问题。该工厂把生产一辆汽车超过 1/4 的工时花 费在这个阶段上,他们认为这是工厂对质量承诺的最佳诠释。而同时期丰田公司仅用了这家德国工厂 1/3 的工时就能生产同等品质的汽车,生产线末端被设计为仅 能停放 2 量汽车,也看不到大量工人维修的场景。丰田正是通过“有人工参与的自动化”技术高效地保证了质量。
可见,质量主要不在于你投入了多少人组建了一个多么大的后期测试队伍,而在于测试的时机和方式,等所有功能都做完了再测试就太晚了。我们或许可以通过大量后期测试的投入得到较好的软件“外部质量”,但很可能早已错失了通过改进设计提升软件“内部质量”的时机。糟糕的内部质量在你为软件增加新功能时会暴露无疑。
准 时化生产要求产品设计人员要走出办公室,到车间和工人们一起解决问题。发生问题时优先考虑通过改进产品设计和工具设计从源头上避免缺陷再次出现。这与传统 管理方式很不同,那时设计被认为是高级别的工作,需要坐在办公室里,认真地绘制图纸。软件开发中的分析设计,编码和测试也需要密切配合,及时反馈,发现问 题,然后从根本上解决问题。而不是像瀑布方式那样,分清阶段,采用扔砖过墙的方式将问题传递到下一个部门。
五. 现场管理与劳动力授权
实施准时化生产的企业认为管理信息和生产数据不应仅保存在电脑中或是高级经理的办公桌里,它们中的绝大部分信息都不值得保密,反而应该公开出来发挥其本身应该发挥的作用。准时化生产的工厂强调可视化的现场管理,你可以通过简单的观察在 5 分钟内了解生产现场状态,了解到各小组要满足的生产需求,生产进度和人员安排等等,而这些 都不需要动用计算机或询问任何人。工厂广泛运用看板、信息提示板、改进提示版、大屏幕、信号灯和各种标记线等方式将重要的信息展示在办公环境中,并授权一 线小组,维护和利用这些信息,安排生产,做决策,解决遇到的问题。
劳动力授权就是将决定权交给那些最熟悉某种特定情况的 人,放权各个小组组织生产。小组的成员一般来自传统企业的各个部门,共同完成具体的任务,强调敞开式办公,配合可视化的现场管理实现充分的沟通。这样的小 组有助于拆除分隔各部门之间的壁垒。大家还要改变观念,由主管吩咐做什么转化为小组决定做什 么,这包括安排人员,进行改进活动,甚至包括当出现质量问题时派人拜访客户等等。
敏捷开发中采用几乎一样的方式组织开发 团队,并授权团队成员自我管理和决策。敏捷开发和前述的工厂一样,利用各种可视化方法将反映项目状态的信息展示出来,典型做法包括使用用户故事卡墙和 Burn Down/Up 图,还可能会用大屏幕或信号灯来揭示持续集成的状态。开放的办公环境更利于交流,大家也更容易“嗅”到团队中的小问题,并在问题出现时能及时主动地提供 导和帮助。
价值产生于生产现场,现场是发现和解决问题的地方也是了解生产现状的最佳场所。精益生产强调“现场态度”,不要听报告,到现场去了解情况,管理人员走出办公室,到现场去解决问题。
软件开发中的现场指:
- 人
- 工作环境,包括办公环境和各种不同用途的机器设备等
- 所有工作产出物,包括代码,文档,任务跟踪系统和配置信息等
我们要问问,这个现场是否整齐清洁,是否有没用的东西,有用的东西是否简单明确地存放到了唯一的位置,团队成员是否清楚什么时候需要什么东西,到哪里找?这些问题不仅要用来问办公环境和机器设备,更重要的是用来问问所有的产出物,尤其是代码库。敏 捷开发强调同样的现场态度,报告离现场远了一些,并不一定能反映出项目的真实现状,也未必会帮助你发现和解决问题。如果懂开发,就去看看代码,或与程序员 结对开发一会;不懂得话可以和 QA 结对真正使用一下团队开发的软件,或者和需求分析人员一同分析一个新需求。这些都会让你得到的信息更接近项目的真实状 态。
敏捷开发强调共享现场,而不是各自维护自己的一块。它通过结对和频繁地更换结对来培养每个人对现场的整体认识,为平时的决策打下基础。团队内部的技术讨论也建立在对现场的充分认识上,避免空洞的建议。
六. 小结
综上,准时化生产的思想强调在软件开发过程中进行频繁的交付,以此减少库存,暴露并消除浪费的步骤,加快价值的流动;它强调通过客户来拉动开发过程,确保每 一时刻团队成员都在围绕客户认为最重要的软件功能展开工作;它强调在第一时间、第一现场发现问题,并从根本上解决问题,以此将质量内建在分析、设计和开发 的过程中;它强调将与项目相关的所有人组成高度授权的团队,通过可视化地向团队成员全面展示项目信息来支持自我决策。准时化生产的思想还告诉我们,当改进 流程和实践时,要以快速交付和高质量为目标,而成本则要端到端地考量,低成本往往是实现快速交付与高质量的自然结果。前面提到了准时化生产和精益生产中的一些观点和实践,这些也仅涵盖了其一小部分内容。还有很多其它有趣的观点和实践,比如持续改进、单件流、5S、全面生产维护、标准化和快速换模等等,它们对软件开发也颇有启发意义。
希望软件从业者能虚心地向制造业中的先进思想学习,不要因为软件开发中包含了更多的智力活动就过早地持怀疑态度。重要的是制造业和软件开发行业都面临着一些类似的问题,我们希望了解精益生产解决这些问题的方法,有选择地学习和借鉴它的思路,巩固和发展软件开发实践。
作者简介:
路宁,ThoughtWorks 公司咨询师,擅长.NET 企业应用开发,在敏捷过程方面有着丰富的经验。目前主要致力于精益软件开发方面的探索和研究。他的博客位于 www.luning.name 。
评论