java代碼重構技巧(java構造方法重寫)

本文目錄一覽:

常見代碼重構技巧(非常實用)

1_代碼重構漫畫.jpeg

項目在不斷演進過程中,代碼不停地在堆砌。如果沒有人為代碼的質量負責,代碼總是會往越來越混亂的方向演進。當混亂到一定程度之後,量變引起質變,項目的維護成本已經高過重新開發一套新代碼的成本,想要再去重構,已經沒有人能做到了。

造成這樣的原因往往有以下幾點:

對於此類問題,業界已有有很好的解決思路:通過持續不斷的重構將代碼中的“壞味道”清除掉。

重構一書的作者Martin Fowler對重構的定義:

根據重構的規模可以大致分為大型重構和小型重構:

大型重構 :對頂層代碼設計的重構,包括:系統、模塊、代碼結構、類與類之間的關係等的重構,重構的手段有:分層、模塊化、解耦、抽象可復用組件等等。這類重構的工具就是我們學習過的那些設計思想、原則和模式。這類重構涉及的代碼改動會比較多,影響面會比較大,所以難度也較大,耗時會比較長,引入bug的風險也會相對比較大。

小型重構 :對代碼細節的重構,主要是針對類、函數、變量等代碼級別的重構,比如規範命名和注釋、消除超大類或函數、提取重複代碼等等。小型重構更多的是使用統一的編碼規範。這類重構要修改的地方比較集中,比較簡單,可操作性較強,耗時會比較短,引入bug的風險相對來說也會比較小。什麼時候重構 新功能開發、修bug或者代碼review中出現“代碼壞味道”,我們就應該及時進行重構。持續在日常開發中進行小重構,能夠降低重構和測試的成本。

2_代碼常見問題.png

代碼重複

方法過長

過大的類

邏輯分散

嚴重的情結依戀

數據泥團/基本類型偏執

不合理的繼承體系

過多的條件判斷

過長的參數列

臨時變量過多

令人迷惑的暫時字段

純數據類

不恰當的命名

過多的注釋

3_代碼質量如何衡量.jpg

代碼質量的評價有很強的主觀性,描述代碼質量的詞彙也有很多,比如可讀性、可維護性、靈活、優雅、簡潔。這些詞彙是從不同的維度去評價代碼質量的。其中,可維護性、可讀性、可擴展性又是提到最多的、最重要的三個評價標準。

要寫出高質量代碼,我們就需要掌握一些更加細化、更加能落地的編程方法論,這就包含面向對象設計思想、設計原則、設計模式、編碼規範、重構技巧等。

4_SOLID原則.png

一個類只負責完成一個職責或者功能,不要存在多於一種導致類變更的原因。

單一職責原則通過避免設計大而全的類,避免將不相關的功能耦合在一起,來提高類的內聚性。同時,類職責單一,類依賴的和被依賴的其他類也會變少,減少了代碼的耦合性,以此來實現代碼的高內聚、松耦合。但是,如果拆分得過細,實際上會適得其反,反倒會降低內聚性,也會影響代碼的可維護性。

添加一個新的功能,應該是通過在已有代碼基礎上擴展代碼(新增模塊、類、方法、屬性等),而非修改已有代碼(修改模塊、類、方法、屬性等)的方式來完成。

開閉原則並不是說完全杜絕修改,而是以最小的修改代碼的代價來完成新功能的開發。

很多設計原則、設計思想、設計模式,都是以提高代碼的擴展性為最終目的的。特別是 23 種經典設計模式,大部分都是為了解決代碼的擴展性問題而總結出來的,都是以開閉原則為指導原則的。最常用來提高代碼擴展性的方法有:多態、依賴注入、基於接口而非實現編程,以及大部分的設計模式(比如,裝飾、策略、模板、職責鏈、狀態)。

子類對象(object of subtype/derived class)能夠替換程序(program)中父類對象(object of base/parent class)出現的任何地方,並且保證原來程序的邏輯行為(behavior)不變及正確性不被破壞。

子類可以擴展父類的功能,但不能改變父類原有的功能

調用方不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。接口隔離原則提供了一種判斷接口的職責是否單一的標準:通過調用者如何使用接口來間接地判定。如果調用者只使用部分接口或接口的部分功能,那接口的設計就不夠職責單一。

高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象。

一個對象應該對其他對象保持最少的了解

盡量使用合成/聚合的方式,而不是使用繼承。

單一職責原則告訴我們實現類要職責單一;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;接口隔離原則告訴我們在設計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,告訴我們要對擴展開放,對修改關閉。

