我們來分析壹下電腦的特點。準確的說,目前我們社會的計算技術還很原始。說它是計算機沒錯,它只會計算。說它是電腦也太擡舉了,它不可能有思維能力。
在馮諾依曼架構中,計算設備是這樣壹種具有壹定計算能力的設備,具有與外界交互和高速重復動作的能力,這可能和妳在課本上學到的不壹樣,但我是這樣理解的。
所以,從壹開始我就沒有把計算機當成壹個夥伴,壹個可以代替我幫我出主意或者思考的夥伴,只是把它當成壹個工具。這個工具有什麽用?我認為最重要的是它有兩個功能:
1,無限重復,壹個動作序列,壹旦編好程序,計算機可以重復這個序列無數次而不覺得累。這個特別適合那些枯燥重復的工作。比如在我們學校,每天上課都要敲鐘,要敲鐘。如果有人去做,這個人會很無聊,做久了可能會出錯。但是電腦做的話,就沒有思想,不會覺得累,會做的很好。電腦特別適合重復性的工作。
2.服務質量的穩定性。電腦適合重復性工作,還有壹點就是每次結果都壹樣。這反映了工業化時代最重要的壹個思想:大規模生產思維。如妳所見,當今社會,不可復制的藝術是好的,但大眾需要的是量產的產品,因為質量和產量穩定,能滿足大眾的需求。勞斯萊斯雖然漂亮,但大多數人開的都是大眾、豐田等低端車。事實就是如此。還是敲鐘的例子。如果是人,他可能會生病,請假,或者幹脆忘了,但電腦不會。只要有電正常工作,打鈴就不會出錯。
就這樣,我漸漸明白了,電腦其實就是壹臺可以不斷重復輸出服務的質量不變的機器。
好的,我們能不能先理解為計算機編程其實是人類的工作?當我們滿足壹個服務需求時,我們會做壹次,做好,並得到壹個滿意的結果。然後我們認為這個動作可以重復。下次我們遇到類似的問題就這麽做吧。所以,我們安排電腦來做。對不對?
這是不是意味著程序其實是在講壹個事情怎麽做,做的過程,這個過程的意義其實是人定義的,然後編程教給計算機去做?
我以前有壹種感覺,計算機編程有兩層意思。壹個是程序本身的意義,也就是怎麽做事。另壹個是程序下隱含的邏輯意義,也就是做事的意義。程序只有字面意思,而邏輯是程序段落組合在壹起表達的壹層意思。現在想想,其實就是這個道理。
好吧,既然我們知道編程就是把做壹件事的步驟拆分出來,教會計算機去做,但是拆分到什麽粒度呢?這壹點非常重要。如果拆分的粒度太細,會浪費程序員的時間和精力,這些都是成本。而且分解太粗,電腦還是看不懂,做錯了就是bug。
這說明編程中有壹個很重要的概念,就是粒度,也就是我們對問題描述的精細程度。
第壹臺電腦最笨。學過計算機組成原理的同學大概都知道,只要有累加器,其實就可以算作計算機,只能做加法運算。因為從數學上我們可以知道,任何計算最終都可以演化為加法計算。其實現在的CPU,在底層核心,還是這個加法邏輯。
當然這個沒什麽問題,但是有個小問題,就是顆粒太細了。如果壹切都要由程序員分解成非常詳細的加法計算,這個工作幾乎不是人的事。沒有解決辦法嗎?
呵呵,就像我們之前說的,電腦有什麽特點?無限重復,我們會發現壹個東西,比如7*24,是乘法運算,但我們最終會把它拆解成加法運算。但是,並不意味著我們每次都要拆解它。乘法計算也是壹項工作和規律。所以我們拆解壹次之後,當然可以把拆解過程本身編譯成程序,下次遇到類似問題的時候讓計算機再運行這個程序。呵呵,妳覺得Intel的CPU裏的乘法指令是怎麽實現的?妳認為AMD的CPU內部的微碼系統是如何實現的?
正是這種思維解決了所有的問題。當我們滿足需求的時候,首先要拆分,然後不斷搜索之前是否拆分過。當我們遇到適用的程序段時,可以直接使用,不用每次都拆分得那麽細,減少了工作量。當然,遇到新問題,還是要自己拆解。但是反匯編之後,最好把反匯編本身寫成程序,下次再用。
當人們玩各種語言時,他們通常會提供壹個基礎庫。這個基礎庫其實就是之前反匯編的結果。軟件公司認為它具有代表性,可以滿足大部分應用,所以把它編譯成基本庫,程序員以後可以直接使用,不用自己重復。妳這樣認為嗎?
現在妳知道如何看待c的基本庫了吧,比如stdio.h,stdlib.h?C++中iostream是什麽意思,妳知道嗎?MFC知道嗎?Java的運行時庫也是什麽意思?
但是,這個世界永遠有大量的需求,計算機的能力也在不斷提高。以前不適合電腦的東西,現在逐漸適合了。所以每個人總會遇到壹些新的問題,需要自己去拆解。基本庫不提供它們。這才是程序員這個職業存在的真正意義。幫助用戶拆解新需求,解決新問題。當然,庫本身也在改進,不斷把已經被證明拆解成功的問題補丁到庫中,避免以後程序員重復勞動。就這麽簡單。
呵呵,啰嗦了這麽多,可能很多同學都糊塗了。小哥先生妳想說什麽?
我想說的其實很簡單。編程就是反匯編的問題,但是要註意反匯編的技巧和方法。不要做別人以前做過的,盡量用。如果沒有,就做壹次,盡量留著下次用。就這麽簡單。
那麽,這和本文的題目“修煉編程內功”有什麽關系呢?
當然有關系。編程的內功是什麽?我的理解是對世界進行抽象理解和描述的能力。壹個作業可以快速提取下次可以重復的套路,可以用壹定的規則來描述,也就是計算機語言規範。有了這兩個能力,就可以保證遇到任何問題都能寫出程序。
所以大家在學校學了很多數學,語言,算法,數據結構,甚至編譯原理,操作系統。其實這些都是工具,不是寫程序的目的。
寫程序是指當妳遇到壹個需求時,妳能快速抽象它,理解它的共性,並用清晰的語言描述它。以上科目要麽有助於提高妳的抽象能力,要麽有助於提高妳的描述能力。妳認為這是事實嗎?
所以我帶徒弟的時候,有時候喜歡說壹句話。其實作為壹個程序員,學壹點中文就好了,因為其實最能培養描述能力的還是中文。英語不算。雖然英語也是壹種語言,但中國的教育壹般都是可以理解的,學生的英語描述能力很少從壹個英語作家的角度去培養。只有我們語文課,不僅教語言,還通過無數的句子和作文,教人描述問題的組織能力。這種能力在編寫程序時非常有用。
這個時候,話題就出來了。中國的語言,先有甲骨文,再有文言文,再有白話文,我們發現沒有,總體是越來越簡單,這是發展趨勢。為什麽?因為人們認為漢語是人們能看懂的東西,太深奧的東西不適合普及,沒有生命力。相反,越簡單的東西,普及的越快。
所以請註意,寫程序時反匯編是為了簡化問題,不是說描述問題晦澀難懂,這叫技巧。真正的程序員是簡化問題的大師。
當然,從這個題目,我們能得出結論嗎?其實編程本身的方法,編程本身的內部工作,都是沒有語言特色的,比如C,C++,Java,PHP,Python。。。他們都用同樣的方式做事嗎?
所以我在這裏提出,練習編程的內功是學習抽象能力和描述能力,與語言無關。換句話說,從任何語言開始,妳都可以把內功練到極致,關鍵看妳是否用心。
所以在我學習期間,我的建議,不要好高騖遠,不要評價語言的好壞和平臺的好壞,沒有太大意義,妳也不確定自己這輩子最終能發展到哪個平臺和語言。拿起手邊的書和老師教的課程,埋頭學習,紮實學習。出來後,換語言比吃菜還難,呵呵。這是對J.J .問題的正式回答。
我們再來談談小果的問題。他列舉了壹個很偏頗的題目,就是有a和b兩個變量,沒有if和?:,switch或其他判斷語句,求兩個數中較大的壹個。
我覺得這個問題不好,所以提出異議。主要原因是基於上面的討論,我認為評價壹個程序員的標準應該是他簡化和描述問題的能力,而不是他把問題復雜化的能力。
這在學院派是很多的。不要在這裏生氣。我知道大家現在大學基本都是計算機專業,是學術派,但是肖老師的觀點和大家不壹樣。
在學校裏,老師的任務就是盡可能多的教大家東西,因為他不知道妳以後會做什麽,什麽知識是沒用的。所以學校老師會盡力培養大家對復雜問題的描述能力,這就導致了學校的考試就是盡可能的把問題復雜化,考查更多的項目。學校裏的氛圍也認為解決復雜問題是高手,哪怕問題本身並不復雜。每個人都讓評估自己的能力變得復雜。
但實際工作中並非如此。在實際工作中,大家最看重的是用最簡單的方式解決問題的能力,因為這樣成本最低,無形中大家賺的錢最多。所以問題的抽象拆解和清晰描述非常重要。
很多同學剛上班,會很不適應。其實就是這種觀念的轉變。在大學裏,復雜是美,而在商業公司裏,簡單是美。這應該是很大的思想轉變,甚至是世界觀的轉變,很難。壹般來說,轉得快的同學在公司進步更快,但我也見過幹了幾十年都沒轉過來的程序員。壹般住公司都有點累。
建議大家思考壹下我今天說的話,看問題,抓住本質。只要妳能及時了解商業公司的發展思路,懂得簡約的元素,我不敢說妳壹定能找到工作,但只要妳找到了,基本上就能很快融入公司。