Refactoring with simple polymorphism

2 Feb, 2019
0 views
ruby

I’m in the process of writing a gem, and I’ve not been really focused on writing the best possible code, in order to build something in the least amount of time. I now have some time on my hands, so I’ve decided to try to make it clearer.

This is the code I’ve had:

Output = Struct.new(:body, :method, :headers, :url)
 def initialize
 self.method = 'GET'
 self.headers = {}
 self.url = ''
 self.body = ''
 end
 def sort_headers
 self.headers = headers.sort.to_h
 end
 def to_http
 output = "#{method}#{url} HTTP/1.1\n\n"
 headers.each do |key, value|
 output += "#{key}: #{value}\n"
 end
 output
 end
end
class Parser
 def parse(command, format:)
 self.output = Output.new
 output.sort_headers
 case format
 when :json
 output.to_h.to_json
 when :http
 output.to_http
 else
 output.to_h
 end
 end
end

What’s itching me is how Output knows about the different formats this gem supports. What happens when another format is introduced?

I’ve decided to tackle this problem with some good ol’ polymorphism.


Output = Struct.new(:body, :method, :headers, :url) do
 def initialize
 self.method = 'GET'
 self.headers = {}
 self.url = ''
 self.body = ''
 end
 def sort_headers
 self.headers = headers.sort.to_h
 end
 def convert
 raise NotImplementedError
 end
end
class HTTPOutput < Output
 def convert
 output = "#{method}#{url} HTTP/1.1\n"
 headers.each do |key, value|
 output += "#{key}: #{value}\n"
 end
 output += "\n#{body}"
 output
 end
end
class JSONOutput < Output
 def convert
 to_h.to_json
 end
end
class HashOutput < Output
 def convert
 to_h
 end
end
class Parser
 def self.parse(command, format: nil)
 self.output = create_output(format)
 output.sort_headers
 output.convert
 end
 private
 OUTPUTS = {
 http: HTTPOutput,
 json: JSONOutput,
 hash: HashOutput
 }.freeze
 def create_output(format)
 OUTPUTS.fetch(format) { HashOutput }.new
 end
end

Notice how we know have a nice hash of all the formats we support and how easy it is to introduce another format.

AltStyle によって変換されたページ (->オリジナル) /