February 2010 Archives

As I'm working on my Veure project, I've used DBIx::Migration to handle database migrations. If you're familiar with this module, this might seem like a surprising choice since it is, well, awful. However, I know exactly what the limitations are and since I'm so familiar with it, I now have a custom Veure::DBIx::Migration. There are several things I find useful about this.

If you've been using Subversion or (shudder) CVS, you only have the briefest glimmerings of what source control is about. I don't really like having to dig too deeply into tools that I use. I want them to be easy, but I dig when something's hard.

On thing which frustrated me about Subversion is that fact that, as mentioned, I don't think about some things. More than once I've quickly hacked up a change to a module, switched other modules to use that module and do a quick svn rm and svn add.

But what happens if you rename a table? I've done this more than once on my new project, continually working to ensure that I keep things clean and consistent. Unfortunately, that means that a renaming the foo_bar table to foo means that a different schema class is created, separate from the old one. Naturally, I don't think about this and I do a quick git rm and git add.

And git sees what I did and it realizes that the file has been renamed and I don't lose my history.

From what I read (I could be wrong), git actually uses heuristics to determine whether or not a file has been renamed, but so far it's worked flawlessly for me. I am still using Subversion at work (I've not felt comfortable checking out the git-svn work, but that's me being silly), and it's just painful. I doubt I'll ever use Subversion for a personal project again.

Update: came into work this morning and was asked to merge one branch into another. It was conflict hell and I was having trouble figuring out all of the changes. A colleague, using git-svn, merged the two branches cleanly, no problem. I think it's time for me to learn git-svn now.

So let's say you're looking around for a Web-based email client. Even though the Application Service Provider industry has struggled, many people want Web-based email. So when you evaluate an email client, what are you looking for?

You probably want to be able to send email. You probably want to be able to receive email. In fact, I'll go out on a limb and suggest you might want to read the email you receive. So when you are looking at email clients, what's the one feature you really, really want?

So, you're deep inside of a series of functions and you find that you really, really want what is effectively a goto: that is to say, you want to jump right out of all of those functions to the top level. Many people think "aha!, I'll just throw an exception."

Years ago, many Java programmers used to do this (of course, Exceptions are first class in Java). To paraphrase Mencken, it was simple, easy, and wrong. As understanding grew of how exceptions should be used, it was learned, surprisingly to some, that exceptions should be used for exceptional conditions. One rule of thumb was that exceptions (like aspects later) should be reserved for code where, in theory, if nothing went wrong, they could be completely removed without affecting the program's correctness. So you might throw an exception if you fail to open a file, but if you're iterating over the lines in that file (and if it's OK for that file to have no lines), then you don't throw an exception just because you've reached the end of the file. EOF is expected. Failure to connect is not. Unfortunately, failure to understand failure caused some horrible knock-on effects.

The vast majority of the time when I run the debugger on a test, I get frustrated because I have to wait for the test to load, then type '{l' (always list next window of lines before the debugger prompt) and then 'c' (continue to breakpoint -- because I've almost always set one at this point).

And in my vim config (where you put it will vary depending on your setup), I have this:

noremap <buffer> <leader>D :!DEBUGGING_TESTS=1 perl -d -Ilib %<cr>

With that, I hit ',D' (comma D) and my debugger starts up and runs to my breakpoint for me, rather than me getting annoyed at typing those instructions at the start of every debugger sections. I really need to read perldoc perldebug more carefully. There are some lovely tidbits of information there.

Long term, I'm thinking about combining some tricks with Devel::CoverX::Covered such that I can use that module with a custom $HOME/.perldb file to simply insert a breakpoint in my code (not the test) and automatically have the appropriate test run to that point without me doing anything more than simply adding a breakpoint. No more hunting for tests when narrowing down a bug.

I had written about Testing With PostgreSQL and today discovered some failing tests. It turns out this is because I had migrated a database down two levels, altered a table, and migrated it back up (I can do this because no one is relying on a production copy). Unfortunately, when I migrated it back up, the new tables didn’t have their correct triggers assigned because the _test_changed_table check was in place. As a result, my test module assumed the testing system was in place.

# Testing Test::Most 0.21, Perl 5.008009, /home/chris/pit/rel/perl-5.8.9/bin/perl
# Exception::Class version is 1.29
# Test::Deep version is 0.106
# Test::Differences version is 0.5
# Test::Exception version is 0.29
# Test::Harness version is 3.21
# Test::Simple version is 0.94
# Test::Warn version is 0.21

Though 1: Test::Class::Most fails on Perl 5.010001 -- but only on Linux. Not on FreeBSD, OS X or Solaris. I've already emailed the testers and hopefully someone can track down what's going on. I don't want to say "bug in Perl", but this is not platform-specific code, so it looks suspicious.

Thought 2: Can anyone please explain to me why anyone would want to buy a whyPad?

Thought 3: What does the following print and why? Results are the same for 5.10.1 and 5.8.9, in case you're wondering. Try and figure out the output before you run the code. I now know why it does this, but I was confused by the behavior.

After uploading Test::Class::Most, I kept thinking and thinking about the fact that you automatically get strict and warnings with it. I started to think about my annoyance with test suites in general and am now thinking about doing this with Test::Most. I proposed this to Perl-QA and received three positive responses (two offlist) and no negative. It won't import "features" of 5.10, but instead of this:

use strict;
use warnings;
use Test::Most tests => 34;

You can just write:

use Test::Most tests => 34;

... and it's the same thing. I can't recall the last time I've seen a test suite using modern tools and not using strict and warnings, so I think this is a win. chromatic's Modern::Perl is a tiny bit of code but the underlying idea is very important and it's a pattern I'd like to see more of.

About Ovid

Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you.
And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/