我创建了一个跟踪汽车里程和服务历史记录的程序,以便更新用户以了解汽车即将到来的服务需求。
我有三个课程:Car
,CarHistory
和CarServiceHistoryEntry
。第三个是直截了当的;它包含与服务相关的所有属性:日期,里程,执行的服务等。CarHistory
类如下:
require_relative 'car_service_history_entry'
class CarHistory
attr_reader :entries
def initialize (*entry)
if entry.size > 1
@entries = []
else
@entries = entry
end
end
def add_service_entry entry
@entries << entry
end
def to_s
entries_string = ""
@entries.each {|entry| entries_string << "#{entry.to_s}\n"}
entries_string
end
end
initialize
中,是否应该检查entry
的班级?add_service_entry
中,采用鸭子打字(如Andy Thomas在“编程Ruby”中的论点),我是否会测试是否可以添加CarServiceHistoryEntry
?我不能只是传递String
而不是设置,然后在我的单元测试中添加CarServiceHistoryEntry
吗?CarHistory
的唯一必要属性是entries
数组和to_s
方法,我应该将这个类全部废弃并放入car
类?答案 0 :(得分:1)
很难对CarHistory
课程与其他人的关系发表评论,但我相信随着你的进展你会很清楚。
您的一些方法可以简化,但我必须说我不理解if
中的initialize
,也许它只是倒退而应该是> 0
。< / p>
def initialize *entry
@entries = entry # if not specified it will be [] anyway
end
def to_s
@entries.join "\n"
end
是的,Ruby应该很简单。您不需要使用运行时类型检查来丢弃代码。如果代码运行您的单元测试,那么您可以宣布胜利。数以万计的显式转换往往会修补类型错误。
Ruby无论如何都会在运行时检查你的类型。将类型检查留给口译员并将您的精力投入到功能测试中是完全合理的。
答案 1 :(得分:1)
对于1和2,当你转向像Ruby这样的松散类型的语言时,你需要释放对“严格打字”的紧密控制。
代码片段:代码可以更简洁
# just for simplicity, I'm making HistoryEntry a string, it could be a custom type too
class CarServiceHistoryEntry << String
end
class CarHistory
attr_reader :entries
def initialize(*history_entries)
@entries = history_entries
end
def add_service_entry(entry)
@entries << entry
end
def to_s
@entries.join("\n")
end
end
irb>x = CarHistory.new("May 01 Overhaul", "May 30 minor repairs")
irb>x.add_service_entry("June 12 Cracked windshield")
irb>x.to_s
=> "May 01 Overhaul\nMay 30 minor repairs\nJune 12 Cracked windshield"
答案 2 :(得分:0)
我将跳过前两个问题并回答第三个问题。如果CarServiceHistoryEntry的唯一属性是字符串,则是,废弃CarHistory(以及CarServiceHistoryEntry)并向Car添加service_history属性,这只是一个字符串数组。除非另有证明,否则更简单。
对于鸭子打字,你永远不会想要测试某个'是'是'只看'它是否'响应'(最多)。
最后,回答问题#1,不应该更简单:)
希望这有帮助, 布赖恩