jplindstrom's Journal http://use.perl.org/~jplindstrom/journal/ jplindstrom's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:06:37+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 jplindstrom's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~jplindstrom/journal/ A Test::Class idiom http://use.perl.org/~jplindstrom/journal/39503?from=rss <a href="http://search.cpan.org/dist/Test-Class/lib/Test/Class.pm">Test::Class</a> 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. <p>Let's say there's a class with quite a few different tests and I'm currently TDD-ing this single method.</p><blockquote><div><p> <tt>sub ion_favourites : Test(no_plan) {<br>&nbsp; &nbsp; #<nobr> <wbr></nobr>...<br>}</tt></p></div> </blockquote><p>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. </p><p>To only run this test, I temporarily rename it and put an exit at the end:</p><blockquote><div><p> <tt>sub a__ion_favourites : Test(no_plan) {<br>&nbsp; &nbsp; #<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; exit(1);<br>}</tt></p></div> </blockquote><p>The naming ordering is actually <a href="http://search.cpan.org/dist/Test-Class/lib/Test/Class.pm#RUNNING_ORDER_OF_METHODS">mentioned in the manual</a>, but seems to be more geared to running sanity checks first. </p><p>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. </p><p>Smells a bit hacky, but it works. So, does anyone else do this?</p> jplindstrom 2009-08-21T14:26:53+00:00 journal The Emacs Perl debugger++ http://use.perl.org/~jplindstrom/journal/38415?from=rss <p>I had to use the debugger today and it struck me how convenient this was with the latest PerlySense.</p><p>The Perl part of Emacs' Grand Unified Debugger (gud) is brilliant. Not as brilliant as the <a href="http://emacs-fu.blogspot.com/2009/02/fancy-debugging-with-gdb.html">gdb integration</a> I understand, but still very, very good.</p><p>The only downsides are similar to how <a href="http://cpansearch.perl.org/src/JOHANL/Devel-PerlySense-0.0178/doc/flymake.html">Flymake</a> 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.</p><p>In the latest version of PerlySense most of these issues are fixed and the launch of <em>perldb</em> is streamlined. Hit <strong>C-o r d</strong> for <em>Run File in Debugger</em> to get a default command line suitable for the type of file you're editing.</p><p>See <a href="http://search.cpan.org/~johanl/Devel-PerlySense-0.0178/lib/Devel/PerlySense.pm#Debugging_Code">PerlySense: Debugging Code</a> for more details.</p><p> <em>Note</em>: if you're upgrading, you need to regenerate your</p><blockquote><div><p><nobr> <wbr></nobr><tt>.PerlySense/project.yml</tt></p></div> </blockquote><p> file so it contains debugger config, like this:</p><blockquote><div><p> <tt>debug_file:<br>&nbsp; -<br>&nbsp; &nbsp; command: "perl -d ${INC} \"${SOURCE_FILE}\""<br>&nbsp; &nbsp; moniker: Test<br>&nbsp; &nbsp; rex: \.t$<br>&nbsp; &nbsp; debug_from: source_root_directory</tt></p></div> </blockquote><p>The easiest way to upgrade your config file is:</p><blockquote><div><p> <tt>perly_sense create_project</tt></p></div> </blockquote><p>This will back up your old config file and create a new one (merge any changes into the new config file manually).</p><p>If you're upgrading, you might also want to check out the <a href="http://cpansearch.perl.org/src/JOHANL/Devel-PerlySense-0.0178/Changes">Changes</a> file for recently added features (especially the note for 0.0174).</p> jplindstrom 2009-02-06T15:20:28+00:00 journal Finding stuff http://use.perl.org/~jplindstrom/journal/38126?from=rss <p>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.</p><p>By trying to keep things well factored you can try to keep related things in one place...</p><p>...but there are many ways to slice the abstractions, for example across the domain (Person, MoneyAccount) and technical responsibilities (MVC layers, tests).</p><p>If you use a statically typed language the IDE can keep track of things for you...</p><p>...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.</p><p> <strong>grep-find and ack</strong> </p><p>For a long time, I just used the Emacs <strong>grep-find</strong> command and <a href="http://search.cpan.org/dist/ack/ack">ack</a>. In Emacs, the current working directory is the cwd of the current buffer, so I used to switch to the <em>*svn-status*</em> buffer which has the project root directory as <em>cwd</em>, and run <strong>grep-find</strong> from there.</p><p>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):</p><blockquote><div><p> <tt>ack --nogroup --nocolor -- SEARCH_TERM</tt></p></div> </blockquote><p>Add --perl, --xml, --yaml or --all according to taste.</p><p>Navigating to matching lines is very convenient. Either hit Return in the <em>*grep</em>* buffer, or <strong>C-c C-c</strong> in a source file to jump to the next match.</p><p>This is extremely powerful when combined with keyboard macros to make complex project-wide edits.</p><p>(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.)</p><p>So this is useful, but still a few too many key strokes to get to the actual search.</p><p> <strong>project-root</strong> </p><p>The <a href="http://www.shellarchive.co.uk/content/emacs.html">project-root</a> package is one way to define the concept of a <em>project</em> in Emacs. This piece of<nobr> <wbr></nobr><em>.emacs</em> config defines a sensible Perl setup:</p><blockquote><div><p> <tt>(require 'project-root)<br>(setq project-roots<br>&nbsp; &nbsp; &nbsp; '(("Generic Perl Project"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:root-contains-files ("t" "lib"))))<br> <br>(global-set-key (kbd "C-c p g")&nbsp; &nbsp; &nbsp; &nbsp;'project-root-grep)<br>(global-set-key (kbd "C-c p a")&nbsp; &nbsp; &nbsp; &nbsp;'project-root-ack)<br>(global-set-key (kbd "C-c p C-x C-f") 'project-root-find-file)</tt></p></div> </blockquote><p>With that you can use:</p><ul> <li> <p> <strong>C-c p g</strong> or <strong>C-c p a</strong> to find stuff, similar to what I described above.</p></li><li> <p> <strong>C-c p C-x C-f</strong> 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.</p></li></ul><p> <em>project-root</em> also provides the <em>with-project-root</em> macro for running any existing function programmatically, and the <em>project-root-execute-extended-command</em> defun. If you bind the last one to a key, you can use that as a prefix to run anything from the root directory.</p><p>Very handy.</p><p> <strong>PerlySense</strong> </p><p> <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm">Devel::PerlySense</a> also has a concept of a <em>project</em>. Since the PerlySense backend is editor neutral, it doesn't use <em>project-root</em>. And since release 0.0170 there is support for <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm#Finding_Code">Finding Code</a> in the project using ack.</p><p>In addition to the general ability to <em>ack</em> through the code base, it also provides a few useful Perl specific searches.</p><p> <strong> <em>Find with Ack</em> </strong> </p><p>[ <a href="http://search.cpan.org/src/JOHANL/Devel-PerlySense-0.0173/doc/find_with_ack.html">Screenshot</a> ]</p><p> <strong>C-o f a</strong> -- Ack through the source and display the hits in a <em>*grep*</em> buffer.</p><p>Before running ack you'll get to edit the command line with a sensible default chosen from:</p><ul> <li> <p>the active region</p></li><li> <p>the word at point (with the <em>-w</em> whole word option)</p></li></ul><p>Remember that earlier searches are available in the command history, just like with grep.</p><p> <em>Tip:</em> You can jump from a source file to the next hit with <strong>C-c C-c</strong> (type <strong>C-h m</strong> in the <em>*grep*</em> buffer to see the mode documentation).</p><p> <em>Tip:</em> if you need to find something else while browsing the <em>*grep*</em> buffer, you can easily rename the current <em>*grep*</em> buffer to something else using <em>M-x rename-buffer</em>.</p><p> <strong> <em>Find sub declarations</em> </strong> </p><p>[ <a href="http://search.cpan.org/src/JOHANL/Devel-PerlySense-0.0173/doc/find_sub_declaration.html">Screenshot</a> ]</p><p> <strong>C-o f s</strong> -- Ack the Project for <em>sub declarations</em> of the method, or word at point.</p><p>I.e. look for lines with <em>sub NAME</em>.</p><p>The point can be either on the method (<em>$self-&gt;st|ore</em>), or on the object (<em>$us|er_agent-&gt;get()</em>).</p><p> <strong> <em>Find method calls</em> </strong> </p><p>[ <a href="http://search.cpan.org/src/JOHANL/Devel-PerlySense-0.0173/doc/find_method_calls.html">Screenshot</a> ]</p><p> <strong>C-o f c</strong> -- Ack the Project for <em>method calls</em> to the method, or word at point.</p><p>I.e. look for lines with <em>-ENAME</em>.</p><p> <strong> <em>Elisp</em> </strong> </p><p>For <em>elisp</em> programmers, there's the <em>ps/with-project-dir</em> macro similar to <em>with-project-root</em>.</p> jplindstrom 2008-12-21T21:38:54+00:00 journal PerlySense does Moose http://use.perl.org/~jplindstrom/journal/37928?from=rss <p>I just uploaded <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm#DESCRIPTION">PerlySense</a> 0.0165 to PAUSE.</p><p>The new feature is a syntax plugin for Moose. It understands "has" (the basics), "extends", and "with".</p><p>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.</p><p>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.</p><p>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<nobr> <wbr></nobr>:)</p> jplindstrom 2008-11-24T00:33:17+00:00 journal PerlySense does Git http://use.perl.org/~jplindstrom/journal/37915?from=rss <p>I just uploaded <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm#DESCRIPTION">PerlySense</a> 0.0160 to PAUSE after fixing the release script to not truncate trailing zeroes.</p><p>* 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.</p><p><small>* Fixed bug: Coverage visualization always instantiates an empty "covered" directory, even if there isn't any coverage to begin with.</small></p><p><small>* Fixed bug: Nothing happens after choosing between &gt; 1 base classes in "Go to Base class" (response key named "class-description" instead of "class_description").<br></small></p><p>I chose <a href="http://zagadka.vm.bytemark.co.uk/magit/">Magit</a> 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.</p><p>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).</p><p>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.</p><p>If it's not supported at all, at least the ediff thing should be fairly easy to hack together.</p> jplindstrom 2008-11-20T23:50:01+00:00 journal You can get there from here - but it's the long way around http://use.perl.org/~jplindstrom/journal/37396?from=rss <p>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 <tt>DBIC/Mapper/Episode.pm</tt> to <tt>Domain/Episode.pm,</tt> adding tests to <tt>domain/episode-general.t</tt>. You get the picture.</p><p>So that's a pattern. A 2d matrix of things in the code base. One dimension is the entities in the domain: <tt>Book</tt>, <tt>Person</tt>, <tt>Account</tt>. The other is the technical aspects they need to deal with: <i>database tables</i>, <i>business logic</i>, <i>web request dispatch</i>, <i>templates</i>, <i>tests</i>.</p><p>A project with an MVC structure usually ends up with the technical dimension (<i>Model</i>, <i>View</i>, <i>Controller</i>) at the top level in the directory tree, and then each of the <i>M</i>, <i>V</i>, <i>C</i> contain all of the the "things". There isn't always a 1:1:1 match between all of them, but often enough there is.</p><p>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.</p><p>So how annoying was it to navigate up and down this directory tree all day long? A lot annoying is what it was.</p><p>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.</p><p>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.</p><p>So over the weekend I wrote <tt> <a href="http://search.cpan.org/dist/File-Corresponding/lib/File/Corresponding.pm">File::Corresponding</a> </tt>, to help me find related files. Basically an aid to navigate sideways in the directory tree, solving the problem described above.</p><p>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 <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm">Devel::PerlySense</a> which incorporates this.</p><p>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<nobr> <wbr></nobr>:) If you decide to give it a spin, feel free to share your experience in the comments.</p> jplindstrom 2008-09-10T00:24:15+00:00 journal Copy-paste from X11 windows to Putty hangs (sometimes) http://use.perl.org/~jplindstrom/journal/37321?from=rss <p>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.</p><p>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.</p><p>According to the Putty web site, that's only <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/rdesktop-paste-hang.html">semi-buggy behaviour</a>. Well, I don't know.</p><p>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.</p><p>Of course, that's general enough to have been done before, so now I use <a href="http://www.binaryfortress.com/clipboardfusion/">ClipboardFusion</a> to scrub the clipboard contents, and it seems to work okay.</p><p>Actually, researching this blog post and re-reading the semi-bug web page again, I may have discovered another way. Isn't it ironic... *)</p><p>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.</p><p>*) It is. If you subscribe to the Alanis Morissette school of irony.</p> jplindstrom 2008-09-01T15:55:45+00:00 journal Indentation in Python considered, well... not very important http://use.perl.org/~jplindstrom/journal/37256?from=rss <p>Can we please, <i>please</i> stop <a href="http://www.perlmonks.org/?node_id=706271">talking</a> about how Python's <a href="http://www.reddit.com/comments/6ofa0/why_i_hate_python/">forced</a> <a href="http://developers.slashdot.org/comments.pl?sid=650931&amp;cid=24671033">indentation</a> makes code readable? The "forced" part is not an issue. At all.</p><p>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.</p><p>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.</p><p>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.</p><p>All well written programs are indented properly, but not all properly indented programs are well written.</p> jplindstrom 2008-08-22T20:08:04+00:00 journal YAPC Schedule Clashes http://use.perl.org/~jplindstrom/journal/37152?from=rss I'm preparing for YAPC. Sorting out travel arrangements, printing maps, getting stuff on the phone for offline browsing. <p> And I'm looking at the schedule. Looks good, interesting stuff. </p><p> But a few clashes with must-attend talks side by side. Here are the toughest match ups: </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1321">Everything but the secret sauce</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1392">Effective Code Coverage</a> </b> <br> 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 <a href="http://search.cpan.org/dist/Devel-CoverX-Covered/lib/Devel/CoverX/Covered.pm">Devel::CoverX::Covered</a> is mentioned ( *nudge, nudge*<nobr> <wbr></nobr>:) </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1384">Putting Types To Work In Perl 6</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1379">Elegant^Elegant: Web application metaprogramming with Reaction</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1390">Profiling Modules - A Survey</a> </b> <br> 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. </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1402">Nothing Can Possibly Go Wrong... Again</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1091">Building Catalyst apps on the Amazon Web Service Platform</a> </b> <br> 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! </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1355">DOM manipulation by Gainer/Wiimote over</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1309">Making (large) legacy systems beautiful</a> </b> <br> 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. </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1313">Unicode Best Practices</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1316">Modifying databases - changing the schema in a controlled way</a> </b> <br> 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. </p><p> Advantage: schema changes, because it's more open ended. </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1345">Describing classes with Ernst</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1401">Strawberry Perl - Achieving Win32 Platform Equality</a> </b> <br> 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. </p><p> 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. </p><p> Advantage: Ernst. </p><p> <b> <a href="http://www.yapceurope2008.org/ye2008/talk/1176">Ye Compleat History of Ye Perle Mongers of Olde London Towne</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1363">10 modules I haven't yet talked about</a> <br>vs<br> <a href="http://www.yapceurope2008.org/ye2008/talk/1354">CPAN6 Under Construction</a> </b> <br> 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). </p><p> (hmmm, I just realized I implied Dave Cross is a bad speaker there. He isn't.) </p><p> 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. </p><p> All in all, a nice lineup of talks. I especially like that the Lightning Talks go unchallenged.</p> jplindstrom 2008-08-11T15:08:59+00:00 journal Moose lessons http://use.perl.org/~jplindstrom/journal/36867?from=rss <p>Things I've learned by Moosifying classes over the past few days. In no particular order.</p><p>Moose is cool.</p><p>But it's too easy to go overboard and try to use all of it at once.</p><p>Type constraints are very useful, if nothing else because of the documentation value, e.g.</p><blockquote><div><p> <tt>has 'rex_skip_source_file' =&gt; (<br>&nbsp; &nbsp; is =&gt; 'rw',<br>&nbsp; &nbsp; isa =&gt; 'ArrayRef[RegexpRef]',<br>&nbsp; &nbsp; default =&gt; sub { [] },<br>);<br> &nbsp; <br>has is_publication_outlet =&gt; (is =&gt; "rw", isa =&gt; "Int");</tt></p></div> </blockquote><p>The default of ''is =&gt; "ro"'' seems badly chosen. Having ''is =&gt; "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.</p><p>Type constraints are also useful because you can do certain things declaratively instead of imperatively. Data driven code is always a win; less code ==&gt; less bugs, so refactor it into the framework or language.</p><p>The Perl internal types <i>are</i> <a href="http://search.cpan.org/~stevan/Moose-0.54/lib/Moose/Util/TypeConstraints.pm#Default_Type_Constraints">documented</a>, but not in an obvious place.</p><p>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.</p><p>Bool seems weird and doesn't play well with Perl's idea of true / false.</p><p>The constraints above disallow undef, so if you want a value to be either a string or undef, the syntax is:</p><blockquote><div><p> <tt>isa =&gt; "Maybe[Str]"</tt></p></div> </blockquote><p>To override the default for an attribute in a subclass without having to retype the entire declaration you prepend a plus:</p><blockquote><div><p> <tt>has "+is_persistable" =&gt; (default =&gt; 1);</tt></p></div> </blockquote><p>This visual distinction feels very right and makes it obvious it is overridden.</p><p>Roles are nice but the keywod "<i>with</i> MyRole" isn't the same as Perl 6' "<i>does</i> 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.</p><p>The "lazy =&gt; 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.</p><p>Moose is clearly the new default way of Perl OOP.</p> jplindstrom 2008-07-08T00:21:34+00:00 journal 5 and 6 http://use.perl.org/~jplindstrom/journal/36751?from=rss <p><a href="http://www.prelovac.com/vladimir/wp-content/gallery/mother/camel.jpg">Perl 5, and 6</a>.</p> jplindstrom 2008-06-23T12:36:54+00:00 journal D'oh of the Day http://use.perl.org/~jplindstrom/journal/36723?from=rss <p>So in the app at work, input is performed through what we call "an import".</p><p>Just now a strange error occured in the test that sanity checks that all modules compile.</p><blockquote><div><p> <tt>Can't call method "request" on an undefined value</tt></p></div> </blockquote><p>It appears I removed some duplication by extracting to a method called... "import".</p><p><a href="http://www.youtube.com/watch?v=2roCxwynvoA&amp;feature=related">D'oh</a>.</p><p>See also: </p><blockquote><div><p> <tt>perldoc -f use</tt></p></div> </blockquote> jplindstrom 2008-06-19T16:00:10+00:00 journal Emacs Tramp syntax (for reference) http://use.perl.org/~jplindstrom/journal/36485?from=rss <p><a href="http://www.emacswiki.org/cgi-bin/wiki/TrampMode">TRAMP</a> is the Emacs feature that lets you edit files on other servers or as other users transparently. It's super convenient when you can't be arsed to drag the configuration all the way over there[1], or if Emacs isn't installed.</p><p>But I only need to every once in a while so I always forget the exact syntax even thought it isn't very diffcult.</p><p>Today I thought I had forgot it again, but instead I had been too clever with a socks configuration which prevented me to connect to otheraccount@localhost... Duh.</p><p>Anyway, when opening a file, just enter this:</p><blockquote><div><p><nobr> <wbr></nobr><tt>/ssh:otheraccount@localhost:</tt></p></div> </blockquote><p>and hit Tab to get file completion in the other account home dir.</p><p>Neato indeed.</p><p>[1] Yes, I know of -u to load<nobr> <wbr></nobr>.emacs from another account, but that often doesn't work out with the load paths, so TRAMP is actually easier if you don't need the <a href="http://www.emacswiki.org/cgi-bin/wiki/VersionControl">version control</a> integration, or <a href="http://www.emacswiki.org/cgi-bin/wiki/FlyMake">flymake</a>.</p> jplindstrom 2008-05-21T16:26:22+00:00 journal jQuery to the rescue (again) http://use.perl.org/~jplindstrom/journal/36474?from=rss <p>If you do any kind of client side web programming, you should check out <a href="http://jquery.com/">jQuery</a>. Its pragmatic design is just awesome.</p><p>Today I had this Ajax response that I needed to parse to fetch an id so I could have the browser redirect to the correct URL.</p><p>Hmmm... how to work the xml? XPath? Fiddling with the DOM? I do that so rarely I can never remember the methods to call.</p><p>If only I could use the same simple jQuery approach!</p><p>Well, duh, it turns out <a href="http://marcgrabanski.com/article/83/jQuery-Makes-Parsing-XML-Easy">I can</a>.</p><blockquote><div><p> <tt>var xml = $.ajax({ async: false,<nobr> <wbr></nobr>... }).responseXML;<br>var import_id = $(xml).find("import").attr("iid");</tt></p></div> </blockquote><p>jQuery++</p> jplindstrom 2008-05-20T13:16:44+00:00 journal 10% at The Beeb http://use.perl.org/~jplindstrom/journal/36445?from=rss <p>Interesting to read about Jonas's <a href="http://use.perl.org/~jonasbn/journal/36441">Google Day</a>.</p><p>At the BBC we have what's called 10% time, which in our team translates to a Gold Card Day every sprint (i.e. one day in ten, which is... um... 10%).</p><p>"Gold Card", because we do Scrum and we put a card on the board for each developer. With the card we can do whatever we want for a day, but it's supposed to be somewhat related to the product, the project, or the team.</p><p>It's really good if it's also Innovative(tm).</p><p>Innovation is what the BBC is after. Apparently this is even in the BBC charter, and it's something that all of BBC is supposed to be doing. Currently I know of our team and another department doing it, but it's something they are semi-actively trying to get going all over the place at the moment.</p><p>When we started doing this Gold Card thing, it turned out that almost no-one actually took his Gold Card during scrum in the morning. So after a couple of weeks our Scrum Master instated the one "mandatory" day of do-whatever-you-want, which worked out very well. It's at the beginning of the sprint, so we don't risk putting it off at the end of the sprint because things may not be done (if that happens, we need to plan and estimate the sprints better).</p><p>So what kind of things are we talking about?</p><ul> <li>I spent last Gold Card creating a visualization of our code base as a clickable <a href="http://js-treemap.sourceforge.net/">Treemap</a> (I may turn that into a CPAN module in my own time. And replace that somewhat ugly JavaScript treemap with a <a href="http://blog.thejit.org/wp-content/jit-1.0a/examples/treemap.html">prettier one</a>). The Perl code stats collected so far are very naive, but here are some sample treemaps of our CPAN deps directory: <ul><li> <a href="http://www.buzzwordninja.com/slask/treemap/cpan_deps_file_size/">File Size</a></li><li> <a href="http://www.buzzwordninja.com/slask/treemap/cpan_deps_bytes_per_line/">Line Length</a></li><li> <a href="http://www.buzzwordninja.com/slask/treemap/cpan_deps_indentation/">Indentation</a></li><li> <a href="http://www.buzzwordninja.com/slask/treemap/cpan_deps_indentation_per_line/">Indentation per Line</a></li><li> <a href="http://www.buzzwordninja.com/slask/treemap/cpan_deps_sub_count/">Sub Count</a></li></ul></li><li>Way way back I wrote a tool to document and visualize database schemas. As a Gold Card task a month ago I adjusted the tool to MySQL and configured it for our code base so we get an automated SQL Map generated whenever the schema changes.</li><li>And the sprint before that, I spent Gold Card day investigating how <a href="http://search.cpan.org/dist/Devel-Cover/">Devel::Cover</a> worked (yes, that took a day, more than that actually), making it possible to write <a href="http://search.cpan.org/dist/Devel-CoverX-Covered/">Devel::CoverX::Covered</a> and integrate it into Emacs with <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm#Go_to_Tests_-_Other_Files">PerlySense</a> (Ovid wrote <a href="http://use.perl.org/~Ovid/journal/36280">Vim bindings</a>).</li></ul><p>While I tend to focus on tools and the dev environment and stuff like that, my team mates have investigated interesting and potentially useful technologies and done cool things to and with the product.</p><p><small>Edit: Added links to treemaps</small></p> jplindstrom 2008-05-16T16:56:11+00:00 journal Missing Perl::Critic plugins I: RequireElseAfterElsif http://use.perl.org/~jplindstrom/journal/36024?from=rss <p>So this is a bug waiting to happen. Or at least a potential problem.</p><blockquote><div><p> <tt>if ($period eq 'a') {<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>}<br>elsif ($period eq 'c') {<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>}<br>elsif ($period eq 'd') {<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>}</tt></p></div> </blockquote><p>Why?</p><p>Well, if none of the if statements are hit, what should happend? Is it okay to omit that case, or is that in fact a bug because something didn't get handled?</p><p>Without reading and understanding the code you can't know whether the lack of an else clause is intentional or accidental. So it doesn't communicate intent clearly at all.</p><p>An empty else clause may seem redundant here. And it is redundant. To the compiler. But it communicates to the maintenance programmer: yes, I actually thought if this case too.</p><p>But, my experience is that whenever there is an <i>elsif</i> chain without a final <i>else</i> clause to catch all remaining cases, that is often a bug. The missing else clause leads to something not happening at all.</p><p>Sometimes the missing else clause is not a bug <i>right now</i>. One of the elsif clauses will always hit given the current input. But if anything related to producing the input changes (somewhere in a distant corner of the code base, far away) then this piece of code suddenly breaks. Silently.</p><p>At the very least, there should be a guarding else clause which says</p><blockquote><div><p> <tt>die("Internal error, sanity check failed: blah blah blah");</tt></p></div> </blockquote><p>So, dear Lazyweb, please write Perl::Critic::Policy::ControlStructures::RequireElseAfterElsif for me.</p><p>Or else.</p> jplindstrom 2008-04-01T17:06:23+00:00 journal Howto: Install local dist file using the cpan shell http://use.perl.org/~jplindstrom/journal/35764?from=rss <p>Gaah. I forgot it. Again.</p><p>When you have a downloaded tar ball of a CPAN package, but want to use the properly configured cpan shell to install it (and get dependencies nicely resolved):</p><ul><li>Unpack the tar ball</li><li>cd into the dir</li><li>cpan .</li><li>Coffee time!</li></ul> jplindstrom 2008-02-26T10:17:23+00:00 journal Emacs: Debugging elisp http://use.perl.org/~jplindstrom/journal/35515?from=rss <p>In elisp, Data::Dumper is spelled prin1-to-string. Nicely pretty-printed output of deep data structures. Invaluable when you're, like me, lost in the details of Emacs' (and your own for that matter) data structures.</p><blockquote><div><p> <tt>(message "thing: &lt;%s&gt;" (prin1-to-string thing))</tt></p></div> </blockquote><p> <i>Note 1:</i> (message) takes a string like (format) does, which means that if your string value contains e.g. %s... well that's bad. So you should always do (message "%s" my-string).</p><p>This is documented but easily overlooked because (message) is one of the first basic tricks you acquire when you start coding elisp, usually by looking at existing code. And then you think you know how it works. At least, that's how I did it.</p><p>I used to write (message (format "blah" stuff)) for a while before I finally read the docs for it.</p><p><i>Note 2:</i> The &lt; &gt; in the example is an old habit of mine: always always always put visible delimiters around variable output in log messages so that you immediately see when the value contains padding whitespace.</p><p>Yeah, trouble shooting weird errors is easier if you see what you're looking at.</p> jplindstrom 2008-01-29T23:54:02+00:00 journal MySQL: error 150 on rename column http://use.perl.org/~jplindstrom/journal/35440?from=rss <p>Dear Google Search Result Page!</p><p>So this fails on an InnoDB table in MySQL 5.0:</p><blockquote><div><p> <tt>ALTER TABLE `xxx_table`<br>&nbsp; &nbsp; CHANGE COLUMN `importid` `import_id` int(11) NOT NULL;</tt></p></div> </blockquote><p>with this luvely error message:</p><blockquote><div><p> <tt>#&nbsp; &nbsp;Failed test 'Migrating up to 29 '<br>#&nbsp; &nbsp;at t/unit/db/migrations.t line 84.<br>ERROR : DBD::mysql::db do failed: Error on rename of<br>'./xxx_tmp_migration_test_1200915479/#sql-4dcf_348f2' to<br>'./xxx_tmp_migration_test_1200915479/xxx_table' (errno: 150)</tt></p></div> </blockquote><p>Why is this?</p><p>At first I thought it was because <i>importid</i> is part of the composite PK (it's a link table), but that's not it.</p><p>It turns out that there is a FK constraint on <i>importid</i> to another table. Deleting the FK and reinstating it with the new column name solves the problem.</p><p>Thanks for the self explanatory error message MySQL, that was very helpful.</p> jplindstrom 2008-01-21T12:03:48+00:00 journal Emacs: latest habits: regex-tool and Visible Bookmarks http://use.perl.org/~jplindstrom/journal/35438?from=rss <p>Using Emacs means constantly acquiring new habits to improve how you do things.</p><p>Well, maybe not constantly. It's important to let the good habits slowly grow into reflexes, otherwise it's just too much to think about when you try to get things done. Once it's a reflex you can forget about it, just use it and work on picking up the next useful trick. Fortunately that seems like a renewable resource.</p><p>Last week I picked up something I've lacked for a while: Visible bookmarks. I know of putting locations in registers, but I never really started using that for some reason. I think it was ever so slightly too bothersome to use, and so I didn't. We'll see if I have started using these in a week or two, or if I need something else from it.</p><p>The second new thing is the <a href="http://www.newartisans.com/downloads_files/regex-tool.el">Regex Tool</a> which will let you compose a Perl (or Emacs, but we already have re-builder for that, so...) regular expression interactively with matching text highlighed. If you have seen <a href="http://www.weitz.de/regex-coach/">The Regex Coach</a>, this is pretty much it.</p><p>This is obviously a <i>very</i> useful thing to have when writing complicated regexes.</p><p>I just uploaded the latest release of <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm#Assist_With_--_Regex">Devel::PerlySense</a> to PAUSE. Release 0.0141 bundles regex-tool.el and contains a first stab at integrating it with PerlySense. Well, integrate and integrate... The default dialect is set to Perl, and it's got a key binding<nobr> <wbr></nobr>:) That's about it at the moment.</p><p>The next step is to notice if point is on a regex and use that as a default.</p><p>The next next step is to notice whether there is a comment block just above the regex. If there is, it will be assumed to be an example of the text to match and used as the default.</p><p>I've found that putting the example input next to the regex to be a <i>very</i> good practice; it really helps understanding what the regexp is all about when coming back and reading it three months later. Yeah, yeah, there should be complete sample input in unit tests, but those are in a different file, and you may not know about it (or whether it actually exists) when you come across this piece of code. So it's good to have it right there. The <a href="http://use.perl.org/~jplindstrom/journal/35310">Principle of Proximity</a> in action again.</p><p>In the process of incorporating Regex Tool I also upgraded it a bit to support the whole Perl regex syntax with modifiers (including the essential<nobr> <wbr></nobr>/x). I hope the author will accept a patch.</p> jplindstrom 2008-01-21T01:45:15+00:00 journal Emacs: reformat parameter lists http://use.perl.org/~jplindstrom/journal/35321?from=rss <p>So, this is a line-wrappingly long line.<br></p><blockquote><div><p><small> <tt>my $link = API::Link-&gt;new({rel =&gt; 'meta:version', href =&gt; $uri-&gt;as_string, type =&gt; 'application/xml'}),</tt></small></p></div> </blockquote><p> If you think that's not a long line, imagine a <b>really</b> long line with a <b>lot</b> of parameters for the sake of argument.</p><p>One param per line is much nicer in this case.<br></p><blockquote><div><p><small> <tt>my $link = API::Link-&gt;new({<br>&nbsp; &nbsp; rel =&gt; 'meta:version',<br>&nbsp; &nbsp; href =&gt; $uri-&gt;as_string,<br>&nbsp; &nbsp; type =&gt; 'application/xml',<br>}),</tt></small></p></div> </blockquote><p> But it is a bit of a hassle to reformat by hand. Manual drudgery which easily makes me lose focus on why I just just wrote that method call. Now, why did I create that $link again?</p><p>Here is some nice <a href="http://www.emacswiki.org/cgi-bin/emacs/jpl-reformat.el">elisp</a> I wrote to reformat parameter lists either into a single line, into multiple lines, or toggle between the two.</p><p>So just put the cursor somewhere inside the parameter list and hit <code>C-o m p</code> (or whatever key binding strikes your fancy, but this one will work well with out-of-the-box PerlySense conventions) and it will reformat things into the other layout.</p><p>Once you have the nice multi-line layout, you can also align the parameters if that makes things look more sensible. Hit <code>C-o m a</code> et voila:</p><blockquote><div><p><small> <tt>my $link = API::Link-&gt;new({<br>&nbsp; &nbsp; rel&nbsp; =&gt; 'meta:version',<br>&nbsp; &nbsp; href =&gt; $uri-&gt;as_string,<br>&nbsp; &nbsp; type =&gt; 'application/xml',<br>}),</tt></small></p></div> </blockquote><p> Well, not <i>that</i> much difference with those parameter names, but I can't be arsed. You get the picture.</p><p>Enjoy!</p><p>(Now I'm just waiting for someone to tell me I reinvented the wheel. I just couldn't find any.)</p> jplindstrom 2008-01-07T16:31:37+00:00 journal Cohesive source formatting http://use.perl.org/~jplindstrom/journal/35310?from=rss <p> After reading my last journal entry, Ovid and I started talking about how to format source code. He prefers one blank line between the POD docs and its sub, and one blank line between the sub and the next sub (I think it was) over my keeping the sub and its POD together, and separating different subs with three blank lines. </p><p> Having this kind of discussion can easily become very unproductive and <i>stupid</i> if you just spew opinions. But it becomes <i>interesting</i> if you can avoid the "what" and instead drill down to the "why" of things. Being challenged about opinions is good because it makes you figure out the reasons behind them and hopefully it clarifies your thinking in some way. You may even change your mind (imagine that!). </p><p> I often find that whenever I need to explain why I do something it boils down to a principle or rule of thumb or other that I have picked up over the years. And if I can't find a rule of thumb, thinking about it may make me formulate one which is also a win. </p><p> <b>The Principle of Proximity</b> </p><p> In this case of where to put whitespace (or not), it is the <a href="http://coe.sdsu.edu/eet/Articles/Designprin1/start.htm#proximity">Principle of Proximity</a>. Since this issue is all about reading source code, it comes from the area of typography and visual design. </p><blockquote><div><p> <i>The Principle of Proximity tells you to put related items close together physically. Things that aren't related should be farther apart. The amount of separation between items or groups tells your reader how the material is organized. </i></p></div> </blockquote><p> In short: Things that belong together should be together. </p><p> So this is why I don't like source to look like this: </p><blockquote><div><p><small> <tt>}<br> <br>=head2 run_safe($c, $sub, $fail_action, $fail_message, @rest)<br>...<br>=cut<br> <br>sub run_safe {<br>&nbsp; &nbsp;<nobr> <wbr></nobr>....<br>}<br> <br>=head2 class_to_moniker($class_name)<br>...<br>=cut<br> <br>sub class_to_moniker {<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>}</tt></small></p></div> </blockquote><p> To me, even with proper syntax highlighting that just blurs together into a grey goo. It's obvious from convention that the POD comes before the sub, but otherwise there isn't enough visible structure to it. </p><p> The Principle of Proximity is very similar to the concept of <a href="http://www.jnd.org/dn.mss/affordances_and.html">Perceived Affordance</a> from Don Norman's <a href="http://www.amazon.com/dp/0465067107/">The Design of Everyday Things</a>. Translated to web design, this basically becomes: If it <i>is</i> a button, it should <i>look like</i> a button. and if it <i>looks like</i> a button it should <i>be</i> a button. Anything else will guide the user in the wrong direction. </p><p> Translated to source code: if things belong together, it should look like they belong together. If things look like they belong together, they should belong together. </p><p> In source code, the belonging is indicated by visual grouping, which is why I much prefer grouping the sub and its POD block into a visual unit, and separating the individual subs with vertical whitespace, like this: </p><p> <small> <code> }<br> <br> <br> <br> =head2 run_safe($c, $sub, $fail_action, $fail_message, @rest)<br><nobr> <wbr></nobr>...<br> =cut<br> sub run_safe {<br> &nbsp;&nbsp;&nbsp;....<br> }<br> <br> <br> <br> =head2 class_to_moniker($class_name)<br><nobr> <wbr></nobr>...<br> =cut<br> sub class_to_moniker {<br> &nbsp;&nbsp;&nbsp;...<br> }<br> <br> <br> <br> </code> </small> </p><p> See? Two things. At a glance. </p><p> One argument for not putting too much vertical whitespace between subs is that it limits the amount of code visible on the screen. But while I sympathise with that idea, because each individual sub is the unit of interest at a given time, they are generally to be understood in isolation from each other. Separating them visually only reinforces this notion.</p> jplindstrom 2008-01-06T20:59:35+00:00 journal Source makeover http://use.perl.org/~jplindstrom/journal/35289?from=rss <p>Badly formatted source code is ugly. But, a few keyboard macros later and it's much nicer.</p><p>And this little defun helped a lot, maybe someone will find it as useful as I did.</p><blockquote><div><p><small> <tt>(defun jpl-makeover-remove-pod-sub-whitespace ()<br>&nbsp; "Clean up Perl source whitespace formatting"<br>&nbsp; (interactive)<br> &nbsp; <br>&nbsp; (save-excursion<br>&nbsp; &nbsp;<nobr> <wbr></nobr>;; Remove =cut with more POD as the next thing<br>&nbsp; &nbsp; (replace-regexp "=cut\n\n+=" "\n\n=" nil (point-min) (point-max))<br> &nbsp; <br>&nbsp; &nbsp;<nobr> <wbr></nobr>;; Remove whitespace between POD and sub<br>&nbsp; &nbsp; (replace-regexp "=cut\n+sub " "=cut\nsub " nil (point-min) (point-max))<br> &nbsp; <br>&nbsp; &nbsp;<nobr> <wbr></nobr>;; 3 newlines before subs if no POD<br>&nbsp; &nbsp; (replace-regexp "\n\n+sub " "\n\n\n\nsub " nil (point-min) (point-max))<br> &nbsp; <br>&nbsp; &nbsp;<nobr> <wbr></nobr>;; 3 newlines before =head...<br>&nbsp; &nbsp; (replace-regexp "\n\n+=head" "\n\n\n\n=head" nil (point-min) (point-max))<br> &nbsp; <br>&nbsp; &nbsp;<nobr> <wbr></nobr>;;<nobr> <wbr></nobr>...except at the top POD block where it's more compact<br>&nbsp; &nbsp; (replace-regexp "\n\n+=head1 NAME" "\n=head1 NAME" nil (point-min) (point-max))<br>&nbsp; &nbsp; (replace-regexp "\n\n+=head1 DESCRIPTION" "\n\n=head1 DESCRIPTION" nil (point-min) (point-max))<br>&nbsp; &nbsp; (replace-regexp "\n\n+=head1 SYNOPSIS" "\n\n=head1 SYNOPSIS" nil (point-min) (point-max))<br>&nbsp; &nbsp; )<br> &nbsp; <br>&nbsp; (font-lock-fontify-buffer)&nbsp; &nbsp;;; In case it got confused<br>&nbsp; )</tt></small></p></div> </blockquote> jplindstrom 2008-01-04T18:18:29+00:00 journal Springtime for Perl and Emacs http://use.perl.org/~jplindstrom/journal/35217?from=rss <p>There seems to be a lot going on with Perl and Emacs at the moment.</p><p>Looking through the <a href="http://unknownplace.org/cpanrecent/rss">Recent CPAN Changes RSS feed</a> I just found <a href="http://search.cpan.org/dist/PDE/lisp/doc/pde/index.html">PDE</a>, Perl Development Environment in Emacs.</p><p>Looks interesting, especially since I try to pick up as many clever elisp tricks as possible.</p> jplindstrom 2007-12-27T22:13:35+00:00 journal Devel::PerlySense 0.0134 http://use.perl.org/~jplindstrom/journal/35110?from=rss <p>I just uploaded <a href="http://search.cpan.org/dist/Devel-PerlySense/lib/Devel/PerlySense.pm">Devel::PerlySense</a> 0.0134 to PAUSE. If you happen to use PerlySense [1], you may want to upgrade since a few nifty features have been added in the last versions:</p><ul><li>Class Overview with the list of methods/properties that make up the API of the class (so that includes inherited methods). From this list you can use method Docs (d) and Go to (g), just like from within the source. [2]</li><li>In the Class Overview, things are rearranged a bit to show the most useful things at the top: the Inheritance tree and the API.</li><li>Run "perly_sense info" to display diagnostics about what PerlySense thinks your Project dir is, where your Home dir is located, etc.</li><li>A Cookbook page with clever tricks and common problem. Well, one of each so far.</li></ul><p>I got a spontaneous <i>That's fucking cool!</i> reaction from a team mate the other day so if you happen to not yet use PerlySense, but use Emacs, you may want to give it a spin. I fixed the gripe in <a href="http://cpanratings.perl.org/dist/Devel-PerlySense">the CPAN review</a> about fiddling with the elisp files, so that's one less hoop to jump through.</p><p>[1] I have no idea whatsoever if anyone actually uses this thing yet, but I'm guessing the user base is only slightly larger than... well, me.</p><p>[2] The API view is not at all finished yet, but it's still useful. Ideally, the methods should be ordered first by their POD heading, and then by their source location. And private methods of parent classes from outside the Project (i.e. when your classes inherit from CPAN modules) are rarely interesting and shouldn't be displayed at all, or at least be displayed in a more subdued font face.</p> jplindstrom 2007-12-16T05:41:19+00:00 journal Ruby -- first impressions http://use.perl.org/~jplindstrom/journal/34989?from=rss <p>I did some Ruby work at work today. Initial impressions:</p><ul><li>It's very Perlish. Mostly in a good way. No value sigils, but overall tighter syntax. No ugly dereferencing brace fest, and methods on basic datatypes makes for clean code if you are willing to make an effort.<p>I remember someone saying Ruby is Perl's younger, hotter sister. Well, they are clearly related. And she <i>is</i> hot.</p></li><li>The block syntax is really nice.</li><li>Very sparse documentation of method definitions in this app. Not sure whether that's a project thing or a general Ruby/library thing. I mean, It's not like I have been spoiled rotten with well documented Perl enterprise source code historically.<p>But wearing the maintenance hat, exploring a code base with zero prior knowledge clearly reveals the need to document what kind of objects are being passed around in a dynamic language. I wonder if the type inferring statically typed languages (Haskell) have the same kind of issues compared to explicitly typed languages (Java).</p></li><li>In Ruby, local variables are created on first use. No declaration of these seems... well, insane. This already bit me, and I've been using Ruby for, what, a day?<p>I'm a bit curious about the phenomenon. In Perl there's "use strict" and then lexicals are declared with "my". That's such an obvious life saver and such a strongly encouraged practice that it's mind boggling to see people not using it. Not being able to use it. But at the same time... is this the way people using statically typed languages all day look at dynamic languages, not believing it's possible to live without type declarations all over the place?</p><p>There are obvious benefits for understanding the code (see above) to have e.g. type information available in method signatures (not the least the ability to do static analysis of the code for refactorings and command completion, etc), just as there are obvious benefits to not having to care about it until the latest possible moment (late binding). So there's a trade-off there. And you can keep it somewhat sane by documenting as needed (folks, more true laziness, please).</p><p>I can't see the potential advantage of not declaring lexicals. Maybe I'm missing something. Maybe I'll come around. But I'm guessing not, this seems like a genuine misfeature.</p></li><li>There seems to be two kinds of exceptions, those you "raise" and those you "throw". There is a distinction, I haven't quite figured out what it is yet though<nobr> <wbr></nobr>:) Right now I just find it interesting. Off to the manuals.</li><li>Lanuage documentation is decent. Usually a quick Google for anything yields useful results. Same seems to hold for ActiveRecord and friends, but I haven't been doing anything interesting with it yet.</li></ul><p>All in all, a pleasant experience.</p> jplindstrom 2007-11-27T22:31:13+00:00 journal Crappy code http://use.perl.org/~jplindstrom/journal/34981?from=rss <p>Google Video of <a href="http://video.google.com/videoplay?docid=3217540637672747357">Alberto Savoia on Crappy Code</a>.</p><p>The basic premise of the CRAP metric is:<br>Complexity bad<br>Tests good</p><p>Test coverage is measured eminently with <a href="http://search.cpan.org/dist/Devel-Cover/">Devel::Cover</a>. But how do we measure complexity of Perl code?</p><p>Perl::Critic implements the <a href="http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Utils/McCabe.pm">McCabe</a> cyclomatic complexity thingy.</p><p>Does anyone have any actual experience whether that makes sense and is a useful metric? In general? For Perl?</p><p>Or what else can we use to indicate the crappiness of Perl code?</p> jplindstrom 2007-11-26T21:14:28+00:00 journal At BarCamp http://use.perl.org/~jplindstrom/journal/34966?from=rss <p>So Jonathan blagged me into BarCamp London.</p><p>Very interesting so far. Two economy related talks this morning:</p><ul><li>VRM - Vendor Rights Management<p>Turning the Vendor - Consumer relationship upside down and taking back the ownerhip of your transactional information</p></li><li>Voluntary Economics</li></ul><p>I'm talking tomorrow about PerlySense and stuff.</p> jplindstrom 2007-11-24T12:55:32+00:00 journal Word of the Day: Budgetechture http://use.perl.org/~jplindstrom/journal/34899?from=rss <blockquote><div><p> <i>I think the high cost of commercial databases (read: Oracle) leads to a kind of <a href="http://www.michaelnygard.com/blog/2007/11/two_quick_observations.html">budgetechture</a> that concentrates all data in a single massive database.</i></p></div> </blockquote><p>Looks like a very interesting <a href="http://www.michaelnygard.com/blog/">blog</a> in general. Check it out.</p> jplindstrom 2007-11-14T18:08:12+00:00 journal Don't dump everything in the entire world please http://use.perl.org/~jplindstrom/journal/34427?from=rss <p>When dumping deeply nested data structures (like DBIC objects) and the indentation level wraps around the width of the shell yet <i>another</i> time, it's time to start doing this first:</p><blockquote><div><p> <tt>local $Data::Dumper::Maxdepth = 3;</tt></p></div> </blockquote><p>In the debugger, using "x" to dump, it's:</p><blockquote><div><p> <tt>x [maxdepth] expr</tt></p></div> </blockquote><p>This can also be set with the dumpDepth option so you don't have to care about it all the time:</p><blockquote><div><p> <tt>o dumpDepth=3</tt></p></div> </blockquote><p>In the debugger, using the excellent "r" to continue until return of sub, it also insists on dumping the return value (which you rarely care about, you just want to get out of the damn sub), unset the PrintRet option first.</p><blockquote><div><p> <tt>o PrintRet=0</tt></p></div> </blockquote><p>Put these in the<nobr> <wbr></nobr><i>.perldb</i> init file in<nobr> <wbr></nobr><i>./ </i>or <i>~/</i> to make it permanent.</p><blockquote><div><p> <tt>DB::parse_options("dumpDepth=3");<br>DB::parse_options("PrintRet=0");</tt></p></div> </blockquote><p>No more eternal scrolling sessions.</p><p><i>* relief *</i></p> jplindstrom 2007-09-12T16:47:11+00:00 journal