簡體   English   中英

針對接口編程:您是否為所有域類編寫接口?

[英]Programming against interfaces: Do you write interfaces for all your domain classes?

我同意,針對接口的編程是一種很好的做法。 在大多數情況下,Java“接口”在這個意義上意味着語言構造接口,因此您可以編寫接口和實現類,並且在大多數情況下使用接口而不是實現類。

我想知道這是否也是編寫域模型的好習慣。 因此,例如,如果您有一個域類Customer,並且每個客戶可能都有一個Orders列表,您通常也會編寫接口ICustomer和IOrder。 客戶也會有一份IOrders而不是Orders的列表嗎? 或者你會在域模型中使用接口,只有它真的是由域驅動的,例如你至少有兩種不同類型的訂單? 換句話說,您是否會因為域模型中的技術需求而使用接口,或者僅在與實際域相關時才使用接口?

編寫接口“只是因為”讓我感到浪費時間和精力,更不用說違反了KISS原則。

當它們實際用於表示相關類的常見行為時,我會編寫它們,而不僅僅是一個花哨的頭文件。

不要過度設計你的系統。 如果你發現你有幾種類型的訂單,並認為為Orders聲明一個接口是合適的,而不是在需要時重構它。 對於域模型,特定接口在開發生命周期中會發生很大變化的概率很高,因此很早就編寫接口很有用。

接口是隔離組件的絕佳方式,用於單元測試和一般依賴關系管理。 說,我經常更喜歡抽象類,所以至少有一些常見的行為被卸載,而不是強迫接口帶來的一些重復。 現代IDE可以快速輕松地生成界面,因此它們沒有那么多工作:-)

不,我只使用域對象上的接口來保持松散耦合。 對我來說,使用接口開發自己的代碼的主要方面是我可以在進行單元測試時輕松創建模擬。 我沒有看到模仿域對象的重點,因為它們沒有服務層或DAO層類所具有的相同依賴性。

這當然不意味着偏離在域對象中使用接口。 適當時使用。 例如,最近我一直在開發一個webapp,其中不同類型的域對象對應於用戶可以留下評論的永久鏈接頁面。 因此,每個域對象現在都實現了“可注釋”接口。 然后將所有基於注釋的代碼編程到Commentable接口而不是Domain Objects。

實際上,這個問題是關於“對接口編程”的常見誤解的一個例子。

你看,這一個很好的原則,但並不意味着許多人認為這意味着!

“編程到一個接口,而不是一個實現”(來自GoF書)意味着,而不是你應該盡力為所有東西創建單獨的接口。 如果您有一個ArrayList對象,則將變量/ field / parameter / return類型聲明為List類型。 然后客戶端代碼只處理接口類型。

在Joshua Bloch的“Effective Java”一書中,原則在“項目52:通過接口引用對象”中更清楚地表達出來。 它甚至用粗體字母說:

如果不存在適當的接口,則通過類而不是接口引用對象是完全合適的。

對於單元測試,情況完全取決於所使用的模擬工具的功能。 使用我自己的工具JMockit ,我可以像使用接口和依賴注入的代碼一樣輕松編寫單元測試,對於使用從測試代碼中實例化的最終類的代碼。

因此,對我來說,答案是:始終使用已經存在的接口,但如果沒有充分的理由,則避免創建新接口(並且可測試性本身不應該是一個)。

我建議保持精益和敏捷 - 在你需要之前不要做任何事情,然后讓IDE在你需要的時候為你做重構。

它在IDEA / eclipse中非常微不足道,當你決定需要一個時,將一個具體的類變成一個接口。

然后使用依賴注入SpringGuice,如果你有很多接口實現注入代碼中你正在使用'new'的地方

在需要之前編寫接口(用於測試或架構)是一種矯枉過正。

此外,手動編寫接口是浪費時間。 您可以使用Resharper的重構“Pull Members”讓它在幾秒鍾內創建特定類的新界面。 與IDE集成的其他重構工具也應具有類似的功能。

我通常只使用對較小項目有意義的接口。 但是,我的最新工作有一個大型項目,幾乎每個域對象都有一個接口。 它可能有點過頭了,這肯定很煩人,但我們測試和使用Spring進行依賴注入排序的方式需要它。

我們主要用Wicket,Spring和Hibernate編寫Web應用程序,我們使用Spring Beans的接口,例如Services和DAO。 對於這些類,接口完全有意義。 但我們也為每個域類使用接口,我認為這只是矯枉過正。

即使您非常確定只有一個具體類型的模型對象,使用接口會使模擬和測試變得更容易(但是現在有一些框架可以幫助您自動生成模擬類,即使對於具體的Java類 - Mockito,JTestR,Spring,Groovy ...)

但我更經常使用接口來提供服務,因為在測試過程中模擬掉它們更為重要,而對接口進行編程可以幫助你思考像封裝這樣的東西。

如果您將域類用於單元測試,那么編寫域類接口就有意義了。 我們在單元測試中使用Mock對象。 因此,如果您有域對象的接口,並且您的域對象本身尚未就緒,但您的客戶端可以借助模擬對象測試其對接口的使用。

Inteface還為您的域模型測試接口的多個實現。 所以,我不認為它總是矯枉過正。

我認為針對接口編程的主要原因是可測試性。 因此,對於域對象 - 只需堅持使用POJO或POC#Os :)等,即只是讓您的類不添加任何特定的框架,以防止它們產生不同的構建和運行時依賴性,這就是全部。 但是,為DAO創建接口是一個好主意。

我們從一切中提取接口只是因為它有助於測試(模擬)和AOP之類的東西。 Eclipse可以自動執行此操作:Refactor-> Extract Interface。

如果您以后需要修改該類,可以使用Refactor-> Pull Up ...將您需要的方法提取到界面上。

*我這樣做是因為我需要它來創建我的域對象的代理。

這是另一件要記住的事情,我已經參與其中,特別是對於生成的域和DAO對象。 很多接口都太具體了。 說很多域對象都有ID和狀態字段,為什么它們不共享一個公共接口? 這讓我感到沮喪,這是一種不必要的扁平(繼承智能)領域模型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM