命名不同的文件。处理程序? IO?流?处理器?控制器?

时间:2018-06-19 23:58:37

标签: ruby

命名我写的某些文件时遇到麻烦。我真的不知道流,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

我在命名时遇到麻烦。看起来我命名正确吗?应该命名为DataIODataProcessor之类的东西吗?名为DataStream的文件应该做什么?那是converter的东西呢?

2 个答案:

答案 0 :(得分:1)

Ruby不是kingdom of nouns。一些程序员听到“一切都是对象”,并认为“我正在处理数据,因此我需要一个DataProcessor对象!”但是在Ruby中,“所有事物都是对象”。在您的示例中,只有一种新颖的“事物”:巧克力订单(也许也可以兑换)。因此,您只需要一个自定义类:ChocolateOrder。我们已经具有以下对象的其他“事物”:CSV代表CSV文件,Array(或SetHash)可以代表巧克力订单的收集。

一个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的实例方法,则它们可能更惯用。我将从那里开始,看看你对此有何看法。