語言選型
出于公司發(fā)展、市場環(huán)境變化、產(chǎn)品迭代需要等原因,我們要做好語言的選擇,而語言本身沒有優(yōu)劣好壞之分,選擇哪種語言,完全看我們的環(huán)境是什么。通常選擇語言要從以下幾個(gè)點(diǎn)去考慮:
團(tuán)隊(duì)
語言選擇首先要考慮能不能找到這樣的團(tuán)隊(duì),也就是說要在合適的時(shí)間選擇一個(gè)合適的團(tuán)隊(duì),團(tuán)隊(duì)對(duì)某種語言的駕馭能力,將是你開始及發(fā)展壯大的一個(gè)很重要的因素。
成本
我們做項(xiàng)目的時(shí)候,時(shí)間、成本、質(zhì)量是考量的三個(gè)維度。用到架構(gòu)里,我們就要考慮所選擇的語言是不是在成本承受范圍里。另外,這個(gè)成本的考量要綜合,要考慮到人員培養(yǎng)的周期、學(xué)習(xí)的周期、團(tuán)隊(duì)配合的周期,以及人員流失帶來的人力成本。
控制
對(duì)選擇語言的控制力,包括團(tuán)隊(duì)領(lǐng)導(dǎo)對(duì)這種語言是否有理解和控制力,對(duì)其他成員學(xué)習(xí)這種語言的成本控制的力度,這些也都影響語言的選擇。
項(xiàng)目特點(diǎn)
根據(jù)不同的項(xiàng)目需求,最終選擇最適合這個(gè)項(xiàng)目的語言。在初期盡量保證語言的統(tǒng)一性,因?yàn)槿藛T可調(diào)配,建議初期不用過多考慮語言在處理某方面的優(yōu)勢。
技術(shù)健壯性
技術(shù)健壯性包括文檔安全、技術(shù)安全、文檔的健全程度、活躍度、成熟度、是不是能一直持續(xù)更新等。這些也都是我們選擇某一種語言技術(shù)的關(guān)鍵因素。所以要選擇某個(gè)語言,我們通常要考慮到今后是否持續(xù)更新,否則就和現(xiàn)在很多開源項(xiàng)目一樣逐漸銷聲匿跡。未來你再遇見問題的時(shí)候,可能只有自己去維護(hù),可自己能維護(hù)這個(gè)開源框架的話,錯(cuò)認(rèn)為還不如自己寫一套。
技術(shù)多樣性
語言的選擇的時(shí)候一定要考慮多樣性首先,語言多樣性有利于團(tuán)隊(duì)持續(xù)發(fā)展和穩(wěn)定,團(tuán)隊(duì)持續(xù)發(fā)展穩(wěn)定了,公司才能持續(xù)發(fā)展和穩(wěn)定;其次,語言多樣性能帶來更多的選擇,利于實(shí)現(xiàn)產(chǎn)品合作;最后,語言多樣性也是人才培養(yǎng)的一種方式,對(duì)整個(gè)行業(yè)有利。
當(dāng)然,這不是一成不變的,如果有可能的話,我們應(yīng)該保證語言的統(tǒng)一,這樣的話在初期的時(shí)候,我們的人員是可以標(biāo)配的,當(dāng)有小項(xiàng)目的時(shí)候,分出小組,可靈活組合。關(guān)鍵還是可控的。CTO要有這個(gè)意識(shí):通過團(tuán)隊(duì)去控制語言,而不是通過語言去控制團(tuán)隊(duì)。
學(xué)習(xí)成本
出于人員培養(yǎng)的周期、學(xué)習(xí)的周期、團(tuán)隊(duì)配合的周期、人才流失的周期等成本考慮,我覺得在團(tuán)隊(duì)的日常建設(shè)中最好能做到平穩(wěn)過渡,人員建設(shè)有梯度低層輸送學(xué)習(xí)進(jìn)取型人才中層輸送高輸出進(jìn)階型人才高層輸送管理業(yè)務(wù)骨干型人才這樣每個(gè)人發(fā)揮強(qiáng)項(xiàng),互相依賴、互相配合,而且可以逐級(jí)引導(dǎo)。
在培養(yǎng)團(tuán)隊(duì)的時(shí)候,CTO要注意高端輸出型人才培養(yǎng),這決定了團(tuán)隊(duì)在關(guān)鍵項(xiàng)目是否給力。對(duì)于 150 人到 200 人的團(tuán)隊(duì),理想狀態(tài)是中高端有大批的后備軍,而且有幾個(gè)人能夠帶領(lǐng)團(tuán)隊(duì)前行(一到兩個(gè)人就足夠了),這個(gè)團(tuán)隊(duì)就很穩(wěn)。
容器選型
我個(gè)人認(rèn)為,容器的選擇其實(shí)比語言的選擇要容易一些,主要是當(dāng)你選擇一個(gè)很好的容器,性能就會(huì)有一種很大的提升。這種選擇的背后其實(shí)就是成本、時(shí)間、質(zhì)量這三個(gè)緯度的PK.
例如,公司發(fā)展到一定規(guī)范的時(shí)候,質(zhì)量要求越來越高,然后對(duì)于時(shí)間的要求也越來越高,時(shí)間固定,質(zhì)量固定,唯一能做的是增加成本。你想想怎么加成本能搞定這個(gè)事,可以加班、加人手、也可以增加硬件成本。
未來某一天我們能否做到這一點(diǎn):投了很少的時(shí)間和成本、質(zhì)量卻挺高,這其實(shí)就是技術(shù)創(chuàng)新了,這時(shí)候我們就能解決發(fā)展的痛點(diǎn)。通過創(chuàng)新方式去創(chuàng)造奇跡,比馬跑得快的一定不是馬車,所以要換角度去重新思考痛點(diǎn)。
筆者認(rèn)為長遠(yuǎn)地看,好的架構(gòu)是改出來,短期地看,架構(gòu)是設(shè)計(jì)出來的。中長期來看架構(gòu)是邊設(shè)計(jì)邊改出來的。
架構(gòu)更多的是解決我們現(xiàn)有的痛點(diǎn),就跟創(chuàng)業(yè)一樣,我覺得做架構(gòu)就是在做技術(shù)創(chuàng)業(yè),架構(gòu)設(shè)計(jì)的非常好,我們真正的能用多少東西呢?用的東西并不是特別多,所以往往設(shè)計(jì)出來的東西屬于過度設(shè)計(jì),從而導(dǎo)致過度開發(fā),所以架構(gòu)上,設(shè)計(jì)的成分固然重要,但長遠(yuǎn)看,其實(shí)架構(gòu)是改出來的。
企業(yè)的發(fā)展是從無到有、從小到大的過程,而企業(yè)產(chǎn)品演化的方向同樣也是變化的,而且有時(shí)間和成本的限制,因此架構(gòu)在前期、中期、后期需要考慮的點(diǎn)都不一樣,前期要的是快和節(jié)約成本,盡快面市;中期用戶數(shù)長上來了,就要考慮安全性、擴(kuò)展性、穩(wěn)定性了。所以一個(gè)合格的架構(gòu)師,在我看來,應(yīng)當(dāng)因地制宜地選擇語言,選擇合適的容器和合適的架構(gòu),如果能夠把團(tuán)隊(duì)里的人員、技術(shù)、規(guī)劃、時(shí)間、成本、效率,還有幸福度等資源統(tǒng)一協(xié)調(diào)好,以實(shí)現(xiàn)工作目標(biāo),我覺得這才是一個(gè)合格的架構(gòu)師。這也是我為什么固執(zhí)地認(rèn)為架構(gòu)是一種文化,而不是單純的技術(shù)。
龐大的系統(tǒng)進(jìn)行解耦
解耦主要用的逆向思維,這一點(diǎn)和寫游戲外掛非常相似。那么,龐大的系統(tǒng)是如何進(jìn)行解耦的,解耦是否有規(guī)律可循,我個(gè)人的理解是要具體情況具體分析,但肯定是有規(guī)律可循的。
第一步,“抽象+分層”是對(duì)解決方案(代理模式)的整體把握,按照業(yè)務(wù)拆。舉例,有一個(gè)老系統(tǒng),它的軟件不開源,是什么我不知道,好在這個(gè)數(shù)據(jù)庫我能看得見,為了實(shí)現(xiàn)擴(kuò)展,我們做新系統(tǒng)要實(shí)現(xiàn)二者的交互,就要加一個(gè)抽象的代理層,相當(dāng)于在這個(gè)系統(tǒng)之外再做一個(gè)系統(tǒng),相當(dāng)于外掛。
第二步,在模塊內(nèi),熟悉系統(tǒng),研究數(shù)據(jù)流。用逆向工程模擬交互接口,一步步拆分。就像我們做一個(gè)項(xiàng)目,應(yīng)該是把一個(gè)項(xiàng)目需求全部細(xì)分成可持續(xù)的共同點(diǎn),對(duì)于這個(gè)共同點(diǎn)進(jìn)行技術(shù)評(píng)估,評(píng)估完以后進(jìn)行排期。同樣的原理,我們對(duì)原有的一個(gè)系統(tǒng)進(jìn)行分析,分析完以后,你能逆向出數(shù)據(jù)表結(jié)構(gòu)最好,好在成型的系統(tǒng)如果文檔不全,命名至少是拼音加英文。
第三步,按照功能和數(shù)據(jù)流向逐一替代,前期設(shè)計(jì)與數(shù)據(jù)同步,數(shù)據(jù)問題需要寫外掛去處理。思路和游戲外掛一樣的,就是要用大量的逆向工程把系統(tǒng)全部拆出來。
第四步,對(duì)數(shù)據(jù)進(jìn)行收集,用數(shù)學(xué)歸納法,要注意的是切分過程一定會(huì)有臟數(shù)據(jù)。針對(duì)臟數(shù)據(jù),收集bug.數(shù)學(xué)歸納法窮舉問題,分析在每一個(gè)流向的時(shí)候呈現(xiàn)什么問題,然后有什么樣的問題導(dǎo)致這樣的情況,然后對(duì)它進(jìn)行修復(fù)。
第五步,最后打破現(xiàn)在方案,根據(jù)對(duì)現(xiàn)有業(yè)務(wù)的需求,重新設(shè)計(jì)(按照業(yè)務(wù)需要設(shè)計(jì),并非技術(shù)架構(gòu))。
接下來,我們用電商業(yè)務(wù)流程和架構(gòu)舉例。
主流電商業(yè)務(wù)流程
在主流電商平臺(tái)中,若需精細(xì)化管理各個(gè)業(yè)務(wù)流程,一般會(huì)涉及上百個(gè)子系統(tǒng),系統(tǒng)之間的交互接口更是不計(jì)其數(shù)。任何系統(tǒng)環(huán)節(jié)出現(xiàn)問題,都會(huì)對(duì)業(yè)務(wù)帶來或多或少的影響。
這里幾個(gè)大的模塊,有基礎(chǔ)數(shù)據(jù)的建檔,包括采購入庫、退貨供應(yīng)商、電商退換貨、電商出庫這些東西都是以前軟件里的,把它拆分出來,拆出來以后再進(jìn)行統(tǒng)一布局和升級(jí)。發(fā)現(xiàn)有的部分拆出來了,還有一部分系統(tǒng)還沒有拆出來,但我們都繪制出來,就是說,如果要想對(duì)一個(gè)系統(tǒng)拆分的話,必須得把這個(gè)系統(tǒng)所有的業(yè)務(wù)模型全部都繪制出來,數(shù)據(jù)流向全部要摸清楚,你才可以一步一步地去替換。
企業(yè)的系統(tǒng)流程
從上圖中可以看出,在實(shí)際的應(yīng)用中,會(huì)規(guī)劃出所有的模塊,包括具體的功能,最后就和玩卡牌游戲一樣,一個(gè)一個(gè)的重構(gòu),替換,或者重新開發(fā)。最終把整個(gè)系統(tǒng)編織出來。
設(shè)計(jì)的理念
假定給我一個(gè)命題,在半個(gè)小時(shí)內(nèi)教會(huì)一些實(shí)習(xí)生采用 JavaScript 語言進(jìn)行目前的一些項(xiàng)目的開發(fā),他們的能力只限于一些常規(guī)的基礎(chǔ)知識(shí),沒有真正做過項(xiàng)目。
如果按照常規(guī)的方式,我只能說我沒有辦法,因?yàn)槭芟匏麄兊睦斫猓€有我對(duì)質(zhì)量的要求,還有就是他們很多人根本沒辦法上手,如果一點(diǎn)點(diǎn)教,時(shí)間半個(gè)小時(shí)肯定不夠。但是命題就是如此,我應(yīng)該怎么才能做到呢?這里除了用創(chuàng)新的方式,別無它法。
這里我想引出一種技術(shù)框架,這種叫約定式開發(fā)。我們?cè)趺茨軌蜃尣惶珪?huì)寫 JavaScript 的人,會(huì)寫 JavaScript,并且寫的好呢?
這時(shí)我們要有個(gè)理念,配置優(yōu)于編碼,也就是讓一個(gè)不太會(huì)寫代碼的人,通過這種配置的方式可以讓引擎自動(dòng)去生成代碼。
試想編寫完整規(guī)范的模塊,并且書寫風(fēng)格優(yōu)良簡單,問題是我們?nèi)绾伟阉鼈鹘o別人,并且保持一致?如果我編寫一個(gè)公用模塊給大家用,編寫規(guī)則引擎,別人只需要按照規(guī)則引擎的要求去寫一些簡單的配置,具體的實(shí)現(xiàn)代碼是引擎自動(dòng)生成的。這個(gè)時(shí)候,我們可以認(rèn)為代碼是自己生成的,我們只負(fù)責(zé)配置。
但是問題來了,配置文件越來越多,要讓不太會(huì)寫的人也能寫出來,雖然降低了編碼學(xué)習(xí)成本,但是至少還要學(xué)習(xí)寫配置文件。這里筆者認(rèn)為,少寫代碼可以減少復(fù)雜度,約定式開發(fā)就是一種很好的方式,配置優(yōu)于編碼,但是比配置更極致的方式是約定。這樣我們就可以大量減少配置文件。
懂點(diǎn)原理,會(huì)用鼠標(biāo),我認(rèn)為就可以去編程,這是我認(rèn)為的一種設(shè)計(jì)理念,也是一種架構(gòu)思維,這種架構(gòu)思維叫約定式開發(fā),現(xiàn)在有很多前端技術(shù),里面都有這樣的一種設(shè)計(jì)思想。也許未來我們的生活,編程是人們的標(biāo)配,就像司機(jī)這個(gè)職業(yè),現(xiàn)在人人基本上都可以開車。也許未來我們能夠通過說話,就在下達(dá)計(jì)算機(jī)指令,會(huì)有代理機(jī)器人對(duì)我們的指令進(jìn)行分析,通過我們的話語進(jìn)行編碼。