命名我写的某些文件时遇到麻烦。我真的不知道流,I / O,处理程序,处理器(这是一个真正的概念吗?)和控制器之间的区别。这些是我的文件在Ruby中的样子:
从rakefile开始:
desc "Calculate chocolate totals from a CSV of orders"
task :redeem_orders, [:orders_csv_path, :redemptions_csv_path] do |t, args|
args.with_defaults(:orders_csv_path => "./public/input/orders.csv", :redemptions_csv_path => "./public/output/redemptions.csv")
DataController.transfer(
input_path: args[:orders_csv_path],
output_path: args[:redemptions_csv_path],
formatter: ChocolateTotalsFormatter,
converter: ChocolateTotalsConverter
)
end
然后是控制器(在我看来,该控制器使用从rakefile
获得的数据在不同的类之间进行委托):
class DataController
def self.transfer(input_path:, output_path:, formatter:, converter:)
data_processor = DataProcessor.new(
input_path: input_path,
output_path: output_path,
formatter: formatter
)
export_data = converter.convert(data_processor.import)
data_processor.export(export_data)
end
end
处理器(根据传递到该文件的各种文件执行导入和导出):
class DataProcessor
attr_reader :input_path,
:output_path,
:formatter,
:input_file_processor,
:output_file_processor
def initialize(input_path:, output_path:, formatter:)
@input_path = input_path
@output_path = output_path
@formatter = formatter
@input_file_processor = FileProcessorFactory.create(File.extname(input_path))
@output_file_processor = FileProcessorFactory.create(File.extname(output_path))
end
def import
formatter.format_input(input_file_processor.read(input_path: input_path))
end
def export(export_data)
output_file_processor.write(
output_path: output_path,
data: formatter.format_output(export_data)
)
end
end
在控制器中引用的converter
看起来像这样(它将传入的数据转换为其他格式...我对此命名方式更有信心):
class ChocolateTotalsConverter
def self.convert(data)
data.map do |row|
ChocolateTotalsCalculator.new(row).calculate
end
end
end
上面的代码片段中的FileProcessorFactory
创建了一个像这样的文件,它实际上是对CSV进行读取和写入:
需要“ csv”
class CSVProcessor
include FileTypeProcessor
def self.read(input_path:, with_headers: true, return_headers: false)
CSV.read(input_path, headers: with_headers, return_headers: return_headers, converters: :numeric)
end
def self.write(output_path:, data:, write_headers: false)
CSV.open(output_path, "w", write_headers: write_headers) do |csv|
data.each do |row|
csv << row
end
end
end
end
我在命名时遇到麻烦。看起来我命名正确吗?应该命名为DataIO
与DataProcessor
之类的东西吗?名为DataStream
的文件应该做什么?那是converter
的东西呢?
答案 0 :(得分:1)
Ruby不是kingdom of nouns。一些程序员听到“一切都是对象”,并认为“我正在处理数据,因此我需要一个DataProcessor
对象!”但是在Ruby中,“所有事物都是对象”。在您的示例中,只有一种新颖的“事物”:巧克力订单(也许也可以兑换)。因此,您只需要一个自定义类:ChocolateOrder
。我们已经具有以下对象的其他“事物”:CSV
代表CSV文件,Array
(或Set
或Hash
)可以代表巧克力订单的收集。>
将一个CSV行处理为一个订单,将转换为一个可行的数据,并将这些数据总计为一个结果,事物”。他们是行动!在Ruby中,操作是方法,块,proc,lambda或顶级函数*。在您的情况下,我看到了一种类似ChocolateOrder#payment
的方法,用于仅计算价格的总和,然后可能需要一些块来进行其余的处理。
在伪代码中,我想像这样:
# input
orders = CSV.foreach(input_file).map do |row|
# get important stuff out of the row
Order.new(x, y, z)
end
# processing
redemptions = orders.map { |order| order.get_redemption }
# output
CSV.open(output_file, "wb") do |csv|
redemptions.each do |redemption|
# convert redemption to an array of strings
csv << redemption_ary
end
end
如果您的行确实很简单,我什至可以考虑仅在CSV上设置headers:true
,以便它返回Hash
并保留订单。
* Procs,lambda和顶级函数也是对象。但这不重要。
答案 1 :(得分:0)
这似乎是一种“ java”的思维方式-在Ruby中,我没有看到这样的模式经常使用。我想说的是,您可能真的只需要DataProcessor类。 CSVProcessor和ChocolateTotalsConverter仅具有类方法,如果它们是DataProcessor的实例方法,则它们可能更惯用。我将从那里开始,看看你对此有何看法。