新聞中心
“三人行必有我?guī)熝?,擇其善者而從之,其不善者而改之?!边@句話出自論語,卻同樣可應(yīng)用到我們的職業(yè)生涯中。在職業(yè)道路中,你應(yīng)該學(xué)會向那些成功人士請教,詢問他們做了什么、為何這樣做和具體實(shí)踐。在本文中,我將分享我在職業(yè)生涯中所學(xué)到的全棧工程師經(jīng)驗(yàn)。

靈川ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!
作為一名年輕工程師,我在科技行業(yè)和硅谷打拼了十年。這十年,我一直在高速增長的創(chuàng)業(yè)公司工作,經(jīng)歷了與此相關(guān)的所有起起落落。從構(gòu)建 nextgen 電子郵件客戶端,到在全球范圍內(nèi)推廣電動汽車,再到網(wǎng)上購物結(jié)賬,我學(xué)到很多。
當(dāng)回想過往,我覺得有些錯誤完全可以避免。在本文中,我將分享我在職業(yè)生涯中所學(xué)到的全棧工程師經(jīng)驗(yàn)。從中,我總結(jié)了十大經(jīng)驗(yàn)教訓(xùn)。我相信,這些經(jīng)驗(yàn)教訓(xùn)值得起時間考驗(yàn),并在未來幾年里依然適用。
這份列表從前端開始,然后是后端 API 和數(shù)據(jù)庫,最后是工程最佳實(shí)踐 / 流程。
經(jīng)驗(yàn)總結(jié)
- CSS Specificity
- 組件層次結(jié)構(gòu)中的設(shè)計狀態(tài)
- 后端編程中的面條式代碼、千層餅式代碼和餛飩式代碼
- 生產(chǎn)中的 Postgres
- 欲速則不達(dá)
- 投資自動化
- 掌握你的工具
- 最小可行性產(chǎn)品(Minimum Viable Product,MVP)
- 研究支持開發(fā)
- 科學(xué)調(diào)試
1. CSS Specificity
錯誤:我的 CSS 不適用。我要用 !important。
教訓(xùn):應(yīng)該為特殊情況保留使用 !important,因?yàn)樗鼈兤茐牧苏麄€ CSS 層次結(jié)構(gòu),并強(qiáng)制使用特定樣式。所以,你有必要了解 CSS Specificity。
CSS specificity 是瀏覽器應(yīng)用的一組規(guī)則,用來確定哪個 CSS 樣式更 specific。你可以將其視為基于點(diǎn)的系統(tǒng),它決定哪種 CSS 樣式獲得優(yōu)先權(quán),并最終應(yīng)用于 DOM 元素。
如果你想知道,為什么你的 CSS 沒有被應(yīng)用,這與 CSS specificity 有關(guān)。在大型項目中,這是一個很常見的問題,在這類項目中,像 SCSS 這樣的預(yù)處理程序與復(fù)雜的 CSS 層次結(jié)構(gòu)一起使用。了解 CSS specificity 將有助于你保留使用 !important,僅在極罕見的覆蓋情況下使用,例如,當(dāng)你想要覆蓋 CSS 庫或讓 iframe 覆蓋主機(jī)站點(diǎn)樣式時。
本質(zhì)上,優(yōu)先順序是這樣:ID selectors > Class selectors > Type selectors。!important 和內(nèi)聯(lián) style 屬性會覆蓋所有的 CSS。
對于應(yīng)用于元素的每個 CSS,你都可以輕松確定哪種樣式將生效。例如,如果你加載上面的 HTML 代碼:
在本例中,ID selector 優(yōu)先級高于 type selector。如果沖突的 CSS 選擇器具有相同的優(yōu)先級,那么將選擇 CSS 文件中的最后一個。
最后,Chrome DevTools 將會顯示如上圖所示的 specificity 順序。如果你無法使用 CSS,請查看 Chrome 使用的 specificity 順序,然后添加一個更具體的選擇器(如 ID 選擇器、類選擇器、類型選擇器),讓你的 CSS 更特定,并指示瀏覽器選擇它。
如果你不想這么做,請看看這個 specificity 計算器
鏈接:https://specificity.keegan.st/
2. 組件層次結(jié)構(gòu)的設(shè)計狀態(tài)
錯誤:我需要添加這個新狀態(tài)。我只需要將它放到這個 reducer 中,但不確定為什么這個 reducer 還有這么多其他狀態(tài)?
教訓(xùn):管理不當(dāng)?shù)?redux 狀態(tài)會在開發(fā)人員中造成混亂,并導(dǎo)致 bug。如果用 react 和 redux 來構(gòu)建前端應(yīng)用程序,那么你可以考慮使用這種可視化技術(shù),從用戶界面組件層次結(jié)構(gòu)中構(gòu)建狀態(tài)和 reducer 層次結(jié)構(gòu)。從零到統(tǒng)一的組件狀態(tài)層次結(jié)構(gòu)有三個步驟:
- 在線框圖(wireframe)將用戶界面進(jìn)行可視化
- 將狀態(tài)層次結(jié)構(gòu)進(jìn)行可視化以反映用戶界面
- 構(gòu)建 reducer 層次結(jié)構(gòu)以反映狀態(tài)層次結(jié)構(gòu)
讓我們來看一個例子。在這個例子中,我們構(gòu)建一個博客網(wǎng)站,它有兩個頁面,一個頁面用于博客列表,另一個頁面用于個人博客:
第一步:在線框圖中將用戶界面進(jìn)行可視化
主頁和個人博客頁面
第二步:將狀態(tài)層次結(jié)構(gòu)進(jìn)行可視化以反映用戶界面
相應(yīng)的狀態(tài)層次結(jié)構(gòu)圖如下所示:
狀態(tài)層次結(jié)構(gòu)
請注意,公共 Header 狀態(tài)是如何被拉到根狀態(tài)的。類似的,任何共享狀態(tài)都可以在層次結(jié)構(gòu)中“冒泡”,因此很明顯,子組件共享該狀態(tài)。
第三步:構(gòu)建 reducer 層次結(jié)構(gòu)以反映狀態(tài)層次結(jié)構(gòu)
reducer 層次結(jié)構(gòu)
這是一個簡單而強(qiáng)大的例子,展示了如何構(gòu)造狀態(tài)和 reducer 層次結(jié)構(gòu)來匹配用戶界面。這一過程可以輕松擴(kuò)展到復(fù)雜的應(yīng)用程序和大型團(tuán)隊。最后,你可以在這個結(jié)構(gòu)上構(gòu)建操作和表示層。
3. 后端編程中的面條式代碼、千層餅式代碼和餛飩式代碼
錯誤:這個代碼庫是如何組織的?也許我可以在這里添加這個文件,就像所有其他倉庫代碼一樣。
教訓(xùn):我寫過三種“意大利面條式代碼”。說實(shí)話,我覺得在“餛飩式代碼”里放上“迷你千層餅式代碼”也許是個好辦法。組織和培訓(xùn)所有開發(fā)人員以這種方式構(gòu)建代碼庫,可以保持代碼的可維護(hù)性、可測試性,最重要的是能保持敏捷性。你能在不影響其他功能的情況下,輕松修改特定的“餛飩式代碼”(也就是功能)的實(shí)現(xiàn)細(xì)節(jié)。
“千層餅式代碼”是:
- 分層架構(gòu)
- 架構(gòu)整潔
- 外層是 I/O,內(nèi)層是純數(shù)據(jù)結(jié)構(gòu)
- 依賴關(guān)系向內(nèi)注入
- 內(nèi)層不依賴于外層
- 優(yōu)先考慮組合,而非繼承
“餛飩式代碼”是:
- Screaming architecture
- 切片與分層
- 文件夾和文件的空間位置
- 可以是微服務(wù)形式
將它們放在一起,就能得到一個可擴(kuò)展、可維護(hù)的代碼庫。如果你可以想出一種方法,通過特征名來組織文件夾,并且在每個特征中實(shí)現(xiàn)整潔結(jié)構(gòu),這將讓你使用很長時間。
4. 生產(chǎn)中的 Postgres
錯誤:為什么這個查詢速度這么慢?我認(rèn)為是因?yàn)?Postgres 很慢的緣故。我需要切片,或者我認(rèn)為這是 ORM,或者,我需要一個不同的數(shù)據(jù)庫,Postgres 并不適合我。
教訓(xùn):如果你在生產(chǎn)環(huán)境中運(yùn)行 Postgres,那么你將會遇到查詢緩慢、表鎖、無限等待遷移和錯誤的問題。如果不是這樣,那么對你有好處,你又是怎么做到的?這并不意味著 Postgres 不再是正確工具,而是意味著你需要揭開帷幕,看看下面發(fā)生了什么。
截至目前,我發(fā)現(xiàn)的最好工具是 pgbadger。你可以用它解決幾乎所有的 Postgres 問題。
鏈接:https://github.com/darold/pgbadger
這是一個 Perl 命令行工具,它將 Postgres(如果你使用 AWS 的話,就是 RDS)日志作為輸入,并輸出報告。該報告的好壞取決于你在 Postgres 上啟用的日志。因此,在第一步時你可能需要啟用這些日志:
- log_checkpoints = on
- log_connections = on
- log_disconnections = on
- log_lock_waits = on
- log_temp_files = 0
- log_autovacuum_min_duration = 0
- log_error_verbosity = default
- log_min_duration_statement = 1s
此外,你可能還需要啟用 pg_stat_statements 語句來實(shí)時分析查詢,并啟用 auto_explain 來自動解釋日志中運(yùn)行緩慢的查詢。
運(yùn)行報告:
- pgbadger --prefix '%m %u@%d %p %r %a : ' /pglog/postgresql.log
該報告將匯總數(shù)據(jù),并提供有關(guān) Postgres 所做工作的大量信息。你可以找到關(guān)于錯誤、最慢查詢、等待最長查詢、獲取的鎖類型、臨時文件是否用于排序、檢查點(diǎn)運(yùn)行的頻率、真空運(yùn)行的頻率以及其他類似信息。有了這些數(shù)據(jù),你就可以識別和修復(fù)運(yùn)行緩慢的查詢,并通過調(diào)優(yōu)提高 Postgres 的性能。
你可以持續(xù)運(yùn)行此報告(CLI 支持增量模式),從而隨時掌握新問題。
另外,如果你想理解解釋輸出,可以用這款工具。
鏈接:https://tatiyants.com/pev/#/plans/new
該工具將解釋 JSON 和原始查詢作為輸入,并將在如下所示的可視化樹形圖中對解釋輸出進(jìn)行解釋:
正如你所見,節(jié)點(diǎn)將有最大、最慢、最貴等標(biāo)簽。這將幫助你根據(jù) Postgres 的執(zhí)行方式來優(yōu)化查詢。
最后,如果在 Postgres 中建立能力不可行,我建議你問問像 Percona 這樣的數(shù)據(jù)庫咨詢公司。
鏈接:https://www.percona.com/
5. 欲速則不達(dá)
錯誤:看起來不錯嘛,讓我們交付吧!
教訓(xùn):
在這個快速行動、打破常規(guī)的時代,這似乎不是最受歡迎的建議,但是“慢慢來”會有回報的。與其快速發(fā)布糟糕的代碼,還不如有條不紊地來,發(fā)布幾乎沒有生產(chǎn) bug 的代碼。
優(yōu)秀工程師會考慮到軟件系統(tǒng)的所有問題。
鏈接:https://codesqueeze.com/the-7-software-ilities-you-need-to-know/
他們不僅關(guān)心代碼覆蓋率,還關(guān)心可能破壞相同代碼路徑的奇怪輸入。通過分層架構(gòu),它們可以實(shí)現(xiàn)模擬層,并只測試所考慮的層。他們不僅實(shí)現(xiàn)單元測試,而且還實(shí)現(xiàn)了集成和功能測試。如果你的團(tuán)隊還有 QA 工程師,就與他們一起測試這些用例。
子曰:“無欲速,無見小利。欲速則不達(dá),見小利則大事不成?!?/p>
6. 在自動化上投資
錯誤:我們手動部署到 staging 和沙箱,是臨時的。生產(chǎn)也是手工部署,但每天執(zhí)行一次。
教訓(xùn):擁有一個 CI/CD 系統(tǒng)管理部署意味著更可預(yù)測的結(jié)果。軟件以促銷策略在 pipeline 中移動,而臨時部署則被降級到特殊情況下。這可以確保你正交付軟件的穩(wěn)定性和可靠性,這是工程團(tuán)隊的主要責(zé)任。
投資:
- 培訓(xùn)團(tuán)隊成員學(xué)習(xí)如何進(jìn)行代碼審查。你的團(tuán)隊成員可能有各種各樣的技能,但不是每個人都知道如何進(jìn)行更好的 code review。因此,你應(yīng)在學(xué)習(xí)和教授 code review 的最佳實(shí)踐上進(jìn)行投資。
- 使用像 peril 和 hound 這樣的自動化 code review 系統(tǒng)。Peril 可以檢查代碼更改,并根據(jù)預(yù)先配置的設(shè)置,標(biāo)記警告和構(gòu)建失敗。例如,如果數(shù)據(jù)庫遷移文件缺少 statement_timeout 或包含不必要的 DEFAULT NULL,則 pull request 可能失敗。你可以編寫許多這樣的檢查和特定于團(tuán)隊的規(guī)則,并讓 Peril 成為更改的“看門人”。HoundCI 可以做類似的事情,而且規(guī)則是完全可配置的。
- 使用 CircleCI 之類的工具,通過自動推廣策略設(shè)置 CI/CD pipeline。隨著時間推移,優(yōu)化構(gòu)建和部署管道。
鏈接:https://circleci.com/
7. 掌握你的工具
錯誤:我需要找到這個實(shí)現(xiàn)接口,先搜索一下。我記得它以前就在這個文件夾里,現(xiàn)在卻不見了?在那個文件夾里找找,我還是問問別人吧!
教訓(xùn):不知道如何使用你的工具,這會讓你效率變低。你能想象一個邋遢的裁縫使用縫紉機(jī)的樣子嗎?這不僅關(guān)系到代碼結(jié)果,還關(guān)系到構(gòu)建軟件的效率。
了解你的工具,掌握捷徑。代碼編輯器可能是你要掌握的第一個工具。你應(yīng)該知道如何設(shè)置選項卡的排序、打開最后的編輯文件、顯示調(diào)用圖等。如果你使用基于文本的編輯器,而不是圖形用戶界面,這也可行。類似 Vim 這樣的編輯器,有很多實(shí)用技巧。
請注意手動執(zhí)行的常見操作,并學(xué)習(xí)如何通過快捷鍵來執(zhí)行這些操作。要做到這點(diǎn),一個簡單的方法是先記住 5 條捷徑,并熟練掌握它們,然后再記住 5 個捷徑。
全棧工程師每天接觸的其他常用工具有終端、docker、tableplus/pgadmin/ 一些其他數(shù)據(jù)庫客戶端用戶界面、Chrome 開發(fā)工具等。
8. 最小可行性產(chǎn)品(MVP)
錯誤:我覺得這個功能會很有用。我要使用分布式容錯復(fù)制高可用數(shù)據(jù)存儲。我還要構(gòu)建一個基于插件的架構(gòu),使這個軟件具有超強(qiáng)的可擴(kuò)展性。
教訓(xùn):在構(gòu)建某個東西前,請確保它是你要構(gòu)建的正確的東西。這就是 MVP 的用武之地。
理想的最小可行性產(chǎn)品(Minimum Viable Product,MVP)應(yīng)該盡可能少地觸及所有層面,而不僅僅是一個層。這是降低風(fēng)險的一種做法。最好是最低限度地構(gòu)建所有層,而不是完善單個層。最小可行性產(chǎn)品并不意味著技術(shù)債、糟糕的代碼或缺乏測試。它不是拋棄型代碼(throw-away code)。
如果最小可行性產(chǎn)品花的時間太長(在某種程度上),那么它就有可能是錯誤的方案,并且可能有更簡單的解決方案。
奧卡姆剃刀:在其他一切同等的情況下,較簡單的解釋普遍比較復(fù)雜的好。
9. 研究支持開發(fā)
錯誤:我(工程師)認(rèn)為這是我們應(yīng)該構(gòu)建的。
教訓(xùn):在開發(fā)前,應(yīng)該先進(jìn)行大量的研究以佐證。與其跟隨你的直覺,不如進(jìn)行一項用戶研究。要了解用戶需求,可以親自或者通過視頻采訪,進(jìn)行調(diào)查、查看日志等。這將幫助你更好地了解用戶。然后,你可以提出一個假設(shè)并進(jìn)行實(shí)驗(yàn)。當(dāng)形成一個假設(shè)時,請使用反演來駁斥自己的主張。
鏈接:https://fs.blog/2013/10/inversion/
在一個 A/B 測試框架上投資,可以讓你進(jìn)行實(shí)驗(yàn)。
時間寶貴,要明智使用。最聰明的工程師會嘗試優(yōu)化一些不應(yīng)該存在的東西。盡早提出正確問題非常重要。
10. 科學(xué)的調(diào)試
錯誤:有一個 bug。我想是因?yàn)榇a改變所致。讓我看看這個文件。沒準(zhǔn)也許是內(nèi)存問題所致。或者這兩個原因都有可能。
教訓(xùn):作為一名工程師,無論是作為事件一部分,還是在本地環(huán)境中,你都將調(diào)試軟件中的問題。如果不是通過結(jié)構(gòu)化推理來完成的話,調(diào)試可能會非常痛苦、緩慢。
我們?nèi)绾蜗到y(tǒng)找出程序失敗的原因?如果沒有“直覺”、“敏銳思維”等模糊的概念,我們又該怎樣才能做到這一點(diǎn)?我們想要找到一種查找失敗原因的方法——這種方法:
- 不需要先驗(yàn)知識
- 是有系統(tǒng)的
- 我們可以確定找到根本原因,并隨意復(fù)制
將科學(xué)方法應(yīng)用于調(diào)試問題,是發(fā)展失敗理論的公正方法??茖W(xué)調(diào)試的步驟如下:
- 重現(xiàn)錯誤(通常是一些時間、數(shù)據(jù)、用戶、操作系統(tǒng)、調(diào)試器的組合)
- 觀察事實(shí)(徹底讀取日志、錯誤跟蹤等)
- 在日志中明確地陳述假設(shè),而不是在心里做假設(shè)
- 如果你發(fā)現(xiàn)程序中的某部分存在錯誤,使用結(jié)構(gòu)化方法來縮小錯誤范圍,如二分搜索
- 測試假設(shè):使用日志、斷點(diǎn)、斷言
- 如果通過驗(yàn)證,應(yīng)用修復(fù)并確保沒有新錯誤
- 如果無效,請重復(fù)步驟 3 到步驟 6
對簡單的調(diào)試情況來說,這可能看起來有點(diǎn)過頭。但是,對于涉及多個團(tuán)隊的復(fù)雜分布式系統(tǒng)而言,一個系統(tǒng)科學(xué)的調(diào)試過程為消除模糊性提供必要的結(jié)構(gòu)。
11. 額外福利
(1)分享知識,服務(wù)他人
優(yōu)秀的行為是幫助他人成長。當(dāng)你需要用別人能理解的方式來解釋某事時,你對事情的理解會更清晰。
每天在 Slack 上分享有思想的鏈接,進(jìn)行演示、稱贊他人的積極行為,挑戰(zhàn)不明確的決定,并在你希望與某人或某項決定有著不同的方向時,給予建設(shè)性的反饋。你可以使用“感謝 ABC……希望 XYZ”的句式表達(dá)你的反饋。
通過這樣做,你可以為自己打造個人品牌,從而獲得職業(yè)資本。研究表明,那些擁有強(qiáng)大個人品牌、網(wǎng)絡(luò)形象和幫助他人的記錄的人,會取得成功,更重要的是,還會擁有令人滿意的職業(yè)生涯。
(2)塑造自己的世界
你無需接受這一現(xiàn)實(shí)世界。你可以通過坐在駕駛座上,塑造你所感知的世界。
這可能意味著在設(shè)計討論和 code reviews 期間發(fā)表意見,或者修復(fù)關(guān)鍵的不穩(wěn)定的測試(flaky test)。很多人會告訴你要多發(fā)言,提高老牌度,以便在公司內(nèi)部發(fā)展,但他們卻從來不告訴你怎樣才能做到這一點(diǎn)。要做到這一點(diǎn),最好的方法是擁有堅定的觀點(diǎn)和信心,將人們拉向你的方向。不要畏懼組建小型團(tuán)隊來構(gòu)建 / 改進(jìn)事物。不要屈服于你的恐懼。要大聲說出來,只要不是無禮的,你都可以說出來。
負(fù)面情緒是改變的巨大動力。如果有問題讓你感到困擾,你要捫心自問,并想出該如何進(jìn)行改變。如果你將每一天都當(dāng)作成長的途徑,那么生活就會成為一種鍛煉。
(3)結(jié)識朋友
如果你像我一樣,想弄清楚什么對你真正重要,那就去結(jié)識許多朋友吧,尤其是那些讓你感興趣的人。這可能意味著去參加會議、參加在線社區(qū)或者在黑客松活動和項目上進(jìn)行合作。這種接觸會幫你弄清楚你想要做什么。這樣,你就可以對那些無關(guān)緊要的事說“No”,并抓住對你來說重要的那些機(jī)會。
許多成功人士感到幸運(yùn),宣稱只是因?yàn)樗麄冊谝粋€正確的時間和正確的地點(diǎn)做了正確的事情而已,從而知道自己想從什么開始。這讓他們能隨機(jī)應(yīng)變,抓住機(jī)會,減少遺憾。遇到聰明人時,不要輕易拒絕。
通過這樣做,我發(fā)現(xiàn)我更喜歡的是廣度而不是深度,更看重創(chuàng)造力和自由,喜歡多樣化和非正式的關(guān)系。我不適合從事結(jié)構(gòu)化的重復(fù)性工作、例行公事、穩(wěn)定和安全的事情。
如果你知道你想要什么,世界會給你所需的信息。
全棧編程充滿樂趣。這是一個不斷發(fā)展的領(lǐng)域,有一片學(xué)習(xí)沖浪的海洋。不要把自己或錯誤看得太重。分享它們,不斷成長。
網(wǎng)頁題目:干了10年軟件工程師,我學(xué)到10個教訓(xùn)
文章鏈接:http://m.fisionsoft.com.cn/article/djgodgp.html


咨詢
建站咨詢
