自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

厭倦了混亂的代碼?掌握編寫干凈代碼庫的藝術(shù)

譯文
開發(fā)
本文提倡通過清晰的命名、模塊化、DRY原則、文檔、測(cè)試和協(xié)作來編寫干凈、可維護(hù)的代碼。

譯者 | 李睿

審校 | 重樓

對(duì)于入門的開發(fā)人員來說,雖然克服了最初的障礙,學(xué)會(huì)了編程,找到了理想的工作。但其編程旅程并沒有就此結(jié)束。他們面臨真正的挑戰(zhàn):如何編寫更好的代碼。這不僅僅是為了完善功能,還要編寫出經(jīng)得起時(shí)間考驗(yàn)的優(yōu)雅、可維護(hù)的代碼。

在設(shè)計(jì)糟糕的軟件系統(tǒng)中,開發(fā)人員在后臺(tái)就像迷失在一個(gè)沒有地圖導(dǎo)航的城市里一樣。這些系統(tǒng)往往笨重、低效且令人沮喪。

開發(fā)人員可以通過設(shè)計(jì)更好的以用戶為中心、高效、簡(jiǎn)單、靈活的系統(tǒng)來改變這種狀況。他們可以使用函數(shù)、變量、類和注釋來編寫“不要重復(fù)自己”(DRY)和模塊化的代碼,設(shè)計(jì)為人們服務(wù)的系統(tǒng),而不是相反。

因此開發(fā)人員的選擇是明確的:編寫賦能的代碼而不是阻礙的代碼,構(gòu)建讓開發(fā)人員茁壯成長(zhǎng)的代碼體系。

代碼庫的挑戰(zhàn)

想象一下,如果你是一名銷售主管,采用了一款新的應(yīng)用程序,旨在簡(jiǎn)化工作流程,并最大限度地提高潛在客戶的轉(zhuǎn)化率。這款應(yīng)用程序由SmartReach API提供支持,可以實(shí)時(shí)了解潛在客戶,并有可能獲得獎(jiǎng)勵(lì)。

但感覺這款應(yīng)用程序有些問題,其代碼缺乏清晰度和結(jié)構(gòu),引起了人們對(duì)其準(zhǔn)確性和功能的擔(dān)憂。分析代碼變成了一項(xiàng)令人困惑的任務(wù),阻礙了有效使用應(yīng)用程序的能力。

與其糾結(jié)于晦澀難懂的代碼行,不如以一種清晰而結(jié)構(gòu)化的方式來分解代碼。這將使開發(fā)人員能夠識(shí)別潛在的錯(cuò)誤,并確保應(yīng)用程序順利運(yùn)行,最大限度地提高生產(chǎn)力和獲得獎(jiǎng)勵(lì)的潛力。

class ApiCall {
 def getData(pn: Int, v: Int) = Action.async(parse.json) { request =>
 ws.url(s"https://api.smartreach.io/api/v$v/prospects?page=$pn")
 .addHttpHeaders(
 "X-API-KEY" -> "API_KEY"
 )
 .get()
 .flatMap(r => {
 if (r.status == 200) {
 Res.Success("Success!", (response.json \ "data").as[JsValue])
 } else {
 Res.ServerError("Error!",new Exception((response.json \ "message").as[String]))
 }

 })
   }
}

我們將重構(gòu)一個(gè)用Scala編寫但適用于一般編碼的示例銷售應(yīng)用程序。那么目標(biāo)是什么?將令人頭疼的混亂代碼變成一部清晰可讀的杰作。

以下分解重構(gòu)過程,解釋每個(gè)步驟并展示其積極影響。讓我們一起創(chuàng)造激勵(lì)和賦能的代碼!

代碼重構(gòu)

命名約定和代碼注釋

如今,我們都在關(guān)注快速消息,但在編寫代碼時(shí),這并不奏效。

為變量、類、函數(shù)和對(duì)象等使用清晰的名稱是非常重要的。如果讓同事幫助檢查或修改代碼,別忘了在代碼中編寫一些注釋。這可能看起來沒什么大不了的,但當(dāng)你或你的同事試圖解決出現(xiàn)的代碼問題時(shí),這些注釋將提供很大的幫助。

讓我們看看遵循這些規(guī)則之后編寫代碼的結(jié)果

class ProspectsApiGet {
 def getProspectListFromSmartReach(
 page_number: Int,
 version: Int
 ) = Action.async(parse.json) { request =>
 //public API of SmartReach to get the prospect list by page number
 //smartreach.io/api_docs#get-prospects
 ws.url(s"https://api.smartreach.io/api/v$version/prospects?page=$page_number") 
 .addHttpHeaders(
 "X-API-KEY" -> "API_KEY"
 )
 .get()
 .flatMap(response => {
 val status = response.status

 if (status == 200) { 
 //if the API call to SmartReach was success
   /*
 {
 "status": string,
 "message": string,
 "data": {
 "prospects": [*List of prospects*]
 }
 }
 */
 val prospectList: List[JsValue] = (response.json \ "data" \\ "prospects").as[List[JsValue]]
 Res.Success("Success!", prospectList)
 } else {
 // error message
 //smartreach.io/api_docs#errors
 val errorMessage: Exception = new Exception((response.json \ "message").as[String]) 
 Res.ServerError("Error", errorMessage) // sending error
 }
 })
 }
}

