對(duì)于一名熱愛技術(shù)的工程師來(lái)說(shuō),很容易出現(xiàn)非常熱衷于使用新技術(shù)的情況,記得有一次和一位做平臺(tái)應(yīng)用的同事閑聊,他問我最近在搞什么,我說(shuō)在研究 Hadoop,正在用 MapReduce 處理海量圖片的智能分析,他一臉羨慕:“能搞新技術(shù),真好!”。
作為一名工程師,我可以理解大家的心情,我們都是熱愛嘗試新技術(shù)、拋棄過時(shí)技術(shù)的人。但是首先得明確,到底技術(shù)是不是過時(shí)的,還是僅僅是你認(rèn)為它過時(shí)了。這篇文章我想談?wù)勎覍?duì)技術(shù)選型的理解。
這篇文章不僅僅是寫給工程師,更多是寫給技術(shù)團(tuán)隊(duì)負(fù)責(zé)人(大多數(shù)也是從工程師升職上去的,起初思維和工程師差距不大),因?yàn)槟銈兙唧w負(fù)責(zé)技術(shù)選型的方向、方法、過程、結(jié)論明確。
先來(lái)看看軟件開發(fā)領(lǐng)域的變化,變化實(shí)在是太快了。在 JavaScript 里,幾乎每天都有新框架誕生。Node.js(關(guān)鍵詞:事件編程),React 編程,Meteor.js(關(guān)鍵詞:共享狀態(tài)),前端 MVC,React.js…… 你可以隨便舉例。軟件工程領(lǐng)域里新概念也層出不窮:領(lǐng)域驅(qū)動(dòng)開發(fā),六邊形架構(gòu)理論,DCI 架構(gòu)(數(shù)據(jù) - 場(chǎng)景 - 交互)。
洛克希德·馬丁公司的著名飛機(jī)設(shè)計(jì)師凱利·約翰遜所提出的 KISS 原則,指出架構(gòu)設(shè)計(jì)能簡(jiǎn)單絕不復(fù)雜,堅(jiān)決砍掉任何華而不實(shí)的設(shè)計(jì),不要因?yàn)?3 年后可能怎樣甚至是一些現(xiàn)實(shí)中根本無(wú)法出現(xiàn)的場(chǎng)景,加入到當(dāng)下的架構(gòu)設(shè)計(jì)中,導(dǎo)致系統(tǒng)無(wú)比復(fù)雜。有時(shí)候看似引入的是一個(gè)很簡(jiǎn)單很容易解決的問題,可能在具體的執(zhí)行過程中帶來(lái)一系列不必要的麻煩。技術(shù)選型其實(shí)遇到的問題和系統(tǒng)架構(gòu)設(shè)計(jì)類似,也容易出現(xiàn)人為因素導(dǎo)致的偏差,進(jìn)而出現(xiàn)和系統(tǒng)架構(gòu)過度設(shè)計(jì)類似的麻煩。
對(duì)于技術(shù)選型,有以下幾個(gè)建議:
記得看過一篇文章,里面提到一個(gè)新項(xiàng)目最好不要使用超過 30% 的新技術(shù),我覺得這有一定道理,因?yàn)閷?duì)于你完全不知道的技術(shù),你不可能控制使用過程中出現(xiàn)的風(fēng)險(xiǎn)。我在技術(shù)管理中的向下管理里提起過,任何一位技術(shù) Leader,如果你不能得到下屬的技術(shù)尊重,你必將受到懲罰。
也不能說(shuō)完全不能使用新技術(shù),前幾天和朋友聊天,他提到了另外一位總監(jiān)下屬有幾個(gè)人轉(zhuǎn)崗了,都是技術(shù)牛人,最主要的原因是這位總監(jiān)堅(jiān)決排斥新技術(shù),堅(jiān)持自己熟悉 的十年前的框架和編寫代碼規(guī)范。他對(duì)于一個(gè)新技術(shù)的天然不信任,在技術(shù)接受程度還不夠高,并且認(rèn)為公司內(nèi)沒有人能吃透這個(gè)技術(shù)的情況下,不愿意讓自己的業(yè)務(wù)做第一個(gè)吃螃蟹的人,這種做法不能說(shuō)完全錯(cuò)誤,至少對(duì)于他自己來(lái)說(shuō)很穩(wěn)健,但是卻壓制了一些有追求人的內(nèi)心。
謹(jǐn)慎是個(gè)美德,不過如果在一個(gè)非常追求速度的業(yè)務(wù)里,這可能也意味著過于保守,會(huì)延誤時(shí)機(jī)。
那我們應(yīng)該怎樣做到選擇技術(shù)呢?我認(rèn)為,在選擇技術(shù)時(shí)有兩個(gè)大原則。第一,要取其長(zhǎng)避其短;第二,要關(guān)注技術(shù)的發(fā)展前景。每種技術(shù)都是有它特定的適用場(chǎng)景,開發(fā)者經(jīng)常犯的錯(cuò)誤就是盲目追新,當(dāng)一個(gè)新語(yǔ)言、框架、工具出現(xiàn)后,特別是開發(fā)者自己學(xué)會(huì)了這種新技術(shù)后,就會(huì)有種“拿著錘子找釘子”的感覺,將新技術(shù)濫用于各種項(xiàng)目。
記住,技術(shù)選型是穩(wěn)定壓倒一切。
沒有人喜歡“alone in the dark”的感覺,同樣,也很少有工程師喜歡孤獨(dú)地面對(duì)代碼缺陷。我們之所以喜歡在 Apache 上挑選合適的新框架嘗試使用,是因?yàn)?Apache 始終保持運(yùn)作著強(qiáng)大的社區(qū),每天都有很多新建的框架,也設(shè)計(jì)了一整套生命周期管理標(biāo)準(zhǔn),讓一個(gè)項(xiàng)目能夠從孵化項(xiàng)目逐漸一步步地走向頂級(jí)項(xiàng)目。除了像 Apache 這樣的社區(qū),我們也可以評(píng)估是否存在一些商業(yè)公司提供針對(duì)該技術(shù)或者框架的有償支撐,一般來(lái)說(shuō),有公司愿意圍繞該技術(shù)布局,也能說(shuō)明確實(shí)存在使用空間。例如 Apache Cassandra,目前就有 Datastax 和 LastPickle 兩家公司對(duì)它提供技術(shù)指導(dǎo)和有償輔助軟件支撐。
其實(shí)看一項(xiàng)技術(shù)活不活躍,只要去 StackOverflow 這樣的網(wǎng)站看看提問的人多不多就知道了。
選擇一個(gè)技術(shù)的最低標(biāo)準(zhǔn)是,技術(shù)的生命周期必須顯著長(zhǎng)于項(xiàng)目的生命周期。
為什么需要確保所選擇的技術(shù)不斷前進(jìn)?因?yàn)檫@個(gè)世界是發(fā)展的,科技發(fā)展更是非常得快速,你可以看看,所有的成功的科技公司都是因?yàn)榕茉诹藙e人前面,而不是慢悠悠的工作態(tài)度,這就是科技界的殘酷,也正是為什么 FaceBook 辦公室里貼著:“要么做到最好,要么死亡”。
技術(shù)的前進(jìn)不僅僅取決于它本身,而是和大環(huán)境發(fā)展、上下游用戶也密切相關(guān)。比如 AI,60 年代其實(shí)就已經(jīng)提出了相應(yīng)概念,為什么直到今年才進(jìn)入發(fā)展元年?因?yàn)樾酒挠?jì)算效率、數(shù)據(jù)樣本規(guī)模沒有達(dá)到要求。而 Functional Language 為什么這么多年一直默默無(wú)聞,而從前幾年開始逐漸盛行?因?yàn)闄C(jī)器學(xué)習(xí)來(lái)了,AI 來(lái)了,它們有了用武之地。
總的來(lái)說(shuō),你需要使用你所選擇的軟件技術(shù),快速地實(shí)現(xiàn)應(yīng)用程序的構(gòu)建。記住一句話:好的技術(shù)棧永遠(yuǎn)跑在用戶需求前面。
技術(shù)選型必須貼著業(yè)務(wù)來(lái)選擇,不同業(yè)務(wù)階段會(huì)有不同的選型方式。處于初創(chuàng)期的業(yè)務(wù),選型的基準(zhǔn)是靈活。只要一個(gè)技術(shù)夠用并且開發(fā)效率足夠高,那么就可以選擇它。初創(chuàng)的業(yè)務(wù)往往帶有風(fēng)險(xiǎn)性和不確定性,朝令夕改、反復(fù)試錯(cuò)是常態(tài),技術(shù)必須適應(yīng)業(yè)務(wù)的節(jié)奏,然后才是其他方面。等業(yè)務(wù)進(jìn)入穩(wěn)定期,選型的基準(zhǔn)是可靠。技術(shù)始終是業(yè)務(wù)的基石,當(dāng)業(yè)務(wù)穩(wěn)定了技術(shù)不穩(wěn),那就會(huì)成為業(yè)務(wù)的一塊短板,就必須要修正。當(dāng)業(yè)務(wù)進(jìn)入維護(hù)期,選型的基準(zhǔn)是妥協(xié)。代碼永遠(yuǎn)有變亂的趨勢(shì),一般經(jīng)過一兩年就有必要對(duì)代碼來(lái)一次大一點(diǎn)的重構(gòu)。在這種時(shí)候,必須得正視各種遺留代碼的遷移成本,如果改變技術(shù)選型會(huì)帶來(lái)遺留代碼重寫,這背后帶來(lái)的代價(jià)業(yè)務(wù)無(wú)法承受,那么我們就不得不考慮在現(xiàn)有技術(shù)選型之上做一些小修小補(bǔ)或者螺旋式上升的重構(gòu)。
正因?yàn)榧夹g(shù)選型和業(yè)務(wù)相關(guān),我們能夠觀察到一些很明顯的現(xiàn)象:新技術(shù)往往被早期創(chuàng)業(yè)團(tuán)隊(duì)或大公司的新興業(yè)務(wù)使用;中大型公司的核心業(yè)務(wù)則更傾向于用一些穩(wěn)定了幾年的技術(shù);一個(gè)公司如果長(zhǎng)期使用一種技術(shù),就會(huì)傾向于一直使用下去,甚至連版本都不更新的使用下去。這現(xiàn)象背后都是有道理的。
回到我們的主題,學(xué)會(huì)從業(yè)務(wù)端思考。首先我們需要充分地理解業(yè)務(wù),理解用戶需求,理解當(dāng)下需要解決的首要問題,以及可能的風(fēng)險(xiǎn)有哪些,再將目標(biāo)進(jìn)行分解,進(jìn)行具體的技術(shù)選型、模型設(shè)計(jì)、架構(gòu)設(shè)計(jì)。
舉個(gè)例子。假設(shè)我們需要解決的核心問題是并發(fā),則可以通過各種緩存手段(本地緩存、分布式緩存),來(lái)提高查詢的吞吐,這樣雖然會(huì)一定程度上需要在數(shù)據(jù)一致性上做出犧牲,由強(qiáng)一致性變?yōu)樽罱K一致性。
但是,如果數(shù)據(jù)一致性不是核心需要解決的問題,那么,此問題的優(yōu)先級(jí)則可以先放一放,反過來(lái)如果核心問題變?yōu)閿?shù)據(jù)的一致性,如交易系統(tǒng),那么再怎么強(qiáng)調(diào)數(shù)據(jù)的一致性都不為過,由于分布式環(huán)境下為了應(yīng)對(duì)高并發(fā)的寫入以及海量數(shù)據(jù)的存儲(chǔ),通常需要對(duì)關(guān)系型數(shù)據(jù)庫(kù)進(jìn)行分庫(kù)分表擴(kuò)展,這也給數(shù)據(jù)一致性帶來(lái)了很大的挑戰(zhàn),原本的單庫(kù)事務(wù)的強(qiáng)一致性保障,在這個(gè)時(shí)候升級(jí)為跨庫(kù)的分布式事務(wù),而通過二階段或者三階段提交所保障的分布式事務(wù),由于分布式事務(wù)管理器與資源管理器之間的多次網(wǎng)絡(luò)通信成本,吞吐及效率上很難滿足高并發(fā)場(chǎng)景下的要求,而這實(shí)際上對(duì)于交易系統(tǒng)來(lái)說(shuō),又是一個(gè)很難回避的問題。
因此,大家又想出很多的招來(lái)解決這個(gè)問題,通過可靠消息系統(tǒng)來(lái)保障不失為一種方式,變同步為異步,但是,又引入新的問題,消息系統(tǒng)為保證不丟消息,則很難保證消息的順序性以及是否重復(fù)投遞,這樣作為消息的接收方,則需要保障消息處理的冪等性,以及對(duì)消息去重。
對(duì)于未經(jīng)驗(yàn)證的新技術(shù)、新理念的引入一定要慎重,一定要在全方位的驗(yàn)證過后,再大規(guī)模的使用。新技術(shù)、新理念的出現(xiàn),自然有它的誘惑,慎重并不代表保守,技術(shù)總是在不斷前進(jìn),擁抱變化本身沒有問題,但是引入不成熟的技術(shù)看似能帶來(lái)短期的收益,但是它的風(fēng)險(xiǎn)或者是后期的成本可能遠(yuǎn)遠(yuǎn)大于收益。
技術(shù)選型是個(gè)很需要經(jīng)驗(yàn)的活,得有大量的信息積累和輸入,再根據(jù)具體現(xiàn)實(shí)情況輸出一個(gè)結(jié)果。我們?cè)谶x型的時(shí)候最忌諱的是臨時(shí)抱佛腳、用網(wǎng)上收集一些碎片知識(shí)來(lái)決策,這是非常危險(xiǎn)的,我們得確保自己所有思考都是基于以前的事實(shí),還要弄清楚這些事實(shí)背后的假設(shè),這都需要讓知識(shí)內(nèi)化形成經(jīng)驗(yàn)。
經(jīng)驗(yàn)的本質(zhì)是什么,有什么方法能夠確定自己的經(jīng)驗(yàn)增長(zhǎng)了,而不是不斷在重復(fù)一些很熟悉的東西。我現(xiàn)在的結(jié)論是,經(jīng)驗(yàn)等于知識(shí)索引的完備程度。
我們一生中會(huì)積累很多的知識(shí),如果把我們的大腦比作數(shù)據(jù)庫(kù)的話,那我們一定有一部分腦存儲(chǔ)貢獻(xiàn)給了內(nèi)容的索引,它能幫助我們將關(guān)聯(lián)知識(shí)更快的取出來(lái),并且輔助決策。經(jīng)驗(yàn)增長(zhǎng)等同于我們知識(shí)索引的增長(zhǎng),意味著我們能輕易的調(diào)動(dòng)更多的關(guān)聯(lián)知識(shí)來(lái)做更全面的決策。
要想建立好這個(gè)知識(shí)索引,我們得保持技術(shù)敏感性和廣度,也就是要做到持續(xù)的信息輸入、內(nèi)化,并發(fā)現(xiàn)信息之間的關(guān)聯(lián)性,建立索引,記下來(lái)。說(shuō)起來(lái)容易,做起來(lái)還是挺有難度的。
首先難在信息輸入量大,忘記了怎么辦。我們的大腦不是磁盤,不常用的知識(shí)就會(huì)忘記,忘記了就跟沒看過是一回事。我的經(jīng)驗(yàn)是一定要對(duì)知識(shí)進(jìn)行壓縮,記住的是最關(guān)鍵的細(xì)節(jié),并且反復(fù)的去回味這個(gè)細(xì)節(jié)。
去年我做了一次對(duì)于分布式數(shù)據(jù)庫(kù)的選型工作。我們?yōu)槭裁匆鲞@次選型?因?yàn)榇嬖诿鞔_的需求,我們需要解決大規(guī)模高并發(fā)數(shù)據(jù)存儲(chǔ),單次數(shù)據(jù)不大,但是存儲(chǔ)頻率、讀取頻率都很高,并且要確保不丟失數(shù)據(jù),這樣的需求對(duì)于關(guān)系型數(shù)據(jù)庫(kù)來(lái)說(shuō),出現(xiàn)了性能瓶頸。
我對(duì)于技術(shù)選型有自己的一套方法論,我知道,我不可能什么技術(shù)都懂,所以我會(huì)按照自己的這套方法論來(lái)具體執(zhí)行,避免出現(xiàn)選型誤差。我的步驟是:“列出需求”-“細(xì)分需求”-“明確搜索方向”-“網(wǎng)絡(luò)搜索”-“明確評(píng)判標(biāo)準(zhǔn)”-“分頭執(zhí)行”-“匯總材料”-“初步選擇”-“進(jìn)一步調(diào)研”-“會(huì)議評(píng)審”-“做出決定”。這些步驟太多,需求我已經(jīng)介紹了,這里具體再講講我這一次是如何進(jìn)入下一步選型的,也就是“初步選擇”-“進(jìn)一步調(diào)研”之間的過程。
我通過網(wǎng)絡(luò)搜索(進(jìn)入 Google,搜索 Distributed Database、NoSQL Database 等關(guān)鍵詞),我找到了如下這些國(guó)內(nèi)外專家推薦的分布式數(shù)據(jù)庫(kù),他們的基本描述如下所示:
HyperTable: 一個(gè)開源、高性能、可伸縮的數(shù)據(jù)庫(kù),它采用與 Google 的 BigTable 相似的模型。該數(shù)據(jù)庫(kù)數(shù)據(jù)按主鍵在物理上排序,適用于數(shù)據(jù)分析領(lǐng)域,采用 C++ 編寫,可以運(yùn)行在 HDFS 上面。該數(shù)據(jù)庫(kù)受到 GPLV3 協(xié)議約束,考慮到它和 HBase 從系統(tǒng)架構(gòu)上來(lái)說(shuō)很相似,但是協(xié)議約束較多,所以放棄調(diào)研,轉(zhuǎn)而調(diào)研 HBase。
HBase: 即 Hadoop Database,是一個(gè)高可靠性、高性能、面向列、可伸縮的分布式存儲(chǔ)系統(tǒng),采用主 / 從架構(gòu)設(shè)計(jì),利用 HBase 技術(shù)可在廉價(jià) PC Server 上搭建起大規(guī)模結(jié)構(gòu)化存儲(chǔ)集群。它是 Google BigTable 的開源實(shí)現(xiàn)。
VoltDB: 一個(gè)內(nèi)存數(shù)據(jù)庫(kù),提供了 NoSQL 數(shù)據(jù)庫(kù)的可伸縮性和傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)的 ACID 一致性,支持單節(jié)點(diǎn) 53000TPS/s。該數(shù)據(jù)庫(kù)受到 GPLV3 協(xié)議約束。VoltDB 有兩個(gè)版本,一個(gè)開源社區(qū)版本和一個(gè)付費(fèi)企業(yè)版本。付費(fèi)企業(yè)版本除包含了所有開源社區(qū)版的功能,還有些其他特點(diǎn),諸如計(jì)算機(jī)集群管理控制臺(tái)、系統(tǒng)性能儀表盤、數(shù)據(jù)庫(kù)宕機(jī)恢復(fù)、在線數(shù)據(jù)庫(kù) Schema 修改、在線數(shù)據(jù)庫(kù)節(jié)點(diǎn)重新加入、JDBC 和 OLAP 導(dǎo)出支持、命令日志。
由于該框架開源社區(qū)不活躍,主導(dǎo)者更加希望使用付費(fèi)版本,所以決定放棄它,轉(zhuǎn)而調(diào)研類似的 Redis。
CloudData: 一個(gè)結(jié)構(gòu)化數(shù)據(jù)庫(kù),沒有中文資料,從系統(tǒng)架構(gòu)、功能上分析,類似于 MongoDB。
Gridool: 一種基于 MapReduce 原理設(shè)計(jì)的網(wǎng)格計(jì)算引擎,不支持?jǐn)?shù)據(jù)存儲(chǔ),所以放棄。
Ddb-query-optimizer: 找不到資料,放棄。
Cages: 基于 ZooKeeper 實(shí)現(xiàn)數(shù)據(jù)協(xié)調(diào) / 同步,不僅能性數(shù)據(jù)分布式存儲(chǔ),放棄。
Redis: 一個(gè)開源的基于鍵值對(duì)和存儲(chǔ)系統(tǒng),具備高性能特征。支持主從復(fù)制(master-slave replication),并且具有非??焖俚姆亲枞紫韧剑╪on-blockingfirst synchronization)、網(wǎng)絡(luò)斷開自動(dòng)重連等功能。同時(shí) Redis 還具有其他一些特征,其中包括簡(jiǎn)單的 check-and-set 機(jī)制、pub/sub 和配置設(shè)置等,以便使得 Redis 能夠表現(xiàn)得更像緩存(Cace)。絕大部分主流編程語(yǔ)言都有官方推薦的客戶端。
MongoDB: 一個(gè)開源的 C++ 編寫的面向集合且模式自由的文檔性數(shù)據(jù)庫(kù),是 NoSQL 中功能最豐富、最像關(guān)系型數(shù)據(jù)庫(kù)的產(chǎn)品。
核心優(yōu)勢(shì):靈活文檔模型 + 高可用復(fù)制集 + 可擴(kuò)展分片集群;
功能特點(diǎn):二級(jí)索引、地理位置索引、aggregate、map-reduce、OridFS 支持文件存儲(chǔ)。
不足之處:不支持事務(wù),僅支持簡(jiǎn)單 left join。
Spanner:Google 的可擴(kuò)展的、多版本的、全球分布式的同步復(fù)制方式數(shù)據(jù)庫(kù)。Spanner 是第一個(gè)支持全球規(guī)模的分布式數(shù)據(jù)、外部一致性分布式事務(wù)的分布式數(shù)據(jù)庫(kù)。它是一個(gè)在遍布全球范圍的數(shù)據(jù)中心內(nèi)部通過多套 Paxos 狀態(tài)機(jī)器共享數(shù)據(jù)的數(shù)據(jù)庫(kù)。復(fù)制被用于全局可用性和地理位置;客戶在副本之間自動(dòng)切換。當(dāng)數(shù)據(jù)量或者服務(wù)器數(shù)量發(fā)生變化時(shí),Spanner 在機(jī)器之間自動(dòng)共享數(shù)據(jù),并且 Spanner 在機(jī)器之間自動(dòng)遷移數(shù)據(jù)(甚至在數(shù)據(jù)中心之間),用以負(fù)載均衡和響應(yīng)失敗。Spanner 被設(shè)計(jì)為在幾百萬(wàn)臺(tái)機(jī)器之上橫向擴(kuò)展,這些擴(kuò)展穿過了數(shù)百個(gè)數(shù)據(jù)中心和萬(wàn)億行數(shù)據(jù)。功能很強(qiáng)大,可惜沒有開源。
ElasticSearch: 一個(gè)基于 Lucene 的搜索服務(wù)器。它提供了一個(gè)分布式多用戶能力的全文搜索引擎,基于 Restful Web 接口。ElasticSearch 是用 Java 開發(fā)的,并作為 Apache 許可條款下的開放源碼發(fā)布,是當(dāng)前流行的企業(yè)級(jí)搜索引擎。
最終通過這些技術(shù)之間的互相相似度對(duì)比,并且我們?cè)O(shè)定了一些規(guī)則,例如開源協(xié)議的約束,這一點(diǎn)其實(shí)逐漸開始真正起到約束了,看看 FaceBook 針對(duì) Reactor 的專利約束給大家造成的麻煩,你就懂了。最終,我選擇了 Cassandra、MongoDB、Reddis、MySQL、HBase 等幾款進(jìn)入下一步深入調(diào)研。
我們進(jìn)行技術(shù)選型,有的團(tuán)隊(duì)會(huì)根據(jù)社交媒體上的討論來(lái)決定選擇哪種架構(gòu),有的團(tuán)隊(duì)會(huì)跟風(fēng)走,哪個(gè)熱門就選哪個(gè),這些都不是正確的方式,我們應(yīng)該按照方法論執(zhí)行。此外,我們作為團(tuán)隊(duì)管理者,一邊要督促自己不斷學(xué)習(xí)新技術(shù),自己能夠上手使用,也要結(jié)合實(shí)際團(tuán)隊(duì)情況,規(guī)劃新技術(shù)的預(yù)研、落地步驟,讓團(tuán)隊(duì)成員既能享受到穩(wěn)定技術(shù)的紅利,也能不斷地嘗試新事物,讓大家能夠看到未來(lái),不擔(dān)心自己逐漸落后于行業(yè)的發(fā)展,更能提升對(duì)于公司的歸屬感。做到這些,真不容易,加油,諸位。
倒計(jì)時(shí),1 天!
周明耀,2004 年畢業(yè)于浙江大學(xué),工學(xué)碩士。13 年軟件研發(fā)經(jīng)驗(yàn),近 10 年技術(shù)團(tuán)隊(duì)管理經(jīng)驗(yàn),4 年分布式計(jì)算、大數(shù)據(jù)技術(shù)經(jīng)驗(yàn)。出版書籍包括《大話 Java 性能優(yōu)化》、《深入理解 JVM&G1 GC》、《技術(shù)領(lǐng)導(dǎo)力 - 碼農(nóng)如何才能帶團(tuán)隊(duì)》。個(gè)人微信號(hào) michael_tec,個(gè)人公眾號(hào)“麥克叔叔每晚 10 點(diǎn)說(shuō)”。 點(diǎn)擊下方圖片即可閱讀 為什么 Python 發(fā)展得如此之快? 作者介紹
今日薦文
聯(lián)系客服