走向專業工程師
“噢,笑吧,科廷,老夥計。這是上帝,或者也可以說是命運或自然,跟我們開的一個玩笑。不過,不管這傢伙是誰或是什麼,他真幽默!哈哈!”
——霍華德,《碧血金沙》
哦,你點進來了,這麼說,你確實是想成為專業的軟體工程師,對吧?你希望能昂首挺胸向世界宣告“我是專業人士”,希望人們滿懷尊重地看著你,充滿敬意地對待你。希望母親們會指著你告訴自己的孩子要成為像你這樣的人。這些都是你想要的,對吧?
1 清楚你要什麼
“專業主義”有很深的含義,它不但象徵著榮譽與驕傲,而且明確意味著責任與義務。這兩者密切相關,因為你不可能從你無法負責的事情上獲得榮譽與驕傲。
做個非專業人士可輕鬆多了。非專業人士不需要為自己所做的工作負責,他們大可把責任推給僱主。如果非專業人士把事情搞砸了,收拾攤子的往往是僱主;而專業人士如果犯了錯,只好自己收拾殘局。
如果你不小心放過了某個模組裡的一個bug,以致公司損失了1萬美元,結果將會怎樣呢?非專業人士會聳聳肩說:“難免要出點兒狀況嘛。”然後像沒事兒人一樣繼續寫其他模組。而專業人士會自己為公司的那1萬美元買單!
哇,自掏腰包?那可真讓人心疼唉!但專業人士就必須這麼做。實際上,專業主義的精髓就在於將公司利益視同個人利益。看到了吧,“專業主義”就意味著擔當責任。
2 擔當責任
我曾因不負責任嚐盡了苦頭,所以明白盡職盡責的重要意義。
那是1979年,當時我是一家叫Teradyne的公司的“負責工程師”,所負責的軟體控制著一個測量電話線路質量的小型機系統和微機系統,該系統的中央小型機通過頻寬為300波特的撥號電話線與幾十臺控制測量硬體的外圍微機連線在一起,程式是用匯編語言編寫的。
我們的客戶是各大電話公司的客服經理,他們每個人都負責10萬條甚至更多的電話線路。我的系統負責幫助這些服務區經理搶在客戶之前發現各種線路故障並及時修復。這可以減少客戶投訴率,以免對此做監測的公共設施委員會相應下調電話公司收取的服務費。總之,這些系統極其重要。
每天晚上,這些系統都會執行“夜間例行程式”,即中央小型機會通知外圍微機對所控制的電話線路進行檢測;每天早上,中央計算機就能獲取故障線路清單及其故障特徵。根據這些報告,各服務區經理會安排人員修復故障,這樣就不會有客戶投訴了。
一次,我對幾十個客戶推出了一版新發布。“推出”這詞可真是形象啊。我把軟體寫在磁帶上,就把這些帶子“推出”給客戶了。客戶載入這些磁帶,然後重啟系統。
這一新發布修復了幾個小故障,還增加了客戶要求的一項新功能。之前我們曾承諾會在截止日期之前提供那項新功能。我連夜趕工,總算在約定日期前交付了磁帶。
兩天後,我接到現場服務經理Tom的電話,他告訴我已經有好幾個客戶投訴“夜間例行程式”沒能執行完成,他們沒收到任何報告。我不由心頭一沉:為了按時交付軟體,我沒測試例行程式。我測試了系統的其他大部分功能,但測試例行程式要費好幾個小時,而當時我又必須交付軟體。因為故障修復部分都不涉及例行程式部分的編碼,所以我也沒擔心會有什麼不妥。
收不到夜間報告,問題可就大了。修理工們會一時無事可忙但隨後又要超負荷工作,而且,有些電話客戶也可能會在這期間發現故障並投訴。要是弄丟一晚的資料,某一服務區經理肯定會打電話臭罵Tom。
我啟動實驗室系統,載入新軟體,然後開始對“夜間例行程式”進行測試。幾小時後,執行中斷。例行程式執行失敗!如果我在匆忙交付軟體前對此進行測試,就不會發生服務區丟失資料的事了,服務區經理們這時也不會炮轟Tom了。
我打電話給Tom,說我能重現問題了。Tom告訴我其他大部分客戶也已經打電話抱怨了,並問我什麼時候能解決問題。我說我也沒把握,但正在努力。同時我告訴他應該建議客戶倒回去使用舊版軟體。Tom發火了,說那對客戶來說無疑是個雙重打擊,因為客戶不僅為此丟失了一整個晚上的資料,而且還無法使用事先承諾的新功能。
故障排查非常困難,每次測試就要好幾個小時。第一次修復失敗了。第二次也沒能成功。我試了好幾次,等我發現問題所在時,好幾天已過去了。這期間,Tom每隔幾小時就打電話問我問題什麼時候能解決,他還把那些服務區經理喋喋不休的抱怨如數傳達給我,並一再告訴我讓那些客戶重新起用舊軟體令他多麼尷尬。
最後,我終於找出了缺陷所在,重新交付修復了問題的新程式,一切恢復正常。Tom也平靜下來,不再提這段插曲,畢竟,他不是我的上司。事後,我的老闆過來對我說:“你最好別再犯同樣的錯誤。”我只能默默地點點頭。
經過反省,我意識到沒有對例行程式進行測試就交付軟體是不負責任的。為了如期交付產品,我忽略了測試環節,整個過程中只考慮要如何保全自己的顏面,卻沒顧及客戶和僱主的聲譽。我本該早點兒擔起責任,告訴Tom測試還未完成、自己不能按時交付產品。那麼做絕非易事,Tom一定會不高興,但客戶不會丟失資料,客服經理也不會打電話來轟炸。
3 首先,不行損害之事
那麼,我們該如何承擔責任呢?的確有一些原則可供參考。援引“希波克拉底誓言”或許顯得有點誇張,但沒有比這更好的引據了。的確,作為一名有追求有抱負的專業人士,他的首要職責與目標難道不正是盡其所能行有益之事嗎?
軟體開發人員能做出什麼壞事呢?從純軟體角度看,他可以破壞軟體的功能與架構。我們會探討如何避免帶來這些破壞。
3.1 不要破壞軟體功能
顯然,我們希望軟體可以執行。沒錯,我們中的大部分人今天之所以是程式設計師,是因為我們曾開發出可用的軟體,而且希望能再度體驗那種成功創作的喜悅。但希望軟體有用的不單單是我們,客戶和僱主也希望它們能用。是啊,他們出錢,讓我們去開發那些能按照他們意願執行的軟體。
開發的軟體有bug會損害軟體的功能。因此,要做得專業,就不能留下bug。
“等等!”你肯定會說,“可是那是不可能的呀。軟體開發太複雜了,怎麼可能會沒bug呢!”
當然,你說的沒錯。軟體開發太複雜了,不可能沒什麼bug。但很不幸,這並不能為你開脫。人體太複雜了,不可能盡知其全部,但醫生仍要發誓不傷害病人。如果他們都不拿“人體的複雜性”作託辭,我們又怎麼能開脫自己的責任呢?
“你的意思是我們要追求完美嘍?”你可能會這樣抬槓吧?
不,我其實是想告訴你,要對自己的不完美負責。程式碼中難免會出現bug,但這並不意味著你不用對它們負責;沒人能寫出完美的軟體,但這並不表示你不用對不完美負責。
所謂專業人士,就是能對自己犯下的錯誤負責的人,哪怕那些錯誤實際上在所難免。所以,雄心勃勃的專業人士們,你們要練習的第一件事就是“道歉”。道歉是必要的,但還不夠。你不能一而再、再而三地犯相同的錯誤。職業經驗多了之後,你的失誤率應該快速減少,甚至漸近於零。失誤率永遠不可能等於零,但你有責任讓它無限接近零。
1.讓QA找不出任何問題
因此,釋出軟體時,你應該確保QA找不出任何問題。故意傳送明知有缺陷的程式碼,這種做法是極其不專業的。什麼樣的程式碼是有缺陷的呢?那些你沒把握的程式碼都是!
有些傢伙會把QA當作啄木鳥看待。他們把自己沒有全盤檢查過的程式碼傳送過去,想等QA找出bug再反饋回來。沒錯,有些公司確實按照所發現的bug數來獎勵測試人員,揪出的bug越多,獎金越多。
且不說這麼做是否會大幅增加公司成本,嚴重損害軟體,是否會破壞計劃並讓企業對開發小組的信心打折扣,也不去評判這麼做是否等同於懶惰失職,把自己沒把握的程式碼傳送給QA這麼做本身就是不專業的。這違背了“不行損害之事”的原則。
QA會發現bug嗎?可能會吧,所以,準備好道歉吧,然後反思那些bug是怎麼逃過你的注意的,想辦法防止它再次出現。
每次QA找出問題時,更糟糕的是使用者找出問題時,你都該震驚羞愧,並決心以此為戒。
2.要確信程式碼正常執行
你怎麼知道程式碼能否常執行呢?很簡單,測試!一遍遍地測,翻來覆去、顛來倒去地測,使出渾身解數來測!
你或許會擔心這麼狂測程式碼會佔用很多時間,畢竟,你還要趕進度,要在截止日期前完工。如果不停地花時間做測試,你就沒時間寫別的程式碼了。言之有理!所以要實行自動化測試。寫一些隨時都能執行的單元測試,然後儘可能多地執行這些測試。
要用這些自動化單元測試去測多少程式碼呢?還要說嗎?全部!全部都要測!
我是在建議進行百分百測試覆蓋嗎?不,我不是在建議,我是在要求!你寫的每一行程式碼都要測試。完畢!
這是不是不切實際?當然不是。你寫程式碼是因為想執行它,如果你希望程式碼可以執行,那你就該知道它是否可行。而要知道它是否可行,就一定要對它進行測試。
我是開源專案FitNesse的主要貢獻者和程式碼提交者。在寫作本書的時候,FitNesse的程式碼有6萬多行。在這6萬行程式碼中有2000多個單元測試,超過2.6萬行。Emma的報告顯示,這2000多個測試對程式碼的覆蓋率約為90%。
為什麼只有90%呢?因為Emma會忽略一些執行的程式碼。我確信實際的覆蓋率會比90%高許多。能達到100%嗎?不,達不到,100%只是個理想值。
但是有些程式碼不是很難測試嗎?是的,但之所以很難測試,是因為設計時就沒考慮如何測試。唯一的解決辦法就是要設計易於測試的程式碼,最好是先寫測試,再寫要測的程式碼。
這一方法叫做測試驅動開發(TDD),我們在隨後的章節裡會繼續談到。
3.自動化QA
FitNesse的整個QA流程即是執行單元測試和驗收測試。如果這些測試通過了,我就會發布軟體。這意味著我的QA流程大概需要3分鐘,只要我想要,可以隨時執行完整的測試流程。
沒錯,FitNesse即使有bug也不是什麼人命關天的事,也不會有人為此損失幾百萬美元。值得一提的是FitNesse使用者上萬,但它的bug列表卻很短。
當然,也不排除有些系統因其任務極其關鍵特殊,不能只靠簡短的自動化測試來判斷軟體是否已經足夠高質量,是否可以投入使用。而且,作為開發人員,你需要有個相對迅捷可靠的機制,以此判斷所寫的程式碼可否正常工作,並且不會干擾系統的其他部分。因此,你的自動化測試至少要能夠讓你知道,你的系統很有可能通過QA的測試。
3.2 不要破壞結構
成熟的專業開發人員知道,聰明人不會為了釋出新功能而破壞結構。結構良好的程式碼更靈活。以犧牲結構為代價,得不償失,將來必追悔莫及。
所有軟體專案的根本指導原則是,軟體要易於修改。如果違背這條原則搭建僵化的結構,就破壞了構築整個行業的經濟模型。
簡言之,你必須能讓修改不必花太高代價就可以完成。
不幸的是,實在是已有太多的專案因結構糟糕而深陷失敗的泥潭。那些曾經只要幾天就能完成的任務現在需要耗費幾周甚至幾個月的時間。急於重新樹立威望的管理層於是聘來更多的開發人員來加快專案進度,但這些開發人員只會進一步破壞結構,亂上添亂。
描述如何建立靈活可維護的結構的軟體設計原則和模式已經有許多了。專業的軟體開發人員會牢記這些原則和模式,並在開發軟體時認真遵循。但是其中有一條實在是沒幾個軟體開發人員會認真照做,那就是,如果你希望自己的軟體靈活可變,那就應該時常修改它!
要想證明軟體易於修改,唯一辦法就是做些實際的修改。如果發現這些改動並不像你預想的那樣簡單,你便應該改進設計,使後續修改變簡單。
該在什麼時候做這些簡單的小修改呢?隨時!關注哪個模組,就對它做點簡單的修改來改進結構。每次通讀程式碼的時候,也可以不時調整一下結構。
這一策略有時也叫“無情重構”,我把它叫作“童子軍訓練守則”:對每個模組,每檢入一次程式碼,就要讓它比上次檢出時變得更為簡潔。每次讀程式碼,都別忘了進行點滴的改善。
這完全與大多數人對軟體的理解相反。他們認為對上線執行的軟體不斷地做修改是危險的。錯!讓軟體保持固定不變才是危險的!如果一直不重構程式碼,等到最後不得不重構時,你就會發現程式碼已經“僵化了”。
為什麼大多數開發人員不敢不斷修改他的程式碼呢?因為他們害怕會改壞程式碼!為什麼會有這樣的擔心呢?因為他們沒做過測試。
話題又回到測試上來了。如果你有一套覆蓋了全部程式碼的自動化測試,如果那套測試可以隨時快速執行,那麼你根本不會害怕修改程式碼。怎樣才能證明你不怕修改程式碼呢?那就是,你一直在改。
專業開發人員對自己的程式碼和測試極有把握,他們會極其瘋狂隨意地做各種修改。他們敢於隨心所欲修改類的名稱。在通讀程式碼時,如果發現一個冗長的方法,他們肯定會將它拆分,重新組織。他們還會把switch語句改為多型結構,或者將繼承層次重構成一條“命令鏈”。簡單地說,他們對待程式碼,就如同雕塑家對待泥巴那樣,要對它進行不斷的變形與塑造。
4 職業道德
職業發展是你自己的事。僱主沒有義務確保你在職場能夠立於不敗之地,也沒義務培訓你,送你參加各種會議或給你買各種書籍充電。這些都是你自己的事。將自己的職業發展寄希望於僱主的軟體開發人員將會很慘。
有些僱主願意為員工買各種書籍或送員工參加各種培訓課程和會議。那樣挺不錯的,說明他們待你不薄。但可千萬別就此認為這些是僱主該做的。如果他們不為你做這些,你就該自己想辦法去做。
另外,僱主也沒義務給你留學習時間。有些僱主會這麼做,有些甚至要求你這麼做。但是還是那句話,他們待你不薄,你應該適當表示感激。因為這些優待不是你理所當然就該享有的。
僱主出了錢,你必須付出時間和精力。為了說明問題,就用一週工作40小時的美國標準來做參照吧。這40小時應該用來解決僱主的問題,而不是你自己的問題。
你應該計劃每週工作60小時。前40小時是給僱主的,後20小時是給自己的。在這剩餘的20小時裡,你應該看書、練習、學習,或者做其他能提升職業能力的事情。
你肯定會說:“那我的家庭該怎麼辦?還有我的生活呢?難道我就該為僱主犧牲這些嗎?”
在此,我不是說要佔用你全部的業餘時間。我是指每週額外增加20小時,也就是大約每天3小時。如果你在午飯時間看看書,在通勤路上聽聽播客,花90分鐘學一門新的語言,那麼你就都能兼顧到了。
做個簡單的計算吧。一週有168小時,給你的僱主40小時,為自己的職業發展留20小時,剩下的108小時再留56小時給睡眠,那麼還剩52小時可做其他的事呢。
或許你不願那麼勤勉。沒問題。只是那樣的話你也不能自視為專業人士了,因為所謂“術業有專攻”那也是需要投入時間去追求的。
或許你會覺得工作就該在上班時完成,不該再帶回家中。贊成!那20小時你不用為僱主工作。相反,你該為自己的職業發展工作。
有時這兩者並不矛盾,而是一致的。有時你為僱主做的工作讓你個人的職業發展受益匪淺,這種情況下,在那20小時裡花點時間為僱主工作也是合理的。但別忘了,那20小時是為你自己的。它們將會讓你成為更有價值的專業人士。
或許你會覺得這樣做只會讓人精力枯竭。恰恰相反,這樣做其實能讓你免於枯竭匱乏。假設你是因為熱愛軟體而成為軟體開發者,渴望成為專業開發者的動力也正是來自對軟體的熱情,那麼在那20小時裡,就應該做能夠激發、強化你的熱情的事。那20小時應該充滿樂趣!
4.1 瞭解你的領域
你知道什麼是N-S(Nassi-Schneiderman)圖表嗎?如果不知道,那為什麼不瞭解一下呢?你知道“米利型”(Mealy)和“摩爾型”(Moore)這兩種狀態機的差別嗎?你應該知道的。你能不需查閱演算法手冊就可寫出一個快速排序程式嗎?你知道“變換分析”(Transform Analysis)這個術語的意思嗎?你知道如何用資料流圖進行功能分解嗎?你知道“臨時傳遞資料”(Tramp Data)的意思嗎?你聽說過“耦合性”(Conascence)嗎?什麼是Parnas表呢?
近50年來,各種觀點、實踐、技術、工具與術語在我們這一領域層出不窮。你對這些瞭解多少呢?如果想成為一名專業開發者,那你就得對其中的相當一大部分有所瞭解,而且要不斷擴充套件這一知識面。
為什麼要了解這些呢?這一行業發展迅速,許多舊見解似乎也已經過時了,不是嗎?前半句似乎是顯而易見的。確實,行業正迅猛發展,而有趣的是,從多個方面來看,這種進展都只是很淺層的。沒錯,我們不再需要為拿到編譯結果苦等上24小時,我們也已經可以寫出GB級別的系統,我們置身覆蓋全球的網路之中,各種資訊唾手可得。但另一方面,我們還是跟50年前一樣,寫著各種if和while語句。所以,改變說多也多,說少也少。
舊見解過時了這種說法明顯是不對的。過去50年中產生的理念,已經過時的其實很少。有一部分理論確實在慢慢淡出,比如說“瀑布式開發”的理論確實不再流行了。但這並不表示我們不需要了解它,不需要知道它的長處和短處。
總的來說,那些在過去50年中來之不易的理念,絕大部分在今天仍像過去一樣富有價值,甚至寶貴了。
別忘了桑塔亞納的詛咒:“不能銘記過去的人,註定要重蹈覆轍。”
下面列出了每個專業軟體開發人員必須精通的事項。
* 設計模式。必須能描述GOF書中的全部24種模式,同時還要有POSA書中的多數模式的實戰經驗。
* 設計原則。必須瞭解SOLID原則,而且要深刻理解元件設計原則。
* 方法。必須理解XP、Scrum、精益、看板、瀑布、結構化分析及結構化設計等。
* 實踐。必須掌握測試驅動開發、物件導向設計、結構化程式設計、持續整合和結對程式設計。
* 工件。必須瞭解如何使用UML圖、DFD圖、結構圖、Petri網路圖、狀態遷移圖表、流程圖和決策表。
4.2 堅持學習
軟體行業的飛速改變,意味著軟體開發人員必須堅持廣泛學習才不至於落伍。不寫程式碼的架構師必然遭殃,他們很快會發現自己跟不上時代了;不學習新語言的程式設計師同樣會遭殃,他們只能眼睜睜看著軟體業一路發展,把自己拋在後面;學不會新規矩和新技術的開發人員更可憐,他們只能在日漸淪落的時候看著身邊人越發優秀。
你會找那些已經不看醫學期刊的醫生看病嗎?你會聘請那些不瞭解最新稅法和判例的稅務律師嗎?僱主們幹嘛要聘用那些不能與時俱進的開發人員呢?
讀書,看相關文章,關注部落格和微博,參加技術大會,訪問使用者群,多參與讀書與學習小組。不懂就學,不要畏難。如果你是.NET程式設計師,就去學學Java;如果你是Java程式設計師,就去學學Ruby;如果你是C語言程式設計師,就去學學Lisp;如果你真想練練腦子,就去學學Prolog和Forth吧!
4.3 練習
業精於勤。真正的專業人士往往勤學苦幹,以求得自身技能的純熟精煉。只完成日常工作是不足以稱為練習的,那隻能算是種執行性質的操作,而不是練習。練習,指的是在日常工作之餘專門練習技能,以期自我提升。
對軟體開發人員來說,有什麼可以用以操練的呢?乍一聽,這概念顯得荒唐。但是再仔細想一會兒,想想音樂家是如何掌握演練技能的。他們靠的不是表演,而是練習。他們又是如何練習的呢?首先,表演之前,都需要經歷過特別的訓練,音階、練習曲、不斷演奏等。他們一遍又一遍地訓練自己的手指和意識,保持技巧純熟。
那麼軟體開發者該怎樣來不斷訓練自己呢?本書會用一整章的篇幅來談論各種練習技巧,所以在此先不贅述了。簡單說,我常用的一個技巧是重複做一些簡單的練習,如“保齡球遊戲”或“素數篩選”,我把這些練習叫作“卡塔”(kata)。卡塔有很多型別。
卡塔的形式往往是一個有待解決的簡單程式設計問題,比如編寫計算拆分某個整數的素數因子等。練卡塔的目的不是找出解決方法(你已經知道方法了),而是訓練你的手指和大腦。
每天我都會練一兩個卡塔,時間往往安排在正式投入工作之前。我可能會選用Java、Ruby、Clojure或其他我希望保持純熟的語言來練習。我會用卡塔來培養某種專門的技能,比如讓我的手指習慣點選快捷鍵或習慣使用某些重構技法等。
不妨早晚都來個10分鐘的卡塔吧,把它當作熱身練習或者靜心過程。
4.4 合作
學習的第二個最佳方法是與他人合作。專業軟體開發人員往往會更加努力地嘗試與他人一起程式設計、一起練習、一起設計、一起計劃,這樣他們可以從彼此身上學到很多東西,而且能在更短的時間內更高質量地完成更多工作。
並不是讓你花全部時間一直和別人共事。獨處的時間也很重要。雖然我很喜歡和別人一起程式設計,但是如果不能經常獨處,我也一樣會發瘋。
4.5 輔導
俗話說:教學相長。想迅速牢固地掌握某些事實和觀念,最好的辦法就是與你負責指導的人交流這些內容。這樣,傳道授業的同時,導師也會從中受益。
同樣,讓新人融入團隊的最好辦法是和他們坐到一起,向他們傳授工作要訣。專業人士會視輔導新人為己任,他們不會放任未經輔導的新手恣意妄為。
4.6 瞭解業務領域
每位專業軟體開發人員都有義務瞭解自己開發的解決方案所對應的業務領域。如果編寫財務系統,你就應該對財務領域有所瞭解;如果編寫旅遊應用程式,那麼你需要去了解旅遊業。你未必需要成為該領域的專家,但你仍需要用功,付出相當的努力來認識業務領域。
開始一個新領域的專案時,應當讀一兩本該領域相關的書,要就該領域的基礎架構與基本知識作客戶和使用者訪談,還應當花時間和業內專家交流,瞭解他們的原則與價值觀念。
最糟糕、最不專業的做法是,簡單按照規格說明來編寫程式碼,但卻對為什麼那些業務需要那樣的規格定義不求甚解。相反,你應該對這一領域有所瞭解,能辨別、質疑規格說明書中的錯誤。
4.7 與僱主/客戶保持一致
僱主的問題就是你的問題。你必須弄明白這些問題,並尋求最佳的解決方案。每次開發系統,都應該站在僱主的角度來思考,確保開發的功能真正能滿足僱主的需要。
開發人員之間互相認同是容易的,但把一方換成僱主,人們就容易產生“彼”“此”之分。專業人士會盡全力避免這樣的狹隘之見。
4.8 謙遜
程式設計是一種創造性活動。寫程式碼是無中生有的創造過程,我們大膽地從混沌之中建立秩序。我們自信地釋出準確無誤的指令,稍有差錯,機器的錯誤行為就可能造成無法估量的損失。因此,程式設計也是極其自負的行為。
專業人士知道自己自負,不會故作謙遜。他們熟知自己的工作,並引以為榮;他們對自己的能力充滿自信,並因此勇於承擔有把握的風險。專業人士不是膽小鬼。
然而,專業人士也知道自己會摔跟頭,自己的風險評估也有出錯的時候,自己也有力不從心的時候。這時候,如果他們照照鏡子,會看到那個自負的傻瓜正對著自己笑。
因此,在發現自己成為笑柄時,專業人士會第一個發笑。他從不會嘲諷別人,自作自受時他會接受別人的嘲諷。反之,他則會一笑了之。他不會因別人犯錯就對之橫加貶損,因為他知道,自己有可能就是下一個犯錯的人。
專業人士都清楚自己的自負,也知道上天會注意到這種自負,並加以懲戒。如若果真遭遇挫折,最好的辦法就是按照霍華德說的——一笑了之吧!
相關文章
- 程式設計師必須走向專業化程式設計師
- 普通程式設計師走向“專業”的燈塔程式設計師
- SAP解決方案賦能中小企業走向“專精特新”
- 網易微專業大資料工程師大資料工程師
- java工程師走向前端學習心路歷程(二)Java工程師前端
- 韓國IT業是如何走向世界的
- ERP助企業走向智慧化管理
- 環境專業,環境中高階工程師職稱工程師
- 什麼專業轉行web前端開發工程師,就業率最高?Web前端工程師就業
- 頻頻破圈,走向百業:大模型的畢業季大模型
- 網路工程師必懂的專業術語 ZZ (轉)工程師
- 職業轉型的終極指南:從新手到專業的機器學習工程師機器學習工程師
- 走向 DockerDocker
- 化工——一個走向數字化的成熟行業行業
- 2015年終總結 走向職業化
- 機器學習工程師31門課程(視訊):從新手到專業機器學習工程師
- 技術專案走向失敗的五條“捷徑”
- 是小廠全棧好,還是大廠專業工程師好?全棧工程師
- 將專業帶入家庭 明基工程師認證課程開課工程師
- python全棧工程師-CSDN就業班-專題視訊課程Python全棧工程師就業
- 圖資料平臺引領零售業走向成功
- java走向滅亡Java
- AI工程師百天計劃-CSDN就業班-專題視訊課程AI工程師就業
- 今晚直播:展望2022,作業系統將走向何方?作業系統
- 企業IT架構走向多雲需解決三大難題架構
- IDC行業正在走向正規化,都有哪些趨勢呢?行業
- NACE:2013年美國畢業生年高薪專業排名 工程師和電腦科學居首高薪工程師
- Java工程師就業前景分析Java工程師就業
- 軟體工程師的職業生涯軟體工程工程師
- Payscale:美國石油工程師是2018年薪酬最高的大學專業工程師
- 遊戲創業者如何克服困難,控制焦慮情緒,走向成功遊戲創業
- 網際網路創業公司走向失敗的十大因素創業
- 走向產品是程式設計師的第三條職業通道程式設計師
- 免費模式的未來走向是否有利於行業發展?模式行業
- UOF默默走向應用
- 招聘java工程師 java高階工程師 -高薪急聘 電信專案Java工程師高薪
- Web全棧工程師前景+學習指南-CSDN就業班-專題視訊課程Web全棧工程師就業
- 創業公司的 Nodejs 工程師創業NodeJS工程師