variable inheritance

M

Matt Garrish

I'm faced with the problem of one module serving up data for 10
different applications, where the only difference is the data being
generated. Without going into the gory details, each year the data
structure (the database) can change for each application and the
applications have no relation to each other.

For this reason, I've set up 10 separate modules each defining the same
set of variables so that my generic class can access the configuration
information without needing to know which application it is dealing
with. Some of the data is the same between applications, so I keep that
in the base class and then the subclasses override the variables that
are specific to each of the children. As I'm sure the above must sound
like gibberish, take for example:

### DataBase.pm

package DataBase;

use Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/%appInfo %someOtherConfig/;

# this variable will get overriden by the child module
# but declaring it here means I can use it in the
# module and avoid problems with strictures
# not finding the variable before the child require
our %appInfo;

our %someOtherConfig = (test => 1);

### Child1.pm

package DataBase::Child1;

use base 'DataBase';

use Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/%appInfo/;

our %appInfo = (table1 => 'col1, col2, col3');


### application

use strict;
use warnings;

use DataBase;

my $test = 1;

if ($test == 1) {
require DataBase::Child1;
import DataBase::Child1;
}

print keys %appInfo;


#########

The above will print the correct 'table1' key, but my question is am I
setting myself up for disaster if I actually try and go this route? I'm
not saying it's the most elegant code, but since it's not a true object
that I want but more of a configuration file is there any danger in my
assumption that the require will properly result in the %appInfo being
the child version.

I currently have the data all in one big configuration file but it's
quickly becoming unwieldy and too large for the web application it's
designed to serve (plus causes other limitations I won't go into by
sharing so much of the same data), so I want to isolate and import only
as little data as necessary to get the job done.

Matt
 
M

Matt Garrish

I don't see how the %appInfo has in this package
gets over-writtten.




Well, it's confusing to say the least. Are you expecting the %appInfo
in package DataBase to contain the same information as the %appInfo
in package main?

With a bit of code added for debugging and introspection, you'll see
that they aren't the same:
Importing into main from DataBase::Child1: %appInfo at app.pl line 10

$VAR1 = {
'table1' => 'col1, col2, col3'
};
$VAR1 = {};
$VAR1 = [
'Exporter'
];


Note that the %appInfo hash in DataBase remains empty.
Also note that the @ISA array in DataBase::Child1 only contains
exporter -- it's not a derived class of DataBase; you've wiped
out the inheritance by reassigning to @ISA.

Sorry, I haven't actually rewritten the code, so you're right that my
hasty example probably doesn't make a whole lot of sense (I'm just
thinking of ways around the problem right now, and "use vars" is
probably the way I should be going so that I only have to export from
the child and still have the code behave under strictures).

The problem in a nutshell is how do I make the variable "exist" in the
eyes of strictures but not know what it contains until the require
happens. I was trying to come up with any trickery I could just in the
interests of seeing what else was possible, but I think I'll just go
back to tried and true.

Matt
 
X

xhoster

Matt Garrish said:
I'm faced with the problem of one module serving up data for 10
different applications, where the only difference is the data being
generated. Without going into the gory details, each year the data
structure (the database) can change for each application and the
applications have no relation to each other.

If the data can change independently, the structure of the data can change
independently, and the applications have no relation to each other, then
why even bother trying to tie them together?
For this reason, I've set up 10 separate modules each defining the same
set of variables so that my generic class can access the configuration
information without needing to know which application it is dealing
with. Some of the data is the same between applications,

Just by accident? Does this shared data change frequently? When it does
change, is it highly likely to change in concert across all apps? If
either of these are "no" then it seems like it would be better just to copy
this data into each of 10 independent modules.
so I keep that
in the base class and then the subclasses override the variables that
are specific to each of the children. As I'm sure the above must sound
like gibberish, take for example:

### DataBase.pm

package DataBase;

use Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/%appInfo %someOtherConfig/;

# this variable will get overriden by the child module
# but declaring it here means I can use it in the
# module

You can use it in which module? You can't use it in *this* module,
as it won't be initialized (other than to an empty list) in this module.
Why would you want to use it if it contains nothing useful?
# and avoid problems with strictures
# not finding the variable before the child require

And if you don't use it in *this* module, then strictures won't have any
problem with it.

....
The above will print the correct 'table1' key, but my question is am I
setting myself up for disaster if I actually try and go this route? I'm
not saying it's the most elegant code, but since it's not a true object
that I want but more of a configuration file is there any danger in my
assumption that the require will properly result in the %appInfo being
the child version.

That seems to be correct, in the main package (or whichever package
executed the require). Not for other packages, however.
I currently have the data all in one big configuration file but it's
quickly becoming unwieldy and too large

What does that mean? It is taking too long to parse? It is taxing your
server memory? It is causing your text editor to crash when you try to
edit it? It is taxing you mental ability to understand it all?

Xho
 
U

Uri Guttman

MG> The problem in a nutshell is how do I make the variable "exist" in the
MG> eyes of strictures but not know what it contains until the require
MG> happens. I was trying to come up with any trickery I could just in the
MG> interests of seeing what else was possible, but I think I'll just go
MG> back to tried and true.

