同樣是擰螺絲,小公司和大公司的區(qū)別在哪?
上一個(gè)星期一直忙于救火,但是這個(gè)星期的緊張、忙碌以及焦慮,讓我想明白了一些事情,寫(xiě)了本文,只是一些絮絮叨叨。
圖片來(lái)自 Pexels
本文將從以下幾個(gè)部分展開(kāi):
- 小微/外包企業(yè)前端的困境
- 中臺(tái)的概念
- 前后端分離再分離
- 極簡(jiǎn)的技術(shù)棧
- 避免“單點(diǎn)故障”
- 集體利益大于個(gè)人利益
- 談?wù)剛€(gè)人的發(fā)展: 跳槽與跳槽路上
- 總結(jié)
小微/外包企業(yè)前端的困境
相信待在大廠的頭部程序員只是少數(shù),大部分前端還是蝸居在小微企業(yè)前端團(tuán)隊(duì)(特指工程能力較弱的團(tuán)隊(duì),排除大廠和大牛創(chuàng)業(yè)公司),望著大廠的圍墻。
想象他們光鮮亮麗、充滿(mǎn)激情樣子。同樣是擰螺絲,同樣實(shí)踐著前端工程化、同樣用著 Vue、React 全家桶,別人搞的是航母上的鉚釘,你擰的是奧迪雙鉆的螺絲。
大廠談高大上技術(shù)、談架構(gòu),談場(chǎng)景。小微企業(yè)前端談溫飽,我們或多或少面臨這些困境:
①邊緣化
在這類(lèi)公司,前端沒(méi)什么話語(yǔ)權(quán),他們只是一個(gè)簡(jiǎn)單頁(yè)面實(shí)現(xiàn),簡(jiǎn)稱(chēng)切圖仔。
本質(zhì)上是業(yè)務(wù)的性質(zhì)和規(guī)模決定了前端的工作不會(huì)占用太大比重,自然也不會(huì)受到太多重視, 可取代性也很高。
這類(lèi)公司往往是傳統(tǒng)行業(yè),例如硬件、電力。相反依賴(lài)于前端行業(yè),如電商、社交,前端的地位會(huì)高很多。
這種環(huán)境下,前端不會(huì)關(guān)心太多業(yè)務(wù),當(dāng)然容易被邊緣化,扮演相聲里面的捧哏角色。
②協(xié)助混亂/基礎(chǔ)設(shè)施薄弱
小微企業(yè),因?yàn)槿藛T整體水平不高,協(xié)作通常也比較混亂、不規(guī)范。這里指的是一個(gè)項(xiàng)目的整體研發(fā)協(xié)作。
對(duì)于前端來(lái)說(shuō),我們的上游可能是后端,后端的代碼質(zhì)量和規(guī)范性對(duì)前端影響也會(huì)特別大。
例如接口混亂、文檔不規(guī)范、未考慮應(yīng)用場(chǎng)景、接口不測(cè)試等等... 這種工作環(huán)境下,效率會(huì)非常低,前端開(kāi)發(fā)會(huì)非常痛苦。
基礎(chǔ)設(shè)施弱,前端工程化總感覺(jué)束手束腳。
③忙碌
感覺(jué)每天都很忙碌,卻像什么事情都沒(méi)有做。每天的工作重復(fù)一次又一次,原地踏步。
④孤島
像置身孤島,知識(shí)和消息是封閉的,個(gè)人能力和技術(shù)很難有大的突破。公司的格局決定個(gè)人的格局。
⑤人員變動(dòng)
吸引不了優(yōu)秀的人才,而且優(yōu)秀人才也留不住,整體水平較低,很難有技術(shù)沉淀和開(kāi)拓。
⑥理想/企業(yè)文化的認(rèn)同感
我們只是為了賺錢(qián),別跟我談什么理想。我們感覺(jué)自己在被壓榨,是機(jī)器,這樣的工作自然不會(huì)有什么幸福感。
等等等...
中臺(tái)的概念
今年中臺(tái)的概念的很火,我沒(méi)怎么去關(guān)注它,因?yàn)槲艺J(rèn)為它跟我們前端的距離還是比較遠(yuǎn),而且大廠才能搞得起來(lái)。
直到在 TWeb Conf 上聽(tīng)張?jiān)讫堉v了《Headless CMS——小微項(xiàng)目的業(yè)務(wù)中臺(tái)解決方案》讓我對(duì)“中臺(tái)”提起了興趣:
- https://juejin.im/post/5dd20202e51d453ff47f9c81#heading-2
不是大廠才能實(shí)踐中臺(tái),我發(fā)現(xiàn)我們的應(yīng)用也存在很多重復(fù)的業(yè)務(wù),每新建一個(gè)應(yīng)用,后端都要重復(fù)去拷貝和實(shí)現(xiàn)這些業(yè)務(wù)。對(duì)于后端來(lái)說(shuō),資源非常浪費(fèi),對(duì)于前端來(lái)說(shuō)也是一個(gè)災(zāi)難。
因?yàn)槲覀儼l(fā)現(xiàn),盡管后端的業(yè)務(wù)本質(zhì)上是重復(fù)的,但是因?yàn)槿藶樵?,他們每一次拷貝暴露出?lái)的接口和流程或多或少和之前的應(yīng)用不一致,每次前端都需要重新適配。
張?jiān)讫埥榻B了一個(gè)適合小微項(xiàng)目的業(yè)務(wù)中臺(tái)解決方案,他舉的例子是 `Strapi`[5]:這是一個(gè) Headless CMS。
翻譯為中文就是'無(wú)頭'內(nèi)容管理系統(tǒng),和傳統(tǒng) CMS 的最大區(qū)別是 Headless,即它只暴露接口,沒(méi)有固定的界面。
通過(guò)它,你可以實(shí)現(xiàn):
- 可視化、快速的業(yè)務(wù)模型創(chuàng)建。類(lèi)似創(chuàng)建數(shù)據(jù)庫(kù)模型(數(shù)據(jù)庫(kù)無(wú)關(guān)),可以靈活地配置各種字段類(lèi)型(除了原始類(lèi)型、還支持郵箱、文件上傳)以及模型關(guān)系。
- 暴露規(guī)范的接口。支持 Restful 和 GraphQL。內(nèi)置支持排序、分頁(yè)、過(guò)濾、自動(dòng)生成文檔。
- 內(nèi)置權(quán)限控制系統(tǒng)。角色、JWT 鑒權(quán)。
- 輕松集成內(nèi)部系統(tǒng)??梢造`活地與自己的內(nèi)部系統(tǒng)對(duì)接。
- 擴(kuò)展性。插件系統(tǒng)。
Headless CMS 是一種適用于小微企業(yè)的業(yè)務(wù)'中臺(tái)'解決方案。通過(guò) Strapi 我們可以快速搭建簡(jiǎn)單的外圍業(yè)務(wù)模型,復(fù)用通用的服務(wù)和插件。
你也可以認(rèn)為這是一種分層的架構(gòu),隔離了核心業(yè)務(wù)和外圍業(yè)務(wù)。外層相比內(nèi)層更加多變和冗雜,Strapi 中臺(tái)層隔離了 UI 和 核心服務(wù),它讓核心服務(wù)可以下沉,專(zhuān)注于實(shí)現(xiàn)更加通用的服務(wù)。
通過(guò) Strapi 可以快速搭建非核心的外圍衍生業(yè)務(wù)模式,暴露標(biāo)準(zhǔn)化的接口范式。
一方面可以及時(shí)響應(yīng)前端多變的需求,另一方面提供標(biāo)準(zhǔn)化、一致化的接口范式,也可以降低溝通成本、提高開(kāi)發(fā)效率?;诖? 前端也可以沉淀自己的可復(fù)用的業(yè)務(wù)組件。
當(dāng)然,正如張?jiān)讫埶f(shuō)的,Strapi 相比大廠中臺(tái),就是個(gè)玩具。但對(duì)于小微企業(yè),迅速開(kāi)發(fā)原型響應(yīng)市場(chǎng)、提高研發(fā)效率,卻是一劑良藥。
前后端分離再分離
你會(huì)發(fā)現(xiàn)前端開(kāi)發(fā)的體系化、正規(guī)化,其實(shí)伴隨著前后端分離逐步深化:
盤(pán)古開(kāi)天:沒(méi)有前后端之分。
模板時(shí)代:按照 MVC 架構(gòu),后端負(fù)責(zé) MC,實(shí)現(xiàn)業(yè)務(wù),給前端提供數(shù)據(jù)。前端負(fù)責(zé) V,即寫(xiě)模板。前端后在項(xiàng)目結(jié)構(gòu)上并沒(méi)有分離,但是職責(zé)開(kāi)始了分化。
接口時(shí)代:后端提供 HTTP/WS 接口,前端負(fù)責(zé)請(qǐng)求接口和實(shí)現(xiàn)頁(yè)面渲染。
CSR(客戶(hù)端渲染)技術(shù)開(kāi)始爆發(fā),Backbone、Angular、React...前端在項(xiàng)目結(jié)構(gòu)上已經(jīng)從后端脫離。開(kāi)發(fā)效率進(jìn)一步提高。
接口就是一個(gè)約定,按照約定先行的原則,前后端可以實(shí)現(xiàn)并行開(kāi)發(fā)。但是這個(gè)階段后端接口實(shí)現(xiàn)還是需要關(guān)心頁(yè)面的呈現(xiàn),必須提供能夠滿(mǎn)足 UI 渲染的接口。
BFF 時(shí)代:BFF 即 Backends for Frontend。伴隨著陣痛,前后端進(jìn)一步分離。
主要有兩個(gè)原因:終端多樣性,桌面端、iOS、Android、前端、小程序... 不同的客戶(hù)端對(duì)接口有不同的需求、而且這些需求是多變的。
另外后端業(yè)務(wù)也向微服務(wù)演化, 于是后端的接口會(huì)趨向原子化、功能更加單一、更加通用。
但是這對(duì)于前端開(kāi)發(fā)來(lái)說(shuō)也是比較痛苦的,實(shí)現(xiàn)一個(gè)頁(yè)面需要調(diào)用很多接口、隨之頁(yè)面性能也會(huì)降低。
分層架構(gòu)又派上用場(chǎng),那就多加一層唄,這一層就是 BFF,它讓客戶(hù)端開(kāi)發(fā)者根據(jù)自己的需求在服務(wù)端來(lái)粘合后端的通用服務(wù)。
這會(huì)后端再也不用關(guān)心 UI 了。BFF 時(shí)代,GraphQL 和 NodeJS 備受矚目。
Serverless 時(shí)代:BFF 推行需要良好的基礎(chǔ)設(shè)施和研發(fā)流程支撐,架構(gòu)難度也比較高,因此通常只有大廠搞得起來(lái)。
Serverless 借助云平臺(tái), 降低了對(duì)基礎(chǔ)設(shè)施的依賴(lài),以及開(kāi)發(fā)和維護(hù)的難度。所以基于 Serverless 的 BFF 門(mén)檻更低。
Serverless 對(duì)前端開(kāi)發(fā)的意義不止于此,強(qiáng)烈推薦 《Serverless 掀起新的前端技術(shù)變革》這篇文章:
- https://zhuanlan.zhihu.com/p/65914436
后端不想關(guān)心 UI 呈現(xiàn)所需要的數(shù)據(jù),只想關(guān)注于業(yè)務(wù)的實(shí)現(xiàn)。前端也想擺脫后端的下游依賴(lài),既然大家都覺(jué)得不合適,分開(kāi)是最好的。
回到開(kāi)頭那句話,前端開(kāi)發(fā)的體系化、正規(guī)化伴隨著前/后端的分離再分離,反之,正是因?yàn)榍?后端分離的深化,前端開(kāi)發(fā)得以正規(guī)化、體系化。
上一節(jié)張?jiān)讫埥榻B的“中臺(tái)”的概念,在某種意義上,也是一種前后端分離的深化。
因此,如果你的團(tuán)隊(duì)感受到了陣痛,其實(shí)也正好說(shuō)明公司業(yè)務(wù)正處于上升狀態(tài),如無(wú)意外,你們踏上前人走過(guò)的路,和后端進(jìn)一步撕裂。
極簡(jiǎn)的技術(shù)棧
Keep it Simple,Keep it Stupid。最近對(duì)這個(gè)原則體會(huì)頗深。小微團(tuán)隊(duì)技術(shù)選型不應(yīng)該隨大流、追隨最新最熱的技術(shù),而是應(yīng)該選擇符合自己的團(tuán)隊(duì)水平和業(yè)務(wù)情況的極簡(jiǎn)技術(shù)棧。
這四個(gè)原則非常重要:
- 簡(jiǎn)單
- 自動(dòng)化
- 清晰健全的文檔
- 約束
舉幾個(gè)例子,“簡(jiǎn)單”,主要是為了減低學(xué)習(xí)的門(mén)檻、降低心智的負(fù)擔(dān),接口越簡(jiǎn)潔越好:
- 約定>配置。
- 顯式>隱式。
- 聲明式>命令式。
- 接口協(xié)議:JSONRPC>Restful。
- 構(gòu)建工具:Parcel>Webpack,除此之外還有 Vue-cli,create-react-app。
- 框架:隨便舉個(gè)例子 Vue>React。Vue 入門(mén)會(huì)相對(duì)簡(jiǎn)單,React 太靈活、社區(qū)百花齊放、盡管我很愛(ài)它,但是它沒(méi)辦法阻止別人干蠢事。
- 狀態(tài)管理:Mobx>Redux>Rxjs。
- 當(dāng)然,具體場(chǎng)景具體分析
“自動(dòng)化”,能夠自動(dòng)化解決的事情,就不要靠文檔規(guī)范、靠口頭溝通:
- ESlint、Styleint、HTMLlint、Markdownlint... *Lint。有各種各樣的 lint 工具和社區(qū)推薦規(guī)范,自動(dòng)檢測(cè)各個(gè)環(huán)節(jié)是否符合規(guī)范。
- Prettier 代碼格式化。只有一種代碼樣式,別 BB。
“文檔”,重要性不言而喻。有事先看文檔,再問(wèn)別人。
“約束”,在事情失去控制時(shí),我能體會(huì)到那種絕望。這時(shí)候你會(huì)希望當(dāng)初有更多的約束,盡量讓代碼保持在可控范圍之內(nèi)。
例如 Typescript,各種 *Lint。如果沒(méi)有約束機(jī)制,規(guī)范永遠(yuǎn)只是規(guī)范。
避免“單點(diǎn)故障”
小微前端團(tuán)隊(duì),人員資源非常有限,往往每個(gè)人負(fù)責(zé)不同的項(xiàng)目,這就可能出現(xiàn)“單點(diǎn)故障”。假如這時(shí)候項(xiàng)目的負(fù)責(zé)人請(qǐng)假或者離職,就會(huì)讓人措手不及。
一方面項(xiàng)目交接過(guò)程會(huì)拉長(zhǎng),另一方面其他成員上下文切換的成本也很高。我們尤其害怕接手的項(xiàng)目是一個(gè)爛攤子。
解決單點(diǎn)故障的唯一辦法是讓更多的成員交叉參與不同的項(xiàng)目,項(xiàng)目的責(zé)任在于團(tuán)隊(duì)而不在于個(gè)人。
另外可以配合例如代碼 Review 這些手段,多種途徑讓團(tuán)隊(duì)成員可以熟悉項(xiàng)目的代碼。
代碼規(guī)范和共享代碼在這里也可以起到很大的作用。如果知識(shí)可以在多個(gè)項(xiàng)目中復(fù)用和共享,那么項(xiàng)目上下文切換的成本就相對(duì)比較低。
集體利益大于個(gè)人利益
不管是大公司還是小公司,集體的利益永遠(yuǎn)是大于個(gè)人利益的。
上周做了兩個(gè)錯(cuò)誤的決策,一個(gè)是批了一個(gè)緊急項(xiàng)目負(fù)責(zé)人請(qǐng)假,二是項(xiàng)目未完整測(cè)試上線就帶隊(duì)去參加 Tweb Conf。
這兩個(gè)決策導(dǎo)致很大的風(fēng)險(xiǎn),也挨上級(jí)領(lǐng)導(dǎo)批評(píng)了,還好最后都搞定了。
反省以下幾點(diǎn)欠缺:
- 集體利益大于個(gè)人利益。這是我們從小被灌輸?shù)乃枷?,在一個(gè)集體中,你的行為和決策是需要對(duì)集體負(fù)責(zé)的。
- 對(duì)項(xiàng)目缺乏整體的把控,沒(méi)有充分的風(fēng)險(xiǎn)評(píng)估。盡管前端只是一個(gè)完整項(xiàng)目的一環(huán),作為前端團(tuán)隊(duì) Leader,還是需要從整體上了解項(xiàng)目的進(jìn)度。
你要知道項(xiàng)目的開(kāi)始時(shí)間、截止時(shí)間、提測(cè)時(shí)間、開(kāi)發(fā)/測(cè)試進(jìn)度、當(dāng)前資源情況等。通過(guò)這些信息來(lái)進(jìn)行制定資源的分配計(jì)劃和風(fēng)險(xiǎn)預(yù)估。
- 推動(dòng)協(xié)作效率的改進(jìn)。作為團(tuán)隊(duì) Leader,就不能只單純關(guān)注技術(shù)和代碼。我們需要去關(guān)注團(tuán)隊(duì)之間的協(xié)作通道,提高團(tuán)隊(duì)層面的協(xié)作效率,為團(tuán)隊(duì)成員掃除溝通方面的障礙。
就像我經(jīng)常跟我們的團(tuán)隊(duì)伙伴說(shuō):?jiǎn)栴}不可怕,可怕的是不知道問(wèn)題在哪里,你要想進(jìn)步、就要多反思、多問(wèn)為什么。
談?wù)剛€(gè)人的發(fā)展:跳槽與跳槽路上
大公司有什么?如下圖:
小公司有什么,可能什么都沒(méi)有,百?gòu)U待興... 空間可能很大,天花板也可能很低。
大部分情況下,它可能只是你的一個(gè)跳板。你要么在跳槽,要么在跳槽路上,或者你已經(jīng)麻木了,迷茫不知進(jìn)退。
不管怎么樣,小微企業(yè)的前端需要多考慮自己的個(gè)人發(fā)展。包括我自己也在不停地思考,不甘平庸,努力尋找可以花一輩子去奮斗的事業(yè),而不只是工作。
對(duì)于個(gè)人發(fā)展, 我有以下幾點(diǎn)建議:
- 確定自己想要深入挖掘方向。很多所謂的大牛大多都是某一具體領(lǐng)域的專(zhuān)家。前端目前也有很多細(xì)分領(lǐng)域。
- 跳出自己的舒適區(qū),去嘗試新的東西。
- 勇氣。人有多大膽,地有多大產(chǎn)。沒(méi)有勇氣會(huì)錯(cuò)過(guò)很多東西。
- 參與社區(qū),樹(shù)立個(gè)人品牌。
- Stay hungry,Stay foolish。
- 基礎(chǔ)很重要。別著急學(xué)花里胡哨的東西,別著急跟著別人去看源碼。
- 嘗試去理解業(yè)務(wù),理解商業(yè)和世界運(yùn)作的規(guī)律,提升格局和軟技能。
總結(jié)
小微企業(yè)的圍墻不能靠一個(gè)人就能推倒,業(yè)務(wù)的擴(kuò)張和升級(jí)才是真正的動(dòng)力。
如果你覺(jué)得你公司有上升的動(dòng)力和勢(shì)態(tài),而且你認(rèn)同公司的價(jià)值觀,不妨一起努力推動(dòng)公司的進(jìn)步。反之,要認(rèn)真考慮自身的發(fā)展。
不說(shuō)了,各自珍重,努力奮斗!