雖然我不是個遊戲超級玩家,但卻是因喜歡遊戲而開始學習程式設計的(特別是影象渲染演算法)。所以當我看到john carmack在2012 quakecon上的發言時,我覺得自己該聽聽,學習遊戲設計以及開發相關的知識。
不過我所聽到的是乙個黑客在談論他的最近感悟——軟體工程事實上是一門社會科學。其中的大約10分鐘,他涉及到了人性的各個方面,比如開發人員犯的錯誤,程式語言設計,靜態分析,**評審,開發人員培訓,成本/收益分析。文中強調的部分是我加的(文字為我轉錄,如有錯誤,還請海涵)。
在嘗試讓遊戲跑得更快(我們的主要發展方向)的過程中,我們犯了不少《doom 4》中已有的錯誤。其中的一些顯然無法改變,但迫於提速的願景,不得不做。
因為這些行不通,***,兩個遊戲相隔了6年。
而後者是過去多年來我所忽視的,因為過去我把自己標榜為乙個軟體工程的科學家,處理一些抽象、證明、正確相關的事情,真的很酷。
事實上在電腦科學中,真正屬於科學的唯一事情就是演算法,優化屬於工程範疇。但是那些沒有一直開發演算法的人,大部分的時間都花在程式設計上。我們中確實有少數程式設計師在做一些優化以及挑選演算法,但是90%以上的程式設計師在編寫程式,只是為了實現一些功能。當我開始審視這一切時,發現工作中的絕大部分沒有科學、工程、正確的一面。或許,其中某個程式設計師會說,他做了很多的巧妙程式設計工作,實現了一些功能。我們喜歡把自己想象成聰明的工程師,用正確的方式去開發好軟體。但隨著我觀察的越來越多,發現這根本不是事實。
除了那些能夠評估的東西,我們用來評估和重現的工具才是科學的精華所在,有了它們,才能評估、重現,做出**並測試驗證。我們會在做優化和演算法時涉及,但所有其它事,跟科學無關。程式設計師之間的交流,甚至於與不同時期的自己交流。我們談論函式式程式設計,lambda演算,monads,這些想想就很美,但對你在軟體工程方面做的事情沒有任何影響,這些僅僅是最佳實踐而已,一些總結好的做法,但只是在阻止人們犯某些型別錯誤的時候它們才有意義。純函式式的,用最嚴苛的科學的視角寫出來的**,最後還是會轉化為組合語言,事實上你也可以用諸如basic或者其它任何語言來實現。
另一件對我有啟發意義的事情是大兒子開始學程式設計。我確實搖擺過是否應該讓乙個7歲的孩子學習haskell,最終決定不要,我不認為自己是乙個足夠出色haskell程式設計師以至於願意去指導別人。當我思考人們到底如何開始從零學程式設計時,我豁然開朗,意識到我們從軟體工程社群獲取了如此之多,事實上是一些構建在乙個核心基礎之上的由多層元件組成。當你回退到結構化程式設計,不論while迴圈,還是for迴圈,在底層,你如何解釋程式設計,計算機做些什麼,最終都會歸於流程圖(flow chart)。這種條件執行這個,否則執行那個。甚至嘗試解釋在乙個地方到底是應該用for迴圈還是while迴圈時,這僅僅關乎慣例,乙個解決人們經常犯的錯誤的慣例。但是它們不是計算機在做些什麼的核心。這些只是人們根據以往經驗總結的讓你少犯錯誤的方式。
另外一件嚴峻的事情是,程式設計師一直在不斷的犯錯。我去年談論了很多關於靜態分析方面的工作,並嘗試靜態分析我們的所有**,希望它們都能夠順利通過,可惜掃出了數以千計的錯誤。其中一些問題,我的同伴們確實是bug,並保證下次不會再犯,這種感覺不錯。如果一些錯誤沒有從語法上阻止,就可能發生。那正是我投入如此多精力到靜態分析上的原因之一。我希望能夠開啟更多嚴格的語言限制,因為我們一直在犯錯。
最近我開始做的一件事情是code review,檢視每日提交的**,找出一些典型的錯誤案例,給team成員講講。標註出一小段**,說這是個靜態分析工具掃出的bug,推薦這樣的寫法,更簡單清晰,也不容易犯錯,剛開始時有些成員對這種公開文化有些反感,不過我覺得大家現在都接受這樣的做法了。但有個問題,我看看大家都做了什麼就會花費很多的時間,更別說逐一review。能夠指出組內其他成員犯的錯,並告訴大家當心類似的問題,那才是真正的價值所在。只要組員都接受這件事,就是有積極意義的。
當你在爭論譬如是否應該在函式的引數之前加上const關鍵字時,想象一下會發生什麼。這些很難客觀地給出結論,大多數這種情況,我們稱之為快取失效,要耗費很大的精力來做說服工作。如果乙個結論很客觀,顯而易見,就不會起爭論。但是其它的很多事情涉及的只是**風格問題,你或許會說,根據多年的經驗,這會導致種種錯誤,但是很多人會回答說,我從來沒有看到那種錯誤,對於我來說那不是問題,我從來沒有犯過那種錯。這個時候能夠演示錯誤很重要,看,就是這個問題導致的錯誤。
隨著這些事情我做的越來越多,並思考相關的問題,我覺得這些不是科學,而是解決人類弱點的過程,我希望有更好的辦法來處理。我們都希望成為更好的程式設計師,開發出更好的產品,把工作做得更好,但是事實歸結為去訓練數十個人按一致的風格做事情。組內成員有進有出,不斷更迭,新人進來,看著**庫,不了解慣例規則。有更好,也有更壞的方式做事情,不過這真的很難衡量。
我的答案並非到此為止。使用nasa風格的開發流程,他們能夠交付bug率非常低的產品,但這建立在極低的生產力基礎上。你能夠做的一件事情是,分析成本/收益比值,你會說自己能開發出很棒的產品,但推出實在是太晚了。或者我們可以做得很快,領先市場,不過可能做得不大精細,不過我們會讓一些很酷的功能盡快推出。這是乙個典型的例子,合適的工具,處理合適的任務。現實中發生的是,你會很快推出很酷的產品,但會在多年內忍受它的折磨(譯者注,猜測是指維護產品)。而在這方面我覺得我們做的不是很好。
我們知道有些**將會維護十年,我告訴同事這是個好機會——你寫的**,並未與特定的遊戲強相關,或許會活躍10年,會有數以百計的程式設計師閱讀、參考、呼叫它,責任重大。在軟體的api設計層有很多問題,找出它們是項藝術,需要技藝精湛的工匠。我希望以後能夠有更多關於軟體工程藝術的內容與大家分享,我正投入很多精力鑽研其中。
譯者:李榮,搬磚碼農一枚,喜歡搬磚,喜歡設計,**潔癖患者,個人部落格:
軟工 軟體測試
軟體測試的目的 測試是程式的執行過程,目的在於發現錯誤 乙個好的測試用例在於能發現至今未發現的錯誤 乙個成功的測試是發現了至今未發現的錯誤的測試 軟體測試的原則 盡早地和不斷地進行軟體測試 由測試輸入資料和對應的預期輸出結果組成 程式設計師應避免檢查自己的程式 在設計測試用例時,應合理的輸入條件和不...
軟工 軟體維護
一 軟體維護的型別 改正性維護 適應性維護 完善性維護 三類維護佔總維護比例 維護在軟體生存期所佔比例 二 維護的問題 理解別人寫的程式困難,困難程度隨軟體配置成分減少而迅速增加 要維護的軟體往往沒有合適的檔案或資料不全 絕大多數軟體設計時沒有考慮將來的修改 軟體維護不是一項吸引人的工作 軟體人員經...
軟工 軟體計畫
軟體計畫 軟體 估計 成本收益分析 制定軟體計畫是軟體工程的第乙個步驟,其中主要是問題的定義,也就是可行性研究,第二個是專案開發計畫任務 步驟複查系統規模和目標 研究目前正在使用的系統 匯出新系統的高層邏輯模型 重新定義系統 匯出和評價供選擇的方案 推薦乙個方案,並說明理由 推薦行動方針 書寫任務計...