as we tell others when they do a config with tons of scalars:

use a hash.

then you can declare it with our %config in each of the required files
(assuming they are all in the same name space). in each file you just
execute a set of assignments (or a large slice assignment) to the config
hash. you can even have a my hash in the file and assign it with a slice
to the main config

if you load the required files in the correct order (and some required
files will load others) you can control the order of the assignments to
get what you want. this is not true inheritance but good enough.

and i recall talking to michael schwern about a module to make data
inheritance work. i can't find it under his cpan id. but there might be
something like it on cpan. as always i find that kind of design to be
overkill.

uri
 
M

Mumia W.

[ problem with inheriting class data snipped ]
The problem in a nutshell is how do I make the variable "exist" in the
eyes of strictures but not know what it contains until the require
happens. I was trying to come up with any trickery I could just in the
interests of seeing what else was possible, but I think I'll just go
back to tried and true.

Matt

IIWY I would use Class::Data::Inheritable and re-write the
application code to use the class data accessors.
 
M

Matt Garrish

Uri said:
MG> The problem in a nutshell is how do I make the variable "exist" in the
MG> eyes of strictures but not know what it contains until the require
MG> happens. I was trying to come up with any trickery I could just in the
MG> interests of seeing what else was possible, but I think I'll just go
MG> back to tried and true.

as we tell others when they do a config with tons of scalars:

use a hash.

The data is currently in hashes, actually, but there are about fifteeen
in all dealing with various other issues. It's essentially a table
generator module that doesn't want to know anything specific about the
tables but just render them according to the information you pass in.
Unlike a straight database dump to html, however, it's configurable for
external links, cross-references, footnotes, etc. All of this
information has been abstracted out of the class and into the
configuration file, but invariably the usefulness of the module has
grown as so the scale of it has grown beyond its original conception.
I'm now working at redesigning the config data to better scale with the
application.

Unfortunately my brain has also been reduced to mush in the process,
and things that should seem obvious to me no longer are.
then you can declare it with our %config in each of the required files
(assuming they are all in the same name space). in each file you just
execute a set of assignments (or a large slice assignment) to the config
hash. you can even have a my hash in the file and assign it with a slice
to the main config

And that's what wasn't jumping out at me. For whatever reason I got it
in my head to just declare it once in the parent so that it would be
visible at compile time to the calling module and then "overwrite" it
in the require. Thanks helping me screw my head back on.

Matt
 
M

Matt Garrish

If the data can change independently, the structure of the data can change
independently, and the applications have no relation to each other, then
why even bother trying to tie them together?

Why not? The output is identical, only the structure and data differs,
and even at that only to degrees. Since the final output is identical
and only the data coming in different it would be silly to write 10
different applications that all do the same thing. Unless you like the
copy/paste approach to programming.
Just by accident? Does this shared data change frequently? When it does
change, is it highly likely to change in concert across all apps? If
either of these are "no" then it seems like it would be better just to copy
this data into each of 10 independent modules.

Why would I partition off the data between what is general across all
and what is specific to each if that weren't the case? I'm not inclined
to go into ten (and growing) modules to update information that is
shared across them all. The point is that the parent gets imported
regardless of which child gets required later. As one way of making the
data structure appear to be present when the code is compiled, I was
toying with placing blank structures in the parent and overwriting them
in the child.
...

That seems to be correct, in the main package (or whichever package
executed the require). Not for other packages, however.

I realize that, but that's not a concern. There is only one module that
imports this configuration data, so I don't need it to be available
anywhere else.
What does that mean? It is taking too long to parse? It is taxing your
server memory? It is causing your text editor to crash when you try to
edit it? It is taxing you mental ability to understand it all?

You do know that sarcasm is about as funny and original as going around
telling everyone to "tell it to the hand", right? But whatever gets you
off. If you've dealt with a program of any complexity before, you'd
understand exactly what that means. The data wasn't ever intended or
expected to grow at the rate it is now, so what was a manageable
configuration file at first and designed for the scale of the project
is now causing data conflicts. The approach to keep the file in its
orginal state is to start nesting the data within new structures and
rewriting all of the application code that handles it, or parse it down
so that it appears as though no change has been made because each
application has it's own data in its own config module (exactly as it
was originally designed).

Matt
 
X

xhoster

Matt Garrish said:
Why not? The output is identical, only the structure and data differs,
and even at that only to degrees.

The only thing that changes is the data being generated, but the data being
generated is always identical. Well, then I give up.


....
You do know that sarcasm is about as funny and original as going around
telling everyone to "tell it to the hand", right? But whatever gets you
off. If you've dealt with a program of any complexity before, you'd

That wasn't sarcasm, that a question with 4 proposed possibilities for
answers. If you had dealt with programs of any complexity before[1], you'd
know that all of them are real possibilities to encounter, and would know
that how you fix them depends on which one is the actual problem.

[1] Now that was sarcasm.


Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top