拜託,大廠做專案可不簡單!

程式設計師魚皮發表於2021-07-16

揭祕一線大廠研發流程

大家好,我是魚皮。

很多未工作過的小夥伴都很好奇:企業中做專案是怎樣的流程?尤其是大廠那些百萬使用者的專案,和自己學程式設計時做專案到底有什麼區別呢?

實話說,區別可大了!

自己開發專案那是單打獨鬥,自己掌握命運,不會拖垮隊友;但企業中開發專案是開團打本,大家是一根繩上的螞蚱,每個人都會影響整個專案。

我自己也在幾家公司實習過,不得不說,大廠和其他公司的研發流程也有很大的區別。

因此,對於大多數同學,如果沒有在大廠工作過,對很多研發環節可能都是一無所知的。

所以今天給大家揭祕一下大廠的專案研發流程,幫大家開拓思路。

正好之前有同志質疑我的日常工作就只有寫程式碼和摸魚?!這篇文章就作為回擊,讓他明白,在大廠做專案,可不止寫程式碼那麼簡單!

大廠研發流程揭祕

為了規範團隊、保證專案的進展,大廠研發流程通常還是比較複雜的。

可以分為很多個階段,用一張思維導圖來概括:

一線大廠研發流程導圖

需要注意的是,以上階段並不是完全按從上到下的順序執行,階段間可能存在交叉,比如 技術選型 其實在 設計階段 就應該考慮。

正式工作一年多,我也是經歷過多次專案的完整研發流程的。下面就以我的視角,帶大家快速過一遍~

(為了內容更有趣,以下故事有虛構成分)

需求階段

今天是週一,魚皮像往常一樣騎著他的小電動車來到公司,殊不知,等待他的是一場噩夢的開始。

需求產生

上午十點,產品妹子找到魚皮,告訴他:我們們的系統上線後,使用者表示很多功能並不好用,需要大改。

老闆也找到魚皮,告訴他:我今天開啟頁面竟然載入了十幾秒,我們們這個系統的效能太爛了吧!

魚皮心想:嘔豁,完蛋!估計得做個新的專案了,又要開會了。

果然,沒過多久,螢幕上彈出了一條 “歡迎加入會議” 的邀請。

需求評審

第二天上午,老闆、產品、測試、幾位開發大哥和魚皮一起來到會議室,具體討論昨天提到的那些需求 是否合理、要不要做

產品妹子開啟文件,說到:這一期呢,我們要做這幾個需求,下面我來詳細講一下,大家一起評估下有沒有問題。

需求分析

接下來,產品妹子正在對著螢幕侃侃而談、瘋狂輸出時,旁邊的開發大哥坐不住了。

開發大哥:這個需求不合理啊!

產品:為啥不合理?使用者就是有這個需求啊!

開發大哥:我知道,實現不了啊!

於是開始了經典的產品開發撕逼大戰。。。

而魚皮正躲在角落冷靜分析 這個需求怎麼做 ,過了一會兒,提出了一種改動低、實現快的解決方案,平息了這場戰爭。

排期

確定需求合理、可實現之後,產品妹子問到:那這個需求啥時候能上線呀?

開發大哥:我這周忙,下週吧。

產品:使用者可能比較著急,這周就要呢!

開發大哥:我知道,做不完啊!

於是開始了經典的產品開發撕逼大戰。。。

魚皮:要不我們把這個需求拆解為功能 A 和功能 B,這周我先把功能 A 做了,功能 B 排到下週二測試,下週四上線?

就這樣,我們一個個安排了需求的計劃完成日期。

設計階段

終於開完會了,看了下時間,都該下班了!

唉,需求討論完了,產品的工作是完成了一些,可魚皮的工作才剛剛開始。

急著開始寫程式碼麼?

不,想好怎麼寫程式碼比寫程式碼更重要。

架構設計

魚皮開啟寫文件軟體和畫圖軟體,開始梳理整個系統,從整體到區域性,依次設計出系統的層次結構、各層間互動的介面和通訊方式、每層之間包含哪些重要模組、模組選擇何種物理部署方式等。

知名框架 Dubbo 的架構設計

概要設計

