近來在維護並重構一個原來離職的同事的代碼,在將一部分代碼從原有邏輯剝離開來的時候遇到了不少的麻煩,但願本身之後不要留下相似的坑,因此在這裏作一個總結服務器
代碼是Python寫的,工程很浩大,其中代碼運行在一個虛擬化集羣中,個人目的是將一部分原有代碼邏輯差很少,可是實體(機器)要分開的代碼重構函數
其中涉及到主要的有幾點約束:spa
1.新分離的代碼邏輯和原有的代碼邏輯要同樣設計
2.其中涉及到一個任務系統,集羣中的機器取任務和返回任務都是向一臺核心Server獲取,新分離的代碼中任務申請和返回接口發生改變繼承
3.暫時沒想到...接口
從原有代碼中分離出新代碼,且代碼邏輯要同樣,那麼不少人都會偷懶直接Copy一份代碼,而後把其中一些部分稍微作修改開發
用腳趾頭想一想都知道這樣之後的維護工做有多麻煩:文檔
1.修改代碼邏輯須要修改兩份,原有的發生改變後你的也必須改字符串
2.誰知道你和原有代碼有哪些地方不同,不要期望文檔字符串處理
最好的辦法就是繼承,繼承原有代碼的基礎上重載你要修改的東西。
但是之前那位兄弟歷來沒考慮過他的代碼是會被繼承的,也就是說,他用了不少不適合被重載的方法在裏面,例如直接暴露第三方庫,全局變量等等...
這裏就說道了此次開發回憶錄的主題 第三方模塊的鬆耦合
在此次的工程中,第三方模塊依賴很少,主要是JsonRPC暴露的幾個接口
原有的代碼中大多數都是在類中直接import JsonRPC的Client而後引用一個配置文件對Client 作初始化
這樣作的壞處顯而易見,代碼與第三方模塊的緊耦合,在個人需求中,代碼中申請任務和返回任務等一系列接口都是經過JsonRPC來作的,一旦我須要改變這些接口的功能或者指向的時候
在耦合很嚴重的狀況下我不得不重寫代碼,那樣在邏輯上代碼就可能發生改變了,維護工做也很麻煩
在這樣的設計中最好的方式就是遵循設計的一個很重要的原則,動靜分離
說到動靜分離,這裏的動和靜就分別指的是:
1.靜:代碼邏輯是不會變的,即便變那修改自己的需求,也就是日常寫程序的那些if else的邏輯什麼的...
2.動:
a.不屬於你的類的函數調用(姑且看作是第三方模塊),固然要排除一些經常使用的函數好比說字符串處理云云..
也就是說依賴別人的都是不可靠的,沒有人會真正和你在一塊兒約定一生,那麼這部分東西就有多是變化的
b.配置依賴,當我須要使用原有類的一些函數功能的時候,可是發現其中的配置和功能牢牢的耦合在一起,好比說初始化JsonRPC的客戶端中服務器的地址
我在新的邏輯中須要改變這個服務器地址,沒辦法,只有重載初始化JsonRPC Client的函數,可是又發現一個問題就是初始化函數發生在構造函數中,因而子類
在調用父類的構造函數的時候JsonRPC就初始化,輪不到子類來初始化,因此這裏JsonRPC的客戶端都指向了原有的服務端地址
換句話說,這裏的配置也是不可靠的,隨時均可能會變化
作到動靜分離很簡單,避免直接調用,增長一個接口層(若是你是一個強類型的語言的OOP開發者),或者你就封裝一個調用的類
第三方模塊的調用都抽象爲統一的幾個操做並封裝爲另外一個類,好比說我這裏的:
1.申請任務操做
2.返回任務結果
動的代碼依賴->我只須要在原有的代碼邏輯中將這個類做爲參數,之後在調用的時候用這個類直接調用(Python的鴨子類型)(其餘的語言開發者就是利用多態的特性或者接口云云..來調用實際的第三方接口)
動的配置依賴->一樣的將配置封裝爲統一的一個結構,初始化或者其餘時候再動態綁定這個結構中的配置信息而不是直接引用配置文件中的參數
再補充一點:
工程中最好不要出現一個獨立的沒有歸屬的函數,即便有,這個函數也應該是能夠配置的,大學課程時候一個講程序設計藝術的老師說過,沒有返回值的函數應該叫作過程。
這裏我以爲一個功能函數不可配置(除非是真的不須要配置)否則都應該有一個歸屬