百萬行WPF項(xiàng)目代碼重構(gòu)記錄分析
此前帶領(lǐng)小組成員主導(dǎo)過一個(gè)百萬行代碼上位機(jī)項(xiàng)目的重構(gòu)工作,分析項(xiàng)目中存在的問題做了些針對性的優(yōu)化,整個(gè)重構(gòu)工作持續(xù)了一年半之久。
主要針對以下問題:
一 產(chǎn)品型號太多產(chǎn)生非常多重復(fù)性工作
產(chǎn)品型號太多導(dǎo)致代碼工程的分支太多,維護(hù)時(shí)會產(chǎn)生非常多的重復(fù)性的工作。
這是一個(gè)歷史遺留問題,公司成立之初的開發(fā)人員在開發(fā)時(shí)沒有考慮到后期其他機(jī)型的合并而留有余地,后面增加其他機(jī)型而導(dǎo)致的代碼差異,是直接通過創(chuàng)建工程的分支來進(jìn)行維護(hù)。兩個(gè)不同機(jī)型之間可能大部分的業(yè)務(wù)邏輯都相同而只有少部分的界面和業(yè)務(wù)存在差異性,當(dāng)修改一個(gè)共有的bug時(shí),需要在所有分支上面都修改一遍。
同時(shí)有可能因?yàn)榉种Тa的改動,而無法直接進(jìn)行代碼合并,進(jìn)而導(dǎo)致重復(fù)工作量的增加。如果分支不多的時(shí)候倒還好,而當(dāng)機(jī)型越來越多,分支越來越多,這個(gè)重復(fù)性的工作會消耗相當(dāng)大的時(shí)間和精力。所以合并所有機(jī)型的代碼,實(shí)現(xiàn)上位機(jī)代碼在不同機(jī)型上的通用性勢在必行。
一個(gè)良好的軟件架構(gòu)應(yīng)當(dāng)是 面向接口編程,而不是面向?qū)崿F(xiàn)編程。對于不同機(jī)型中的業(yè)務(wù)和流程在主體上是一樣的,只是其中某些細(xì)節(jié)存在差異性的分支,所以我們需要將業(yè)務(wù)代碼提煉出主體流程和對應(yīng)的接口,通過這些業(yè)務(wù)接口來實(shí)現(xiàn)機(jī)型差異所帶來的的業(yè)務(wù)流程上的差異和分支,而非工程上的分支。
在軟件運(yùn)行時(shí),可以通過相應(yīng)的配置來決定業(yè)務(wù)接口的具體實(shí)現(xiàn)是哪一個(gè),同時(shí)由于不同機(jī)型的接口實(shí)現(xiàn)是分離的,修改一個(gè)機(jī)型不會影響到另一個(gè)機(jī)型的代碼。當(dāng)然,在修改主流程代碼時(shí)候就要小心了,需要考慮這一個(gè)改動對所有機(jī)型的影響。除非是非常有把握的情況下直接改動,否則還是先抽象出接口保證原主流程代碼不變,只修改你需要修改的實(shí)現(xiàn)。
二 配置零散,沒有統(tǒng)一的管理機(jī)制,不利于打包
軟件中的配置數(shù)據(jù)保存的地方太零散,有保存在數(shù)據(jù)庫的,有保存在txt文件的,有保存在注冊表的,有保存在app.config的。經(jīng)過不同開發(fā)人員的不斷迭代,積累了很多無用的配置數(shù)據(jù),并且沒有人敢刪除。而售后有時(shí)候?yàn)榱瞬檎倚薷哪硞€(gè)配置需要在各個(gè)地方查找,非常繁瑣。
同時(shí)也因?yàn)楣緳C(jī)型太多導(dǎo)致很多配置數(shù)據(jù)在不同機(jī)型上存在差異性,這些差異性有可能是來自硬件差異,也有可能是來自軟件功能上的差異。而每發(fā)布一個(gè)版本,就有可能需要同時(shí)打包多個(gè)機(jī)型的軟件包,每一個(gè)軟件包至少有1個(gè)G 的大小。而隨著機(jī)型的越來越多,一個(gè)版本不同軟件包也會越來越多,這對于打包人員來說是個(gè)不小的負(fù)擔(dān),同時(shí)也要求打包人員需要明確的知道每一個(gè)機(jī)型配置上的差異性來保證軟件包的正確性。
為了解決這個(gè)問題,我們花了數(shù)個(gè)月的時(shí)間,對所有機(jī)型保存在不同位置的配置做了一個(gè)整理。我們整理出了所有機(jī)型通用的配置,統(tǒng)一保存在數(shù)據(jù)庫表中,同時(shí)為每一個(gè)機(jī)型建立數(shù)據(jù)庫表用來保存存在差異的配置數(shù)據(jù)。為了方便打包人員和售后管理查看這些數(shù)據(jù)庫,我們開發(fā)了一個(gè)配置管理工具用來專門查看和修改配置。
另外,我們?yōu)榱私鉀Q多個(gè)軟件包的問題,把所有硬件相關(guān)的配置整合進(jìn)一個(gè)文件中,并開發(fā)出一個(gè)版本升級軟件。在這個(gè)版本升級軟件中,售后可以選擇機(jī)型對應(yīng)的硬件,升級程序可以通過所選硬件對應(yīng)的配置寫入到數(shù)據(jù)庫中來實(shí)現(xiàn)同一個(gè)軟件包不同機(jī)型的升級工作。
同時(shí)我們開發(fā)了通用的http接口給上層C#程序和下層C++程序使用,用于讀寫數(shù)據(jù)庫的配置數(shù)據(jù)。
由于我們的設(shè)備有多個(gè)PC,并且在醫(yī)院內(nèi)部無法連接外網(wǎng),此前軟件升級時(shí)每個(gè)PC都需要售后人員拷貝軟件包并手動調(diào)用升級腳本來完成升級。而現(xiàn)在,我們的升級程序可以通過遠(yuǎn)程調(diào)用的方式來同時(shí)完成多個(gè)PC的升級工作,做到了一鍵升級功能。
基于第一點(diǎn)的軟件代碼合并,在本次配置優(yōu)化之后,打包人員每次打包僅需要一個(gè)軟件包,即可實(shí)現(xiàn)不同機(jī)型的一鍵升級,省時(shí)又省力。
三 UI和業(yè)務(wù)邏輯混雜
項(xiàng)目以WPF為主,整體使用MVVM框架。項(xiàng)目中沒有使用開源的控件庫,其中含有非常多的高度自定義控件的開發(fā),這些控件的UI表現(xiàn)代碼和業(yè)務(wù)邏輯代碼夾雜在一起,耦合性太高非常不利于理解業(yè)務(wù)代碼和后期維護(hù)。
WPF的MVVM框架本身最大的優(yōu)勢就是為了分離業(yè)務(wù)和UI,降低耦合性,提高可重用性,所以這個(gè)項(xiàng)目并沒有發(fā)揮出MVVM 框架的優(yōu)勢。針對這個(gè)問題,我們分離UI和業(yè)務(wù),提煉出一個(gè)單純的UI庫,這個(gè)UI庫不包含任何的業(yè)務(wù)代碼,除了.Net Framework的依賴庫之外,不依賴項(xiàng)目中的任何其他庫。
每一個(gè)UI控件暴露自定義的依賴屬性,在業(yè)務(wù)邏輯調(diào)用時(shí),通過綁定這些依賴屬性來改變UI的表現(xiàn)邏輯。這樣做的好處是完全分離了UI表現(xiàn)代碼和業(yè)務(wù)邏輯代碼,并且這個(gè)UI庫具有高重用性,可以交給其他項(xiàng)目使用,甚至可以直接開源出來。
而且在后期維護(hù)時(shí),UI代碼的改動與業(yè)務(wù)代碼的改動互不干擾,也有利于Bug的排查。
四 開發(fā)人員的層次不一
由于前期開發(fā)人員的層次不一,并且沒有CodeReview機(jī)制來保證代碼質(zhì)量,導(dǎo)致代碼存在很多低級錯(cuò)誤。
項(xiàng)目中存在大量重復(fù)代碼,明明可以提煉出一個(gè)簡單方便的方法,偏偏要在各個(gè)地方不斷的Copy相同的代碼。
明明只要增加一個(gè)參數(shù)就可以合并成一個(gè)方法,偏偏要寫上幾十個(gè)方法,諸如xxxx1,xxxx2....xxxx30,三十幾個(gè)方法執(zhí)行同樣的功能,只有一個(gè)參數(shù)上的差異。我們的業(yè)績考核又不是看代碼量,這種代碼看了讓人啼笑皆非。
沒有統(tǒng)一的命名規(guī)則,有些屬性首字母小寫,C#和C++風(fēng)格混用,有些命名直接使用縮寫,類似“ggr”這樣縮寫,除了作者誰能看懂這是什么意思?
一個(gè)類,一個(gè)方法代碼過多,幾千行一個(gè)類的文件不在少數(shù),一個(gè)類承擔(dān)的功能也過多也過余復(fù)雜。類和方法都應(yīng)該遵循職責(zé)單一原則,不過在實(shí)際開發(fā)過程中單一原則不太好把控,但應(yīng)該合理的控制代碼行數(shù)。
我們在項(xiàng)目重構(gòu)工作之前,制定了統(tǒng)一的命名風(fēng)格,并嚴(yán)格限制了每個(gè)類每個(gè)方法的代碼行數(shù)。一個(gè)文件,一個(gè)類,最多不超過一千行,一個(gè)方法最多不超過六十行。
六十行代碼一個(gè)屏幕很難放下,這個(gè)要求其實(shí)比較低了,最合理的應(yīng)該是三四十行,一個(gè)屏幕正好可以看完一個(gè)方法的所有代碼。
在項(xiàng)目重構(gòu)的過程中,我們規(guī)定所有人提交的代碼都必須提交給高級工程師CodeReview,高級工程師之間互相CodeReview。每個(gè)人的知識面都是有限的,但可以通過合作來達(dá)到無限的廣度和深度,我們應(yīng)該盡量去避免犯一些低級的、顯而易見的錯(cuò)誤。
五 處理大量的圖片 內(nèi)存和CPU占用過大
5.軟件需要顯示處理大量的圖片,導(dǎo)致程序內(nèi)存和CPU占用過大。
由于我們的軟件需要處理顯示大量的Dicom文件,并且對這些展示的圖片都有較為復(fù)雜的操作,諸如旋轉(zhuǎn),放大、像素提取、銳化等,這些功能都集成在一個(gè)ImageControl中。然而由于我們的ImageControl寫的不合理,讀取一張500K的Dicom并顯示會至少占用2M的內(nèi)存。如果同時(shí)讀取上百個(gè)Dicom文件,程序內(nèi)存可以輕輕松松突破1個(gè)G,同時(shí)由于我們系統(tǒng)中不止一個(gè)程序需要處理這些圖片,所以對系統(tǒng)的內(nèi)存要求非常高。
在前期,我們只能不斷的累加硬件,把內(nèi)存擴(kuò)展到了32G,甚至是64G,然而這只是飲鴆止渴的錯(cuò)誤方式,應(yīng)該從根本上解決ImageControl控件占用內(nèi)存過大的問題,同時(shí)應(yīng)該優(yōu)化程序顯示排列圖片的邏輯。
在考慮到項(xiàng)目人員的分配情況和項(xiàng)目計(jì)劃,我們決定優(yōu)化ImageControl這個(gè)思路暫緩,因?yàn)檫@個(gè)工作量會更大。我們決定先著手優(yōu)化程序展示圖片的邏輯。程序只加載用戶能夠看到的Dicom,當(dāng)用戶下拉進(jìn)度條時(shí),再陸續(xù)加載可見的圖片,并且將其余不可見的ImageControl銷毀,優(yōu)化之后程序占用的內(nèi)存銳減60%-70%,可以接受。
以上就是一次百萬行WPF項(xiàng)目代碼的重構(gòu)記錄的詳細(xì)內(nèi)容,更多關(guān)于WPF項(xiàng)目代碼重構(gòu)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
鴻蒙HarmonyOS開發(fā):Navigation路由導(dǎo)航功能和實(shí)踐
Navigation作為HarmonyOS?NEXT中推薦的路由管理方案,以其強(qiáng)大的功能和靈活性,為開發(fā)者提供了高效的頁面路由管理能力,本文將深入探討基于Navigation的路由管理機(jī)制,從原理到實(shí)踐,帶您一步步領(lǐng)略Navigation組件的強(qiáng)大功能和靈活應(yīng)用,2024-08-08
K8ssandra入門教程之Linux上部署K8ssandra到Kubernetes的過程
K8ssandra不僅幫助我們可以快速可靠地在Kubernetes上部署Cassandra,同時(shí)提供了許多組件,如監(jiān)控、備份、同步、訪問等,這篇文章給大家介紹K8ssandra入門教程之Linux上部署K8ssandra到Kubernetes的過程,一起看看吧2021-10-10
Windows本地部署OpenManus并接入Mistral模型的完整教程
Manus作為一款強(qiáng)大的本地LLM應(yīng)用平臺引起了廣泛關(guān)注,但它需要邀請碼才能使用,不過OpenManus團(tuán)隊(duì)僅用了3小時(shí)就復(fù)刻了一個(gè)功能相似的開源替代方案,下面我們來看看在Windows環(huán)境下的完整部署過程吧2025-03-03
Deepin20安裝開發(fā)環(huán)境的超詳細(xì)教程
這篇文章主要介紹了Deepin20安裝開發(fā)環(huán)境的步驟詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
DedeCMS 5.7 sp1遠(yuǎn)程文件包含漏洞(CVE-2015-4553)
這篇文章主要介紹了DedeCMS 5.7 sp1遠(yuǎn)程文件包含漏洞(CVE-2015-4553)的相關(guān)知識,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
科學(xué)知識:時(shí)間復(fù)雜度計(jì)算方法
這篇文章主要介紹了科學(xué)知識:時(shí)間復(fù)雜度計(jì)算方法,本文介紹了問題的定義、時(shí)間復(fù)雜度計(jì)算步驟、時(shí)間復(fù)雜度計(jì)算規(guī)則等內(nèi)容,需要的朋友可以參考下2015-05-05
鴻蒙系統(tǒng)中的Webview技術(shù)使用方法詳解
webView類是View類的一個(gè)擴(kuò)展,用來顯示網(wǎng)頁,它不包含任何的網(wǎng)頁瀏覽器的特征,像沒有導(dǎo)航控制和地址欄,使用起來也很方便,這篇文章主要給大家介紹了關(guān)于鴻蒙系統(tǒng)中Webview技術(shù)使用的相關(guān)資料,需要的朋友可以參考下2024-07-07
聯(lián)邦學(xué)習(xí)FedAvg中模型聚合過程的理解分析
這篇文章主要為大家介紹了FedAvg中模型聚合過程的理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

