Re: how to make a universally inherited method?
by lachoy (Parson) on Nov 29, 2001 at 10:12 UTC
|
I agree with IlyaM, a singleton makes more sense for this. A singleton is an object that can only be instantiated once -- successive requests for a new object just return the same one.
The Class::Singleton module probably has one of the highest POD-to-code ratios on CPAN, but it's very useful.
Your config module:
package My::Config;
use strict;
use base qw( Class::Singleton );
sub _new_instance {
my ( $class ) = @_;
my %data = (
var1 => 'This is var1',
var2 => [ 'This', 'is', 'var2' ],
);
return bless( \%data, $class );
}
1;
And you can use it:
my $conf = My::Config->instance;
print "Config for var1 is $conf->{var1}\n";
Easy! Good luck.
Chris
M-x auto-bs-mode | [reply] [d/l] [select] |
|
Wow, this is exciting. I finally have a work-related reason to open my copy of the Gang-of-four book.
I'll try Class::Singleton.
Thanks
| [reply] |
Re: how to make a universally inherited method?
by gildir (Pilgrim) on Nov 29, 2001 at 13:59 UTC
|
Simple and efficient solution:
Make one class superclass of all your othe classes.
Let's call it My::Object. All your other classes will inherit
from it. Place every method, that sould be 'universaly inherited'
in this superclass. If you need 'global' variables, make them
static variables of class My::Object. It looks like this:
package My::Object;
use vars qw($global1 $global2);
sub global1 { $global1 }
sub global2 { $global2 }
sub globalMethod { ... }
package My::SomeClass;
use base qw(My::Object);
package main;
my $g1 = My::Object->global1;
$any_my_object->globalMethod();
Note1: It is VERY bad to mess up with 'magic' classes like UNIVERSAL is.
Not because it won't work, but because it will look bad. And if it will look bad,
it will be unreadable. Thik about hubris. A year after you write it you will not be able to understand how it works.
Note2: Avoid 'global' and even 'class static' variables whenever you can.
They will make your life a real pain in long-term development. Every one of them.
Use of global variable of any kind can be avoided by careful object design of application.
As you are rewriting your application, you should be aware of how it works, so
good desing sould be your primary aim here.
| [reply] [d/l] |
Re: how to make a universally inherited method?
by IlyaM (Parson) on Nov 29, 2001 at 09:59 UTC
|
| [reply] |
Re: how to make a universally inherited method?
by jbert (Priest) on Nov 29, 2001 at 16:57 UTC
|
I'm intrigued by this (and the answers so far to your question). You have a hairy bunch of state squirreled away in a collection of global variables. OK, we all agree that is a nightmare. Do we agree that it is primarily a nightmare because it is hard to know which bits of the code touch the globals and how they interact?
If so, how does using a Singleton class help at all? In order to keep the app working, all parts of your app will need access to the singleton. So that in itself will not help. The code is still tweaking a hairy collection of state, only now it is wrapped up in a singleton. I don't see any benefit yet.
You want to migrate. So you plan to move data out of the singleton/global variables into managed packages/objects. Good.
I guess that encapsulation in the singleton gives you the ability to move the data out from the singleton to a new class, as long as you change the implementation of the singleton to access the new class. But that doesn't help your code quality, since all the code which accesses the data still does so through the singleton.
Code quality benefits only accrue once you change the code which accesses the data to do so through the new interface. At which point you will presumably remove that data from the singleton.
But but but. The hard part is changing all the code which uses the data. AFAICS, you propose to do this twice - once to access the singleton and then once to access the 'new interface'.
Why not just leave the old, global-accessing code in place with a view to getting it to use the new interface when it is ready (note that you can do this piecemeal, as you finish each new interface which encompasses part of your global data)? OK, you may have namespace issues (your globals will reside in main::) but they can be hacked around fairly easily by aliasing (a hopefully-temporary 'use Crud' in each new package). The namespace pollution will probably be horrible but you have that already.
OK. I should probably go away and read up on design patterns, but this is an honest question. Can someone explain the benefits to me please? | [reply] |
|
I suspect the better reason for making a singleton, then migrating from it is this:
- By forcing everything to use a singleton, you get to mark every place in the code that accesses a global.
- In addition, you get to regularize every access of every global, thereby reducing bugs.
- In addition(!), you start to find the places that were using typo'ed globals.
Now that the accessing is regularized, you can do a global replace for a single global variable at a time, knowing that you have all your globals code still in one place.
Even if you never go past the singleton, it's still a good idea because you have collected all your globals accessing stuff. I did that in a production project at my previous position and it worked just fine. I had one big Exporter module and each package that needed access to a given global structure would import just that one accessor symbol. I could then grep through the code and find which packages accessed which symbols. This resulted in tighter code and caught about half-a-dozen bugs in the process. :-)
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.
| [reply] |
|
Hi,
exphysicist here again.
I implemented three or four singletons today. It works well
and Class::Singleton is a real gem.
As it happens the globals break down into a number of logically grouped subsets. Each of these sets is well represented by a separate singleton. Not all methods will need to access all of the singletons so my namespace really is reduced. Plus access to the variables can be controlled and monitored.
There's another issue to consider. As soon as I start moving methods into real classes I break the local variable glue that previously held the program together. Singletons provide an easy and quick way of handling that issue.
| [reply] |
|
The reason I proposed using a singleton is that it's simple, easy to understand and easy to port. If you have a global bunch of variables, every program needs some way to access them -- making this access easily understood seems a fairly low barrier to entry.
You're right that a cleaner way would be to use inheritance so that any object can access the information it needs. But there seemed to me to be multiple steps between the poster's current problem and this cleaner solution.
Chris
M-x auto-bs-mode
| [reply] |