程式設計師技能層次模型

2021-03-06 MOOC

編程技能層次

編程技能層次,指的程式設計師設計和編寫程序的能力。這是程式設計師的根本。

0段—非程式設計師:

初學編程者,遇到問題,完全是懵懵懂懂,不知道該怎麼編程解決問題。也就是說,還是門外漢,還不能稱之為「程式設計師」。計算機在他面前還是一個神秘的黑匣子。

1段—基礎程式設計師:

學習過一段時間編程後,接到任務,可以編寫程序完成任務。

編寫出來的代碼,正常情況下是能夠工作的,但在實際運行中,碰到一些特殊條件就會出現各類BUG。也就是說,具備了開發Demo軟體的能力,但開發的軟體真正交付給客戶使用,恐怕會被客戶罵死。

程式設計師程序是寫好了,但到底為什麼它有時能正常工作,有時又不行,程式設計師自己也不知道。

運行中遇到了bug,或者需求改變,需要修改代碼或者添加代碼,很快程序就變得結構混亂,代碼膨脹,bug叢生。很快,就連最初的開發者自己也不願意接手維護這個程序了。

2段—數據結構:

經過一段時間的編程實踐後,程式設計師會認識到「數據結構+算法=程序」這一古訓的含義。他們會使用算法來解決問題。進而,他們會認識到,算法本質上是依附於數據結構的,好的數據結構一旦設計出來,那麼好的算法也會應運而生。

設計錯誤的數據結構,不可能生長出好的算法。

記得某一位外國先賢曾經說過:「給我看你的數據結構!」

3段—面向對象:

再之後,程式設計師就會領略面向對象程序設計的強大威力。大多數現代程式語言都是支持面向對象的。但並不是說,你使用面向對象程式語言編程,你用上了類,甚至繼承了類,你就是在寫面向對象的代碼了。

我曾經見過很多用Java,Python,Ruby寫的面向過程的代碼。

只有你掌握了接口,掌握了多態,掌握了類和類,對象和對象之間的關係,你才真正掌握了面向對象編程技術。

就算你用的是傳統的不支持面向對象的程式語言,只要你心中有「對象」,你依然可以開發出面向對象的程序。

如,我用C語言編程的時候,會有意識的使用面向對象的技巧來編寫和設計程序。用struct來模擬類,把同一類概念的函數放在一起模擬類。如果你懷疑用C語言是否能編寫出面向對象的代碼,你可以看一下Linux內核,它是用C語言編寫的,但你也可以看到它的原始碼字裡行間散發出的濃濃的「對象」的味道。

真正掌握面向對象編程技術並不容易。

在我的技術生涯中,有兩個坎讓我最感頭疼。

一個坎是Dos向Windows開發的變遷過程中,框架的概念,很長一段時間我都理解不了。Dos時代,都是對函數庫的調用,你的程序主動調用函數。Windows時代,則換成了框架。就算是你的main程序,其實也是被框架調用的。UI線程會從作業系統獲取消息,然後發送給你的程序來處理。Java程式設計師熟悉的Spring框架,也是這樣一個反向調用的框架。

現在因為「框架」這個術語顯得很高大上,因此很多「類庫」/「函數庫」都自稱為「框架」。在我看來這都是名稱的濫用。

「類庫」/「函數庫」就是我寫的代碼調用它們。

「框架」就是我註冊回調函數到框架,框架來調用我寫的函數。

另一個坎就是面向對象。很長一段時間我都不知道應該怎麼設計類和類之間的關係,不能很好的設計出類層次結構來。

我記得當時看到一本外國大牛的書,他講了一個很簡單、很實用的面向對象設計技巧:「敘述問題。然後把其中的名詞找出來,用來構建類。把其中的動詞找出來,用來構建類的方法」。雖然這個技巧挺管用的,但也太草根了點,沒有理論依據,也不嚴謹。如果問題敘述的不好,那麼獲得的類系統就會是有問題的。

掌握面向對象思想的途徑應該有很多種,我是從關係資料庫中獲得了靈感來理解和掌握面向對象設計思想的。

在我看來,關係資料庫的表,其實就是一個類,每一行記錄就是一個類的實例,也就是對象。表之間的關係,就是類之間的關係。O-Rmapping技術(如Hibernate),用於從面向對象代碼到資料庫表之間的映射,這也說明了類和表確實是邏輯上等價的。

既然資料庫設計和類設計是等價的,那麼要設計面向對象系統,只需要使用關係資料庫的設計技巧即可。

關係資料庫表結構設計是很簡單的:

1,識別表和表之間的關係,也就是類和類之間的關係。是一對一,一對多,多對一,還是多對多。這就是類之間的關係。

2,識別表的欄位。一個對象當然有無數多的屬性(如,人:身高,體重,性別,年齡,姓名,身份證號,駕駛證號,銀行卡號,護照號,港澳通行證號,工號,病史,婚史etc),我們寫程序需要記錄的只是我們關心的屬性。這些關心的屬性,就是表的欄位,也就是類的屬性。「弱水三千,我取一瓢飲」!

4段—設計模式:

曾經在網上看到這樣一句話:「沒有十萬行代碼量,就不要跟我談什麼設計模式」。深以為然。

