Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

(jeffa) Re: How do you avoid "Code Burnout"?

by jeffa (Chancellor)
on Jun 30, 2003 at 22:14 UTC ( #270345=note: print w/ replies, xml ) Need Help??


in reply to How do you avoid "Code Burnout"?

Just hanging around here inspires me to write all kinds of code/snippets that i would never think of otherwise. Going with Corion's advice about the Facade Pattern (brian d foy wrote an excellent Perl Review article on that pattern by the way - you should read it), here is my quick-n-dirty mini-tutorial:

Say you have a dynamic website whose content is driven by a series of methods/functions contained in some library. Currently, CGI.pm is being used to generate HTML. The library (module) might look like:

package Old; sub new { my ($class,@arg) = @_; my $self = {}; return bless $self,$class; } # pretend these return HTML pages generated via CGI.pm sub index { "CGI.pm index page" } sub page1 { "CGI.pm page1" } sub page2 { "CGI.pm page2" } sub page3 { "CGI.pm page3" } 1;
A cow-orker decides to rewrite these methods and use HTML::Template instead:
package New; sub new { my ($class,@arg) = @_; my $self = {}; return bless $self,$class; } # pretend these return HTML pages generated via HTML::Template sub index { "H::T index page" } sub page2 { "H::T page2" } # page 2 was easier than 1 ;) 1;
They haven't even finished, but the boss is so impressed that (s)he asks you to go ahead and substitute the new methods in. What do you do? You write another "layer" - another module that uses both libraries and delegates which library to use for a given method call. A first naive (as all my first approaches usually are) might look like:
package Interface; use Old; use New; sub new { my ($class,@arg) = @_; my $self = {}; return bless $self,$class; } sub index { return New->new()->index } sub page1 { return Old->new()->page1 } sub page2 { return New->new()->page2 } sub page3 { return Old->new()->page3 } 1;
Before i say why that is naive, here is the test script:
use strict; use warnings; use Interface; my $obj = Interface->new; print $_,$/ for map $obj->$_, qw(index page1 page2 page3);
Go ahead and create those 4 files and make sure everything works. So why naive? Because you probably have more than 4 methods in you old library, many more. I myself am too lazy correctly type in every single method ... why not just use AUTOLOAD? (don't you wish C had one?) Much like the anonymous list i used on the last line of the test script, we could use a similar technique. Here is a revised Interface.pm:
package Interface; use Old; use New; use Carp; sub new { my ($class,@arg) = @_; my $self = {}; return bless $self,$class; } my %new = map {$_ => 1} qw(index page3 page2); sub AUTOLOAD { my $self = shift; my $name = $AUTOLOAD; $name =~ s/.*://; # strip fully-qualified portion #TODO: method name validation! return $new{$name} ? eval "New->new->$name" : eval "Old->new->$name" ; } sub DESTROY {} # good practice - prevents unecessary call to AUTOLOAD 1;
Now all you need to do is add the name of the methods to %new as they are completed. Once Old.pm has been completely deprecated you could get rid of Interface.pm.

By this point you must be asking how all of these name changes are going to affect users ... because they are! In this example, i had the luxury of knowing ahead of time what was going to happen, so i programmed to the Interface.pm module. In reality, i would be programming to the Old.pm module instead. My recommendation is to simply rename the old library to something else, and name your Interface.pm the original old lib name. Then, when the old library has been completely deprecated (oxymoron?), rename the new library to the original old lib name.

Sounds easy, but i know it really isn't. It's hard work no matter how you slice it, but if you provide a seamless way for the lib users to continue to use old methods while new ones are being implemented, then it's probably worth it (er ... whatever it is ...).

Brushing up and writing about the Facade Pattern has nothing to do with my current projects, but i somehow feel more refreshed for doing something new and "not my job" ... oh, and beating the crap outta my drums doesn't hurt either ;)

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)


Comment on (jeffa) Re: How do you avoid "Code Burnout"?
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://270345]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (8)
As of 2014-07-26 01:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (175 votes), past polls