2009-10-31 54 views
6

從不知道在哪裏放置功能,如:創建一個Catch-All AppToolbox類 - 這是一個壞習慣嗎?

String PrettyPhone(String phoneNumber) // return formatted (999) 999-9999 
String EscapeInput(String inputString) // gets rid of SQL-escapes like ' 

我創建一個Toolbox類,可作爲不完全滿足需要的其他類功能的倉庫每個應用程序。我讀過這樣的類是糟糕的編程實踐,尤其是糟糕的面向對象設計。然而,參考文獻似乎更多的是個人設計師和開發人員的看法,而不是一個強有力的共識。所以我的問題是,一個全能的工具箱是一個糟糕的設計模式嗎?如果是這樣,爲什麼,還有什麼替代方法?

回答

6

偉大的問題。我總是發現任何足夠複雜的項目都需要「實用」類。我認爲這只是因爲面向對象編程的本質迫使我們將事物放置在一個整齊的結構化分層分類中,但這並不總是可行或合適的(例如,嘗試爲哺乳動物創建一個對象模型,然後將鴨嘴獸)。這是激勵工作到aspect oriented programming(c.f. cross cutting concern)的問題。通常進入公用事業階級的是交叉擔憂的事情。

使用工具箱或實用程序類的一種替代方法是使用擴展方法爲基元類型提供其他所需的功能。然而,陪審團仍然沒有確定是否構成了良好的軟件設計。

我對這個主題的最後一句話是:如果你需要的話,隨它去吧,只要確保你不是更好的設計。當然,如果需要,你可以在以後重構。

1

這沒有什麼錯。有一件事是試圖把它分解成邏輯部分。通過這樣做你可以保持你的智能清潔。

MyCore.Extensions.Formatting.People 
MyCore.Extensions.Formatting.Xml 
MyCore.Extensions.Formatting.Html 
0

我認爲它在真實皺起了眉頭的原因是因爲「工具箱」可以成長,你將要調用一個函數每次裝載一噸資源。

使用適用於實際類中的對象的方法也更優雅 - 只是更有意義。

這就是說,我個人不認爲這是一個問題,但會避免它只是出於上述原因。

2

在這些例子中我會更傾向於延長字符串:

class PhoneNumber extends String 
{ 
    public override string ToString() 
    { 
     // return (999) 999-9999 
    } 
} 

如果你寫下你需要這些功能的所有地方,你可以找出真正使用它,然後將其添加到相應的類。這有時可能很困難,但仍然是您應該瞄準的目標。

編輯:

如下指出的那樣,你不能在C#重寫字符串。我想指出的一點是,在功能屬於這一操作是在一個電話號碼的,這樣是:

interface PhoneNumber 
{ 
    string Formatted(); 
} 

如果你有不同的格式,你可以交換******中國的實現,而不if語句亂拋垃圾代碼,例如,

相反的:

if(country == Countries.UK) output = Toolbox.PhoneNumberUK(phoneNumber); 
else ph = Toolbox.PhoneNumberUS(phoneNumber); 

你可以使用:

output = phoneNumber.Formatted(); 
+0

問題是關於C#,而不是Java。無論如何,在.NET和Java中,String類是封閉的(最終使用Java) – 2009-10-31 03:19:42

2

我認爲一個靜態輔助類,想到的第一件事。這是很常見的,有些人甚至將其稱爲面向對象設計的一部分。然而,助手類最大的問題是它們傾向於成爲一個大轉儲。我想我看到了這種情況發生在我參與的幾個較大的項目上。你正在研究一個類,不知道該把這個和那個函數粘在哪裏,所以你把它放在你的幫助類中。此時,你的助手不能很好地交流他們的工作。類名稱中的'helper'或'util'本身並不意味着什麼。我認爲幾乎所有的OO大師都提倡反對助手,因爲如果你給予足夠的思考,你可以很容易地用更多的描述性類來替換它們。我傾向於贊同這種方法,因爲我認爲幫手違反了單一責任原則。老實說,帶上一粒鹽吧。我對OOP有一點評論:)

+0

我傾向於在公共庫中創建特定的幫助器。所以你沒有看到一個包含IO輔助函數和字符串助手的通用助手類。但我確實有:IoHelper,StringHelper等等。這就是我如何得到我的'關注點分離'。 ;-) – 2009-10-31 08:58:31

1

我的經驗是,效用函數很少發生孤立。如果您需要格式化電話號碼的方法,那麼您還需要驗證電話號碼和解析電話號碼。遵循YAGNI原則,你肯定不想在實際需要之前編寫這些東西,但我認爲繼續前進並將這些功能分離爲單獨的類是有幫助的。隨着時間的推移,這些從單一方法到次要子系統的類別的增長將自然發生。我發現這是保持代碼長期有組織,易於理解和可維護的最簡單方法。

1

當我創建一個應用程序時,我通常會創建一個靜態類,其中包含靜態方法和屬性,我無法確定將其他位置放在哪裏。

這不是一個特別好的設計,但這就是一個重點:它給了我一個地方化一整套設計決策的地方,我還沒有想到。一般而言,隨着應用程序的增長並通過重構進行改進,這些方法和屬性實際應該存在的地方就會變得更加清晰。毫不誇張地說,重構工具的狀態是這樣的,以至於這些改變通常不會特別痛苦。

我試過用另一種方式做,但另一種方式基本上是在我足夠了解我的應用程序以正確設計對象模型之前實現對象模型。如果我做,我花了相當多的時間和精力提出了一個平庸的解決方案,我必須在未來某個時候從頭開始重新審視和重建。好吧,如果我知道我將重構此代碼,那麼我怎麼樣跳過設計和構建不必要的複雜類的步驟,這些類並不真正起作用?

例如,我構建了一個正被多個客戶使用的應用程序。我很早就想到,我需要有一種方法來分離需要針對不同客戶以不同方式工作的方法。我構建了一個靜態實用程序方法,我可以在程序中的任何位置調用一個自定義方法,並將其粘貼到靜態類中。

這工作好幾個月。但是有一點剛開始看起來很醜陋。所以我決定將它重構成它自己的類。在我查看所有調用此方法的地方的代碼時,非常清楚,所有自定義方法確實需要成爲抽象類的成員,客戶的程序集需要包含單個派生類它實現了所有的抽象方法,然後程序只需要從配置中獲取程序集名稱和命名空間,並在啓動時創建自定義要素類的實例。對於我來說,找到所有必須定製的方法非常簡單,因爲我需要做的就是找到每個地方,我的負載自定義功能方法被調用。我花了整整一個下午的時間來完成整個代碼庫並使這個設計合理化,最終的結果是非常靈活和強大,並且解決了正確的問題。

事情是,當我第一次實現該方法(實際上是三個或四個相關的方法)時,我意識到這不是正確的答案。但我不知道足夠的答案是什麼。所以我用最簡單的錯誤答案去解決問題,直到正確的答案變得清晰。

0

我發表了評論,但認爲我會詳細闡述一點。

我所做的是創建一個帶有命名空間的公共庫:[Organization]。[Product] .Common作爲根和子命名空間Helpers。

這裏有幾個人提到了創建一個班級和推動一些他們不知道放哪裏的東西。錯誤。我會說,即使你需要一個輔助方法,它也與某些東西有關,所以創建一個正確命名的(IoHelper,StringHelper等)靜態輔助類並將其放入Helpers命名空間中。那樣,你會得到一些結構,你會得到某種分離的擔憂。

在根名稱空間中,可以使用需要狀態的實例實用程序類(它們存在!)。不用說也可以使用適當的類名,但不要使用助手後綴。

相關問題