寫完架構設計後,魚皮開始對著產品妹子寫的 PRD(產品需求文件),分析需求,然後依然是從整體到區域性,先整理出系統需要的功能模組,再分析每個功能模組內有哪些子模組。

和抽象的架構設計相比,概要設計和需求的關係更緊密,是對架構設計的細化。

打個比方大家就明白了,你要蓋一棟樓,架構設計就是從整體來考慮,總共有幾層、每層管道怎麼接、每層有幾戶、地基怎麼打等;而概要設計就是考慮每戶套件的內部怎麼劃分,哪裡是客廳、哪裡是衛生間。

很多情況下,概要設計和架構設計可能會在一個文件中進行,劃分並不明確。

詳細設計

想好系統有哪些功能後,魚皮就開始具體分析每個功能如何實現,用到哪些演算法、需要注重哪些細節等。

方案對齊

寫好設計文件後,下次會議上,魚皮和其他的開發同學(前端、後端等)一起針對自己設計的方案展開討論,最終產生一個統一的方案,然後大家分工去做就好了。

測試用例設計

為了保證系統功能的正常穩定,測試同學(或者叫 QA)是非常重要的,測試不是像我們自己做專案一樣對著網頁點幾下就 ok 了。

在大公司中,為了保證測試的覆蓋度、提高測試效率,一般是要設計測試用例的,比如:使用者點選 “登入”,未傳任何資料,期望結果是警告使用者輸入使用者名稱和密碼。

測試用例管理

測試用例設計完後,需要其他同學一起來評審把關,而不是隻交給測試同學。因為一個人很容易忽略掉很多測試細節,最好讓更熟悉程式碼的開發同學一起幫忙補充。

魚皮自己也寫了幾個測試可能會遺漏的用例,和測試同學一起進行了確認,儘量讓問題暴露在測試階段而不是線上。

研發準備

寫了快一週的設計文件,終於準備開始動手搭建專案了。但在此之前,還有一些準備工作要進行。

技術預研

如今技術發展太快,新技術層出不窮,所以魚皮首先對專案中需要或可能需要用到的技術進行了調研。

技術選型

通過調研,魚皮得到了幾個可以滿足需求的技術,但他開始糾結:這麼多技術,我該用哪一個呢?是用 SSM 框架還是 Play 框架呢?用 guava 包還是 Apache Commons 呢?

魚皮又開啟了寫文件軟體,開始對比不同技術的優劣,頭疼啊,技術選型要考量的因素太多了,比如:

  • 單從技術考慮:效能、易用性、穩定性、主流程度和生態、文件詳細度
  • 結合團隊:團隊成員對技術的熟悉度、掌控度(有無精通該技術的人)
  • 結合業務:是否適應業務的量級(單機 or 微服務)、是否適應業務(讀多、寫多 or 分析多)

對於關鍵的專案,魚皮自己還不敢完全確定選型,因此在寫好自己的選型文件後,與同事和 Leader 一起討論,才最終確認。

資源申請

確認好技術後,就要申請資源。比如魚皮用到了 MySQL 資料庫,但是這個 MySQL 從哪兒來呢?

以前的話,魚皮都是去買一臺雲伺服器,自己搭建 MySQL。但是在企業中,一般是有集中管理和分配資源的平臺的,直接到平臺填寫預算、等領導審批、然後等著下發資源就好了。千萬不能私自用自己的或買外部的伺服器來部署專案,不安全!

魚皮這次直接申請到了 2 萬多一年的雲資料庫,真的是爽死了。

環境準備

申請好資料庫等資源後,魚皮按照申請機器的版本搭建了一模一樣的本地開發環境和測試環境,後面就可以直接連線了。

專案初始化

環境準備妥當後,由於是新專案,魚皮要搞一個最小可執行的初始化專案 Demo,使用 腳手架 自動生成程式碼,而不是從零開始一個個新建檔案、手敲重複程式碼。

依賴安裝

生成了專案程式碼後,魚皮使用包管理工具(前端 yarn、Java Maven / Gradle 等)自動安裝依賴,然後專案 Demo 就可以執行啦!

研發階段

前期準備完成後,這才到了程式設計師朋友們最熟悉的寫程式碼環節,也是魚皮最愛的環節。

