I think you should do some more thinking about your interfaces.

I know it is tempting when turning loose on the OO way of thinking to go overboard. For instance writing get/set methods for everything. Having dice that know everything about themselves. So on and so forth.

But such over-engineering is one of the major (IMHO) pitfalls of OO design. To avoid it, stop and walk through how you expect your stuff to be used. Do it by hand if need be. (An interesting extreme programming exercise is to have people stand in a room, each one being another object, and walk through the algorithm, watching as people make requests.)

What you want to do is export a simple interface that can be implemented internally efficiently. For instance most of your get/set routines can be replaced by hash interfaces that you declare cannot be accessed externally. In one stroke you throw away a large amount of your interface and get a huge performance win.

For instance why should a die keep track of its last roll? Almost never is that needed. OTOH you are constantly going to want to roll a particular type of die many times in a row. Why require a ton of objects for that? I maintain that in practice the simpler interface of saying that a die has a size and can be rolled to be rolled many times is just as flexible and far more efficient:

package Dice::Die; $VERSION = 0.04; use strict; sub get_size { (shift)->{size}; } sub new { my $init = shift; my $class = ref($init) || $init; my $size = shift; return bless {size => $size}, $class; } sub roll { my $self = shift; my $count = shift || 1; my $size = $self->{size}; return map {int(rand($size) + 1)} 1..$count; } 1;
(Note that while I provide an external accessor, I don't use it internally.)

Another point is be lazy about doing work. For instance in your Dice::Dice::roll method you do a tremendous amount of work keeping track of totals etc. I have to ask why. After all my experience with role-playing games suggests strongly that people will want to start rolling 5 and taking the top 3 very shortly. Just do a roll and return results. Allow the work of massaging that data to be done by someone else. (Do something simple, and do as little as possible.) After all that is why we have List::Util and friends.

Oh, also think twice before tracking stuff yourself. For instance if you kept your current design I would modify your roll method in Dice::Dice to look more like this:

sub roll { my ($self) = shift; my $diRef = $self->get_di; my ($total, @roll); foreach my $di ( @$diRef ) { my $rolled = $di->roll(); push( @roll, $rolled ); $total += $rolled; } $self->set_total($total); $self->set_dice(\@roll); return $total; }
Oops, where did your quantity go? I don't need it because every array in Perl already knows how long it is. Besides which there is less room for me to make a mistake (and there is somewhat better performance) if I don't try to use explicit for loops.

Another warning is that the entire idea of a pseudo-hash is flawed. There is a real possibility that when Perl 5.8 comes out it will no longer be supported. It is virtually certain that it is an idea that will not survive into Perl 6.0 due to implementation issues. In other words code that depends on it will be in the acceptable 5% breakage. Which means that no matter what the performance benefit may be, it is unwise to start using it.

Unfortunately there is no good way to learn that other than by paying attention to development discussions. But after the first attempt at Perl 6 (the Topaz effort) crashed and burned on that issue, the value of supporting it has to be questioned. Oh, something else with the same idea likely will be introduced in time. But not with that interface.

Besides which the performance benefit is probably not that big for you. While they make accesses faster, they make construction more expensive. Given that your design results in constructing lots of objects that are accessed very few times each, this may well not be a net win. (Hey, as another benefit of not using them you get to do less typing! :-)


In reply to Re (tilly) 1: Dice::Dice by tilly
in thread Dice::Dice by coreolyn

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.