Tanktalus has asked for the wisdom of the Perl Monks concerning the following question:
A co-worker and I are evaluating two different design paths for a certain part of our code. In an attempt to avoid bias (for or against me ;->), I'm going to present both styles without reference to whose idea each one is, and thus, who the advocate of each idea is. Any input from uninvolved parties is appreciated.
Simple behaviour.
In this style, which is already implemented and working, code to handle data from a single location (call this the "cache") is present in a number of places. This also includes code that handles duplication, e.g., the names of two pieces of different data collide, so we use an extra unique identifier in these cases during the placement of the data, and remove the identifier on the way out. Note that a hash of arrays is actually inappropriate here - hash of hashes is actually closer since we only need a specific instance of this data at a time.
Each use of this cache is implemented separately, and is only about 10-15 lines. So far, this is used in about 5 modules. Growth is possible. So far, only 2 uses of the cache potentially collide with themselves.
Adding new uses is actually generally pretty simple. New possible collisions are not expected to collide with existing data, thus they will only collide with themselves.
# $name is somehow derived from the object value we're storing. The # details of that are (probably) unimportant. $name = $key_obj->derive_name($obj); # insert to cache: $cache{$name} = $obj->value(); # insert to cache with possible collision: $cache{$key_obj->object_ID() . $name} = $obj->value(); # remove from cache: $value = $cache{$name}; # remove from cache with possible collision: $value = $cache{$key_obj->object_ID() . $name};
Debugging is simple in that analysis of the %cache is trivial.
Simple usage.
In this style, code to handle the cache, including collisions, is abstracted to a central module. That module is very complex, and also very new. The uses of the module are cut down to one line (or 5-6 lines if you use generous amounts of whitespace).
Data is abstracted, but the internal representation is made more complex, which, given the age of the module, may mean much more entertaining debugging. New possible collisions would be taken care of by this abstraction.
This is implemented, too, but not committed to the version control system.
# The name is keyed to the object we're using so if we have two differ +ent # types of objects with the same ID, we can differentiate. # insert to cache: $cache->insert(tag => ref $key_obj . $key_obj->object_ID(), data => $o +bj->value()); # remove from cache: @values = $cache->retrieve(tag => ref $key_obj . $key_obj->object_ID() +);
Debugging the $cache object's package is abstracted and a bit more messy. Because of the backing storage (treat %cache above as a tie'd hash to the same backing storage, and pretend the tie is perfect), there are certain characters that aren't allowed in the name (or tag here). This method abstracts such that those characters become allowed by taking an MD5 of the tag name, and using that as the hash key.
Note that the Cache::*Cache modules were evaluated and found lacking for this purpose. Also, a collision is pretty much impossible between unrelated pieces of code (we would have fundamental problems if this were the case that are completely unrelated to perl).
The question, then, is which way to go? What would other monks here do? Is there more information I can give (short of an actual implementation ;->) to help? The above code is not precisely the code, obviously, but is a generic representation of both styles - this is why I ask that you treat the %cache in the first style as a perfectly implemented tie - in the real implementation, nothing can go wrong there, almost as if it were a real perl hash.
Hopefully, whatever responses I get here will help convince one of us to go the other way ;-)
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Selecting one of two implementations
by merlyn (Sage) on Apr 25, 2005 at 15:05 UTC | |
by Tanktalus (Canon) on Apr 25, 2005 at 15:24 UTC | |
by merlyn (Sage) on Apr 25, 2005 at 15:29 UTC | |
by Tanktalus (Canon) on Apr 25, 2005 at 15:43 UTC | |
Re: Selecting one of two implementations
by dragonchild (Archbishop) on Apr 25, 2005 at 14:48 UTC | |
Re: Selecting one of two implementations
by dave0 (Friar) on Apr 25, 2005 at 15:08 UTC | |
Re: Selecting one of two implementations
by davies (Monsignor) on Apr 25, 2005 at 15:23 UTC | |
Re: Selecting one of two implementations
by Transient (Hermit) on Apr 25, 2005 at 15:00 UTC | |
Re: Selecting one of two implementations
by salva (Canon) on Apr 25, 2005 at 15:19 UTC |