記得第一次看Gof的設計模式那本書的時候,發現雖然以前並不知道設計模式,但在實際編程過程中,其實還是自覺使用了一些設計模式。設計模式是編程的客觀規律,不是誰發明的,而是一些早期的資深程式設計師首先發現的。

不用設計模式,你也可以寫出滿足需求的程序來。但是,一旦後續需求變化,那麼你的程序沒有足夠的柔韌性,將難以為繼。而真實的程序,交付客戶後,一定會有進一步的需求反饋。而後續版本的開發,也一定會增加需求。這是程式設計師無法迴避的現實。

寫UI程序,不論是Web,Desktop,Mobile,Game,一定要使用MVC設計模式。否則你的程序面對後續變化的UI需求,將無以為繼。

設計模式,最重要的思想就是解耦,通過接口來解耦。這樣,如果將來需求變化,那麼只需要提供一個新的實現類即可。

主要的設計模式,其實都是面向對象的。因此,可以認為設計模式是面向對象的高級階段。只有掌握了設計模式,才能認為是真正徹底掌握了面向對象設計技巧。

我學習一門新語言時(包括非面向對象語言,如函數式程式語言),總是會在了解了其語法後,看一下各類設計模式在這門語言中是如何實現的。這也是學習程式語言的一個竅門。

5段--語言專家:

經過一段時間的編程實踐,程式設計師對某一種常用的程式語言已經相當精通了。有些人還成了「語言律師」,擅長向其他程式設計師講解語言的用法和各種坑。

這一階段的程式設計師,常常是自己所用語言的忠實信徒,常在社區和論壇上和其他語言的使用者爭論哪一種語言是最好的程式語言。他們認為自己所用的語言是世界上最好的程式語言,沒有之一。他們認為,自己所用的程式語言適用於所有場景。他們眼中,只有錘子,因此會把所有任務都當成是釘子。

6段--多語言專家:

這一個階段的程式設計師,因為工作關係,或者純粹是因為對技術的興趣,已經學習和掌握了好幾種程式語言。已經領略了不同程式語言不同的設計思路,對每種語言的長處和短處有了更多的了解。

他們現在認為,程式語言並不是最重要的,程式語言不過是基本功而已。

他們現在會根據不同的任務需求,或者不同的資源來選擇不同的程式語言來解決問題,不再會因為沒有使用某一種喜愛的程式語言開發而埋怨。

程式語言有很多種流派和思想,有一些程式語言同時支持多種編程範式。

靜態類型編程範式

採用靜態類型編程範式的程式語言,其變量需要明確指定類型。代表語言:C,C++,Pascal,Objective-C,Java,C#,VB.NET,Swif,Golang。

這樣做的好處是:

1,編譯器可以在編譯時就能找出類型錯誤。    

2,編譯器編譯時知道類型信息,就可以提高性能。

這種範式認為,程式設計師肯定知道變量的類型,你丫要是不知道變量的類型,那你就別混了!編譯時,程序會報錯。

Swift和Go語言都是靜態類型程式語言,但它們都不需要明確指定類型,而是可以通過推斷由編譯器自動確定其類型。

動態類型編程範式

採用靜態類型編程範式的程式語言,其變量不需要明確指定類型。任意變量,可以指向任意類型的對象。代表語言:Python,Ruby,JavaScript。

動態類型的哲學可以用鴨子類型(英語:ducktyping)這個概念來概括。JamesWhitcombRiley提出的鴨子測試可以這樣表述:「當看到一隻鳥走起來像鴨子、遊泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。」

這種範式認為,程式設計師肯定知道變量的類型和它支持的方法和屬性,你丫要是不知道變量的類型,那你就別混了!運行時程序會崩潰!程序崩潰怨誰?怨你自己唄,你不是合格的程式設計師!

動態類型的好處是:

不需要明確定義接口和抽象類型。只要一個類型支持需要的方法和屬性,那麼就OK。程序會相當靈活和簡單。C++,Java,C#視之為命脈的接口/基類,在動態語言這裡都視如無物!

缺點是:

1,如果類型不對,編譯器也無法找到錯誤,而是運行時程序崩潰。

2,因為編譯器不知道變量的類型,因此無法優化性能。

面向對象編程範式

面向對象編程範式,從上世紀70年代末開始興起。它支持類和類的實例作為封裝代碼的模塊。代表語言:Smalltalk,C++,Objective-C,Java,C#,VB.NET,Swift,Go,Python,Ruby,ActionScritp,OCaml.

早期程式語言都是面向過程的。就是順序,條件,循環,構成一個個函數。隨著代碼規模的增大,人們發現有必要對代碼進行模塊化。一個概念對應的代碼放在一個文件中,這樣便於並發開發和進行代碼管理。

人們還發現了「程序=數據結構+算法」的規律。因此,一個概念對應的數據結構和函數應該放在一個文件中。這就是類的概念。

面向對象編程範式,確實極大地提高了生產效率,因此得到了廣泛的應用,因此在語言層面支持面向對象編程範式的語言是極多的。

C語言儘管在語言層面上並不支持面向對象編程範式,但現代的C語言開發都會應用面向對象的模塊化思想,把同一類的數據結構和函數放在一個文件中,採用類似的命名方式。

畢竟C語言沒有在語言層面上支持面向對象,因此就有很多程式設計師想給C語言添加面向對象支持。其中的代表是C++和Objective-C。

