javascript代碼的小小重構
寫js也有那麽段時間了,也看過幾本關於js的書,從最初的《鋒利的jquery》《高性能javasrcipt》到《javascript設計模式》等,雖然看了些書,看到了書中的各種理論與技巧,然而在實際的使用中,真正用到的卻是不多。
js的面向對象與我所熟悉的c#等語言的面向對象稍有不同,但基本都會有封裝,繼承,多態等。弱語言天生就具備多態性,沒有類型檢測的js相對而言可以做出許多強類型語言所做不到的靈活,雖然這不能說完全沒有壞處,但這個優勢讓js代碼變得豐富多彩。
程序的編寫基本遵守一些原則,比如單一原則,開閉原則,迪米特原則等,js的也不例外。然而因為js的特殊性,很多時候隨著需求的改變及代碼量的增加很有可能會變成面條式的代碼,變的難以閱讀,不易擴展,重復並且分散。這時候就不禁的想要改變,想要重構。
亡羊補牢,猶未為晚。
重構的目的是讓程序更加健壯,即健壯性。符合基本原則,可擴展,可復用,易維護等。
那麽怎樣重構才能讓程序更加健壯呢?隔離變化,抽象不變。讓程序更符合基本原則。
var outConding=function(result){ var outCond=1; var outConded=2; kinds={ kindItem:outCond, KindChildren:outConded }; cols=[{ value:outCond }]; }; var inConding=function(result){var inCond=1; var inConded=2; kinds={ kind:inCond, Children:inConded }; cols=[{ price:inConded, value:inCond },{
price:inConded,
value:inCond
}];
}
outConding(res);
inConding(res);
上面代碼是否健壯呢?很明顯至少沒有考慮到復用性及擴張性,如果之後需要添加onCoding,offCoding難道還需要將重復的代碼在一次次寫一遍嗎?
那麽這就需要完善了,對其重構。兩段代碼有明顯的相似的地方,比如結構,擁有kinds,cols等。但也有不同的地方,比如臨時參數。如何將其抽離出來以符合健壯性呢?
var conding=function(result){ kinds={}, cols=[]; }
首先將不變的抽象出來,只留下基本結構。然後分析變化。問題來了,裏面需要依賴臨時變量,臨時變量的變量名是未知的,數量是未知的,這該如何抽象出來呢?
用重載可以嗎?不行,變量在不變的程序裏是未知的。那讓不變的程序繼承變化的父類呢?。。。好像可以,那來實現試試吧。
js有原型鏈可以模擬繼承,讓父類變的可變化,子類繼承父類,子類中使用的變量在父類中聲明,這就可以解決變量的未知性了。
寫著寫著,忽然有個想法,不是有個更簡單的方法嗎?既然是弱語言為何一定要用強語言的優勢放棄自己的?
var conding=function(tempParams, kindsParam,colsParam, result){ var CondingParams=new tempParams(); kinds=kindsParam(CondingParams), cols=colsParam(CondingParams); };
js沒有類型檢測,那麽我傳個參數表示臨時變量集合可以嗎?當然可以。接下來就是可擴展,遵循單一職責原則,開閉原則,迪米特原則,完成以下代碼。
var conding=function(tempParams, kindsParam,colsParam, result){ var CondingParams=new tempParams(); kinds=kindsParam(CondingParams), cols=colsParam(CondingParams); }; var outCondingInfo = { tempParams: function () { this.outCond = 1; this.outConded = 2; }, kindsParam: function (param) { return { kindItem: param.outCond, KindChildren: param.outConded } }, colsParam: function (param) { return [{ value: param.outCond }] } } var inCondingInfo = { tempParams: function () { this.inCond = 1; this.inConded = 2; }, kindsParam:function(param){ return { kind:param.inCond, Children:param.inConded } } , colsParam: function (param) { return [{ price: param.inConded, value: param.inCond }, { price: param.inConded, value: param.inCond }]; } } var res=1; conding(outCondingInfo.tempParams,outCondingInfo.kindsParam,outCondingInfo.colsParam,res) conding(inCondingInfo.tempParams,inCondingInfo.kindsParam,inCondingInfo.colsParam,res)
這個對於最初的代碼,如果需要新增一個onCoding,只需要新增一個onCondingInfo的對象就可以了,是不是可擴展了?是不是相對而已面向對象了一點?
不過一味追求健壯性,面向對象,雖然不會成為面條式代碼,但有可能在你不講解的情況下,他人很難看懂你寫的是什麽,於是這就造成了閱讀性,關聯上下文內容等問題。這便是取舍的問題了。
還有一些重構的小技巧,比如只在一個方法內使用,其他地方使用不到的方法,盡量不要單獨寫為一個全局函數,最好是直接在使用的方法內用一個臨時變量存儲他,盡量不去汙染全局。使用閉包讓待執行的方法順序執行,或限定執行完幾個方法後在執行特定方法等。
如果有好的意見或好的技巧,歡迎分享,歡迎指點。
javascript代碼的小小重構