我是如何成為一名全棧工程師的?
作者 | 宋奕興
經歷了將近一年的時間,我終于階段性地完成了從iOS開發到后端開發的角色轉變。
現在我可以自豪地說,我已經接近一名全棧工程師了,已經熟悉了后端開發的各種工具、環境和一些后端工作的方式。
接下來,我將繼續熟悉框架、工具、語言,并繼續深入研究后端的一些技術方案和實現策略。
通用軟件開發流程
在這將近一年當中,經歷過太多的坑了。
幸運的是,我們作為一名通用軟件的工程師,這個行業發展了這么多年,其工作流程已經趨于穩定。
所以,在我個人看來,無論是什么樣的開發角色,對于開發這個崗位來說,我們大致可以將知識結構分為以下幾個方面:
- 語言
- 框架
- IDE
- 依賴管理
- 測試框架
- 編譯運行環境
- 運行平臺
- 打包工具
- 部署方式
- CI/CD配置
- 性能指標
如下圖所示,例如:
做iOS開發的語言就是OC或者swift,我們學習語言特性之后,需要學習如何使用對應的框架進行開發,開發過程中,我們用Cocoapods做依賴管理,使用XCTest寫測試代碼,最后經過LLVM和Mach-O的編譯打包后生成了IPA包,我們將IPA通過Xcode發布到AppStore中,然后用戶可以下載并運行在相應的AppleOS(iOS/iPadOS/MacOS/WatchOS…)中,并且上線后我們需要重點關注的指標是崩潰率和卡頓率。
那么我們也可以將這些模塊映射到后端的學習中去。
后端開發也會大致遵循這個結構,就像流水線上的各個工位一樣,每一步都是需要做的,只是使用的工具和方式不同罷了。
接下來,比如,我們選擇JS語言進行后端開發,那么我們一定也會選擇一個框架(如果不是從底層開始寫的話),假如我們選擇了NestJS框架,那我們肯定也會問,管理依賴用什么做呢?測試用什么框架寫呢?哪個IDE好用呢?我要如何將它進行打包發布呢?上線之后我們用什么指標作為衡量其好壞的標準呢?
一旦我們擁有了針對整個流水線或者工作流程的認知,我們接下來要做的,只是在尋找有什么工具能夠實現這一步驟而已,如此,對于快速學習上手很有幫助。
這里,有一個網站,或許能有所助益,https://roadmap.sh
借助這個網站,我們可以清晰地規劃自己的學習路徑。
圖片來源:https://roadmap.sh/backend
開發過程側重點的轉變
正所謂屁股決定腦袋,作為一名前端或者iOS開發,在開發過程中的側重點一般在以下幾個方面(按照我腦袋中的順序排列):
- UI/UX的實現
- 怎樣的數據結構可以更好地驅動UI
- 如何和后端交互
- 各個模塊之間如何更好地調用
- 如何更好地持久化數據
- 如何更好地使用線程,協調UI渲染時的主線程和其他線程
- 如何讓CI/CD更有效率
- 降低崩潰率/卡頓率
而在后端開發過程中,我的側重點變成以下幾個方面了:
- 數據如何更好的存儲,注重表結構的設計
- 如何和前端更好地交互
- contract怎么設計
- 怎么更好的兼容多平臺,例如,Auth怎么做,BFF怎么做,數據結構怎么設計
- 怎么更好地做API的版本管理
- 各個模塊或者服務之間如何更好地協作,如何更好地設計事件
- CI/CD怎么更有效率,不同環境的部署怎么做能更好地做E2E測試
- 降低接口響應時間/HTTP錯誤率
當然,側重點的轉變主要還是因為前端和后端的服務對象不同。
前端應用更多的是服務用戶,所以如何將頁面做的更好是首要,然后再向后思考如何更好地為頁面汲取數據。
而后端更多的是服務前端,或者其他后端服務,重點在于數據處理和API設計,所以數據是首要,如何存儲數據,如何傳輸數據,是重中之重。
開發者思維角度的轉變
由于工作的側重點變了,所以思考的方式也會隨之改變。
作為一名iOS開發,在日常生活中,我會習慣性地對一個正在使用的APP思考,這個特效是如何實現的,這個APP的頁面是如何組織起來的,或者這么多頁面同時存在切換,它是如何進行內存管理的?
而作為一名后端開發,我開始思考的是,微博的互粉功能在數據結構上是怎么保證高效率查找的?微信消息是怎么做到丟失率這么低的?
更加明顯的是,在進行需求分析的時候,之前習慣性的將頁面作為錨點,比如討論業務需求首先確定這個頁面交互如何實現,然后確定什么數據更好的驅動頁面,然后再定API。
而對于后端,更多考慮的是背后的數據表字段怎么定義,表關系如何管理。
但是,可喜的是,由于現在同時具備這些經驗了,所以又可以提起那個老生常談的策略:分層,或者分而治之。
所以,在進行需求分析的時候,更多的關注點,或者切入點就是BFF和contract怎么定義,用AOP的方式管理團隊的關注重點,大家討論的時候只關注交互的地方,以及可能變化的地方,剩下的工作都在各自的領域中進行,互不影響。
這種方式同樣適用iOS開發內部或者后端開發內部,比如我們同時完成一個大的功能,我負責A,你負責B,于是我們先定義好A和B的交互部分,將interface先實現,然后各自回到自己的領域做事,最后面向interface接洽就好。
如何更好地理解業務
隨之而來的,我可以理解頁面,知道如何做UI/UX會更好地服務客戶,現在也可以理解數據,知道如何更好地讓數據流轉和存儲,所以針對業務,站在技術人員的角度,我們可以提供更多的建議,以及指導如何更好地拆解和實現業務。
比如,使用BFF來隔斷前端所需的數據結構和內部數據結構,用來避免業務變化對底層實現的影響,并且可以兼容各個平臺,給不同的平臺分發不同的數據結構。
業務的變化可以被隔離在domain中,前端對于domain的體現是不同的module,后端可以是module也可以是微服務,然后我們討論時重點關注的是他們中間如何交互,而不是很多的內部實現細節
再比如,現在需要實現一個登錄功能:
- 作為前端,我只在乎如何畫出登錄頁面,調用登錄接口,持久化session然后進入主頁面。
- 作為后端,我只在乎如何進行Auth的實現,然后存儲生成的 session并記錄日志。
可以從流程中看出來,初始數據是前端提供的賬號密碼,從前端流向后端,而后端生成session,然后從后端流向前端,我們第一步需要做的就是確定數據怎么流,剩下的就是各自領域的事情,后端去研究數據怎么存,前端去研究頁面怎么畫,僅此而已。
在此基礎之上,我們就可以把握整體,進行更好地架構設計和分層設計了。
并且無論是前后端之間,還是前端和后端各自內部的工作。
如何開始
前面說了一大堆,都是成為全棧之后的好處和所得。
那么,如果你也有這個計劃,你應該如何尋找一個機會,或者創造一個機會開始呢?
從一個純粹的前端轉到后端,并不僅僅是技術棧的遷移,還包括思維視角的轉變。
首先,我們得確立轉職的原因:
主觀上:
- 興趣學習
- 成為一名全棧開發
- 成為一名TL
客觀上:
- 項目需要
- 市場需要
如果僅僅是項目需要,那機會已經送到眼前,相信一般情況下,項目上會給你時間和精力專門從事學習,并且還有很多機會直接進行開發,剩下的只是效率問題。
但如果沒有客觀的條件支持,那么我的處理方式是,找一個你感興趣的APP,去思考它是如何實現這些功能的,然后嘗試著自己去實現,例如小紅書,微信等等。
用一個項目和實踐來承載你的學習,這樣子,就不僅僅只是看看文檔,并且練手的時候順便分析學習了一個成熟產品,也不用耗神在創造技術的應用場景上。
再接下來,確定你要點哪些技能點。
從興趣,市場需求,各個方面,確定語言,確定框架,然后最好跟著官方文檔進行學習吧。
上面分享的模塊化知識和roadmap網站在這里就非常有用。
或者跟著某個學習視頻來進行學習和練手,但是會有幾個問題:
- 講解的技術點不一定是官方最新建議的
- 一般這種視頻進行的練手項目都很簡單,不能完全應對真實的使用場景
學習方式
學習需要區分了解和使用,在這里,我將知識點分為三類:
- 知識類:這種類別的知識我們需要的是記住,例如我們看到狗就知道他是狗,例如我們知道我們需要用NodeJS去運行我們的應用。
這類的知識主要在于主動獲取并記住理解它。
- 技能類:這種類別的知識,就是唯手熟爾,例如我們需要熟練地使用JS中各種語法特性,我們知道拆分數據需要用哪個函數。
有一些知識起初是知識類類的,當我們知道了解后,但是一旦你運用到實踐當中,并且越來越熟練,就證明你徹底掌握了這項技能。
- 索引類:這種類別的知識,是技能類退而求其次的產品,有些技能或者方式我們并不需要掌握的如此熟練,但是,我們是知道有這種方法存在的,在需要精確的書寫實踐它的時候,再去查閱就行了。例如π的前30位數字,例如八皇后的算法。
而針對不同類別的知識,我們采取不同的學習方法。
語言
針對語言的學習,重點在于練習,是我們需要不斷使用和磨練的技能:
- 數據類型
- 數據結構
- 函數的定義和使用
- 線程
對于我而言,學習JS的時候,對應著OC,或者Swift的一些語法結構,會學習的很快。
在這里其實也可以進行各種模塊化,例如數據結構其實已經比較恒定,在不同的語言中,字符串、HashMap、數組、Decimal都有各自的處理方式方法,只是名稱不同而已,實現的功能是一樣的。
再比如,無論是什么語言,都需要進行函數調用棧的管理,只是實現方式不同罷了。
而一些特殊的地方,例如JS中的類型解構,也可以找到對應的概念去理解,例如Swift中的元組。
框架
針對框架,重點在于對控件的使用和對其文件組織方式的了解。
我們根據需求和興趣選擇某一個框架后,在這個框架中,構建運行應用,使用其提供的工具進行需求的實現,例如在NestJS中使用TypeORM或者接入Kafka非常方便,它使用module-controller-service的方式來組織文件。
練習
在上面的陳述中,我提到可以選擇一個成熟的APP進行仿作練習,在這個過程中,使用TDD,并且使用ChatGPT來進行結對編程簡直是絕佳的選擇。
TDD可以幫助我們快速了解框架,語法和API的使用,而結對編程能夠幫助我們更好地了解它為什么這么寫,為什么能夠適用這個場景以及獲取一些經驗,尤其在有了chatGPT之后,就算沒有一個大佬或者共同學習的小伙伴跟你結對編程,但是我們依然可以假裝在結對編程。
寫在最后
在這快一年的時間里,我接觸了PHP,Typescript,React,React-Native,最近開始研究研究ES的標準,從一名iOS純開發慢慢轉型到后端甚至全棧,在這個過程中不僅僅是提升了自己的技術能力。
更多的是了解了不同崗位之間思考的差異,能夠更好的作為TL拆分需求,跟各個崗位的同學們進行溝通。
并且,經過發現總結后,又提升了一點點自己快速學習的能力。
現在只是想寫出來,和大家共勉,其中當然有很多不那么恰當甚至錯誤的理解,也希望能夠得到大家的指正。