2012-05-23 42 views
2

我有一個項目,我在紅寶石工作,它需要從一些工作人員沉重的工作。大多數業務邏輯都包含在這些工人中,他們變得相當複雜。我設計的技術模擬了組合方法模式,但它很大程度上依賴於實例變量來保持狀態。我設定這個方法似乎是合乎邏輯的,但我想從社區那裏得到一些關於這是否錯誤的反饋,或者不是我可以設置的最乾淨的方式。我基本上使用工人面向對象的方法來處理複雜的方法

執行(Sidekiq)方法,作爲一種開關

def perform(transaction_id, data, account_id) 
    @transaction_id = transaction_id 
    @data   = data 
    @account  = Account.new(account_id) 

    @campaign_tag = nil 
    @match_str  = nil 
    @options  = nil 

    has_starter_tag  || return 
    find_campaign  || return 
    determine_options || return 
    find_active_option || return 
    reservation_over || return 
    already_filled  || return 

    send_to_inventory 
end 

每個方法遵循相同的邏輯。檢查規則如果不令人滿意,則執行操作(發送電子郵件,不管..)並返回false,從而停止執行。如果滿意,存儲完成交易所需的一些伊娃數據並返回true,從而進入下一步。

def has_starter_tag 
    result = true 

    @campaign_tag = find_starter_tag(@account, @data[:variable]) 
    if [email protected]_tag 
    result = false 
    send_email_about_badness 
    log_some_stuff 
    end 

    result 
end 

爲了測試這段代碼,我爲每個方法依賴的實例變量存根。我知道這是一種代碼味道,因爲我的測試知道實現而不是接口。也就是說,我喜歡這些方法的清晰界面,我覺得我可以掃描源代碼並且確切地知道發生了什麼。

如果我做錯了,有人可能需要一些時間並解釋正確的方式(或至少另一種方式)來做到這一點?我總是遇到一些問題,如何處理那些必須執行許多小步驟的對象,而這些步驟似乎都是相互依賴的。

+0

您如何使用您在工作人員中設置的前三個實例變量? '@ campaign','match_str'和'options'用於什麼?首先,我會讓'has_starter_tag'和其他方法接受每個人都需要的參數。這可以讓你測試分離,而不依賴於實例變量。 –

+0

我更新了示例方法,以更好地說明如何使用它。前3個變量基本上是大多數方法用於數據的常量。我可能應該已經指定了這一點,但是我完成了大部分在'has_starter_tag'外方法調用的方法中的工作。那些不訪問實例變量,並單獨進行單元測試。 – rabidpraxis

回答

1

我的直覺是你試圖在某種程度上過度設計這個東西。

您所描述的並不算作設計模式 - 它只是將所需的功能分離爲若干單獨的方法。問題是這些方法彼此如此緊密地聯繫在一起,除了「分組」功能之外,將它們分開除了沒有其他用途。這些函數唯一的共同點是他們檢查某些內容並取消檢查工作失敗。除了重複功能外,通過將所有代碼放在一個函數中,並用空行分隔各個部分,可以獲得相同的效果。

在代碼中使用某些OOP解決方案或設計模式的時候可能會適得其反。在這一天結束時,真正重要的是它是否提供了優勢?它保存了代碼嗎?它是否使代碼易於維護和擴展? (代碼需要才能容易擴展嗎?)不要爲了OOP而試圖使用OOP。