C++是一種新的語言,但大部分語言元素是和C兼容的。

Objective-C是完全兼容的C的。Objective-C是給C添加了薄薄的一層語法糖以支持接口(就是其他語言的類)和協議(就是其他語言的接口)。甚至,Objective-C一開始的實現,就是一個C語言的預編譯器。Objective-C坦白講,除了添加的語法不太符合C流外,實際上其面向對象系統設計是相當精妙的。賈伯斯早年慧眼識珠,把Objective-C收人囊中,因為封閉於Apple/NextStep系統內,因此少有人知。隨著iOs系統的普及,Objective-C近幾年才名滿天下。

函數式編程範式

函數式編程範式,是一些數學家發明的程式語言,他們認為程序就是數學函數嘛。代表語言:Lisp,Erlang,JavaScript,OCaml,Prog。

有很多大牛極力鼓吹過函數式程式語言,認為其極具革命性。但我認為他們過高估計了函數式編程範式的威力,我並不認為函數式編程範式相對於面向對象編程範式有何高明之處。

函數式程式語言,核心就是函數,它們沒有Class類的概念。但它的函數又不是傳統面向過程語言的函數,它的函數支持「閉包」的概念。

在我看來,函數式程式語言的函數,也就是「閉包」,說白了,其實就是「類」。程式語言發展到今天,就是需要模塊化,就是需要把「數據結構」和「算法」結合起來。不論何種語言,不把它們結合起來的編程方式,都是沒有出路的。

面向對象程式語言,用類把「數據結構」和「算法」結合起來。類的核心是「數據結構」,也就是其「屬性」,而不是「算法」,其「函數」。在類中,是函數依附於屬性。

而函數式程式語言,用閉包把「數據結構」和「算法」結合起來。是函數能夠抓取外部的欄位。是「屬性」依附於「函數」。

「類」本質上和「閉包」是等價的。現在很多面向對象程式語言都加上了對閉包的支持。觀察其代碼,我們可以發現,它們實際上都是用「類」來實現「閉包」的。

「類」和「閉包」誰更易用?明顯是「類」。

而「閉包」更簡潔一些,因此「閉包」在面向對象程式語言中常用來替換匿名類。只有一個函數的類,寫成一個類太麻煩,不如寫成閉包,更加簡潔。

吐槽一下OCaml語言,其前身Caml語言本身是一種挺好的函數式語言,硬生生添加了一套完整的面向對象機制,同時支持面向對象和函數式編程範式,很容易像C++一樣腦裂的。

也有很多面向對象語言控看著JavaScript嫌煩,總是想把面向對象支持添加到JavaScript上。ActionScript就是其中一種嘗試。我用過,真的是和Java沒多少區別了。

再吐槽一下ExtJS。當初選型Web前端開發框架時比較了ExtJS和JQuery。

ExtJS明顯是Java高手開發的,硬生生用JavaScript模擬Swing的設計思想,搞了一套UI庫。

JQuery開發者明顯是領悟了JavaScript的函數式編程範式,依據JavaScript的動態函數式程式語言的特點打造了一套UI庫,立刻秒殺ExtJS。

由ExtJS和JQuery的故事,我們可以看到多語言編程能力是多麼的重要。ExtJS的作者精通並喜愛Java,因此他把手術刀JavaScript當做錘子Java使,一通亂敲,費力不討好。

函數式程式語言,還有尾遞歸等一些小技巧。尾遞歸可以不用棧,防止遞歸調用時棧溢出。

模板編程範式

模板編程,就是把類型作為參數,一套函數可以支持任意多種類型。代表語言:C++。

模板編程的需求,是在C++開發容器庫的時候發明的。因為容器需要保存任意類型的對象,因此就有了泛型的需求。

C++的模板編程,是在編譯時,根據源碼中的使用情況,創建對應類型的代碼。除了C++這種方式,Java,C#也有類似的機制,叫做「泛型」,但它們的實現方式和C++的模板很不同。它們的編譯器不會生成新的代碼,而是使用強制類型轉換的方式實現。

在沒有模板/泛型的程式語言中,怎樣在容器中存放對象呢?存取公共基類類型(Java,C#)的對象,或者void*指針(C)即可,取出時自己強制類型轉換為實際類型。動態類型語言,不關心類型,更是無所謂了,隨便什麼對象直接往容器裡扔進去,取出來直接用即可。

一些C++高手又在模板的基礎上搞出了「模板元編程」。因為模板編程,就是C++的編譯器搞定的嘛,模板元編程就是讓編譯器運算,編譯完結果也就算出來了。我不知道除了研究和炫技,這玩意有啥用?

小結

一門語言是否值得學習,我認為有幾個標準:

1,是否要用,要用就得學,這麼沒有疑問的。畢竟我們都要吃飯的嘛。

2,其語言特性是否給你耳目一新的感覺。如果是,那就值回票價了。如Go語言廢掉了異常,改用返回多值。我深以為然。我其實已經主動不用異常好多年了。因為,我覺得既然C不支持異常也活得很好,為什麼需要異常呢?出錯了,返回錯誤碼。無法挽回的錯誤,直接Abort程序就可以嘛!而且,異常實際上是違反面向過程編程原則的。一個函數應該只有一個入口一個出口。拋出異常就多了出口了。

3,是否擅長某一個領域。如果你手裡只有一把錘子,那麼你就只能把所有任務都當做釘子猛錘一通。但如果工具箱裡有多種工具,那面對不同的任務就得心應手多了。

7段—架構設計

還需要掌握架構設計的能力,才能設計出優秀的軟體。架構設計有一些技巧:

1,分層

一個軟體通常分為:

表現層--UI部分

接口層--後臺服務的通訊接口部分

服務層--實際服務部分

存儲層—持久化存儲部分,存儲到文件或者資料庫。

分層的軟體,可以解耦各個模塊,支持並行開發,易於修改,易於提升性能。

2,SOA

模塊之間通過網絡通訊互相連接,鬆耦合。每一個模塊可以獨立部署,可以增加部署實例從而提高性能。每一個模塊可以使用不同的語言和平臺開發,可以重用之前開發的服務。SOA,常用協議有WebService,REST,JSON-RPC等。

3,性能瓶頸

1)化同步為異步。

