And now for Tea

Now in my last post I left off with a bit of a code mess. Roles bleeding code into each other and my API in a dreadful state.

Well on thing I have seen before in non moose apps was use something called 'Class::Rebless' to rip the 'DA::LSDs' from my DA class but that is sort of an abuse of that code as it really is just for renaming name-space and I am not sure it will do what I want.

I had a look about the Moose::MOP class and found something called 'rebless_instance' which should take my original class, in this case DA with one or more LSD roles back to just a DA class.

Seems like a good idea but I think I would be opening myself up to a whole new slew of problems as I would only have a base object perhaps with it attributes in place and any other roles I may want removed.

So what to do??

Well I was thinking of making my LSD back into classes and then create a new instance of that class and threat is as a delegate. However if I was to to that each I would either have to find some way to pass in the DA down into these new classes so I can pass along the Element and View objects. That would make for very complicate or at least messy code. Did play with this a bit but after lots of typing I gave up and decided to try something else.

I used a modified delegate pattern by first creating this new class

use Moose;

has DA => (
is => 'rw',
isa => 'Object',

then in my retrieve sub I instantiate it then apply the requested LSD role
my $lsd = DA::LSD->new(DA=>$self);
if ($conn eq 'DBH'){
apply_all_roles( $lsd, "DA::LSD::SQL_D");

and I keep the does role bit as well like this
die "LSD $conn must use DA::Roles::API"
if (!does_role($lsd,'DA::Roles::API'));

and finally I call the '_execute' sub on the $lsd like this
return $lsd->_execute("retrieve",$conn,$container,$opt);

Now I did have to modify my LSD classes a little. Before I would do something like this
$sql .= $self->view()->name();

now I call up to the delegate like this
$sql .= $self->DA->view()->name();

So $self in this case is no longer my DA class but my DA::LSD class with appropriate LSD role applied. Now I would not be much of a module maker if It did not test the above so here is the test. I also wanted to see if I have any code bleed into my DA so I added in this test for DA::LSD::SQL
fail("address can ping");
if ($@) {
pass("Address cannot do a ping");

and a similar one for Pong and did them both after a load of the SQL and Mongo LSDs and got this

ok 10 - Address cannot do a ping
ok 11 - Address cannot do a pong
ok 12 - Mongo Query correct
ok 13 - Address cannot do a ping
ok 14 - Address cannot do a pong

so no code bleed. And for kicks I comment out the with again in Mongo and re-ran my tests and got this

LSD MONGO must use DA::Roles::API at D:\GitHub\DA-blog\lib/ line 31.
# Looks like you planned 12 tests but ran 11.
# Looks like your test exited with 255 just after 11.

so the API role doesn't hang around so I think I got a pattern I can work with. Now to get rid of those darn sub SQL in my View and Element objects, but fist a cup of tea.


Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations