首先談為什麼要進行重構吧,畢竟已經維護了兩年了,大大小小也經歷了很多次迭代開發,為何這次會進行重構呢?
這要先交代一下我們這個介面專案是咋回事。
controlers #控制器層
models #模型類層
common #公用函式
config #配置檔案目錄
libs #基礎類庫
ext #第三擴充套件
index.php #入口檔案
複製**從**的專案結構看得出來,最主要的是控制器層和模型層:
控制器層(controllers)
controllers
v1.0.0
v1.0.1
...v5.0.0
複製**模型層(models):
業務邏輯層,也包含對資料進行curd,呼叫第三方,引數校驗等功能,幾乎所有業務功能都在這裡,不同版本的模型層相互呼叫,所以這一層也是功能最混亂的層,因此也是最需要重構的分層,models目錄的版本劃分與controllers類似,不同版本的model類有大量重複的**。
models
v1.0.0
v1.0.1
...v5.0.0
複製**通過上面的介紹,其實你會發現,這個是乙個簡單到不能再簡單的專案,但再簡單的專案,隨著業務的推進以及多個迭代開發,**的**極其混亂,總結起來大概是以下幾個問題:
沒有良好的目錄分層,大體上只是簡單分了控制器層和模型層,所有的業務邏輯都堆積在控制器層和模型層,完全沒有任何擴充套件性可言。
很多配置都直接寫死在**裡,雖然專案中有專門存放配置的目錄,但還是有很多的配置直接寫死在**,比如連線redis的**。
沒有編碼規範,無論變數名還是常量或是類名,命名都很隨意。
**裡還充斥著大量的魔法數值,如何有新人接手,會完全搞不清楚到底這些數值到底什麼意思。
所有的**都沒有輸出日誌,出現bug時,很難定位問題。
業務**直接堆積在控制層和模型層,沒有抽離公共**,新增乙個版本介面時,需要完全複製上個版本的**。
完全沒有使用php的命名空間,不能很好劃分不同的類。
上面列出專案的幾個問題,其實重構的過程,就是把上面提出問題的優化吧。
重構要達到的目的
重新劃分專案結構,使專案結構層級更加清晰。
進行版本迭代開發時,不需要複製乙份同樣的**,提公升開發效率。
增加**的可維護性。
重構的原則
單一職責原則:每個類的功能要單一,每個方法的作用要單一,避免**臃腫。
變數命名規範
避免在**中直接寫魔法數值
迭代介面,新增乙個介面版本時,不需要完全複製上乙個版本介面的**。
重新劃分的專案結構
controllers # 控制器層,只能將引數傳遞給services層。
v1_0_0
indexcontroller.php
v1_0_1
......
v5_0_0
services #具體業務邏輯層,可以呼叫manager層或models來實現業務邏輯
v1_0_0
v1_0_1
......
v5_0_0
handlers # 擴充套件層,對services的補充
models # 模型,針對資料表的curd**
entity #實體類
managers #業務封裝層
libs #類庫
ext #第三方類庫
common #公用函式
index.php #入口檔案
複製**下面的專案的目錄結構的截圖:
乙個controller類的示例:
class indexcontroller
public function actionindex()}
乙個service型別的示例:
#不同版本的service之間通用**抽取到service類,作為基類被繼承
class indexservice
//業務方法
public function index($page = 1)
protected function getarticle()
}
在重構過程中,之所以設計如上所示的目錄結構,乙個重要的考慮點就是如果在新增加乙個版本介面時,最大限度地復用上乙個版本的邏輯,這裡的新增介面的意思是現在首頁介面的版本為v1.0.0,但由於版本迭代,會把介面公升級為v1.0.1,也就是介面公升級。
乙個介面的公升級,無非兩個原因:
介面的業務處理邏輯發生改變,因此需要公升級介面。
介面的資料結構發生改變,比如新增資料或資料型別發生改變,因此需要公升級介面。
比如說,index介面從v1.0.0公升級v1.0.1時,getarticle()方法資料結構或者業務邏輯發生改變,這時候繼承父類介面,並覆蓋getarticle()方法即可。
class indexservice extends indexbaseservice
//重寫覆蓋父類邏輯
pulic function getarticle()}
但這時候,你會發現在getarticle()方法重寫的邏輯,只在v1.0.1這個版本中,如果這個重寫的邏輯在後續版本也是一樣的,那不是每個版本都要重寫?
這時候,可以將這段邏輯抽取出來,給每個需要的版本復用,如果某個有單獨的處理邏輯,可以使用的的覆蓋重寫的方法,而抽取出來的邏輯,放在handlers目錄結果中,handlers目錄是對services中需要重寫覆蓋並會在多個版本復用邏輯的抽取層。
所以我們把getarticle()方法抽取出來,如下所示:
trait getarticle}
這時候v3.0.1的介面,載入上面handlers的方法,完全邏輯復用。
class indexservice extends indexbaseservice
}老實說,專案開發時間不夠,而我個人能力也有限,因此我只能在本次的開發中,盡自己的能力去完善整個專案架構,很多不完善的地方,只能之後的開發中優化了。
重構後的優點
相比原先全部業務堆積在models層,劃分後的架構,每個層級只負責自己的事情,因此邏輯比較清晰,**可維護性強,每個類或方法的職責單一,降低了開發難度。
重構後的缺點
當然,原來的**非常簡單,就是controllers層直接呼叫models層,或者有時候,所有的業務邏輯直接寫在controller層,重構後,**的複雜性也會相應增加。
可能很多人會問,這麼簡單的專案,直接重做不就好了嗎?其實是這樣,除了上面重構中的重新分層,專案還有很多公用的**和模組,如果重新開發乙個專案的話,那麼這些基礎的也需要重新開始,而舊專案也需要繼續維護,更加增加開發和維護的成本,因此重構是比較合適的選擇。
老實說,我重構的這個介面專案一點也不複雜,最主要的**還是curd,並沒有非常複雜的業務邏輯,但由於從一開始就沒有進行嚴格的**架構分層,在開始過程也沒有一致的**規範,導致經過兩三年業務的發展與**迭代開發,造成了**混亂和重複業務邏輯堆積。
所以,對於任何專案來說,良好的**分層和開發規範,是保證專案可維護性的根本。
為什麼我使用 Linux 開發
當我對 linux 的印象似乎還停留在黑乎乎的命令列介面上的時候,我身邊的一些朋友告訴我或者建議我使用 linux 時,我會一臉驚訝的問他,那個怎麼用 來開發或者日常使用 首先說說我每天打交道最多的 shell 吧,我給自己設定的預設 shell 是 fish。你還可以搭配 fzf 這個軟體,實現高...
為什麼我不推薦敏捷開發?
當專案成員越多,我越不推薦敏捷開發,原因在於 當連自己要做什麼事 為什麼這樣做 這樣做為了解決什麼問題 都搞不清楚前,就跳下去玩敏捷開發,那和比通靈還慘,通靈起碼還有個目標物在前面,搞不清楚狀況的人只能陪他跳世界迷霧開地圖了 敏捷開發 mba智庫百科 最下方有段 對敏捷開發的誤解 可順便參考 敏捷軟...
我為什麼要開發亞馬遜ERP
在大學的時候時常聽經貿系的同學說,他的乙個同學搞亞馬遜,乙個月兩萬多的存收入,讓人聽起來無比的羨慕。在我看來,亞馬遜的印象還在停留在賣書的 這幾年,aws,傑夫 貝佐斯 jeff bezos 的字眼經常出現,讓我想深入了解一下亞馬遜。大學的學的是計算機系,在學校的時候做過幾個web應用,我自認為和網...