1 概述
軟體類專案具有一些與生俱來的複雜性,因此在整個產品生命週期中,往往由於一些環節的處理不當,而造成了進度延誤、BUG較多,甚至專案失敗的後果。相比之下,網際網路類專案除了本身就是軟體專案之外,又具備更多的環節、需要更多的互動。因此,網際網路專案在產品週期中,更容易出現問題。
一個專案週期可以大致分為這幾個階段:專案規劃、需求分析、軟體設計、軟體開發、軟體測試、軟體釋出,系統運維。而在現代軟體(尤其是網際網路)專案中,這幾個階段已經不是十分清晰地劃分開來,而是通過所謂“迭代”的方式迴圈前進。儘管專案週期的幾個階段並不能夠完全獨立地劃分,但是每一個階段都是缺一不可的,對任何一個階段的過於草率甚至忽略將會帶來嚴重後果。
關於軟體開發過程,有很多相關的書籍有詳盡的描述。事實上,過於遵循嚴格的流程定義,也會適得其反,尤其是對於較小的團隊。如何能做到最大程度的“敏捷”,應該是一個小規模團隊的追求目標。本文將針對網際網路專案的幾個重點環節,依據已有的一些經驗,為軟體技術(網際網路)類的專案開發提供一些參考性的思路。
2 前瞻性和細節:關於專案規劃和需求
2.1 專案規劃
在專案開始之前,一個規劃的過程是不可缺少的。規劃包括技術方面和非技術方面,對於不同型別的專案,這二者各有側重。對於大多數專案來數,技術是次重要的。
在這個過程中,有幾個主要的事情需要完成:
明確專案目標:沒有一個明確的目標,任何專案都無法避免失敗的命運。雖然,在專案的進行過程中,目標是會不斷地調整,但是,必須在專案初期確立主體目標。也就是說,要明確地描述出這個專案將要做成什麼樣子,依靠哪幾個關鍵點來贏得使用者。儘量通過最簡略的語言描述專案目標,如果做不到,或許是對於專案的考慮還不成熟。
往往,很多團隊已經小有規模,但是專案目標仍然在不斷調整,這實際上是一種無奈之舉,因為之前的工作沒有做到位。這種情況會產生很多負面影響,無論是對於成本,還是團隊士氣。因此,對於專案目標的規劃,應具備足夠的前瞻性。
競爭對手分析:當前的環境下,已經很難找到一個完全沒有其他人蔘與的專案(如果有,可能說明了這個專案沒有價值)。而對於網際網路專案來說,瞭解競爭對手的成本是相對較低的。作為使用者,去體驗競爭對手的網站,可以獲取第一手的資料。去發現對手做得好的以及不好的地方,可以為自己節省大量的時間。
發現優勢和劣勢:每一個商業模式,都是由幾個環節組成的。首先要明確,對於團隊來說,這幾個環節是通暢的。進一步,要考慮對於哪些環節具有優勢,這些優勢將是帶來商業利益的關鍵點。對於劣勢環節,則要考慮如何去克服。在專案規劃階段,對於優勢和劣勢的分析,要儘量避免樂觀思維。
技術選型:儘管不是最重要的,不過技術選型依然是在專案規劃階段要考慮的。系統所執行的平臺,開發工具和語言,第三方程式的成熟度。基於專案目標,對這些方面進行初步的分析,理想情況是,儘可能利用現有的東西,尤其是開源產品。另外,工具和語言的選擇要考慮人員招聘的需要。
2.2 需求分析
角色定義:“產品經理”-負責完成需求分析,輸出技術團隊所需要的需求規格,並跟進專案的開發、運營過程。
產品經理的角色非常重要,尤其是對於網際網路專案。首先,對於專案團隊來說,產品經理代表了“使用者”,通過日復一日地使用自己的產品,調研使用者的需求,對產品進行不斷改進。另外一個方面,產品經理充當了技術團隊和非技術團隊之間的橋樑,他們需要把非技術團隊的需求轉換成技術化的語言傳達給技術團隊,起到兩者之間“潤滑劑”的作用。
首先,產品經理需要關注產品的“核心能力”。沒有一個產品可以做到面面俱到,產品經理需要找到最能夠滿足使用者需求的核心點,並將其發揮到極致。這種滿足了使用者需求並做得極致的核心點,最終將成為口碑,併為使用者所傳播。
其次,產品經理需要對產品的運營保持敏感。通過對統計資料的持續關注,通過在產品論壇上了解使用者的反應,產品經理要能夠及時瞭解到產品目前的發展走勢,並以最快速度做出調整。
然後,在產品的互動設計方面,尤其是網際網路專案,產品經理要把自己當成“最笨”的使用者來看待自己的產品,選單的設定、按鈕的擺放、提示語的位置等等,如何讓使用者能以最簡單、最快捷、最不需要動腦筋的方式使用產品,應該是產品經理追求的目標。
另外,關於產品經理的素質,產品經理為了做好產品設計工作,除了對產品的感覺之外,需要有一定的技術功底,例如對頻寬、伺服器效能、WEB標準等方面應有一定的瞭解。對於細節的極致追求,也應該是產品經理應具備的特質之一。
小故事:巨人網路的史玉柱,號稱自己大部分的時間都花在遊戲上,有一段時間他甚至親自作為客服人員,直接傾聽來自使用者的反饋。騰訊的馬化騰,自從05年之後就從管理事務中脫身,把自己更多地當成“首席產品體驗官”的角色。常常在凌晨時分,他會把對產品的意見傳送到負責產品經理的郵箱裡。
3 差異化思維和迭代開發:關於設計和開發/測試
3.1 系統設計
不同型別的產品,不同的開發平臺,設計思路有非常大的區別。本文不會就具體的軟體設計做討論。這裡想重點強調的一點是系統設計中的“差異化”思維。
舉個例子,一個西餐廳,平常的客流量基本上是穩定的,但是在情人節等特殊的日子,客流量會有一個突發性的增長。有什麼辦法可以解決這個問題,即使在忙的時候,也不能讓客戶過長時間的等待。另外一個例子,盛夏時節,使用者家裡的空調壞了,維修需要3天時間,作為售後服務方,應如何應對。
這些問題的解決思路,實際上在於如何進行合理的差異化設計。一個熱門的網際網路應用,在繁忙時間段(例如週末、晚間),會出現頻寬、伺服器資源緊張的情況,這個時候網路丟包、操作響應變慢,影響使用者體驗。更嚴重的情況下,當負荷超過閾值,出現雪崩效應,基本上處於無法服務的狀態。
所謂的差異化設計,即要根據業務的本質,對產品所提供的服務按照一定的粒度劃分層次,什麼是基礎服務,什麼是增值服務;什麼是必須滿足的服務,什麼是錦上添花的服務。舉例來說,對於一個即時通訊業務,傳送文字類訊息是最基本的,而魔法表情、虛擬形象則是增值服務。在合理地對業務進行了劃分之後,就可以在不同情況下作出取捨。系統和頻寬空閒的時候、資源緊張的時候,系統出現故障的時候,在不同的情況下,系統的設計要能夠支援劃分的業務單元按需要進行組合和取捨。
對於業務單元的劃分,也可以從另外一個角度來考慮,那就是使用者的“憤怒”指數。對於一個具備十幾項功能的服務,某幾項功能出現問題會使使用者覺得無關痛癢,而另外幾項則會使使用者暴跳如雷,甚至有幾項出問題會使使用者發誓永遠不用你的服務。通過對不同功能的憤怒指數進行設定,也可以得出層次化的劃分。
當系統、IDC、網路出現問題的時候,要優先保證最基本的、也就是憤怒指數最高的功能。當問題逐漸升級,功能要逐層取捨。這是在系統設計需要考慮的問題。
回到西餐廳的例子,在業務空閒的時候,餐廳提供的服務可能包括熱毛巾、個性化選單、豪華餐具,甚至跪式服務。而在繁忙的時候,為了能夠提高流轉速度,餐廳可能需要一份特殊選單,這份選單上沒有過多的選擇,只能像做選擇題一樣,選擇情人節套餐A,B或者C。對於修空調來說,空調的維修需要3天,這個是無法更改的。但是,我們在維修的同時,是否可以為使用者提供一個風扇,緩解目前的狀況。一切方法是為了降低使用者的憤怒指數,而網際網路產品的差異化設計的目的也是一樣的。
另外一個需要在系統設計時考慮的重要問題是“可擴充套件性”(scalability),也就是說當系統的壓力持續增加時,需要能夠通過擴充套件硬體來達到容量的提升。理想的情況是線性擴充套件,也就是硬體的增長和使用者壓力的增長是成線性比例的。但是,大多數系統是做不到線性擴充套件的,更差的是,很多系統在設計的時候完全沒有考慮“可擴充套件性”,從而無法突破單機的效能極限。
現代的網際網路系統基本上都是“分散式”的,把系統劃分成前端顯示層、業務邏輯層、資料儲存層等幾個部分,在各個部分能夠進行不同策略的負載均衡。例如資料庫可以採用主從備份和均衡、資料分片等方案,WEB前段可以使用squid/nginx等進行負載均衡,甚至採用DNS全域性負載均衡等方案。
3.2 開發和測試
網際網路是一個快速變化的世界,我們所面臨的使用者、環境每天都在改變,這就要求專案的技術團隊能夠適應這種情況,要能夠做到“快速迭代”。不同於傳統的軟體專案,動輒幾個月甚至幾年的專案週期,網際網路專案通常是以周為單位進行迭代。
在大多數情況下,一個網站在應付日常的特性修改的同時,也在醞釀大型的版本升級。因此,技術團隊負責人需要對版本進行很好的規劃。在開發過程中,藉助SVN等版本管理工具,對主線版本和分支版本進行管理,保證日常的BUG修復可以歸併到主線版本中。對於需求文件、設計思路、BUG記錄等,則可以借用WIKI等工具。通過快速原型的構建,使得產品經理和其他內部客戶能夠儘早地體驗系統功能,及時發現問題和明確方向。
開發團隊應當在工作中逐步總結出編碼規範,例如,HTML/CSS製作規範、PHP/JAVA程式設計規範等等。這裡要特別強調的是,網際網路應用中的安全問題是非常突出的,這方面需要在開發過程中特別關注。常見的網際網路安全問題包括:跨站指令碼攻擊、程式碼注入、緩衝區溢位、SQL隱碼攻擊、許可權驗證漏洞、第三方系統漏洞等等。
根據專案的大小不同,測試團隊的規模相差也很大。有些專案需要和開發團隊人數相當的測試人員,而有些團隊的開發人員則兼任了測試的職責。在專案的發展過程中,應儘量對一些基礎功能製作自動化測試工具,並不斷完善測試用例。這樣測試團隊可以把更多精力投入到新功能的測試中,而不是每次版本釋出都在對已有功能是否被破壞而感到擔心。
從管理的角度來說,如何使開發和測試人員熱愛自己所從事的產品工作是非常重要的。往往,很多專案都是產品經理和管理層在推動,技術團隊只是被動地完成任務,並不斷有抱怨產生,這樣的專案是不健康的。技術人員同樣要成為產品的主人,要具備相當高的主觀能動性來投入工作,把所開發的產品看作是自己的孩子般關心和愛護。
4 規範化操作和成本控制:關於釋出和運維
4.1 系統釋出
系統釋出是指將版本開發完成的系統在生產環境進行部署。對於一個網站來說,系統釋出可能是非常頻繁的。系統釋出需要有嚴格的釋出規範和工具來支援,否則釋出錯誤,版本回退等問題會經常出現。
對於靜態內容的日常更新,需要CMS系統來支援。CMS可以使用一些通用的系統,也可以針對自己的應用來定製開發。無論是哪種實現方式,一定要把日常更新和程式釋出分開,否則產品和運營人員每次更新內容都需要勞動開發人員進行程式釋出,將是非常低效和容易出錯的。對於CMS系統的建設,需要對內容的結構和後設資料的規劃給予足夠的重視,在這個階段的投入將對今後的可擴充套件性和介面的靈活性起到決定性的作用。
對於程式的釋出,也應當有自動化的工具支援。尤其是要支援“版本恢復”功能,也就是一旦新發布的程式如果出現問題,應該立刻能恢復到之前的穩定版本。因為,在網際網路專案中,測試不充分的事情時有發生,而且正式環境和測試環境也差別很大。系統釋出後出現問題的概率也較大,這個時候就需要“版本恢復”這樣的功能來保證網站的正常執行。
對於大型的網際網路應用,“灰度釋出”也是較常採用的方式。由於對新開發的功能的效能、使用者接受程度等沒有百分之百的把握,在這種情況下進行全量釋出則風險太大。為了既不影響產品的正常執行,又能夠對新功能進行生產環境下的測試,可以採用灰度釋出。所謂灰度釋出,即僅針對部分使用者釋出新功能。劃分的依據可以有很多種,例如使用者來源區域、使用者年齡/性別特徵,甚至按照一定概率隨機選擇。一開始先用較小的比重進行灰度釋出,如果測試順利,則逐步加大比重,直到完全釋出。
在系統釋出的日常管理中,“規範化操作”是非常重要的。這需要自動化的釋出系統的支援,以及相應的管理制度來約束。
4.2 系統運維
系統運維是指系統的日常管理和維護,這包括對伺服器硬體、網路、頻寬方面的維護,以及軟體系統的日常管理。
在網際網路專案中,系統運維的核心工作是對伺服器和網路的管理。在專案開始的時候,需要進行硬體選型、網路規劃;在專案上線後,要對硬體和網路實施不間斷的監控,並及時進行調整。往往,很多開發人員不具備系統級的知識和經驗,因此他們所開發的程式經常對這些方面的問題考慮不足。這就需要運維團隊的系統專業人員給出建議。關於系統對CPU、記憶體、磁碟、網路等方面的要求,運維團隊需要和開發團隊緊密合作,來不斷完善系統。
需要強調的是,運維團隊應當具備成本意識。當網際網路應用發展到一定使用者規模後,伺服器和頻寬成本將佔據相當大的比重。在很多情況下,伺服器和頻寬資源出現不足,並不是因為使用者壓力確實已經不堪重負,而是開發和運維工作沒有做細。所謂“Every Byte Counts”,需要具備足夠強的成本意識來對待伺服器和頻寬資源的消耗。
我們常常看到伺服器的CPU佔用偏高,記憶體即將耗盡,磁碟IO非常繁忙,IDC出口頻寬曲線出現被削平的波峰。在出現這些情況的時候,要使用工具快速發現瓶頸所在。根據二八原則,絕大多數資源消耗在了小部分的功能上。抓住主要問題,針對性地進行優化將很快能夠緩解問題。
對於網際網路應用來說,有一些常見的問題和優化手段,這裡簡單列舉一二。標準編譯的apache和進行裁減編譯後的apache程式佔用的記憶體可能有上百兆的差別,在併發請求較高的情況下,記憶體使用的差異就更大。對於PHP,JAVA等開發語言,都可以進行位元組碼的快取,這樣可以大大提高執行效率,避免每次請求進行指令解釋的開銷。對於檔案和資料庫等磁碟IO比較密集的操作,應考慮不同層面的cache,從檔案系統cache、資料庫cache、記憶體cache,第三方CDN,一直到客戶端的瀏覽器cache,優化的cache可以有效地降低磁碟和網路IO,從而提高使用者體驗和降低系統負荷。
當然了,這些優化工作都是需要時間和精力投入的,始終不要忘記二八原則,關注最主要的問題。
當網際網路後臺系統規模逐漸發展到一定程度,運維工作需要和其它技術類工作(例如開發和測試)有明確的劃分,相互之間需要有明確的交接、輸出規定。運維工作中的裝置管理、網路管理、釋出管理、突發事件管理、客服管理等各項工作需要依據一定的規範來進行。對於IT系統(包括網際網路),業界常用的是SLA(服務品質協議)來作為整個運維管理的規範化參照體系。對於小規模的團隊來說,沒有必要應用過於複雜的流程規範,不過也應該把一些常用的流程明確化,並不斷改進。
5 總結
面臨這方方面面的問題和陷阱,專案團隊需要做好準備來迎接各種挑戰。最關鍵的是構建學習型團隊和溝通團隊。及時總結經驗和教訓,從而不重複犯同樣的錯誤,團隊在專案的發展中不斷學習提高。建立通暢的溝通渠道和分享機制,養成團隊成員良好的溝通習慣,分享彼此的經驗和教訓,是專案成功的必要條件之一。