Tuesday, July 31, 2012

Catalyst done wrong


     Perl fans enjoy their language because it allows them to be
     expressive. As such, for better or for worse, we aggressively
     defend our right to do it our way. One place where this
     attitude should be left at the door is with frameworks such as
     Catalyst.
   
     Catalyst can easily be thought of as an easier way to make a web
     app. while this is certainly true, it is more accurate to say that
     it is a means of delegating basic web application architecture
     decisions.  The delegation of directory and namespace structure
     and these built in methods certainly make things easy, but the
     fact of the matter is that this is a mere side-effect.

     This is important because these architecture decisions are made
     for a reason; to separate the logic, database, and markup. While
     this is certainly not everyone's cup of tea, it allows one to
     focus on one of these fundamental components at a time; and keeps
     us from asking that age old question: Is that stray quotation
     mark coming from the html, the query, or my Perl?
     
     Unfortunately, I keep finding myself working on Catalyst code
     that for one reason or another decides to re/undo some of these
     architectural decisions.

     For example, I've seen cases where people decide that that they
     should slice some logic out of the controller and put it into a
     new directory.  They put it at the same level as the model view
     and controller. This always seems to over-compartmentalize the
     code. The caveat of mvc is that you have to manage your app in
     three different places. Why do I need a fourth?

     Then they create libraries the way you would in an intro to Java
     class where a class is a noun and all of the actions it performs
     are verbs.  What results is a cancer that grows out of control.

     As the application slowly metastasizes, The library names don't
     match the database tables and there are always more and more
     excuses to create more mvc inconsistent modules. The result is an
     undocumented abomination that lacks the consistency of the rest
     of the application

     Developers who do this aren't awful for doing this. On the
     contrary, they are applying well accepted best practices to their
     creations. They want to architect their own application; which
     doesn't work so well when the application you are working on has
     already been architected. So if you are working on a catalyst app
     and you find yourself wanting to try any of the above, do
     yourself a favor; choose a more flexible framework or roll your
     own.

Wednesday, March 21, 2012

Overriding insert in DBIx::Class


Sometimes when working with DBIX::Class whenever you create a record
in a table, you want to create another record in a corresponding
table. Are you going to go and sift through your code base looking for
all code that writes to the table? Not when you can change your schema
class to handle the action for you.

In order to do this we can override the insert method. This example is
taken from DBIx::Class::Manual::Cookbook :

sub insert {
  my ( $self, @args ) = @_;
  $self->next::method(@args);
  $self->create_related ('cds', \%initial_cd_data );
  return $self;
}

You see above that next::method is called and then a record is
inserted in a related field. Be aware that you need to call
next::method before you call create so that you write the original
call before making the new one.

Tuesday, March 6, 2012

before, after, and around Moose


One of the things I like about Moose is its method modifiers. They
provide an easy interface to modifying methods without disturbing
them. What's more is that they are stupidly simple.

the three modifiers are "before", "after", and "around". "before" and
"after" are simple in that they allow you to run code before or after
a given method So whether you want to ensure something happens
before you run a method:

  before 'wear_boots' => sub {
      my $self = shift;
      $self->wear_socks;
  };

 or after:

  after 'use_bathroom' => sub {
      my $self = shift;
      $self->wash_hands;
  };

You can be sure that you can make it happen without disturbing the way
that the method is supposed to run.

The "around" modifier provides a lot more flexibility. It receives the
original method, the object, and then any arguments that are passed to
it. This way you can execute the original method depending on your own logic:

  around 'eat' => sub {
      my $orig = shift;
      my $self = shift;

      if ($self->time_of day eq "morning") {
         $self->{meal_type} = "breakfast";
      }
      elsif ($self->time_of day eq "afternoon") {
         $self->{meal_type} = "lunch";
      }
      elseif ($self->time_of day eq "evening") {
         $self->{meal_type} = "dinner";
      }
      return $self->$orig(@)
  };

Moose is great because it provides a simple syntax that abbreviates OO
Perl's boilerplate requirements. These modifiers are a perfect example
of this. They make overriding methods easy. The relevant documentation in the cpan is here

Thursday, February 23, 2012

How much milage do you get with SQL::Abstract?


I have been hearing a lot about SQL::Abstract. So I started trying to
put some queries together with it. It is quite interesting but leaves
me unsure about whether or not it's right for me.

The module takes data structures and returns the query statement and
the bind values that need to be passed to a DBI handle. I like this
because it allows me to just worry about the data I need to make the
query without having to worry about the sql syntax.

On the other hand is writing sql hard enough to justify this kind of
abstraction? One thing that I see happening is that if I am writing
more complex queries, I would probably just go to my database client
and start typing out queries to get what I want. Plus, at least in the
beginning I would probably be translating from raw sql to SQL::Abstract
in my head.

I guess it's kind of nifty that SQL::Abstract keeps me from having to type
so much in order to interact with the database. Does anyone use
SQL::Abstract and (love|hate) it? I'd love to hear other people's
experience with this module

Saturday, February 4, 2012

Hash de-duplication in Perl


If I were to ask you to take a list of values and remove duplicates, how would you do it? The most obvious way would be to compare every value to every other value and removing anything equivalent. However this is probably the most inefficient way as well.

Thankfully, a hash data structure has some properties that helps us with this kind of task. Due to the fact that hash keys cannot be duplicated we can just load every value as a hash key with a value. I usually choose 1.


If you run the code above you should get similar output to:


As you can see, all duplicates have been removed.

Every time you insert an item from the array as the hash key it's going to assign a "1" to that value. So once a duplicate comes along it will just write another "1" into the same hash key. Happy de-duplicating.

Thursday, February 2, 2012

TIMTOWTDI doesn't mean anything goes


Perl is a language that provides a lot of freedom. The philosophy of
"There's more than one way to do it", allows coders to be as
expressive and creative as they want to be. Unfortunately this
provides the impression that one has license to eschew best
practices.

Nothing could be further from the truth. As they say, with freedom
comes great responsibility. Sure, when you are writing one liners or
scrap code who cares, but when you are writing something serious
please make it easy to read.

I have seen too many nested ternary operators within nested maps to
forget the pain that unclear code can be to manage. What's more is I
can't understand why someone would do things like this. Yes, by some
miracle the code worked but could the original author make any sense
of it? Did they care?

Then there are the indestructible spaghetti blobs. These happen when
somebody doesn't feel like segmenting their code into reusable chunks.
So you end up having to make 5-10 small changes spread out amongst
1000 lines in order to work on the same feature.

Whoever writes this kind of code in a group setting is being
inconsiderate to any future maintainer. And if the only maintainer is
the author then they are still only hurting themselves. Sure, there may
be more than one way to do it, but please make it a manageable one.