簡體   English   中英

領域驅動設計 - 可測試性和“新”關鍵字

[英]Domain Driven Design - testability and the “new” keyword

我一直在嘗試在我的新項目中遵循域驅動的設計方法。 我一直使用Spring進行依賴注入,這很好地將我的應用程序代碼與構造代碼分開,然而,使用DDD我似乎總是有一個域對象想要創建另一個域對象,這兩個域對象都有狀態和行為。

例如,給定媒體文件,我們希望將其編碼為不同的格式 - 媒體資產調用轉碼服務並接收回調:

class MediaAsset implements TranscodingResultListener {

    private NetworkLocation permanentStorage;
    private Transcoder transcoder;

    public void transcodeTo(Format format){
        transcoder.transcode(this,format);
    }

    public void onSuccessfulTranscode(TranscodeResult result){
        Rendition rendition = new Rendition(this, result.getPath(), result.getFormat());
        rendition.moveTo(permanentStorage);
    }

}

這引發了兩個問題:

  • 如果再現需要一些依賴(比如MediaAsset需要一個“Transcoder”)並且我想使用類似Spring的東西來注入它們,那么我必須使用AOP才能運行我的程序,我不喜歡。
  • 如果我想要MediaAsset的單元測試來測試新格式是否被移動到臨時存儲,那么我該怎么做? 我無法模擬rendition類來驗證它的方法被調用...將創建真正的Rendition類。

有一個工廠來創建這個類是我考慮過的,但是為了包含導致問題的“new”關鍵字,需要大量的代碼開銷。

這里有一種我想念的方法,還是我只是做錯了?

我認為在這種情況下注入RenditionFactory是正確的方法。 我知道它需要額外的工作,但你也從你的班級中刪除了SRP違規。 在業務邏輯中構建對象通常很誘人,但我的經驗是,對象或對象的注入在100次中有99次得到回報。 特別是如果所提到的對象是復雜的,和/或如果它與系統資源交互。

我假設你的單元測試方法是MediaAsset測試MediaAsset 這樣做,我認為工廠是常見的解決方案。

另一種方法是測試整個系統(或幾乎整個系統)。 讓您的測試訪問外部接口[1](用戶界面,Web服務接口等),並為系統訪問的所有外部系統(數據庫,文件系統,外部服務等)創建測試雙精度。 然后讓測試注入這些外部依賴項。

這樣做,您可以讓測試完全與行為有關。 測試與實現細節分離。 例如,您可以使用依賴注入來實現Rendition :測試不關心。 此外,您可能會發現MediaAssetRendition不是正確的概念[2],您可能需要將MediaAsset拆分為兩個,並將其中的一半與Rendition合並。 同樣,您可以在不擔心測試的情況下完成此操作。

(免責聲明:外層測試並不總是有效。有時你需要測試常見概念,這需要你編寫微測試。然后你可能會再次遇到這個問題。)

[1]最佳級別實際上可能是“域界面”,低於用戶界面的級別,您可以使用域語言而不是字符串和整數,並且您可以在這里談論域操作而不是按鈕點擊和焦點事件。

[2]也許這實際上是你的問題: MediaAssetRendition是正確的概念嗎? 如果你問你的域專家,他知道這些是什么嗎? 如果沒有,你真的在​​做DDD嗎?

暫無
暫無

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

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