我在实施此服务的最佳方式之间徘徊:
目前我有这个:
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类更改为类似这样的内容从initialize方法中删除参数并添加私有方法来创建和访问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
好还是坏?
谢谢,
马特
答案 0 :(得分:1)
为什么您的网关不需要凭据等内容?我猜它确实如此,网关的凭证只是硬编码。真的,这应该在某处初始化然后传入(因为你的ReissueInvoices
类不应该处理如何设置网关,可能只有一个网关,你应该在任何地方使用同一个对象)
我不会在发票生成器中烦恼,除非它很昂贵,或者你需要控制它为测试返回的内容,或者有多种方法来生成这个东西,你可以&# 39;从这里合理地知道哪个是正确的。这只是因为它是一个做一些计算并返回一个值的东西。除了我提到的那些考虑因素外,简单明了。
另外,我可能会将其更改为:
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
的类方法。然后,这些变成了当地的变种。