如果仔細(xì)觀察,錯(cuò)誤就會(huì)隱藏在代碼中! 對(duì)潛在客戶的分析不太正確。但是,通過提供更多的注釋和使用更好的名稱,可以避免這些錯(cuò)誤。

代碼庫組織和模塊化

直到現(xiàn)在都一切順利。編寫的代碼很好,應(yīng)用程序也很簡(jiǎn)單。既然代碼運(yùn)行良好并且更易于閱讀,那么讓我們來處理下一個(gè)挑戰(zhàn)。

考慮在這里引入一個(gè)篩選系統(tǒng)。這會(huì)讓事情變得更加復(fù)雜。我們真正需要的是一個(gè)更有組織的代碼結(jié)構(gòu)。

為了使其實(shí)現(xiàn)模塊化,我們將代碼分成更小的模塊。但是如何確定每個(gè)模塊的位置呢?

(1)目錄結(jié)構(gòu)

目錄是代碼的總部,本質(zhì)上是一個(gè)將所有內(nèi)容放在一起的文件夾。如果創(chuàng)建一個(gè)新文件夾,這樣就有了一個(gè)目錄。

在這個(gè)目錄中,可以存儲(chǔ)代碼文件或創(chuàng)建其他子目錄。在我們的例子中則選擇子目錄。將代碼分成四個(gè)部分:模型、數(shù)據(jù)訪問對(duì)象(DAO)、服務(wù)和控制器。

值得注意的是,目錄結(jié)構(gòu)可能會(huì)根據(jù)企業(yè)偏好或應(yīng)用程序的特定需求而有所不同。可以根據(jù)最適合企業(yè)或應(yīng)用的內(nèi)容來定制。

(2)模型

當(dāng)我們談?wù)摼幋a中的模型時(shí),本質(zhì)上是在談?wù)撚脕順?gòu)建和管理數(shù)據(jù)的框架。例如在這個(gè)例子的場(chǎng)景中,前景模型充當(dāng)了藍(lán)圖,概述了代表系統(tǒng)內(nèi)前景的特定特征和行為。

在這個(gè)模型中,我們定義了潛在客戶擁有的屬性——可能是姓名、聯(lián)系方式或任何其他相關(guān)信息。這不僅僅是存儲(chǔ)數(shù)據(jù),還是有關(guān)以一種對(duì)應(yīng)用程序有效地交互和操作有意義的組織方式。

case class SmartReachProspect(
 sr_prospect_id: Long, //id of the prospect in SmartReach database
 p_first_name: String,
 p_last_name: String,
 p_email: String,
 p_company: String,
 p_city: String,
 p_country: String,
 smartreach_prospect_category: String // Prospect category in SmartReach
 // can be "interested", "not_interested", "not_now", "do_not_contact" etc
 )

(3)數(shù)據(jù)訪問對(duì)象(DAO)

這個(gè)對(duì)象被恰當(dāng)?shù)孛麨閿?shù)據(jù)訪問對(duì)象(DAO),充當(dāng)從數(shù)據(jù)庫或第三方API獲取數(shù)據(jù)的橋梁。

避免在這些文件中添加復(fù)雜的邏輯是至關(guān)重要的;它們應(yīng)該只專注于處理輸入和輸出操作。當(dāng)我們談?wù)揑O操作時(shí),指的是與外部系統(tǒng)的交互,其中故障的可能性更高。因此,在這里實(shí)現(xiàn)保障措施對(duì)于處理意外問題至關(guān)重要。

在Scala編程語言中,我們利用Monad(特別是Futures)來有效地管理和處理潛在的故障。這些工具有助于捕獲和管理IO操作過程中可能發(fā)生的故障。

數(shù)據(jù)訪問對(duì)象(DAO)的主要目標(biāo)是從數(shù)據(jù)源檢索數(shù)據(jù),然后將其組織到適當(dāng)?shù)哪P椭?,以便進(jìn)一步處理和利用。

