程式者的胡言亂語

pageicon 星期一 十月 05, 2009

當時程延遲之後

在上一回中我們探討了時常被低估所需時間的工作類型,像是測試及修正所需的時間、以及需求變更可能造成的時程變化。另外,我們也提到了開發時程規劃中可能暗藏的不穩定因素,例如程式員為了讓表面上如期完成而暗藏在系統中的地雷,以及身兼多個開發專案中工作的程式員,很容易因為某個專案的工作延遲,造成了其他專案同步發生延遲的情況。雖然許多人都會透過加班來試著解決專案延遲的問題,但它終究非最佳良方。增加人力是個可行之道,但應該愈早加入愈好,因為專案的新成員總是需要時間適應上手。而事實上,每個專案成員都應該在專案有可能延遲的訊號時,提前讓專案經理以及所有成員都意識到,並且讓專案經理有機會開始規劃因應之道。

接下來,我們要談一個最現實的問題,倘若加班以及增加人力都無法挽救時程的延遲時,那麼專案該怎麼進行下去?是呀,專案總得進行下去。軟體開發的故事,大多都不是童話故事。或許經過專案經理以及所有團隊成員的努力,專案仍然無法準時在期限內完成,但這不百分之百意謂著這是不努力的結果,例如或許只是被意外的事件所擊中。

即使專案因為人為的疏失而造成了延遲,但延遲總是無法逃避的事實,與其在專案尚未結束之前便開始檢討,或者更負面的說推託責任,不如試著面對專案即將或已經延遲的事實,試著降低延遲所造成的傷害,這才是有正面意義的做法。我曾在一個專案會議中,聽到客戶指著專案經理說:「你倒說說看,因為這樣子而造成專案延遲了,究竟是你們的錯還是我們的錯呢?」專案經理很平和的回答:「現在討論究竟是那一方的過錯,對於讓系統上線也沒有太大的幫助,如果真的非得是某一方的過錯,那就算是我的錯好了,讓我們繼續來討論下一個待解決的問題吧!」很多人在專案面臨延遲時,時常會不知所措,便急著釐清責任甚至是劃分界線,確保專案的延遲責任與自己無關。但他們都忘了,讓系統上線或是讓產品交付才是最重要的事情。

有名的eXtreme Programming認為,軟體專案有四個重要變數中:成本、品質、時間和規模,想要調整其中任一項,就必須連帶跟著調整其他的變數。好比,你希望規模變大(例如希望擁有更多的功能),那麼你可能可以選擇延長時間、提高成本(例如投入更多的人力)、或者在不改變時間及成本的情況下降低品質(當然,很少人會選擇降低品質這個選項)。如果維持同樣的規模,你希望縮短時間,那麼就大概只能提高成本來達成了。事實上,eXtreme Programming的看法和現實情況也差相彷彿,但還是有不少人無法看清現實。

相信大家都有經驗,自己的客戶或老闆於專案進行中,期望在維持原時程的情況下,持續的擴增要開發的規模,但卻也沒有增加相對應的人力。於是,專案執行的結果,不是時間超出了紋風不動的期限,就是品質低落導致遲遲無法結案。想要更動這四大因子中的一項,卻又期待其他因子不跟著連動,簡直是很難做到的事情。事實上,這四個因子中,時間和規模相較於成本及品質,是比較好控制的兩個因子。

所以,當規模增加時,得投入更多的時間,而當專案可能會延遲時,倘若時間是完全不可動搖的項目,例如系統上線日已經確定,相對應的活動也無法再更改,那麼想要準時的上線,削減系統規模雖然是逼不得已,但也應該是最有效的手段。

