天天看點

工作這兩年的經驗與教訓

        來北京工作兩年了,終于從一個3D遊戲程式設計菜鳥,過渡到了一個有經驗的初級開發者。這兩年工作甚忙,自己也沒有意識到要寫篇日志來總結下自己這兩年的工作和生活,以及對未來職業發展做個清晰的規劃。最近,由于工作的不順心,想跳槽,去參加了一次筆試和面試,結果以失敗告終。我覺得,其實不是我知識水準不夠,而是學到的東西太混亂,自己沒有一個清晰的思路把問題和解決方案說明白,給面試官的感覺是能力不行。回來後,我也沒有急着去投下家,而是仔細反思了一段時間,總結了下這些年,自己在程式設計道路上的得與失,找準自己的定位,做充分的準備。

        歸納起來主要有一下幾點失誤:

1.急于求成造成事倍功半

        我是一個動手能力很強的人,做事情的時候很迫切想看到結果,這就導緻節奏過快,忽視了學習過程中應有的步驟,遺漏掉了許多基礎知識點。我一直都有一個錯誤的觀念,就是先看當下能用到的知識,其他的東西到後面用到了再學。是以在外行看來,我會相當多的東西,其實,我的基礎一點都不紮實。由于有太多的東西放在了後期學習,是以現在我每天都在還債,學習那些曾經遺漏的知識。

        大學的時候,因為c語言學的還不錯,花了一周時間就看完一本c++語言大學教程,自認為已經掌握c++了。後來花了一兩個月的時間學習MFC,會寫電腦之類的圖形界面程式了,自認為自己會MFC了。結果呢?距離學習開始到現在,4年過去了,每年都會再學到很多c++的知識,我現在還在看《STL源碼剖析》,《C++ Templates》,如果不學好這些東西,根本沒法看懂大牛寫的代碼。那些大型遊戲引擎源碼,從文法層面來說,你確定百分百能讀懂嗎?文法都弄不明白,還怎麼去讀懂他背後神秘的算法呢?

        假設一下,如果你會c++基本文法,但是你不懂STL,不懂模闆,不懂動态多态,你來做一款射擊類小遊戲,如何下手呢?我想,你肯定會為子彈集合設計一個連結清單,為飛機集合設計一個連結清單,如果飛機類型有多種,那每種類型的飛機都會設計一個連結清單,那麼遊戲循環應該是這樣寫的:

while(true)

{

selfBulletList.update(elapse);

enemyBulletList.update(elapse);

enemyList.update(elapse);

player.update(elapse);

}

        如果你會上面所提到的知識,這裡隻用stl::list就可以搞定了,你什麼連結清單實作代碼也不用寫。而且,遊戲裡所有類型物體,都可以使用動态多态原理放到同一個list裡。遊戲循環就會變成這樣:

std::list<GameObject *> objectList;

while(true)

{

for(GameObject * p : objectList) //c++11文法

p->update(elapse);

}

        是不是很簡潔,是不是節剩了很多時間,是不是少調了很多bug?重點不是這一個地方簡潔了,如果你是一個多産的程式員,你一個月寫了5款小遊戲,上面那些備援的代碼你要寫5遍?

        再舉個例子,駕馭500行以内的代碼量,對菜鳥來說基本上都是小意思。但代碼量超過5k行的時候,有些人就抗不住了,程式開始失控了,bug層出不窮,各種指針崩潰問題難以查明原因。開始網上到處求助,病急亂投醫,結果連問題出在哪自己都描述不清楚,别人又如何幫助你解決呢?

        是以,一味的追求結果,而忽視了程式員應具備的基礎知識以及完善的知識體系,在求職、工作以及後續的學習當中,是要付出沉重代價的。急于求成的心态,不但會浪費你大量時間跟精力,還會打消你的自信心,讓你在面試官 面前,把技術缺陷暴露的一覽無餘,成為一個會說話的啞巴。

        我不會告訴你,我就是這樣一路走過來的。

2.學習速度過快,超過吸收領會速度

        這兩年,我大概看過10本左右的程式設計技術書籍。你要問我對那本映像最深刻,我的回答是沒有。因為看的太快了,也沒有做什麼讀書筆記,事後也沒有複習過,是以看完一段時間後,就忘卻了書裡的内容——這不就相當于沒看。

        而且,經常會碰到一些很難了解的知識,就跳過了,事後也沒有回過頭來再看——這不就是,會的還是會的,不會還是不會的。

