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

程序的腐化原因及建議

開發(fā) 前端 移動開發(fā)
什么是一個軟件的質(zhì)量?一個分類標(biāo)準(zhǔn)是軟件外部質(zhì)量與軟件內(nèi)部質(zhì)量的統(tǒng)一,外部質(zhì)量是對外表現(xiàn)是否正常,內(nèi)部質(zhì)量是對后續(xù)開發(fā)有沒有坑,就是我在這里說的軟件有沒有腐化。內(nèi)部質(zhì)量標(biāo)準(zhǔn)有:可維護性,靈活性,可移植性,可重用性,可測試性,可理解性(摘錄自代碼大全)。

[[230778]]

寫代碼如同打掃屋子,有句話叫一屋不掃何以掃天下。如果單個的一個模塊代碼都不能管好,如何成就一個完善的軟件系統(tǒng)?今天我們來說說,一個代碼模塊的代碼是如何一步步腐化變質(zhì),到***程序員都不愿意去維護它,然后要么重構(gòu),要么廢棄換新模塊的?

代碼是有一定的周期的,這個沒有錯。為什么有的代碼跑上幾十年任然好用,而現(xiàn)在互聯(lián)網(wǎng)公司的很多代碼,每年都要做好幾次重構(gòu)?一個成立2年的互聯(lián)網(wǎng)公司,做一個支付系統(tǒng),可以做了4-5代,每次重構(gòu),這樣的代價有多大?如何才能讓原有的代碼生命周期更加長,而不增加很多的學(xué)習(xí)維護成本,開發(fā)一次使用更久呢?

大部分程序員是沒有很多機會從0開始搭建一個新程序的,更多的時候是接手別人寫的代碼。有代碼移交還好一點,往往因為各種因素,這些因素你懂的,沒有產(chǎn)品文檔,沒有設(shè)計文檔,沒有程序說明,程序里可能連注釋都沒有。然后,程序員更新?lián)Q代又極其的快,互聯(lián)網(wǎng)時代,程序員在一個公司的平均年資也就1年多,程序就又被傳給下一任維護者。很大可能的情況是,最終到你手里的程序各種問題,卻能實現(xiàn)基本的功能需求,但代碼內(nèi)部各種問題讓程序員總有一個沖動,重構(gòu)它。今天不想說重構(gòu)的問題,而是從根源角度分析,程序為什么會變成這個樣子?

什么是程序的腐化?

什么是一個軟件的質(zhì)量?一個分類標(biāo)準(zhǔn)是軟件外部質(zhì)量與軟件內(nèi)部質(zhì)量的統(tǒng)一,外部質(zhì)量是對外表現(xiàn)是否正常,內(nèi)部質(zhì)量是對后續(xù)開發(fā)有沒有坑,就是我在這里說的軟件有沒有腐化。內(nèi)部質(zhì)量標(biāo)準(zhǔn)有:可維護性,靈活性,可移植性,可重用性,可測試性,可理解性(摘錄自代碼大全)。不符合以上標(biāo)準(zhǔn)都可以稱之為代碼腐化,形象的理解就是一個蘋果,從內(nèi)部開始爛了,爛到原本應(yīng)該負責(zé)內(nèi)部代碼的程序員拒絕去維護了。

實際的代碼腐化的例子:

代碼混亂,沒有代碼規(guī)范不該連數(shù)據(jù)庫的模塊連了數(shù)據(jù)庫模塊間的調(diào)用混亂:模塊內(nèi)部的調(diào)用混亂,例如C#代碼已經(jīng)使用了EntityFramework,代碼中跳過EntityFramework,直接用數(shù)據(jù)庫連接修改數(shù)據(jù)??蚣芘c其他不一致,不統(tǒng)一:有的包管理使用gradle管理,有的使用maven。有的后臺用.Net,有的用Node,有的用Java。

用了HttpClient,又使用Feign去連接其他應(yīng)用模塊有一些設(shè)計前后不一致:有的代碼使用了統(tǒng)一的錯誤定義CommonException,有的用原生的Exception。微服務(wù)模塊,有resource層接口,定義訪問的路徑,resource的Impl,service的接口提供具體的數(shù)據(jù)接口,serviceImpl提供具體數(shù)據(jù)獲取的實現(xiàn)。而在具體編碼時,將大量的業(yè)務(wù)邏輯寫入了resource的實現(xiàn)中。

太復(fù)雜的抽象不能做方便的變更:一開始設(shè)計的Job系統(tǒng),上面是2-3張圖片,下面是動態(tài)生成的問題。代碼層面對于此設(shè)計做了很細致的抽象。突然產(chǎn)品提出了某一個Job的圖片有特別,要求顯示10張圖片,就對抽象的圖片部分做了if-else的處理……無用代碼,廢棄的接口沒有標(biāo)明

代碼腐化的原因

沒有代碼會是init commit的時候就開始腐化的,腐化都是循序漸進的,要一個過程。我總結(jié)了一些代碼腐化的原因:

  • 沒有統(tǒng)一標(biāo)準(zhǔn),或者沒有嚴(yán)格執(zhí)行
  • 統(tǒng)一標(biāo)準(zhǔn)之代碼規(guī)范

每個程序員都是有自己的審美的,例如即使是縮進長度這種代碼里不影響任何功能的東西,有的喜歡空4格,有的喜歡2格。有的喜歡黑色的編程背景,有的喜歡白色的編程背景。有的喜歡if后直接跟上左括號,有的就喜歡另起一行。代碼規(guī)范還是要有的,包含各種格式定義,大小寫規(guī)范,命名規(guī)范等。前端有各種lint工具(jslint,tslint)可以幫助規(guī)范,后臺的ide也有一些方法幫助。像Baidu,Google這樣的公司還有構(gòu)建時的自開發(fā)的檢查工具,所以常常一個資深程序員***次開發(fā)的代碼要花上1-2天才能提交通過。代碼規(guī)范的混亂,直接導(dǎo)致代碼可讀性的降低??勺x性直接影響后續(xù)的生產(chǎn)力。一個程序員天天對著看不順眼的代碼,怎么可能高效?

統(tǒng)一標(biāo)準(zhǔn)之基礎(chǔ)規(guī)范

除了代碼規(guī)范外,項目命名,通訊方式,基本的程序框架,后端Java的springboot,sprintMVC,前端的angular,vue,react等都需要統(tǒng)一,還有統(tǒng)一的基礎(chǔ)環(huán)境(eureka,elk,redis,apigateway等)。不統(tǒng)一的后果是各種部署,管理,編碼的低效。例如搭一個jenkins,然后部署服務(wù)A用的Maven,服務(wù)B用的gradle,就導(dǎo)致編譯代碼寫2套,如果寫一套基本一樣的,當(dāng)然會快一些。 我統(tǒng)計的java代碼中可以統(tǒng)一的部分(包含但不限于)Http調(diào)用格式,統(tǒng)一用content-type:application/json,response也統(tǒng)一要求這樣。HttpClient的標(biāo)準(zhǔn)化框架,如SpringBoot項目管理工具:Maven,Gradle項目的CI,CD配置管理模式,例如統(tǒng)一成一個配置文件application.properties環(huán)境變量配置方式,qa,stag,prod。不要有的人寫stage,staging,也不要寫成production等等細節(jié)代碼基礎(chǔ)結(jié)構(gòu):例如標(biāo)準(zhǔn)的maven目錄的結(jié)構(gòu)

 

圖0:程序的腐化

項目命名方式:com.(公司名).(開發(fā)組名).(系統(tǒng)名).(模塊名)例如:com.omniprimeinc.cosmetic.application.server;Restful接口設(shè)計統(tǒng)一:大小寫,命名方式,Body的***大小例如,Post接口是否可以加PathParameter和QueryParameter。Post接口是否可以不帶Body。其他配套功能的統(tǒng)一性:調(diào)用鏈,動態(tài)配置管理,緩存,分布式事物數(shù)據(jù)庫的統(tǒng)一:統(tǒng)一數(shù)據(jù)庫,數(shù)據(jù)庫版本,是否可以使用存儲過程等。關(guān)于數(shù)據(jù)庫統(tǒng)一性不在這里展開,這點也非常的重要。

統(tǒng)一規(guī)范之公司統(tǒng)一框架

剛才說的統(tǒng)一,很多是從公司層面的統(tǒng)一,如果大家都只用springboot,都沿用統(tǒng)一的后端框架,前端統(tǒng)一用angular。那么這個時候,為了方便統(tǒng)一,就需要有代碼相關(guān)的腳手架工具,直接生成基本的統(tǒng)一項。這樣一個工具的好處是可以直接一鍵完成許多基礎(chǔ)工作,并完成了底層的統(tǒng)一工作。

多頭維護

代碼腐化的一個很重要的因素是多頭維護,甚至是多代維護。一個公共項目,多個開發(fā)團隊都在維護,那就很難統(tǒng)一標(biāo)準(zhǔn)。初始版本有一個架構(gòu),然后換了一個架構(gòu),開發(fā)更是換了幾批。人多手雜說的就是這樣的情況。任何開發(fā)團隊接手一個舊項目時,其實都是有學(xué)習(xí)和適應(yīng)的成本的。頻繁的變更開發(fā)人員帶來的壞處就是反復(fù)的人為制造這個成本,其次就是有幾率丟失之前的一部分標(biāo)準(zhǔn)和架構(gòu)規(guī)劃。

架構(gòu)沒有落地

代碼模塊的功能設(shè)計規(guī)劃,制定的標(biāo)準(zhǔn),沒有詳細的落地。架構(gòu)定了一套,開發(fā)沒有嚴(yán)格執(zhí)行。每天寫代碼這么忙,架構(gòu)只管架構(gòu),不管細節(jié)。開發(fā)每天擼代碼,只管功能,不管架構(gòu)和代碼質(zhì)量(這個質(zhì)量不是指功能實現(xiàn)上的質(zhì)量,而是說嚴(yán)格執(zhí)行各項統(tǒng)一標(biāo)準(zhǔn)的程度)。甚至說,一個高層服務(wù),不能調(diào)用同級服務(wù),只能調(diào)用底層服務(wù)。因為開發(fā)的沒有嚴(yán)格執(zhí)行,甚至加了數(shù)據(jù)庫連接,直接去取了數(shù)據(jù)庫,這樣的事一旦開了口子,就像黃河決堤,不可收拾了。所以,以上說的是架構(gòu)的落地落實很重要,讓所有具體的開發(fā)參與者落實同一個標(biāo)準(zhǔn)。架構(gòu)就需要落實相關(guān)的設(shè)計,相關(guān)的文檔,相應(yīng)的執(zhí)行檢查?,F(xiàn)實的情況從來沒有靠文檔解決一切問題的,可它能解決80%的問題,另外就盡量減少開發(fā)人員的變動,以減小換人帶來的代碼腐化問題。

防止代碼腐化的建議:

代碼規(guī)范標(biāo)準(zhǔn)化,統(tǒng)一化治理

代碼的內(nèi)部質(zhì)量其實很難保證,規(guī)范執(zhí)行也更多的靠人治,甚至個別標(biāo)準(zhǔn)化的東西,只能通過代碼層面去檢驗,無法通過測試或其他手段進行。另外,雖然有一些通行的默認標(biāo)準(zhǔn),更多的標(biāo)準(zhǔn)是代碼的負責(zé)人自行確定的標(biāo)準(zhǔn),完全根據(jù)喜好來,就像前面說的縮進的長度。好比是老媽和丈母娘都跑來你家里幫你打掃衛(wèi)生,老媽喜歡把廚房里的鍋都一路洗好掛起來,丈母娘喜歡找一個櫥柜,都放在櫥柜里,你能怎么辦?沒關(guān)系,只要確定下一套標(biāo)準(zhǔn),不要經(jīng)常改就好了。

架構(gòu)嚴(yán)格落地

像前面說的標(biāo)準(zhǔn),特別是自定義的標(biāo)準(zhǔn),都需要落地。***優(yōu)先文檔,第二是團隊內(nèi)部達成共識,第三是執(zhí)行。

嚴(yán)格的codereview

防代碼的腐化執(zhí)行是一個關(guān)鍵點,這個關(guān)鍵點就是codereview。在這個時間點,再次與開發(fā)強調(diào)標(biāo)準(zhǔn)的重要性,讓開發(fā)知曉執(zhí)行,讓測試監(jiān)督,讓架構(gòu)嚴(yán)格檢查。對于不符合的,開發(fā)要再次去學(xué)習(xí)執(zhí)行標(biāo)準(zhǔn)。

減少開發(fā)人員的變動

如果一個團隊內(nèi),原本標(biāo)準(zhǔn)就是統(tǒng)一的,團隊內(nèi)實行敏捷開發(fā),任何一個開發(fā)都可以替代其他開發(fā)工作,那么兩個人交換任務(wù)就沒有問題。如果團隊內(nèi)都不統(tǒng)一,這個變動就會嚴(yán)重影響開發(fā),代碼腐化的可能會變的很大。而團隊間,標(biāo)準(zhǔn)統(tǒng)一的可能性比在團隊內(nèi)更難,要避免團隊間的項目移交才是***的方法。

代碼模塊架構(gòu)Keep it Simple&Stupid,使用一眼就明白的架構(gòu)

現(xiàn)實世界中,業(yè)務(wù)需求永遠的跑在技術(shù)需求前面,很可能架構(gòu)相關(guān)的設(shè)計沒有文檔,沒有說明,一旦架構(gòu)師不在,原來的開發(fā)換人了,導(dǎo)致原先的標(biāo)準(zhǔn)和設(shè)計無法繼續(xù)下去,一旦有交接,標(biāo)準(zhǔn)的丟失和架構(gòu)的變化不可避免。這時,此條原則就能發(fā)揮作用。要使用傻瓜化的架構(gòu),就是任何一個新來的程序員,一眼就能看明白的架構(gòu)。例如使用公司統(tǒng)一的項目代碼生成器,腳手架,生成統(tǒng)一的代碼結(jié)構(gòu),不需要程序員再投入代碼結(jié)構(gòu)學(xué)習(xí)的成本。而且通用架構(gòu)就意味著,后續(xù)的架構(gòu)師接受原先設(shè)計的可能性大增。

 

