I'm having this problem which I think it might be a code smell, I have a class that receives an argument in its initialiser and contains one public and several private methods - everything normal. Example:
class Foo
def initialize(a)
@a = a
end
def apply?(examples)
foo_1(examples)
end
private
def foo_1(examples)
foo_2(examples) ? 1 : 2
end
def foo_2(examples)
examples.size > @a
end
end
My problem here, is 'examples' that is received by the public method being carried around over and over the private methods, it doesn't look pretty and it seems like a code smell, what's the best approach here? Make it an instance variable inside the public method?
Thanks
Yes, this may be considered a code smell if the number of private methods accepting examples
is bigger than 1-2.
One thing to consider would be to extract a class to represent the rule
here.
For example:
class Foo
def initialize(a)
@a = a
end
def apply?(examples)
size_rule_applies?(examples) ? 1 : 2
end
private
def size_rule_applies?(examples)
SizeRule.new(@a, examples).apply?
end
class SizeRule
def initialize(a, examples)
@a = a
@examples = examples
end
def apply?
@examples.size > @a
end
end
end
I wouldn't make the examples
an instance variable of the Foo
class as there's a risk it would persist in memory between the calls to that object. I've seen bugs like that.
If examples
changes dynamically then making it instance variable is not an option. You'll either need to instantiate Foo
for every examples
or you'll end up having mutable Foo
where examples
itself is changing, which is also not good.
Your code looks fine. The only thing that concerns me is that one method depends on another. It's usually not a big deal, but this would look better to me:
def apply?(examples)
foo_1(examples) && foo_2(examples)
end
Another option is to use block:
class Foo
def initialize(a)
@a = a
end
def apply?(examples)
foo_1 { examples }
end
private
def foo_1
v = foo_2 { yield.size }
v ? 1 : 2
end
def foo_2
yield > @a
end
end
Since the class Foo
does nothing else presently than just evaluate .apply?(examples)
I will advice examples be added to the initializer and made an instance variable. This is simpler, more efficient and more obvious.
class Foo
def initialize(a, examples)
@a = a
@examples = examples
end
def apply?
foo_1
end
private
def foo_1
foo_2 ? 1 : 2
end
def foo_2
@examples.size > @a
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.