重构导入具有标头的csv文件的代码

时间:2013-08-07 02:28:25

标签: ruby oop polymorphism switch-statement

我正在尝试重构一些读取csv文件的代码。文件每行中的第一个字符表示记录类型:H =标题,I =信息,D =数据。每种记录类型都有固定且不同数量的字段。我的程序使用FasterCSV从文件中读取一行,然后使用case语句来确定如何处理该行。

     record_type = new_record[:record_type]
     case record_type
     when "H"
     factory_build_H_record(new_record)
     when "I"
     factory_build_I_record(new_record)
     when "D"
     factory_build_e_record(new_record)
     end

对于重构,我试图遵循Sandi Metz' blog post在OO编程中使用case语句并消除case语句。我倾向于我需要创建一些代表三种记录类型的类,然后定义一些像process_record这样的方法。我不确定如何创建课程。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您链接的博客文章具体是关于使用case语句来判断什么类型的对象是什么。这通常是设计糟糕的症状,而这正是她所要做的。

您使用case语句的方式更为可接受。事实上,无论你如何重组这个,你都要对该列进行某种测试(caseif或其他方式),以确定行的正确行为

如果您的代码稍后必须尝试通过他们的类(使用case语句或if)来区分这些对象,那么您违反了博客文章的精神。

解决方案是创建具有相同接口的对象(具有相同的方法,以相同的方式使用。这些方法的行为在每个类的内部是不同的,以便为该对象做正确的事。

希望这有助于为您理清概念:)

答案 1 :(得分:0)

案例陈述对于像你这样的小而且相当静态的条件案例来说并不坏。

如果(理论上)你预计将来会有更多的记录类型(除了H,I和D),那么case语句的问题是它可能会导致你开始违反Open-Closed Principle

在这种情况下,您可以创建一组RecordType类,这些类似于以下几行:

class HeaderRecordType
  def is_mine(record)
     ...
  end
  def build(record)
     ...
  end
end

class DataRecordType
   ...
end

class SomeNewRecordType
   ...
end

然后,您只需迭代所有RecordType的列表(或使用Chain of Responsibility)并询问每一个is_mine(record),而不是这种情况。一旦其中一个人说是,那么你就停止寻找并致电build