image.png

模塊結構說明

代碼開發要遵守各層的規範,並注意層級之間的依賴關係。

多個方法代碼重複、方法中代碼過長或者方法中的語句不在一個抽象層級。

方法是代碼復用的最小粒度,方法過長不利於復用,可讀性低,提煉方法往往是重構工作的第一步。

意圖導向編程 :把處理某件事的流程和具體做事的實現方式分開。

將函數放進一個單獨對象中,如此一來局部變量就變成了對象內的字段。然後你可以在同一個對象中將這個大型函數分解為多個小型函數。

方法參數比較多時,將參數封裝為參數對象

任何有返回值的方法,都不應該有副作用

臨時變量僅使用一次或者取值邏輯成本很低的情況下

將複雜表達式(或其中一部分)的結果放進一個臨時變量,以此變量名稱來解釋表達式用途

把複雜的條件表達式拆分成多個條件表達式,減少嵌套。嵌套了好幾層的if – then-else語句,轉換為多個if語句

當出現大量類型檢查和判斷時,if else(或switch)語句的體積會比較臃腫,這無疑降低了代碼的可讀性。 另外,if else(或switch)本身就是一個“變化點”,當需要擴展新的類型時,我們不得不追加if else(或switch)語句塊,以及相應的邏輯,這無疑降低了程序的可擴展性,也違反了面向對象的開閉原則。

非正常業務狀態的處理,使用拋出異常的方式代替返回錯誤碼

某一段代碼需要對程序狀態做出某種假設,以斷言明確表現這種假設。

當使用一個方法返回的對象時,而這個對象可能為空,這個時候需要對這個對象進行操作前,需要進行判空,否則就會報空指針。當這種判斷頻繁的出現在各處代碼之中,就會影響代碼的美觀程度和可讀性,甚至增加Bug的幾率。

空引用的問題在Java中無法避免,但可以通過代碼編程技巧(引入空對象)來改善這一問題。

根據單一職責原則,一個類應該有明確的責任邊界。但在實際工作中,類會不斷的擴展。當給某個類添加一項新責任時,你會覺得不值得分離出一個單獨的類。於是,隨着責任不斷增加,這個類包含了大量的數據和函數,邏輯複雜不易理解。

此時你需要考慮將哪些部分分離到一個單獨的類中,可以依據高內聚低耦合的原則。如果某些數據和方法總是一起出現,或者某些數據經常同時變化,這就表明它們應該放到一個類中。另一種信號是類的子類化方式:如果你發現子類化隻影響類的部分特性,或者類的特性需要以不同方式來子類化,這就意味着你需要分解原來的類。

繼承使實現代碼重用的有力手段,但這並非總是完成這項工作的最佳工具,使用不當會導致軟件變得很脆弱。與方法調用不同的是,繼承打破了封裝性。子類依賴於其父類中特定功能的實現細節,如果父類的實現隨着發行版本的不同而變化,子類可能會遭到破壞,即使他的代碼完全沒有改變。

舉例說明,假設有一個程序使用HashSet,為了調優該程序的性能,需要統計HashSet自從它創建以來添加了多少個元素。為了提供該功能,我們編寫一個HashSet的變體。

通過在新的類中增加一個私有域,它引用現有類的一個實例,這種設計被稱為組合,因為現有的類變成了新類的一個組件。這樣得到的類將會非常穩固,它不依賴現有類的實現細節。即使現有的類添加了新的方法,也不會影響新的類。許多設計模式使用就是這種套路,比如代理模式、裝飾者模式

繼承與組合如何取捨

Java提供了兩種機制,可以用來定義允許多個實現的類型:接口和抽象類。自從Java8為接口增加缺省方法(default method),這兩種機制都允許為實例方法提供實現。主要區別在於,為了實現由抽象類定義的類型,類必須稱為抽象類的一個子類。因為Java只允許單繼承,所以用抽象類作為類型定義受到了限制。

接口相比於抽象類的優勢:

接口雖然提供了缺省方法,但接口仍有有以下局限性:

接口缺省方法的設計目的和優勢在於:

為了接口的演化

可以減少第三方工具類的創建

可以避免創建基類

由於接口的局限性和設計目的的不同,接口並不能完全替換抽象類。但是通過對接口提供一個抽象的骨架實現類,可以把接口和抽象類的優點結合起來。 接口負責定義類型,或許還提供一些缺省方法,而骨架實現類則負責實現除基本類型接口方法之外,剩下的非基本類型接口方法。擴展骨架實現佔了實現接口之外的大部分工作。這就是模板方法(Template Method)設計模式。

