Flatten must be banned
I have strong opinion about some patterns in Ruby. Certain things are frequently
used in a terribly wrong way (what a surprise). In this post I will explain what
is wrong with how Array#flatten
is used sometimes.
Array#flatten
Argument-less flatten
should not exist. In my experience, only in very rare
cases do we need to call it. Most often, flat_map
should be used instead.
In most of the remaining cases, flatten(1)
is an option.
flatten
without arguments means that you have no idea what kind of input to
expect. This is a violation of YAGNI principle and just sloppy coding.
There are literally hundreds of examples of abusing flatten
on GitHub. Let’s
review some of them.
Case One
a.map{}.flatten
is not always equivalent to a.flat_map{}
, but in this particular
case it is, as well as in many similar cases.
Case Two
Way simpler, right?
Case Three
This pattern is especially popular among Ruby developers. With this pattern, the
caller is allowed to call helper_attr
in many different ways:
Some people call it “convenient”. I respectfully disagree. I consider this code
unconfident, vague and sloppy. Interface of helper_attr
is overly broad.
Without losing much readability, flatten
can be dropped and the method will
become more strict, it will obtain a well-defined type, if you wish:
If the splat in helper_attr(*HELPERS)
really, really, really bugs you, then
there still exists an option way better than argument-less flatten
: flatten(1)
.
Case Four
If we know the shape of the input, why on Earth do we need to use the overly generic and slow method that hides our intent instead of making it as clear as possible?
Case Five
Surprisingly often I see this [something].flatten
code. In most cases, what
people want is: if it’s a collection, keep it as is, otherwise wrap it in array.
This is exactly what Kernel#Array
does.
Conclusion
Do I need to say that flatten
-less code is generally faster than equivalent code full
of argumentless flatten
s?
But mind you, performance is not my main concern. My main concern is
maintainability. I consider naked flatten
a code smell.
In many cases code with flatten
is the opposite of what I would call
Confident Ruby.