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