I often need to convert some kind of data into other data (usually strings, arrays and hashes). For example:
- input:
"a;simple;list"
expected_output
:[ { content: "a", length: 1 }, { content: "simple", length: 6 }, { content: "list", length: 4 } ]
This can be done by:
input.split(";").map{|s| { content: s, length: s.size } }
but I want to use conversion at different places. So I need to provide encapsulated logic to achieve and reuse this. Three ways pop into mind:
Use a helper method (put a single method into a module):
module Converter extend self def convert(input) input.split(";").map{|s| { content: s, length: s.size } } end end module Caller Converter.convert(input) end
Use a dedicated class with parameters:
class Converter def initialize(input) @input = input end def convert @input.split(";").map{|s| { content: s, length: s.size } } end end module Caller Converter.new(input).convert end
Use refinements, using monkey patching to create a method on the data object but letting a caller decide if it should be included.
module Converter refine String do def convert self.split(";").map{|s| { content: s, length: s.size } } end end end module Caller using Converter input.convert end
I'm not satisfied with any of them, but the third option seems the cleanest because that is usually what you would do if you deal with custom objects. But it also feels wrong because it's monkey patching light. What are your thoughts?
It's great that you are approaching this from an OO perspective.
I like a variation on your second suggestion, with a small difference-- use an object, but don't instantiate it.
As long as this class is only going to do one thing, once, I can't think of a good reason to persist it in memory.
The benefits of this approach are that you're encapsulating the logic in the
StringConverter
class, without writing another module (the first option in your question), or changing the expected behavior of theString
class (the third option). It's a dedicated class for this transformation that you can use anywhere you need it.