Image [5].png

接口Protocol:定義了RPC協議層兩個主要的方法,export暴露服務和refer引用服務

抽象類AbstractProtocol:封裝了暴露服務之後的Exporter和引用服務之後的Invoker實例,並實現了服務銷毀的邏輯

具體實現類XxxProtocol:實現export暴露服務和refer引用服務具體邏輯

由於為了保持Java代碼的兼容性,支持和原生態類型轉換,並使用擦除機制實現的泛型。但是使用原生態類型就會失去泛型的優勢,會受到編譯器警告。

每一條警告都表示可能在運行時拋出ClassCastException異常。要盡最大的努力去消除這些警告。如果無法消除但是可以證明引起警告的代碼是安全的,就可以在儘可能小的範圍中,使用@SuppressWarnings(“unchecked”)註解來禁止警告,但是要把禁止的原因記錄下來。

參數化類型不支持協變的,即對於任何兩個不同的類型Type1和Type2而言,List既不是List的子類型,也不是它的超類。為了解決這個問題,提高靈活性,Java提供了一種特殊的參數化類型,稱作有限制的通配符類型,即List? extends E和List? super E。使用原則是producer-extends,consumer-super(PECS)。如果即是生產者,又是消費者,就沒有必要使用通配符了。

還有一種特殊的無限制通配符List?,表示某種類型但不確定。常用作泛型的引用,不可向其添加除Null以外的任何對象。

嵌套類(nested class)是指定義在另一個類的內部的類。 嵌套類存在的目的只是為了它的外部類提供服務,如果其他的環境也會用到的話,應該成為一個頂層類(top-level class)。 嵌套類有四種:靜態成員類(static member class)、非靜態成員類(nonstatic member class)、匿名類(anonymous class)和 局部類(local class)。除了第一種之外,其他三種都稱為內部類(inner class)。

總而言之,這四種嵌套類都有自己的用途。假設這個嵌套類屬於一個方法的內部,如果只需要在一個地方創建實例,並且已經有了一個預置的類型可以說明這個類的特徵,就要把它做成匿名類。如果一個嵌套類需要在單個方法之外仍然可見,或者它太長了,不適合放在方法內部,就應該使用成員類。如果成員類的每個實例都需要一個指向其外圍實例的引用,就要把成員類做成非靜態的,否則就做成靜態的。

通過對常見場景的代碼邏輯進行抽象封裝,形成相應的模板工具類,可以大大減少重複代碼,專註於業務邏輯,提高代碼質量。

面向對象編程相對於面向過程,多了實例化這一步,而對象的創建必須要指定具體類型。我們常見的做法是“哪裡用到,就在哪裡創建”,使用實例和創建實例的是同一段代碼。這似乎使代碼更具有可讀性,但是某些情況下造成了不必要的耦合。

對於頂層的(非嵌套的)類和接口,只有兩種的訪問級別:包級私有的(沒有public修飾)和公有的(public修飾)。

對於成員(實例/域、方法、嵌套類和嵌套接口)由四種的訪問級別,可訪問性如下遞增:

正確地使用這些修飾符對於實現信息隱藏是非常關鍵的,原則就是:儘可能地使每個類和成員不被外界訪問(私有或包級私有)。這樣好處就是在以後的發行版本中,可以對它進行修改、替換或者刪除,而無須擔心會影響現有的客戶端程序。

不可變類是指其實例不能被修改的類。每個實例中包含的所有信息都必須在創建該實例時提供,並在對象的整個生命周期內固定不變。不可變類好處就是簡單易用、線程安全、可自由共享而不容易出錯。Java平台類庫中包含許多不可變的類,比如String、基本類型包裝類、BigDecimal等。

為了使類成為不可變,要遵循下面五條規則:

可變性最小化的一些建議:

TDD的最終目標是整潔可用的代碼(clean code that works)。大多數的開發者大部分時間無法得到整潔可用的代碼。辦法是分而治之。首先解決目標中的“可用”問題,然後再解決“代碼的整潔”問題。這與體系結構驅動(architecture-driven)的開發相反。

採用TDD另一個好處就是讓我們擁有一套伴隨代碼產生的詳盡的自動化測試集。將來無論出於任何原因(需求、重構、性能改進)需要對代碼進行維護時,在這套測試集的驅動下工作,我們代碼將會一直是健壯的。

Image [6].png

添加一個測試 – 運行所有測試並檢查測試結果 – 編寫代碼以通過測試 – 運行所有測試且全部通過 – 重構代碼,以消除重複設計,優化設計結構

