成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我從資深軟件工程師學(xué)到的避坑大法

開發(fā) 開發(fā)工具
本文是彭博社的一位開發(fā)者所寫的文章,介紹了從一位資深工程師同事的身上學(xué)到的一些開發(fā)經(jīng)驗。

過去一年中,我坐在一位資深的軟件工程師旁邊,可以仔細(xì)地觀察他是怎么工作的。我們兩人經(jīng)常共同編程,使得這項觀察更為容易。此外,在團(tuán)隊文化中,從背后窺探寫代碼的人并不令人反感。以下是我所學(xué)到的:

一、編寫代碼

1. 如何命名

我首先著手的是 React UI。我們有一個主要組件來放置其他所有的組件。我喜歡在代碼里加點幽默感,因此我想要將它命名為 GodComponent。當(dāng)進(jìn)入代碼審查環(huán)境的時候,我才明白為什么命名這么難。

在計算機科學(xué)里有兩個難題:內(nèi)存不足、命名、以及差一(off-by-one)錯誤。

——Leon Bambrick

我每個命名的代碼段都有隱藏含義在里面。GodComponent 是所有我不必費心去尋找合適位置來存放那些垃圾的地方,它可以容納所有東西。如果我早早把它命名為 LayoutComponent,之后的我就會發(fā)現(xiàn)它所做的就是分配 layout,沒有狀態(tài)。

我發(fā)現(xiàn)命名好的另一個好處是:如果它看起來太長了,就像 LayoutComponent 包含了很多業(yè)務(wù)邏輯層,我就知道是時候要重構(gòu)了,因為業(yè)務(wù)邏輯層并不屬于這里。如果是以 GodComponent 命名,這里的業(yè)務(wù)邏輯層也不會和其他有所區(qū)別。

命名你的集群?以在服務(wù)器上運行的服務(wù)名稱來命名更好,直到用它們來運行其他服務(wù)為止。我們最終以團(tuán)隊的名字來命名服務(wù)器。

在函數(shù)上也是同樣的道理。doEverything() 是一個糟糕的名字,會有很多難以預(yù)料的后果。如果這個函數(shù)能夠做所有事情,那么在測試函數(shù)某個特定部分時將變得非常困難。因為不管這個函數(shù)有多大,你都不會覺得奇怪,畢竟這個函數(shù)應(yīng)該做所有的事情。這時候就需要改名、重構(gòu)了。

有意義的命名也有不太好的一面。如果名字的表意太強,結(jié)果掩蓋了一些功能上的細(xì)微差別怎么辦?例如:當(dāng)你在 SQLAlchemy 中調(diào)用 session.close() 時,這只會關(guān)閉會話但不會關(guān)閉底層數(shù)據(jù)庫的連接。

在這種情況下,可以以 x,y,z 來命名而不是 count(),close(),insertIntoDB(),這樣可防止為其賦予隱性含義并強制開發(fā)人員仔細(xì)檢查它所執(zhí)行的操作。

2. 歷史代碼和下一名開發(fā)者

你曾否看過一些代碼,覺得它們很奇怪?這些代碼為什么這么做呢?它們的實現(xiàn)一點都不合理。

我曾負(fù)責(zé)過遺留代碼庫。代碼中有諸如「當(dāng) Mohammad 發(fā)現(xiàn)情況時取消注釋代碼」這類的注釋。這是在做什么?誰是 Mohammad?

在這里可以做下角色轉(zhuǎn)換——想象下一個人來看我的代碼,他們是否會覺得奇怪?

同行審查可以某種程度上解決代碼注釋這個問題。這讓我想到了上下文的概念:注意我團(tuán)隊正處的上下文位置。

如果我忘記了這部分代碼,之后又回到了代碼工作上,沒有注釋的話我不能重新創(chuàng)建上下文,我可能只會想:「為什么他們要這么寫?這沒有任何意義……哦,等等,是我寫的。」

這里就是開發(fā)文檔和注釋該出現(xiàn)的地方。

3. 文檔和注釋

文檔和注釋有助于維護(hù)上下文和分享知識。