3.沒有做到舉一反三,缺乏發現問題的能力

        沒有養成一個思考的好習慣,學完一門知識就學完了,也沒有多思考他的用處,也沒有思考知識本身的缺陷。解決了一個問題,當面對另一個變體的問題後,就想不到一個合适的解決方案。

        當策劃的一個設計方案存在問題的時候,自己總是不能在動手實作之前發現設計缺陷,等到寫了部分代碼的時候,才恍然發現,這個設計按照現有的接口,無法實作!或者,實作了這個設計方案,卻無意間破壞了其他功能。

4.閉門造車,缺乏交流,把别人的建議不當回事

        一直以來,我自己寫代碼,做demo,從來沒有跟别人交流過,也沒采納過别人的意見。感覺就是一個人在盲目的摸索,把自己禁锢在自己的思想裡,自認為自己水準不錯,其實,自己隻是一個碼農。

5.盲目讀/寫代碼浪費時間

        很多時候,在學習一項技術的時候,看到一部分後,實在難以繼續看懂,我就會根據自己的了解,用自己的方式來實作。雖然這是好事,但是,畢竟自己隻是這樣猜測,做出的東西功能很簡單,最終要實作一個完整的功能,還得需要了解哪些技術。花大量時間瞎猜、寫代碼、調bug,把這些時間拿來仔細學習這些技術相關的知識,已經綽綽有餘了。

        舉個例子,我之前學習碰撞檢測的時候,我先參考過BigWorld1.8源碼,它是用bsp實作的,勉強看懂了部分代碼,然後憑自己的了解,實作了一個簡單的bsp碰撞檢測,結果射線拾取效率還過得去,體碰撞處理的效率實在很低。準備繼續看Bigworld如何優化體碰撞時,怎麼也看不懂,因為我是抛開其他功能隻看碰撞部分的,而碰撞檢測又必須依賴一些底層子產品,比如地形、物體組織結構、數學庫等。我隻想學習碰撞,然後給我的demo加入碰撞檢測,暫時不想花時間學習其他的東西,是以就放棄了研究BigWorld。

        于是,我在網上搜尋一些輕量級的碰撞檢測庫,找到了一個叫Opcode的開源庫。這個庫大緻是使用AABB樹來解決問題的。看到一部後源碼後,實在難以繼續下去了,然後我又就根據自己對Opcode的了解,對先前的bsp代碼進行了改版,改成了我所謂的“八叉樹”(其實就是AABB樹的一種),利用八分空間的思想,将三角網格分成八部分,每次碰撞檢測的時候,都從整體到局部去檢測,這次效率确實是提高了,我的目的終于達成了。

        功能是實作了,但是仔細想想,覺得很不值。研究BigWorld、Opcode、自己實作bsp和AABB樹,中間還有在網上搜集資料的時間,學習一些零散的計算幾何知識,這些時間加起來,大概有3個多月。我覺得靜下心來,我看完《3D數學基礎》+《實時碰撞檢測算法技術》+Opcode源碼的時間也不會超過3個月。而且,如果我安照後者方案進行,我還會形成一套完整的知識體系,而且還能将Opcode以最恰當的方式內建到我的demo中來。

        結果,我現在所了解的碰撞檢測知識,也隻是我寫過代碼的那部分,其餘的知識一無所知,這不就是一種悲哀嗎。

7.小結

        當學習一項技術的時候,切忌不要從源碼開始,上來就讀“核心”源碼,而是從相關的書籍、文檔開始。如果一段代碼看不懂,大緻有兩個原因,一是不了解代碼背後所使用到的算法;二是不熟悉此代碼所依賴的其他子產品。找準問題的本質,切莫硬着皮頭看下去,否則隻能身心俱疲。

        不要為了看書而看書,看完一部分要做個總結,用自己的話把核心技術描述出來,也就是做個讀書筆記。隔一段時間,再複習一下自己的筆記,避免遺忘。好書應該堅持看完,看到一半,那不叫看過,那叫翻過。

        基礎知識一定要紮實,熱門技術也一定要熟知。以免在筆試、面試的時候吃啞巴虧。

        對于代碼狂來說,少寫代碼多讀書,讀别人代碼。團隊合作,大部分時間都是了解别人代碼,了解别人提供的接口。

        總覺得每次方案小修改,都有大量代碼要改改,那是因為你的程式架構不好。

        多練習跟别人交流,鍛煉表達能力。能把問題描述清楚的程式員沒有幾個,能用問題的嚴重性說服設計者改變方案的程式員更少。

        任何程式設計工作都是技術活,沒有所謂的簡單。寫腳本跟寫引擎,同樣都是技術活,能把腳本寫好的人也沒有幾個,你不信的話,可以去應聘主程職位,我不信所有寫腳本的都可以勝任主程。

繼續閱讀