日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

別糾結(jié),提高代碼整潔度也沒那么難

作者 | Jonathan Fulton

譯者 | 彎月,責(zé)編 | 屠敏

頭圖 | CSDN 下載自東方 IC

出品 | CSDN(ID:CSDNnews)

以下為譯文:

幾年前,我們?cè)龅竭^重大的代碼質(zhì)量問題:大多數(shù)文件中的邏輯糾纏夾雜、大量重復(fù)、沒有測試。無論是編寫新功能還是修復(fù)很小的bug都需要付出嘔心瀝血的代價(jià),常常氣到你吐血。令我們苦不堪言。

別糾結(jié),提高代碼整潔度也沒那么難

如今,我們的代碼庫的整體質(zhì)量明顯提高了,這在很大程度上要?dú)w功于我們?yōu)樘岣叽a質(zhì)量而做出的不懈努力。幾年前,在發(fā)現(xiàn)代碼質(zhì)量問題后,我們整個(gè)團(tuán)隊(duì)一起閱讀了Robert Martin的《代碼整潔之道》,然后竭盡全力貫徹了他的建議,甚至引入了“清潔規(guī)范”作為工程團(tuán)隊(duì)的核心文化。如果你打算擴(kuò)張團(tuán)隊(duì),那么我強(qiáng)烈建議你現(xiàn)在就開始實(shí)施這兩項(xiàng)措施。從長遠(yuǎn)來看,恰當(dāng)?shù)貙?shí)施“干凈的代碼”實(shí)踐可以提高一倍生產(chǎn)力,并顯著提高工程團(tuán)隊(duì)的士氣。有了選擇,誰還會(huì)愿意進(jìn)入上圖右邊那個(gè)Bad code的房間呢?

在我們實(shí)施的“清潔規(guī)范”以及其他想法之中,有四項(xiàng)措施將團(tuán)隊(duì)的生產(chǎn)力和幸福指數(shù)提高了80%。

  1. 沒有經(jīng)過測試的代碼一概不安全。

    你需要編寫大量測試,尤其是單元測試,否則你會(huì)追悔莫及。

  2. 選擇有意義的名稱。

    為變量、類和函數(shù)選擇言簡意賅的名稱。

  3. 類與函數(shù)保持最小,遵守單一功能原則

    函數(shù)不應(yīng)超過4行,而類不應(yīng)超過100行。是的,你沒看錯(cuò)。而且它們應(yīng)該只做一件事。

  4. 函數(shù)不能有副作用

    副作用(例如,修改輸入?yún)?shù))是有害的。請(qǐng)確保你的代碼中沒有副作用。盡可能在函數(shù)聲明中明確規(guī)定這一點(diǎn)(例如,傳入基本類型,或者傳遞沒有setter的對(duì)象)。

下面我們來詳細(xì)介紹上述每一點(diǎn),幫助你理解并應(yīng)用到工程團(tuán)隊(duì)的日常工作中。

別糾結(jié),提高代碼整潔度也沒那么難

 

沒有經(jīng)過測試的代碼一概不安全

每當(dāng)遇到原本應(yīng)該在測試捕捉到的bug時(shí),我就會(huì)對(duì)我們的工程師重復(fù)這句話。除非你建立了測試的文化,否則你也會(huì)一次又一次地引用這句話。你需要編寫大量測試,尤其是單元測試。認(rèn)真考慮集成測試,并確保你的測試用例足夠涵蓋核心業(yè)務(wù)功能。請(qǐng)記住,如果有一段代碼沒有被測試覆蓋到,那么將來肯定會(huì)出問題,而且你根本意識(shí)不到,直到被你的客戶發(fā)現(xiàn)。

你需要一遍又一遍地向團(tuán)隊(duì)成員重復(fù)這句話:“沒有經(jīng)過測試的代碼一概不安全”,直到這句話在每個(gè)人的心里生根。無論你是剛畢業(yè)的新手軟件工程師還是經(jīng)驗(yàn)豐富的資深軟件工程師,都應(yīng)該時(shí)刻履行這個(gè)實(shí)踐。

別糾結(jié),提高代碼整潔度也沒那么難

 

選擇有意義的名稱

計(jì)算機(jī)科學(xué)界有兩大難題:緩存失效和命名。

可能你曾聽過這句話,這與工程團(tuán)隊(duì)的日常工作有著莫大的關(guān)系。如果你和你的團(tuán)隊(duì)成員不擅長代碼中的命名,那么你們的維護(hù)工作就會(huì)變成一場噩夢(mèng),而且你將一事無成。你會(huì)失去最優(yōu)秀的開發(fā)人員,而且你的公司距離倒閉也不遠(yuǎn)了。

這個(gè)問題非常嚴(yán)重,你不應(yīng)該使用諸如data、foobar或myNumber之類不恰當(dāng)?shù)淖兞棵乙步^對(duì)不能將SomethingManager作為類名稱。務(wù)必使用言簡意賅的名稱,確保在發(fā)生沖突時(shí)能準(zhǔn)確找到。良好的命名不僅可以大幅提高開發(fā)人員的效率,而且還可以通過IDE的快捷方式“按名稱查找” 等輕松查找文件。另外,良好的命名需要通過嚴(yán)格的代碼審核貫徹。