用內存隊列(Redis),工作流引擎(JBpm)等實現。內存隊列容易丟失數據,但是速度快。工作流引擎會把請求保存到資料庫中。

通過化同步請求為異步請求,基本上99.99%的性能問題都可以解決。

2)用單機並行硬體處理。

如,使用GPU,FPGA等硬體來處理,提高性能。

3)用集群計算機來處理。

如,Hadoop集群,用多臺計算機來並行處理數據。

自己的軟體棧中,也可以把一個模塊部署多份,並行處理。

4)用cache來滿足請求。常用的內容加熱cache後,大量的用戶請求都只是內存讀取數據而已,性能會得到很大的提升。

cache是上帝算法,記得好像它的性能只比最佳性能低一些,就好像你是上帝,能夠預見未來一樣。現在X86CPU遇到了主頻限制,CPU提升性能的主要途徑就是增加高速Cache了。

4,大系統小做

遇到大型系統不要慌,把它切分成多個模塊,用多個小程序,通過SOA協作來解決。這秉承了Unix的設計思想。Unix上開發了大量單一目的的小程序,它主張用戶通過管道來讓多個小程序協作,解決用戶的需求。當然,管道方式通訊限制太多,不夠靈活。因此,現在我們可以通過URI,通過SOA的方式來讓多個程序協作。Andorid和iOS上的應用程式,現在都是通過URI實現協作的。這也算是Unix設計思想的現代發展吧?!

5,Sharding切片

現在有一個潮流,就是去IOE。I-IBM大型機,O-Oracle資料庫,E-EMC存儲。之前,大型系統常用IOE去架構,在大型機上部署一個Oracle資料庫,Oracle資料庫用EMC存儲保存數據。IOE是當今最強的計算機,資料庫和存儲。但他們面對海量系統也有抗不住的一天。

Oracle資料庫是Shareeverything的,它可以在一個計算機集群(伺服器節點不能超過16個)上運行。計算機集群都共用一個存儲。

去IOE運動,標誌著ShareEverything模式的破產。必須使用ShareNothing,系統才能無限擴展。

用MySQL資料庫就可以應付任意規模的數據了。前提是,你會Sharding分片。把大系統切分成若干個小系統,切分到若干臺廉價伺服器和存儲上。更Modern一些,就是切分到大量虛擬機上。

如,鐵道部的12306網站。我們知道火車票都是從屬於某一列列車的。那麼我們把每一個列車作為一個單元來切分,就可以把12306網站切分成幾千個模塊。一臺虛擬機可以承載若干個模塊。當某些列車成為性能瓶頸之後,就可以把它們遷移到獨立的虛擬機上。即使最終有部分列出服務不可用,系統也不會完全不可用。

12306網站,只有一個全局的部分,就是用戶登錄。這個可以交給第三方負責。如可以讓用戶用微信,微博,qq等帳戶登錄。

也可以自己實現用戶登錄服務。還是用切片的方式用多臺Redis伺服器提供服務。Redis伺服器存儲每一個登錄用戶的sessionId和userId,角色,權限等信息。sessionId是隨機生成的,可選擇其部分bit用於標識它在哪一個Redis伺服器上。用戶登錄後,把sessionId發給客戶。用戶每次請求時把sessionId發回給伺服器。伺服器把sessionId發給Redis伺服器查詢得到其用戶信息,對用戶請求進行處理。如果在redis伺服器上找不到sessionId,則讓用戶去登錄。即使所有註冊用戶同時登陸,也不需要太多的內存。而且,可以在session內存過多時,刪除最早登陸的用戶的session,強制他再次登陸。同時活躍的用戶數不會太多。

領域知識層次

前面的所有層次,都是關注編程本身的技能,說白了,就是基本功,本身並不能產生太大的價值。但有太多的程式設計師浪費太多的時間在那些築基的層次上。

有些程式設計師特別喜歡鑽研程式語言,每有一種新的程式語言出來或者舊語言被熱炒,就會投入精力進去研究。我就是其中之一,浪費了很多精力在程式語言上,在奇技淫巧上。