正如李在《如何構(gòu)建好軟件》中所說,「軟件的主要價值不是編寫它的代碼,而是編寫它的人所積累的知識。」

比如說,我們有個似乎沒有人用過的、面向隨機客戶端的 API 終端。因為這些原因,我就應(yīng)該把它刪除嗎?畢竟這是一個技術(shù)累贅。

如果說,在某個特定國家,有 10 名記者會一年一次將他們的報道發(fā)送到這個終端,怎么辦?你如何測試它?如果沒有開發(fā)文檔(那時就沒有)就不能測試。所以我們沒有測試。我們刪除了那個終端。過了幾個月后,到了一年中發(fā)送的時間,因為這個終端已經(jīng)不存在了,10 名記者也就無法發(fā)送這 10 份重要報告。

雖然熟悉產(chǎn)品的人已經(jīng)離開了團(tuán)隊,但是現(xiàn)在代碼中有注釋解釋終端的作用。

據(jù)我所知,文檔是每個團(tuán)隊都在努力的東西。不僅僅是代碼的文檔,還有關(guān)于代碼的流程。

4. 自信地刪掉垃圾代碼

我過去很不喜歡刪除垃圾代碼或過時的代碼。我認(rèn)為過去寫的代碼都是神圣的。我的想法是:「他們寫這些代碼的時候肯定有一些想法。」這是傳統(tǒng)和文化與第一性原則之間的碰撞,與刪除一年一次的終端發(fā)生的事相同。我在那里學(xué)到了詳細(xì)的一課。

我嘗試基于已有代碼進(jìn)行工作,但是資深工程師會嘗試解決掉它——全部刪除。一個永遠(yuǎn)無法到達(dá)的 if 聲明?一個不應(yīng)該調(diào)用的函數(shù)?是的,都消失了。

至于我呢?我只會把我的函數(shù)寫在最上面。我沒有減少這些技術(shù)累贅,反而增加了代碼的復(fù)雜程度,以及誤導(dǎo)別人的可能。下一個人將事情拼湊起來會更困難。

現(xiàn)在我受到的啟發(fā)是:有一些代碼你可能不理解,也有一些代碼你知道永遠(yuǎn)不會用。刪除那些你永遠(yuǎn)都不會用的代碼,小心那些你不理解的代碼。

5. 代碼審查

代碼審查對學(xué)習(xí)來說非常有用。這是你寫代碼和其他人寫代碼時進(jìn)行的外部反饋循環(huán)。

兩種實現(xiàn)有什么區(qū)別呢?一種方法比另一種好嗎?每次代碼審查時我都問自己:「他們?yōu)槭裁催@樣做?「。每當(dāng)我找不到合適的答案時,我就會去和他們談?wù)劇?/p>

在第一個月后,我開始在同事的代碼中找到錯誤(就像他們對我代碼做的一樣)。同行審查對我來說變得更有趣了——這是我期待的游戲——一個提高我代碼意識的游戲。

我的啟發(fā)是:在理解代碼如何實現(xiàn)前不要批準(zhǔn)它。

二、測試

我非常喜歡測試,以至于如果沒有測試就將代碼寫入代碼庫我會感到非常不舒服。

如果整個應(yīng)用程序只做一件事(就像我所有的學(xué)校項目),那么手動測試是可以的。但是如果該應(yīng)用程序可完成 100 種不同的功能,那該怎么辦呢?我不想花半個小時來測試所有的功能,何況有時候還會忘記一些需要測試的地方。

所以就出現(xiàn)了自動化測試。

我認(rèn)為測試是一種文檔,是對代碼假設(shè)的文檔。測試會告訴我(或我之前的人)他們預(yù)想代碼是如何工作的,以及他們預(yù)期哪里會出錯。

所以,當(dāng)寫測試時,我會記住:

  • 記錄如何使用測試時用到的類/函數(shù)/系統(tǒng)。
  • 記錄我所想到的會出錯的地方。

在大多數(shù)情況下,以上的結(jié)論是在我在測試而不是實現(xiàn)的過程中想到的。