因為之前設計方案時需要保持冷靜、仔細思考,沒法邊聽歌兒邊做;而方案設計好後,已經明確了該怎麼做,寫程式碼實現就很簡單了,頂多是遇到一些坑,上網搜尋去解決就好了。

本地開發

開發時,一般魚皮會先在本地寫程式碼,通過配置熱更新工具,實現程式碼更新時自動重新編譯打包,而不用手動重啟專案,大大提高了開發效率。

對了,企業開發都會使用版本控制系統的,比如 Git,開發前記得先建立一個自己的分支,在這個分支上開發。

遠端開發

現在還有一種比較流行的遠端開發方式,就是可以像編輯本地檔案一樣編輯遠端檔案,直接修改伺服器上的程式碼。一般我們每位研發同學是有自己的開發機的,通過遠端開發就省去了反覆部署除錯的麻煩,提高效率。一般用 VSCode 等開發工具,安裝遠端開發外掛就可以實現了。

程式碼優化

魚皮在寫程式碼的時候,始終保持主動優化程式碼的好習慣,注重程式碼的時空複雜度;並且當重複程式碼多了,會想辦法抽象成函式或者使用設計模式。之前專門寫文章分享過我的程式設計習慣:我寫程式碼時的小倔強

單元測試

注意!不要聽到測試就以為是測試同學的工作,開發同學也同樣需要編寫小粒度的測試來為自己的程式碼負責。

魚皮一般會為每個資料庫讀寫函式和業務邏輯函式編寫單元測試,像 Java 的話一般用 JUnit 等工具,還可以用 Jacoco 生成測試覆蓋度報告。每次修改關鍵程式碼後,都要執行一遍單元測試,防止意外錯誤。

Jacoco 測試覆蓋度報告

開發聯調

魚皮終於寫好了後端程式碼,也自測完成了,下面就是把寫好的程式碼打包構建,然後把可執行專案包釋出到測試伺服器上,和前端同學一起聯調,讓他請求我的介面,驗證系統的功能是否可用。

測試驗證

魚皮和前端聯調完畢後,告知了測試和產品同學。

測試驗證是企業中至關重要的環節,甚至可以說是最後一道防線。測試的目的是找 Bug,儘量發現系統中的問題,把它們扼殺在測試階段。

在企業中,測試驗證又有很多型別。

整合測試

整合測試比單元測試粒度更大,是把多個模組或程式碼單元放在一起,驗證模組之間的整合和呼叫關係。

因為單個函式的執行可能是正常的,但把多個函式組合在一起順序呼叫,可能就會出現問題。

打個比方,我們有個吃麵包系統:

功能 A:小魚吃一個麵包

功能 B:小皮吃一個麵包

每次只有一個麵包,獨立執行功能 A 和 B 都是允許的。但如果兩個一起執行,後執行的那個功能就會報錯。

系統測試

系統測試比整合測試的粒度更大,測試物件是整個系統,不僅包括軟體,還可能覆蓋對硬體的測試。

產品體驗

除了測試同學要驗證系統可用性,產品妹子也要體驗下功能是否符合預期、是否易用。大多數情況下,產品會在體驗時提出修改建議,開發可能還要再去做一些修改。

驗收測試

測試和產品妹子終於表示沒有問題啦,那就到了最後一步,把整個產品或功能給最終的使用者來體驗。老闆 使用者說沒問題,才是真的沒問題!

提交階段

系統沒問題之後,魚皮就可以把程式碼釋出到遠端倉庫了,一般使用 Git 和 SVN 等版本控制系統。

程式碼提交

魚皮首先在本地觸發程式碼提交(git commit),為保證規範,在大專案中一般會使用提交檢測外掛,防止你把錯誤的程式碼進行了提交。

程式碼推送

下一步就是把本地的提交推送到遠端的同名分支。一般大廠會有推送檢測工具,檢測程式碼的錯誤、圈複雜度、程式碼規範等,和提交檢測一樣,防止你把錯誤或不規範的程式碼進行了推送。

合併請求

程式碼分支推送到遠端之後,魚皮發起了一個分支合併請求(MR),希望把該分支的程式碼合併到主幹分支(沒問題的程式碼)。

