這一頓神操作!我把 3000 行代碼重構(gòu)成 15 行!
點(diǎn)擊“開發(fā)者技術(shù)前線”,選擇“星標(biāo)?”
讓一部分開發(fā)者看到未來

把三千行代碼重構(gòu)為15行




要在編程過程中多思考 編程的思想很重要,請多看點(diǎn)經(jīng)典的書 從小處著眼,慢慢重構(gòu),尤其在應(yīng)對一個(gè)大型的系統(tǒng) 當(dāng)重復(fù)出現(xiàn)的時(shí)候,你應(yīng)該考慮重構(gòu)了 粘貼復(fù)制的代碼越少,你的系統(tǒng)越穩(wěn)定
少用代碼生成器
因?yàn)槭褂昧藙?dòng)軟代碼生成器,生成代碼方便,就沒多想了。 三層架構(gòu)的概念倒是了解了,但是沒有去深入思考就拿來應(yīng)用 遇到重復(fù)的代碼,沒有重構(gòu)的概念,這是思想的問題——思想比你的能力重要
for?(int?n = 0; n < rowsCount; n++)
{
????model = new?DBAccess.Model.eventweek();
????if(dt.Rows[n]["GroupNo"].ToString()!="")
????{
????????model.GroupNo=int.Parse(dt.Rows[n]["GroupNo"].ToString());
????}
????if(dt.Rows[n]["Week0"].ToString()!="")
????{
????????model.Week0=int.Parse(dt.Rows[n]["Week0"].ToString());
????}
????if(dt.Rows[n]["Week1"].ToString()!="")
????{
????????model.Week1=int.Parse(dt.Rows[n]["Week1"].ToString());
????}
}
不要重復(fù)發(fā)明輪子
public?List<string> GetDevices(string?dev){
????List<string> devs=new?List<string>();
????int?start=0;
????for(int?i=0;i????????if(dev[i]=='^'){
????????????devs.Add(dev.SubString(start,i));
????????????start=i+1;
????????}
????}
????return?devs;
}
重復(fù)發(fā)明輪子?;ㄙM(fèi)了額外的時(shí)間,函數(shù)的健壯性和很差 可讀性差。其實(shí)是一個(gè)很簡單的功能,但是用上了這么一段函數(shù),起初我還以為有什么特別的功能。
了解你所學(xué)的編程語言的特性。你可以看一本基礎(chǔ)的入門書籍,把所有的特性瀏覽一遍,或者上MSDN,把相關(guān)的內(nèi)容過一遍。 在你決定動(dòng)手發(fā)明一個(gè)輪子之前,先搜索一下現(xiàn)成的解決方案。你還可以到CodeProject、GitHub之類的網(wǎng)站搜索一下。在知乎上有很多人都在批評這么一種現(xiàn)象,老是問一些重復(fù)性的問題,然后又職責(zé)知乎沒落了,沒有人回答他的問題,實(shí)際上相關(guān)問題已經(jīng)有了很詳細(xì)的解答,那提問之前,不能首先去搜一下是否有現(xiàn)成的答案,反而指責(zé)沒有回答他的問題呢? 你有一定的基礎(chǔ)之后,還應(yīng)該去讀一下相關(guān)的經(jīng)典書籍,深入了解其中的原理。比如,你覺得你有一定的基礎(chǔ)了,我建議你去把《CLR Via C#》多讀幾遍,你了解原理越多,你越是能夠利用這編程語言的特性,從而來實(shí)現(xiàn)原本那些你認(rèn)為要靠自己寫代碼的功能。
public?abstract?class?MissionBase?: IMission
{
????private?DateTime _nextExecuteTime;
????protected?virtual?DateTime[] ExecuteTimePoints { get; private?set; }
????protected?virtual?int?IntervalSeconds { get; private?set; }
????protected?IEngine Engine { get; private?set; }
????public?bool?IsCanceled{get{……}}
????public?bool?IsExecuting{get{……}}
????public?bool?IsTimeToExecute{get{……}}
????public?abstract?bool?Enable { get; }
????public?abstract?string?Name { get; }
????protected?MissionBase(IEngine engine)
????{
????????ExecuteTimePoints = null;//默認(rèn)采用間隔的方式
????????IntervalSeconds = 60?* 60;//默認(rèn)的間隔為1個(gè)小時(shí)
????????Engine = engine;
????}
????///?任務(wù)的執(zhí)行方法
????public?void?Done()
????{
????????if?(Interlocked.CompareExchange(ref?_isExecuting, 1, 0) == 1) return;
????????try
????????{
????????????……
????????}
????????finally
????????{
????????????Interlocked.CompareExchange(ref?_isExecuting, 0, 1);
????????}
????}
????
????///實(shí)際方法的執(zhí)行
????protected?abstract?void?DoneReal();
}
等你無法重構(gòu)的時(shí)候再考慮重寫
需要花更大的精力來完成一些看似簡單的BUG
你要知道,有一部分看似錯(cuò)誤或者非常不優(yōu)美的代碼,其實(shí)恰恰是為了解決一些非常刁鉆的問題的。再也無法兼容老的系統(tǒng)了
你急于把原有系統(tǒng)重寫,卻往往忽略了對原有系統(tǒng)的兼容,那么你新的系統(tǒng)的推進(jìn)則會(huì)十分緩慢。而老系統(tǒng)的維護(hù),又會(huì)陷入及其尷尬的情況。過度設(shè)計(jì),導(dǎo)致重寫計(jì)劃遲遲無法完成
有重寫沖動(dòng)的程序員往往是在架構(gòu)設(shè)計(jì)上有一些讀到的見解,他們善于利用所學(xué)的各種設(shè)計(jì)模式和架構(gòu)技巧來建立系統(tǒng),但是越是想盡可能的利用設(shè)計(jì)模式,越是陷入過度設(shè)計(jì)的困局,導(dǎo)致重寫的計(jì)劃遲遲都無法完成。無法有效利用現(xiàn)有系統(tǒng)已經(jīng)完成并測試的代碼
如果你確實(shí)有必要進(jìn)行重寫,我還是建議你把代碼盡可能的重構(gòu)。因?yàn)橹貥?gòu)之后的系統(tǒng),能夠讓你更輕易的重寫,又最大限度了保留以前可用的業(yè)務(wù)代碼。
class?MainEngine:IEngine{
????public?MainEngine(ConfigSettings config){
????????
????}
????public?void?Start();
????public?void?Stop();
}
class?ConfigSettings{
????public?bool?NewFuncEnable{get;private?set;}
????public?ConfigSettings(){
????????NewFuncEnable=xx;//從配置文件讀取
????}
}
class?MainEngine:IEngine{
????private?NewFuncClass newCls=new?NewFuncClass();
????public?MainEngine(ConfigSettings config){
????}
????public?void?Start(){
????????if(config.NewFuncEnable)
????????????newCls.Start();
????}
????public?void?Stop(){
????????if(config.NewFuncEnable)
????????????newCls.Stop();
????}
}
主程序代碼和擴(kuò)展功能耦合性太強(qiáng),每增加一個(gè)功能都要修改主程序代碼,這里非常非常容易出錯(cuò)。尤其是新的人進(jìn)度開發(fā)組,很容易就忘主程序中增加了一些致命性的代碼。比如上述的擴(kuò)展功能,可能是在特定的項(xiàng)目中才會(huì)有這個(gè)擴(kuò)展功能,但是,寫代碼的人忘記增加是否啟用的配置選項(xiàng)了,導(dǎo)致所有的項(xiàng)目都應(yīng)用了這個(gè)功能,而這個(gè)功能需要特定的表,這樣就悲劇了。即使是你增加了配置,也是非常的不美觀,因?yàn)樵谕ㄓ玫陌姹局惺褂昧诉@個(gè)配置,往往會(huì)讓定制項(xiàng)目以外的人員感到困惑。 增加擴(kuò)展功能的人還需對整個(gè)MainEngine代碼有一定的熟悉,否則,他根本就不知道在Start方法和Stop方法進(jìn)行newClas的對應(yīng)方法的調(diào)用 如果你打算對這段代碼進(jìn)行重寫,那么,你會(huì)感到非常的困難,因?yàn)槟惴植磺宄ewCls這個(gè)新實(shí)例的作用,要么你花大精力去把所有代碼理清楚,要么直接就把這段新增的業(yè)務(wù)代碼去掉了。
private?void?RegisterTaskHandlerBundles()
????{
????????var?bundles = xxx.BLL.Caches.ServiceBundleCache.Instance.GetBundles("TaskHandlerBundle");
????????if?(bundles != null?&& bundles.Count > 0)
????????{
????????????var?asmCache = new?Dictionary<string, Assembly>();
????????????foreach?(var?bundle in?bundles)
????????????{
????????????????try
????????????????{
????????????????????if?(!asmCache.ContainsKey(bundle.Category)) asmCache.Add(bundle.Category, Assembly.Load(bundle.AssemblyName));
????????????????????var?handler = (ITaskHandler)asmCache[bundle.Category].CreateInstance(bundle.ClassName, false, BindingFlags.Default, null,
????????????????????????new?object[] { this, bundle }, null, null);
????????????????????_taskHandlerBundles.Add(bundle, handler);
????????????????}
????????????????catch?(Exception e)
????????????????{
????????????????????NLogHelper.Instance.Error("加載bundle[Name:{0},Assembly:{1}:Class:{2}]異常:{3}", bundle.Name, bundle.AssemblyName, bundle.ClassName, e.Message);
????????????????}
????????????}
????????}
????}
class?MainEngine:IEngine{
????private?NewFuncClass newCls=new?NewFuncClass();
????public?MainEngine(ConfigSettings config){
????????RegisterTaskHandlerBundles();
????}
????public?void?Start(){
????????_taskHandlerBundles.Start();
????}
????public?void?Stop(){
????????_taskHandlerBundles.Stop();
????}
}
新增的類只需按規(guī)范寫即可,完全對MainEngine代碼沒有任何影響。你甚至可以把這個(gè)MainEngine代碼寫在一個(gè)新建的Dll中。 新增功能的這個(gè)業(yè)務(wù)類跟原來的代碼解耦,非常方便進(jìn)行新功能的業(yè)務(wù)測試,而無需考慮原有框架的影響 新增功能的業(yè)務(wù)類與架構(gòu)完全分離,我們在重寫代碼中只要保證接口的穩(wěn)定性,無論我們怎么把系統(tǒng)架構(gòu)重寫,我們可以馬上就重用上原有的業(yè)務(wù)功能代碼。
學(xué)會(huì)單元測試,培養(yǎng)你的重構(gòu)意識

所謂重構(gòu)
把基礎(chǔ)打牢固 多看點(diǎn)優(yōu)秀的代碼 避免復(fù)制粘貼,如果看見重復(fù)代碼時(shí)應(yīng)該有意識要消滅它 減少對代碼生成器的依賴 在處理現(xiàn)有代碼時(shí)盡量用重構(gòu)代替重寫,在重寫之前一定要先重構(gòu) 盡量讓所有的方法都是可測試的
掃碼加我微信進(jìn)群,內(nèi)推和技術(shù)交流,大佬們零距離
開發(fā)者技術(shù)前線 ,匯集技術(shù)前線快訊和關(guān)注行業(yè)趨勢,大廠干貨,是開發(fā)者經(jīng)歷和成長的優(yōu)秀指南。
Java vs Kotlin,開發(fā)人員應(yīng)該首選哪種語言?
再見,x 雷!這款 Github 全能下載工具,很強(qiáng)!



