[英]What is the best way to refactor Utility class in java (static classes)
我正在考慮重構我們的一些實用程序類(靜態類)。 靜態類很難測試,主要問題在於它使我們的代碼非常緊密地耦合在一起,具有很多依賴性。 用於重構的最佳設計模式是什么? 我曾考慮過使用構建器實現不可變的對象,但不確定
將此代碼視為1我想重構
public class UtilTest {
public static boolean isEligibleItem(Item item){
if(isCondition1(item)){
return isCondition2(item);
}
return false;
}
public static boolean isCondition1(Item item){
//go to service that go to the data base
return false;
}
public static boolean isCondition2(Item item){
//go to service that go to the data base
return false;
}
}
如果要測試isEligibleItem()方法,則需要模擬轉到db的2方法。 我不能這樣做,因為它們是靜態的。 我想避免使用Powermock
人們說靜態方法很難測試的原因更多在於它如何隨着時間的推移將不相關的類緊密地耦合在一起,並且減少了內聚力以及引入了看不見的副作用 。 這三件事比一些單元測試揮手抱怨更為重要
它比測試static
方法本身更多的是測試與其他代碼的交互。 這才是Java真正需要將Functions
作為第一類對象的地方。
在大多數情況下,只有static
方法的類絕對是代碼的味道。 也有例外,但是這種反模式很容易被非面向對象語言的初學者和老手濫用。
異常主要是那些可能被認為是標記為final
類(例如, Immutable
String
所缺少的東西。
擁有具有通用static
方法的Strings
類還不錯,因為String
是不可變的(無副作用),並且您無法向String
類添加任何內容,因此您沒有很多選擇。 Integer
等也是如此, Guava
具有這種命名約定,並且適用於這些不可變的對象。
static
方法往往會帶來很多副作用。 拿一個對象並以某種不透明的方式操縱該對象的事物是不好的,更糟的是,當它們然后根據傳入的實例查找其他對象並對其進行操縱時,它們混淆了正在發生的事情並緊密耦合,並且內聚力低。
關於緊密內聚的討論不多於耦合,但它同樣重要。 它們是同一枚硬幣的兩個面,因此忽略其中一個會導致另一面遭受損失。
這些static
方法應該放在作為參數的類上,並與這些類緊密耦合。 在這種情況下,為什么它們不在Item
類上?
一旦添加另一個采用SomeOtherItem
static
方法,您就將不相關的類間接耦合在一起。
補救此問題的最簡單方法是將事物移動到更靠近它們所屬位置的Item
類。
如果您確實有一些general
事情,或者由於某些final
原因或其他原因而無法將其添加到類中,那么使用接口和Provider
模式是使用Factory
生成Provider
實例的最佳方法,甚至更好。
然后,您可以使用Guice
東西注入所需的任何實現,具體取決於它是否為測試。
甚至還有一個混合Utility
模式,可以從Provider
中注入實現,這將為您Provider
static
方法的便利性以及不使用它的靈活性和可維護性。
對可測試的設置的簡單翻譯是:
public class UtilTest {
private final MyDatabaseService service;
public UtilTest(MyDatabaseService service) {
this.service = service;
}
public boolean isEligibleItem(Item item){
if(isCondition1(item)){
return isCondition2(item);
}
return false;
}
public boolean isCondition1(Item item){
this.service.goToDataBase();
return false;
}
public boolean isCondition2(Item item){
this.service.goToDataBase2();
return false;
}
}
這並不能消除所有問題,但這只是一個開始,您可以使用模擬的數據庫服務來測試您的類。
如果您想進一步推動事情,可以聲明一個接口,其中包含您希望UtilTest
公開的所有方法(您可能還希望重命名該類...),並使UtilTest
實現它。 應該將所有使用UtilTest
的代碼重寫為使用該接口,然后您可以完全直接地模擬UtilTest
。 是否值得,在很大程度上取決於UtilTest
的實際復雜UtilTest
。 如果它執行的任務相對簡單,您可能會認為它比它值得的麻煩。 但是,如果其中要進行一些繁重的處理,則您肯定希望使其易於模擬。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.