以下是我在 Google 衛(wèi)生間小休時學(xué)到的例子:

  • 我在 #2 中遺漏了一些東西,那里是 bug 出現(xiàn)的地方;
  • 所以每當(dāng)發(fā)現(xiàn) bug 時,確保修復(fù) bug 的代碼也有相應(yīng)的測試(稱為回歸測試),用于記錄信息:這里可能出現(xiàn)另一種錯誤。

僅僅編寫這些測試并不能提高我代碼的質(zhì)量,而編寫代碼卻可以。但是我從閱讀測試代碼中獲得了寫更好代碼的直覺。

但是,并不只有這一種測試,這就是為什么有部署環(huán)境測試的原因。

你可以有完美的測試單元,但是如果沒有系統(tǒng)測試,就會出現(xiàn)以下的情況:

[[275640]]

這同樣適用于已經(jīng)測試好的代碼:如果你機器上沒有你需要的庫,你會崩潰。

為了測試你需要:

  • 有一臺你用于開發(fā)的機器;
  • 有一臺你用于測試的機器;
  • 最后,有一臺你部署的機器(請不要用與開發(fā)程序使用同一臺)。

如果測試和部署機器之間的環(huán)境不匹配,你就遇到麻煩了。所以這里就出現(xiàn)了部署環(huán)境。

  • 我們先有本地開發(fā)環(huán)境,在我的機器上是 docker;
  • 然后有服務(wù)器上的開發(fā)環(huán)境,機器上安裝了一系列的庫(和開發(fā)工具),我們在安裝了代碼的機器上進(jìn)行開發(fā)。其他相關(guān)依賴的測試都可以在這里進(jìn)行;
  • 接下來是 beta/stage 環(huán)境,它與生產(chǎn)環(huán)境完全一樣;
  • 最后是生產(chǎn)環(huán)境,它是代碼運行和服務(wù)于實際客戶的機器上的環(huán)境。

這里的想法是嘗試捕獲單元和系統(tǒng)測試無法捕獲的錯誤。例如,請求系統(tǒng)和響應(yīng)系統(tǒng)之間的 API 不匹配。個人項目與小公司的情況大不一樣。不是每個人都有資源來搭建自己的設(shè)備。然而,這個想法仍適用于像 AWS 和 AZURE 這樣的云供應(yīng)商。

你可以為開發(fā)和生產(chǎn)設(shè)置分開的集群。AWS ECS 使用 docker 鏡像來部署,所以即使跨環(huán)境事情也會相對平穩(wěn)。棘手的一點是其他 AWS 服務(wù)之間的集成。你是否可以在正確的環(huán)境中調(diào)用正確的終端呢?

你甚至可以更進(jìn)一步:下載其他 AWS 服務(wù)的備用容器鏡像并使用 docker-compose 來配置本地完整的環(huán)境。它會加速反饋循環(huán)。

三、設(shè)計

為什么我要將設(shè)計放到寫代碼和測試的后面呢?設(shè)計本應(yīng)該在第一位,但是如果我沒有在環(huán)境中寫代碼和測試,我可能會不擅長設(shè)計一個遵循環(huán)境特性的系統(tǒng)。

在設(shè)計系統(tǒng)時,有很多事情需要考慮:

  • 使用編號是多少?
  • 有多少用戶?預(yù)期增長是多少?(即需要使用多少數(shù)據(jù)行)
  • 未來可能出現(xiàn)的問題是什么?

我需要把它轉(zhuǎn)成一個名為「需求收集」的合理清單。這個過程有點與靈活性的原則相悖——在開始系統(tǒng)開發(fā)之前,你可以設(shè)計多少部分呢?但是這是一種平衡——你需要選擇什么時候做什么。當(dāng)然僅僅收集需求并不是所有需要考慮的事情。我認(rèn)為,在設(shè)計中包含了開發(fā)的過程也是值得去做的。例如:

  • 本地開發(fā)如何運作?
  • 怎么打包和部署?
  • 如何進(jìn)行端對端的測試?
  • 怎么對新的服務(wù)進(jìn)行壓力測試?
  • 怎么管理機密信息?
  • CI/CD 集成?