作者:VectorJin

昆明java培訓學校告訴你進行代碼重構有哪些常見的問題?

很多人在進行軟件開發和軟件維護的時候會發現一個嚴重的問題,需要對軟件代碼進行重構,讓系統更加穩定的運行。那麼在進行代碼重構的過程中有哪些常見的問題呢?下面雲南電腦培訓為大家具體介紹。

1、任務管理問題和離線模式問題。

我們的線服務是眾所周知的,我們往往容易受到網上商業邏輯守則的約束,這些守則往往忽略了在線規則的管理和維護。然而,在現場,在線規則和守則也很重要。因此,雲南IT培訓發現有效維護守則和離線任務是我們面臨的問題。

2、特徵日誌問題

在推薦系統中,我們經常遇到特徵的拼寫和特徵的“穿越時間”問題。特徵時間穿越是指,使用在模型訓練時無法預測無法得到的“未來信息”,這主要是因為訓練label與特徵的連接時間不嚴格。

3、服務監製問題

一個通用的推薦系統應當在基礎監視上儘可能通用地再利用,具體的業務應當減少對監視的開發量,並且昆明IT培訓發現這樣更加方便業務定位問題。

4、離線任務的管理問題

在包含推薦系統的算法方向上,需要構建大量的脫機任務,支持各種數據計算業務,需要支持模型的定時訓練工作。但是在實際工作中,我們往往忽略了離線任務代碼管理的重要性,當時間變長時,昆明電腦培訓發現各種數據和特徵的質量往往是不能保證的。

昆明java培訓學校告訴你代碼重構過程中會產生哪些常見問題?

相信大家在開發軟件和進行軟件維護的時候也會發現,有時候我們會針對一些軟件的功能進行代碼重構來讓系統運行更加的穩定。今天雲南java培訓就一起來了解一下,在代碼重構的過程中都會遇到哪些問題。

1、離線任務和模型的管理問題。我們做在線服務的都有體會,我們經常容易對線上業務邏輯代碼更關注一些,而往往忽視離線代碼任務的管理和維護。但離線代碼任務和模型在推薦場景中又至關重要。因此如何有效維護離線代碼和任務,是我們面臨的一個問題。

2、特徵日誌問題。在推薦系統中,我們常常會遇到特徵拼接和特徵的『時間穿越』的問題。所謂特徵時間穿越,指的是模型訓練時用到了預測時無法獲取的『未來信息』,這主要是訓練label和特徵拼接時時間上不夠嚴謹導致。如何構建便捷通用的特徵日誌,減少特徵拼接錯誤和特徵穿越,是我們面臨的二個問題。

3、服務監控問題。一個通用的推薦系統應該在基礎監控上做到儘可能通用可復用,減少具體業務對於監控的開發量,並方便業務定位問題。

4、離線任務和模型的管理問題。

在包括推薦系統的算法方向中,需要構建大量離線任務支持各種數據計算業務,和模型的定時訓練工作。但實際工作中,我們往往忽略離線任務代碼管理的重要性,當時間一長,各種數據和特徵的質量往往無法保證。為了儘可能解決這樣的問題,我們從三方面來做,一,將通用推薦系統依賴的離線任務的代碼統一到一處管理;二,結合公司離線任務管理平台,將所有任務以通用包的形式進行管理,這樣保證所有任務的都是依賴新包;三,建設任務結果的監控體系,將離線任務的產出完整監控起來。

5、特徵日誌問題。

AndrewNg之前說過:『挖掘特徵是困難、費時且需要專業知識的事,應用機器學習其實基本上是在做特徵工程。』我們理想中的推薦系統模型應該是有乾淨的RawData,方便處理成可學習的Dataset,通過某種算法學習model,來達到預測效果不斷優化的目的。

但現實中,我們需要處理各種各樣的數據源,有數據庫的,有日誌的,有離線的,有在線的。這麼多來源的RawData,不可避免的會遇到各種各樣的問題,比如特徵拼接錯誤,特徵『時間穿越』等等。

這裡邊反應的一個本質問題是特徵處理流程的規範性問題。那麼我們是如何來解決這一點呢,先,我們用在線代替了離線,通過在線落特徵日誌,而不是RawData,並統一了特徵日誌Proto,如此就可以統一特徵解析腳本。

雲南北大青鳥java培訓告訴你系統重構需要注意哪些問題?

當軟件工程師從事軟件開發時,在時間比較緊的情況下,通常需要讓軟件最先上線,然後在後期工作中慢慢重新配置和調整,以替換由於時間不足而留下的漏洞。那麼在進行調整的過程中,有什麼需要了解呢?其中最重要的是心態、技巧和技術三個方面。在學習電腦培訓的過程中,還需要掌握更多的問題。