每個人都希望系統上線或產品發佈時,能夠完成所有規劃的功能,但是受迫於既定的時程,對於系統或產品的功能勢必就得有所取捨。當你決定透過削減規模來追求如期的上線或發佈時,你必須試著逐一的評估所有未完成功能的重要性。對某些人來說,每個功能的重要性都是五顆星,所以沒有一個功能可以被削減掉。但是,這麼想其實無濟於事。你必須試著以中性的角度來思考,究竟那些功能是真正不可缺少的功能,這樣子的功能可能是系統運作完全不可缺少的,也有可能是你的系統或產品所要強打的、可以與其他系統或產品建立市場區隔性的功能,這類的功能我們稱為「必備(must have)」的功能。相反的,有些被歸類為「有的話更好(nice to have)」的功能,這類的功能的存在,或許是讓使用者的操作流程更為流暢,或許是提供更貼心的作用,但無論如何,少了這樣子的功能,使用者並不會覺得系統殘缺了一大塊。所有的功能都可以依據它究竟有多麼的重要來一一的排定其優先順序。而你可以依據這個優先順序,逐一的刪除掉最不重要的功能,直到你認為這些未完成的功能得以如期完成為止。

區分各個功能的重要性,以及逐一將它們從系統功能清單中移除並不是難事,難的是要接受必須採取削減系統規模的事實,尤其是對付錢買單的客戶而言更是如此。對承接外包開發專案的團隊而言,客戶付的是固定的價碼,希望得到的也是他們所預期得到的系統。在這種情況下,開發團隊需要做的便是試著和客戶溝通協調。對開發團隊而言,希望爭取的是在首次上線日期無法更動的情況下,分階段來完成承諾客戶完成的東西。開發團隊可以試著讓客戶明白專案開發進度不符預期,以及之所以超出預期的原因,爭取客戶的諒解,並且溝通當不更動這上線日期的情況下,勢必削減系統規模的事實(因為通常在此時,加入新的人力已經緩不濟急)。所承諾客戶的系統功能,並不是不交付,而是分階段交付,先讓客戶能夠正式讓系統營運,之後再分批補足其餘的功能。專案到了這種情況,其實客戶和開發團隊已經在同一條船上,系統能夠上線,雙方的壓力都能夠釋放許多,堅持一定要在勢必延遲的時程下完成所有的預定範圍,有時便會顯得過於意氣用事,最後淪至雙敗的局面。事實上,即使上線的系統不夠完美,但能上線便是一個重要的里程碑。上線後,才更有機會碰觸到真正的使用者,得到更多來自於使用者的意見回饋,很多時候,更會發現原先還未實作的功能,其實根本反而是多餘的。

對於自有產品或系統的開發,雖然不需要跟外部的客戶溝通,但仍然少不了與內部客戶溝通的過程。其實自有產品、系統的開發多半比較有彈性
不論是系統規模或時程。但面對不可更動的產品發表日或上線日,說服內部客戶削減系統範圍是比較明智的做法。事實上,有時候這也讓內部客戶以及開發團隊重新思考每個功能存在的必要性,畢竟經歷過一段時間的開發,不論是內部客戶或開發團隊,都對即將問世的產品或系統有了更深一層的了解,在去蕪存菁的情況下,反而可以濾掉原先所設想的系統範圍裡,其實不是那麼必要的功能。

開發過程受到意外的干擾或者估計的誤差導致時程延遲,有時難以避免。但面對牢不可變的完成日,最好的解決手段便是試著縮小系統範圍。在縮小系統範圍的過程中,最重要的工作便是和客戶協調,爭取客戶的認同,最終還是有機會如期的交付一個可以接受的版本。

開發時程的預估(2)

在上一回中我們探討了預估時程的量化方法,想要透過量化的估算方法來預估軟體的開發時程,那麼收集團隊開發的相關歷史資料就成了一個很重要的工作。依據過去的經驗累積,是我們得以估算新的開發工作究竟需要多少時間及資源來完成的重要參考。我們也提到了,技術上的風險是時程估算的不確定因素,應該要盡量的降低每個開發專案裡的技術風險。此外,我們也建議每個工作的估計時程,應由專案經理和每一項工作的執行者一同討論進而決定下來,並且藉此取得執行者對工作時程的承諾。而緩衝時間的設置,也是專案經理時常用來保護時程的一個技巧,但由於自我實現的預言所故,最好不要為個別的工作設置緩衝時間,而是將緩衝時間留給整個專案本身。

