When to use freeze in Ruby
I recently saw a few Tweets where some pretty bright Ruby developers were
complaining that Ruby's freeze method causes more problems than it's worth.
(For those who don't work with Ruby, freeze makes a mutable object
immutable). I've seen this method used incorrectly a few times in the past, so
I thought it merited writing a short blog post.
In order to understand the utility of freeze, it's important to look
at a language's features in terms of those useful at runtime (i.e. calculating
string length) and those useful during development (i.e. defining a class).
Freeze is mostly useful for development. Consider the code below:
class Universe
include Singleton
ELEMENTS = {
1 => :H,
2 => :He,
3 => :Li,
4 => :Be,
...
103 => :Lr
}.freeze
end
Here, freezing the ELEMENTS hash makes it impossible to add new elements. (Yes,
Ruby constants are mutable). Why do this? Because it should be something
extremely unusual to add a new element; so unusual in fact, that I want to
make it very hard for a developer on my team to do so without causing an error.
I'm not going to worry about freeze causing runtime errors, because I'm
writing tests and assume my collaborators are too. If a new element is discovered,
I don't want it added via a monkey-patch, I want the source itself patched.
These are the only places I tend to use freeze; almost any place else is
likely to cause annoyance. I'm sure there are plenty of exceptions to prove
this rule, but by and large unless you know WHY, don't use freeze except in
setup code.
Published