別糾結(jié),提高代碼整潔度也沒那么難

 

類與函數(shù)保持最小,遵守單一功能原則

這兩大原則的關(guān)系就像雞和雞蛋一樣,無論先有雞還是先有蛋,有了二者的因果輪回,才有我們無盡的美味。下面先來談?wù)勵(lì)惻c函數(shù)保持最小。

“小”對(duì)函數(shù)意味著什么?不超過4行代碼。是的,你沒看錯(cuò),就是4行。你可能現(xiàn)在就想告辭了,但是千萬別走。雖然這個(gè)數(shù)字看起來有些武斷,而且太少,你一輩子可能都沒寫過像這樣的代碼。但是,只有4行代碼的函數(shù)會(huì)強(qiáng)迫你認(rèn)真思考,并為子函數(shù)選擇真正的好名字,而這些子函數(shù)就是代碼最好的文檔。另外,4行代碼意味著你不會(huì)使用嵌套的IF語句,省得你需要耗費(fèi)大量腦力搞清楚所有的代碼路徑。

下面讓我們一起來看一個(gè)例子。Node有一個(gè)名為“build-url”的npm模塊,用途如其名所示:構(gòu)建URL。你可以通過這個(gè)鏈接(https://github.com/steverydz/build-url/blob/master/src/build-url.js)查看源文件。以下是相關(guān)代碼。

function buildUrl(url, options) { var queryString = ; var key; var builtUrl;
 if (url === ) { builtUrl = ''; } else if (typeof(url) === 'object') { builtUrl = ''; options = url; } else { builtUrl = url; }
 if (options) { if (options.path) { builtUrl += '/' + options.path; }
 if (options.queryParams) { for (key in options.queryParams) { if (options.queryParams.hasOwnProperty(key)) { queryString.push(key + '=' + options.queryParams[key]); } } builtUrl += '?' + queryString.join('&'); }
 if (options.hash) { builtUrl += '#' + options.hash; } }
 return builtUrl;};

請(qǐng)注意,此函數(shù)長35行。雖然理解起來也不是非常難,但如果我們應(yīng)用“小”原則來重構(gòu)輔助函數(shù),則會(huì)大大簡化。更新和改進(jìn)后的版本如下。

function buildUrl(url, options) { const baseUrl = _getBaseUrl(url); const opts = _getOptions(url, options);
 if (!opts) { return baseUrl; }
 urlWithPath = _AppendPath(baseUrl, opts.path); urlWithPathAndQueryParams = _appendQueryParams(urlWithPath, opts.queryParams) urlWithPathQueryParamsAndHash = _appendHash(urlWithPathAndQueryParams, opts.hash);
 return urlWithPathQueryParamsAndHash;};
function _getBaseUrl(url) { if (url ===  || typeof(url) === 'object') { return ''; } return url;}
function _getOptions(url, options) { if (typeof(url) === 'object') { return url; } return options;}
function _appendPath(baseUrl, path) { if (!path) { return baseUrl; } return baseUrl += '/' + path;}
function _appendQueryParams(urlWithPath, queryParams) { if (!queryParams) { return urlWithPath }
 const keyValueStrings = Object.keys(queryParams).map(key => { return `${key}=${queryParams[key]}`; }); const joinedKeyValueStrings = keyValueStrings.join('&');
 return `${urlWithPath}?${joinedKeyValueStrings}`;}
function _appendHash(urlWithPathAndQueryParams, hash) { if (!hash) { return urlWithPathAndQueryParams; } return `${urlWithPathAndQueryParams}#${hash}`;}

你會(huì)注意到,雖然我們沒有嚴(yán)格遵守每個(gè)函數(shù)4行的原則,但我們創(chuàng)建了幾個(gè)相對(duì)“較小”的函數(shù)。每個(gè)函數(shù)僅完成一項(xiàng)任務(wù),你可以根據(jù)函數(shù)名輕松理解這段代碼。如果需要,你甚至可以針對(duì)每個(gè)函數(shù)進(jìn)行單元測試,而不是只測試一個(gè)大型的buildUrl函數(shù)。你可能還會(huì)注意到,這種方法產(chǎn)生的代碼略多一些,從35行變成了55行。這完全可以接受,因?yàn)檫@55行代碼比原來的35行更加方便維護(hù)和閱讀。

如何才能編寫出這樣的代碼?我個(gè)人認(rèn)為,最簡單的方法是列出你希望逐步完成的各項(xiàng)任務(wù)。每一步都可以是建立某個(gè)子函數(shù)或輔助函數(shù)。例如,針對(duì)上述buildUrl函數(shù)我們希望完成如下工作:

  1. 初始化baseUrl和options

  2. 添加路徑(如果有的話)

  3. 添加查詢參數(shù)(如果有的話)

  4. 添加錨點(diǎn)(如果有的話)