在軟體開發時程的規劃上,許多團隊時常會低估測試以及修正所需的時間。這也是導致產品延遲交付的常見原因之一。這或許是因為當完成了程式碼撰寫的工作後,系統看起來也像是能夠運作了,所以人們也就認為它距離可以交付的水平不遠了吧。許多專案經理甚至會在自己的時程表中,很樂觀的估計一個很短的測試時間。事實上,許多開發專案需要的測試時間,往往不是這麼樂觀。

測試時間是軟體開發時程中很難估計的一環,許多人看待測試時間的態度,就是設下一個期限,然後預期能在期限內測試完成。倘若你能夠列出或者估計出測試案例的約略數量,那麼你或許能夠估計執行這些測試案例所需的時間。但是,在規劃進行測試的時間內,不單要執行測試,更重要的是,程式員必須針對找出的臭蟲修正錯誤。軟體的臭蟲可以依據嚴重程度來分類,有一類的臭蟲相當嚴重,因為它們的存在,擋住了你,使得你無法繼續執行之後眾多的測試案例。像發生這樣子的情況時,測試員就必須等待程式員修正錯誤之後,才有機會繼續往下測試。也就是說,在程式員修正錯誤前,測試員便有可能陷入了空轉的狀態。而程式員修正一個錯誤需要多少時間,也是不易估計的一件事。有時候解決一個臭蟲很快,有時候,即使修正一個臭蟲的方法只需要修改一行程式碼,但卻可能耗去你數天甚至數週的時間在除錯。如果這類型的臭蟲一多,那麼連能不能在期限內執行完所有的測試案例都成了問題。

此外,測試時間內要做的工作,不單只是執行測試案例而已,更重要的是驅逐臭蟲、修正錯誤需要的時間。正如前一段中所提到的,修正錯誤的時間難以估計,究竟需要多少時間來修正錯誤,其實是很難說的。接著,在修正完錯誤後,還得重新測試。除了針對原先有問題的測試案例進行驗證,確定臭蟲的確被修正之外,還得對相關的測試案例重新測試一輪,即使它們原先是正常的。這是因為,許多對臭蟲的修正動作,往往衍生了副作用,反而引來更多的臭蟲,使得原先運作正常的功能反而出錯了。整個測試的時間,便在這來來返返的錯誤與驗證過程中耗去。

測試階段的結束與否,並不是以時程表上的期限做為判斷標準,而是以軟體品質是否已達可以接受為標準。但軟體品質何時才能達到可以接受的水平呢?相較於程式碼的撰寫而言,這又更難估計了。

另一方面,倘若開發時程過於緊湊,對程式員的壓力施加過大,程式員有可能試著先完成看起來功能完整,但內部卻暗藏許多地雷的系統,以求完成程式撰寫階段,先闖關進到測試階段卸下大部份的壓力再說。這或許是源自於一種「頭過身就過」的心態,但是,「出來跑的遲早要還」。這些問題,或許暫時被隱藏著,但是在測試階段「醜媳婦總是得見公婆」。更重要的是,這些暗藏的地雷,會使得測試階段不僅拉的更長,而且更不易預估究竟會需要多少時間,因為你不知道程式員究竟埋了多少地雷在系統裡面。而這些,都是造成低估所需測試時間的可能原因。

除了測試時間會被低估之外,整個開發過程中都有可能發生需求變更,而容忍需求變更的部份,也沒有被考量進來。同樣的,需求變更可能會對時程造成的衝擊可小可大,小則訊息、圖片的修改,大者可能影響到整體架構。不同的開發方法,允許改變需求的方式也不同,估量這部份時間的方式,也會跟著改變。但無論如何,當你在考慮時程時,不應該忽略需求變更肯定會發生,而且肯定會佔去開發時程。

