程式設計師應該怎樣提高自己?

it技術之家 發佈 2020-01-02T11:25:19+00:00

DonKnuth 說,Premature optimization is the root of all evil ,這句話背後的道理,不必一開始就強行接受。

經常有小(我 20 歲左右的)朋友問我(雲風),作為一個程式設計師該怎樣提高自己。每個人的經歷不同,所處環境不錯,其實這個問題很難具體回答。不如好好寫一篇總結,以後就不必每封 email 都重新寫一次了。

縱觀我近 30 年的編程生涯,在每個時期,我看到的東西都不同。想必再過 10 年還會有變遷。我只能寫寫當下眼界所及之處。

引我愛上編程,並樂此不疲的學習,是「我能寫出更高效的代碼」這種樂趣。如果一個人在學習編程開始,不努力讓自己的代碼變得更高效,發現不了優化的樂趣,我想他很難愛上編程。Don Knuth 說,Premature optimization is the root of all evil ,這句話背後的道理,不必一開始就強行接受。evil 最能蠱惑人心,但是我們需要它引入門。

朝著優化這條路走下去,你會有自發的動力去了解計算機的本質架構,理解作業系統,理解內存模型,理解新的軟硬體技術(它們大多數都是為了讓程序跑的更快而發明出來)。否則,現在去學習這些東西,並不會體會到現實的意義。軟體開發在今天,大部分的工作都在很高的層次了,大部分人的日常都在完成一些瑣碎的業務,用不到這些。但實際上,你在融匯貫通後,可以在很高的層面憑經驗就能從蛛絲馬跡判斷出底層發生的問題;可以從一些代碼片段,判斷出整個模塊的設計意義。這些是無法作為單獨的技能學會的。

精通一門語言是最基本的要求。所謂精通,就是要了解這門語言的各種陰暗角落。用每一樣語言特性的背後的代價。知道在面臨各種問題時用這門語言解決該問題的慣用法。大部分通用語言都會有設計缺陷,表現在具體方面就是面對某些問題,寫起來直接了當,而另一類問題時卻要繞很多彎彎,這些繞彎彎的部分就需要用某種模式去彌補。我認為,所謂編程的設計模式,並不是跨語言而獨立存在的,它們是強烈依附於程式語言的。《設計模式》這本書,我讀過的版本是基於 C++ 的,設計模式被談論的更多的是在 Java 社區。這類模式都有很深的語言烙印。我們學習設計模式其實學的就是一門語言的慣用法。

初次學習設計模式時,肯定會有豁然開朗的感覺。但不應把自己陷入其中。為了提高一次層次,就必須精通至少第二門的語言。我的第一語言是 C ,第二語言是 Lua 。但對於許多人,肯定會有很多更好的選擇。多看看不同的語言下解決問題的不同方式,有助於提高編程技能。

在我談論程式設計師的編程技能的時候,我指的通常是兩類能力:一是運用熟悉的程式語言,用在該語言下最高效的方法解決需求的能力;二是領域知識,儘量多的了解工作所處領域前人的積累,已存在的軟體層次的接口,接口背後的代價。這兩者缺一不可。不要用自己學習能力強為藉口,認為隨時可以進入一個新語言,一個新領域,而不會比別人差。不管是一門語言的使用,還是對一個領域的了解,都是需要長期的實踐刻意積累的。

以上,都是我認為一個程式設計師對自己最基本的要求。這些東西多麼精進都不為過。但還有一些更高層面的東西。

那就是分解問題,保持簡潔的能力。也可以說是規劃和構架的能力。這是超出程式語言,具體問題領域的,不過絕不能繞開它們。如果一個程式設計師編碼很粗糙,或是對所在領域一知半解,我絕對不會信任他做的設計。

Keep It Simple, Stupid 誰都會說,但不受優化的蠱惑,我覺得很難。因為完全對優化代碼免疫的人,我覺得他很難成為一名優秀的程式設計師。邁不過第一步,就談不上在下一步有什麼成就。大部分軟體問題,本質上都是怎麼把複雜問題分層次,分模塊,化繁為簡的過程。底層開發、基礎設施建設為什麼吸引了很多自命熱愛編程的人,不是因為它們有挑戰,相反,它們更純粹,更簡單,更容易做取捨。精益求精的人更容易做出成績。