請(qǐng)注意,上述每一步都可以直接轉(zhuǎn)化為子函數(shù)。一旦養(yǎng)成了這樣的習(xí)慣,你就可以使用這種自頂向下的方法編寫所有代碼,然后根據(jù)上述步驟列表,建立子函數(shù),再針對(duì)每個(gè)子函數(shù)繼續(xù)遞歸,創(chuàng)建步驟列表、建立子函數(shù),以此類推。

下面再來談?wù)剢我还δ茉瓌t。根據(jù)維基百科,單一功能原則的定義如下:

在面向?qū)ο缶幊填I(lǐng)域中,單一功能原則(Single Responsibility Principle)規(guī)定每個(gè)類都應(yīng)該有一個(gè)單一的功能,并且該功能應(yīng)該由這個(gè)類完全封裝起來。所有它的(這個(gè)類的)服務(wù)都應(yīng)該嚴(yán)密的和該功能平行(功能平行,意味著沒有依賴)。

在《代碼整潔之道》中,Robert Martin給出了另一個(gè)定義:

單一功能原則表明,類或模塊應(yīng)有且只有一條加以修改的理由。

假設(shè)我們正在建立一個(gè)需要某種報(bào)告以及顯示報(bào)告的系統(tǒng)。比較樸素的做法是構(gòu)建一個(gè)存儲(chǔ)報(bào)告數(shù)據(jù)以及用于顯示報(bào)告的邏輯模塊/類。但是,這違反了單一功能原則,因?yàn)樾薷脑擃惖母邔釉虺霈F(xiàn)了兩個(gè)。首先,如果報(bào)告字段發(fā)生變化,我們需要修改類;其次,如果報(bào)表可視化要求發(fā)生變化,我們也需要修改類。因此,我們不提倡利用一個(gè)類存儲(chǔ)數(shù)據(jù)和顯示數(shù)據(jù)的做法,我們應(yīng)該將這些概念和所有權(quán)區(qū)域劃分為兩個(gè)不同的類,例如ReportData和ReportDataRenderer等。

別糾結(jié),提高代碼整潔度也沒那么難

 

函數(shù)不能有副作用

副作用確實(shí)是罪惡之源,因?yàn)楦弊饔玫拇嬖冢帉憶]有錯(cuò)誤的代碼會(huì)非常困難。看看下面的例子,你能看出副作用嗎?

functiongetUserByEmailAndPassword(email, password) {  let user = UserService.getByEmailAndPassword(email, password); if (user) { LoginService.loginUser(user); //Log user in, add cookie (Side effect!!!!) } return user;}

根據(jù)函數(shù)名所示,這個(gè)函數(shù)的目的是通過電子郵件/密碼組合查找用戶,這是所有Web應(yīng)用程序的標(biāo)準(zhǔn)操作。然而,如果你沒有閱讀代碼的實(shí)現(xiàn),就不知道這個(gè)函數(shù)還有一個(gè)隱藏的副作用:在用戶登錄時(shí),創(chuàng)建一個(gè)登錄令牌,將其添加到數(shù)據(jù)庫中,然后將cookie發(fā)送給用戶,而用戶則“成功登錄”。

這中間有很多問題。

首先,不閱讀實(shí)現(xiàn)代碼就不知道該函數(shù)的功能/接口。即使你通過文檔說明該函數(shù)登錄的副作用,也仍然不是理想的做法。工程師喜歡使用現(xiàn)代IDE中的智能提示,因此當(dāng)遇到一個(gè)簡單的函數(shù)名時(shí),大部分人都不會(huì)閱讀相應(yīng)的文檔。他們會(huì)利用這個(gè)函數(shù)來獲取用戶對(duì)象,卻沒有意識(shí)到他們正在請(qǐng)求中添加Cookie,這可能會(huì)引發(fā)很多棘手且不易發(fā)現(xiàn)的bug。

其次,考慮到所有的依賴關(guān)系,測試這個(gè)函數(shù)相當(dāng)困難。你需要驗(yàn)證是否可以通過電子郵件/密碼順利找到用戶,需要模擬HTTP響應(yīng)以及登錄令牌的寫入。

第三,用戶查找和登錄之間的緊密結(jié)合必然無法滿足將來的所有用例,例如,你可能需要單獨(dú)查找用戶或登錄用戶。換句話說,這個(gè)函數(shù)不具有前瞻性。

別糾結(jié),提高代碼整潔度也沒那么難

 

總結(jié)

總的來說,你需要牢記以下四個(gè)提高代碼整潔度的原則,并通過這些原則提高團(tuán)隊(duì)的生產(chǎn)力:

  1. 沒有經(jīng)過測試的代碼一概不安全

  2. 選擇有意義的名稱

  3. 類與函數(shù)保持最小,遵守單一功能原則

  4. 函數(shù)不能有副作用

感謝您的閱讀!

原文:https://engineering.videoblocks.com/these-four-clean-code-tips-will-dramatically-improve-your-engineering-teams-productivity-b5bd121dd150

分享到:
標(biāo)簽:代碼
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定