另外,許多專案中都會有所謂的「共用資源」。像在軟體開發專案裡格外明顯。怎麼說呢?尤其在同一家公司裡,程式設計功力較高的幾個程式員,時常會被同時分派在多個開發專案裡,一人身兼多職,這種現象很普遍,但卻是對時程規劃的一大傷害。因為同時參與多個專案的程式員,很容易成為專案的瓶頸所在。一方面是專案經理時常會高估多工下的程式員的生產力,但事實上,倘若一名程式員平均工作在兩個專案裡,那麼可以為這兩個專案分別貢獻的生產力,通常不到全職生產力的一半。那麼,同時參與兩個以上的專案,就更不用說了。此外,當多個專案中的某個專案發生了意外,「咬住」了這名程式員,原先預計在另一個專案中登場的時間點就會延遲,那麼倘若這個工作又是落在該專案的要徑(critical path)上,整個專案便會一同發生延遲。身兼愈多專案的程式員,愈有可能成為各專案中愈不穩定的因素。

那麼,當無法趕上預計的開發時程時又該如何?或許許多團隊會選擇加班,但正如前文中所提的,加班適用於偶而為之的短期衝刺,但對於較長時間的時程延遲並不適合。另外,有些團隊可能也會考慮為專案加入更多的資源
也就是加入更多的人力。不過,想要透過加入人力來解決時程問題,也不是全然的沒有負面效應。由於新加入的人力可能對這個已經開發到一半的專案不那麼熟悉,生力軍需要花一段時間才能上手,通常都不是即戰力。因此,在考量加入額外的人手時,也必須考慮到這批生力軍上手的時間。

因此,專案即將發生延遲,必須愈早偵測出來愈好。大多數人對專案時程的延遲,多半還是存在「拼拼看」的態度,於是,即使是發生了將要延遲的訊號了,仍然還是憑著一股拼勁,想要在最後一刻趕上。這固然是一種積極的心態,但也有可能造成到了期限的那一天,所有的人才發現原來時程趕不及了,而無法在其他方面進行配套的措施。事實上,專案中的每個人,在意識到自己的工作可能會有延遲時,都應該提出來討論,起碼做為一個示警的訊號,讓其他人-尤其是專案經理有更多的資訊來調整計畫,專案經理不應該是到了期限那一天才知道該工作會延遲完成。愈早查覺出工作可能會發生延遲,加入新人力的效果才會愈好,因為這麼一來便能夠保留愈多的上手時間。

除了上手時間之外,人力愈多,也會提高管理的複雜度,這是專案經理必須試著克服的另一點。

開發時程的預估(1)

在上一回中提到了不切實際的時程規劃表,大多數時程規劃表其之所以不切實際,主要是源自於兩種原因。第一種是「過度樂觀」的想法,低估了軟體開發的複雜度及高風險。第二種則是「過度侵略性」的態度,在這種態度底下,時程的訂定者多半認為訂一個高難度的時程目標,最後結果也是「雖不中亦不遠矣」,仍然可以壓縮時程,甚至提前完成。

不過過度樂觀、忽略眾多可能變因的想法,通常就是讓現實來證明專案終究會不那麼樂觀的結束。而「過度侵略性」的時程訂定態度,形同於壓榨開發者的生產,暗示著長期加班的可能性,但這運用於短期衝刺或許可用,但想要長期壓榨開發者,除非提供極好的待遇,否則很少開發者有辦法忍受,畢竟沒有人的身心皆是鐵打而成的。在長期的壓榨底下,開發者對於開發工作,很容易變得心灰意懶。研究也指出,長期加班,即使整體的工時提昇,但由於專注力下降,程式碼品質也容易驟降,導致整體生產力反而更低。