class SmartReachAPIService {
 def getSmartReachProspects(
 page_number: Int,
 Version: Int
 )(implicit ws: WSClient,ec: ExecutionContext): Future[List[SmartReachProspect]] = {
 //public API from SmartReach to get the prospects by page number
 //smartreach.io/api_docs#get-prospects
 ws.url(s"https://api.smartreach.io/api/v$version/prospects?page=$page_number") 
 .addHttpHeaders(
 "X-API-KEY" -> "API_KEY"
 )
 .get()
 .flatMap(response => {
 val status = response.status
 if (status == 200) { 
 //checking if the API call to SmartReach was success

 /*
 {
 "status": string,
 "message": string,
 "data": {
 "prospects": [*List of prospects*]
 }
 }
 */
 val prospects: List[SmartReachProspect] = (response.json \ "data" \\ "prospects").as[List[SmartReachProspect]]
 prospects
 } else {
 //error message
 //smartreach.io/api_docs#errors
 val errorMessage: Exception = new Exception((response.json \ "message").as[String]) 
 throw errorMessage
 }
 })
 }
}

(4)服務(wù)

這里是我們系統(tǒng)的核心——業(yè)務(wù)邏輯位于這一層。在這里將實(shí)現(xiàn)一種篩選機(jī)制,展示如何毫不費(fèi)力地在這部分代碼庫中引入額外的功能。

這個(gè)部分編排驅(qū)動(dòng)應(yīng)用程序的核心操作和規(guī)則。在這里,根據(jù)業(yè)務(wù)需求定義應(yīng)該如何處理、操作和轉(zhuǎn)換數(shù)據(jù)。添加新特性或邏輯變得相對(duì)簡(jiǎn)單,可以輕松地?cái)U(kuò)展和增強(qiáng)系統(tǒng)的功能。

class SRProspectService {
 val smartReachAPIService = new SmartReachAPIService
 def filterOnlyInterestedProspects(
 prospects: List[SmartReachProspect]
 ): List[SmartReachProspect] = {
 prospects.filter(p => p.prospect_category == "interested")
 }
 def getInterestedProspects(
 page_number: Int,
 version: Int
 )(implicit ws: WSClient,ec: ExecutionContext): Future[List[SmartReachProspect]] = {
 val allProspects: Future[List[SmartReachProspect]] = smartReachAPIService.getSmartReachProspects(page_number = page_number, version = version)
 allProspects.map{list_of_prospects => 
 filterOnlyInterestedProspects(prospects = list_of_prospects)
 }
 }
}

(5)控制器

在這一層,我們與API建立直接連接——這一層充當(dāng)網(wǎng)關(guān)。

它充當(dāng)接口,通過我們的API接收來自前端或第三方用戶的請(qǐng)求。在接到這些請(qǐng)求之后,收集所有必要的數(shù)據(jù),并在處理后處理響應(yīng)。

保持關(guān)注點(diǎn)分離是至關(guān)重要的。因此避免在這個(gè)層中實(shí)現(xiàn)邏輯。與其相反,該層側(cè)重于管理傳入請(qǐng)求流,并將它們引導(dǎo)到實(shí)際處理和業(yè)務(wù)邏輯發(fā)生的適當(dāng)服務(wù)層。

class ProspectController {
 val prospectService = new SRProspectService
 def getInterestedProspects(
 page_number: Int
 ) = Action.async(parse.json) { request =>
 prospectService
 .getInterestedProspects(page_number = page_number, version = 1)
 .map{ intrested_prospects => 
 Res.Success("Success", intrested_prospects)
 }
 .recover{ errorMessage => 
 Res.ServerError("Error", errorMessage) // sending error to front end 
 }
 }

}

我們改進(jìn)的代碼庫具有更高的清潔度和更強(qiáng)的可管理性,促進(jìn)了更高效的重構(gòu)工作。

此外,我們還建立了不同的標(biāo)記,用于合并邏輯、執(zhí)行數(shù)據(jù)庫操作或無縫集成新穎的第三方API。這些清晰的劃分簡(jiǎn)化了在系統(tǒng)中擴(kuò)展功能和適應(yīng)未來增強(qiáng)的過程。

測(cè)試和質(zhì)量保證

測(cè)試可能看起來是重復(fù)的,但它的重要性怎么強(qiáng)調(diào)都不為過,尤其是在熟練使用的情況下無需為重新編碼而煩惱。

讓我們更深入地了解構(gòu)建健壯Spec文件的指導(dǎo)原則。

1.覆蓋是關(guān)鍵:在為特定函數(shù)構(gòu)建規(guī)范時(shí),確保這些規(guī)范涉及該函數(shù)中的每一行代碼是至關(guān)重要的。實(shí)現(xiàn)全面覆蓋保證了在測(cè)試過程中對(duì)功能內(nèi)的所有路徑和場(chǎng)景進(jìn)行仔細(xì)檢查。

2.失敗優(yōu)先測(cè)試:Spec文件的主要作用是檢查代碼在不同情況下的行為。為了實(shí)現(xiàn)這一點(diǎn),包含一系列測(cè)試用例是至關(guān)重要的,尤其是那些模擬潛在故障場(chǎng)景的測(cè)試用例。確??煽康腻e(cuò)誤處理需要對(duì)所有可預(yù)見的故障實(shí)例進(jìn)行測(cè)試。

