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
{
package
DA::LSD;
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
eval{
$address->ping();
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/DA_D.pm 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