fREWdiculous!
7 Sep
I’ve taken care of a significant portion of the refactoring that I’m doing to disable meta-tests for the Moose test suite. I’ve done all the tests up until the 100 series (which are examples.) The following is an example of how it’s done:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #!/usr/bin/perl use strict; use warnings; use lib 't/lib'; use Test::More tests => 23; use Test::Exception; use MetaTest; { package Foo; use Moose; use Moose::Util::TypeConstraints; } skip_meta { can_ok('Foo', 'meta'); isa_ok(Foo->meta, 'Moose::Meta::Class'); } 2; meta_can_ok('Foo', 'meta', '... we got the &meta method'); ok(Foo->isa('Moose::Object'), '... Foo is automagically a Moose::Object'); skip_meta { dies_ok { Foo->meta->has_method() } '... has_method requires an arg'; dies_ok { Foo->meta->has_method('') } '... has_method requires an arg'; } 2; can_ok('Foo', 'does'); skip_meta { foreach my $function (qw( extends has before after around blessed confess type subtype as where coerce from via find_type_constraint )) { ok(!Foo->meta->has_method($function), '... the meta does not treat "' . $function . '" as a method'); } } 15; |
Typically there will be some skip_meta blocks scattered throughout a test. As it stands the skip_meta (and skip_all_meta variant) will skip if the SKIP_META_TESTS environment variable is set. As I said before, if people want to change that it’s only defined in one place so we can change how it’s done fairly easily.
There are a few places I’m not sure I need to skip yet, like things in the Moose::*::Meta namespace. But I know for sure to skip the ->meta stuff, so that’s what I’ve been doing. The 100 tests are quite a bit more complex, which is why I haven’t finished any yet. I certainly plan to, and hope to take care of them soon. But in the meantime mst can get started on Antlers as a good amount of the tests should work for him now.
If anyone wants to help out let me know, and we can make Moose faster sooner!
1 Sep
Today the question was asked: “To Moose or Not to Moose?” The article is fairly well written, but it seems to me that the comments are not exactly educated. Here is the main one this is in response to:
I’d try Mouse too. Unless you’re doing something funky I’d be surprised if it’s more than a 1 letter change to your source code.
First off, here is a quote from the POD:
Moose is wonderful. Use Moose instead of Mouse.
The author recommends not to use Mouse. That’s a big deal to me. Also, enjoy the following quote:
The original author of this module has mostly stepped down from maintaining Mouse. See http://www.nntp.perl.org/group/perl.moose/2009/04/msg653.html. If you would like to help maintain this module, please get in touch with us.
He’s also given up on it. Moral of the story, don’t use it.
Today I started working on mst’s plan for MX::Antlers, which is a way to use the actual Moose, with the speed of Mouse, without persistence or anything like that. Great for CGI and whatnot.
Now I’m a little fuzzy on the implementation, but if I understand correctly this will “compile” Moose into a single file. It will not include Class::MOP, so you won’t be able to use ->meta, but generally for basic modules don’t need it, so no big deal really. What I am working on is updating the existing Moose test-suite to disable the tests for ->meta. My current plan is to use an environment variable, but whatever I do it will be a function so that we can change it to some other methodology if we need to.
So! Get excited! Depending on the code we may be able to abstract it to apply to other heavy frameworks (Catalyst?) to make them sufficiently fast as well. Once I have some basic stuff in the public repo (hopefully a couple before Friday) I’ll put up a post or two explaining how to get the work done, and then we can parallelize the work. Who’s with me?
22 Jul
I am just getting through chapter four of the Catalyst book and there are already a whole lot of things worth mentioning. My internet is currently at 50% packet loss because our wifi router is busted so this is pretty painful for me. So we’ll keep it short.
The book has a nice (very short) introduction to Moose. Not only is this good because Catalyst is now based on Moose, but also I would say you probably want your OO code to be based on Moose. There are times when you probably don’t want to use Moose, but there are also times when you don’t want to use strict. As a rule, use Moose for OO code.
There is also a very good introduction to usage of CPAN. A lot of us think that CPAN is our programming platform. Knowing how to use it is extremely important. It includes not just finding stuff on CPAN, but also ascertaining the quality of those modules, and how to install them. Very good information for a perl programmer.
In chapter 4 mst discusses how he writes tests (which can be slightly supplemented with his latest blog post) and it’s actually quite helpful. Some people write tests after writing their code and run the risk of forgetting to test at all (that’s me!) Other people are all hardcore TDD and write tests first, but that assumes that they have already thought through the interface for what they are writing. mst posits that it’s better to write your code, and “test” it from test files as you go. And test in this case means warns, Data::Dumps, whatever. After it works how you expect, you then take those warns and whatnot and translate them into ok’s, is’s, and cmp_deeply’s. It’s really much nicer than the alternative: build it all and see if it works. Try it!
Lastly, I really like how they represent code as diffs instead of monolithic code. Writing large swaths of code doesn’t work that well in real life. It works much better to do tiny changes and make sure they still compile, do what you want, etc.
But the book certainly isn’t perfect! There are some weird code layout issues, (p34, 36, 39, etc) and I am pretty sure I saw at least one syntax error (END__ instead of __END__).
So far though, I would say that the book is better than most programming books. Really, a lot of programming books need to be more like this, instead of focusing entirely on the arcana of one framework they should help you be a better programmer overall.
21 Jun
Today was the first day (for me) of YAPC::NA. It was pretty cool! A coworker and I convinced our work to pay for us to go to YAPC and go to the Moose Masterclass. The class was very good. I thought that the slides were very complete and that the exercises were great for a professional conference. Basically he would present a major section of Moose (there were 4 or 5 I think) and then he would tell us to get going on the Classes for that given library. We would get instructions from comments in the base unit test file and then we would just run the unit tests to see if we were doing the right thing. There were some discrepancies between the comments in the tests and the tests themselves, but I’d say that’s pretty standard for comments. Anyway, the slides were all just webpages and the rest was of course just perl code. So check it out here!
I actually found the most intriguing part of the talk to be MooseX::Types. Unfortunately that is not included in the slides linked about as it was done by Jonathon Rockway. I can’t yet find slides for it. But the important thing is that Types are awesome with Moose. It’s fairly trivial to write new types. He wrote a type for Social Security Numbers and then showed us how to use it and how to make a thing that would automatically coerce integers into the SSN type. Very cool stuff! I am very excited for when I get to use that in the future.
Another thing that must be mentioned. There is always someone in a talk who wants to be heard more than the presenter. Or maybe they just act that way. I don’t know. But we had one of those in our talk. There was a point at which our presenter was showing how to have a singleton as an attribute to a class and apparently this guy zoned out when he was showing it. Furthermore he didn’t notice that the code
1 2 3 4 5 6 7 8 9 10 | package Person; use Moose; my $highlander_bank = Bank->new( name => 'Spire FCU' ); has bank => ( is => 'rw', default => sub { $highlander_bank }, ); |
had the word highlander in it. Anyway, he tried to correct the presenter about this and before the presenter got a chance to respond MST yelled at the dude and said, “THERE CAN ONLY BE ONE! THAT’S WHY IT’S CALLED A HIGHLANDER!” It was hilarious.
So yeah, that’s day minus-one for YAPC. I will write about everything I go to so that you can be ok with the fact that you are stuck at work or whatever
30 Apr
We should have all heard of Moose by now as a great way to do OO with Perl. While I was working on WebCritic I decided that it would be a good idea to hook my OO stuff up Moose style. I figure that even if I were to just write code and then disappear I might as well write 2009 code instead of 1999 code so that if it ever gets copied it will bless the copier instead of curse them.
One reason that Moose is great is that it makes things that you do all the time very succinct and obvious. For example, before:
1 2 3 4 5 6 7 8 |
after:
1 2 3 4 5 | has directory => ( is => 'rw', isa => 'Str', required => 1, ); |
That’s not a lot shorter, but it is more clear. Plus we get some extra error checking for free.
There’s also some cool options that allow you to write cleaner code. Before:
1 2 3 4 5 6 7 8 9 10 11 12 |
After:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
The boilerplate in the first version goes away in the new version. Much nicer.
And lastly, check this out, before:
1 2 3 4 5 6 7 8 9 10 11 |
after:
1 | # nothing! |
That’s right! All of that goes away and gets created automatically by Moose. The error checking is done automatically. Instantiation is done automatically. And heck, it will even work with a hash or hashref as the instatiation data!
13 Feb
Today I was talking with a friend about the stuff we are doing at work and I mentioned to him how I was planning on doing the authorization. Since I had only thought about it at that point I didn’t even know if my idea was valid Perl syntax, let alone a feasible idea. But enough with the backstory, how about some real information.
Let’s assume that we have a webpage that lets you read user data and write user data. Theoretically we have already logged the user in, so we know who they are talking to, and we have a simple database model of the roles the user is authorized for. That’s no fun but it’s pretty easy. Three tables: one for the user, one join table from user to roles, and one that lists roles. So if we wanted to limit a sub to a user with role ‘read_user’ and ‘write_user’ we could do this:
1 2 3 4 5 6 7 8 | sub read_user { my $self = shift; if ($self->user->has_role('read_user') and $self->user->has_role('read_user')) { # display user data somehow } else { # display some form of error } } |
That’s really a fine way to do it. It works. It’s how most things work. But it would be no fun to have to write that for essentially every page on a site. That’s a drag!
Perl has this thing call attributes; which is basically a way to tag functions. At first I thought, “Hey, we’ll just tag a function with it’s roles and have validation work based on that. So our previous thing would look like this:
1 2 3 4 |
That would be great! But how on earth would you do something like that? I started off looking at the source to AutoRunmode which basically gave me this idea in the first place. There is some very deep magic in there, so I decided to keep looking. The source to AutoRunmode references Attribute::Handlers, originally by Damian Conway (author of numerous Perl
books
) which allows me to at least do something when someone includes a handler. That’s a start. So I looked at how to use Attribute::Handlers and after seeing what was possible I decided it would be easier and more clear to change my goal to this:
1 2 3 4 | sub read_user : Authorize(qw/role_read_user role_write_user/) { my $self = shift; # display user data somehow } |
That way if I use the Attribute::Handlers system I write a single function that gets a list of roles (amongst other things.) Then came the hard part. How can you change a function in Perl? Well, it turns out that changing a method is Kinda Hard, but Dave Rolsky Stevan Little made Moose, which makes it totally easy!
So this is the final mockup of how I plan on doing it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package MyClass; use feature ':5.10'; use Attribute::Handlers; use Moose; sub Authorize : ATTR(CODE) { my ($class, $globref, $referent, $attr, $data, $phase, $filename, $linenum) = @_; # deep magic that gets the name of the function my ($function) = ${$globref} =~ /::([^:]+)$/; $class->meta->add_before_method_modifier ($function => sub { foreach (@{$data}) { $class->validate($_); } }); return; } sub read_user : Authorize(qw/user_read user_write/) { my $self = shift; say "reading personal files!"; } sub validate { my $self = shift; my $role = shift; say "validating $role for ".$self->user; } sub user { my $self = shift; return 'frew'; } |
Debolaz from #perl helped out a lot with this one. The only major thing left is some way to check all functions with the attribute ‘Runmode’ and ensure that they also have the Authorize attribute with at least one thing in there. That way we can’t accidentally forget to authorize people. I don’t think that will be very hard, but even if we can’t do it, this is still great.
The only thing I am worried about is whether I can use Moose in a CGI::App class. Probably, but we’ll see.
Hurray for Perl!