我們最近為 BNEF 開發(fā)了一個新的搜索系統(tǒng)。做這件事真的很棒。我開始設(shè)計本地開發(fā),學(xué)習(xí) DPKG(打包和部署)和試圖解決部署機密信息的問題。

誰會想到對產(chǎn)品中的機密信息進(jìn)行部署會變得如此棘手呢?

  • 你不能將這些信息存到代碼中,因為這樣任何人都能看得到。
  • 把它們作為環(huán)境變量?這是一個好主意。但你怎么把它們放在那里?(每次機器啟動時訪問 PROD 機器來填充環(huán)境變量是一件痛苦的事情)
  • 部署為機密文件?文件從哪里來呢?怎么進(jìn)行填充呢?

而且我們不想進(jìn)行手動操作。

最后我們使用了一個有角色訪問控制的數(shù)據(jù)庫(只有我們的機器可以與數(shù)據(jù)庫對話)。我們的代碼在啟動時從這個數(shù)據(jù)庫中獲取秘密數(shù)據(jù)。這個能在開發(fā)、測試和產(chǎn)品之間很好地復(fù)制——在各自的數(shù)據(jù)庫中都有機密。

同樣的,對于像 AWS 這樣的云供應(yīng)商,這可能非常不同。你不必考慮太多機密。獲取你角色賬戶,在用戶界面中輸入機密數(shù)據(jù),在需要的時候你的代碼會找到它們。它簡化了很多時間,這非常酷,而我很高興有經(jīng)驗領(lǐng)會這種簡易性。

設(shè)計時考慮維護(hù)需求:

設(shè)計系統(tǒng)是件令人興奮的事。維護(hù)系統(tǒng)呢?就沒那么有趣了。

我在維護(hù)過程中遇到了這個問題:系統(tǒng)為什么會降級,以及如何降級?

有兩個原因可以解答為什么系統(tǒng)也會有降級的時候:

  • 首先,系統(tǒng)不應(yīng)當(dāng)舍棄舊的東西,而是在已有的基礎(chǔ)上增加更多功能。系統(tǒng)更新傾向于增加而不是刪除。
  • 其次,帶著最終目標(biāo)來設(shè)計。一個進(jìn)化到做不該做的事情的系統(tǒng)和一個從零來設(shè)計做同樣事情的系統(tǒng)一樣,沒有用。這是一種系統(tǒng)的倒退。因此需要對系統(tǒng)進(jìn)行降級。

現(xiàn)在我知道至少三種降低降級機率的方法:

  • 將業(yè)務(wù)邏輯和基礎(chǔ)設(shè)施分開:通常是對基礎(chǔ)設(shè)施降級——當(dāng)使用量增加、框架過時、出現(xiàn)零日漏洞等情況下;
  • 圍繞系統(tǒng)維護(hù)建立流程。對舊的和新的組件都使用相同的更新。這可以防止組件之間出現(xiàn)差異,保持整個代碼「現(xiàn)代化」;
  • 確保一直修剪你不想要的/舊的東西。

四、部署

將功能進(jìn)行捆綁部署還是逐個部署呢?如果答案是將功能捆綁在一起,則會出現(xiàn)問題。

接下來要問的問題是:為什么想要把功能進(jìn)行捆綁呢?

  • 部署是否花費過多時間?
  • 代碼審查是否容易進(jìn)行?

不管是什么原因,這是需要修復(fù)的流程瓶頸。

捆綁功能部署至少有兩個問題:

  • 如果一個功能中有 bug,將妨礙另一個功能執(zhí)行;
  • 增加整體出錯的風(fēng)險。

然后,無論你選擇什么部署過程,你總是希望你的機器像一頭牛而不是像寵物一樣。它們并不珍貴。你知道每臺機器上運行的是什么,以及如何在死機的情況下重新創(chuàng)建它們。當(dāng)一臺機器死機時,你不會心煩意亂,你只需要啟動一臺新機器。你像牛一樣放養(yǎng)它們,而不是像寵物一樣養(yǎng)著他們。

五、程序出錯的時候

當(dāng)事情出錯時,而且一定會有出問題的時候,黃金法則是將對客戶的影響最小化。