帶著把各方各面都做到精益求精的心,跨越多個層次去看整個問題。奉著此心做取捨,知道封裝和簡化帶來的代價,隨時審視代價到底值不值。我很難總結出教條,這似乎真的只能用個人品味去解釋:為什麼這裡要保持更樸素的數據結構,而犧牲高效的算法;那裡為了少定義一個 api ,卻讓一件簡單的任務變得更繁瑣。

另一方面,規劃不僅僅是針對代碼,也包括了開發過程的一切。你不僅需要規劃問題怎樣劃分,還要規劃每個部分花多少時間和精力,區分輕重緩急。順便談談超時工作的問題,我在前段談 996 的時候就寫過,超時工作其實反映的是規劃的失誤。找到正確的方法做事,最終需要投入的人力能有 10,100 倍的差距;而延長工作時間卻無法超過 3 倍工時。提高自己的規劃能力,應該先盡力減少超時工作。


前段時間有人問我,現在讓你去面試程式設計師,你會考察些什麼。我想了想,最近幾年,我越發的不會做面試了。越來越不喜歡用具體技術問題考驗面試者。

相比編寫代碼、調試代碼、閱讀代碼、這些硬能力;我可能更為看重對各類工具掌握的軟能力。比如有些人對 C++ 的犄角旮旯了解的一清二楚,卻對 C++ 編譯器的命令行參數一知半解,只會使用 IDE 開發,我覺得這樣的技術棧是非常畸形的。軟體的構建流程絕不僅僅是寫好代碼,就全部交給自動化工具去完成。即使僅局限於寫代碼,那麼用代碼生成代碼,設計 DSL 解決領域問題,也是必備技能。這些在 meta 層面解決問題的方式,離不開你對構建工具的了解。

我們在日常工作中面臨的很多瑣碎,大部分都有現成的工具解放你的時間。分析日誌 ,加工數據、收集信息,等等。都有很多途徑去做。有笨拙的手工方法,有工具語言方便你編寫腳本批處理,有現成的工具待你去發掘學習。看看你的工具箱裡是不是只有一把錘子?


開源逐漸成為主流,我認為是現代軟體開發方式的重大變遷。程式設計師群體可能是為數不多的,頂尖個體的生產力能夠百倍千倍於平均水平的人群了。世界範圍的開源開發,使得最頂尖的人可以把精力聚焦在不同的點,極大的放大他們的價值。所以造輪子固然有趣,會用輪子卻更為重要。但大多數情況下,我們不能像搭樂高積木一樣的組裝軟體——雖然那一定是每個開源模塊的努力方向——理解和溝通的能力就顯得格外重要。

有一段時間我在招聘應屆畢業生時甚至覺得,考察寫的代碼好不好一點都不重要。真不如看看他寫的文章,寫的東西簡單還是複雜不重要,就看有沒有能力把事情說清楚。

在開源的世界中,不是你有能力讀懂別人的代碼就夠了。如果你想使用,就必然面臨你特有的需求,也有極大的可能性遇到別人沒有遇到的問題。和作者溝通,和開發社區建立起良好的關係,說服維護者按你的想法推進這個軟體的發展,或是吸納別人的想法修正自己的設計,這是非常重要的技能。而弄個 fork 自己隨心所欲的修改,甚至重起爐灶自造輪子,自己的層次就很難進一步突破了。

談到這裡,不得不提的是, git 絕對是軟體行業近二十年最偉大的發明之一。它值得每個程式設計師正兒八經的學習,絕不應滿足於會 commit push pull 就夠了。它是進入開源世界的敲門磚。一個能力超強的程式設計師,如果不融入同樣頂尖的團體,就是在浪費自己的人生。

作者:雲風

連結:https://blog.codingnow.com/2019/07/top_programmer.html

關鍵字: