2014-11-05 61 views
0

我的最佳方式之間徘徊,以實現此服務:依賴注入的正確實施

目前我有這樣的:

class ReissueInvoices 

    def initialize(registration, invoice_gateway, invoice_generator) 
    @registration = registration 
    @invoice_gateway = invoice_gateway 
    @invoice_generator = invoice_generator 
    end 

    def call 
    void_current_invoices 
    regenerate_invoices 
    create_third_party_invoices 
    end 

    private 

    attr_reader :registration, :invoice_gateway, :invoice_generator 

    def void_current_invoices 
    registration.invoices.each do |invoice| 
     unless invoice.paid? 
     invoice_gateway.void_invoice(invoice) 
     end 
    end 
    end 

    def regenerate_invoices 
    invoice_generator.call(registration) 
    end 

    def create_third_party_invoices 
    invoice_gateway.create_invoices(registration) 
    end 

end 

,我把這個(通常是從我的控制器)是這樣的:

ReissueInvoices.new(@registration, InvoiceGateway.new, InvoiceGenerator.new).call 

我明顯有一個InvoiceGateway,InvoiceRegistration類,並將它們作爲依賴項傳遞給我的ReissueInvoices類。

這是做事情的最佳方式嗎?這是否正確實施了依賴注入?或者我應該改變我的ReissueInvoices類像這樣的初始化方法去除參數和添加私有方法來創建和訪問invoice_generator和invoice_gateway對象:

class ReissueInvoices 

    def initialize(registration) 
    @registration = registration 
    end 

    def call 
    void_current_invoices 
    regenerate_invoices 
    create_third_party_invoices 
    end 

    private 

    attr_reader :registration 

    def invoice_gateway 
    @invoice_gateway ||= InvoiceGateway.new 
    end 

    def invoice_generator 
    @invoice_generator ||= InvoiceGenerator.new 
    end 

..... 

,並調用它像這樣

ReissueInvoices.new(@registration).call 

最後,你們怎麼想的初始化定義這樣的默認參數的:

def initialize(registration, invoice_gateway=InvoiceGateway.new, invoice_generator=InvoiceGenerator.new) 
    @registration = registration 
    @invoice_gateway = invoice_gateway 
    @invoice_generator = invoice_generator 
end 

是好是壞?

感謝,

馬特

回答

1

爲什麼你的網關不需要像憑據?我猜它是的,網關的憑證只是硬編碼。真的,應該在某個地方進行初始化,然後傳入(因爲你的類應該不需要處理如何設置網關,大概只有一個網關,並且你應該到處使用同一個對象)。

我不會打擾傳遞發票生成器,除非它很昂貴,或者您需要控制它返回的測試或有多種方式來生成該事件,並且您無法從這裏合理地知道哪些是正確的。這只是因爲它是一個計算並返回一個值的東西。不錯,簡單,除了我提到的那些之外。

而且,我可能會改變它是這樣的:

module ReissueInvoices 
    def self.call(registration, invoice_gateway) 
    registration.invoices.each do |invoice| 
     invoice_gateway.void_invoice(invoice) unless invoice.paid? 
    end 
    InvoiceGenerator.call(registration) 
    invoice_gateway.create_invoices(registration) 
    end 
end 

的思維過程就大約是這樣的:

  • 我永遠不會看那個調用方法而不需要看他們實施的方法,所以讓我們看看他們做了什麼。哦,他們只是隱藏了合作者。
  • 拉起來到#call
  • 「爲什麼我實例化一個InvoiceGenerator?它不帶任何參數,所以它不應該具有的狀態,所以無需實例。我認爲它只有一個方法,因爲該方法被命名爲#call,所以只要將它設置爲單例方法,並且如果有一些實例化的價值,那麼單例方法可以做出這個決定。
  • 現在一切都在ReissueInvoices#call中,剩下的是什麼?這只是佈線以支持此行爲的對象(#initialize和訪問器)。相反,使它成爲名爲call的類方法。然後,這些變成了局部變量。
  • 既然我們只有一個類的方法,使得這個類是誤導性的,因爲它不會被實例化。所以把它變成一個模塊吧。