從碼農(nóng)到大牛,做到技術(shù)與心境的雙重提升!
來自當(dāng)當(dāng)架構(gòu)部的張亮老師,從技術(shù)和情懷的角度分享自己的成長軌跡,具備工匠精神的同時也要注重回報(bào)社會,做到技術(shù)與心境雙重提升。
業(yè)務(wù)功能關(guān)注點(diǎn)
對于一個做技術(shù)的從業(yè)人員來說,大部分人開始走的是一條技術(shù)+業(yè)務(wù)的線路。
從業(yè)務(wù)功能方面回顧一下工程師工作的大致內(nèi)容:
- 業(yè)務(wù)理解和分析,通過解讀需求文檔,理解并分析業(yè)務(wù)。
- UML 建模,將對業(yè)務(wù)的理解抽象和歸納為領(lǐng)域模型,并通過繪制 UML 展現(xiàn)。
- 數(shù)據(jù)庫表結(jié)構(gòu)設(shè)計(jì),大部分應(yīng)用程序都是有數(shù)據(jù)庫的。在設(shè)計(jì)過程中,有人喜歡先設(shè)計(jì)數(shù)據(jù)庫表結(jié)構(gòu),再創(chuàng)建域模型,也可以反過來,習(xí)慣而已。
- 選擇合適的開發(fā)框架,在表結(jié)構(gòu)設(shè)計(jì)完畢之后,就會選擇或搭建合適的開發(fā)框架,然后進(jìn)入開發(fā)階段?;A(chǔ)框架采用分層模型居多,選用 ssh 或 ssi 等流行的框架比較常見。
隨著經(jīng)驗(yàn)越來越豐富,工程師的關(guān)注點(diǎn)從功能需求逐漸擴(kuò)展到了非功能需求。功能的滿足只是冰山浮在水面上的一小塊。
而冰山下面的的巨大沉積物則是非功能需求,它們經(jīng)常被非技術(shù)從業(yè)人員所忽視,但卻是實(shí)實(shí)在在地影響一個系統(tǒng)成功與否的關(guān)鍵。
非功能需求關(guān)注點(diǎn)
非功能需求有如下四個關(guān)注點(diǎn):
安全性,有無 SQL 注入和跨域腳本攻擊的問題;密碼是否明文在網(wǎng)絡(luò)間傳輸;是否可通過主鍵推算出其他主鍵并達(dá)到非法訪問的目的(如:ID 是連續(xù)的,只要知道一個 ID,就可能獲取到其他人的信息)。
健壯性,程序是否由于異常情況導(dǎo)致崩潰,性能是否穩(wěn)定(如:鎖的不正確使用導(dǎo)致等待過多)等。
可伸縮性,業(yè)務(wù)成長初期和業(yè)務(wù)爆發(fā)性增長期的應(yīng)用承載量是完全不同的。當(dāng)業(yè)務(wù)快速增長,應(yīng)用承載量大幅度提升時,如何通過增加服務(wù)器數(shù)量的水平擴(kuò)展而不是增加單一服務(wù)器硬件配置的垂直擴(kuò)展來達(dá)到承載更多流量和數(shù)據(jù)量的目的,并且可以在流量洪峰平穩(wěn)度過后適當(dāng)?shù)臏p少硬件服務(wù)器來控制成本。
可維護(hù)性,在需要人工介入的系統(tǒng)部署流程中,失誤無法完全避免。并且由于網(wǎng)絡(luò)抖動而需要運(yùn)維或重啟時,大量的手工操作難免手忙腳亂,極易產(chǎn)生操作延遲。應(yīng)通過自動化調(diào)度以及部署來幫助運(yùn)維工程師盡量降低人工介入的頻度。
在成長的軌跡中,工程師大多從微觀入手,并最終領(lǐng)悟如何從宏觀看待技術(shù)。
成長軌跡:微觀關(guān)注點(diǎn)
幾個常見的微觀關(guān)注點(diǎn):
- 如何對慢 SQL 創(chuàng)建索引?相信工程師們應(yīng)該都做過這件事,分析 SQL 執(zhí)行計(jì)劃,查看索引命中情況等。
- 如何保證線程安全?單線程時沒有問題,但多線程時則可能產(chǎn)生莫名其妙的問題。如何在多線程中合理的使用 synchronized,volatile 以及并發(fā)包等,是重要且困難的。
- 并不是不寫多線程代碼就能完全規(guī)避這些問題。若使用的框架包括多線程,也需要使用者理解它的線程模型。
- 如何減少 Full GC 的頻度?一個跑在 JVM 里面的程序,如果每小時做一次 Full GC 導(dǎo)致應(yīng)用停止響應(yīng)一秒的時間,在性能以及并發(fā)要求較高的系統(tǒng)中是難以接受的。需要通過 JVM 調(diào)優(yōu)來降低 Full GC 頻度。
- 如何考慮使用設(shè)計(jì)模式?設(shè)計(jì)模式是發(fā)現(xiàn)而非發(fā)明出來的,目前設(shè)計(jì)模式已經(jīng)歸納的很成熟了,已不太容易再發(fā)現(xiàn)新設(shè)計(jì)模式。利用設(shè)計(jì)模式可以更好的寫出結(jié)構(gòu)清晰,易于理解的代碼,并降低相互的溝通成本。
- 如何寫出具備強(qiáng)表現(xiàn)力的代碼?若代碼本身難以理解,即使通過注釋也難于讓代碼本身具有表現(xiàn)力。而且代碼和注釋也不一定是同步修改的。
著急改代碼,但注釋沒有改的情況比較常見,這樣的注釋是沒有價(jià)值的,不如花些時間讓代碼本身更具展現(xiàn)力。
成長軌跡:宏觀關(guān)注點(diǎn)
隨著時間的推移以及經(jīng)驗(yàn)的累積,工程師會漸漸地關(guān)注更加宏觀的方面,例如:
如何選用適合數(shù)據(jù)庫存儲相應(yīng)的數(shù)據(jù)?
對于存儲訂單、交易等核心數(shù)據(jù),穩(wěn)定成熟的關(guān)系型數(shù)據(jù)庫是不二之選;對于存儲帖子類的文本數(shù)據(jù), ES 就會更加合適。
因此需要工程師了解各種數(shù)據(jù)庫的適合場景,結(jié)合上下文分析并最終確定選型。
如何規(guī)劃系統(tǒng)范圍的劃分和拆分?
規(guī)模較大公司的系統(tǒng)不可能僅有一個或幾個,它們也不會將所有的服務(wù)全部部署在同一個應(yīng)用服務(wù)器中,而是將其拆分為幾十、幾百甚至上千個系統(tǒng)。
無論是當(dāng)前較為流行的微服務(wù)架構(gòu),還是以前提及較多的 SOA 架構(gòu),都需要對系統(tǒng)進(jìn)行拆分。
如何合理劃分系統(tǒng)的范圍是宏觀思考的范疇,如:一個需求應(yīng)該放入哪個系統(tǒng),多個需求是否是獨(dú)立組成的新系統(tǒng)等。
如何規(guī)范系統(tǒng)間的同步異步通訊方式?
系統(tǒng)增多,則需要考慮系統(tǒng)間的通信交互方式。通信有 RPC 或 RESTful 的同步訪問方式,也有通過消息中間件的異步訪問方式。
定義各種交互的規(guī)范,如:確定采用同步通信以及異步通信的標(biāo)準(zhǔn);確定采用明文、二進(jìn)制以及加密自定義序列化協(xié)議的場景。
分布式系統(tǒng)高可用以及伸縮性如何保障?
分布式系統(tǒng)和單機(jī)系統(tǒng)最大的區(qū)別在于分布式的不確定性,每次遠(yuǎn)程調(diào)用的請求是否到達(dá)難于保證。
單機(jī)系統(tǒng)宕機(jī),會導(dǎo)致整個系統(tǒng)不可用,但盡力去維護(hù)一個單一的系統(tǒng)難度并不大。而分布式系統(tǒng)出現(xiàn)最多的場景是一部分服務(wù)宕機(jī),其余的大部分服務(wù)仍然正常。
在系統(tǒng)很多的情況下,其排列組合的可能性是指數(shù)級上升的。如何能在這種情況下,保證系統(tǒng)的可用性以及伸縮性,是需要從宏觀點(diǎn)考慮的。如:是否需要有服務(wù)治理系統(tǒng),如何監(jiān)控,何時擴(kuò)容等。
如何考慮資源、調(diào)度、運(yùn)維、監(jiān)控一體化?
在容器、云計(jì)算發(fā)展的較為成熟的今天,基于 Mesos、K8S、Swarm 等平臺提供資源分配 +調(diào)度+部署的一體化平臺已不是難事。
比如,現(xiàn)在有一個由 2 臺 4 核服務(wù)器組成的8核小集群,運(yùn)行一個任務(wù)只占用 0.5 核 CPU,如果該任務(wù)占用整個一臺服務(wù)器,資源利用率是很低的,因此需要考慮資源的合理分配和調(diào)度。
一旦某臺服務(wù)器宕機(jī),應(yīng)將該服務(wù)器中運(yùn)行的任務(wù)分配到另一臺服務(wù)器中,這個過程應(yīng)盡量自動化。
以上簡單聊了一些技術(shù)人員隨著經(jīng)驗(yàn)和技能的增長發(fā)生的客觀變化。工作內(nèi)容會從僅關(guān)心業(yè)務(wù)功能轉(zhuǎn)變?yōu)橥瑫r關(guān)注非功能需求,思維方式也會經(jīng)歷從微觀到宏觀的大局觀演進(jìn)。
接下來聊一聊主觀方面的東西,從工匠精神開始談起。
工匠精神
工匠精神是什么?
借用日本劍道三個字——“守破離”。它對其他行業(yè)也有借鑒意義,對從事技術(shù)行業(yè)的同事來說,可以這樣解讀:
守——鉆研基礎(chǔ)知識、理解經(jīng)典理論、熟悉各種輪子
首先,應(yīng)充分了解技術(shù)的現(xiàn)狀?,F(xiàn)在的各種技術(shù)棧已經(jīng)趨于完善,應(yīng)該多了解、多體會、多學(xué)習(xí),多思考。
盡量多的理解經(jīng)典理論,比如,CAP 理論是在說明什么問題,BASE 的最終一致性該怎么做。
基于 PAXOS 和 ZAB 協(xié)議做的 ZooKeeper 適用于什么場景,Raft 和他們又有什么異同;ACID 的強(qiáng)事務(wù)又應(yīng)該用在何處等。
理解經(jīng)典理論的同時,再熟悉各種各樣的輪子。這時不應(yīng)急于考慮自己應(yīng)該重新做什么,如果沒有熟練的使用 Spring Framework,理解它的依賴注入和控制反轉(zhuǎn)理念,直接做一個超越它的框架又談何容易。
破——嘗試修改框架源碼,總結(jié)自己的最佳實(shí)踐
通過學(xué)習(xí)鉆研,已逐漸的形成自己的獨(dú)立知識體系。對一些技術(shù)通用性不強(qiáng),但行業(yè)通用性較強(qiáng)的問題,可以自己寫框架,或者改寫優(yōu)秀框架的源碼,吸收其精華,徹底轉(zhuǎn)化為自己的知識。
通過總結(jié)自己獨(dú)特的最佳實(shí)踐,慢慢的找到一條適合自己的道路,這不僅限于技術(shù),也包括管理、做事方式等方面。
離——拋開束縛,開辟新境界
這個境界很多人終其一生也很難達(dá)到。觸摸到這個境界之時,可以將一切的束縛都拋開,根據(jù)自己的經(jīng)驗(yàn)和能力,順勢而為的完成一些作品,獨(dú)立地創(chuàng)造一些東西,可以是技術(shù)產(chǎn)品,也可以是服務(wù),更可以是創(chuàng)業(yè)的公司。
概括來說:
- 守,剛到公司,熟悉自己的工作,積累經(jīng)驗(yàn)。
- 破,在團(tuán)隊(duì)中負(fù)責(zé)核心工作,根據(jù)自己的知識制定規(guī)范,領(lǐng)導(dǎo)他人。
- 離,可遇而不可求,創(chuàng)造更大的價(jià)值。
舉例來說, Linux、MySQL、Hadoop 這種級別產(chǎn)品所謂的神級人物,他們所做的不僅僅是一個產(chǎn)品,而是一個時代。
技術(shù)并不簡單,無論是深度還是廣度,都存在極大的縱深。想真正的成長為大牛,應(yīng)該要遵循工匠精神,產(chǎn)生足夠敬意,因?yàn)榻酉聛頃幸粭l很長的路要走。
成長必要條件
興趣
只有保持足夠的興趣才能在技術(shù)上走得更遠(yuǎn)。如果做技術(shù)無法體會快樂,完全是為了養(yǎng)家糊口而被迫走上這條路,相信很難在漫長的職業(yè)生涯中有足夠的動力持續(xù)成長。
世界很精彩,不喜歡做技術(shù)的人不一定非要做技術(shù),如果最終一定要轉(zhuǎn)行,越早就越能在新的行業(yè)中掌握主動權(quán)。
決心
對技術(shù)有興趣是先決條件,但并不是僅通過興趣,隨隨便便的學(xué)習(xí)和提高,就一定能成為技術(shù)大牛。當(dāng)然不排除有的人天賦較高,成為技術(shù)大牛的路徑會稍微輕松一點(diǎn)。
技術(shù)這個領(lǐng)域與變化相對少的領(lǐng)域不同,一年前的大牛,由于跟不上劇烈的技術(shù)變化而快速出局的可能性也是有的。因此想保持長期的競爭力,持續(xù)學(xué)習(xí)和提高決心是很重要的因素。
毅力
一旦下了決心就要持續(xù)的提高自己,這是一個長期積累的過程,需要有足夠的毅力堅(jiān)持。最終的一蹴而就,需要各方面的積累和融會貫通。
想成為大牛的一個先決條件,一定是有想成為大牛的強(qiáng)烈愿望。這個道理與不想當(dāng)將軍的士兵不是一個好的士兵是一樣的。
如果本人都沒愿望、沒信心、沒興趣,自己都不朝著這個目標(biāo)努力,他不太可能被動的被成長為一個大牛。
從“守破離”三點(diǎn)來看,被推動,即使平臺再優(yōu)秀,能走到“破”這一階段已經(jīng)是極限了,能走到“離”階段的人,是通過的興趣、決心和毅力主動達(dá)到的。
一些建議
這里特別澄清一下,我沒有任何傾向表達(dá)轉(zhuǎn)崗不好,任何崗位和行業(yè)都有其獨(dú)特的價(jià)值,行行出狀元,這里僅僅是對開發(fā)崗朋友的一些建議。
優(yōu)質(zhì)完成工作
畢竟工作還是很重要的,而且只有工作這個平臺,給人帶來的促進(jìn)和成長才是最大的。
不能因?yàn)橹粚兗夹g(shù)感興趣,而對工作中的業(yè)務(wù)完全沒興趣,就不盡力做,不用心思考,脫離業(yè)務(wù)的技術(shù)本身并不會產(chǎn)生價(jià)值。
保持對技術(shù)的熱情
有的朋友在接觸一個新技術(shù)一段時間之后,完全掌握了使用問題,雖然也可能吐槽某些方面用起來不順手,但并不深究其原理,也不動手改進(jìn),一直停留在使用階段,用它做做業(yè)務(wù),把工作完成。
這種類型的人如果繼續(xù)做技術(shù),未來難免會遇到瓶頸,從而失去自己的核心競爭力,盡早轉(zhuǎn)管理、業(yè)務(wù)或產(chǎn)品甚至測試都是可以的。
目前新概念層出不窮,當(dāng)前的熱點(diǎn)技術(shù)過段時間也許就不再流行,因此養(yǎng)成長期關(guān)注技術(shù)趨勢,保持敏感度也很重要。
完成一個基于興趣的作品
將一個作品當(dāng)做藝術(shù)品去做,不考慮排期、取舍,而是盡自己最大的努力,一點(diǎn)點(diǎn)的打磨,螺旋形的提升它的代碼和功能。
當(dāng)完成了一個與工作無關(guān),只因興趣打造的作品完成之后,一定能從中獲取很多經(jīng)驗(yàn),帶來很大成長。
維持開放的心態(tài)
無論自己的水平成長的有多高、多快,個人的精力有限,永遠(yuǎn)不可能了解和認(rèn)知所有的技術(shù)和知識。
因此仍舊需要隨時維持開放的心態(tài),多交流、溝通、學(xué)習(xí),充實(shí)自己。
開源、分享、回饋社區(qū)
做開源,讓其他工程師研究你寫的代碼,或在各種平臺分享自己的經(jīng)驗(yàn),以及積極的回饋社區(qū),包括回答問題,對開源產(chǎn)品提交 issue、提交 pr、撰寫文檔、編寫使用心得等。
做這些看似不能直接帶來收益的事情,經(jīng)過積累之后所獲取的收益不僅是能力提升,也會對技術(shù)影響力帶來提升,并且有更多的機(jī)會與更多的牛人交流。
成長的目標(biāo)
專業(yè)性的態(tài)度
以兩個技術(shù)問題聊聊專業(yè)性的態(tài)度:
框架是設(shè)計(jì)出來的還是演進(jìn)出來的?
這其實(shí)是一個開放性問題,不同習(xí)慣的人,他們的回答也許不一樣。我認(rèn)為優(yōu)秀的設(shè)計(jì)可以少走一些彎路,但一個長久不衰的框架,一定是經(jīng)過層層演進(jìn)而來。
如大家熟悉的 Spring Framework,已發(fā)展到了 Spring 5.X,Spring 1X 和 Spring 5.X 差別很大。
在其長期的演變過程中,層出不窮的出現(xiàn)了很多新技術(shù),它為了適配一步步的進(jìn)行演進(jìn),直至現(xiàn)在。
所以,需要一個專業(yè)性的態(tài)度,讓自己的產(chǎn)品可以持續(xù)演進(jìn)。
如何精煉一個模塊?
去觀察一個存在時間較長的活躍項(xiàng)目的提交記錄,代碼的增加和刪除行數(shù)基本成正比,有效的刪除無用代碼的重要程度和新功能開發(fā)相當(dāng)。
如果是觀察一個試水性質(zhì)的項(xiàng)目的提交記錄則另當(dāng)別論,基本上代碼只增不刪。因此,精煉一個模塊,要持續(xù)對它進(jìn)行修改和完善,它才能以螺旋型的方式去提升。
前瞻性的眼光
架構(gòu)是設(shè)計(jì)出來的還是演進(jìn)出來的?
如果剛才的問題是開放性的,那么這個問題并不能算是開放性的。我認(rèn)為好的架構(gòu)一定是設(shè)計(jì)出來而非演進(jìn)而來的。
如果架構(gòu)一開始并沒有設(shè)計(jì)的足夠好,而是隨著系統(tǒng)的演進(jìn),架構(gòu)也在與時俱進(jìn)的演進(jìn)。
那么架構(gòu)和業(yè)務(wù)的雙重修改所帶來的復(fù)雜性和不確定性是難以估量的,而且架構(gòu)所能提供的能力決定了業(yè)務(wù)代碼的上限。不具備前瞻性的架構(gòu)是失敗的作品。
設(shè)計(jì)一個架構(gòu),是在設(shè)計(jì)一個世界還是實(shí)現(xiàn)一個細(xì)節(jié)?
這個問題的答案顯而易見。所謂架構(gòu),最先出現(xiàn)于建筑學(xué),架構(gòu)相當(dāng)于一個房屋的梁與柱,用于 IT 行業(yè),架構(gòu)同樣相當(dāng)于一個系統(tǒng)的基礎(chǔ)設(shè)施。
因此設(shè)計(jì)一個架構(gòu),是大方向的規(guī)劃和演進(jìn)路徑的闡述,而非細(xì)節(jié)的實(shí)現(xiàn)和優(yōu)化。
顛覆一個架構(gòu)的損失會有多大?
不到萬不得已,企業(yè)不會輕易更換開發(fā)語言和數(shù)據(jù)庫。同樣,更換架構(gòu)也是實(shí)在撐不下去才為之。
因此大部分時間,工程師都是在一個已經(jīng)相對過時的架構(gòu)中開發(fā),那么架構(gòu)設(shè)計(jì)的是否有前瞻性,是否最大限度的靈活擁抱變化、滿足性能要求就更加重要。
系統(tǒng)性的思考
方案如何落地?
完成一個方案之后,讓其落地并不簡單,如何部署、運(yùn)維、調(diào)試、灰度升級、回滾都是需要考慮的范疇。這是一個整體落地的過程,一個整體思維上的閉環(huán)。
代碼提交了就是全部嗎?
剛才提到的方案落地話題比較大,換一個小一點(diǎn)的話題。技術(shù)人員主要以寫代碼為主,代碼提交只是工作的一部分,剩余的工作量還有很多。
比如怎么交接、文檔是否易懂、如何修復(fù) Bug 等一系列相關(guān)問題。同樣需要培養(yǎng)一個整體的、系統(tǒng)的思考能力。
心境轉(zhuǎn)換
在完成技術(shù)層面的提升外,還需要有心境上的轉(zhuǎn)換。主要包括責(zé)任心、自驅(qū)力和執(zhí)行力三個方面,它們應(yīng)隨著技術(shù)水平的提升而相應(yīng)的提升。
能力越強(qiáng),其責(zé)任必然越大,責(zé)任心與能力應(yīng)成正比,能力再高的人,若責(zé)任心不足,企業(yè)是無法將重大的事情交給他的。責(zé)任不僅僅在于做好自己的事情,也在于敢于承擔(dān)更多的挑戰(zhàn)和職責(zé)。
平穩(wěn)的度過職業(yè)生涯早期后,自驅(qū)力的重要性就更加顯露無疑。被別人推動去做事與主動的高要求的做事,能力成長的差距會愈加明顯。
今日事今日畢。雖然企業(yè)永遠(yuǎn)有做不完的事,但越盡早的完成一件事,才能盡早的投入另一件事。高效的執(zhí)行力與強(qiáng)大的自驅(qū)力相得益彰。
目標(biāo)與愿景
職業(yè)生涯早期看到的主要是工作愿景和個人愿景;公司愿景即在公司做更重要的事,更高的職位;個人愿景則是獲得更高的薪水,享受更好的生活。
社會愿景也可以稱之為行業(yè)愿景,它隨著閱歷的提高而逐漸展現(xiàn)。做開源,寫博客,參與分享甚至自己創(chuàng)業(yè),都會承擔(dān)更多的社會責(zé)任,也會更多的獲得業(yè)界認(rèn)可,能更加正向的勉勵自己不斷向前邁進(jìn)。
以社會愿景為最終目標(biāo),可以更有效的促進(jìn)工作愿景以及個人愿景的達(dá)成。
最后分享一些我做開源的經(jīng)驗(yàn):在開源的一兩年時間里,交流群和 Github 中被問到很多問題,提出很多質(zhì)疑,它們推動著我在開源的路上繼續(xù)前行。
在幫助別人的同時,吸取社區(qū)精華,完善自己的項(xiàng)目,感覺收獲遠(yuǎn)多于前幾年的積累。
張亮,當(dāng)當(dāng)架構(gòu)部總監(jiān),主要負(fù)責(zé)分布式中間件以及私有云平臺的搭建。致力于開源,目前主導(dǎo)兩個開源項(xiàng)目 elastic-job 和 sharding-jdbc。擅長以 Java 為主的分布式架構(gòu)和以 Mesos 為主的云平臺方向,推崇優(yōu)雅代碼,對如何寫出具有展現(xiàn)力的代碼有較多研究。