Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jplindstrom (594)

jplindstrom
  (email not shown publicly)

Journal of jplindstrom (594)

Friday August 21, 2009
09:26 AM

A Test::Class idiom

Test::Class is very nice, but I realize I've started to use it in a peculiar way that I think is an indication of a missing feature.

Let's say there's a class with quite a few different tests and I'm currently TDD-ing this single method.

sub ion_favourites : Test(no_plan) {
    # ...
}

It's quite annoying to run the whole test class, because all of the test methods are run, not just the one I'm working on. The output of my test is easily lost in the sea of output, and running all of the tests increase the turnaround time.

To only run this test, I temporarily rename it and put an exit at the end:

sub a__ion_favourites : Test(no_plan) {
    # ...
    exit(1);
}

The naming ordering is actually mentioned in the manual, but seems to be more geared to running sanity checks first.

The full test suite fails becuase of the exit status, but I can easily see whether the stuff I'm working on passes and that's what I care about during TDD.

Smells a bit hacky, but it works. So, does anyone else do this?

Friday February 06, 2009
10:20 AM

The Emacs Perl debugger++

I had to use the debugger today and it struck me how convenient this was with the latest PerlySense.

The Perl part of Emacs' Grand Unified Debugger (gud) is brilliant. Not as brilliant as the gdb integration I understand, but still very, very good.

The only downsides are similar to how Flymake for Perl works out of the box (which dir to run from, a proper @INC, etc). That, and the way the command line is determined is somewhat clunky.

In the latest version of PerlySense most of these issues are fixed and the launch of perldb is streamlined. Hit C-o r d for Run File in Debugger to get a default command line suitable for the type of file you're editing.

See PerlySense: Debugging Code for more details.

Note: if you're upgrading, you need to regenerate your

.PerlySense/project.yml

file so it contains debugger config, like this:

debug_file:
  -
    command: "perl -d ${INC} \"${SOURCE_FILE}\""
    moniker: Test
    rex: \.t$
    debug_from: source_root_directory

The easiest way to upgrade your config file is:

perly_sense create_project

This will back up your old config file and create a new one (merge any changes into the new config file manually).

If you're upgrading, you might also want to check out the Changes file for recently added features (especially the note for 0.0174).

Sunday December 21, 2008
04:38 PM

Finding stuff

If you work with even a moderately large code base, it's very important to have a way to easily find stuff in it. Otherwise you'll inevitably break things when you change something and are unaware of all the places that thing is used.

By trying to keep things well factored you can try to keep related things in one place...

...but there are many ways to slice the abstractions, for example across the domain (Person, MoneyAccount) and technical responsibilities (MVC layers, tests).

If you use a statically typed language the IDE can keep track of things for you...

...but there are usually lots of ways to represent something outside of the core programming language; SQL files, XML data files, test data, config files.

grep-find and ack

For a long time, I just used the Emacs grep-find command and ack. In Emacs, the current working directory is the cwd of the current buffer, so I used to switch to the *svn-status* buffer which has the project root directory as cwd, and run grep-find from there.

With the command history, it's easy to reuse and adapt a command line useful for grep-mode to understand (file name and line number):

ack --nogroup --nocolor -- SEARCH_TERM

Add --perl, --xml, --yaml or --all according to taste.

Navigating to matching lines is very convenient. Either hit Return in the *grep* buffer, or C-c C-c in a source file to jump to the next match.

This is extremely powerful when combined with keyboard macros to make complex project-wide edits.

(Clever trick: record the macro so that the last thing it does is to position point at the next place to edit. That way you can eyeball the text to make sure it's safe to run the macro again.)

So this is useful, but still a few too many key strokes to get to the actual search.

project-root

The project-root package is one way to define the concept of a project in Emacs. This piece of .emacs config defines a sensible Perl setup:

(require 'project-root)
(setq project-roots
      '(("Generic Perl Project"
         :root-contains-files ("t" "lib"))))

