2013-02-08 70 views
1

比方說,我有一個帳戶類和一個AccountReport類。在帳戶#顯示我想顯示一個帳戶的報告。 Account和AccountReport都有一些公開的方法。以下哪種技術更好?委託或實例化額外的類?

1)實例化一個賬戶和一個賬戶報告,用賬戶數據初始化賬戶報告。

class AccountsController < ActionController::Base 
    def show 
    @account = current_user.account 
    @account_report = AccountReport.new(@account.orders) 

    respond_with(@account) 
    end 

    # ... 
end 

2)允許帳戶的實例來實例化AccountReport和委託方法調用

class Account < ActiveRecord::Base 
    attr_reader :account_report 

    delegate :method_a, :method_b, :method_c, :method_d, :to => :account_report 

    after_initialize :setup_account_report 

    def setup_account_report 
    @account_report = AccountReport.new(orders) 
    end 

    # ... 
end 

選項2似乎是一個更簡潔的方法給我,但有很多的方法加載了帳戶使得它感覺像一個上帝階級。

回答

2

嗯,我認爲你必須使這兩種選擇的組合。

第一個是好的,如果你只使用顯示報告。 如果您使用所有時間報告爲您的帳戶,第二個是好的。

隨着第二個,您的報告將實例化,它可能會降低性能。

你或許應該嘗試這樣的事:

class Account < ActiveRecord::Base 
    # ... 

    @report = nil 
    def report 
    if @report.nil? 
     @report = AccountReport.new(self.orders) 
    end 
    end 

    # ... 
end 

這種解決方案的好處是,如果需要的報告只裝,但不會每次加載。 這個解決方案的壞處是如果你添加一些訂單你的報告將不會是最新的。

UPDATE: 爲了改善這一點,你可以用這一個

if @report.nil || self.created_at_changed? 
+0

我想我明白了。我喜歡懶惰地加載報告的想法。是否有可能以這種方式委託給AccountReport/Report,或者是否需要使用方法鏈接account.report.total,並使用此方法? –

+0

'@report || = AccountReport.new(self.orders)'是你上面試圖做的一個很好的比喻。 –

+0

謝謝!我已經將這兩條建議結合起來,它的運作非常好。我甩掉了我的讀者,寫了一個獲取報告的方法,然後在那裏返回或初始化它。 –

0

我喜歡的第一個選項,因爲它使低耦合更換條件。第二個選項以一種可能不必要的方式將Account和AccountReport關聯在一起。每當你得到另一種類型的報告時會發生什麼?您可能需要更改帳戶中的一些內容,這很令人傷心,因爲它們看似不相關。

您可以通過在服務對象中組合這兩個東西並將它交給您的視圖來保持控制器中的邏輯/冗長度較低。一個AccountReporting服務可以處理後面這兩個類組合在一起的邏輯,例如:

class AccountReporting 
    def initialize(account) 
     @account = account 
    end 
    def report 
     AccountReport.new(account.orders) 
    end 
end 

然後,要使用它的控制器:

AccountReporting.new(current_user.account) 

這是否有道理?

+0

有趣。我可以看到這會有用。我認爲對於經常使用的類,我可以使用方法#2的精煉版本,對於不常用的類,我可以使用這種方法(改進#1)。您預先準備好了幾種這樣的類,這是正確的。我試圖削減我的應用程序的兩個上帝類更好的SRP /解耦。 –