fREWdiculous!
17 Jan
Recently I took it upon myself to make Catalyst::Plugin::Authentication know users had logged in after users had logged in in a completely non-Catalyst part of our app. After LOTS of frustration, code spelunking, and bugging a couple people in #catalyst (hobbs and t0m) I got it working.
Basically what I did was have the session plugin look at a different cookie and load information from our own strange brew of session table. It’s not perfect, but I’m much happier with it than I was before. Here’s the code:
First, you need to create your own Session Store, our app is called Lynx, so the namespace reflects that:
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 | package Lynx::Session::Store; use strict; use warnings; use base qw/Catalyst::Plugin::Session::Store/; use DateTime::Format::MSSQL; use Catalyst::Authentication::Store::DBIx::Class::User; sub get_session_data { my ($c, $key) = @_; my ($k, $v) = split /:/, $key; if ($k eq 'session') { if (my $login = $c->model('DB::Login')->single({ access_num => $v })) { return { __user_realm => 'default', __user => { user => $login->userid, }, } } } elsif ($k eq 'expires') { if (my $cookie = $c->request->cookie('Access_Num')) { if (my $login = $c->model('DB::Login')->single({ access_num => $v })) { my $ex = DateTime::Format::MSSQL->parse_datetime($login->last_accessed)->epoch + 720 * 60 - DateTime->now(time_zone => 'local')->offset; return $ex; } } } } sub store_session_data { } sub delete_session_data { } sub delete_expired_sessions { } 1; |
We have stub methods for the session stuff that we don’t support. Eventually I may fill those out, but what’s more likely is that we remove this code entirely and just use what’s provided by CPA.
Next is get_session_data, which gets arguments like session:1234 and expires:1234. They are meant to return the session data and the expiry time (seconds since epoch) respectively. Clearly I had to do a lot of really weird stuff with datetime to get that expiration date from our database, but it works, so that’s cool. You may store your expiration directly. Who knows.
So far, so weird. Then I had to figure out how to “inflate” the session. The keys __user_realm and __user are hardcoded in CPA, and I kinda think they should change to just current_user_realm and current_user, or maybe catalyst-plugin-authentication-user. Whatever. But the fact is they are what they are. The value for __user_realm is which realm is currently selected. I imagine the vast majority of people should have that set to default, as they typically only have a single realm (we actually have two, but I didn’t realize till this code broke in a special way.) The value for __user is not a user object, but instead what get’s passed to the auth store’s from_session method. I am mostly sure about that, but it’s a pretty deep stack trace at that point.
Next up I made a Session subclass:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
This is clearly pretty basic. I just overrode sessionid to look at our cookie to get the sessionid.
After that I just loaded the plugins I needed and configured CPA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ... use Catalyst qw( Authentication +Lynx::Session Session::State::Cookie +Lynx::Session::Store ); ... 'Plugin::Authentication' => { default => { credential => { class => 'Password', password_field => 'password', password_type => 'clear' }, store => { class => 'DBIx::Class', user_model => 'DB::User', }, }, }, ... |
Note that the credential is unused in my use case as catalyst doesn’t do the actual authentication at all.
Hope this helps someone!
19 Sep
Recently I needed to do some deep cloning of some objects at work. I think I ended up looking at all of the major ways to do it, and I figure I might as well discuss them here.
Nearly everyone should be able to answer this, but it doesn’t hurt to define it anyway. Deep cloning means you clone other things the current object is related to, recursively. So while a shallow clone of a hashref (in Perl) would be merely:
1 | my $clone = { %{ $other_hash_ref } }; |
That doesn’t do if the things in the hash get mutated and are also references, because in that case you’ll be modifying parts of the other hash, possibly surprisingly.
Well yes. If it’s something as basic as a simple data structure you can just use Storable. The code for above would become:
1 2 | use Storable 'dclone'; my $clone = dclone($other_hash_ref); |
Storable has been core enough for long enough that if it’s not core you need to upgrade
Sadly just default Storable isn’t good enough. I needed to deeply clone the objects, but not clone any related schemata. That is, the objects had a DBIx::Class::Schema object attached to them and for various reasons I do not want to clone that at all. The correct way to deal with such an issue is to define the two Storable hooks as follows:
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 | my @stack; sub STORABLE_freeze { my ($self, $cloning) = @_; die q(you can't freeze this thing silly!) unless $cloning; my %ret = %$self; my %frame; $frame{schema} = delete $ret{schema}; push @stack, \%frame; return \%ret } sub STORABLE_thaw { my ($self, $cloning, $ice) = @_; die q(you can't thaw this thing silly!) unless $cloning; my %frame = %{pop @stack}; my $new = $self->new({ %$self, map { $_ => $frame{$_} } keys %frame, }); %$self = %$new; } |
This is a little more generic than you probably need, and came from my prototype module, Clone::Hooker, but I gave up on that as well as Storable.
Two reasons; first, defining the hooks above might be a bad thing. Storable is something that someone other than me may use, and by defining the hooks above I am changing the relatively generic interface of Storable for my module. Second, there’s a better alternative that I ended up using.
I ended up settling on the handy MooseX::Clone. Obviously it is for Moose modules only, but all of my modules are Moose objects in this case. It’s very simple to use, here’s how it works for me:
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 | package Dashboard; use Moose; with 'MooseX::Clone'; has gadgets => ( is => 'rw', isa => 'ArrayRef', traits => [qw(Clone)], ); 1; package Gadget; use Moose; with 'MooseX::Clone'; has schema => ( is => 'ro', ); 1; my $d = Dashboard->new( gadgets => [ Gadget->new( schema => $schema, ) ] ); my $cloned_d = $d->clone; |
This avoids the “global” nature of changing the interface of Storable, is fairly unobtrusive in my code, and works well.
7 Sep
I left my book and notes at work yesterday, hence the late post.
What is the external interface for creating a new object when a Constructor Method is too wordy?
Sometimes creating an object is exorbitantly wordy. The example that the author gives (in javascript) is the following:
1 | var p = new Point({ x: 1, y: 2 }) |
Add methods to a lower level object that can construct your objects. Take care to only do this rarely.
This can’t be done with the example given in javascript, but the idea is to do something like the following:
1 | var p = ( 1 x 2 ) |
Personally, I’m very wary of this idea. I see the value, but even operator overloading, which is a step HIGHER level than this, is usually viewed skeptically. I do think it’s a good idea to make shortcut methods to instantiate related objects, but that’s a far sight better than creating a method on all integers. If you do monkey-patch something like integer, it would be best if it were done dynamically, so only the code in your own project sees it.
How do you convert an object’s format to another object’s format?
This is (at least to me) quite obvious. Some would think that they should add methods to every object to convert to other formats. So one might monkey-patch the DOM stuff to return a jquery DOM thing with the asJQDom method or something like that. Of course doing that means you’re going to end up with a ton of random conversion methods.
Convert objects by merely instantiating the second object type
This just seems so obvious I almost feel bad even writing it…
3 Sep
I’m surprised I haven’t actually blogged this before. I had to do it recently for the first time in a long time and I figured I’d share the secret sauce.
At work we just added a complete permission system on top of our existing user system, but we didn’t want to make the UI as flexible as the underlying code. We ended up making a single role (which has all permissions) called “Full Control”. Without that role all you get is the stuff configured directly for your user; that is, your user gets a dashboard. So instead of making a grid of roles etc etc we just made a single checkbox on the user edit form. Of course I could have put in controller code to handle this special case, but I’m trying to get better at factoring code correctly. (As an aside: two years ago I would have also put all of this in the model; the frustrating thing is that Fat Model Skinny Controller only really works for relatively small apps. I’ll try to do a blog post on why I think that at another point later
)
Anyway, first off, here’s the full_control accessor I made:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Not a whole lot going on. If an argument is passed we set the user’s roles based on the truthiness of the argument. Because the system is currently just the one role we delete all roles for clearing it. Later on if we make the system more full featured we’ll have to change this up a bit of course. If no argument is passed we just return the count of full control roles, as that approximates truthiness just fine.
Next up are the “insert” and update wrappers. I quote insert because I actually override new:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | sub update { my ($self, $args, @rest) = @_; my $full_control = delete $args->{full_control}; my $ret = $self->next::method($args, @rest); $ret->full_control($full_control); return $ret } sub new { my ($self, $args, @rest) = @_; my $full_control = delete $args->{full_control}; $args->{user_roles} = [ { role => { name => 'Full Control' } } ] if $full_control; my $ret = $self->next::method($args, @rest); return $ret } |
The code for update should be abundantly clear. We just update the object, calling our accessor afterwards. The new code is a little bit more messy. Basically, instead of trying to use the accessor on new (which is wrong as new doesn’t actually imply an insert) we just leverage the excellent MultiCreate which DBIx::Class provides for us.
And that’s it! I hope this helps you get your job done that much faster/better
3 Sep
How do you set instance variables from a constructor method?
The fundamental issue here is that often validation is bypassed at construction time, for whatever reason. So one’s accessor may look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Clearly this method is just doing to much. To solve this we make special set methods that are entirely to be used during construction. So in Perl this might look like the following:
1 2 3 4 | sub _set_x { my ($self, $x) = @_; $self->{x} = $x; } |
Interestingly, with Moose we happily side-step this issue, as the default constructor doesn’t go through the accessors and already sets the raw values.
Ok, so I think I may start trying to apply this stuff to JavaScript instead of Perl. I almost feel like the fact that I have Moose in Perl is cheating. I know that there is Joose in JavaScript, but I’ve yet to use that in production, and I find that I have a harder time making well factored code in JavaScript than Perl. Part of that is that the underlying libraries I use in JS (ExtJS 3) are not really well factored either, but I still struggle with overall structure.
1 Sep
Sadly reading is going slower than expected due to being so busy with various things in life. Oh well, just a single pattern today.
How do you represent instantiation?
In addition to a vanilla constructor, add methods for common cases to instantiate typical objects. For strange cases allow the use of accessors.
Using Perl (with Moose) an example might be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
So now both of the following work:
1 2 | my $p = Point->new(5, 6); my $v = Point->r_theta(10, 1.4); |
31 Aug
Today I had to spend time taking care of passport stuff for my upcoming honeymoon, so I only got to read a handful of pages. I’ll post my notes nonetheless.
Methods are more important that state because, correctly factored, methods paper over any changes in state over time. Most of us who took OO classes in college had this hammered into our brains
Methods should be written to get something done, but should also be written to communicate with the reader. Method names like “task_1″, “task_2″, etc are completely useless for a regular person, and should be named as to what they actually do.
Small methods are expensive in that they cost more CPU cycles and typically cause the novice trouble in following the structure of a program. On the other hand, more methods means more human readable names, easier maintenance (pinpointing changes,) and method overrideability is much more feasible with small methods.
How do you split your program into methods?
As already mentioned, large methods are faster and easier for the reader to follow, but small methods with good names work well in the long run. A seasoned programmer is able to see a method and assume what it does without needing to read the code for it. On top of that, small methods with good names allow you to communicate the structure of your code to the reader. Also, small methods are a must for inheritance.
Split your program into methods that do a single identifiable task.
A Perl example might be something like:
1 2 3 4 5 6 7 |
The Composed Method patter can be used in a top down fashion, that is, write your higher level methods in an almost pseudo-code fashion, and then fill in the details of the lower level methods as you work. You may also opt to use the bottom up approach of writing a larger method and splitting it into smaller methods as you notice repetition or other reusable structures. Or lastly (and I think the most new idea to me) you can use this to find holes in your API. So if an object is calling more than one method on another object, the second object probably needs to implement a method that will encapsulate the multiple calls.
30 Aug
For work I decided I’d start reading some technical books, taking notes, and then trying to reiterate what I’ve learned. Yesterday I read the Preface and Chapter 1 and today I read Chapter 2, but sadly it’s all still introductory. I might as well discuss what I’ve read nonetheless.
First though, I should say that I am reading the book because Thomas Doran of Catalyst development recommended it, and it clearly applies to Perl with Moose. I am sure some of it won’t be applicable (the whitespace formatting for example) but hopefully it can make me a better programmer.
The main point of the book is to go over things that programmers deal with all the time, examples given are naming, where to split up methods, and how to make comprehensible code.
The overall structure of a pattern is:
Patterns (especially the ones in this book) are good for pretty much everyone. Beginners, obviously, as they don’t have experience or habits yet and these are “blessed” habits that they can start using immediately. Professional programmers may get a fresh perspective or even more importantly a shared vocabulary for what they already do. Teachers can use patterns as stepping stones to teach students or even just ideas for material to teach. Managers, lastly, can use patterns for communication, so that they can actually understand what their programmers are doing.
The title, Smalltalk Best Practice Patterns, can be broken into three parts. Smalltalk is the language used in the book. Best Practice is a legal term which basically means you did what a professional would do, without neglect. And Patterns are, according to the book, decisions that experts make over and over.
Interestingly, the distinction is made between coding and programming, which I always thought was largely archaic. The fundamental point that Beck makes remains though. There is a time for planning, and a time for implementation, and if you run into an issue during implementation change the plan.
When programs get huge, hard to understand, and generally unwieldy, the information you should take from this is that you need to fix whatever issue is causing these problems, don’t just assume that the plan is set in stone and leave it forever.
The patterns described in the book should help you decrease duplicate code, remove conditional logic (not really sure what he means by that yet,) simplify complex methods, and clean up “structural code,” that is, using objects as data structures.
Good programs balance speed of development, project mutability over the lifetime of the system, and “copy pasta,” which is my term for making code that should be ok to be cargo culted.
Keep in mind that some patterns on help some of the above items listed. That’s reality and part of becoming a great programmer is knowing which thing to optimize for when.
Another thing stressed in the book is that code should be written to be read. That doesn’t mean write lots of comments (this is my interpretation) but it means name variables well, name methods well, and don’t do confusing things in the code if possible.
The things that all patterns take into account are productivity, life cycle cost (not making something so unmaintainable that you can’t do other work too,) time to market, and risk. Again, these things need to be balanced.
According to Beck, good style is not repeating yourself, writing short methods and small objects, things should be modular and replaceable, low coupling which again leads to replaceability, and lastly, segmentation based on rates of change. The last bit I’d never really considered before. A perfect example is Catalyst vs CGI::Application. With Catalyst you have a “context” that changes for each action and gets passed to the controllers. The context has a request and a response. With CGI::Application, on the other hand, the request and response are part of the controller, so the controller gets mutated on each response at a higher rate of change than the controller really needs.
A number of issues aren’t discussed in the book. Exception handling is one, as it is confusing and the author didn’t have a signification amount of experience with it. Copying objects isn’t really discussed as it’s usually a performance suck. Become (which I’m guessing is a Smalltalk feature) isn’t discussed because it’s confusing. Performance isn’t discussed as it’s typically not worth considering. Overall design isn’t discussed; he points to the Gang of Four book for that. Modelling and Requirements are entire books in themselves and thus left out. And lastly UI design is left out, as it’s probably an entire field in itself.
The book is organized into 6 parts, philosophy of patterns, patterns for methods, patterns for state, patterns for collections, a brief overview of classes (in Smalltalk I’m guessing,) and formatting (which I might not even read.)
There are three methods for adoption of patterns listed in the book. First is the Bag of Tricks method, where you pick and choose the few that you’ll start to implement over time. Next is as a fairly large style guide, complete with justifications. You pick the patterns for your organization, have programmers read them, and then ensure that people use them. Last is the Whole Hog method, where you keep the book in your lap and every time you need to make a choice the book discusses, you look up the appropriate pattern and apply it. I’m hoping to try the latter method, but we’ll see if I can keep to that.
To learn a pattern you should focus on the context (patterns before and after the pattern.) You should read the example. Focus on the problem shown and the solution shown. If possible try to find examples of the problem in your own codebase. Lastly, write your own example. I fully intend on writing an example of each pattern in Perl.
One interesting point is that patterns are supposed to work where code reuse doesn’t. Another interesting fact is that a lot of these patterns are so small that reuse would be meaningless, for example, how do you “reuse” the naming of a method?
One of the main goals for patterns is to increase communication. To increase communication you either need to say more, or have the speaker and listener share more ground so words mean more. The latter is what patterns try to achieve.
By knowing patterns you should be able to understand code that uses such patterns better. Patterns will also help you answer questions that come up constantly during development. Shared patterns also help reduce the friction involved with code review as you just request that a pattern be implemented in a give place. Patterns can also reduce documentation as it is more shared by the writer and reader. Lastly, when joining an existing project, rote application of a handful of patterns can often help general understanding of the project as well as some basic cleanup.
The format for all patterns is: a title/name for the pattern, optionally any patterns that should be read before the current pattern, the problem that the pattern solves or maybe the question it answers, the forces that constrain the pattern, the solution to the problem, discussion or practical application of the pattern, and lastly, any patterns that should be read after the current pattern.
29 Aug
This week I finished the following three git conversions:
And I started on the following four git conversions (I think they are ready but I want t0m to sign off on them) :
28 Aug
One of the things that annoys me a lot when using git is if I go through a lot of work to stage some changes, probably using `git add -p` to stage parts of files, and then from muscle memory I type `git ci -am ‘lolol I dummy’`. If you didn’t know the -a says commit everything, so then of my painstaking staging is gone.
Well, on Thursday I finally fixed this problem. I wrote the following, very basic, git wrapper. All it does is:
I’m fairly happy with the alias detection; the only thing it should also do is introspect the arguments in the values of the alias as well as the current command. I don’t have any aliases like that, but if I wanted to make this a canned solution that would be a must.
The arguments detection is actually very dumb. It wouldn’t work if you did `git ci -m ‘Foo’ -a`. I’m ok with that because this is to battle my own muscle memory and I would never type that. But it is definitely a spot for improvement.
The staged checking I am very happy with. It only checks for staged modifications. So if you add a new file or delete a file and then do `git ci -am “station”` it will happily go on it’s way, which I like.
Anyway, here’s the script. To install it just put it somewhere in your path as wrap-git (I use ~/bin) and alias git=wrap-git
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 | #!/usr/bin/env perl use strict; use warnings; my %aliases = map { split(/\n/, $_, 2) } split /\0/, `git config -z --get-regexp alias\\.`; my %commit_aliases = (( commit => 1 ), map { s/alias\.//; $_ => 1 } grep $aliases{$_} =~ /^commit\b/, keys %aliases); my ($command, @args) = @ARGV; if ($commit_aliases{$command} && $args[0] =~ /^-a|^--all/) { my @staged = grep /^M/, split /\0/, `git status -z`; if (@staged) { print "There are staged changes, are you sure you want to commit all? (y/N) "; chomp(my $answer = <STDIN>); if ($answer =~ /^y/i) { run_command() } } else { run_command() } } else { run_command() } sub run_command { system 'git', $command, @args; exit $? >> 8; } |
One thing I think would be really cool would be to make a WrapGit.pm and wrap-git would just be coderefs passed to WrapGit.pm. I’d love to have full introspection of all git commands and arguments. It would let me do things like keep statistics about how you use git, maybe make a powerful achievement system, make more commands prompt the way this one does. Anyway, I’ll probably do that one of these days when I finish all the other stuff on my list