那麼,開發的時程又應如何預估呢?我們很容易可以找到許多評估的方法和技巧,例如有名的功能點(function point),便是透過將欲開發的系統拆解成若干個功能,再以各個功能所需的資料輸入個數、資料查詢個數、資料輸出個數、檔案個數、外部界面個數做為參數,帶入一個計算的公式裡,最終可以得到系統規模的評估值。理想的情況下,我們可以透過換算,知道需要多少工時,也就可以做為預估時程之用。

這類量化的方法看似迷人,因為開發時程的預估始終都是管理上讓人很頭痛的一件事情。人們通常對數字有一種近乎迷信的心理心素,時常認為計算得出來的總比隨口喊出來的來得可信賴。事實上,量化的方法的確有其可用之處,但倘若要提昇預估的準確程度,還是得倚賴開發歷史資料的收集。

CMMI Level 2裡有個流程領域叫做度量與分析(MAMeasurement
and Analysis
)其中便包含了要針對開發過程收集相關的度量值,並且進行分析、記錄以及溝通。

為什麼需要收集歷史的資料,是因為每個團隊所開發的系統類型不同(例如,商用的ERP系統和線上遊戲系統就有很大的不同)、開發團隊的成員組成方式及素質也不同(事實上是,每個程式設計者的能力都不同),而量化的估算方法裡,通常都有許多要代入的參數,而這些參數都必須從開發的歷史中去得到。事實上,我甚至認為歷史的記錄比起估算的式子本身更重要,因為它基本上是保留了過去的經驗值。平常我們所謂「空口估時程」,其實也是依據我們隱性的過去經驗來「開出價碼」的。當然,明確的將開發歷史記錄下來,更有助於日後新的開發專案預估時程的參考及類比之用。

此外,即使有了過去的經驗值做為參數,想要更準確的預估時程,必須降低各種風險。專案中會發生的風險有很多類型,其中技術風險時常會被低估。

開發專案中之所以會有技術風險,有一部份原因是因為有些技術上的不確定性存在,而充滿不確定性的開發項目,是很難從過去的經驗中知道究竟會需要多少時間來完成的。例如,在你的專案裡,需要一個影像處理的引擎,而這個引擎對於效能還有效果,都有一些必須達成的目標。因此,這個引擎有一些演算法上必須克服的困難在,你或許得持續嘗試、研究,才能得到符合需求的引擎。但究竟需要多少時間來嘗試及研究,沒人說得準的。或許你可以在時程裡估計一個時間,但實際上需要多少,都只有做了才知道。倘若這種高度不確定的工作項目成了你開發時程裡重要的工作時(例如深深影響到主時程時),那麼其實你對最終完成時間的估計,也是同時有著高度不確定性的。

對負責這種工作的程式設計者,事實上不能在時程上過於苛責。因為專案管理者所預估的時程,時常原本就是一種沒有根據的估算(或許是從期限倒推回來),既然是你估不準的,又怎麼能怪罪別人沒有實現一個沒估準的期限呢?

專案中的工作倘若技術上的不確定性低,那麼就容易從歷史上的經驗預估,發生出乎意料之外結果的機會也相對較低。因此,應當是盡量不要把不確定性高的工作擺入一個期限要求嚴格的專案中,針對不確定性高的工作項目,最好成為一個獨立的專案,令其帶有實驗性質,而不對其設定過度嚴格的完成期限。也就是說,會被擺入專案中的工作,盡量都是已經驗證過技術可行性的工作,那麼不確定性可以降低,對於時程的估計也就可以更準確些。

