程序員水平的高低指的是什麼

一個關於程序員水平的思考

img

很多程序員可能聽說過一句話:“Talk is cheap, show me the code”。 是的,這句話就是linux操作系統的締造者Linus Torvalds說出來的。他本人的成就這裏不去描述,實在描述不過來。用網上的一句話就是“他用了50年的時間達到了別人幾輩子都無法企及的高度”。

​ 這句話,其實很好理解:口說無憑,把你的成果拿出來一看便知。也許你是大牛,這在你的代碼上能很好的體現,不用多說我們也能看出來。如果你是一個水平很low或者一般的攻城獅,可能口才很棒,說話水平一流,但是你的代碼如果一般,那麼我們也會認爲你不是一個合格的程序員。 這用在程序員身上是很容易理解的,而且程序員更注重代碼水平,口才不是排在第一位的。

​ 舉個自己的親身體會吧:

​ 我以前偶爾(也沒那麼偶爾)看到別人寫的開源代碼,因爲我主要是做網絡方向的,這部分的開源代碼基本都是C語言實現的(例如各種通信協議)。C語言的基礎我的水平也算是熟悉的階段(沒人敢談精通),看基本的語法是沒什麼問題的,偶爾來幾個個性的寫法確實看不懂(比如說signal函數實現、container_of實現等、… …),但是說一個完整的項目功能,不可能完全是這個晦澀的語法的堆積,因此在語法上基本都是可以看懂的。那麼問題來了,只看的懂語法,不知道人家在做什麼,實現什麼功能該怎麼辦? 也許會有人問:“既然能看得懂語法,你怎麼可能不知道人家在幹什麼?”。 這個問題確實是存在的,我們在看得懂人家的代碼的基礎上要學習人家的思想:爲什麼這個實現? 其他的方式不行嗎?這實現的好處是什麼? 當然這一連串的問題可能需要我們花費比較長的時間一個個來思考。這所有的一切的前提都是能看懂人家的代碼。

​ 還是這個問題“如何才能看得懂人家的代碼”?

​ 我們只拿C語言來說話,因爲這個最基礎,很多人在大學都接觸過。 它的語法說句實話,不是很多。也許函數接口比較多,但是我們經常用的卻是比較少的,比如:IO類(read, write,close,open…),進程類、線程類、IPC類、網絡通信類(TCP、UDP函數接口)、IO複用等。這部分函數我們一般都會接觸到或者經常用到,可以說比較熟。但是,對,是但是,它們我們也許只是看着很熟悉,它們的用法真的熟悉嗎?舉幾個例子:

  • TCP能使用sendto發送數據嗎?SYN包能攜帶數據嗎?
  • select, poll, epoll函數的區別是什麼?(面試可能經常遇到)
  • 爲什麼要線程分離?
  • 常見的信號類型及處理方式;信號進程屏蔽字

這些有一部分是我之前的疑問,有一些是看開源代碼是自己思考的。我們不是看不懂人家的語法,而是對這個基礎知識理解太淺,雖然基礎知識很少,但是每一個點都是值得深究的。不是說拿起課本直接開始啃,而是遇到一個學習一個(最最常用的那些其實也沒那麼多)。在舉個例子:

​ 我們都知道IO多路複用中的select和poll函數。select函數有個不好的地方:它監控的描述符有限(可能是1024左右),而且監控越多效率多低。而我在看openswan代碼的時候就遇到一個用法:他們自己實現了struct fd_set以及對應的操作函數FD_SET, FD_ISSET, FD_ZERO等,然後在select調用時,使用他們自己的fd_set類型。他們的基本用法我知道,但是是否可以自己定義類型、修改後是否能用等我之前並不知道。也許這個問題並不影響我們對這個代碼的理解,也許這就是我們與他們存在的一個小小的差距。

​ 接着上述的問題,我們再說select和poll的一個例子:(我只用openswan中的原話)

/* Even though select(2) says that there is a message,
* it might only be a MSG_ERRQUEUE message.  At least
* sometimes that leads to a hanging recvfrom.  To avoid
* what appears to be a kernel bug, check_msg_errqueue
* uses poll(2) and tells us if there is anything for us
* to read.
*
* This is early enough that teardown isn't required:
* just return on failure.
*/
if (!check_msg_errqueue(ifp, POLLIN))

這個使用的情形是:通過select函數監控所有的網口的一個端口(500),當其中有讀事件準備好時,select函數返回執行上面的代碼。但是select可能返回的是一個“MSG_ERRQUEUE”,而這個錯誤會導致讀阻塞,因此再使用poll函數檢查是否存在上述“MSG_ERRQUEUE”。說句實話,這種用法我第一次遇到,也是對select、poll不熟導致的吧。

​ 看源碼還有個難點就是:他們的數據結構之間的組織關係。這部分沒有什麼技術上的難點,但是邏輯上、實現上讓我懷疑人生的感覺。

​ 我們與大神級程序員的差別也許就在那些基礎知識的理解深度上,同樣的兩個人:一個普通程序員、一個微軟Google等的高級程序員,對待同一個功能實現,可能基本的函數接口相同,但是他們考慮的情況很多、程序的健壯性、魯棒性更好。這不僅僅是他們遇到這類情況多,另一個原因可能是他們知道使用那些接口會遇到什麼樣的問題,然後再使用另一種方式來進行彌補、檢測。

在這裏插入圖片描述

​ 也許Linux很普及、也許Nginx功能很強大、也許VPN很安全、也許網絡發展的很快很快。但他們都是用C語言支撐起來的。

​ 也許C語言很容易入門。但它真的很難。

​ 也許程序員喫的真是青春飯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章