引言
我們來看一下幾類在程序員成長、發展的常見問題,如果你或多或少存在一些,那么恭喜你,這篇文章值得你仔細往下看了:
-
你自認為付出了跟別人同樣的努力,但是你的成長確實更慢一些,比如學得比別人慢,排查問題比別人慢,出方案老是有漏洞等等;
-
你覺得你只是在疲於應付需求,自己做的事情完全沒有技術含量(很多人覺得自己做的業務開發就是沒有技術含量,但我認為每個領域都有自己的技術含量,只是你有沒有get到);
-
你發現總是在犯同樣的錯誤,或者做的事情不斷地在同一個水平循環;
-
每次要晉升的時候,你發現根本講不出來(很多人會認為是表達能力問題,但是我認為不是);
-
當你換到一個新的領域,你發現自己的經驗好像用不上;
-
你一直很難搞懂老鳥說的“認知升級”到底是什么概念?不同級別的技術思維能力到底有什么差別?為什么晉升的是他,而不是我?
在這篇文章里,我會告訴大家一些技術成長的誤區,我先點出來:
-
只要把事情搞定了,成長是自然而然的事情——可能過段時間,你發現之前犯過的錯誤,后來一個都沒有避免;
-
我只要努力,996甚至007,我就能夠成長得比別人快——可能你發現你干得最多,但是並沒有拿到最好的結果;
-
我盡力了,還是比別人慢,應該是我智商確實差一些——恭喜你,其實大家的智商並不會有太大差別;
-
別人表現好,或者晉升了,只不過是比我表達能力更強而已——我可以負責任地告訴你,這並不是僅僅是表達能力的問題。
先拋一個非常重要的結論:“思考力”是程序員需要具備的一種至關重要的素質。掌握了思考力,你就掌握了在互聯網領域,這種高度“智力密集型”行業成長的鑰匙。上面這幾個成長的問題和誤區,跟沒有掌握思考力有着非常重要的關系,而且我發現所有發展比較順暢的同學,他們的思考和學習能力是非常強悍的。
我個人在工作中,一直有意或者無意地鍛煉自己和團隊同學的思考力,包括哪些是對我們最重要的思考力,如何去訓練思考力,有一些心得,希望能夠分享給大家。
一、關於思考力
思考力是一門很深的學問,包括認知科學,心理學、教育學、邏輯學,如果要系統化學習,是需要看很多書的,我推薦以下幾本:
1.《金字塔原理:思考、表達和解決問題的邏輯》-[美] 芭芭拉·明托,這本書系統闡述了思考、表達和解決問題的邏輯,也是麥肯錫的思維能力基礎,算是一本比較標准的思考力教材;
2.《麥肯錫教我的思考武器》- [日] 安宅和人,作者根據自己在麥肯錫公司工作時積累的豐富經驗以及腦神經學的專業背景,設計出一套極具邏輯性的問題解決思維模式;
3.《思維的本質》-[美]約翰·杜威 ,這本書是美國著名教育家約翰·杜威的代表作,闡述了思維訓練的基礎理論和實踐;
本文並不是探討思考力的深層理論,而是分享我們從日常的技術學習和項目過程中沉淀下來的思考力,以及如何培養這些思考力,這些思考力幾乎我們每天都可以用到,只要你有一定體感,你一定會感同身受。
二、有哪些對程序員最重要的思考力
A. 原理性思維:找出知識背后的原理
有的人會說,為什么要思考原理,而不是直接掌握知識就可以了?我只需要會用就行了啊。
我們先來舉一些技術方案設計的案例:
-
為什么訂單創單要先create,然后enable?
這其實是一種采用二階段提交解決分布式事務的思路,只是從一般的事務框架延展到交易領域;
-
業務系統中為什么要使用消息?
因為消息使用的是觀察者模式,觀察者模式的好處是可以實現多個消費事務與觸發事務的解耦;
-
為什么業務系統中會使用DTS來做補償?
這本質上是一種最終一致性BASE理論解決分布式事務的一種思路;
-
為什么更新數據的時候一定要在sql中加上版本比對或者狀態比對?
這本質上是一種借助DB實現的樂觀鎖機制。
進一步,你會發現再大到系統架構和頂層設計的案例:
-
比如阿里系的技術框架NBF、TMF、早期的webx,各類框架設計理念,逃不脫設計模式,比如開閉原則,模板方法、責任鏈、工廠模式、開閉原則;
-
不管是底層中間件,錯綜復雜的業務系統,在設計的時候永遠無法離開核心的業務建模,比如實體與實體關系的構建;在分析這類系統的設計思想時,你會發現最好的工具就是UML!
實際上除了軟件領域的原理,還有商業設計的原理,比如案例:
-
所有的售中退款前必須要先取消履約,所有的履約過程中發生缺貨都需要退款,為什么?因為交易的基本原則是:“錢貨平衡”,錢和貨的變更必須是最終同步的(允許短期的不平衡),你掌握了錢貨平衡的基本原理,交易中的很多復雜的流程設計就很好理解了;
-
在設計財務系統、庫存系統時候,業務流程、業務邏輯可能非常復雜,導致你暈頭轉向,這時候“有借必有貸,借貸必相等”的財務平衡性原理就發揮作用了,你只要知道這個原理,很快就能看懂各類財務流程、庫存流轉流程,以及各類數據對賬邏輯;
-
在我的領域“高可用線下收銀系統”進行線下系統容災的時候,有各種容災方案的設計,會員容災、商品容災、交易容災、支付容災……不同的容災手段看起來讓你眼花繚亂,但是他們有沒有共同遵循的原則呢?有,這就是“讓消費者最快速度完成交易,但保持最后追溯的能力”。你只要get到這個基本原理,設計各類容災策略就會得心應手了。
此外,我們的工作流程、管理手段,同樣也蘊含着深層的原理,非常有意思,大家可以抽空仔細推敲一下,比如:
-
為什么團隊機制要透明?溝通要透明?
-
為什么要有owner意識,都是在工作,owner意識會有什么不同呢?
-
為什么管理者不能管得太細,也不能放羊?到底哪些該管,哪些不該管?
所以,掌握了知識背后的原理,帶來的好處是:
-
軟件系統的復雜度越來越高,我們所面對的場景越來越多,掌握原理實際上可以大幅度降低我們對於知識的記憶量,知識量是爆炸的,但是原理絕對是可控的!
-
原理性的東西比直接的知識有更強的復用度!記住最核心的原理,當你面對新的場景時,你會驚喜地發現,你的理解速度大大加快!這個點大家應該有體會,比如可能之前我們都學習過dubbo等底層的RPC通信框架的基本原理,但是你如果僅了解了他的基本用法,你會發現對你現在做業務系統沒有什么幫助!但是,當你了解的是dubbo如何尋址,如何做容災,如何做擴展,你再去做業務系統,發現設計原理是一樣的,並沒有本質區別!這樣你之前研究中間件的設計思想就可以快速用到業務系統上面。
-
另外探求原理的過程,本身很有樂趣!這是一個非常有價值的思維訓練過程,不斷對系統設計思想、業務設計思想、做事情的工作方式,追尋背后的原理,並找到他們之間的共性,在我看來非常有樂趣,一段時間訓練以后,你會發現你看透本質的能力越來越強!
好,那么我們程序員的工作中,究竟有哪些與原理性知識是需要我們掌握的呢?按我們團隊的實戰經驗來看:
-
java,linux,數據結構和算法,數據庫,網絡通信與分布式計算的原理,這幾類是比較重要的基礎知識,我們在做方案設計、編碼、問題排查中會運用得很多;
-
設計模式,UML這個是對系統架構設計必要要掌握的知識,當你經歷了很多大規模的軟件系統設計,回到根本上,你會發現逃不出這一塊的理論和工具;
-
領域性的基本原則,比如我們上面提到的“錢貨平衡”,“財務平衡公式”,“線下收銀讓消費者最快速度走人”,這種邏輯需要大家get到這些領域性的設計原理,甚至自己去總結出這種原理;
-
關於管理學,人際溝通,心理學的一些基本原理,大家可以按照自己的實際需求去看一下。
如何在工作中學習和運用這些原理,我覺得有一個最佳實踐:
-
首先,對你可能用到的領域知識,建立一個基本的概念。看書,看文章,找行業資深的人去聊,都可以得到。注意,這里需要有一個基本的概念就可以,這樣你在有可能touch到這些原理的時候,你會有意識,也不至於花很多時間;
-
在實踐中,有個意識是“多問一下為什么”,並一直“刨根問底”,最終肯定能夠追查到背后的最終原理;這里面還要注意思考一下,為什么在這個地方會運用這個原理,也就是找到“場景”和“原理”的關聯關系,這樣你的理解會更加深刻;
-
了解了原理以后,在實踐中運用一下,這樣你對這個原理的理解就會非常深刻,並且你知道如何去運用這原理;
-
如果這是一個非常重要的原理,建議大家如有余力去結合經典的書籍系統化學習。
B. 結構化思維:構建自己的知識樹
知識樹要解決的問題,我們看一些場景:
-
為什么我知道很多東西,但是當場景來的時候老是會記不起來使用;
-
完成一個方案你只能想到一些點狀的手段,還有其他方案被漏掉了;
-
講一件事情的時候邏輯非常混亂,前后沒有邏輯性關聯。
但是很有可能你的知識都是知道的,為什么會出現這種悲劇?
這個就跟大腦中的知識結構有關,這是知識學習中“索引”沒有建立,也就是說,你的知識只有點,沒有線!大家想一想,把東西亂七八糟地丟在房間中,到用的時候沒有查找的線索和路徑,怎么找得到呢?
來看一下我們工作場景的結構化的典型案例,大家體會一下:
項目中測試MM提了一個bug,我總結出來的比較標准的問題定位步驟:
-
確認剛才是否有過代碼變更和部署,因為有比較高的概率是剛才變更的代碼又搞壞了……
-
追蹤鏈路日志看鏈路是否有異常;
-
通過RPC的控制台調用看接口輸入輸出是否符合預期;
-
追蹤關鍵方法的入參和出參,看是否有問題;
-
定位到方法細節后,推理邏輯是否有問題;
-
如果無法通過推理,那就最后一招,回放異常流量debug,這樣肯定能夠找到原因。
某個鏈路耗時比較長,需要進行性能優化,我的分析步驟是:
1. 通過實際流量制造一個耗時較高的trace;
2. 進行trace分析,看清楚耗時最多的原因,然后按優先級進行排序;
3. 針對對原因找解決方案,可能的方案有:
-
減少數據訪問次數或者計算量,常見手段是增加cache:線程內的invokeCache;分布式緩存tair;頁面緩存……
-
增強處理速度,比如多線程加速;
-
減少循環調用次數,比如請求合並后再分發;
-
減少數據處理范圍,比如減少查詢內容,異步加載分頁;
-
邏輯簡化,比如邏輯進行優化,或者非核心邏輯異步化等;
-
……
4.改掉以后,回放同樣的case,看性能消耗是否滿足預期,不滿足預期繼續優化;
如何熟悉一個新系統,我的步驟是:
-
要一個測試賬號,把相關功能走一遍,這樣能非常快地了解一個系統的功能;
-
看關鍵的核心表結構,這樣可以快速了解系統的領域模型;
-
根據功能步驟找到系統對外的接口列表,了解系統的L0業務流程;
-
下載系統工程,熟悉整個工程結構和模塊職責;
-
以一個最重要的流程為入手點,閱讀代碼,看清楚核心的執行邏輯,可以變看邊畫時序圖;
-
制造一個debug場景,以debug方式走一遍流程,這樣可以實際加深一下對系統的理解;
-
做一個小需求,掌握相關的流程和權限;
下單這里來了一個新的需求,出一個技術方案的步驟:
1. 看清楚之前的需求,把這個需求所在的場景和鏈路大致閱讀一遍,搞懂;
2. 找到需求的變化點;
3. 分析變更的方案,涉及的內容可能會有:
-
數據結構會不會變,如何變;
-
交互協議會不會變,如何變,交互協議分為:端和組件要不要變;和下游接口要不要變;
-
執行邏輯會不會變,如何變,執行邏輯變更的細化考慮點:是否變更域服務;是否變更流程編排;是否變更主干邏輯;是否變更擴展點是否變更擴展點的內部邏輯,變更內部邏輯的時候,又可以進一步拆解:
a.重構原有的方法,覆蓋之前的邏輯,那就需要進行回歸;
b.通過邏輯路由到新的方法,這里需要增加路由邏輯;
4. 穩定性方案;
5. 發布方案;
可以看到,面對任何一個場景,不管多大多小,我們所需要掌握的知識或者技能都可以構建成一個樹結構,同類之間是順序關系,上下之間是父子關系(或者粗細顆粒度)。
當這個樹在大腦中構建起來以后,你會發現你做什么事情都是有一個明確的分析和執行邏輯,不太可能產生遺漏和混亂!
那么如何訓練出自己的知識樹呢?我給一些比較有效的實踐方案:
1. 一定要總結出自己的知識樹,而不要盲從書本上的或者別人的,為什么呢?一是因為人的思維速度和習慣、技能有一定差異,不一定每個人都是一樣的;二是如果沒有內化別人的知識成為自己的知識,這棵樹不太能夠很熟練地運用;
2. 習慣性總結,做完任何一個事情,都習慣性地回顧一下,往自己的樹上面掛新東西,這個是構建知識樹的必備手段,這個總結不需要花很多時間,比如做完事情后花個幾分鍾回顧一下就可以,但是需要堅持;
3. 推薦一個很常見的工具:xmind,把自己的樹記錄下來;
4. 訓練自己的思維習慣和做事方式變得結構化,當你做事情的時候,習慣性用樹的方式推進,強迫自己按照這個方式來。
C. 擴展性思維:舉一反三,拓展思維
擴展性思維的核心目標是提升我們思維的廣度,也就是讓我們的知識樹變得更加開闊;
我在工作中總結出來的擴展性思維的兩個關鍵的擴展方向:
(1)舉一反三:解決同類型的N個問題
舉一反三的好處是:“我們能否用同樣的知識和手段去解決類似的相關聯的幾個類似問題”,先舉一些案例:
-
當發現某個系統的jvm參數配置存在一個錯誤配置,不是僅僅修復這個系統的jvm配置,而是把負責的幾個系統都檢查一下是否需要統一修改;
-
系統中存在某個bug導致產生了臟數據,不是直接訂正已發現的臟數據,而是根據特征拉取出所有的臟數據,進行一次性處理;
這種思維方式的特征是舉一反三,觸類旁通,相當於產生批處理的效果,可以大大提升解決問題的效率,避免重復處理。
(2)尋求更多的可能性:拓展解決問題的不同手段
拓展思維常見的手段是:是否能夠換更多的理解方式,或者更多的解法,舉一些案例:
-
產生故障的時候,快速止血除了回滾以外,還有哪些方案?如果故障處理經驗豐富的人一定知道,除了回滾,其實還有系統降級,運營活動降級等多種方案;
-
除了寫更加健壯的代碼,還有哪些手段都可以提升系統的容錯性?還有數據監控,單據閉環等多種手段;
當解決問題的手段更多了,思維就開闊了。
D. 抓重點思維:提升效率,方便記憶和傳遞
當我們發現知識樹構建起來以后,怎么樣使得記憶和使用的效率變高?而且對外傳遞的時候更加容易讓人理解?抓重點思維要解決的場景是:
-
如果每件事情都按照知識樹方式做,效率可能不會特別高,有更快的辦法么?
-
在對外溝通表達的時候,要表達核心思想,否則別人會很難理解你的表達內容;比如大家再晉升答辯、項目匯報的時候一定會有體會。
解決這兩類困惑,核心思路是要抓住重點和脈絡。
但是抓住重點和知識結構化之間並不矛盾,而且我認為是有先后次序的,一定要先建立知識結構化,然后才能從里面篩選出重點,否則知識的體系是不完整的。
那么篩選重點的思路有哪些呢?
(1)歸納法
采用歸納法,把細節隱藏掉,呈現知識的脈絡,這是一種非常好的思路;尤其是大家在准備晉升ppt時,ppt的每一頁都需要歸納一個核心觀點,不是全是細節,這個非常重要!並且訓練歸納的能力,本身就是對知識理解深刻程度的一種反映;
(2)優先級法
優先級策略往往應用於在多項任務之間找到最最關鍵或者收益最大的那個任務項,比如完成一個事情可能有若干個步驟,其中哪個步驟是最有效的,大致可以做一個排序。在實施的時候,你可以按照優先級去落實。
但是找到效果最好的那個任務項,在不同場景下是不同的,跟我們的熟練程度和經驗有關。就像老中醫把脈,越有經驗判斷越准,這塊沒有什么捷徑,只能不斷練習自己找到哪些任務項在什么場景下更加重要。
E. 反思性思維:思考哪里可以做得更好
反思性思維是提升知識質量和深度的一個關鍵能力。因為只有不斷反思才能讓下一次在上一次基礎上升級,而不是重復循環。
常見的反思案例:
-
有個問題我查了2個小時,師兄只花了10分鍾,這是為什么呢?是他的業務比我熟悉?思路比我清晰?還是知道某個我不知道的工具?一定要找到關鍵的差異點,然后彌補掉這個差距;
-
一個項目項目做完了,從方案設計,研發過程,質量保障上面,哪些地方下次可以做得更好?找到不足,下次避免;
對於我們技術團隊,哪些內容值得反思,我們團隊的經驗是:
-
這個項目商業價值OK嗎?是否取得了預期的效果?
-
項目中我的能力有哪些問題,有哪些做得好的和不好的?
-
系統設計的優勢和不足?
-
項目質量保障是否可以做得更好一些?
-
研發過程和項目管理是否有不足?
反思性思維的實踐,注意有兩個點比較關鍵:
-
反思性思維最重要的意識:做事情的過程總有優化的空間,每次都要有進步;如果沒有這種心態,那么很難持續地進行反思;
-
反思是一種習慣和潛意識,可以在不經意之間經常進行,其實不需要很形式化地花很多時間,有時候做完一個事情,習慣性思考一下就可以。
三、鍛煉思考力的有效實踐
1.意識覺醒
意識覺醒是提升思考力最重要的一個點,我認為。只要形成了這種意識,就已經成功了一半。
很多同學思維能力沒有上去,是沒有意識到思考力這個概念,只是機械地做事情,做事情,做事情……每次都在同一個思維層次上面轉悠,不可能有本質的提升。
從初級工程師,高級工程師,技術專家,高級專家,資深專家……級別提升靠什么?多接了多少需求?多寫了多少代碼?這些因素會有,但是關鍵因素不是這些,而是思考力在不斷提升,思維方式在不斷進化,進而導致業績產出必變得更加優秀,產生的是事半功倍的效果。
能夠堅持看到這里的同學,一定是能夠知道思考力的重要性了。
2.保持信心
現在知道思考力的重要性了,很多同學可能認為自己是一個不夠聰明的人。為什么我努力了,還是不行?
給大家一個信心:有位大師說過:在相同的文明程度和種族背景下,每一個正常人的潛意識與意識相加之和,在精神能量意義上基本上是相等的。
我幾乎接觸到的很努力但是成長速度不快的同學都是因為沒有沒有掌握正確的方法;
只要掌握了正確的方法並堅持訓練,思考力絕對可以提升。
3.空杯心態
思考的過程其實是對人的知識進行不斷刷新和重構的過程,這里一定要保證空杯心態,對新的環境,新的理念,新的技術持開放態度,否則就是自己給自己制造阻力。
4.思考的時間從哪里來?
常見的借口是“我連需求都做不完,哪來的時間思考”?
訓練思考力其實並不需要太完整的時間,我的口訣是:“1.利用碎片時間;2.抓住工作的過程”。
-
利用碎片時間,比如上下班路上的時間,吃飯的時候,可以把剛才或者今天的事情想一想,想通了,然后定期匯總一下就可以;
-
抓住工作的過程,注意,每次每次出技術方案,優化代碼,排查問題,處理故障,准備晉升……都是一次訓練的機會,在做事情的過程中就可以思考並快速實踐。
5.思考力提升有沒有什么判斷標准?
有的,一般來說思考力有三個度:廣度、深度、速度,這你自己就能夠感覺出來的:
-
廣度:就是你自己的知識樹能夠長多大的范圍,越廣知識越淵博;比如從“如何寫一個多線程程序”,提升到“如何做系統性能優化“,再到“如何做系統穩定性備戰”,這就是一種廣度的提升;
-
深度:就是你自己的知識樹的葉子節點有多深,越深對知識了解越透徹;比如從“分布式事務問題解決思路”,到“利用最終一致性解決分布式事務”,再到“利用DTS解決分布式事務”,這就是一種深度的提升;
-
速度:就是建立和刷新知識樹的速度了。比如原來你想清楚一個建模方案要一天,現在只需要半小時可以想清楚,那就是速度的提升了。
6.好的工具有推薦么?
還是推薦一個工具:Xmind,這個最土的工具最有效。可以下載手機版和PC版本,隨時進行記錄。
7.一定要相互分享
思考雖然主要是靠自己,但是一定要相互分享。因為思考是智力活動,相互分享完全能夠取得1+1>2的效果;
注意分享可以有很多形式,比如我們團隊最經常的是:
-
項目分享:重大項目是一定要分享的,包括架構設計經驗,過程經驗,質量提升經驗,都需要分享出來;
-
周會分享:團隊周會重點過進度?那太浪費啦,了解進度和風險看周報就可以了。周會是學習分享的好時機重點就是一些關鍵的方案,架構設計理念,好的工具,甚至工作無關的內容;
-
群內分享:當有個人踩坑以后,在群里面提醒一下大家,這是一個很及時的分享方案;
-
年度/季度分享:這時候適合找個風景優美喝茶的地方,大家講一講自己的成長和思考,非常有幫助;
-
小圈子:大家形成自己的小圈子,隨時都可以相互傾訴一下自己的心得體會,其實這種效果也很好;
8.技術Leader在訓練大家思考力中的職責
在技術團隊中,技術Leader的思考力意識、能力和實際行動,決定了一個團隊的整體思考力水平和成長速度!
一個團隊要提高思考和學習的能力,首先得這個團隊Leader的思考意識就要提上來,如果團隊Leader沒有思考意識,也沒有把團隊同學的成長放在心上,那么整個團隊的思考力和成長速度絕對快不起來。
在提升團隊整體思考力的實踐中,技術Leader的職責:
-
先要把自己變成一個思考者,自己做表率,以身作則;
-
意識心態上先變過來,要把團隊同學的成長速度最為最重要的職責之一,沒有這個意識都是空談;
-
多創造思考的條件和氛圍,一定要抓住任何機會(代碼reivew、方案評審、周會都可以)鼓勵大家去思考和分享;
-
控制團隊節奏,給大家學習和思考留出一定的時間;
-
及時的引導和示范,有的同學可能掌握會偏慢一些,這時候需要有耐心去引導同學找到思考的感覺;
-
不必過多干預細節,發揮大家的群體智慧,而不必做過多干預,更不能以個人的意志去強迫別人接受。
四、重要觀點小結
好了,到這里可以給重要觀點做個小結,時間緊的同學們可以直接讀這一段:
-
思考力對程序員的成長至關重要,團隊和個人都需要有意或者無意識地提升思考能力。
-
對程序員最重要的思考力有:原理性思維、結構化思維、反思性思維、擴展性思維、抓重點思維。
-
-
原理性思維是根基,因為沒有搞懂的情況下所有的知識建構都是空談;
-
結構化思維幫助我們建立了我們的知識樹;
-
反思性思維不斷對知識進行重構,是實現認知升級的必備條件;
-
擴展性思維可以提升知識的廣度和深度;
-
抓重點思維可以加快知識的使用效率和傳遞效率;
-
3. 在提升思考力的實踐中:
-
-
思考力提升最關鍵的是意識的轉變;
-
要對思考力的提升充滿信心;
-
多在工作中去鍛煉思考力,不需要花太多額外的休息時間;
-
多相互分享;
-
團隊Leader要團隊同學的成長和把思考力提升作為最重要的內容,並拿出實際行動。
-