我覺得C++語言是一個特別大的坑。剛開始是作為面向對象的C被開發的。後來發現了模板編程,就大力鼓吹模板編程和進一步的模板元編程。最近又推出了C++11,C++14等新標準,進一步添加了很多新東西,函數式編程,類型推斷等。C++過分複雜,太多的坑消耗了大量程式設計師的大量精力。我使用C++時,只使用面向對象部分和模板部分,其他過於精深的特性都不使用。

計算機科學是一個面相當廣泛的學科,有很多領域知識需要和值得我們深入研究,我們才能寫出有價值的程序來。軟體必須要和行業結合起來,要落地才有價值。僅僅研究編程技巧,不懂領域知識是寫不出有價值的程序的。

計算機科學領域有很多,列舉一些如下:

存儲----塊設備,文件系統,集群文件系統,分布式文件系統,光纖SCSI,iSCSI,RAID等。

網絡----乙太網,光纖網,蜂窩網絡,WIFI,VLAN等。

計算機體系結構,主要就是CPU指令集。x86,ARM等。

USB協議。需要知道URB包。

PCI協議,PCI-E協議。現代計算機的外設都是PCI協議和PCI-E協議的。顯卡現在全是通過 PCI-E協議連接到計算機上的。相對來說減少了很多需要學習的知識。搞虛擬化就需要深入掌握PCI協議。

圖像處理--圖像壓縮,視頻實時編碼等。

3D遊戲

關係資料庫

NoSQL資料庫

作業系統

分布式作業系統

編譯原理

機器學習--現在大數據要用哦!

了解這些領域知識,也包括了解該領域現有的商用硬體、商用軟體和開源軟體。很多時候,你要完成的工作,已經有現成的工具了。你只要使用現成的工具就可以完成任務,不需要進行開發。有時候,只需要組合現有的工具,寫一些腳本就可以完成任務。

如,我一次要實現一個雙向同步任務。找到了一個優秀的開源軟體Unison,編寫一下配置文件就圓滿地完成了任務。不需要編寫任何代碼。

還有一次,要做高可用,用Python調用了幾個開源軟體就輕鬆實現了。

編寫安裝程序,定製作業系統,知道了作業系統的領域知識,寫幾行腳本就可以輕鬆搞定。

不具備領域知識的人,就可能不得不進行大量無謂的開發,甚至開發很久之後才發現,這根本就是一條死路。

另外,紮實的領域知識,可以大大提高編程調試、查錯的能力。知道編譯器和程式語言運行時工作原理,就能快速根據編譯錯誤和警告信息修改代碼。

知道作業系統底層運行機制,就能快速找到運行時錯誤的問題根源。如,有一次我編寫一個windows升級服務程序。它是一個windows服務,需要執行dos腳本,這個腳本會替換掉這個windows服務本身。發現有時腳本執行無效,查了一晚上,發現當windows服務安裝後,第一次啟動就執行腳本時就會有權限問題,log都正確,但實際執行這個腳本沒有任何效果。但一旦windows服務程序啟動一次之後就ok。這必然是windows作業系統底層安全機制的問題,因為我對Windows內核了解不多,因此花了很長時間才發現這個問題,並對造成這個問題的根源並不清楚。

0段—領域知識菜鳥

對領域知識沒有多少認知,通過搜尋引擎找到一些該領域的軟體和硬體的介紹性文章,按照文章指示配置和使用軟體。勉強能夠使用現有軟硬體。

1段—領域知識行家

了解領域內常用硬體,深入掌握領域內常用軟體的配置和使用技巧。能夠使用現有軟硬體熟練搭建解決方案,能夠解決實際工作中遇到的種種問題。

2段—領域知識專家

當你不僅僅掌握了該領域的軟體和工具,知道怎麼用,還知道其原理,「知其然,也知其所以然」,就是該領域的知識專家了。

你知道網絡協議的原理,你才能在網絡出現問題時知道是哪裡可能出現了問題。是mac衝突,ip衝突,還是網絡環路?

你知道存儲的原理,你才能知道為什麼這種存儲方式不適合虛擬化,那種存儲方式適合虛擬化,另一種方式適合資料備份。

你知道PCI協議,你才能知道你怎樣才能虛擬化一個硬體設備。

你知道網卡硬體協議,你才能模擬出一個虛擬機能正常使用的虛擬網卡。

你知道視頻編碼格式和原理,才能知道什麼視頻格式佔用帶寬最少,什麼視頻格式佔用CPU最少。

你了解IntelVT/Amd V指令集,才能知道虛擬化是怎樣實現的。

你明白工作流其實就是狀態機,在遇到複雜工作流程時,你才能知道怎樣設計滿足要求的工作流引擎。

3段—科學家

你是領域知識專家,但你的知識都是來自於書本,來自於其他人的。

如果你滿足於當領域知識專家,你只能拾人牙慧,永遠別想超越。別人的研究成果,未必願意告訴你。當別人告訴你的時候,它可能已經發現了更新的理論,並且新一代產品可能馬上就要發布了。

科學家是探索未知,勇於創新的人,是推動人類社會進步的人。

傳說,思科的一位高管曾經半開玩笑地說過:「如果思科停止了新技術的研發,華為就會找不著方向」。這是在嘲笑華為只是處在領域知識專家的水平,只能山寨無法超越。我不知道華為的實際情況,但希望現在的華為已經走到了領跑者的位置。