(global-set-key (kbd "C-c p g")       'project-root-grep)
(global-set-key (kbd "C-c p a")       'project-root-ack)
(global-set-key (kbd "C-c p C-x C-f") 'project-root-find-file)

With that you can use:

  • C-c p g or C-c p a to find stuff, similar to what I described above.

  • C-c p C-x C-f to open a file relative to the project root. This is especially useful for opening file names you copy from other shells, tests, error messages, etc.

project-root also provides the with-project-root macro for running any existing function programmatically, and the project-root-execute-extended-command defun. If you bind the last one to a key, you can use that as a prefix to run anything from the root directory.

Very handy.

PerlySense

Devel::PerlySense also has a concept of a project. Since the PerlySense backend is editor neutral, it doesn't use project-root. And since release 0.0170 there is support for Finding Code in the project using ack.

In addition to the general ability to ack through the code base, it also provides a few useful Perl specific searches.

Find with Ack

[ Screenshot ]

C-o f a -- Ack through the source and display the hits in a *grep* buffer.

Before running ack you'll get to edit the command line with a sensible default chosen from:

  • the active region

  • the word at point (with the -w whole word option)

Remember that earlier searches are available in the command history, just like with grep.

Tip: You can jump from a source file to the next hit with C-c C-c (type C-h m in the *grep* buffer to see the mode documentation).

Tip: if you need to find something else while browsing the *grep* buffer, you can easily rename the current *grep* buffer to something else using M-x rename-buffer.

Find sub declarations

[ Screenshot ]

C-o f s -- Ack the Project for sub declarations of the method, or word at point.

I.e. look for lines with sub NAME.

The point can be either on the method ($self->st|ore), or on the object ($us|er_agent->get()).

Find method calls

[ Screenshot ]

C-o f c -- Ack the Project for method calls to the method, or word at point.

I.e. look for lines with -ENAME.

Elisp

For elisp programmers, there's the ps/with-project-dir macro similar to with-project-root.

Sunday November 23, 2008
07:33 PM

PerlySense does Moose

I just uploaded PerlySense 0.0165 to PAUSE.

The new feature is a syntax plugin for Moose. It understands "has" (the basics), "extends", and "with".

So now I can finally visualize and navigate inheritance hierarchies in the code base at work again. That's been sorely missing for a while. Quite annoying once you've gotten used to it.

The plugin isn't a separate distribution yet. I couldn't be bothered to go through the chore of setting up a new one, so I just made it part of core PerlySense and made a new release. That will change of course, but not today.

The plugin system is in beta anyway, there are a few things that need cleaning up before other people can write plugins and expect the interface to not change. But if there is interest, nagging will probably hasten that process :)

Thursday November 20, 2008
06:50 PM

PerlySense does Git

I just uploaded PerlySense 0.0160 to PAUSE after fixing the release script to not truncate trailing zeroes.

* Git support (Magit) for the Version Control commands. This means you can use the usual "Go To VCS Status" command for all (um, both) vcs backends.

* Fixed bug: Coverage visualization always instantiates an empty "covered" directory, even if there isn't any coverage to begin with.

* Fixed bug: Nothing happens after choosing between > 1 base classes in "Go to Base class" (response key named "class-description" instead of "class_description").

I chose Magit after experimenting with a few Emacs Git modules. Magit seems to support the full Git feature set well enough and still actually work in Emacs 22.

I'm not quite happy though, I also really need visual diffing a la ediff-buffers, and preferably something like the standard vc blame feature, which is truly awesome (the usefulness of the Version Control integration in Emacs is impressive enough to warrant a screencast some day).

vc with the git backend probably does this, but I'm not sure, and I think it might not work out of the box with Emacs 22.

If it's not supported at all, at least the ediff thing should be fairly easy to hack together.

Tuesday September 09, 2008
07:24 PM

You can get there from here - but it's the long way around

Last week I spent some time refactoring the code base at work, moving configuration into the domain layer. Lots of editing, lots of moving around the code base. And waaay too much time spent chasing down specific files when moving things from DBIC/Mapper/Episode.pm to Domain/Episode.pm, adding tests to domain/episode-general.t. You get the picture.

So that's a pattern. A 2d matrix of things in the code base. One dimension is the entities in the domain: Book, Person, Account. The other is the technical aspects they need to deal with: database tables, business logic, web request dispatch, templates, tests.

A project with an MVC structure usually ends up with the technical dimension (Model, View, Controller) at the top level in the directory tree, and then each of the M, V, C contain all of the the "things". There isn't always a 1:1:1 match between all of them, but often enough there is.

The project at work has even more technical aspects of most domain entities, because we support multiple input formats (and soon multiple output formats). Add tests to that and you have a big pile of files.

So how annoying was it to navigate up and down this directory tree all day long? A lot annoying is what it was.

But at least it's a structured pile of files. Certain files are next to each other, in the same directory. Other files have the same name, but are in different directories.

I ended up taking shortcuts, like switching to a file in the neighbourhood of where I was going and opening the file from there, so the cwd would be the correct one. But still very annoying.

So over the weekend I wrote File::Corresponding , to help me find related files. Basically an aid to navigate sideways in the directory tree, solving the problem described above.

A config file and a command line script you can shell out to from your editor of choise. And if your editor of choise is Emacs, I just made a release of Devel::PerlySense which incorporates this.

Since I just implemented the Emacs thing I haven't actually tried it out much yet, so it'll be interesting to see if it's actually useful :) If you decide to give it a spin, feel free to share your experience in the comments.

Monday September 01, 2008
10:55 AM

Copy-paste from X11 windows to Putty hangs (sometimes)

Sometimes (but not always) when I copy things from my Emacs X11 window and try to paste it into Putty, it hangs Putty. That's pretty annoying.

I can generally get out of the freeze by pressing Ctrl-uh-some-key-in-the-top-left-corner, but from then on paste doesn't work anymore.

According to the Putty web site, that's only semi-buggy behaviour. Well, I don't know.

But from the explanation on that page I thought I could write something that would grab what's in the clipboard and put it back, working around the problem.

Of course, that's general enough to have been done before, so now I use ClipboardFusion to scrub the clipboard contents, and it seems to work okay.

Actually, researching this blog post and re-reading the semi-bug web page again, I may have discovered another way. Isn't it ironic... *)

It also seems this may not be a problem if I start Emacs in one Putty terminal and don't use that terminal again for anything. That wouldn't be a problem for me, I have five other terminals open anyway, and I could always minimize the Emacs terminal to the tray. I might try that and see how that works out.

*) It is. If you subscribe to the Alanis Morissette school of irony.

Friday August 22, 2008
03:08 PM

Indentation in Python considered, well... not very important

Can we please, please stop talking about how Python's forced indentation makes code readable? The "forced" part is not an issue. At all.

Ever since structured programming was invented, proper indentation is the first basic thing that makes code more readable. It's so basic that people don't even seem to think about it.

The idea that Python programmers wouldn't indent their source code properly if not for the language rules is ridiculous! Same as all other even remotely competent programmers.

Python's indentation rules don't make Python code more readable, because proper indentation is the norm in any language. And if you have to be forced to indent your code, no language can save you from yourself.

All well written programs are indented properly, but not all properly indented programs are well written.

Monday August 11, 2008
10:08 AM

YAPC Schedule Clashes

I'm preparing for YAPC. Sorting out travel arrangements, printing maps, getting stuff on the phone for offline browsing.

And I'm looking at the schedule. Looks good, interesting stuff.

But a few clashes with must-attend talks side by side. Here are the toughest match ups:

Everything but the secret sauce
vs
Effective Code Coverage

A bunch of pragmatic tips on how to get stuff done, vs code coverage. Tough one. I may already have seen the code coverage stuff, but I'd also like to see if Devel::CoverX::Covered is mentioned ( *nudge, nudge* :)

Putting Types To Work In Perl 6
vs
Elegant^Elegant: Web application metaprogramming with Reaction
vs
Profiling Modules - A Survey

All of these sound interesting. Basic Perl 6 OO is old news (Damian Conway sold me on that in Munchen six years ago), but I'd like to know more about type system (it may have a Moose connection and hence be usable today). Overshadowing that is the fact that I have been waiting to see what Reaction looks like for a long time now, and I think this is the first public appearance.

Nothing Can Possibly Go Wrong... Again
vs
Building Catalyst apps on the Amazon Web Service Platform

I've never done anything with the EC2 cloudy stuff so I'd like to hear about that. But Adam Kennedy is apparently an energetic speaker with an interesting topic. Damnit!

DOM manipulation by Gainer/Wiimote over
vs
Making (large) legacy systems beautiful

Fun and games against the harsh realities of everyday software maintenance. I may sit down in the back of the room of either talk and discreetly task switch for a bit.

Unicode Best Practices
vs
Modifying databases - changing the schema in a controlled way

Two difficult, utterly pragmatic topics pitted against each other. How is that fair? We have solved both with various degrees of success at work and it would be interesting to see how others did it.

Advantage: schema changes, because it's more open ended.

Describing classes with Ernst
vs
Strawberry Perl - Achieving Win32 Platform Equality

Taking Moose to the next level sounds very interesting, the more so when Ernst sounds like what we could use at work to tie together our domain layer with multiple input and output formats.

And Perl on Windows is interesting since I use that to some extent. Which ironically means I may already be in the loop and op top of it.

Advantage: Ernst.

Ye Compleat History of Ye Perle Mongers of Olde London Towne
vs
10 modules I haven't yet talked about
vs
CPAN6 Under Construction

London.pm history, probably interesting, but Leon is a good and entertaining speaker (conference tip: a good speaker + boring topic beats a bad speaker + interesting topic).

(hmmm, I just realized I implied Dave Cross is a bad speaker there. He isn't.)

But on the other hand, CPAN6 is interesting, and Mark Overmeer is also a good speaker. On the third hand, I think I saw this talk last year.

All in all, a nice lineup of talks. I especially like that the Lightning Talks go unchallenged.

Monday July 07, 2008
07:21 PM

Moose lessons

Things I've learned by Moosifying classes over the past few days. In no particular order.

Moose is cool.

But it's too easy to go overboard and try to use all of it at once.

Type constraints are very useful, if nothing else because of the documentation value, e.g.

has 'rex_skip_source_file' => (
    is => 'rw',
    isa => 'ArrayRef[RegexpRef]',
    default => sub { [] },
);
 
has is_publication_outlet => (is => "rw", isa => "Int");

The default of ''is => "ro"'' seems badly chosen. Having ''is => "rw"'' everywhere seriously adds clutter. From what I gather it's from Perl 6, and the little Perl 6 code I've seen leaves the same impression. I guess the argument is "public accessors are bad so it should hurt to use them". But that argument doesn't hold water, because this is also how you declare private attributes. So either way, most of your attribute declarations will have "rw". Not very optimized for the common case.

Type constraints are also useful because you can do certain things declaratively instead of imperatively. Data driven code is always a win; less code ==> less bugs, so refactor it into the framework or language.

The Perl internal types are documented, but not in an obvious place.

Many attributes in a compact layout become visually disturbing. Aligning things here is a must for readability. Apparently Vim has some kind of magic I'm envious of. A very simple split-on-non-string-whitespace-and-render-in-columns would work here.

Bool seems weird and doesn't play well with Perl's idea of true / false.

The constraints above disallow undef, so if you want a value to be either a string or undef, the syntax is:

isa => "Maybe[Str]"

To override the default for an attribute in a subclass without having to retype the entire declaration you prepend a plus:

has "+is_persistable" => (default => 1);

This visual distinction feels very right and makes it obvious it is overridden.

Roles are nice but the keywod "with MyRole" isn't the same as Perl 6' "does MyRole". I'm not sure which is better for guiding the thought on how roles should be named, but they will have different outcomes if you care about naming at all.

The "lazy => 1" property on attributes is very cool and all you need to decompose bulky initialization code into a roll-your-own IoC setup for an object.

Moose is clearly the new default way of Perl OOP.