當(dāng)事情出了差錯,我自然傾向于趕快解決 bug。事實證明,這并不是最理想的解決方案。與其修復(fù)哪里錯了,即使只是「修改一行」,所做的第一件事應(yīng)該是回滾版本。回到之前的工作狀態(tài),這是讓客戶恢復(fù)工作最快的方法。

過了這個時候,才應(yīng)該看看哪里出了問題并修復(fù)那些 bug。

在你的集群中出現(xiàn)一臺「垮掉」的機器也應(yīng)當(dāng)是同樣的做法——在試圖找出機器出了什么問題之前,先把它停了,并標(biāo)記它不可用。

首先找 bug 這種本能會引導(dǎo)我走上解決 bug 的漫長旅途,反而偏離了讓客戶先恢復(fù)工作這一理想的目標(biāo)狀態(tài)。有時候,我覺得它沒有工作的原因是因為寫的代碼有問題,而仔細(xì)閱讀每一行代碼后會陷入混亂,像是一種深度優(yōu)先搜索。

之后,我的啟發(fā)是,首先開始廣度優(yōu)先搜索,然后再深度優(yōu)先搜索,去除最頂端的節(jié)點。能否用已有的資源確認(rèn):

  • 機器啟動了嗎?
  • 是否安裝了正確的代碼?
  • 配置是否正確?
  • <代碼特定配置>,像代碼中的路由是否正確?
  • 模式版本是否正確?
  • 然后進(jìn)入代碼。

在某次出錯的問題上,我們以為機器上沒有正確安裝 nginx,但結(jié)果是配置被設(shè)置為了 false。

當(dāng)然,我不需要總是這樣做。有時候錯誤信息已經(jīng)足以減少需要搜索代碼的區(qū)域。而且當(dāng)我無法解決這個問題時,我嘗試并持續(xù)修改代碼以將問題降到最低。修改的次數(shù)越少,我就能越快地處理實際問題。

但是我現(xiàn)在還是會記錄花了 1 個多小時來解決的 bug:遺漏了什么?這通常是一些我忘記檢查的愚蠢錯誤,比如像設(shè)置路由、確保模式版本和服務(wù)版本匹配等。這是熟悉使用的技術(shù)堆棧的另一步,而且只有經(jīng)驗會告訴我為什么系統(tǒng)無法運行。

六、監(jiān)控

這是我以前從未想過去做的事。說句公道話,在全職編碼之前,我從沒維護(hù)過系統(tǒng)。我只是搭建它們,使用 1 個星期后然后進(jìn)行下一項工作。

有兩個系統(tǒng),一個有良好的監(jiān)控,另一個并不那么好。我逐漸非常喜歡監(jiān)控。如果我不知道 bug 在哪我就不能修改錯誤。其中一種最糟糕的感覺是從客戶那里知道有 bug。

「我做了什么?!我甚至不知道我的系統(tǒng)出了什么問題?」

我認(rèn)為監(jiān)控由 3 個部分組成——日志、衡量標(biāo)準(zhǔn)和警報。

1. 日志

以代碼中進(jìn)行日記記錄就像人寫日志一樣,是一個進(jìn)化的過程。

你要找到你可能需要監(jiān)控的東西,日志記錄下來,運行系統(tǒng)。一段時間后,你會發(fā)現(xiàn)你沒有足夠信息來解決的 bug。這是增強日志記錄的好時機——你的代碼少了些什么?

我想你會憑直覺地知道什么東西很重要需要記錄,但是在我們的服務(wù)器中我和資深軟件工程師所記錄的東西有很多不同。我認(rèn)為只要請求-相應(yīng)日志就足夠了,但是他會有更多的記錄內(nèi)容,比如查詢執(zhí)行時間、代碼進(jìn)行的一些特定的內(nèi)部調(diào)用,以及何時轉(zhuǎn)儲日志。一切都已經(jīng)解決了。

幾乎不可能在沒有日志的情況下進(jìn)行調(diào)試——如果你不知道系統(tǒng)的狀態(tài),你怎么重新創(chuàng)建它呢?

2. 衡量標(biāo)準(zhǔn)和驚爆

衡量標(biāo)準(zhǔn)可以源于日志,也可以獨立于日志(例如向 AWS CloudWatch 和 Grafana 發(fā)送時間)。你可以決定你的衡量指標(biāo)并在代碼運行時發(fā)送數(shù)字。

警報是把所有東西整合到一個的強大監(jiān)控系統(tǒng)的粘合劑。如果一個衡量標(biāo)準(zhǔn)是當(dāng)前產(chǎn)品中運行的機器數(shù)量,當(dāng)這個數(shù)字降到 50% 時,這是一個很好的警報——你知道有什么出錯了。

失敗計數(shù)高于某個閾值時?是的,又一個警報。

這里暗示了另一個需要養(yǎng)成的習(xí)慣。當(dāng)你修復(fù) bug 時,你不僅僅關(guān)注如何修復(fù) bug,而是你為什么不早點發(fā)現(xiàn)它呢?是否有布置警報?如何能夠更好地監(jiān)控來避免類似的問題?

我還不知道如何監(jiān)控 UI。即使吧組件測試到位,也還不足以了解出錯的情況。這些錯誤通常是由客戶來告訴我們的——這看起來不太對勁。

七、總結(jié)

在過去的一年里,我學(xué)到了很多東西。當(dāng)我對這篇文章進(jìn)行回顧時,我能夠更好地體會到我的成長。希望你也可以從這里得到一些東西!

原文鏈接:https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html#when-things-go-wrong

【本文是51CTO專欄機構(gòu)“機器之心”的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】 

戳這里,看該作者更多好文

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2014-09-05 13:37:29

程序員

2020-03-16 14:25:57

軟件開發(fā) 經(jīng)驗

2019-10-08 11:17:20

開發(fā)者技能工具

2015-08-25 09:15:24

ceo程序員軟件工程師

2015-08-25 10:24:55

CEO軟件工程師技能

2013-08-19 14:27:49

2011-12-30 09:40:28

2014-12-22 10:09:50

工程師

2021-04-12 15:21:15

HarmonyOS物聯(lián)網(wǎng)開發(fā)者

2013-09-03 09:30:44

軟件工程師軟件工程師頭銜

2022-09-16 08:00:00

軟件工程師求職薪酬

2024-03-11 13:36:53

2012-08-27 09:40:07

2009-02-11 13:15:54

軟件工程師女工程師google

2022-07-29 09:12:44

軟件硬件開發(fā)

2009-06-29 10:20:25

搬運工軟件工程師

2022-01-16 07:12:30

軟件工程師吵架開發(fā)

2023-06-05 10:07:13

軟件工程平臺工程師

2018-01-09 17:21:18

軟件工程師創(chuàng)業(yè)代碼

2021-04-22 09:00:00

軟件工程師代碼
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久久久久国产精品免费免费狐狸 | 国产九九精品 | 国产精品av久久久久久久久久 | 日韩成人免费视频 | 一区二区三区国产视频 | 欧美在线观看一区二区 | 在线亚洲人成电影网站色www | 日日骚av| 自拍视频网站 | 色又黄又爽网站www久久 | 亚洲成人自拍 | 精品国产一区二区三区久久久久久 | 免费观看av | 午夜精品一区二区三区在线播放 | 日韩精品一区二区三区在线 | 久久精品国产一区二区三区不卡 | 欧美阿v| 国产精品久久久久久久久久免费看 | 91视频18 | 欧美性受xxxx | 国产成人精品综合 | 日韩国产欧美 | 一区二区av | 国产日韩欧美电影 | 在线观看欧美一区 | 久久精品国产v日韩v亚洲 | 成人av在线播放 | 黄视频国产 | 色桃网 | 91视频免费视频 | 中文字幕亚洲区一区二 | 偷拍自拍网址 | 日韩视频在线一区二区 | 久久精品国产免费高清 | 中文字幕成人av | 在线看av的网址 | 国产精品美女久久久久aⅴ国产馆 | 国产高清精品在线 | 亚洲精品色 | 激情黄色在线观看 | 亚洲精品在线观看视频 |