發起新合併請求

程式碼審查

並不是發起了合併請求就能直接合並,還要通過程式碼審查,即 CR。

審查又分為兩種方式:人審和機審。

相信不少同學都知道人審,一般是由你的上級和其他專案負責人來閱讀和評論你的程式碼,覺得沒問題就 Approve(通過),否則打回去修改。

那機審是個啥呢?其實就是機器自動檢測你的程式碼是否符合規範,是否能夠成功自動化構建等,一般是由專案負責人配置的,可以幫助發現一些人工難以發現的問題。

剛接觸新專案的時候,魚皮經常被機審折磨得苦不堪言,經常被提示一些莫名其妙的程式碼問題,比如加號要換行,檔案行末要加空行等。但後來注意編碼習慣後,就很自然地適應了,的確不錯。

釋出階段

程式碼審查通過後,魚皮的專案程式碼就可以釋出上線啦。

打包構建

傳統上線方式是開發人員到正式伺服器上拉取程式碼,然後安裝依賴,再通過工具把程式碼打包構建,得到部署包,通過 Nginx、Tomcat、Docker 等技術執行。

但這樣效率很低,有很多重複工作。所以大廠一般是用自動化構建的,像 Jenkins、各種 CI / CD 工具等。程式碼合併到主分之後,由機器把程式碼打包構建為最終的部署包。

預釋出

為了防止上線出問題,一般我們會先在預釋出環境部署專案,再觀察一下是否能夠正常執行。

正式釋出

預釋出測試正常後,魚皮終於等到了上線的這一刻。大專案一般都會部署在多臺機器上,所以不可能一臺臺登入機器去釋出部署包。

通常公司會提供視覺化釋出平臺,點選需要釋出機器(一般先灰度,選一小部分機器,再全量釋出),點選一鍵釋出,等專案管理員審批通過之後,就交給機器自動部署吧!

後續

魚皮曾天真地以為專案上線之後,就可以高枕無憂了。但後來發現,專案上線之後,同樣需要保持警覺。雖然已經測試過,但仍然時不時會出現個預期之外的小 Bug,還是很考驗心態的。

來看看上線之後,魚皮做了哪些事呢?

監控運維

魚皮會定期檢視專案的監控皮膚,觀察專案的執行情況,機器的負載等。

統計分析

魚皮在程式碼中新增了一些日誌,可以利用 ELK 等日誌收集視覺化平臺對這些日誌進行分析,從而感知到使用者的行為,進一步優化業務和系統。

比如我會統計使用者執行 SQL 查詢的耗時,對重複率高的慢 SQL 進行鍼對性地優化。

事件反饋

有的時候,使用者自己都不能清楚地描述 Bug,而且歷史 Bug 也不方便找到。所以公司內部一般會有事件反饋平臺,產品等內部同學在接收到 Bug 時,會在該平臺釋出一個 Bug 事件,詳細描述 Bug 出現的時間、狀況、詳情等,便於我們開發集中分析和處理問題。

事件反饋平臺

文件沉澱

每次上線了新功能和專案,魚皮都會通過寫文件來記錄專案的背景、設計方案、開發過程和一些坑點,便於後續其他同學瞭解專案,這是非常重要的!利人利己。

曾經分享過我的寫文件技巧:如何寫好文件?

迭代優化

最後,一個需求的結束往往只是另一個需求的開始。像魚皮最近在跟進的專案,一期做完做二期,二期還沒做完三期就來了;還要抽出時間去優化以前的程式碼,這日子遙遙無期,沒盼頭啊!


以上就是本期分享,看完本文後,歡迎閱讀我之前的這篇文章:大廠機密!30 個提升團隊研發效能的錦囊 ,瞭解更多大廠技術。

最後再送大家一些 幫助我拿到大廠 offer 的學習資料

跑了,留下 6T 的資源!

歡迎閱讀 我從 0 開始自學進入騰訊的程式設計學習經歷,不再迷茫!

我學計算機的四年,共勉!

我是魚皮,點贊 還是要求一下的,祝大家都能心想事成、發大財、行大運。

相關文章