除了怎麼估計之外,另外究竟是由誰來預估專案中的每一項工作需要的時間同樣也是一個議題。最好的情況,應該是由專案經理和每一項工作的執行者一同討論進而決定下來。許多專案工作的時程安排,都缺少了執行者的承諾。這會造成一個問題,就是專案經理單方面的認定這個工作應當在某個時間點完成,但執行者卻沒有承諾他可以完成。在這種情況下,倘若不能如期完成工作,責任究竟是專案經理還是執行者呢?我想,恐怕不能片面的歸疚於執行者。雖然從傳統的管理觀點來看,管理者交代工作規定期限,執行者赴湯蹈火也應該要在這期限內完成,倘若工作不能如期完成,那自然是執行者的問題。可是,軟體專案的工作有其獨特之處,程式設計工作的時程許多時候充滿了不確定性,即使是執行者本身所預計的時程,都有可能發生不少誤差,何況或許不那麼了解工作本質的專案經理呢?因此,最好的方式,便是時程的訂定者(專案經理)和執行者一同討論,一方面讓執行者更清楚的明白工作的內容,另一方面則是同時了解執行者所預估的時間,判斷是否有必要調整對專案時程的安排。

在「過度樂觀」或「過度侵略性」的時程規劃之外,還有一種「過度保守」的時程規劃。為了面對充滿不確定性的開發,時程的訂定者,可能為每一項工作以及專案本身都加上了「緩衝時間」,也就是說,倘若一項工作預估需要十天,但緩衝的時間是百分之二十的話,就會將這個工作所需的時間拉長到十二天。加上了提供保護作用的緩衝時間,那麼看起來專案應該更有機會如期完成了吧?很可惜的,我看過的很多實例,緩衝時間都沒有如預期的發揮其作用。原因便在於所謂「自我實現的預言」的現象。你可以仔細回想你的經驗,專案中的工作是不是很少會提前完成呢?倘若時程比較寬裕,執行者會用比較鬆馳的心態來看待時程,即使是準時完成了工作項目,但最終還是耗光了時間。這麼一來,緩衝時間不僅不能保護每個工作項目,甚至還浪費了生產能力。

針對專案管理中緩衝時間的設置,「制約理論(Theory of ConstraintsTOC)」主張不個別為每個工作項目局部地設置緩衝時間,而是將可用的緩衝時間全部留給專案本身。個別的工作項目可以將時程擬定的稍緊,甚至機率上允許發生延遲,但由於專案本身設有緩衝時間,可以為專案中發生延遲的工作項目提供保護作用。

不切實際的時程規劃表

對程式設計者而言,倘若可以自由自在的、在沒有時間壓力的情況下來撰寫程式、開發軟體,那肯定是相當美好的一件事。但是,在大多數現實的條件底下,軟體的開發,不論精細與否,都有其進行的時程規劃
而其中最重要的,當然是每項工作完成的時間點。有時我們將工作完成的截止時間稱為deadline,從字面上去解讀,那就是「死線」。這字面上的意義彷彿告訴我們,截止的時間就好比在時間軸上劃下一道線,越過了這道線,也就是超出了這個理應完成時間點,那就只有死路一條。

在我們當中的大多數程式設計者,他們的開發生活幾乎可以說是大大小小的各種工作的「死線」所交織而成的。這種無時無刻不在與時間壓力博鬥的工作,有時難免多少減少了幾分程式設計者對程式設計工作的喜愛。

但軟體專案的開發,卻又缺少不了對每項工作的時間起迄規劃(專案的本質就是有固定的開始及結束的時間),不可能在完全沒有時間規劃的情況下進行。事實上,開發時程的擬定與規劃,也一直是軟體開發與專案管理的諸多議題中相當重要的一個,因為它關係到開發專案是否能夠準時如期交付。

在我們的印象裡,似乎滿大比例的軟體專案都無法如期交付,延遲交付似乎是軟體開發專案的常態。而大多數的情況下,當軟體延遲交付時,程式員通常都會成為眾矢之的,擔負起延遲交付的責任。因為,在許多人的認知裡,程式員是開發專案最主要的執行者,他們所撰寫的程式碼則是專案最終的產物,當這個最終的產物無法如期完成時,當然是程式員要負最大的責任。程式員或許偷懶、或許能力不夠,才會無法依照專案的時程規劃完成工作。

