Older blog entries for chromatic (starting at number 227)

A Simply Serializing Factory:

I've found a nice pattern of using objects and classes for configuration information, but I don't want to go all of the way to Class::DBI with them because I like the simplicity of working with flat files.

The third or fourth time I found myself writing a factory to load and to save objects to and from YAML files, I resolved someday to write a module that does that and refactor the other attempts to use the module. Today, instead of working on one of two books, cleaning my house, or doing either of the programming projects that crossed my mind, I wrote Class::StorageFactory (and Class::StorageFactory::YAML, which is what I wanted).

If it seems useful and no one objects, I'll upload it to the CPAN in a couple of days. I looked for prior art but didn't find much in a few minutes.

I have new versions of SUPER and Test::MockObject to upload soon too.

12 Mar 2005 (updated 12 Mar 2005 at 00:56 UTC) »

People to Ignore in Software Development:

When discussing feature requests, development practices, and design issues of any public software project, reasonable people will disagree. That's fine. It's normal. It happens. It can be healthy if you deal with them appropriately.

However, sometimes some people draw lines in the sand around one position -- whatever the position -- and say something like:

Which is exactly why open source software will never replace commercial software or Microsoft.

Flip the bozo bit. Flip them all. Don't argue. Don't read any further. Above all, don't take the person seriously.

There might be merit to the argument, but you're not going to hear it from that source.

