# Evidence Based Scheduling [Evidence Based Scheduling – Joel on Software](https://www.joelonsoftware.com/2007/10/26/evidence-based-scheduling/) Software developers don’t really like to make schedules. Usually, they try to get away without one. “It’ll be done when it’s done!” they say, expecting that such a brave, funny zinger[^2] will reduce their boss to a fit of giggles[^1], and in the ensuing joviality[^3], the schedule will be forgotten. 軟體開發者都不怎麼喜歡訂時程。而且,他們總是會想辦法逃避這件事。對於老闆的詢問,他們總是回答說:「完成的時候就是完成了!」他們也總是會期望有一個精緻且有趣的玩笑,能讓他們的老闆笑一笑,然後就可以忘了時程這件事。 Most of the schedules you do see are halfhearted attempts. They’re stored on a file share somewhere and completely forgotten. When these teams ship, two years late, that weird guy with the file cabinet in his office brings the old printout to the post mortem[^4], and everyone has a good laugh. “Hey look! We allowed two weeks for rewriting from scratch in Ruby!” 許多你看起來排好的時程,它們都不是真心全意的嘗試。它們只會被儲存在某個共享空間,然後就完全被大家所遺忘。直到這個團隊在晚了2年才能交付產品的時候,會有一個怪咖從舊的檔案櫃中,把之前印好的時程表帶到這個死透的產品的"驗屍現場",大家會笑出來,而且說:「嘿,你們看!我們還有排上2週,要用Ruby從無到有,整個重寫呢...」。 Hilarious[^5]! If you’re still in business. 太爆笑了!如果你們還在營運的話… You want to be spending your time on things that get the most bang for the buck[^6]. And you can’t figure out how much buck your bang is going to cost without knowing how long it’s going to take. When you have to decide between the “animated paperclip” feature and the “more financial functions” feature, you really need to know how much time each will take. 你一定想要讓時間是花在刀口上的。所以當你決定在「小幫手(animated paperclip)」和另一個「更重要的財務功能」還一個來做的時候,你真的必須知道它們各自要花多少時間。 Why won’t developers make schedules? Two reasons. One: it’s a pain in the butt[^7]. Two: nobody believes the schedule is realistic. Why go to all the trouble of working on a schedule if it’s not going to be right? 為何開發者都不做時程規劃?理由有兩個,第一就是那實在太費事傷神了。第二就是沒人相信時程是真的。所以,如果這一切根本就不會照規劃走,為什麼他們要去訂時程? Over the last year or so at Fog Creek we’ve been developing a system that’s so easy even our grouchiest[^8] developers are willing to go along with it. And as far as we can tell, it produces extremely reliable schedules. It’s called Evidence-Based Scheduling, or EBS. You gather _evidence_, mostly from historical timesheet data, that you feed back into your schedules. What you get is not just one ship date: you get a confidence distribution curve, showing the probability that you will ship on any given date. It looks like this: 去年在Fog Creek我們開發了一個很簡單的時程估計系統,連我們最會埋怨的開發者都可以與之和平共處。據我們所知,它可以產出極度可信的時程,這個方法被稱為「證據式時程規劃(Evidence-Based Scheduling)」,簡稱EBS。用戶只要收集足夠多開發歷程的「證據」,多數是來自於之前的耗費的時間記錄,輸入到這個系統,最終不只是得到一個交付的日期,而是一個可信度分佈曲線,讓你知道不同的日期有多少確信率可以真正交付產品,就像這樣: ![](https://i.imgur.com/5z9MhA6.png) The steeper the curve, the more confident you are that the ship date is real. Here’s how you do it. 曲線越陡峭,代表交付日期的"成真率"越高。 接下來這就是你使用這個系統的過程說明。 ## 1) Break ‘er down When I see a schedule measured in days, or even weeks, I know it’s not going to work. You have to break your schedule into very small tasks that can be measured in _hours_. Nothing longer than 16 hours. 1) 把所有的工項都確實拆解 當我看到估出來的時程是以「天」為單位,甚至是以「週」為單位時,我就知道這完全是玩假的。你必須把時程中的每個工項拆解到非常小,小到可以用「小時」為單位來估計,而且沒有任何一個工項可以超過16個小時。 This forces you to actually figure out what you are going to do. Write subroutine _foo_. Create this dialog box. Parse the Fizzbott file. Individual development tasks are easy to estimate, because you’ve written subroutines, created dialogs, and parsed files before. 這能要求你確實把你要做的事情搞清楚。這可能包括要寫一隻子函式「foo」,創建一個對話框,解析一個Fizzbott檔等等。這些事情是容易被估出會耗費的時間的,因為你寫過這些函式,創建過對話框,也解析過那個檔案。 If you are sloppy[^9], and pick big three-week tasks (e.g., “Implement Ajax photo editor”), then you _haven’t thought about what you are going to do._ In detail. Step by step. And when you haven’t thought about what you’re going to do, you can’t know how long it will take. 如果你很懶散,只是隨便為一個工項訂了3週的時程(像是「實作一個Ajax版的照片編輯器」),這就代表你壓根就沒想過你究竟要做些什麼事情來完成這個功能。一定要一步一腳印,確實把所有的細節拆出來,不這麼做,你絕對無法正確的預估你要花多少時間做這件事。 Setting a 16-hour maximum forces you to _design_ the damn feature. If you have a hand-wavy[^10] three week feature called “Ajax photo editor” without a detailed design, I’m sorry to be the one to break it to you but you are officially _doomed_. You never thought about the steps it’s going to take and you’re sure to be forgetting a lot of them. 設定一個16小時的最大耗時,可以強迫你去設計出每件你應該要做的事。如果你只是掐指一算,"覺得"應該需要三週來完成「Ajax版的照片編輯器」,你就完蛋了~你一定不曉得幹這件事會有多少"意外"出現。 ## 2) Track elapsed time It’s hard to get individual estimates exactly right. How do you account for interruptions, unpredictable bugs, status meetings, and the semiannual Windows Tithe Day when you have to reinstall everything from scratch on your main development box? Heck, even without all that stuff, how can you tell exactly how long it’s going to take to implement a given subroutine? 2) 追蹤耗費時間 要精準預估每個人所花費的時間是很困難的,因為我們都不知道要怎麼把「被插斷」,「非預期的bug」,「同步會議」或是大約半年就會出現的「Windows奉獻日(Windows Tithe Day)」:你必須把你的開發機整個重灌。正確的列入計算?就算這些事情都不算進來好了,我們又要怎麼正確的計算,我們花在一個工項的「實際研發時間」是多少? ![](https://i.imgur.com/y9JLt1E.png) Each point on the chart is one completed task, with the estimate and actual times for that task. When you divide estimate by actual, you get _velocity_: how fast the task was done relative to estimate. Over time, for each developer, you’ll collect a history of velocities. 在圖上的每個點都是一個完成的工項,也就是會有「預估」和「實際」的耗時。當你透過「預估 / 實際」這麼一除,就會得到所謂的「速度」:這個工項比預期快多少完成。隨記錄的時長越久,我們就能取得一連串的速度記錄。 - The mythical _perfect estimator_, who exists only in your imagination, always gets every estimate exactly right. So their velocity history is {1, 1, 1, 1, 1, …} - A typical _bad estimator_ has velocities all over the map, for example {0.1, 0.5, 1.7, 0.2, 1.2, 0.9, 13.0} - Most estimators get the scale wrong but the relative estimates right. Everything takes longer than expected, because the estimate didn’t account for bug fixing, committee meetings, coffee breaks, and that crazy boss who interrupts all the time. This _common estimator_ has very consistent velocities, but they’re below 1.0. For example, {0.6, 0.5, 0.6, 0.6, 0.5, 0.6, 0.7, 0.6} - 理想的完美預估時程(只存在你想像裡的那種),也就是預估和實際耗時一致,所以它們的速度記錄應該會是{1 ,1 ,1, 1, 1....} - 很糟糕的預估時程,就會在圖表上點得到處都是,像是{ 0.1, 0.5, 1.7, 0.2, 0.9, 13.0...} - 大部分的預估都會獲得一定程度的"低估"。基本上每件事情都會比預期的還要久,因為我們的預估通常不會把「修正臭蟲」,「同步會議」,「喝杯咖啡」或是「老闆的奪命連環扣」算進來。這些普遍的預估通常會以一種蠻一致的程度出現,也就是它們大約都會造成40%-50%的誤差,所以換算成速度(阻力)會長得像這樣:{0.6, 0.5, 0.6, 0.6, 0.5, 0.7, 0.6...} As estimators gain more experience, their estimating skills improve. So throw away any velocities older than, say, six months. If you have a new estimator on your team, who doesn’t have a track record, assume the worst: give them a fake history with a wide range of velocities, until they’ve finished a half-dozen real tasks. 隨著人們預估的經驗越來越豐富,預估能力會變得更好,所以我們就可以把隨口說說的預留時間(buffer),比如說「預留6個月」這種沒有依據的預估給丟了。 如果在你的團隊中有新人,他們沒有足夠的記錄可以去追蹤,計算或分析,那我們只好往最壞的狀況假設:給他們足夠混亂的假的速度分布表,去預估他們的時程,直到他們真的完成了一些(比如說半打)的任務,我們才開始做一些調整。 ## 3) Simulate the future Rather than just adding up estimates to get a single ship date, which sounds right but gives you a profoundly wrong result, you’re going to use the Monte Carlo method to simulate many possible futures. In a Monte Carlo simulation, you can create 100 possible scenarios for the future. Each of these possible futures has 1% probability, so you can make a chart of the probability that you will ship by any given date. 3) 模擬未來 比起只是隨便加入一個預估的時間去得到一個可以交付的日期(很顯然聽起來就是錯的離譜…),你應該要使用蒙地卡羅(Monte Carlo)法去模擬許多可能的未來。在蒙地卡羅的模擬中,你可以有100種未來的可能場景,而每一個狀況會有1%的可能性,那麼你就可以劃出一張圖表明不同的交付日期的"成真率"有多大。 While calculating each possible future for a given developer, you’re going divide each task’s estimate by a _randomly-selected velocity_ from that developer’s historical velocities, which we’ve been gathering in step 2. Here’s one sample future: 當要開始預估某個開發者可能的交付日期時,你要先根據他的歷史速度記錄,把他的每個工項的預估時間,亂數選一個速度來除: | Estimate | 4 | 8 | 2 | 8 | 16 | | | --- | --- | --- | --- | --- | --- | --- | | Random Velocity | 0.6 | 0.5 | 0.6 | 0.6 | 0.5 | Total: | | E/V | 6.7 | 16 | 3.3 | 13.3 | 32 | 71.3 | Do that 100 times; each total has 1% probability, and now you can figure out the probability that you will ship on any given date. 這個動作執行100次,我們可簡單認定每種不同的速度狀況的發生率是1%,你就可以得到每個不同的交付日期,有多高的"成真率"。 Now watch what happens: - In the case of the mythical perfect estimator, all velocities are 1. Dividing by a velocity which is always 1 has no effect. Thus, all rounds of the simulation give the same ship date, and that ship date has 100% probability. Just like in the fairy tales! - The bad estimator’s velocities are all over the map. 0.1 and 13.0 are just as likely. Each round of the simulation is going to produce a very different result, because when you divide by random velocities you get very different numbers each time. The probability distribution curve you get will be very shallow[^11], showing an equal chance of shipping tomorrow or in the far future. That’s still useful information to get, by the way: it tells you that you shouldn’t have confidence in the predicted ship dates. - The common estimator has a lot of velocities that are pretty close to each other, for example, {0.6, 0.5, 0.6, 0.6, 0.5, 0.6, 0.7, 0.6}. When you divide by these velocities you increase the amount of time something takes, so in one iteration, an 8-hour task might 13 hours; in another it might take 15 hours. That compensates for the estimators perpetual optimism. And it compensates _precisely_, based _exactly_ on this developers _actual, proven, historical optimism_. And since all the historical velocities are pretty close, hovering around 0.6, when you run each round of the simulation, you’ll get pretty similar numbers, so you’ll wind up with[^12] a narrow range of possible ship dates. 那我們現在可以來看看有幾種可能性: - 在完全正確的預估中,所有的速度都是1,所以100次累積出來的交付日期等於是有100%的成真率。可以當作神話看看就好。 - 在很糟的預估狀況中,速度會以0.1到13亂數分布,每次的模擬計算都會的到非常不同的結果,所以最終得到的曲線斜率會是一個很平緩的分布,這表示交付日期不管是明天還是未來的某一天,機率幾乎是一樣的。當然,這看來似乎是沒什麼參考價值的資訊,但這至少告訴我們一項資訊:不要對任何一個交付日期抱有過高的期望。 - 在一般的預估狀況下中,我們的亂數速度差異並不會太大,大約就像是{0.6, 0.5, 0.6, 0.6, 0.5, 0.6, 0.7, 0.6}這種分布。所以當我們把開發者每個工項的預估時間,除以這些速度後,我們會得到一個"被放大一點"的預估時程。一個8小時的工項可能會放大到13小時,另一個可能會被放大到15小時,這就為我們的預估做了一些樂觀的補償,而且這個補償是根據這個開發者的歷史記錄的精確補償。因為這些速度分布的很靠近,所以你做出來的模擬最終就會獲得一個很小區間,成真率夠高的交付日期。 In each round of the Monte Carlo simulation, of course, you have to convert the hourly data to calendar data, which means you have to take into account[^14] each developer’s work schedule, vacations, holidays, etc. And then you have to see, for each round, which developer is finishing last, because that’s when the whole team will be done. These calculations are painstaking[^13], but luckily, painstaking is what computers are good at. 在每一次的蒙地卡羅模擬中,我們需要把算出來的工時轉換到日期在日曆上的日期。也就是說我們要把開發者的工作時程,包括假日和假期,換算成最終的交付日期。然後,你必須看看哪一個開發者是最後完成工作的,因為那就是整個專案產品最終交付的真實日期。這個計算過程很累人,不過幸運的是,"計算"是電腦最擅長的事。 ## Obsessive-compulsive disorder[^15] not required What do you do about the boss who interrupts you all the time with long-winded[^16] stories about his fishing trips? Or the sales meetings you’re forced to go to even though you have no reason to be there? Coffee breaks? Spending half a day helping the new guy get his dev environment set up? When Brett and I were developing this technique at Fog Creek, we worried a lot about things that take real time but can’t be predicted in advance. Sometimes, this all adds up to more time than writing code. Should you have estimates for this stuff too, and track it on a time sheet? 不需要有強迫症 你的老闆總是喋喋不休他的釣魚記,你總是被強迫去參加你根本不需要去的銷售會議?下午茶呢?還是花上半天的時間幫助新人設定他的開發環境?…當Brett跟我在開發Fog Creek時,我們很困擾於這些令人分神的事情無法事前預知,而且這些"小事"加總起來都已經超過寫code的時間了,我們也應該把這些時間也加總到我們的實際工時去嗎? ![](https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2007/10/26ebs3.png?resize=460%2C223&ssl=1) Well, yeah, you can, if you want. And Evidence Based Scheduling will work. _But you don’t have to._ It turns out that EBS works so well that all you have to do is _keep the clock running_ on whatever task you were doing when the interruption occurred. As disconcerting[^17] as this may sound, EBS produces the best results when you do this. 是啊,你可以這麼做,如果你想要的話。而且,EBS一樣可以用。 但是你不需要真的這麼做。 EBS只要求你一件事:「確保時鐘不停歇」。也就是在執行工項的實際耗時,有確實被記錄下來,不管有什麼中斷或打擾插入。僅管這聽起來有點不合理,但EBS就是能產生最好的預測結果。 Let me walk you through a quick example. To make this example as simple as possible, I’m going to imagine a very predictable programmer, John, whose whole job is writing those one-line getter and setter functions that inferior[^18] programming languages require. All day long this is all he does: 讓我給你展示一個很簡單的範例。為了說明這個案例,我們來假設一個很有生產力,估計時程能力很好的工程師叫做John,他今天的工作就是要把以下的源碼寫完: ```cs private int width; public int getWidth () { return width; } public void setWidth (int _width} { width = _width; } ``` I know, I know… it’s a deliberately[^20] dumb example, but you _know_ you’ve met someone like this. Anyway. Each getter or setter takes him 2 hours. So his task estimates look like this: 好好,我知道,這完全就是一個刻意為之的傻範例,但你也知道,你就是有機會碰上這種鳥事。基本上這段程式很容易預估會耗時多久,所以他的工時資料會是這樣分布的: {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, … } Now, this poor guy has a boss who interrupts him every once in a while with a two-hour conversation about marlin fishing. Now, of course, John could have a task on his schedule called “Painful conversations about marlin,” and put that on his timesheet, but this might not be politically prudent[^19]. Instead, John just keeps the clock running. So his actual times look like this: 鳥事發生了。這可憐的傢伙被老闆叫住,"談"了2小時關於怎麼釣馬林魚的對話。當然,John可以在實際的耗時工作表上記下「關於馬林魚的痛苦的2小時」,但這可能不是個很厚道的職場禮儀。所以,在「確保時鐘不停歇」的前提下,他的實際工時就是這樣分布的: {2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 2, … } And his velocities are: 所以他的速度分布變成是這樣: {1, 1, 1, 1, 0.5, 1, 1, 1, 1, 0.5, 1, … } Now think about what happens. In the Monte Carlo simulation, the probability that each estimate will be divided by 0.5 _is exactly the same as the probability that John’s boss would interrupt him during any given feature._ So EBS produces a correct schedule! 接下來讓我們看看會發生什麼事。在蒙地卡羅模擬中,每個工項都有機率會除以0.5的速度(工時就變成2倍),而這件事確實就是有機率,在John的任何一個工項中發生。因此在多次模擬的結果下,EBS正確的產出了受影響的時程預估。 In fact, EBS is far more likely to have accurate evidence about these interruptions than even the most timesheet-obsessive developer. _Which is exactly why it works so well_. Here’s how I explain this to people. When developers get interrupted, they can either 1. make a big stink[^21] about putting the interruption on their timesheet and in their estimates, so management can see just how much time is being wasted on fishing conversation, or 2. make a big stink about refusing to put it on their timesheet, just letting the feature they were working on slip, because they refuse to pad _their_ estimates which were _perfectly correct_ with stupid conversation about fishing expeditions to which they _weren’t even invited_, … and in either case, _EBS gives the same, exactly correct results_, no matter which type of passive-aggressive[^22] developer you have. 事實上,EBS比那些最執著於耗時表的工程師,還要能表達出這些中斷干擾造成的影響。它之所以能運作的這麼準確,這裡有兩個解釋可以跟人們說明。當開發者被干擾的時候,他們通常會有這兩個反應: 1. 對這些干擾大肆抱怨,然後將干擾造成的耗時成本記入耗時表,讓管理層知道討論釣魚這件事浪費了開發者多少時間。 2. 對這些干擾大肆抱怨,但堅持**不**將這些干擾造成的耗時成本記入耗時表,然後就讓他們的工項規格開天窗。因為他們不想要讓那個愚蠢的釣魚故事(對話),破壞原本完美估計地好好的時程。 所以,不管是哪一種反應,EBS都會給出一致正確的預估結果,不管是多消極反抗的工程師都一樣。 ## 4) Manage your projects actively Once you’ve got this set up, you can actively manage projects to ship on time. For example, if you sort features out[^23] into different priorities, it’s easy to see how much it would help the schedule if you could cut the lower priority features. 4) 更積極地管理你的專案 一但你可以把這些事情都設置的很好,你可以更積極的管理你的專案,讓交付更為準時。例如,若是你可以對所有功能都給予優先權,並予以排序,把低重要度的功能放下,你就可以很輕鬆的讓時程壓力更小。 ![](https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2007/10/26ebs4.png?resize=297%2C180&ssl=1) You can also look at the distribution of possible ship dates for _each developer_: 當然,你也可以回頭看一下每個開發者的交付日期分布在哪裡: ![](https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2007/10/26ebs5.png?resize=460%2C238&ssl=1) Some developers (like Milton in this picture) may be causing problems because their ship dates are so uncertain: they need to work on learning to estimate better. Other developers (like Jane) have very precise ship dates that are just too late: they need to have some of their work taken off their plate. Other developers (me! yay!) are not on the critical path at all, and can be left in peace[^24]. 有些開發者(像圖中的Milton)可能就是會造成交付日期不穩定的因子,因為他的交付時程太不穩定了,他需要做更好的預估。其他的開發者(像是Jane)雖然有準確的交付日期預估,但她的日期根本就確定會造成整個產品的delay,我們需要拿掉一些她的工項。再看看另一個開發者(就是我啦),他似乎不在關鍵路徑(Critical Path)上,那我們就可以不用特別管他了。 ## Scope creep [^25] Assuming you had everything planned down to the last detail when you started work, EBS works great. To be honest, though, you may do some features that you hadn’t planned. You get new ideas, your salespeople sell features you don’t have, and somebody on the board of directors comes up with a cool new idea to make your golf cart GPS application monitor EKGs[^26] while golfers are buzzing around[^27] the golf course. All this leads to delays that could not have been predicted when you did the original schedule. 範疇蔓延 假設你把所有的事情都計劃的很詳盡,EBS當然可以運作的很好。但老實說,你一定就是會有東西不是事先就可以規劃得到的。總是會有新的想法,不論是來自你自己或是董事會的總監想出來的。也總是會有銷售人員"賣"出了你根本沒有的功能,甚至會有人異想天開地要求要在高爾夫球車的app上,新增可以監控跑來跑去的球手的心電圖。這些都是會導致專案交付日期延遲的事情,而且都不是你原來的預估中可以事前計劃到的。 Ideally, you have a bunch of buffer for this. In fact, go ahead and build buffer into your original schedule for: 1. New feature ideas 2. Responding to the competition 3. Integration (getting everyone’s code to work together when it’s merged) 4. Debugging time 5. Usability testing (and incorporating[^28] the results of those tests into the product). 6. Beta tests So now, when new features come up, you can slice off[^29] a piece of the appropriate buffer and use it for the new feature. 理想情況下,你會需要準備一些緩衝空間(buffer)來應付這些狀況。沒錯,實務上就是有這個需求。儘管去保留一些緩衝空間吧,因為實際上就是會用在這些地方: 1. 新的功能和想法 2. 對競品的應對措施 3. 實作整合(就是把大家寫好的東西合併起來) 4. 除錯 5. 可用性測試(以及把最終的結果整合到產品身上) 6. 上市前測試(Beta Test) 所以一但有一些新的狀況出現,你就可以把準備好的緩衝時間,一塊塊切下來應付這些臨時的需求。 What happens if you’re still adding features and you’ve run out of buffer? Well, now the ship dates you get out of[^30] EBS start slipping. You should take a snapshot of the ship date confidence distribution every night, so that you can track this over time: 如果你已經用完了緩衝時間,還一直加入新的功能要實作的話,會發生什麼事?嗯,當然你EBS估計的日期會開始跑掉。這時你該做的,就是每晚把EBS重新估算的交付日期圖給快照一份下來,這樣你可以不斷的追蹤其變化: ![](https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2007/10/26ebs6.png?resize=460%2C246&ssl=1) The x-axis is when the calculation was done; the y-axis is the ship date. There are three curves here: the top one is the 95% probability date, the middle is 50% and the bottom is 5%. So, the closer the curves are to one another, the narrower the range of possible ship dates. If you see ship date getting later and later (rising curves), you’re in trouble. If it’s getting later by more than one day per day, you’re adding work faster than you’re completing work, and you’ll never be done. You can also look and see if the ship date confidence distribution is getting tighter (the curves are converging), which it should be if you’re really converging on a date. ## While we’re at it Here are a few more things I’ve learned over the years about schedules. 1) Only the programmer doing the work can create the estimate. Any system where management writes a schedule and hands it off to programmers is doomed to fail. Only the programmer who is going to implement a feature can figure out what steps they will need to take to implement that feature. 2) Fix bugs as you find them, and charge the time back[^31] to the original task. You can’t schedule a single bug fix in advance, because you don’t know what bugs you’re going to have. When bugs are found in new code, charge the time to the original task that you implemented incorrectly. This will help EBS predict the time it takes to get _fully debugged_ code, not just _working_ code. 3) Don’t let managers badger[^32] developers into shorter estimates. Many rookie software managers think that they can “motivate” their programmers to work faster by giving them nice, “tight” (unrealistically short) schedules. I think this kind of motivation is brain-dead. When I’m behind schedule, I feel doomed and depressed and unmotivated. When I’m working _ahead_ of schedule, I’m cheerful and productive. The schedule is not the place to play psychological games. 當我們在實作EBS的時候 這裡有一些這幾年我在建立時程預估時學到的事: 1) 只有實際要做這件事的程式設計師可以決定「預估耗時」。任何由管理層寫好,拿來要求程式設計師的時程,一定是準備爆炸的版本。只有要實作這個功能的程式設計師才能搞懂,做這個功能需要的所有步驟。 2) 當找到問題(bug)的時候,就馬上修正它,而且要把這段時間回饋到原工項的耗時去。因為你不知道會遇到什麼問題,自然你不能預先排出修正問題所需的耗時。發現問題並把時間回加到原先預估的耗時,才能幫助EBS預估出完整除錯後的源碼,而不是「只是會動」的版本。 3) 別讓管理者要求開發者開出更短的耗時預估。許多新手管理者會天真的以為,訂出更緊密的(通常就是不合理的)時程,可以"激勵"開發者有更快的開發效率,我認為這完全是腦子壞掉才想得出來的"激勵"法。當我無法趕上時程的時候,我只會覺得我把事情搞砸了,而且會很沮喪,完全沒有"被激勵"的效果。只有當我一切順利,比原訂的時程更快時,我才會感到愉悅,也更有生產力。時程預估不是拿來玩心理遊戲的。 Why do managers try this? When the project begins, the technical managers go off[^33], meet with the business people, and come up with a list of features they _think_ would take about three months, but which would really take twelve. When you think of writing code without thinking about all the steps you have to take, it always seems like it will take n time, when in reality it will probably take more like 4n time. When you do a real schedule, you add up all the tasks and realize that the project is going to take much longer than originally thought. The business people are unhappy. Inept[^34] managers try to address this by figuring out how to get people to work faster. This is not very realistic. You might be able to hire more people, but they need to get up to[^35] speed and will probably be working at 50% efficiency for several months (and dragging down the efficiency of the people who have to mentor them). You might be able to get 10% more raw code out of people _temporarily_ at the cost of having them burn out 100% in a year. Not a big gain, and it’s a bit like eating your seed corn[^36]. Of course, when you overwork people, debugging time _doubles_ and a late project becomes later. Splendid karma. But you can never get 4n from n, ever, and if you think you can, please email me the stock symbol for your company so I can short it. 為什麼管理者會嘗試這麼做? 當專案開跑之後,技術管理者也開始會見一些商務人員,然後會聽到一系列的需求,此時他們就會開出一系列"他認為"可以3個月完成的功能,但實際上會花12個月。當你沒有想過實際上開發這個功能所需要經過的所有步驟時,你以為花費的時間是n,但實際上它可能耗時達4n的時間。而當你真的把這些工項搞清楚了,也把所需耗時的時程搞清楚了之後,比你一開始預計更長的時程,這件事就會讓商務人員開心不起來了。 無能的管理者可能會嘗試讓開發者做的更快,來解決這個問題,而這完全是不切實際的。他們也許會僱用更多的人,但這些新人要達到可以"全速運行"之前,大概會有幾個月的時間只能有50%的開發效率(而且他們還會把其他人的開發效率給拉下來,因為要指導這些新人…)。 就算你要求這些開發者全年加班,也只能暫時得到額外10%的源碼產出,沒什麼太大的效果,只是寅吃卯糧罷了。當然,當你要求開發者加班趕工,你還會額外獲得加倍的除錯時間,以及延遲的更嚴重的交付時程。多美好的業力啊,簡直就是惡性循環。 所以,你絕對不可能讓開發效率從n變成4n,如果你覺得你辦得到,請告訴我你公司的股票代碼,好讓我去放空你的公司。 **4) A schedule is a box of wood blocks.** If you have a bunch of wood blocks, and you can’t fit them into a box, you have two choices: get a bigger box, or remove some blocks. If you wanted to ship in six months, but you have twelve months on the schedule, you are either going to have to delay shipping, or find some features to delete. You just can’t shrink the blocks, and if you pretend you can, then you are merely depriving yourself of[^37] a useful opportunity to actually _see into the future_ by lying to yourself about what you see there. Now that I mention it, one of the great benefits of realistic schedules is that you _are_ forced to delete features. Why is this good? Suppose you have two features in mind. One is really useful and will make your product really great. The other is really easy and the programmers can’t wait to code it up (”Look! <blink>!”), but it serves no useful purpose. If you don’t make a schedule, the programmers will do the easy/fun feature first. Then they’ll run out of time, and you will have no choice but to slip the schedule to do the useful/important feature. If you do make a schedule, even before you start working, you’ll realize that you have to cut something, so you’ll cut the easy/fun feature and just do the useful/important feature. By forcing yourself to chose some features to cut, you wind up[^38] making a more powerful, better product with a better mix of good features that ships sooner. 4) 時程就是一個要裝下所有木塊的箱子 如果你有一些大小不一的木塊,發現無法全部裝進一個箱子裡,你只有兩個選擇:找一個更大的箱子,不然就是減少要放進去的木塊。如果你想要在6個月後交付產品,但你有12個月份的工作要做,要嘛你不是要讓交付日期開天窗,要嘛你就是要砍掉一些功能別做。你無法做到的就是把木塊縮小,而且若你以為你可以,你只是用謊言在欺騙自己,喪失一個能展望未來的好機會。 就像剛剛提的,一個真實可靠的時程能帶給你最大的好處就是,它可以強迫你去砍掉一些功能別做。可這有什麼好的? 如果在你心中有兩個功能都很重要,一個是真正有用,能讓你的產品變得偉大的功能,另一個則是很簡單,開發者也很喜歡的"閃亮(很炫)"功能,但它並沒有辦法為產品帶來更大的價值。 此時,如果你沒有訂好時程,工程師就會先去做那個簡單或有趣的功能。他們在順手完成功能的同時,也會"順手"花光僅有的時間。此時你幾乎沒有選擇,只能讓時程開天窗,補做那些真正有用或該做的功能。 如果你有確實訂好時程,甚至可以在動工之前,就可以理解你必須準備砍掉一些規格。所以你會先拿那些簡單/有趣的規格開刀,然後專心做那些有用/重要的規格。籍由強迫你自己去砍掉一些規格,你最終會更快的,真正的創建出更多有用功能,更好的產品。 Way back when I was working on Excel 5, our initial feature list was huge and would have gone way over schedule. “Oh my!” we thought. “Those are all super important features! How can we live without a macro editing wizard?” As it turns out, we had no choice, and we cut what we thought was “to the bone” to make the schedule. Everybody felt unhappy about the cuts. To make people feel better, we told ourselves that we weren’t cutting the features, we were simply deferring them to Excel 6. As Excel 5 was nearing completion, I started working on the Excel 6 spec with a colleague, Eric Michelman. We sat down to go through the list of “Excel 6” features that had been punted[^39] from the Excel 5 schedule. Guess what? It was the shoddiest[^40] list of features you could imagine. Not one of those features was worth doing. I don’t think a single one of them ever was. The process of culling features to fit a schedule was the best thing we could have done. If we hadn’t done this, Excel 5 would have taken twice as long and included 50% useless crap features that would have had to be supported, for backwards compatibility, until the end of time. 回到當時我們還在做Excel 5的時候,一開始我們開出來的功能,所需要的時間就遠超過時程非常多。「天啊!這些都是超級重要的功能啊,我們怎麼可以沒有巨集編輯精靈!?」 當然,當時我們沒有選擇,我們只能把想做的功能清單砍到見骨,來符合上市的時程需求。每個人都很不開心,為了讓大家心理好受一點,我們跟大家說,我們並不是"砍掉"這些功能,我們只是把這些"驚喜"延到Excel 6再做。 當Excel 5告一段落後,我開始跟同事Eric Michelman坐下來,好好討論Excel 6的功能規格,尤其是那些被我們剔除的那些。你猜怎麼著?Excel 6的功能清單和Excel 5想做的相比,簡直是寒酸到不行。但是,沒有任何一個Excel 5當時覺得「一定要有」的功能,值得加到Excel 6,我們很確定沒有任何一個值得花時間去做。當時回頭去砍掉那些"重要"功能的過程,肯定是我們在做Excel 5的過程中最重要的一件事,如果我們沒這麼做,Excel 5肯定會比預期的時間多出2倍的時間,而且還會含入50%沒有的垃圾規格,更別說後續還要繼續支援,或是要解決相容性問題之類的。 ## Summary Using Evidence-Based Scheduling is pretty easy: it will take you a day or two at the beginning of every iteration to produce detailed estimates, and it’ll take a few seconds every day to record when you start working on a new task on a timesheet. The benefits, though, are huge: realistic schedules. Realistic schedules are the key to creating good software. It forces you to do the best features first and allows you to make the right decisions about what to build. Which makes your product better, your boss happier, delights your customers, and—best of all—lets you go home at five o’clock. 總結 使用「證據式時程」是蠻容易的一件事:只要花個一、兩天,在每個工項開始執行的前後,都確實的產出預估和實際的耗時。而這麼做的回報非常非常大:一個真實的時程估計。 真實的時程估計,是創建好軟體產品的關鍵。它能讓你先做最好的功能,決定該先做什麼功能,因此能讓你的產品更好,讓你的老闆更快樂,也讓你的顧客更開心,最重要的是,能讓你準時在5點下班回家。 [^1]: a fit of giggles: something or someone that provokes amusement [^2]: a striking or amusing remark. [^3]: good-humored cheerfulness [^4]: post-mortem: an examination of a dead body to determine the cause of death. [^5]: extremely amusing. [^6]: bang for the buck: More value for one's money, a greater return on an investment. [^7]: pain in the butt: A nuisance; a source of trouble or annoyance. [^8]: grouch: voice one's discontent ill-temperedly; grumble. [^9]: careless and unsystematic; excessively casual. [^10]: hand-wavy: Hand-waving (with various spellings) is a pejorative label for attempting to be seen as effective. [^11]: of little depth [^12]: wind up with: to end up having someone or something. [^13]: done with or employing great care and thoroughness [^14]: take into account someone: To think about, consider, or keep in mind someone or something regarding the future. [^15]: obsessive-compulsive disorder: a common mental health condition where a person has obsessive thoughts and compulsive behaviours [^16]: (of speech or writing) continuing at tedious length. [^17]: To frustrate (plans, for example) by throwing into disorder; disarrange. [^18]: Low or lower in order, degree, or rank. [^19]: Careful or wise in handling practical matters. [^20]: Done with or marked by full consciousness of the nature and effects; intentional: [^21]: make or raise a great deal of trouble; 大吵大鬧; 惹事生非 [^22]: passive-aggressive: 消極反抗 [^23]: sort out: arrange things systematically in groups or according to type. [^24]: leave someone in peace: To not bother someone or something. [^25]: refers to changes, continuous or uncontrolled growth in a project’s scope, at any point after the project begins. 範疇蔓延 [^26]: EKG: Electrocardiography; 心電圖 [^27]: buzz around: to move around quickly [^28]: take in or contain (something) as part of a whole; include. [^29]: slice off: to remove (something) by cutting [^30]: get out of: contrive to avoid or escape a duty or responsibility. [^31]: chargeback: A chargeback is a return of money to a payer of some transaction, especially a credit card transaction. [^32]: repeatedly ask (someone) to do something [^33]: go off: (of a gun, bomb, or similar device) explode or fire. [^34]: having or showing no skill; clumsy. [^35]: get up to: be involved in something, especially something illicit or surprising. [^36]: eat the seed corn: a desparate measure, since it only postpones disaster. [^37]: deprive of: to take (something) away from (someone or something) [^38]: wind up: to bring to a conclusion [^39]: To cease doing something; give up: [^40]: shoddy: Of poor quality or craft.