在物件導向的編程中如何處理一些無法歸類的對象

來源:互聯網
上載者:User
這種現象在所有的物件導向工程中都會遇到,在我們編碼時,對一般的對象比如mvc的,我們可以把寫好的類檔案放到相應的 model view controller包裡面去。但是對於一些共用類就不那麼好處理了,比如一些工具類,或者是共用對象,你對它一個類命名一個軟體包吧好像有點浪費,但是他們之間又確實沒啥關聯。

很常用的做法是全部放到一個類似util的包裡,但是最近看到一篇文章說這樣過於簡單粗暴,而且其他人也不好理解這樣的分層,不知道各位是怎麼處理這個問題的。

回複內容:

這種現象在所有的物件導向工程中都會遇到,在我們編碼時,對一般的對象比如mvc的,我們可以把寫好的類檔案放到相應的model view controller包裡面去。但是對於一些共用類就不那麼好處理了,比如一些工具類,或者是共用對象,你對它一個類命名一個軟體包吧好像有點浪費,但是他們之間又確實沒啥關聯。

很常用的做法是全部放到一個類似util的包裡,但是最近看到一篇文章說這樣過於簡單粗暴,而且其他人也不好理解這樣的分層,不知道各位是怎麼處理這個問題的。

對於這種問題,沒有什麼硬性規定,重要的是團隊內部必須形成規範,且團隊的每個成員必須遵守這個規範,這樣的話,就會降低新加入成員的熟悉成本。

我們團隊內部對於項目公用的一些工具類(類似StringUtils,CollectionUtils等),也會以Util打成包;對於一些模組內部的共用對象,如果是一些enum類,則會以enums打成包;如果是一些模組(例如module1等)內部層與層之間的對象,則會先以dto命名包,再將其放入用其模組名命名的子包內,對於一些模組之間共用的對象,放入common命名的子包,其他共用的類,也會類似的先按照業務功能命名包名,然後在包內,按照不同模組劃分子包。

最後一點重要的還是形成並遵守規範。

理論上“對象”應該是由“狀態”(資料)與“行為”(邏輯)組合而成,其中狀態就是類成員變數,行為就是類成員方法。
樓主所說的工具方法,在大多靜態語言中,本身就是非物件導向的東西,又如何以物件導向的方式組織?以Java中常用的Apache Commons Lang庫為例,其中的大半類都是各種靜態方法組成,例如StringUtils等——靜態方法本身就是純邏輯,與對象無關,也不會保持狀態,可以說和平時我們寫過程式語言的函數幾乎一模一樣,所以這類方法參考Apache Commons庫或是java.util包寫就好了,也是業內通用的做法。

但對於樓主提到的這類工具方法,這裡我想補充一下,也算對上段“大多靜態語言”這個定語的解釋。如果拋開語言限制,僅看物件導向,那麼多工具方法的存在其實大半是不合理的

先看一下JDK內建的工具類java.util.Arrays類,隨便挑一個方法,例如Arrays.sort(int[])對數字數組排序:

public static void sort(int[] a);public static void sort(int[] a, int fromIndex, int toIndex);

這個方法的調用為:

int[] xx = ...java.util.Arrays.sort(xx);java.util.Arrays.sort(xx, 1, 10);

以上靜態方法的方式看似很合理——因為本來就是個排序邏輯嘛,但如果寫成這樣呢:

int[] xx = ...xx.sort();xx.sort(1, 10);

是不是更加OO?我本來就要對數組排序,為何不讓數組給自己排序?再看org.apache.commons.StringUtils類,隨便找個方法例如:

public static boolean isAlpha(CharSequence cs);

調用時你更想寫成下面哪樣?

org.apache.commons.StringUtils.isAlpha(aString);
aString.isAlpha();

是不是讓你想起了 "string".trim() "string".indexOf() 這些方法?如果你想,可以把StringUtils裡的所有方法都變成String的成員方法。。。。。那為毛JDK不把這些東東變成成員方法,而是讓它們以靜態方法的方式存在於那些醜陋的純行為類呢?這其實是由各種Java語言特性導致的,例如:

  1. 對null的強制判斷。使得string.isEmpty()有些雞肋而StringUtils.isEmpty(String s)存在合理
  2. primitive類型的存在。使得int[].sort()的實現變為不可能,而int的行為也要靠封裝類Integer來進行。
  3. 對象擴充方式單一。為了保持JDK的精鍊,只能在String上提供有限的方法,而由於無法對String類進行擴充所以只能做成靜態方法。
  4. 。。。

看看其他語言的情況:
1. JavaScript語言的string沒有提供trim()方法,但我們可以擴充:

String.prototype.trim = function() { ... }"string ".trim();

2. Objective-C中對象擴充除了繼承之外還可以使用Category的方式(而且Objective-C中對nil的設定灰常和諧)

@interface NSString (Cute)- (NSString *)beCute;@end...[@"string" beCute];

因此,對於樓主的問題回答是:不是這些類無法歸類,而是沒有歸好類或是語言特性使得很難去歸類——只能歸成Utils工具類了

最後,個人在這些年裡見過的80%以上的 A.method(b) 其實都是可以變化成 b.method(),做到更加OO。其中最多最坑爹還最被廣泛認同的一種寫法就是:

userManager = ...UserManagerSingleton;userManager.save(user);

這裡把明明是User的行為(save)拆分到獨立的UserManager類裡面搞得一個只有行為一個只有狀態本就很奇怪了,還要把完全沒有狀態的UserManager執行個體化一個singleton出來,做一個OO假象給別人看。。。騙誰呢。。。還好Rod Johnson後來自己也承認Spring提倡的這種寫法其實是在延續EJB時代的“事務指令碼”,是anti-OO的東東。國內技術環境浮躁,不少人都是從SSH學起,還以為自己一直在寫OO的代碼,還以為自己懂OO。。。。

這就是我不提倡純物件導向的原因之一, 很多時候可以作為一個函數的東東, 一定要被封裝成一個類, 加上一個命名空間, 寫成一個靜態方法.

如果用一個比較好的語言系統, 應該首先語言標準庫就提供很多重要的函數和類

其次是第三方庫, 作為vendor

然後是本身有價值的東西, 可以有common, 或者內部開源成為一個第三方庫, 規範介面.

我不提倡在一個公司的幾個projects之間share common, 否則其他團隊的修改會bug/crash你的產品, 不如將原來的common fork出來加以修改.

最後是和這個項目的直接相關的代碼邏輯

團隊溝通是成本最高的, 唯一的辦法, 控制Team Dev人數

關鍵還是在於你對代碼的組織能力和對商務邏輯的建模能力。你的類名是否起得合適,能否描述這個類的真正業務職責。你的包名、類名應該反映你的商務邏輯,而不是簡單的model,controll,view,這種名字只是反映的軟體的架構,無法反映你真正的業務,我覺得是應該避免的。

我覺得是可以在controller和model間再思考的。

mvc也只是一種程式碼群組織形式而已,但不要被mvc限定住,一個良好的層次可以不只是mvc。
如果你的業務情境裡這三層是很簡單,比如“資料庫取下資料,controller裡稍微加工下,view顯示”,那麼mvc就夠了。
可如果controller下面的資料群組織相當複雜,比如需要操作很多其他的系統,或是經過複雜的業務處理後才能得到最終的一份業務資料。那麼controller和model之間可以做的文章還是很多的。

那這介於controller和model之間代碼如何組織,可能是初步採用物件導向的思路後遇到的煩惱,但當真正理解物件導向對象的概念後其實情況還是可以很清楚的。覺得可以參考下一些關於“設計模式”的東西。

可以架設出很多個屬於service(在本地對很多功能進行封裝)的類,或者甚至把較獨立的功能就封裝成內部的api(http的server)。

物件導向本身就是坑,不是什麼東西都一定要用類來封裝的,比如函數,比如靜態方法,比如全域對象?做java的有沒有考慮過單例這麼自然的東西為什麼到java裡就成了一個模式?

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.