3.接受集成測(cè)試:雖然單元測(cè)試擅長(zhǎng)于評(píng)估代碼的邏輯方面,但它們可能會(huì)無意中忽略與輸入/輸出操作相關(guān)的潛在問題。為了解決這個(gè)問題,集成和執(zhí)行徹底的集成測(cè)試變得必不可少。這些測(cè)試模擬真實(shí)世界的場(chǎng)景,驗(yàn)證代碼在與外部系統(tǒng)或資源交互時(shí)的行為。

協(xié)作與團(tuán)隊(duì)合作

有一條要記住的黃金法則:在遇到難以解決的問題時(shí),可以尋求他人幫助。他人的幫助對(duì)于你自身能力實(shí)現(xiàn)指數(shù)增長(zhǎng)至關(guān)重要。

創(chuàng)建一個(gè)健壯的代碼庫不是一項(xiàng)單獨(dú)的任務(wù),而是需要團(tuán)隊(duì)的努力。盡管開發(fā)人員的職業(yè)表面上看起來是內(nèi)向的,但協(xié)作構(gòu)成了編碼的支柱。這種合作超越了企業(yè)的界限。

GitHub、LeetCode和StackOverflow等平臺(tái)展示了編碼社區(qū)的活躍和社交性質(zhì)。如果你遇到一個(gè)以前沒有遇到的問題,很可能別人也遇到過。因此請(qǐng)始終對(duì)尋求幫助持開放態(tài)度。

代碼文檔的最佳實(shí)踐

無論是公共API還是內(nèi)部代碼,可靠的文檔是游戲規(guī)則的改變者。不過,現(xiàn)在將重點(diǎn)放在編碼方面。

確保一流的文檔實(shí)踐不僅僅是為了簡(jiǎn)化開發(fā)人員的入職過程,而是為了向開發(fā)團(tuán)隊(duì)提供一個(gè)對(duì)代碼庫有清晰見解的寶庫。這種清晰性推動(dòng)了學(xué)習(xí),使每個(gè)參與者都受益。

預(yù)先編碼和研究

這是啟動(dòng)項(xiàng)目的所有要素的起點(diǎn)——從系統(tǒng)設(shè)計(jì)到指向相關(guān)文檔的關(guān)鍵鏈接。

在預(yù)編碼文檔中,開發(fā)人員不僅可以找到新的表結(jié)構(gòu)和修改,還可以找到指向第三方文檔的有價(jià)值的鏈接。需要記住的是,充分的準(zhǔn)備為成功奠定了基礎(chǔ),將會(huì)事半功倍!

編碼期間

這是開發(fā)人員在代碼中嵌入注釋的地方。這些注釋作為指南,揭示了代碼功能背后的復(fù)雜性和意圖。

事后編碼

這是有效利用代碼的指導(dǎo)中心,也是將來修改代碼的指南。它是引導(dǎo)用戶使用代碼的指南,并概述了后續(xù)修改代碼的路徑。

結(jié)論

優(yōu)秀的代碼遵循可靠的命名約定,保持模塊化,遵循“不要重復(fù)自己”(DRY)原則,確??勺x性,并經(jīng)過徹底的測(cè)試。編寫這樣的代碼需要混合文檔、協(xié)作以及為編碼人員提供幫助。

文章標(biāo)題:Tired of Messy Code? Master the Art of Writing Clean Codebases,作者:Upasana Sahu

責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2013-03-22 16:43:03

可讀代碼代碼的藝術(shù)代碼編寫

2022-06-07 09:30:35

JavaScript變量名參數(shù)

2020-07-15 14:51:39

代碼C+開發(fā)

2020-08-27 07:00:00

代碼軟件應(yīng)用程序

2023-03-27 15:05:10

Python技巧

2017-09-14 12:45:35

2023-01-27 14:53:03

2015-05-11 10:48:28

代碼干凈的代碼越少越干凈

2024-06-24 10:31:46

2023-02-01 08:17:48

GitHub提交信息

2021-12-29 16:34:19

JavaScript代碼庫開發(fā)

2019-11-08 09:20:57

代碼開發(fā)工具

2022-07-18 10:15:16

Python

2021-09-01 08:55:20

JavaScript代碼開發(fā)

2024-06-26 11:19:33

2021-11-30 10:20:24

JavaScript代碼前端

2020-10-04 13:15:37

代碼技術(shù)開發(fā)

2011-03-24 13:09:11

數(shù)據(jù)庫代碼

2023-09-01 21:20:06

授權(quán)委派KPI

2020-07-17 13:01:44

If-Else代碼編程
點(diǎn)贊
收藏

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