Hello monks.. I finally have something worth posting again (or maybe i'm just sleep deprived rambling).. and it goes a little something like this:
I'm working on a web game, which will hopefully be into it's beta testing phase soon so I can get my friends to waste their precious time again :) The game is a fairly large project, whose goal was to teach me some more about OO, DBs, and CGI funstuffs...
As I was looking through the code today, I noticed that one of my first objects, a little guy called ServerInfo didn't do much in the way of enforcing data hiding. Basically, ServerInfo's main duty is to read a configuration file and control the variables that come from it.
Well, for the longest time (up till about an hour ago) ServerInfo basically read the config file variables into a hash, and then I would refer to those variables like:
my $si = new ServerInfo; $si->configure; print "This is one of the variables: $si->{'VARIABLE_X'}";
As you can see, it's just a hash holding it. Nothing prevents someone from accidentally doing something like $si->{'VAR_X'} = "No, you're not supposted to _assign_ me, you fool!". So I got thinking, how do i promote data hiding? I can't create a bunch of individual methods like $si->variable_x(), since the data in the config file changes... So, onto my solution..
What I ended up doing, in my brainded-awake-for-24+-way-too-long-hours state was to modify the configure method just slightly, so that it keys the hash variables with an opening "i'm magic, don't touch me" underscore. So, my variable becomes $si->{_VARIABLE_X}. And created another method, get() which appends an underscore to the beginning of it's argument and returns what is in the hash. Now I don't have to worry about someone doing $si->get('VARIABLE_X') = "ha! you can't touch this".
So, what i'm wondering is, is my solution a good one? or will i wake up tomorrow, look at the code and wonder what the hell I was thinking? I figure making the variables harder to play with (Oh, sure, ppl can still assign to $si->{_VARIABLE_X}, but they would have to do it intentionally, and we all know intentionally messing with magic variables is a no-no in most instances) is a good thing, but now I have to access a function rather than just accessing the hash.. I'm not sure yet if there will be much in the way of a performance loss... Any other thoughts on how to handle something like this? code critique?
Thanks monks..
-Syn0
And here's the code and a bit of the configuration file...
(oh, and this was also my first toying with POD, fun)
# ==================================================================== +== # ServerInfo.pm # Server Information object # # Copyright (C) 2001 Art C. Pacheco (Synapse0) All rights reserved. # # ==================================================================== +==== package ServerInfo; use strict; # ==================================================================== +== # /* ----------------------------------------------------------------- +-- */ sub new { my $class = shift; my $self = {}; bless($self, $class); # Grab the name of the calling executable. my $x = $0; $x =~ s#.+/##; $self->script("$x?"); return $self; } # ==================================================================== +== # script(scalar) # sets/returns name of script # /* ----------------------------------------------------------------- +-- */ sub script { my $self = shift; $self->{_script} = shift if @_; return $self->{_script}; } # ==================================================================== +== # assign(KEY, VALUE[, VALUE, VALUE, ...]) # assigns key->value pairs to ServerInfo hash # /* ----------------------------------------------------------------- +-- */ sub assign { my $self = shift; my $field = shift; my $item; $field = "_$field"; if (@_ > 1) { # we were pushed an array while (@_) { $item = shift; push(@{$self->{$field}}, $item); } } else { # we were pushed a single item $item = shift; $self->{$field} = $item; } } # ==================================================================== +== # configure() # reads in configuration file ( ./_config.inf ) and assign()s the # key->value pairs specified # /* ----------------------------------------------------------------- +-- */ sub configure { my $self = shift; my($cfg_var, $val) = ('',''); if (open(FILE, "< _config.inf")) { while (<FILE>) { # skip anything that's not a directive, untaint next unless my($line) = ($_ =~ /^(\w.*)/); chomp($line); ($cfg_var, $val) = split(/\s+/, $line, 2); $val =~ s/{(.*?)}/$self->get($1)/eg; # resolve any {vars} if ($val =~ /^\@ (.*)/) { # $val holds a list $self->assign($cfg_var, split(/\s+/, $1)); } else { $self->assign($cfg_var, $val); } } close(FILE); } else { # do something about open error print "ACK!! NOOOOOOOOOOOO : $!\n\n\n\n"; } # debug $self->assign('DEBUG', -e "$self->{_BaseDir}/DEBUG" ? 1 : 0); } # ==================================================================== +== # get(scalar) # retrieves a value (scalar or list) assigned by assign() # /* ----------------------------------------------------------------- +-- */ sub get { my $self = shift; my $key = shift; return $self->{"_$key"}; } # /* ----------------------------------------------------------------- +-- */ 1; __END__ =head1 NAME ServerInfo - Server information object =head1 SYNOPSIS # create a new server object and execute configuration use _Mod::ServerInfo; my $si = new ServerInfo; $si->configure; # access a configuration variable # used to be $email_link = $si->{AdminEmailLink} # but now it's safer $email_link = $si->get('AdminEmailLink'); =head1 DESCRIPTION ServerInfo encapsulates configuration information obtained from the _c +onfig file in the root directory. =head2 OBJECT METHODS =item $si = ServerInfo->new() Creates a new ServerInfo object. The constructor initializes the script() method described next. =item $si->script([scalar scriptname]) If given an argument, script() will set the name of the current script +. If called without an argument, script() will return the script name. script() is initialized when a new ServerInfo object is created. =item $si->assign(scalar key, scalar/list value) Takes two (or more for an list) arguments and creates a hash, assigning the value(s) to the key. =over 4 =item example: $si->assign('KEY', 'VALUE'[, 'VALUE', 'VALUE', ...]) =back =item $si->configure() Configuration method. Reads in data from the configuration file B<_config.inf> which lives in the same directory as the ServerInfo mod +ule. configure() reads in the data and splits the info at the first whitesp +ace, using the lefthand data for the key, and the righthand data for the va +lue (which can be a list). It uses assign() to place the data into a hash, accessible by the ServerInfo object. =item $si->get(scalar key) Retrieval method. Returns a value assigned by the assign() method =head1 AUTHOR INFORMATION Copyright 2000-2001, Art Pacheco. All rights reserved. =cut
config file:
BaseDir /home/tech/htdocs/arena BaseURL http://dev/~tech/arena # # Intro script (index script) # IntroURL {BaseURL}/arenaintro.cgi? IntroEXE {BaseDir}/arenaintro.cgi # # Some Default Colors # DefBody: bgcolor text link vlink alink DefBody @ #000000 #99c68e #99c68e #99c68e #bcc7c7 # Table background color TableBgColor #333333 # Hilighted text hilight #c9e6be # bold text bold #c7aa7d # undefined color UndefColor #555555 # # Battle colors # Char basic attack color ChBasAtt #559955 OppBasAtt #00aaaa ChAttHit #dddd55 OppAttHit #dd0055 ChMiss #77aa77 OppMiss #22bb99 ChArmAbsorb #658978 OppArmAbsorb #008888 ChSpecAtt #bbbb33 OppSpecAtt #bb0033 ChCounter #88cc88 OppCounter #33dddd

In reply to Object insanity and data hiding by synapse0

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.