重構下載功能模塊

背景

最近項目新上線的版本中,出現了很多涉及下載相關的bug;經過艱難的代碼調試排查,可還是沒有準確定位問題。主要還是由於代碼年久,經過多代人的修修補補,到處都是“壞味道”的代碼。跟項目經理溝通過後,同意重構這部分的代碼。下面就簡單記錄一下重構的過程。

項目現狀

項目最早可追溯至2014~2015年,分為配置管理網站(Server),WPF桌面軟件(Client)。桌面軟件又分為:用戶操作界面WPF,後台服務 Windows Services 程序。
在後端Services中,維護一個本地的小型Firebird數據庫,為WPF提供數據和用戶狀態保持;實現了從遠程服務器同步數據到本地,訪問遠程接口下載管理數據上報等功能。而我這次要做的就是,重寫下載管理。下面是關於舊代碼的分析:

  1. 三種不同的下載觸發機制:軟件啟動觸發用戶觸發數據同步到本地觸發
  2. 八種不同的資源下載,分別在不同的表中管理;
  3. 有五套複製粘貼的代碼:軟件啟動(兩套)、用戶觸發(兩套)、數據同步(一套);
  4. 大量無意義嘗試,比如下載失敗404后,短時間內沒有必要再次嘗試;
  5. 狀態管理不統一,有的下載完成狀態改為 ReadyForUse,有的下載完成狀態改為 DownloadSuccess;
  6. 執行方法語義重疊,比如 DownloadPause 和 DownloadStop,DownloadFinished 和 DownloadSuccess;
  7. 大段註釋代碼,這些代碼基本永遠不會再使用的;

重構設計

鑒於項目是在運行階段,一方面要考慮時間成本,另一方面要保證原有的運行方式。在當前軟件的框架下,把重寫的代碼限定在下載模塊內部,對外的接口不做改變。
重構代碼的抽象設計,也是依據當前項目的實際情況,盡可能的通用和易擴展。設計的UML類圖如下:

下面的三個虛類,是下載管理流程的核心,所有的控制邏輯都包含在其中。

  1. DownloadResourceAbstract 虛類 資源文件的基本信息: DatabaseIDResourceID為了兼容不同數據庫表的設計;DownloadPriority 預設優先級;DownloadImmediatelyPriority 用戶觸發的下載,優先級最高,立即執行;其它字段涵義可見字段名稱;
  2. DownloadWorkItemAbstract 虛類 資源下載操作類,包含下載狀態,開始,停止,MD5檢查,狀態更改的回調方法;與一對一關係;
  3. DownloadControlerAbstract 虛類 控制同時下載的數量,根據優先級控制下載的順序;與一對多關係

下面的類,是具體下載方法的實現;當前的項目只有HTTP下載,類圖中也只實現了HTTP的下載的管理功能:

  • 可擴展下載方法設計:FtpClientHttpClient繼承自DownloadClientAbstract
  • 關聯 HTTP 下載,分別實現的子類 HttpDownloadWorkItemHttpDownloadControler

對不同類型的資源文件,組合不同的下載方式:

  • AutoHttpDownloadDealer: 自動下載的資源 + HTTP 下載;
  • UserOperHttpDownloadDealer: 用戶手動操作的資源 + HTTP 下載;
  • 由數據同步到本地的觸發下載資源 + HTTP下載;(未在UML圖中畫出)

發現bug的真實原因

在重構測試階段,意外發現了bug的原因:前段時間更換了文件服務器,而新的文件服務器,不支持斷點續傳,HTTP Status 返回的不是預期的Partial Content(206),而是OK(200);下載文件不存在時,HTTP Status 返回的也不是 404,而返回自定義的 Response Text 。。。

由於這兩個不合理的地方,導致軟件的下載功能,出了好多莫名其妙的bug,再疊加到處複製 + 粘貼“壞味道”的代碼,修復起來異常繁瑣,於是就有了重構這件事情。

個人感受

在當前的項目中,也做了幾次小範圍的重構,要麼代碼影響範圍小,要麼只是在原代碼基礎上套個框架。而這次是徹底幹掉原代碼,重新設計,重新寫。下面是代碼重寫完成后 git merge 的 log:

Showing 1107 revision(s), from revision 6092a531 to revision f336c077 – 1 revision(s) selected, 166 file(s) selected; line: 5226(+) 5251(-) files: modified = 118 added = 28 deleted = 20 replaced = 0

從上面的log匯總信息,好像也不足以展示修改工作量。這些修改大約花費了我一周的時間,自願工作日加班,自願周末加班(有時候代碼寫上頭了,還得強迫自己下班休息去)。開始的前三天的時間,邊讀舊代碼,邊搭建新的框架,嘗試把舊代碼融入到新設計中;後期轉換思路,理解代碼邏輯,把代碼邏輯融入到新設計中

這樣就可以放開手腳的干起來了,寫代碼的時候,感覺時間過的好快,如有神助般各種代碼中的細節,也會不假思索的寫出來。在下階段單元測試中,非常順滑,基本沒有發現什麼bug,真的是酣暢淋漓。

最最讓我寒心的是,好不容易重構測試完代碼了,壓抑着無比激動的心情,希望組裡的同事給個积極肯定的反饋,可連一個“卧槽”也沒有,就行往常平淡的工作日。。。項目經理也是很淡然的說,要儘快拿給測試。

尾聲

即使我的努力和心血沒有得到,預期中的肯定,我也要把這個過程留存記錄下來:把重構的代碼剔除項目信息,再提取合併通用的部分,重新梳理成一個類庫Github 地址;寫一篇文章來記錄一下。

其實,後面我細細回想了一下。如果最開始項目設計的下載功能是,把所有下載資源放在同一張數據庫表中管理,是不是就那不就更簡單了?如果最最早期的設計做好了,後期可以省掉多少功能擴展、修復bug、重構。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

您可能也會喜歡…