Ask Hack Learn Share!
A simplified version of the code is this
before going on the problems I see in this code, let’s see the good uses of modules in Ruby and see why I think this code is not eloquent enough.
Ruby modules are good to:
Mixins: group methods related to a common functionality, to then include the behavior in classes. The Enumerable mixin is a good example of this, which then Array and others include.
for namespacing purposes, e.g.
and then using it makes perfectly clear that the Query is a MySQL one
MySQL::Query.select ...
plus other benefits of separation of code.
And it is in this last category where the code at hand seems to fit into.
Let’s see the symptoms that point to the fact that using a class would mean here clearer code. As Olsen’s Eloquent Ruby says: the code has to tell a story, and has to tell it well, and I’ll add to that that it should tell it also by minimizing the surprise points for developers.
The code when used looks like Calculator.sum(1,2)
when I read that I normally expect that Calculator
to be a class not a
module. So here first surprise appears.
Moreover the mean
method calls both sum
and divide
, passing the same
parameters repeated times. The symptoms here are, a method calling another
when they are supossedly not much related (since you put them in the junk drawer),
and at the same time many parameters are floating around in method calls.
To add more confusion to the latter, notice also that divide
is a private method in a
module.
Let’s use the code to see another problem:
As you see you need to keep the sum
yourself, and also know the amount of
sums you have made in order for your method mean
to work. This
implies that encapsulating state inside the Calculator
would be a good idea.
And last but no least, the 3 methods are related to calculations, so this
points to the fact that an object Calculator
is needed. But instead a
junk room for methods was used, somehow implying that the object modeling was
not clearly achieved, so the code fell short in being eloquent again.
A version using a class could be:
And the use of the code would be:
So, would you write the above as an class/object or as a module? My advice is use an object whenever you can.