2010-09-03 60 views
0

我有一個Email對象有兩個屬性,標籤和值。系統用戶需要驗證他們的電子郵件,然後才能在系統中使用它。驗證過程非常簡單:域對象屬性和封裝

  1. 設置了電子郵件
  2. 激活碼發送一封電子郵件,激活碼驗證電子郵件是有效的

電子郵件對象如下所示:

class Email { 
    String label 
    String value 
    EmailStatus status 
    String activationCode 

    boolean requestVerification() { 
     // Set the activationCode that will be refereced to change the email status 
     this.activationCode = UUID 
     // Raise an event to send a notification email by a communication service 
     EventManager.fire('emailVerificationRequest',this) 
    } 

一切工作正常,除了activationCode屬性不電子郵件對象中正確感覺。它並沒有描述對象的狀態,它僅用於電子郵件驗證過程。所以我修改了我的代碼來引入一個名爲ActivationToken的新對象。該對象將用於封裝activationCode。這裏的電子郵件對象

class Email { 
    String label 
    String value 
    EmailStatus status 

    boolean requestVerification() { 
     new ActivationToken(target:this,code:UUID,expiryDate:new Date()).save() 
     // Raise an event to send a notification email by a communication service 
     EventManager.fire('emailVerificationRequest',this) 
    } 

class ActivationToken { 
    Email target 
    String code 
    Date expiryDate 
} 
  1. 的新版本是這樣一個聲音域設計還是我複雜的我對象沒有
  2. 是否requestVerification方法屬於Email對象首先還是應放置在其他地方;在服務中,或在一個過程中。
  3. 有沒有辦法,我可以按照解決類似的問題

更新

我想解釋一下,爲什麼我連第二重構後保留電子郵件域對象的requestVerfication方法部分的任何設計模式做法。

我有一個直接與域對象通過調度員以下列方式進行交互的遠程接口:

remote://email/6/do/requestVerification 

本來我想繼續通過域對象渠道後端所有的通信和是否有需要與我使用IOC將其注入域對象並使用域對象作爲代理的服務進行交互。遠程接口和域對象之間的分離看起來很乾淨,但是結果卻是一個非常糟糕的想法,因爲它扼殺了域設計,並將無用的依賴性引入了與外部對象無關(在這種情況下爲EmailVerificationService),這與該行爲無關或域的狀態方面對象

另一種解決方案來解決這個可能是保持在其中其自然地所屬的業務的requestVerification方法和引入新的語法的通信協議如:

remote://service/email/do/requestVerification 

你們有什麼感想 ?

謝謝

-Ken

回答

0

你已完成了從分離電子郵件 ActivationToken正確的步驟 - 從概念上它們是獨立的事情(順便說一句,我會用EmailActivationToken爲明晰)。

通常,將使用EmailVerificationService來封裝驗證邏輯。

+0

請參閱我的問題的更新,解釋爲什麼我沒有選擇服務方法的原因。您的意見非常感謝。謝謝 – ken 2010-09-03 14:34:09

1

就我個人而言,我發現兩種方法都可以接受,但更喜歡第二種。我將用什麼來確定哪種方法,將成爲領域專家的輸入。在對域進行建模時,激活碼是否是明確要求的一部分,或者您是否有理由在電子郵件帳戶進行驗證後進行維護?如果你沒有明確的理由去採用你的第一種方法,我會堅持你的第二種方法。

在問候你的個人問題:

  1. 我不會盡可能考慮它被複雜化更從域抽象的服務水平的關注你的對象中去。是的,這是更多的代碼和更多的工作,但可能是更好的方法 - 除非你有明確的理由使用原始方法。

  2. 如上所述,我真的認爲這是服務級別的責任,應該是某種EmailVerificationService。在域模型本身,只有真的在意,如果電子郵件是有效的,而不是它被驗證的手段。

  3. 在我看來,您已經在使用最好的方法。從域對象中引發事件的事件總線是乾淨可靠的。

+0

請參閱我的問題的更新,解釋爲什麼我沒有選擇服務方法的原因。您的意見非常感謝。謝謝 – ken 2010-09-03 14:34:32

0

我認爲在ActivationToken中封裝功能是一個好主意。但通過在Email類中初始化ActivationToken,您已創建對外部資源的隱藏依賴項。這有效地使Email很難進行單元測試,並被其他具有另一激活方案的客戶端重新使用。

相反,您可能需要使用Dependency Injection/Inversion of Control模式將ActivationToken注入Email類。這使您可以注入不同的激活策略,並打開易於對Email類進行單元測試。

要做到這一點你需要ActivationToken和接口Email類的構造函數應該參照的對象實現了這個接口:

interface IActivationToken 
{ 
    void Save(object target, string code, DateTime date); 
} 

class Email 
{ 
    IActivationToken token; 
    // Other properties go here. 

    public Email(IActivationToken token) 
    { 
     this.token = token; 
    } 

    boolean RequestVerification() 
    {  
     token.Save(this, code, date);   
     // Raise an event to send a notification email by a communication service  
     EventManager.fire('emailVerificationRequest', this)  
    }  
} 

現在Email類對外部資源沒有隱藏的依賴。

+0

請參閱我的問題的更新,解釋爲什麼我沒有選擇服務方法的原因。您的意見非常感謝。謝謝 – ken 2010-09-03 14:35:04