歐文·雅各布斯發現了CDMA碼分多址的原理,並發現它在通訊上大有可為,組建了高通公司。高通公司主要以專利授權費為生,它僱傭了大量科學家在通訊領域展開研究。有人說高通是專利流氓。這些人不明白知識的價值。在他們眼裡,Windows的合理價格就應該是5元錢,一張光碟的價格。iPhone就應該是1000多元裸機的價格。高通是專利流氓,那你也流氓一個CDMA,LTE出來給我看看!

X86晶片在設計上沒有考慮虛擬化。因此會有所謂的「虛擬化漏洞」出現。就是說,一些CPU特權指令執行時,在虛擬機環境下不會拋出異常,因此就無法切換到Host。這樣,X86晶片上就無法運行虛擬機。

VmWare公司是由美國的幾位科學家在1998年創建的。他們發現可以使用二進位翻譯的技術,在X86計算機上運行虛擬機。

Xen虛擬化軟體也是幾位科學家發明的。他們發現只要修改虛擬機作業系統和Host作業系統的內核,在需要執行「虛擬化漏洞」指令時直接調用Host的功能,就可以實現虛擬化,而且大大提高了虛擬機的運行性能。

後來,Intel為自己的晶片添加了IntelVT指令集,Amd為自己的晶片添加了AmdV指令集,彌補了「虛擬化漏洞」。於是就有了KVM虛擬機軟體,它直接用CPU硬體指令實現虛擬化。

KVM在執行CPU指令時,是直接在物理CPU上運行的,因此效率極高。但是,虛擬機運行虛擬外設時,就必須用軟體模擬,因此虛擬機的IO訪問速度很慢。

IBM科學家RustyRussell,借鑑了Xen的研發經驗,創建了VirtIO技術。就是在虛擬機中編寫一套PCI虛擬設備和驅動,這套虛擬PCI設備有一塊虛擬設備內存。這個虛擬設備內存Host是可以訪問的,虛擬機通過VirtIO驅動程序也可以訪問。也就是一塊內存在虛擬機和Host中共享,這就解決了虛擬機的IO性能問題。

再講一個搜尋引擎的故事:

很久以前,我要給一個程序添加搜索功能。剛開始使用sql查詢實現,發現實在太慢了。後來找了開源的Lucene項目。它使用反向索引技術,通過在文件中創建反向索引,大大提高了搜索速度。

Google的兩位創始人發現了html中link的秘密,他們發現可以通過html頁面的link關係來為每一個html頁面設置權重。也就是PageRank算法。於是,Google的自動搜尋引擎擊敗了Yahoo人工分類的搜尋引擎。

OK,利用反向索引技術和PageRank,以及一個簡單的html爬蟲機器人,我們就可以創建一個搜尋引擎了。但是,網際網路很大,每天產生大量新網頁,要為整個網際網路建立反向索引是很困難的。

若干年後Google又公開了三篇論文:Googlefs,Mapreduce,Bigtable。於是Lucene項目的開發者根據Google的Mapreduce論文開發了Hadoop項目。MapReduce就是使用大量計算機存儲數據並計算,最後匯總結果。使用Hadoop+反向索引+PageRank,就可以創建搜尋引擎了。Yahoo,Baidu等公司紛紛基於Hadoop開發了自己的搜尋引擎。

但是,其他公司的搜尋引擎效果還是沒法和Google相比。這一點我們程式設計師最清楚。像我,就總是翻牆出去,只為了Google一下。

Google黑板報上發表了吳軍博士的一些文章,其中介紹了很多機器學習方面的知識。從文中可以知道,Google其實使用機器學習來分析搜集到的頁面。Google明顯不會把這個公式公開出來。即使有一天Google真的公開了這個公式,那麼可以想見Google肯定又研發出了更加犀利的秘籍,山寨貨的搜尋引擎效果還是比不上Google的。

山寨是通向創新的必由之路。在成為領域的領頭羊和領導者之前,必然要經過學習,模仿的階段。但要成為行業的老大,成為Champion,必須勇於彎道超車,勇敢地走上創新之路,成為真正的科學家,真正的大牛!

總結

編程能力可分為兩個維度:一個是編程技能水平,另一個是領域知識水平。

有些程式設計師可能把精力都花在提升編程技能上了,領域知識知之甚少,這其實在日常工作中也是極其有害的。有些需求可能早已經有了現成、開源免費的解決方案,或者只需要組合幾個現有軟體就可以快速搞定,而他們卻不得不自己花大量時間去開發。另外,缺少領域知識,在程序出現非預期狀況時,很難快速定位到問題的根源,很難解決bug。

來源:良少的專欄

轉載自公眾號:CocoaChina

產權及免責聲明本文系「MOOC」公號轉載、編輯的文章,編輯後增加的插圖均來自於網際網路,對文中觀點保持中立,對所包含內容的準確性、可靠性或者完整性不提供任何明示或暗示的保證,不對文章觀點負責,僅作分享之用,文章版權及插圖屬於原作者。如果分享內容侵犯您的版權或者非授權發布,請及時與我們聯繫,我們會及時內審核處理。

了解在線教育,
把握MOOC國際發展前沿,請關注:
微信公號:openonline
公號暱稱:MOOC

相關焦點

  • 層次分析法建立層次結構模型分為哪些層次?
    層次分析法建立層次結構模型分為哪些層次? 2019-03-19 12:11  來源:  字體:大小  列印 【試題】 層次分析法建立層次結構模型分為哪些層次?
  • 程式設計師的技能樹應該包括哪些內容
    從技術體系的角度來看,程式設計師的技能樹應該分為三大部分,其一是基礎學科知識,重點在於數學和物理,因為軟體問題說到底就是數學問題,硬體問題說到底就是物理問題,所以數學和物理的掌握情況,能夠決定程式設計師是否能夠在技術領域走得更遠。
  • 程式設計師是做什麼的?未來計算機變得智能,就不需要程式設計師了嗎?
    甚至不少程式設計師對他們是做什麼的都沒有清晰的概念。 2.細節層次。人類的溝通是籠統而不帶有過多細節的,例如:「我想讓這該死的程序運行起來」。這樣可以節省時間與精力,但由於缺少詳細信息,會產生兩個比較大的問題——誤解和不確定性。而計算機需要所有細節——每件事都要說清楚。 3.思維模式。
  • Java程式設計師不同層次的薪資對照,你在哪個檔口?
    第二層境界:世界如此之大,要學的東西很多修煉第二層境界的程式設計師,他們往往是從事了Java開發好幾年了,從第一層境界進階上來的好手,即,沒有被優勝劣汰掉的那批人。之所以說「沒有被優勝劣汰」這麼「殘酷」的用詞,並非危言聳聽,我們經常看到,在這一關掉隊的人們,由於志向偏離,或者吃不了苦,或者對困難估計不足,甚至是身體原因放棄軟體開發職業。
  • 思維模型的四個層次
    個人能力提升 思維模型的四個層次494848; --tt-darkmode-color: 494848; --tt-darkmode-color: 494848這四類思維模型是隨思維的深度不斷遞進
  • 程式設計師成長分為哪幾個階段?需要掌握哪些技能?
    技能:我們知道如何團隊協作、如何使用項目管理工具、項目版本如何控制、我們寫的代碼如何測試如何在線上運行等等,積累了一定的開發經驗,也對代碼有了一定深入的認識,是一個比較純粹的Coder的階段。心態:在學習過程中,和老師做過一些小項目,自認為自己很牛,那個時期的我們,壓根不知道自己不知道,還以為自己懂很多,現在想起自己以前就好笑,那個時候還算不上程式設計師,頂多只能算是個業餘編程愛好者。表現:假自信、過度承諾、滿口我能行沒問題、看不起其他程式設計師….。
  • 【軟科學.認知篇】確認自己的知識技能模型
    [軟科學.認知篇]確認自己的知識技能模型 每一個人,都有自己的優勢領域,自己感興趣的事情,自己熱衷的生活方式,自己的謀生手段。 知識型,就是喜歡學習,注意力放在關注各種概念,抑制不住的想多了解點啥,因此知識豐富廣博,屬於資料庫型的人,這樣的人適合成為一個知識工作者,做老師,培訓,作家,等等 技術型,就是啥都想試試,都想操作一下,關心原理和機制,對做出點啥很有成就感,這樣的人,很有耐心,喜歡刨根究底,能長時間無數次的嘗試,想要構建出點啥,這樣的人適合做程式設計師
  • (面試感悟)一名3年工作經驗的程式設計師應該具備的技能
    這篇文章大部分內容都是面向整個程式設計師群體的,當然因為LZ本身是做java開發的,因此有一部分內容也是專門面向咱們java程式設計師的。面試完LZ多方了解了一下,對方認為我基本功什麼的都不錯,但是實際項目經驗還是欠缺一些,因為對方是創業型公司,需要人上手就能幹活,因此我在這個時候還不是特別適合他們團隊至於其他成功的四家公司,給LZ的面試評價都挺高的貌似,但LZ也不想記流水帳,因此就不一一列舉每家公司的面試過程了,下面LZ主要談談作為一名工作三年左右的java程式設計師應該具備的一些技能以及個人的一些其他感悟。
  • 數據模型概念及類型劃分
    DBMS為了保證其獨立性與可移植性,大部分物理數據模型的實現工作又系統自動完成,而設計者只設計索引、聚集等特殊結構。  在概念數據模型中最常用的是E-R模型、擴充的E-R模型、面向對象模型及謂詞模型。在邏輯數據類型中最常用的是層次模型、網狀模型、關係模型。  資料庫領域採用的數據模型有層次模型、網狀模型和關係模型,其中應用最廣泛的是關係模型。
  • 提高程式設計師面試技能,我推薦這10本書
    這本書對經驗豐富的程式設計師、技術帶頭人、自學的程式設計師及幾乎不懂太多編程技巧的學生們都是大有裨益的。可以說,無論是什麼背景的讀者,閱讀這本書都有助於在更短的時間內、更容易地寫出更好的程序。讀者點評:我在職業生涯的三年中讀過《Code Complete》。這是迄今為止我成為更好的程式設計師所讀過的最好的一本書。
  • 一名3年工作經驗的Java程式設計師應該具備哪些技能
    每個程式設計師、或者說每個工作者都應該有自己的職業規劃,如果看到這裡的朋友沒有自己的職業規劃,希望你有所警醒。LZ認為一名程式設計師應該有幾個階段(以下時間都算上實習期):第一階段-——三年我認為三年對於程式設計師來說是第一個門檻,這個階段將會淘汰掉一批不適合寫代碼的人。這一階段,我們走出校園,邁入社會,成為一名程式設計師,正式從書本上的內容邁向真正的企業級開發。第二階段——五年五年又是區分程式設計師的第二個門檻。
  • 面試感悟:3年工作經驗java程式設計師應有的技能
    這篇文章大部分內容都是面向整個程式設計師群體的,當然因為LZ本身是做Java開發的,因此有一部分內容也是專門面向咱們Java程式設計師的。面試完LZ多方了解了一下,對方認為我基本功什麼的都不錯,但是實際項目經驗還是欠缺一些,因為對方是創業型公司,需要人上手就能幹活,因此我在這個時候還不是特別適合他們團隊至於其他成功的四家公司,給LZ的面試評價都挺高的貌似,但LZ也不想記流水帳,因此就不一一列舉每家公司的面試過程了,下面LZ主要談談作為一名工作三年左右的Java程式設計師應該具備的一些技能以及個人的一些其他感悟。
  • Java程式設計師幾年能實現月薪2萬,需要具備哪些技能?
    拋開工作經驗,項目經驗,學歷背景,單從技術點分析,哪些方面可以判斷一個java程式設計師的技術紮實程度,怎樣才能知道他值多少月薪呢?本文將為你解答:有人說這只能是大企業或者網際網路企業的工程師才能拿到。也許是的,小公司或者非網際網路企業拿兩萬的不太可能是碼農了,應該是已經轉管理後才有可能。
  • 入門Java開發程式設計師未來就業前景如何?
    而其中,Java開發程式設計師是業內薪資較高的程式設計師之一。受疫情影響,更多的企業轉向網際網路領域,眾多中小企業急需全面系統掌握Java軟體開發基礎技能與知識的軟體工程師,對於優秀的Java工程師的需求也不斷的擴大。
  • 程式設計師教你如何追女生
    今天我們談一個你們這群單身狗已經掌握卻一直沒怎麼用的技能:「追求女生」。交給你一個項目,遇到不會的開發工具怎麼辦?學啊!我們程式設計師擁有超強的自學能力。星座,塔羅牌,看手相,大姨媽陪護,這些能引起女生共同話題的知識不要以為沒有用,你就當學習一門新的程式語言嘛!一點都不難對不對?
  • 從空軍機長到大廠程式設計師,關係資料庫之父傳奇
    他一生中為計算機科學做出了很多有價值的貢獻,而關係模型作為在資料庫管理方面舉足輕重的基礎理論,被認為是他最引人矚目的成就。 空軍機長轉行做程式設計師 科德於1923出生在英國英格蘭多塞特郡的波特蘭,長大後進入在牛津的埃克塞特學院學習數學與化學。
  • 首款3D模型設計軟體與圖形化編程工具的結合-3D程式設計師(Scrstch3D),貓友匯邀您有獎公測啦!
    「3D程式設計師」是一款結合圖形化編程工具Scratch的交互式3D模型設計軟體,支持2D/3D圖形、造型變換、數學函數等一系列參數化功能,既可以培養編程能力和邏輯思維,又能鍛鍊3D空間設計能力,以Scratch和3D的方式呈現孩子們的創新想法。IME3D - 3D程式設計師於1月16日發布Beta公測版本,現聯合國內最大創客教育社群貓友匯,特邀請您參與測試,並提出您的寶貴建議和意見。
  • 矽谷經驗本土化,力扣 LeetCode 通過 「程式設計師職業技能提升」 和...
    力扣(官網:https://leetcode-cn.com/ )是 36 氪最近接觸到的一家面向程式設計師提供 IT 技術職業化提升和測評的平臺,是矽谷最早期的 OJ(Online Judge)之一。程式設計師通過使用力扣進行技術編程練習,提升職業技能,找到更合適的工作。
  • 程式設計師自我成長需要這3大軟技能,別讓自己輸在這些上面!
    學會自我成長的程式設計師月薪在1~3年就破10K,而不會自我成長的程式設計師仍然在底層跌打滾爬,甚至混了5年工資也不見漲。究竟是什麼阻礙了程式設計師的自我成長呢?程式設計師自我成長需要什麼軟技能?1、表達技能有些程式設計師一年365年敲代碼,加班加點,但是就是無法升職。程式設計師的競技場屬於懂技術+會表達的人,不然僅僅是感動自己而工作,一直受制於人,是非常痛苦的。
  • 英語在程式設計師的工作中究竟扮演著什麼樣的角色?
    英語對程式設計師來說重要嗎?也就是說,如果完成基礎工作就是目的,英語水平過及格線即可~反之,如果不想一直只是個初級程式設計師,還想進階成為中高級層次,僅僅及格水平的英語可滿足不了我們的工作需求。大家都知道,程式設計師編程最重要的是算法和語法,英語並不在這其中,在編寫代碼的過程中只是屬於實現算法的工具,這也正是英語在程式設計師工作中扮演的角色,同樣,英語在程式設計師的工作中不可或缺。另外,英語能力還體現在程式設計師的能力提升上,閱讀源碼、查看書籍免不了對我們的英語實力有要求。 程式設計師的英語到什麼水平比較合適呢?