http://qs321.pair.com?node_id=1207876

There are two hard problems in computer science: cache invalidation and naming things*. Questions about naming things, for me, show up the most when designing a new class (and I wrap nearly all my code into a class, these days). Since I used to earn my rent by writing code in C++, my method names in Perl tend to reflect that heritage.

The most obvious example of this pattern is the way I name object constructors. If I have a package, Xyzzy, the constructor for that class is usually called Xyzzy::new. When the initialization of an object is expensive, I would wrap the constructor in a singleton design pattern, and call that method new. A simplified implementation of this constructor might look like the following:

package Xyzzy; { # scope of cache my $cached = {}; sub new { my $class = shift; # may be a derived subclass my @args = @_; # reuse singleton object iff a valid one is available. delete $cached->{$class} if ($class->cache_invalid()); return $cached->{$class} if ($cached->{$class}); my $obj = {}; # no object found in cache, bless( $obj, $class ); # so create a new one. $obj->_initialize( @args ); # expensive! $cached->{$class} = $obj; # cache data by class id return $obj; } } # scope of cache … other methods here …

This design pattern allowed me to conceal the singleton nature of a Xyzzy, and I used to think that was a good thing.

Recently, however, the needs of my job called for me to write a substantial quantity of code in the Programming Language That Shall Not Be Named. That language was written with a philosophy that directly opposes TMTOWTDI – for any task you want to perform, there is One True Way you must do it. It is a philosophy that complicates the implementation of simple one liners, but greatly reduces, I suspect, the time spent grading test questions which must be answered by writing code in that language.

One of the True Way conflicts I encountered while working in this programming language was the implementation of singleton constructors. You cannot choose a different name for your constructor, and the memory allocation of the object is done externally before your constructor code gets invoked. In short, there is simply no way you can override the constructor with a singleton allocator, and any class method that implements a singleton design pattern must be explicitly invoked by the caller. This leaves me with something like

package Xyzzy; { # scope of cache my $cached = {}; sub instance { my $class = shift; # may be a derived subclass my @args = @_; # reuse singleton object iff a valid one is available. delete $cached->{$class} if ($class->cache_invalid()); return $cached->{$class} if ($cached->{$class}); # no object in the cache, so create/return a new one. my $obj = new $class( @args ); $cached->{$class} = $obj; return $obj; } } # scope of cache sub new { my $class = shift; my @args = @_; my $obj = {}; bless( $obj, $class ); $obj->_initialize( @args ); # expensive! return $obj; }

Having switched to this new nomenclature, I find that singleton instances are only reused when I want them to be used. True, that’s almost always, but this naming technique does leave me the option of constructing a new object instance if I wanted to do something ugly to it and didn’t want to risk polluting the cache. On the other hand, if I want to use this pattern on a class that is already widely used, I have to go on a global search-and-destroy mission, replacing constructor calls with calls to instance(), if I want to benefit from the performance improvement that comes from using a singleton.

These days, I still find myself banging my head on the desk when none of the four different ways I might solve a problem in Perl can be applied in The Other Language, but I think this one particular technique is beginning to grow on me. And I’m glad Perl follows TMTOWTDI; it allows me to bring back these new techniques back into my regular job, and benefit from them here, as well.

*Also, off-by-one errors. But if I had said that up above, someone may have accused me of being swayed by that Other Programming Language into parroting the Spanish Inquisition sketch – and that is a dead parrot.