Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Concerning code factorization, efficiency and tied variables:

In the wake of Are lvalue methods (as properties) a good idea?, I've revisited an old node of mine, To Validate Data In Lvalue Subs. One thing that I realize now is that I didn't make clear how independent the Constrained class is from the notions of closures and lvalue subs. Constrained can be applied to any scalar variable, including references to anything.

What good is that? A tied interface is slower than simple assignment for a reason; it's doing something. The 40% (or whatever) extra overhead for assigning or fetching through the tied interface is trivial if you have work to do inside it. What work? Whatever is ubiquitous enough to factor this way! I think that that is more than "syntactic sugar", and it's sweeter, too.

For reference, here is a slightly updated and renamed version of Constrained, package Tie::Constrained;

use Errno qw/EINVAL EDOM ERANGE/; sub TIESCALAR { my $class = shift; my $self = { test => defined $_[0]? $_[0]: \&validate }; $self->{test}($_[1]) or invalid(EINVAL) if defined $_[1]; $self->{val} = $_[1]; bless $self, $class; } sub STORE { my ($self, $try) = @_; $self->{test}($try) or invalid(EINVAL); $self->{val} = $try; } sub FETCH { $_[0]->{val}; } sub DESTROY {} sub validate { 1 } sub invalid { $! = shift; die sprintf("Constraint violation: %s by %s::%s in %s line %s.\n", $!, map { qq($_) } (caller 1)[0,3,1,2] ); } 1; __DATA__
Usage: use Tie::Constrained; tie my $var, Tie::Constrained => \&mytest, $initval; Both arguments are optional, but the default validator function always says yes. mytest() should be designed to return true for valid data and false for data to reject.
That's much like the older code, but I've removed the stringency from FETCH() and added a dummy default validator. Those changes were to make subclassing easier. A subclass would typically override invalid() to get different error handling or validate() to have a common class-wide default test.

Data validation is the job the Tie::Constrained class does. That's an example of something you may want to do many times, the same way each time, every time a mutator is applied to your variable.

Off the top of my head, I can think of three basic ways to code those tests.

  1. Paste in a call to a validator function after each mutation. At least, just before each use where the validity matters.
  2. Bless the variable into a class which overloads mutators to validate.
  3. Tie to Tie::Constrained

The first and most obvious one is dismal in practice. The mutation is done to your variable before you get to validate. You can't apply it to third-party code. Paste errors may gum you up. Maintainance is a nightmare. The limited checking of 1b) does nothing to inform you where the bad data crept in. The code has flashing neon signs saying "Factor me!"

The second is better, but it has problems of its own. The proliferation of classes confuses development. Overriding core functions and overloading core operators confuses everybody. The class packages represent a lot of perhaps tricky code to write. Factorization is pretty good, but nothing like . . .

Three. Once a variable is tied to its very own automatic validity check, every mutator will be checked before the variable is modified. That is true of old code and new, third-party code, perl modules, all without the code needing to know anything about it. No infrastructure at all. No special coding beyond the tie call.

That is code factoring with a vengence. I also consider it a particularly sparse and clean kind of OO code, where the object is the aggregate of variable, test and exception.

I'm considering doing a little more tuning and much pod writing to prepare a distribution for CPAN. I'll welcome your comments.

After Compline,
Zaxo


In reply to Tie Me Up, Tie Me Down by Zaxo

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



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (5)
As of 2024-04-19 13:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found