或許現實之中,真有一些例子是因為程式員偷懶或者能力不足才造成專案時程的延遲。但以我自己的親身經驗看來,專案時程的延遲,通常都是發生在不可歸疚於程式員的環節之上。

專案時程的延遲,有一個很常見的原因是,時程本身就有問題。許多軟體專案的完成時間規劃,並不是從究竟有多少資源、以及究竟要完成那些工作來進行的。它們通常是已經先假定了必須完成的時間,以及要完成的最終產物,再回過頭來展開其中需要完成那些工作,依照可運用的人力,填入每個工作需要被完成的時間。這種我稱為倒推法的時程規畫方式,要完成的最終產物,以及必須完成的時間,幾乎都是不可以改變的,但資源是有限的,倘若可運用的人力看似不足以在期限內完成時,那又要如何呢?無疑的,你得做些調整和改變。

許多人選擇改變的,並不是最終的產物(也就是縮減開發的範圍)、也不是完成時間,而是壓縮其中工作的完成時間,以便在完成一份能在完成時間結束前,圓滿的達成所有工作的時程規劃表。但問題便出在,其中的工作所需的時間為什麼能夠壓縮?原先預估撰寫一個功能需要十天,為什麼專案經理大筆一揮,把它壓縮成六天,它就能夠變成六天呢?這就是一種過度的樂觀,相信「拼一下」應該就沒問題。你或許可以在專案當中「拼」個幾個工作,但很難從頭「拼」到尾。

當專案經理完成一份洋洋灑灑、編排美觀-而且最重要的是,在預期的期限內結束的時程規劃表時,好似他的工作已經完成,接下來的責任就交給每個工作的執行者了。這樣的時程規劃表不過只是粉飾太平的一份文件,因為它所呈現出來的,只是一個假象。時程規劃表是專案中所有成員所賴以依循,做為導引專案前進之用的一份文件。但,倘若這規劃表裡,充滿了太多對工作時程能夠壓縮的樂觀態度,那麼這樣的文件還有什麼參考價值呢?我們常說照表操課,但可惜的是,有許多人的專案,實際執行的情況,和時程規劃表往往是兩回事,其中最重要的原因,便是這張表本身就無法被執行。

完成一份務實的時程規畫表,對於專案能否如期完成是相當重要的一件事。而一份能實際被使用的時程規畫表,應該要取得專案參與者(當然包括程式員)的承諾。也就是說,專案參與者必須明白他究竟在這個專案中會有那些工作,每個工作他自己是否能夠承諾規劃表裡所假定的完成時間。我們可以看到許多時程規劃表,不過只是專案經理自己一個人的一廂情願,並沒有適度和所有參與的成員溝通,並且取得所有成員的承諾。許多程式員都是被告知工作需被完成的時間點,他們沒有機會表示他們對於時程的看法。但不顧工作執行者對時程的看法,無疑的只是讓這份時程規劃表距離現實更遙遠,愈加的不可執行罷了。我們可以想想,我們要一份不可執行的時程規劃表做什麼呢?

當專案中的工作發生延遲時,很少人歸因於完成期限本身就有問題,而多半認為問題出在執行者身上。但充斥著不合理的完成期限的專案,最終又怎麼有可能如期完成呢?

許多專案經理會樂觀的認為時程可以壓縮,是因為他們相信「加班」這個秘密武器。倘若壓縮後的時程真的趕不及,那就讓程式員們加班吧。每天加班四小時,就等於就多出了原先一半的時間,對於時程,他們當然有樂觀的權利。程式員可都是渾身熱血的動物呀,只要燃燒起來,沒有什麼不可能的。可惜的是,研究指出,長期加班的程式員,其實際的生產力反而比不加班還要糟。雖然工作的時間或許拉長了,但是,每個單位時間能夠產出的有效程式碼卻降低許多。

