寫工業級別代碼是怎樣一種體驗?
看了這邊左耳朵耗子的文章,作為一個寫民用程序的程序員,對寫工業級別的代碼的體驗有深深的好奇 .文章鏈接:這多年來我一直在專研的技術
沒想到陳皓那麼年輕,想像中他的技術年齡應該要比Windows還老(
現在想想,雖然我從2000年就開始學習編程,但是我的技術其實是沒有什麼主線的。雖然我主觀意識上不喜歡弄演算法,但是我這麼多年竟然都是在弄演算法(當然不是大家熟悉的那些搜索派演算法),API就只練習了Windows API、VCL和.net framework,背誦了一點關鍵字。
不過想想這樣也好,反正API和語言是編程裡面最不需要消耗腦細胞的東西了,就應該通過大量的演算法的練習,潛移默化地掌握語言的通用技巧,好讓你在工作的時候如果突然要你背誦新的函數名和關鍵字,你也能立即上手。
回到問題上,Office應該算工業級別的代碼了吧,由此相對應的波音上面的幾百萬行C++的飛機控制系統應該算軍工級的,雖然從文件大小上來算還不夠Office的1%,但是比我們還是要屌多了。我以前看過他們做超音速戰鬥機的紀錄片,出了bug的結果就是把飛行員弄死。微軟有史以來出的最嚴重的bug也就是讓一大堆公司損失金錢。現在想想,某些行業的代碼出了bug最嚴重的結果就是讓用戶浪費點時間,現在的程序員實在是太幸福了,什麼責任感都不需要有,也能賺錢……
我寫工業級別的代碼的最大的感覺,就是自動化測試多到,提交代碼的正常結果就是被源碼管理系統自動revert。從感情上來講,我最喜歡寫的還是MSRA的代碼,這樣就什麼壓力都沒有了,愛怎麼寫怎麼寫,隨便弄個design document就可以被老闆拿去當sample,寫多幾行unit test還能獎勵京東購物卡。
陳皓這篇文章寫得挺好的。
第一次看到他相對完整的履歷。我覺得我可能到他那個年紀趕不上他吧。至於工業代碼么,其實並沒有什麼特殊之處,只是在質量上有要求而已。按照很多答案裡面說的來看,其實做晶元時候寫得那些代碼,都稱得上工業代碼了 —— 因為測試很多,而且還基本不能有Bug。但是Code Quality在我看來並不怎麼樣。所以這一點我很同意馮東的觀點,就是工業代碼實際上是對品控而不是對代碼自身的要求。但是工業代碼是有代價的,一個是很難處理非常複雜多變的工況,也就是說通用性上有缺陷,所以通常會根據具體需求進行定製;
另外一個是很難做到規模很大,比如VxWorks和飛控那已經是極端複雜的軟體了;然後開發周期長,而且很難通過什麼辦法來縮短。畢竟你要把代碼的bug數從2/10000做到1/10000可能要付出上百倍的時間來進行檢查和修正也說不準。
最後就是成本要比一般軟體貴上許多;所以如果你真要說體驗的話,那可能更多的錢是用來換Quality而不是換Feature吧,開發過程多少會更加無聊一些。我做的是鋰電池BMS系統中的電池容量演算法和主控IC function,而且很多都是出口的。這個IC是和電芯組合成一起作為電池Pack裝到手機/筆記本里的,所以在整個電池使用的三五年中程序必須正常運行不出錯。因為鋰電池容量演算法特別複雜,稍有參數、代碼錯誤表現的就是iPhone或筆記本電腦立即關機。在筆電上還好說,因為有對IC的DFU/IAP支持,之後升級/維護方便;但在手機上並無此功能,如果錯了就可能面臨出口產品的退貨/召回、工廠IC的code重燒等,非常麻煩。
因為主IC還是C51平台、在Keil上編程,調試或排查極其不便。特別涉及到容量演算法,必須用鋰電池去充放電實測來檢驗演算法的精度與異常處理,通常調一次參數就需要高溫低溫常溫+輕載重載中載組合測試,需要一周時間。效率極低,而且出錯概率大。僅靠經驗、拼人品顯然是不可能做下去的。
之前採用了matlab進行模擬,但由於代碼和KeilC的語法完全不同,故達不到代碼debug的效果。為此,專門在知乎上請教了輪子哥和趙姐夫,開始搭建C++模擬。在Visual Studio中採用C++模擬C51中的硬體器件運行結果,達到KeilC和C++代碼每行都完全兼容,運行結果也完全一致。舉個最簡單的離子:
C51是8bit CPU,每次加法若溢出後,會置位PSW標誌位[CY]為1.在程序中經常會用if(CY)判定是否溢出。在C++模擬中便採用了運算符重載的辦法進行了模擬。將特定的加減法轉換為自定義類型的加法,這樣程序跑到重載函數中便可模擬8bit溢出的情況。
模擬將電池充放電log數據吃進去之後,實際模擬出運行的效果,使原先一周的驗證時間縮短到了半小時,現在鋰電池演算法的效果已經非常好了,逼近世界No.1的TI。
在工作過程中,我一個嵌入式工程師,專門學了好多C++和C#的東西,自己的進步很大。同時學習了STM32的官方C庫,收穫了很多。在之後諸如TWI、HDQ、E2ROM、USB等等其他擴展功能上也貫徹了嚴密細緻的精神,程序現在伴著IC每月1M+的出貨量穩穩的運行著。特別感謝知乎,讓我認識了那麼多的軟體大神,特別感謝輪子哥和趙姐夫在答案中的指點!
如果你認真看過知乎下面關於傳統工業的答案,應該有種感覺。先進的工業技術其實不是設計出來的,而是測試出來的。就拿內燃機來說,內部燃燒模型根本不清楚,完全是靠實測一點一點摸索。飛機設計也要靠風洞吹吧,再不濟也得用模擬模擬一下吧。
所以說,工業級別的代碼,「寫」起來沒什麼感覺,但是一定有一大堆人在給你寫的東西挑刺,還有一大堆人在反對你寫。如果有兩三個產品經理天天求你加 feature 那估計不是工業級代碼。
軟體工程從瀑布模型發展到重視 iterative 的開發方式,其根本原因就是軟體的預判設計是不可能對質量有決定性作用的。最後的結果只能是用測試來約束軟體的編寫(不要誤會,我不是在說 TDD)。有什麼樣的測試,就有什麼樣的產品。
如果引申一下,人類的工業進步莫不如此。人類如何從石質工具一步一步發展到精密機床?低精度工具如何製造出高精度工具?答案就是測試。近代產生的公差等數學和概率工具來用測試驅動技術進步。雖然人腦在認知方面的能力沒有軟體能比,但是對於高頻度高強度的自動化操作,人腦是一種很粗糙的工具,而測試就是幫助人類在軟體領域從人腦和低級工具進化出複雜工具的手段。當然,當一種軟體工具的可靠性已經得到證明之後,如果它又具備的通用型,就就可以用來增強其它系統的可靠度。這就是說以前的測試成果被固化了,不用重複了。就像用納米級精度的機床,不用太多測試也能做出毫米級精度的產品。
所以我們說工業級軟體是靠測試出來的,與你在整體方案中採用已有的高可靠性模塊並不矛盾。
另外附上另一個答案:看看工業級產品,不光自己測,還用白菜價引白老鼠測 你碰到過的最難調試的 Bug 是什麼樣的? - 林鎧鵬的回答(裡面 C 公司的後端)
再舉第二個例子:請看這個答案下關於如何「生產」專業顯卡:專業顯卡和遊戲顯卡究竟有什麼區別呢? - Benjamin Hsu 的回答 - 知乎。其實就是針對不同的目標軟體(遊戲還是專業繪圖軟體)進行兼容性測試,然後考慮關閉/打開穩定性和性能敏感的部分。新的鄙視鏈誕生了
- 民用
面向普通人,無需負責
就是我們用的知乎這種
天天 404 500 並且功能不完整上線 5 年仍然是勉強湊合能用的狀態- 商用
面向企業負責
品質過硬,方便好用,不然分分鐘幾十萬上下的損失就是 SAP Oracle 用友 金蝶 這種- 工業/工控
面向大型工業廠商負責
就是世界第一汽車大廠豐田汽車控制程序這種,嚴謹穩定,十年如一日地輸出有著 1 萬個全局變數的一大坨代碼
- 軍用
屬於黑科技級別,不是我們普通人可以窺見的
代表是麒麟系統信息化特戰部隊的實力:解放軍美女尖兵:90晝夜主持編寫40萬行代碼所以說,普通人寫十年代碼,能力還比不上軍校信息科大二的學生如果你好奇工業級別的代碼的專業和嚴謹程度,那麼你應該會喜歡下面這篇文章如何測試洗牌程序鐵路行業用的軟體和 @木城 答案中的汽車軟體設計流程差不多,整個過程也是按照V-Cycle進行的。
可能不同的地方是,鐵路信號這邊軟體是分為了通用層和邏輯層的。一般來說通用層不太會有大的變動,因為是最基礎的執行性代碼,這些代碼都是久經考驗的。主要的開發位於邏輯層的,因為最左邊的原始輸入文檔裡面有一些比較重要的東西是來自客戶方面的,比如A國鐵路的信號系統原則和B國的是不一樣的,就算在同一個國家,每個車站也會有一些例外的情況,所以邏輯層就會千變萬化。
一般開發商內部都有一些自己的工具,首先把系統原則根據車站的拓撲和信號設施的安裝情況實例化為具體的參數,參數比如在某個位置有個信號機,從這個信號機出發有些什麼進路,這些進路的建立條件是是檢查XX設備YY設備的狀態等等。。然後根據例外的情況對參數做需要的修改,然後用自動化工具根據參數去生成具體的執行代碼。這一步完成後,就是到了V--Cycle的右側,交給測試部門進行各個層次的測試。測試部門同樣會根據左側的原始輸入文檔去配置測試參數,然後用參數生成具體的測試用例,理論商測試這邊生成的參數應該是和開發這邊的一致的,只有所有的測試都通過才能確認交付到現場進行測試。
整個項目周期裡面會有多次迭代,一般有兩種原因,第一是測試中發現參數有不符合輸入文檔的情況導致需要修正參數。第二是需求文檔本身的變動,一般導致需求文檔本身的改動是因為發現了通用總則沒法解決的特例,需要做專門的參數修改,另外就是客戶那邊的通用總則發生變化了。
另外一點就是,測試團隊和開發團隊必須是不同的工程師組成,團隊主管不能來自同一個部門。。答主混跡在美帝汽車軟體行業,在兩家一級零部件供應商的軟體部門工作過。曾經合作過的整車廠包括通用、福特、克萊斯勒、現代和大眾,目前在幫助一家矽谷初創公司完成他們的電動汽車項目。在這裡,答主簡要介紹一下汽車工業中關鍵安全部件(Safety Critical
Parts)的控制軟體是怎麼寫出來的。所謂「關鍵安全部件」,通俗點說就是出了問題要死人的部件,比如發動機、變速箱、轉向系統、安全氣囊、剎車系統等等。與之相對的非關鍵部件,則包括電動車窗、空調系統、音響系統什麼的。試想一下,發動機軟體出了故障也許會導致汽車爆沖(為凱美瑞默哀…),安全氣囊軟體不工作或亂工作,更是會直接導致駕駛員傷亡(高田掩面而去…)。相比之下,車窗不升降或者亂升降、音響無法控制什麼的,一般並不會導致交通事故。所以,關鍵安全部件的軟體設計要比非關鍵部件嚴苛得多。
一、行業標準
關於關鍵安全部件的軟體設計流程,有兩個公認的行業標準,即aSPICE (Automotive Software Process Improvement and Capability
Determination) 和 功能安全標準ISO26262中的軟體部分((Road vehicles – Functional safety - Part 6)。幾乎所有整車廠和絕大部分汽車零配件供應商都參考這兩個標準來制定自己的軟體設計流程。而越來越多的整車廠——比如德國大眾——採購零部件的基本門檻之一就是供應商的軟體設計流程通過了aSPICE認證。圖1. aSPICE 流程
(資料來源:http://image.slidesharecdn.com/webinarautomotivespice3-150731093914-lva1-app6892/95/automotive-spice-30-was-ndert-sich-9-638.jpg?cb=1452240786)
根據aSPICE流程,軟體開發過程可以被拆分為需求分析——架構設計——單元設計——單元測試——軟體集成和集成測試,以及最後的軟體綜合測試,每個步驟依次進行。學過軟體工程的人會認為,這就是老掉牙的「瀑布式(water fall)」開發流程嘛,但其實aSPICE與瀑布式流程是不相同的,這個我們後面會提到。
圖2. ISO26262 – 第六部分
( 資料來源:Achieving ISO 26262 Compliance with Reactis: An ISO 26262 Process using Reactis)
再來看看ISO26262。額…這個跟aSPICE也太像了吧。話說我也沒有考證過它倆是誰借鑒誰,總之幾乎就是一樣的。比如圖1的SWE.1對應圖2的Step 6;SWE.2對應Step 7…… 也許是因為它們太相像了,在業內我們一般統稱為「V」型開發流程 (The V Model)。
現在來說說這個V型開發流程和瀑布式流程有什麼不同,或者說,它有什麼獨特之處。答主個人認為,V型流程有兩個最大的特點:
1. 同一組責任人負責同一個層級的開發和驗證。從圖2可以看出,需求文檔和需求驗證相對應,是第一層級;架構設計和集成測試相對應,是第二層級;單元設計與單元測試相對應,是第三層級。V型流程要求,同一層級的開發與測試,由同一個(或一組)責任人負責。比如,架構師除了參與架構設計,還要制定集成測試用例 (Test Case),並且在集成測試完成後審閱測試報告;又如,參與單元設計的工程師除了寫代碼,還要寫單元測試用例,並且審閱單元測試報告。
這樣種流程的設計是為了最大限度的保證軟體被可靠而完整的驗證,降低由溝通不暢而引發設計缺陷的可能。
2. 每個步驟的實現和驗證都具有嚴格的可追溯性。具體而言,就是在最終發布的代碼中任意選擇一個語句,都能夠快速地確定它是實現哪項軟體設計,對應哪一條軟體需求,進而對應哪一條客戶需求;另一方面,這條語句被哪個單元測試用例測試過,進而又對應哪條集成測試用例,也必須是清晰明了的。而所有這些信息還必須包括對應的責任人、審閱人、日期及必要的備註。
這樣設計流程的目的,一方面是為了在團隊高流動性的情況下,新人能夠快速、準確的上手;更重要的是為了在出現問題以後,能夠快速而全面的做出故障分析,得出故障的根本原因。
當然啦,嚴格遵守這些流程的缺點就是…項目開發中至少一半的時間都用在維護文檔上了…沒辦法,誰叫我們是能決定駕駛員身家性命的程序員呢。
二、團隊組成
在涉及具體的軟體開發流程以前,答主覺得有必要先介紹一下典型的汽車行業軟體開發團隊的組成。前面已經介紹過行業標準流程了,那麼開發團隊自然是按照標準流程來配備的:
圖4.典型的軟體部門組成
- 需求工程師(Req. Engr.)負責分析和撰寫軟體需求,對應aSPICE的SWE.1;
- 架構師(Architect) 負責軟體架構設計,明確各個單元之間的介面,並且負責操作系統的配置和調度對應SWE.2
- 基礎軟體工程師(Base SW Engr.)負責硬體和底層驅動,應用軟體工程師(App. Engr.)負責應用層軟體的開發,他們都對應SWE.3
- 集成工程師(Integration Engr.)負責系統集成和測試,對應SWE.10
- 測試與驗證工程師(Test/Validation Engr.)負責所有的測試,對應 SWE.9, SWE.10, SWE.11
等等,答主你剛不是說V型開發流程里同一層級的設計和驗證,要由同一人負責嗎,咋突然冒出來這麼多工程師!事實上,圖4介紹的團隊組成和V型開發流程的特點並不衝突:
雖然工程師分工各有側重,但在同一層級中,一定是有一個工程師總體牽頭負責的。在一些企業中,架構師和集成工程師更是習慣由同一人兼任。對於基礎/應用軟體開發工程師而言,工程現實決定了在大多數項目里,他們不可能做到既寫代碼又寫全部的測試用例。這時候,就需要由開發工程師確定測試的「大綱」,由測試工程師來完成具體測試用例的編寫和執行。開發工程師只需要審閱測試報告就可以了。
圖4介紹的只是一種典型的團隊組成。不同企業根據自身特點,有不同的團隊結構,但萬變不離其宗。而應用層工程師還可以進一步細分為控制工程師、通信工程師和故障診斷工程師等等,這裡就不展開了。
從具體項目的角度,還可以列出另一種人員組成結構。
圖5.典型的軟體開發團隊
只要滿足了圖5的人員配置,基本上項目就可以開工了。在實際工作中,有些企業的項目組長(Proj. Lead) 是專職的,另一些企業則是由某個工程師兼任。一般而言,架構師或者集成工程師兼任項目組長的情況比較多,控制工程師兼任的也不少。
除了上述工程師以外,要完成整個軟體開發,還需要質量工程師、安全工程師、系統工程師等等。由於這些人員往往並不只為軟體部門服務,所以這裡就不介紹了。很多企業——特別是美企——軟體團隊里還會有很多不懂技術,只負責財務、客戶溝通以及監督進度的項目經理(PM)。這些人往往都是職場老油條,答主和他們相愛相殺了好多年,這裡也不細說了。
三、工業級別的代碼是怎麼寫出來的
卧槽終於寫到正題了。答主有一種前面離題萬里的感覺有沒有。
圖6.軟體開發流程
首先上場的是需求工程師。需求工程師需要重複閱讀客戶的需求文檔(Customer Req.)以及系統需求(System Req.),對於其中不明了或者有歧義的地方,要和客戶以及其他工程師充分溝通,最終寫出一份軟體需求文檔(SW Req.)。
如果這是一個全新的軟體,那麼軟體組的大牛們會聚在一起討論設計的可行性,然後進行一個叫dFMEA (Design
Failure Mode and Effects Analysis,設計失效模式及後果分析)的東西。事實上,由於汽車軟體行業已經有了好幾十年的發展,基本上沒有什麼軟體是「全新」的、總有前代產品可以借鑒,也總有已完成的細節設計和dFMEA可供參考,所以這個過程是不算太長的。如果是既有軟體的版本更新,那麼dFMEA就可以暫時省去了,只用進行可行性分析和影響分析。(答主在這提一句,這也是為什麼「自動駕駛」進程如此緩慢的重要原因。因為自動駕駛軟體真的是沒有任何東西可以借鑒,完全是start from scratch)
有了需求文檔,項目組長和架構師(很多時候是同一個人…)就開始根據需求文檔規劃一個軟體變更(Change Request),並且把這個變更,根據不同分工和性質細分成很多個小的任務(sub-task),並分配給各個基礎軟體工程師和應用軟體工程師,然後工程師們就開始討論軟體設計啦。對於每一項設計變更,不少企業會進行DRBFM (Design
Review Based on Failure Mode) 來確保設計的可靠性。完成了軟體設計以後,工程師們就開始編程。現在越來越多的企業開始使用自動代碼生成工具(TargetLink, Rhapsody等等),只要設計好邏輯,就可以自動生成出高質量的代碼。
有了代碼之後,這些工程師需要和測試工程師配合,完成一系列的單元測試,包括靜態測試(MISRA)、動態測試、模型在環測試(MIL)、軟體在環測試(SIL)、處理器在環測試(PIL) 等等,然後進行同行評議(Peer Review),等這些測試都通過了,再整理好文檔,每個小任務的單元測試也就完成了。
每個小變更都通過測試,並不意味著它們組合到一起能夠通過測試。這時候就要集成工程師把所有小變更集成起來,行成一個可編譯的整體軟體,這個集成了所有小變更的軟體一般叫做「0級軟體」,也就是沒有任何保障的軟體。
隨後測試工程師再次登場,在集成工程師的配合下對「0級軟體」進行集成測試,包括回歸測試(Regression Test)、硬體在環測試(HIL)、故障注入測試(Fault Injection Test)等等等等。如果全部通過,就會被下載到汽車上,進行上車測試(In Vehicle Test),最終在滿足了一系列嚴苛的條件後,成為可以最終送到客戶手中的發布軟體。
於是一長段工業級的代碼就誕生了。
上文所敘的只是最理想情況下的軟體開發流程。工程實際要比這個複雜得多,比如客戶翻來覆去改需求啦,工期無故被縮短啦,測試出了大問題要返工啦,甚至已發布的軟體在消費者手裡出了問題需要召回啦等等。如何解決這些問題,就不是一兩千字能說得清楚的了,在這裡且略過不表。一句話總結,答主的理解是,工業級的代碼就是按照行業公認的標準、經過了嚴謹的分析、具有詳細的文檔、通過了嚴苛的測試的代碼。
我還以為沒人問呢,真好,有人問了。那我也來回答一下
——————————————————————
其一、這個問題的各位答主根本就沒有看我的文章,至少看的不細。我文章中說了,工業級的軟體是有沒有SLA,SLA是多少?不先討論這個條件,就直接討論體驗,也是醉了。怪不得會出現些什麼「工業級的軟體是靠測試出來的」這樣謊謬的答案。
其二、我更多說的是提供服務的集群架構而不是什麼單機版的軟體,請參看我的第二篇文章:《關於高可用的系統》
其三,體驗是什麼?大家是不看我的文章么?要了解幾乎所有的技術細節,要過嚴謹科學的軟體設計和代碼評審,過嚴格的測試,還要開發先進的配套工具……認真+嚴謹+科學+苦逼,這意思是,相當的廢腦子、勞神、和苦逼!
——————————————————————
我在文中也說過我的一些經歷,這裡再多說幾個經歷吧,這樣你會知道體驗是什麼樣的(可能還會再更新中):
- 之前做銀行的時候,一個上線的bug,導致那個城市所有的銀行門店關門,把當天所有的單據重錄一遍,後來才知道銀行方面都要去報警了?有過這樣的經歷,你才會知道——代碼寫不好有可能也是一種犯罪。
- 2002年沒受過什麼正規訓練的我去Platform才兩三個月,code reivew的時候被定性為代碼寫的太差,雖然功能一切正常,也沒怎麼被QA測試出BUG,而且我文檔寫的還很好,但是沒有通過code reivew,於是經理約談我,讓我去當測試人員……
- 在路透的時候,代碼開發通常不到一個月,功能測試一周多一點,然後就是漫長的性能測試(參看 性能測試應該怎麼做?),花三天時間找到系統的性能承受點,然後開始,不同的數據包的測試,極限壓力測試,峰刺測試,為期至少一周的Soak Test,可能我還漏了一些,大概要花一個月到兩個月,然後上線了還要在線上做至少三個月的hybrid running。
- Amazon的時候,有一個小夥子在重構代碼,美國那邊的工程師問,你重構的design發出來review一下,結果小夥子說,我寫了一些測試case,然後見招拆招,結果被批評的相當重,case-by-case的編程,你是不想混了吧。
- Amazon的時候,我的那個要把全球所有的marketplace連一塊的項目,關資料庫的表模型就被reivew了將近三個月,還有架構設計的reivew也同步進行了兩三個月,被各種principle SDE提了好多好多設計意見,幾乎把amazon內的所有的技術都比較了遍,做了好多POC的測試才得到一個大家相對認可的design。
- Amazon內部有一個Pub/Sub,我們要接,因為我們還要在匯流排上加個filter,Pub/Sub團隊說,可以,但是為了不影響Pub/Sub匯流排的SLA,所以,你們得把你們的需求、架構和代碼拿來Reivew,一個月過去了,我們的代碼又改好了一些,而且和別的團隊的架構整合也好了很多。
- Amazon的時候,想讓商家可以出口,所以,需要商家在他的後面簽個法律文件,結果到了日本,出了個問題——日本人的商戶名和店主都是日文的,但是出口單要項英文,所以,需要用戶輸出他的英文姓名和商名,這在美國,歐洲都沒有問題,因為都是用英文的。但是因為這個需求是日本本地化的,這意味著我們需要給商戶加兩個欄位,而且還有if-else判斷,以及站點的異化配置,而且這兩個欄位會導致所有的服務介面都要跟著改,於是,這造就了後台服務的巨大重構(數據交換協議+服務介面),歷時半年,影響了幾乎所有和物流相關的團隊,我估計怎麼著也有上百個吧。
- 工具。2002年的時候,國內的開發都還不知道什麼是版本控制工具的時候,我第一次接觸到了,然後還用到了很多那個牛逼的Rational公司做的各種工具,簡直是絕了。人類之所以聰明,就是懂得發明和使用工具,所以,工具現代化的水平直接決定了你的系統的水準。好的工具是事半功倍,而且是可以把人給下崗了的(解放生產力),國外的工具幾乎都是向自動化的方向走的,國內的工具幾乎都是向領導審批的方向走的,呵呵。
最後說一下,Amazon的S3的SLA是11個9 - 99.999999999%,機房隨便掛。沒有見過的人,是不會知道這是怎麼做出來的。所以,開眼界真的很重要。在做追溯軟體的公司工作,雖然我是做前端的,但是經常能看到後台和資料庫寫的代碼導致工廠產線出問題,嚴重的時候導致停線。 這個時候就需要公司的現場工程師去工廠現場解決問題了,然後一大幫子領導和工人圍著現場工程師,看著他解決問題。工廠領導在後面罵:「好了沒有,這麼慢,行不行呀~不行我找你們老闆換人了」諸如此類。然後給現場工程造成了天大的壓力。一般解決完問題都是跟做手術下台一樣,整個人都要虛脫了好嘛!!!那麼,如果沒解決!我的天!你們公司的領導全給我過來,問題不解決你們等死吧!因為涉及到工業製造流水線,工廠停工會導致供貨遲滯,然後工廠的客戶就各種不滿意,然後一系列連鎖反應。。。。 當然我個人寫的玩意兒,主要是頁面,用來表現數據要求就比民用低很多。工廠里的界面都要落後於民用至少3年。。。。工業級別的不要求UI與時俱進,很多工廠都是能用就行,穩定不出錯,升級反而要出問題,有額外的損失。並且我們客戶都是在區域網中直接生產,並展示數據。我基本寫完代碼連注釋都不用做處理,更別說壓縮什麼JS,直接就發到工廠用了。但是!但是!有一個慘絕人寰的事情!部分工廠里的設備偏老有木有啊!頁面要支持IE5.5呀!!!5.5呀!要是IE6我也就忍了!!!!而且屏幕顯示效果慘不忍睹!解析度大部分都是1024px,768px呀!!!!我的天!我們頁面做的要求是簡介,大方,字體要大!對比度要強!!工廠要求能讓工人迅速看清屏幕呀!!!!完全沒美感好嘛!
說到了工業級,怎麼沒有一個答案提到MTBF和FMEA的,都在扯淡搞笑么?
個人最高的故障經歷是觸發了一堆人打電話調衛星鏈路做後備。那年大概25吧?一個通宵下來全身都汗濕透了,還好大半夜的沒啥實際業務量。======今天更新了amazon砍掉測試團隊的原因,請往下拉到更2 *(^o^)/*=======
額,被陳皓本人點贊了,看來我這個是正確的標準答案(大誤+汗)為什麼很多的關注很少的贊T_T,請大家給予我繼續寫得元氣呀~~ ↖(▔^▔)↗8年amazon老兵,先來佔個坑,( ^ω^ ) , 在大家都看好我轉TPM的情況下,依舊毅然決然的堅持走技術和coder的路線(雖然亞麻升級SDEIII 登天樣難... T_T,很多人轉管理也是因為技術觸頂),天天跟著research scientist研究model,真的比當TPM有意思太多了!沒想到陳皓也在platform干過… 當時我在platform工作的時候,真的以為自己已經掌握了這世界上最先進的科技了,grid computing,MPI,LSF,高性能計算,讓科學模型並行跑在上千個core的機群上的黑科技,亦可賽踢的!客戶都是什麼 美國航天局,氣象局,對了還有神6;各種高大上…
然而來了amazon才真的開拓了眼界… 也是為什麼在這裡一呆就是8年 (在什麼組,真的真的很重要)話說原來在中國office時候跟陳皓在同一層,經常遇到,直到他走了才知道他那麼有名…
陳皓所謂:「世界前沿的軟體設計架構和解決方案,以及做技術的態度和工程的方法,我的眼界、腦洞和視野都巨大的打開,並且在技術管理、工程管理、產品管理、人員管理、公司管理等等管理方面的思維有了質的提升」
有人看的話, 有時間可以稍微介紹下。 ^_?☆
-------------------------------更1 ------------------------------
貌似由於這個回答被不少人關注了 -_- 於是也下決心好好完成這個回答,補上這個坑。坑留得比較大... =_= 沒有大塊的時間放在知乎這裡,所以會分多次update這個回答,既然承諾介紹下「世界前沿的軟體設計架構和解決方案,以及做技術的態度和工程的方法」(羞) 自然答案所包括的內容也遠超問題「寫工業級別代碼是怎樣一種體驗?」 本身了。首先,為什麼需要「世界前沿的軟體設計架構和解決方案,以及做技術的態度和工程的方法」,是這次更新要談的問題。我們不能用手術刀在市場買肉切牛肉, 也不會用核彈來拆出拆遷建築。如果你是一個為了「高精尖」來提高自己逼格而不管要解決的問題而使用「高精尖」的人,那我們可以說是話不投機了,以後的很多內容估計也會引起您的不適,請及時關閉本答案。
先介紹一下個人背景,我的技能棧和輪子有所不同,輪子感覺上屬於精研PL,技能點集中一個自己喜歡的方向往技能樹深處點下去的類型;而我則非常分散, 一些主要的技能點列在了這個回答里:後端所謂複雜的問題是什麼? - 阿萊克西斯的回答 所以看問題的角度會有不同,之後有機會也想說一下程序員的發展路線,深度優先/廣度優先,分別適合什麼樣的人。
再說一下現在的工作的大環境,我只在platform和amazon呆過,platform做的算得上軍工級傳統軟體了(maybe?);而amazon則是完全不同的互聯網畫風,所以對傳統行業,互聯網行業也算得上都有涉獵;我所在的組/部門更是互聯網公司中的另類,那就是:探索型領域。另外一個核心角色加入了進來,那就是RS(Research Scientist),也就是你們可愛的曾博 @大勃勃 的角色;探索型領域有個特點, 那就是會失敗, 經常失敗,因為沒人知道什麼是對的;客戶只會說, 我要最好的馬,什麼是「最好的」,不知道,你去找吧。我想讓XXXX的利潤最大化,怎樣才能最大化,怎麼就算最大化了,不知道,你去找吧。很多時候客戶(或領導)想讓你把月亮摘下來,然而一開始誰都不知道這是一個把月亮摘下來的「不可能完成的任務」, 去做吧,你得到的「需求」也許一開始就錯了。所以做了幾個月1年的項目,可能一天就砍掉了(終於探索到,證明了「這是不可能的任務了」),可能寫了幾個月的代碼,開一次會,就要全部刪掉重來(因為探索到solution就是錯的)。
但是,探索型領域,卻是往往是一個大公司的:核心競爭力,為什麼近年來FLAG都開始狂招RS,不在探索中持續前進,就在探索中衰落,現在這個年代,能抱著自己的老飯碗,自己的已有優勢吃5年都是不可能的事情了,想要在競爭中生存,不僅要去探索,還要付出比別人小的代價來最大的換取探索的成果。因為大家也都在探索在進步,只是進步是不行的,要比別人進步的快,才能存活!(在探索這方面,國內的阿里做的非常好) 在探索型領域中,精英的RS和SDE將是核心人員,而其他比如產品經理,dev manager則成為輔助。在這樣一個充滿挑戰,激動人心的領域,擔任一個精英怪的角色,正是吸引我這樣一個數學系出身,曾經想轉行學經濟的SDE,在這裡一呆就是8年的原因好的,接下來就要開始講在這樣的環境下,怎麼來進行:
rise question-&>rise solution-&>design-&>coding-&>test-&>verify-&>meet new problem-&> rise question 這個無限的循環了,敏捷開發的流程在這裡大放異彩,莫名其妙的奇葩問題不斷展現,各種各種的黑科技始現魔力;正如陳皓文中所說,問題環環相扣,技術問題歸根結底也許是公司文化問題,讓我們期待下一期, 走近科學。。。。(我會再回來的。。。 老婆留給我的自由活動時間已經到了。。。看孩子去了。。。)
對於程序員來說,怎樣才算是在寫有「技術含量」的代碼? - 阿萊克西斯的回答留一個簡介我技術三觀的回答吧。。。也許看了你們就發現咱們道不同不相為謀了。。。如果是這樣, 請大量對本回答點擊反對。。。我也就不用填這個坑了。。。。(好好回答問題。。。太累了。。)---------------------------更2-----------------------
今天恰巧看到這麼一個問題,微軟Windows團隊的程序員質量在下降嗎? - Microsoft Windows微軟的大大們紛紛表示把鍋甩給砍掉QA團隊,吃瓜群眾紛紛表示QA必不可少,批評敏捷鼓吹QA DEV結合就是瞎搞,於是在某回答下評論了一下。寫得比較長,不如就貼這裡當作更新了吧 ( ^ω^ ) 寶寶我真是機智呀 ~ ~(認真臉)從amazon的角度來說下這個問題,amazon大幅度裁減了QA團隊,主要由於:
第一:非常嚴格的要求SDE寫UT,因為能把UT覆蓋率提高本身也體現了程序設計的flexibility,當程序質量由於UT提高之後,很多團隊發現QA不僅沒什麼幫助,因為測出bug的幾率大大降低,反而成為了團隊的累贅,因為communication是需要消耗團隊精力的,amazon的two pizza team保證了交流的範圍和效率,一個複雜的feature,甚至scientific model需要SDE,QA同時深刻理解,當然沒有隻需要SDE深刻理解來的有效率,靈活而敏捷。對於非常需要fast prototyping,拿到反饋來revise產品,design,甚至大方向的探索型項目來說,多一倍的溝通效率就是競爭中生與死的區別。這時要balance,出bug的幾率,bug的影響的cost,和引入QA團隊的cost。那麼權衡之下,大多數非bug敏感的團隊發現都是可以取消QA團隊的。當然出bug就致命,直接死的團隊,一個bug就是million dollar損失的團隊,還是保留了QA團隊的。當然UT cover%100也不代表系統沒bug,end to end的manual test還是可以增加系統健壯性。however…The trend recently has been away from any large-scale manual testing, in favor of automating as much as possible. ——引自《building microservice》任何的manual的,厚重的test流程,都會增加「變化」的成本;這裡關鍵要認識到:要麼犧牲開發探索敏捷靈活性,來增加系統的confidence level,要麼犧牲一些confidence level,增加系統敏捷性。測試不是簡單的有或者沒有,而是從0到100的程度,需要你根據自己的系統的實際情況做出選擇!其二:Amazon強調SDE要有ownership,自己做出的東西,自己就要負責到底。做design就直接要考慮testability(一個不可測,或者很難測的系統,必然是沒有經過domain,tech concern separation的,必定是一個不靈活的design),考慮到以後怎麼maintain,考慮到怎麼部署怎麼release。如果總是想著出了錯,第一個背鍋的不是自己,那麼系統質量怎麼能嚴格保證呢?怎麼才能方便的test,或者說怎樣很容易的定義/驗證程序的正確性,本身就是design必不可少的一部分呀~ 因為design要做到: A good system, doesn"t only work well, it SHOULD also be seen work well. 這就是所謂的系統透明性原則了, 你寫code做design的時候考慮到了么? ( ^ω^ )
其三:很多時候,不想被厚重的測試限制,那么可以用monitor來增加系統的confidence level而不太影響系統敏捷性。Amazon就是大量的使用了各種各樣的monitor framework,讓SDE自己來定義和監視系統的運行時正確性。很多組一個QA都沒有,系統健壯性全靠UT,SDE手測加上monitor,也活的好好的,對有責任心的SDE來說,測試也必然成為他的必點技能之一(融入到他的design和coding之中了)。對於一部分組和部門來說,這基本就夠了
總結:不要被方法步驟迷住了雙眼,測試的目標是為了系統正確性,而系統正確性不僅僅可以靠測試還可以靠monitor;系統的正確性健壯性的目標又是為了核心競爭力,那麼當核心競爭力可以通過剪裁系統正確性來提高的話,那麼犧牲正確性又有何不可?還是那句話,直追你的目標,忘記你在用劍,才能使出最高的劍法,不滯於物,才能隨心所欲,登峰造極~
欲知後事如何,且聽下回分解( ^ω^ )
(下次來講下怎樣拿需求,和PM的關係,怎樣向上管理PM,要知道,SDE才是項目的真正核心!)補充:本來不想趟「windows10到底應不應該砍QA」這個問題的渾水,因為我也說了,測試和系統敏捷性,甚至公司戰略目標,這個balance要就事論事,才能決定。就win10被罵這個問題來說,」 被用戶罵「或者抬高來點說」系統正確性「也只是公司競爭力的眾多衡量因素中的一個罷了。簡單來說,如果砍掉過多的「正確性保證」(就是QA)能得到x,失去y,那麼這是不是一個好的決定完全取決於x和y誰大。但是這麼大個事兒,誰說的准呢?(知乎的屁民從用戶體驗的角度來思考,那肯定是質量大過天了) 所以我也沒有直接就說「砍得好」, 「win完全不需要QA」 這個話,只是希望大家分析問題能再上幾個高度來思考,從系統靈活性,健壯性的trade off來思考, 甚至從公司戰略目標,和多種影響戰略目標的因素(測試或者系統健壯性只是其中之一)來思考。不過評論區有人上來就「你的認識太過膚淺和片面」,不是就事論事的說話,而是寫些情緒性的東西。那我就對「win10要不要砍QA」這個問題再加些「膚淺和片面」的評論:1. 砍QA到底是得是失,x和y到底那個大,沒試驗之前(易地處之,人家做這個決定的時候可不是像大家這樣做馬後炮),這麼大個事兒,誰說的准呢?至少微軟CEO和一眾高管做出了和知乎上的屁民不同的決定不是么? 你是看到了win10被很多人罵,但是萬一這件事本身就是高層取捨中的」棄子「呢?國際象棋,高手過招,只要國王沒死, 皇后都可以捨棄(IBM為了進化連X86伺服器都給賣了,憑什麼微軟就不能把資源更多的集中在Azure上邊?到底微軟的什麼業務是微軟再次偉大的希望?);還是要從企業發展的大局來看啊。2. 大局怎麼看? 微軟近些年是變好了還是變壞了?(別扯別的,咱就看股價)微軟沒點「大」變化,下場就是IBM,摩托羅拉,諾基亞,朗訊。管理層敢於這麼大膽嘗試,我給微軟10000個贊!看好微軟的未來!3. 微軟的」有些「SDE啊,都」xx「慣的!寫工業級代碼最最重要的是:要求設計和實現儘可能簡單再簡單。
複雜的設計,難以認知,難以維護。
簡單的設計,易於理解,容易編碼,便於測試。題主的問題很好。從陳皓的文章和題主的問題內容來看,這應該一個關於如何做工業級後台服務的問題。但截止目前,好像只有兩個回答,是關於後台服務的。這似乎說明,現階段關於如何構建工業級別的後台服務的經驗和實踐,都是欠缺的,而對於目前蓬勃發展的雲計算和互聯網服務來說,這又是不可或缺的。
以系統穩定性而論, 大多數2C的互聯網產品,產品功能和運營是第一位,系統穩定性其次,假如知乎的可用性只有99%,即一天中會有十幾分鐘不可用,並不會對知乎構成致命傷害, 但假如一款2B的雲計算產品一天當中有十幾分鐘不可用,可能一個客戶都沒有,不管產品功能有多麼牛逼。
這就倒逼雲計算的從業人員,去思考如何構建高可用的服務。當然,穩定性只是一點,工業級別的後台服務,其實還包括很多方面。過去一年,在從事 UCloud 從事分散式雲資料庫 UDDB 的研發和運營過程中,我們碰到了很多跟產品和服務質量相關的問題,有的來自項目本身,有的來客戶。在思考和解決這些問題的過程中,也觸發了我們對工業級別後台服務的一些思考。 UDDB這個項目還剛上線, 我們的實踐和思考也還在進行當中, 要把構建工業級別的後台服務,很好地總結成理論並輸出, 還需要不少時間和實踐。
這裡, 針對題主的這個問題,我想先談一下,我們認為的,工業級別後台服務 的一些評價指標。我們認為,要做工業級別的後台服務,要先把工業級別的指標先搞懂,然後才能綱舉目張,有的放矢。當然,由於我們的經驗有限,而雲計算在國內也是剛走過最初的發展階段,距離汽車電力等行業的工業強度高度,還有很長路要走。這裡只是先拋磚引玉,期待更好的想法。同時有時間的話我會進一步就這個話題,進行補充和完善。
我們認為一個後台服務,是否達到工業級別,有以下幾個評價指標:
一、用戶體驗
這裡的用戶體驗,有別於大家常說的用戶體驗。常規的用戶體驗,是用戶使用產品或服務主觀+客觀,理性+感性的綜合感受。而我們這裡只想談一下,一個後台服務,在純理性(易使用,易維護)層面,需要提供哪些好的體驗。我們認為有4點:
1. 正確執行,合理反饋
正確執行,不僅包括正確執行用戶正確的輸入,還包括各種錯誤的輸入,也包括系統內部發生異常時, 是否還能夠對用戶請求進行正確處理。
合理反饋我們認為有兩點,一個是及時反饋,另一個是反饋信息忠實於系統現狀。比如,在一個漫長的後台操作過程中,是否在每個階段,都能夠輸出用戶關注的一些狀態信息,讓用戶對操作的進度了如指掌;輸出的信息,特別是錯誤信息,是否能夠忠實與系統現狀,並做到簡潔凝練。
工業級別的軟體或服務,不管是單機軟體還是分散式後台系統,在反饋的及時和忠實程度上,總是讓人愉悅,讓人放心的,會讓你感覺到軟體的運行,一切盡在掌握。
2.訪問介面的冪等性
對於一個系統介面(api),同樣的請求, 不管重複執行多少次,系統都能夠返回同樣的結果。操作具備冪等性,則客戶對系統的管理就變得非常方便,一個請求發過去,如果正確了,不需要擔心是否產生了和上一次不一樣的效果;如果錯誤了,也不需要檢查各種錯誤返回碼,來做各種異常判斷。 比如,對象存儲服務(比如AWS S3、UCloud UFile)提供的api,做到很好的冪等性。一個put操作,只要是請求內容完全一樣,不管什麼時候調用,效果都是一樣的。而有些資料庫SQL語句,則不具備冪等性, 比如 創建一個表或者insert 一個帶主鍵的表,如果表存在或者記錄存在,會報錯。 為了彌補這個缺陷, SQL標準還提供了這樣的機制:create table if not exists( ... );
insert into t values(...) on duplicate key set ...;
這些語句都是為了彌補冪等性的不足,而增加的補償性措施,在一些sql腳本里,我們可以看到這些類型語句被大量應用。
系統的介面要具備冪等性,其實是挺難達到,這需要從系統架構到內部實現到所使用的支撐系統,各個層面的配合。 但是做到了這一點,將給客戶在系統使用和管理上,帶來極大的便利。
3.速錯
4.魯棒性
4.1 功能邏輯的魯棒性: 等同於用戶體驗第一點中所說的 `正確執行` 。即用戶在正常使用過程中,不論用戶構建任何錯誤輸入,都能夠正確執行,產生正確的、一致的結果。
4.2 高訪問壓力的魯棒性:包括兩點, 一個是在海量的訪問請求下,系統各層面,各模塊是否能夠正常運行, 正確響應,請求耗時在正常範圍;另一個是當訪問請求超出系統設計成長範圍,能否高效彈性地進行擴容,做到不停服,不影響業務使用。 4.3 節點異常的魯棒性:後台服務一般都是一個分散式的系統。分散式就意味著可能某些節點會出現異常,任何幾點的異常是否都不會影響整體可用性, 異常是正確處理,快速恢復, 是做好節點異常魯棒性需要考慮的。 4.4 惡意攻擊的魯棒性:如果防範惡意攻擊或者竊取造成的服務不可用,數據被篡改甚至數據丟失,屬於惡意攻擊魯棒性的要求。
二、開發團隊的內功
1.流水線生產的能力
開發團隊效率要達到工業級別,首先要具備的是流水線的生產能力。具體來說就是代碼是否能夠模塊化,基礎類庫建設得好,模塊復用度高;編碼是否能夠有合適的開發框架和工具,做到儘可能自動化,傻瓜化,代碼完全靠程序員手工一行一行敲,是絕對達不到工業級別的生成效率的,即使個人能力再牛逼;另外,測試體系是否足夠完善,是否能做到單元測試,做好集成測試等,也是工業級別開發能力的體現。更多的敬請補充。
2.自動化的部署和運維繫統
3.立體化的監控系統
三、專業的售前和售後支持
UCloud 在業內一直以服務好著稱, 比如業內在率先推出的90秒響應,又比如售前售後團隊包括研發團隊,能夠主動介入用戶的需求和日常工作當中,去幫助用戶解決問題和提供技術決策。用兩句話概括就是:急用戶之所急,向用戶之所想,急用戶之未急,想用戶之未想。
最後是廣告時間: UCloud分散式資料庫:UDDB已經在北京二可用區B、D,以及廣東可用區B,正式上線,詳細內容請見:知乎專欄 知乎專欄。歡迎大家試用。
自己寫代碼主要就是覆蓋happy path,最多考慮一下這裡掛了怎麼辦,那裡太慢了怎麼辦而已。
工業級代碼更多要考慮監控啊,報警啊,匯總報告啊這些繁瑣的東西。監控主要是指,系統現在忙不忙,是正常的忙碌還是哪裡有問題,如果不正常,用戶是否受到了影響,波及範圍有多大。報警也是配套的,出了問題能不能自動報警,能在多少時間裡發出警報。匯總報告就是各方關注的各種指標,不一定是基礎的技術面指標,還包括業務指標。另外好不好部署,好不好測試那些也都算吧。
基礎設施做得好的公司都有輪子,新人進來其實代碼寫的隨意一點也不要緊,基礎設施都幫你兜著。要是沒有這些東西就吃力啦。其實也沒啥特別的,該怎麼寫就怎麼寫不過測試的時候比較嚴格罷了出了bug你就等著領導跟你吹鼻子瞪眼吧項目緊的時候心理壓力還是很大的,因為你要是出了bug(尤其是重要領導驗收的項目),那是非常不好收場的,那可真是丟全國級別的臉。。。所以養成了寫代碼不崩潰為第一位的習慣。。。跑的慢一點,效果差一點不要緊,你可千萬別給我在領導驗收的時候崩潰啊
看lua源碼就知道啥叫工業級
好吧,年輕的時候比較氣盛,部門接到隔壁部門一個單子,需求基本類似,只是項目名字前面加了個耐用版,少量新需求。
我負責寫新模塊代碼,當時催得緊求快,有些特定細節沒太考慮,出貨後,隔壁部門來人發難了,說測試不通過,我一看是有人操作不對,把一些東西鎖了,當然這個可以做的更好,比如應該加上防誤操作,和臨時快速解鎖,我就解釋了 寫了個文檔,過了幾天又來人了,一看又是不正常的操作造成的,三番五次後,領導也關注了,我看不行了,我說給你們更新軟體吧,加上很多防護功能、對方說好,但是產品已經分發到很多個點了,我們只能帶你去一個點,你先演示給我們看看怎麼做,我門做剩下的。
到了地方,一看是個兵營,咯噔了下,進門還要壓了身份證,然後到了點,看到的是一排巨大的裝甲車,當場懵逼了,我門的東西,在車頂最上面,看到他們老大爬上爬下的接線,我還是蠻愧疚的,最後盡心儘力的把軟體改好了,真正做到了「耐用版」。現在從事電能表程序的設計和編寫工作,工廠每年的出貨數量是幾百上千萬隻表,電力公司會分散安裝在全國各地的用戶家門口,並且設備沒有任何網路連接。我就想知道,一旦出BUG了我該怎麼辦?
不存在什麼工業級別的代碼,只有採取不同程度思考方式的程序員
有的程序員思考層面和層次就是比別人高好幾個量級,無論他寫的是什麼程序,都是最高標準的之前給東風做項目,必須保證7*24小時運行,出了故障停一分鐘賠償1萬塊,感覺代碼質量也不高,只是測試比較多而已。
推薦閱讀:
※一段簡單文件IO的C程序,為什麼我的優化反而更慢?
※如何優化QTableView的性能?
※你見過哪些令你瞠目結舌的C/C++代碼技巧?
※gcc為何有時會在call前push eax,默認的調用約定不是cdecl?
※現代C/C++編譯器有多智能?能做出什麼厲害的優化?