引言java
咱們來看一下幾類在程序員成長、發展的常見問題,若是你或多或少存在一些,那麼恭喜你,這篇文章值得你仔細往下看了:linux
你自認爲付出了跟別人一樣的努力,可是你的成長確實更慢一些,好比學得比別人慢,排查問題比別人慢,出方案總是有漏洞等等;程序員
你以爲你只是在疲於應付需求,本身作的事情徹底沒有技術含量(不少人以爲本身作的業務開發就是沒有技術含量,但我認爲每一個領域都有本身的技術含量,只是你有沒有get到);web
你發現老是在犯一樣的錯誤,或者作的事情不斷地在同一個水平循環;算法
每次要晉升的時候,你發現根本講不出來(不少人會認爲是表達能力問題,可是我認爲不是);sql
當你換到一個新的領域,你發現本身的經驗好像用不上;數據庫
你一直很難搞懂老鳥說的「認知升級」究竟是什麼概念?不一樣級別的技術思惟能力到底有什麼差異?爲何晉升的是他,而不是我? 設計模式
在這篇文章裏,我會告訴你們一些技術成長的誤區,我先點出來:緩存
只要把事情搞定了,成長是天然而然的事情——可能過段時間,你發現以前犯過的錯誤,後來一個都沒有避免;性能優化
我只要努力,996甚至007,我就可以成長得比別人快——可能你發現你幹得最多,可是並無拿到最好的結果;
我盡力了,仍是比別人慢,應該是我智商確實差一些——恭喜你,其實你們的智商並不會有太大差異;
別人表現好,或者晉升了,只不過是比我表達能力更強而已——我能夠負責任地告訴你,這並非僅僅是表達能力的問題。
先拋一個很是重要的結論:「思考力」是程序員須要具有的一種相當重要的素質。掌握了思考力,你就掌握了在互聯網領域,這種高度「智力密集型」行業成長的鑰匙。上面這幾個成長的問題和誤區,跟沒有掌握思考力有着很是重要的關係,並且我發現全部發展比較順暢的同窗,他們的思考和學習能力是很是強悍的。
我我的在工做中,一直有意或者無心地鍛鍊本身和團隊同窗的思考力,包括哪些是對咱們最重要的思考力,如何去訓練思考力,有一些心得,但願可以分享給你們。
1、關於思考力
思考力是一門很深的學問,包括認知科學,心理學、教育學、邏輯學,若是要系統化學習,是須要看不少書的,我推薦如下幾本:
1.《金字塔原理:思考、表達和解決問題的邏輯》-[美] 芭芭拉·明託,這本書系統闡述了思考、表達和解決問題的邏輯,也是麥肯錫的思惟能力基礎,算是一本比較標準的思考力教材;
2.《麥肯錫教個人思考武器》- [日] 安宅和人,做者根據本身在麥肯錫公司工做時積累的豐富經驗以及腦神經學的專業背景,設計出一套極具邏輯性的問題解決思惟模式;
3.《思惟的本質》-[美]約翰·杜威 ,這本書是美國著名教育家約翰·杜威的表明做,闡述了思惟訓練的基礎理論和實踐;
本文並非探討思考力的深層理論,而是分享咱們從平常的技術學習和項目過程當中沉澱下來的思考力,以及如何培養這些思考力,這些思考力幾乎咱們天天均可以用到,只要你有必定體感,你必定會感同身受。
2、有哪些對程序員最重要的思考力
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嗎?是否取得了預期的效果?
項目中個人能力有哪些問題,有哪些作得好的和很差的?
系統設計的優點和不足?
項目質量保障是否能夠作得更好一些?
研發過程和項目管理是否有不足?
反思性思惟的實踐,注意有兩個點比較關鍵:
反思性思惟最重要的意識:作事情的過程總有優化的空間,每次都要有進步;若是沒有這種心態,那麼很難持續地進行反思;
反思是一種習慣和潛意識,能夠在不經意之間常常進行,其實不須要很形式化地花不少時間,有時候作完一個事情,習慣性思考一下就能夠。
3、鍛鍊思考力的有效實踐
1.意識覺醒
意識覺醒是提高思考力最重要的一個點,我認爲。只要造成了這種意識,就已經成功了一半。
不少同窗思惟能力沒有上去,是沒有意識到思考力這個概念,只是機械地作事情,作事情,作事情……每次都在同一個思惟層次上面轉悠,不可能有本質的提高。
從初級工程師,高級工程師,技術專家,高級專家,資深專家……級別提高靠什麼?多接了多少需求?多寫了多少代碼?這些因素會有,可是關鍵因素不是這些,而是思考力在不斷提高,思惟方式在不斷進化,進而致使業績產出必變得更加優秀,產生的是事半功倍的效果。
可以堅持看到這裏的同窗,必定是可以知道思考力的重要性了。
2.保持信心
如今知道思考力的重要性了,不少同窗可能認爲本身是一個不夠聰明的人。爲何我努力了,仍是不行?
給你們一個信心:有位大師說過:在相同的文明程度和種族背景下,每個正常人的潛意識與意識相加之和,在精神能量意義上基本上是相等的。
我幾乎接觸到的很努力可是成長速度不快的同窗都是由於沒有沒有掌握正確的方法;
只要掌握了正確的方法並堅持訓練,思考力絕對能夠提高。
3.空杯心態
思考的過程實際上是對人的知識進行不斷刷新和重構的過程,這裏必定要保證空杯心態,對新的環境,新的理念,新的技術持開放態度,不然就是本身給本身製造阻力。
4.思考的時間從哪裏來?
常見的藉口是「我連需求都作不完,哪來的時間思考」?
訓練思考力其實並不須要太完整的時間,個人口訣是:「1.利用碎片時間;2.抓住工做的過程」。
利用碎片時間,好比上下班路上的時間,吃飯的時候,能夠把剛纔或者今天的事情想想,想通了,而後按期彙總一下就能夠;
抓住工做的過程,注意,每次每次出技術方案,優化代碼,排查問題,處理故障,準備晉升……都是一次訓練的機會,在作事情的過程當中就能夠思考並快速實踐。
5.思考力提高有沒有什麼判斷標準?
有的,通常來講思考力有三個度:廣度、深度、速度,這你本身就可以感受出來的:
廣度:就是你本身的知識樹可以長多大的範圍,越廣知識越淵博;好比從「如何寫一個多線程程序」,提高到「如何作系統性能優化「,再到「如何作系統穩定性備戰」,這就是一種廣度的提高;
深度:就是你本身的知識樹的葉子節點有多深,越深對知識瞭解越透徹;好比從「分佈式事務問題解決思路」,到「利用最終一致性解決分佈式事務」,再到「利用DTS解決分佈式事務」,這就是一種深度的提高;
速度:就是創建和刷新知識樹的速度了。好比原來你想清楚一個建模方案要一天,如今只須要半小時能夠想清楚,那就是速度的提高了。
6.好的工具備推薦麼?
仍是推薦一個工具:Xmind,這個最土的工具最有效。能夠下載手機版和PC版本,隨時進行記錄。
7.必定要相互分享
思考雖然主要是靠本身,可是必定要相互分享。由於思考是智力活動,相互分享徹底可以取得1+1>2的效果;
注意分享能夠有不少形式,好比咱們團隊最常常的是:
項目分享:重大項目是必定要分享的,包括架構設計經驗,過程經驗,質量提高經驗,都須要分享出來;
週會分享:團隊週會重點過進度?那太浪費啦,瞭解進度和風險看週報就能夠了。週會是學習分享的好時機重點就是一些關鍵的方案,架構設計理念,好的工具,甚至工做無關的內容;
羣內分享:當有我的踩坑之後,在羣裏面提醒一下你們,這是一個很及時的分享方案;
年度/季度分享:這時候適合找個風景優美喝茶的地方,你們講一講本身的成長和思考,很是有幫助;
小圈子:你們造成本身的小圈子,隨時均可以相互傾訴一下本身的心得體會,其實這種效果也很好;
8.技術Leader在訓練你們思考力中的職責
在技術團隊中,技術Leader的思考力意識、能力和實際行動,決定了一個團隊的總體思考力水平和成長速度!
一個團隊要提升思考和學習的能力,首先得這個團隊Leader的思考意識就要提上來,若是團隊Leader沒有思考意識,也沒有把團隊同窗的成長放在心上,那麼整個團隊的思考力和成長速度絕對快不起來。
在提高團隊總體思考力的實踐中,技術Leader的職責:
先要把本身變成一個思考者,本身作表率,以身做則;
意識心態上先變過來,要把團隊同窗的成長速度最爲最重要的職責之一,沒有這個意識都是空談;
多創造思考的條件和氛圍,必定要抓住任何機會(代碼reivew、方案評審、週會均可以)鼓勵你們去思考和分享;
控制團隊節奏,給你們學習和思考留出必定的時間;
及時的引導和示範,有的同窗可能掌握會偏慢一些,這時候須要有耐心去引導同窗找到思考的感受;
沒必要過多幹預細節,發揮你們的羣體智慧,而沒必要作過多幹預,更不能以我的的意志去強迫別人接受。
4、重要觀點小結
好了,到這裏能夠給重要觀點作個小結,時間緊的同窗們能夠直接讀這一段:
思考力對程序員的成長相當重要,團隊和我的都須要有意或者無心識地提高思考能力。
對程序員最重要的思考力有:原理性思惟、結構化思惟、反思性思惟、擴展性思惟、抓重點思惟。
原理性思惟是根基,由於沒有搞懂的狀況下全部的知識建構都是空談;
結構化思惟幫助咱們創建了咱們的知識樹;
反思性思惟不斷對知識進行重構,是實現認知升級的必備條件;
擴展性思惟能夠提高知識的廣度和深度;
抓重點思惟能夠加快知識的使用效率和傳遞效率;
3. 在提高思考力的實踐中:
思考力提高最關鍵的是意識的轉變;
要對思考力的提高充滿信心;
多在工做中去鍛鍊思考力,不須要花太多額外的休息時間;
多相互分享;
團隊Leader要團隊同窗的成長和把思考力提高做爲最重要的內容,並拿出實際行動。