圖1:程序的腐化

分層的概念很早就提出來了,為什么MVC的概念會這么受歡迎?我覺得是因為它足夠傻瓜化。數(shù)據(jù)庫的架構(gòu)結(jié)構(gòu)中,定義repository,service接口,serviceImpl的實現(xiàn)等也成為了很通用性的設(shè)計。有一個挺經(jīng)典的例子就是asp.net.MVC的程序組織架構(gòu)三個文件夾:Controllers,Models,Views直接約定,并強調(diào)約定大于配置。只要是開發(fā)過這類程序的程序員,都知道從Controller看路徑和RestApi入口,Models看數(shù)據(jù)結(jié)構(gòu),View看Html視圖。就不需要額外的學(xué)習(xí)成本。Maven的標(biāo)準(zhǔn)目錄結(jié)構(gòu)也是一個例子。(見上圖)

定期清理維護

如同像打掃房間一樣,一段時間不打掃,自然會有邊邊角角的臟東西出來。那么有沒有定期的去清理呢?還是不管他,每次看到地上的一團紙,都繞過,而不是去扔了?定期的清理維護不單是一個維護代碼的過程,更是一個重新梳理和統(tǒng)一標(biāo)準(zhǔn)的過程,讓現(xiàn)有的開發(fā)和架構(gòu),再次的達成一致,以提高戰(zhàn)斗力

防止代碼膨脹

微服務(wù)概念的提出后,很好的解決了一個問題,我們的一個代碼模塊應(yīng)該寫多少大的問題?一個模糊的建議是一個Sprint能重寫的大小,如果更大,就應(yīng)該要差分。有時候代碼的清理維護工作也要以這個原則來處理,不能出現(xiàn)過大的代碼模塊。因為過大的代碼模塊,首先帶來的是程序的復(fù)雜度,讓程序員理解起來要更多成本。其次,模塊內(nèi)部的耦合度必然也提高了,增加了難度。這時,需要的是切分出一個新模塊出來。

總結(jié)

代碼腐化是程序開發(fā)的一個經(jīng)典問題。代碼內(nèi)部質(zhì)量的降低,外部質(zhì)量確可以被客戶接受。程序員經(jīng)常想著,等業(yè)務(wù)沒那么忙的時候,做點清理,做點模塊局部的微重構(gòu),我的經(jīng)驗告訴你,這些都是假的。如果定下了定期清理,定期檢查拆分,就必須立馬去做。做這些事的優(yōu)先級要遠高于業(yè)務(wù)需求。 為什么呢?想象一個程序C++的printf,里面的代碼寫的非常的爛,變量命名都是p,m,k完全不能直觀理解含義,我們需要鄭重的去處理這個模塊的代碼腐化問題嗎?

其實不需要,因為printf模塊的代碼需求,就是把輸入的內(nèi)容打印出來,永遠都是這樣,沒有任何新需求,沒有新需求就代表沒有程序員需要深入內(nèi)部去改它的代碼,不需要改的代碼,我們是沒有動力去解決它的腐化問題的。有必要經(jīng)常深入解決腐化問題的代碼,必然是業(yè)務(wù)需求很多,經(jīng)常要變更的代碼。不要等到它已經(jīng)腐化到代碼生命周期都快走到頭了,才想起來去維護清理它,要經(jīng)常維修一下,才能更好的讓它發(fā)揮作用,是吧?一輛不打算開的老爺車,發(fā)動機壞了就壞了,一輛經(jīng)常開的二手奔馳,定期維護少不了。

責(zé)任編輯:未麗燕 來源: 代碼灣
相關(guān)推薦

2023-09-01 13:35:30

2011-07-06 12:04:53

架構(gòu)

2015-10-15 09:38:21

程序員發(fā)福

2023-08-16 12:29:34

2011-11-30 13:59:17

JavaJVM

2011-08-02 08:59:02

程序員

2014-10-16 13:43:31

2018-10-19 13:20:47

Python編程語言建議

2017-08-04 14:48:54

Linux優(yōu)勢建議

2011-08-19 11:02:03

電腦變慢

2015-06-12 11:22:52

程序員程序員跳槽

2014-08-27 10:24:33

.NETC#

2013-10-23 09:20:28

2009-09-06 14:35:34

如何學(xué)習(xí)CCNA建議

2021-06-25 10:52:12

云計算滲透測試云安全滲透測試

2019-10-10 17:22:07

多云CIO多云策略

2023-06-12 08:18:19

MySQLDDL數(shù)據(jù)

2017-10-17 14:33:41

2021-03-10 11:13:06

IT項目首席信息官執(zhí)行顧問

2009-07-10 14:32:06

JVM崩潰
點贊
收藏

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