很少程式員在經歷長期加班的工作後,能夠不感疲累的吧?拖著疲累的身驅及大腦撰寫程式,反而更容易出錯。程式員花了更多的時間,卻無法寫出更多有效的程式碼,這簡直是賠了夫人又折兵。

加班這個武器不是不能用,而是得用在刀口上。加班不適合長期為之,但偶而用於短期衝刺,還是有其效果。但總的來說,對程式員的工作時間安排,應該還是稍微放鬆一點,這有助於產出更良好品質的程式碼。適度的降低對程式員的時間壓力,程式員會拿更好的程式碼來回報的。

開發軟體,必須學習面對現實的時程。而時程也是最現實的,因為無論你有多樂觀,它仍然會忠實的反映它應該要有的面貌。我曾參加過一個嚴重延遲的專案,專案經理為了迎合客戶的心理,刻意的又編排了一個樂觀的時程表,希望可以少受點客戶的責難。當時技術的最高主管看了這一份時程表後說道:「我們又何必自欺欺人呢?」的確,編寫一份不切實際的時程表,只是註定再次延遲,無助於專案準時交付。還不如面對現實,讓大家都相信時程表中規劃的時間,的確都是可以準時完成的,這麼一來,所預估的專案完成時間也才會更合理,更有機會被達成。

pageicon 星期一 七月 06, 2009

在Android上撥放SHOUTCAST MP3 stream

Android (我使用的是1.5)透過一個叫做android.media.MediaPlayer的類別來提供撥放串流影音或本地端影音檔的功能。不過,眾所皆知的,它支援的串流協定以及codec,相當的有限。我想,這一點在現在及未來,肯定會受到相當多開發者的注目以及戮力加強。


本文提到的是解決一個特定問題的方式,想解決的是在Android上撥放SHOUTCAST MP3 stream。許多網路音樂串流都是採用SHOUTCAST MP3 stream的方式,但即使Android支援了HTTP以及MP3,而且SHOUTCAST MP3 stream的內容幾乎就是MP3 stream,但透過內建的MediaPlayer,你仍然無法撥放。這原因當然是因為MediaPlayer沒有處理SHOUTCAST,即使SHOUTCAST的協定和HTTP是那麼的相像。


由於我才接觸Android數日,可以說是對Android還相當的陌生,不知道除了走原生程式碼這條路外,還有沒有別的方法(之前有想過,直接處理SHOUTCAST協定再自行decode MP3,但似乎沒有內建的MP3 decode介面,或許有Android高手可以指點一下),所以設計了一個機制,在不寫任何原生程式碼的情況下,讓MediaPlayer能處理SHOUTCAST MP3 stream


這個機制的核心想法是這樣樣子的 放置一個HTTP proxy介於MediaPlayerSHOUTCAST server之間(當然HTTP proxy也跑在你的Android應用程式之中),這個HTTP proxy一手接收MediaPlayer的單純HTTP請求,另一邊則扮演一個SHOUTCAST client,接收SHOUTCAST server回傳的內容,並且依據SHOUTCAST協定,將回傳內容中的MP3 stream剖析出來,回傳給另一邊的MediaPlayer


今天實驗了一下,這個機制的確能夠讓MediaPlayer撥放SHOUTCAST的網路音訊串流。大抵的精神如上所描述,不過細節處還不少。最重要的大概就是怎麼處理MediaPlayerHTTP請求。MediaPlayer基本上是兩個請求就搞定,一個是HEAD一個是GET。透過HEAD它可以判斷究竟是否支援,再透過接下來的GET取得真正的內容。當然,針對這兩個請求,Content-Type都會是audio/mpeg,而且千萬不要忘了(或故意不)提供Content-Length(因為是串流,所以,請給個超大的值吧),否則MediaPlayerprepare的時候就會失敗了。

把對母乳媽媽的感謝與支持傳出去

« 十一月 2014
星期日星期一星期二星期三星期四星期五星期六
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
      
今日

Search this blog

Links

Weblog menu

Today's referrers

Feeds