Separating detailed data code from the main application - Ruby example
Archive - Originally posted on "The Horse's Mouth" - 2016-05-16 23:08:51 - Graham EllisIn almost every appication, you'll be writing a number of pieces of code that use the same data type. It's tempting initially to write all the detail of the individual fields and attributes of the data into a main program - especially if the application's not very long and you're in a hurry:
fh = File.new "ac_20160516"
counter = {}
fh.each do |record|
parts = record.split " "
if parts[1] == "option247.uk"
page = parts[6]
if counter[page].nil?
counter[page] = 1
else
counter[page] += 1
end
end
end
pages = counter.keys
pages.sort! {|this,that| this.length <=> that.length}
pages.each do |page|
puts "#{page} #{counter[page]}"
end
Which works well enough, but ties the program down to a specific data format and implements the algorithms individually. If your data records are sometime available in a different way, you need to rewrite all the code, and if you want to use the counter technique elsewhere, you'll have to recode that too. Better to write the code a little longer and clearer and abstact the algorithms and data formats into separate classes.
class Counter
def initialize()
@internal = {}
end
def count(item)
@internal[item] = @internal[item].nil? ? 1 : @internal[item]+1
end
def getKeys()
return @internal.keys.sort { |this,that| @internal[this] <=> @internal[that]}
end
def getKey(which)
return @internal[which]
end
end
class Hit
def initialize(record)
@fields = record.chomp.split(" ")
end
def issite?(which)
return @fields[1] == which
end
def url
return @fields[6]
end
end
# ----------------------
if __FILE__ == %body%
fh = File.new "ac_20160516"
counter = Counter.new
fh.each do |record|
hit = Hit.new(record)
parts = record.split " "
if hit.issite?("option247.uk")
counter.count(hit.url)
end
end
pages = counter.getKeys
pages.each do |page|
puts "#{page} #{counter.getKey(page)}"
end
end
Complete source code of this example - the before [here] and the after [here]. From the Ruby Course I am presenting this week. The datafile is available [here].