(You probably should ignore the people who continue the argument from that point too, but I don't like to flip the entire double-word of bozo bits immediately.)

Cool Testing Stuff:

Good things have happened in the test world in the past couple of weeks.

Andy has checked in a couple of patches for Test::Harness::Straps to collect diagnostic information. This means that writing a custom harness to print out (and colorize) only failed tests is easy.

Last week, Autrijus and I discussed porting Test::Builder to Perl 6 for Pugs. Schwern and I sketched out some refactorings of Test::Builder a couple of years ago and promptly didn't do it. I resurrected the idea (if not the notes, if that hard drive even exists anywhere accessible anymore) and came up with some ideas last night. Today, the idea came up again on the Perl QA mailing list for Perl 5 and it looks like we can go ahead with it.

Most of the ideas are merely internal cleanups, but they'll make it possible to do some cooler things that people have asked for in cleaner ways.

I've spent some of my off-hours documenting existing and inventing some new testing tricks. I'll explain more about this soon.

Finally, I'm fiddling with the OpenGL bindings to Parrot again. What? You didn't know they existed? Oh, they do. I'll show them off soon.

Dear Ranters:

Hey, avrietta, remember when you said:

Lastly (didn't I just say that?), ORA, again, sucks. I'm saying it again, and I can't believe it. Will they publish ANYTHING?

...and we all laughed?

I was thinking. If you want to know my editorial standards and rationales, you can kindly ask me. Contrariwise, you could fume and piddle about what the horrors and terrors of storing recipes in an non-MVCC relational database until your heart explodes. Either way.

F/OSS Testing:

zhaoway claims that the open source way to test is to make your users do it.

If I thought I could find users who ran tests completely, perfectly, and quickly, report errors accurately, never felt bored, never skipped steps, and who could perform tests in real time as I develop, I'd consider the idea.

In other words, it sounds like yet another excuse for software quality by wishful thinking. Sorry.

Dark, Dark Corners of Perl:

After tonight's PDX.pm meeting, in the bar, I bet Ovid that I could reimplement his Sub::Signatures by replacing the source filter with subroutine attributes. (Wisely, he believed me.)

A few minutes later, he asked idly if I knew of any reason why Perl couldn't call methods with spaces in their names. Offhand, I couldn't think of anything besides the tokenizer that prevents it, believing that gv.c cares more about null-byte termination than the <code>\w+</code>ness of identifiers. If you can bypass that for symbol installation and method invocation (and that's trivial), you've done it.

I hate to give away the punchline before both frightening people who didn't know such things were possible and stumping a few of the people who know it's possible but don't see the answer right away, so here are my tests. They all pass on my machine and I expect them to run just fine on at least Perl 5.8.0 and newer. (Perl 5.6 probably works, but I expect it to fail on more complicated things.) You don't need any non-core modules besides Attribute::Handlers, and I believe that's in the core in the 5.8.x family.

#!/usr/bin/perl -w

BEGIN { chdir 't' if -d 't'; use lib '../lib', '../blib/lib'; }

use strict; use Test::More tests => 4;

my $module = 'Attribute::Scary'; use_ok( $module ) or exit;

package Hello;

use strict; use warnings;

use Attribute::Scary;

sub new { my ($class, $name) = @_; bless \$name, $class; }

sub name :Method { return $$self; }

sub greet :Method { return sprintf( "Hello, %s!\n", $self->name() ); }

package main;

my $hi = Hello->new( 'Bob' ); is( $hi->greet(), "Hello, Bob!\n", ':Method attribute should autoadd invocant shift' );

my $spacey_name = 'spacey 0'; my $spacey_greet = 'spacey 1';

is( $hi->$spacey_name(), 'Bob', '... also installing first method as "spacey 0"' ); is( $hi->$spacey_greet(), "Hello, Bob!\n", '... and second as "spacey 1"' );

There are two tricks in the implementation, one of which is an "eww, evil--and CLEVER!" trick and the other is something either you know about or you don't.

Quieter Test Output:

I never really understood the point of <code>prove</code>; I write my tests as normal Perl programs, launchable from the command line. <code>perl t/testname.t</code> did most of what I wanted to do.

With more than 24 tests in a file, though, I often promised myself to write or find someday a variant test harness that ignored successes and reported only failures or an all clear message.

I looked at the code of <code>prove</code> today to find where to add it, but again, it doesn't seem to do anything I really need and there was no way to add it. I moved on to Test::Harness::Straps. I don't know if anyone's ever actually used this module (and it's admittedly a bit of a mess inside, though the long-promised Test::Builder refactoring may make it easier to write), but it took 67 lines of code to do what I needed (and a little more) in a well-factored way.

I call it qtest:


use strict; use warnings;

use Test::Harness::Straps;

my $strap = Test::Harness::Straps->new();

for my $file (@ARGV) { next unless -f $file;

my %results = $strap->analyze_file( $file );

if ($results{passing}) { report( sprintf('All (%d) tests passed in %s', $results{seen}, $file)); } elsif ($results{skip_all}) { report( sprintf('All (%d) tests skipped in %s', $results{seen}, $file)); } else { report( find_failures( $file, \%results ) ); } }

sub report { my $message = shift; print "$message\n"; }

sub find_failures { my ($file, $results) = @_; my $report = create_header($file, @{$results}{qw( max seen ok )}); my $count = 0;

for my $test ( @{ $results->{details} } ) { $count++; next if $test->{ok}; $report .= create_test_result( $count, @{ $test }{qw( name reason ) } ); }

return $report; }

sub create_header { my ($file, $expected, $seen, $passed) = @_; my $failed = $seen - $passed; return sprintf "File '%s'\nExpected %d / Seen %d / Okay %d / Failed %d\n", @_, $failed; }

sub create_test_result { my ($number, $name, $reason) = @_; $name =~ s/^-\s*//; $reason ||= ''; $reason = " ($reason)" if $reason; return sprintf "\tTest #%d: %s%s\n", $number, $name, $reason; }

In practice, I may tweak the formatting somewhat. It might be nice to report skips and surprisingly-passing TODO tests, too. I also might want a flag to end after the first failure, to solve the problem of cascading failures rolling off of the screen. Still, this was a lot simpler than I thought and already makes my life easier.

Excuses Not To Hack:

Having started Write Your Life the first week of October, I spent a month writing my own versions of the assignments. (No, you probably won't ever see them.) That was enlightening and habit-forming.

Unfortunately, the weird not-on-a-month-boundary timing caused me to miss the start of National Novel Writing Month by at least a week. That's too bad; if I'd known and could have planned for it, I would have participated. 50,000 words is intimidating, but a thousand a day is doable. (It would have been wrong to set aside my first ever One Month Project because I know I'd probably never go back to it.)

The discipline of writing at a set time every day for a month was valuable though. Instead of writing about myself (it drove me crazy to see personal pronouns in so many sentences), I've written over 7000 words of what may just become a novel in the past week.

You might see that online in the near future.

In the meantime, feeling guilty about not hacking (though not guilty enough to figure out why the JIT fixes for Parrot on AIX have broken it on Linux PPC), I've released Test::MockObject 0.15. This version allows you to prevent logging certain method calls; that'll make many lives easier.

Too Many Choices:

If "too many choices" of applications in the typical Linux distribution is really keeping people on Windows, why aren't there more people starving to death in the cereal aisles of grocery stores?

A Strange Mix of Writer and Programmer:

Though most people know me for my programming, I also consider myself a writer. My day job combines both fields very nicely, but it doesn't leave a lot of room for non-technical writing.

The other night, I had a conversation spanning several subjects, including the deaths of my grandparents, the fear that I hadn't heard their full life stories, and my desire to make the world a better place, in part by helping non-programmers learn just enough programming to solve smaller problems. I felt guilty explaining the latter idea, as it seems self-indulgent in some ways and trivial in others.

As often happens, several divergent ideas ganged up on me and presented a different solution. I do want to make the world a better place, but maybe programming isn't the right place at the moment. Instead, I'm looking for a wider audience.

I've spent the past week putting the foundations of Write Your Life in place. The idea is to encourage people who want to improve their writing to practice writing every day for a month by providing one topic per day.

It uses an autobiographical theme for two reasons. First, it's important to write what you know. Though it's still difficult to start writing a thousand words about your home, once you cross that barrier, it can be more difficult to stop. (I blew past the word limit and didn't even start on the upper story of my house.)

Second, I believe everyone has a story to tell. I really regret not learning more from my grandparents while I had the chance, though my friend did point out that they may have told me as much as they felt comfortable sharing. There's a wealth of wisdom and experience in the previous generations that we may lose unless we encourage people to write and speak.

I hope my project will convince a few people to publish their own lives. Please feel free to pass the link to your friends.

(I'll try to add an RSS or Atom feed for the assignments today.)

218 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!