一、關於心態

在任何項目的實踐中,心態問題是最重要的,其次就是技術問題。為什麼心態問題是最重要的呢?因為對於10年以上的舊功能模塊,最複雜的功能模塊實際上是業務邏輯,而不是技術實現。因此,對於舊系統的重建,需要整理模塊中大規模累積的業務邏輯,這本身就為重構提供了無形的壓力。與核心業務模塊相結合,較少的業務邏輯將導致在線收入減少,最終導致程序員的大量時間付出。這一系列背景使得重構過程中的心理壓力變得更大。

重構項目的最佳方法是仔細澄清所有業務邏輯,然後使用思維來繪製圖片,這樣您就可以清楚地了解過去所有的業務邏輯。清晰的業務邏輯,對於後續系統重新設計和編碼有很大的幫助,並且還是角色的決定性部分。

二、關於技巧

重構的經驗和技巧遠比技術實力重要,因為經驗可以減少許多不必要的麻煩。在我說出自己的想法之前,我想問一個問題:如果在重構的過程中遇到一個問題,進行處理會讓項目更好,但是不解決也沒有太大的影響,你會如何去做呢?在這種情景下,麗江麗江北大青鳥建議,最好是不做,在不影響重構的目標的情況下,能不做最好是不做,這並不是懶惰,而是你永遠不知道會有多大的坑在等着你。

三、關於技術

技術是最後一步,但是並不是最重要的一步,至少在我進行重構的過程中,由於我的心態或缺乏技巧,我基本上能夠完成了60%的工作。在我的項目中重構的技術能夠在不到10%的時間內完成。重構技術實際上更多地是使用設計模式以簡潔的代碼呈現複雜的業務邏輯。簡而言之,它是使用設計模式來承載複雜的業務邏輯並使編寫的代碼儘可能簡潔。

在進行重構需要更多測試,主要是對業務的深刻理解和對抽象思維的進一步使用。如果業務是深入和抽象的,那麼可以選擇麗江北大青鳥進行學習設計模式。如果是相反的話,就沒有辦法做到這一點。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/306583.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2025-01-02 12:01
下一篇 2025-01-02 12:01

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python字符串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字符串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字符串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • 使用vscode建立UML圖的實踐和技巧

    本文將重點介紹在使用vscode在軟件開發中如何建立UML圖,並且給出操作交互和技巧的指導。 一、概述 在軟件開發中,UML圖是必不可少的重要工具之一。它為軟件架構和各種設計模式的…

    編程 2025-04-29
  • Python基礎代碼用法介紹

    本文將從多個方面對Python基礎代碼進行解析和詳細闡述,力求讓讀者深刻理解Python基礎代碼。通過本文的學習,相信大家對Python的學習和應用會更加輕鬆和高效。 一、變量和數…

    編程 2025-04-29
  • 倉庫管理系統代碼設計Python

    這篇文章將詳細探討如何設計一個基於Python的倉庫管理系統。 一、基本需求 在着手設計之前,我們首先需要確定倉庫管理系統的基本需求。 我們可以將需求分為以下幾個方面: 1、庫存管…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • 寫代碼新手教程

    本文將從語言選擇、學習方法、編碼規範以及常見問題解答等多個方面,為編程新手提供實用、簡明的教程。 一、語言選擇 作為編程新手,選擇一門編程語言是很關鍵的一步。以下是幾個有代表性的編…

    編程 2025-04-29
  • Python實現簡易心形代碼

    在這個文章中,我們將會介紹如何用Python語言編寫一個非常簡單的代碼來生成一個心形圖案。我們將會從安裝Python開始介紹,逐步深入了解如何實現這一任務。 一、安裝Python …

    編程 2025-04-29
  • 怎麼寫不影響Python運行的長段代碼

    在Python編程的過程中,我們不可避免地需要編寫一些長段代碼,包括函數、類、複雜的控制語句等等。在編寫這些代碼時,我們需要考慮代碼可讀性、易用性以及對Python運行性能的影響。…

    編程 2025-04-29
  • 北化教務管理系統介紹及開發代碼示例

    本文將從多個方面對北化教務管理系統進行介紹及開發代碼示例,幫助開發者更好地理解和應用該系統。 一、項目介紹 北化教務管理系統是一款針對高校學生和教職工的綜合信息管理系統。系統實現的…

    編程 2025-04-29

發表回復

登錄後才能評論