lachoy's Journal lachoy'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:02:47+00:00 pudge Technology hourly 1 1970-01-01T00:00+00:00 lachoy's Journal Perl webapp frameworks: what to explore? <p>I've been working pretty much exclusively in Java for the last few years. However, we have a subproject to do some system/application automation work that's written in Perl. It's currently a CLI tool that allows us to install/upgrade our application remotely, restart the service(s) (the app runs on Solaris), and other fun stuff.</p><p>We're not only expanding its scope, but we're giving it a nice shiny GUI shell via a website. After working for years on Perl webapps I've been out of the loop for years. That can actually be a worse position than not knowing anything, because I have outdated ideas and biases as to how things 'should' work.</p><p>And now we get to my question. It looks like people are commonly using Catalyst, CGI:Application, Jifty. Are there others? And what's the "best" one to use?</p><p>Some constraints/ideas:</p><ul> <li>I hope to not have to deploy an RDBMS, so if a framework requires one it's out,</li><li>Built-in REST support would be nice,</li><li>Gobs of dependencies aren't too scary. We're hoping to deploy this in a Krang-like fashion, entirely self-sufficient and black-box[1],</li><li>Easy to start and easy to maintain (should go without saying, but these shouldn't be a trade-off),</li><li>Team composed of solid Perl folks but webapp newbies or webapp geezer (me).</li></ul><p>Perl is supported at our company for a nifty internal testing/automation suite, some build automation, and probably under-the-radar stuff, but that's about it.</p><p>By comparison, this is a project we're not only hoping will be long-lived, but it will be deployed on servers not in our control (thus the Krang-like deployment above), and used by people (mostly IT staff) not in our control.</p><p>Will they freak out that this is a Perl app? Unknown -- what do you think? (This is IT in healthcare, FWIW.) Do we even need to tell them it's Perl (e.g., "it's a black box")? Unknown, but IMO we likely do.</p><p>Reading the recent 'perl is dying/dead' threads here [on use.perl] also makes me wonder about hiring. Hearing that quality organizations are having trouble finding competent Perl developers is disturbing, whatever the reason. For instance, take <a href="">Grant Street</a>. From what I've heard, they have a solid team that gets to work on pretty interesting stuff, not your typical CRUD tedium. You'd think with that combo they'd attract competent people like honey attracts bears. But they're <b>always looking</b>.</p><p>There's always an argument that you can hire someone smart and they can just "pick up" the language/platform. I think that's true if you have 6-12 months to burn. It's easy to learn a language, even Perl. It's harder and more time-consuming to learn its ecosystem -- which modules to use and not-use, idioms, approaches for common tasks, etc. It's not that these things are <b>required</b> to get things done, it's that the rest of the team will have to go over all of the new hire's work much more closely.</p><p>----------</p><p>[1] Wasn't there a project to extract the Krang build logic into something self-contained? The projects occupying that area of my brain are 'Smolder' (which is aimed at code coverage and reports) and 'Matchstick' (which looks to have been abandoned). Is there something else?</p> lachoy 2008-12-11T22:15:13+00:00 journal Clarification on small teams <p>There's a nice response from Bob on my thoughts on small vs large teams. He raises a bunch of good points, go read 'em.</p><p>Re-reading <a href="">what I wrote</a>, it sounds a bit like I'm a large team guy. People I work with know better: I'm quite the opposite. The largest development team I've ever worked on is what I'm on now -- seven developers, four on the server-side (including me) and three for the application on our wearable device (although we get to steal them sometimes). And one of the server-side folks came on four weeks ago.</p><p>And even at one point when we had the potential of bringing other folks temporarily on the team for our last three months before product intro, I resisted. Primarily because software isn't a generic thing you're building, it only makes sense in a context. And our containx (nursing homes) isn't something you can pickup overnight. So I saw that maybe we could get lots of code produced, but we'd be cleaning it up for the life of the product. </p><p>Anyway, what I wrote was primarily a response what I saw as some naive thinking. When someone says that a team of three people can do anything, I hear "I've never put a system into production." (Yes, it's hugely unfair.)</p><p>But reaction pieces aren't affirmative, they don't really tell you what a person thinks, just what he doesn't think. So here's what I think: small teams kick ass. Products designed and built initially by a small team tend to have a greater cohesion than those built by larger groups, and I think this is an overlooked benefit for maintenance programmers.</p><p>But small teams can by risky, too. Developers tend not to talk about risk because we think we can steamroll over it by heroics and cleverness. You have to be much more careful about hiring -- bad apples spoil any team, but they're immediately fatal to a small team. And it's even riskier if you need to move quickly -- it takes time to find the right people.</p><p>Of course, the alternative is risky as well. Hiring any warm body may seem productive at first ("we hit our hiring numbers!"), but it won't buy you success. And adding warm bodies to a project in trouble is a sure way to tank it.</p><p>A number of the strengths of small teams have a double-edge. For instance: on a small team it's easier to trust everyone, to know that they're going to do their job so you don't need to cover for them. But when something unexpected comes up there are fewer people to deal with it. So people tend to work longer hours. Which isn't so bad for a short time, but that has a bad habit of going longer than anticipated. Not so good for people with families.</p><p>Compared to this, choices among programming languages or even frameworks seem secondary. Or maybe teams choose these things to fit the folks working there? (If they're able.)</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-11-29T06:20:58+00:00 journal Small teams and big jobs <p>Reg Braithwaite has a typically interesting post, <a href="">What if powerful languages and idioms only work for small teams?</a>. As usual I think things are more complex than most of the posters.</p><p>First, most of them completely disregard timeframe. Sure, as Carmack said, "a team of 3 focused and creative people can accomplish almost anything" -- given sufficient time. But time is the knob that many (most?) projects have little control over. Everybody has competitors, and everything needs to get out yesterday.</p><p>Second, most of the comments regard developers only. Does "small team" include QA? People to gather requirements? People to write documentation for users, or even other developers? Or do the developers do those too? (And if they do, see the first item.)</p><p>Third, I think there's a huge distinction between creating something and maintaining/improving it. I agree with Bob that it's possible to <b>create</b> complex software. But what happens when it gets in front of customers? And then when you can no longer count the number of customers on your fingers and toes? And assuming only half of them have potential ideas as to bugs and improvements, who's going to do all that <b>and</b> develop new features to keep up with the Jonses, or those left out from the last version due to time constraints?</p><p>Fourth, the examples brought up during the comments are all tools -- Linux, Delphi, even Quattro Pro. They're generic tools built without regard for any specific business logic. But I'd venture a guess that most developers don't work on such systems. They have to deal with automating processes that have been accreted for years on paper and informally in the brains of the workers. And even then they have to communicate with systems and coordinate not only protocols (which is what tools do) but content, even in the face of stupid implementations.</p><p>And doing all that for non-trivial businesses, with a small team, no matter what language, is a tough job. (Not even mentioning figuring out what it is you're supposed to build.) In a short amount of time? Approaching impossible.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-11-26T02:31:09+00:00 journal I'm going to the Pittsburgh Perl Workshop, are you? <p>The second <a href="">Pittsburgh Perl Workshop</a> is this weekend, and twice as long as it was last year! There are lots of great talks lined up and even a full day opportunity to <a href="">get your Perl learn on</a>.</p><p>Even if you're not really a Perl person this is a fun time. My Perl status is grandfathered in from earlier jobs and projects so the talks aren't directly relevant to my job. But hanging out with a bunch of smart people together with ideas zipping by a mile a minute is never a bad idea. And throw in free food, you're golden.</p><p>See you there.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-10-12T13:28:42+00:00 journal Yeah, that me (view image: <a href="">long duk dong</a>) <p>MJD has been working on his <a href="">red flags</a> book for a while, and he's had an open invitation to Perl Mongers groups: he'll speak at your group for free as long as you give him something to talk about. This could be work you'd like to see improved, whatever</p><p>. </p><p>I can testify that in the absence of volunteers he'll find other work. In our case, he happened on the Class::Observable module when he came to Pittsburgh last year. I remember walking in just as they were handing out copies of the source code, and seeing '' at the top: my stomach plummeted.</p><p>Fortunately, he was extremely fair, and it was difficult to argue with any of his choices. The only one I could raise a tiny objection to was naming: I'd used 'update' to mirror the Java <tt>java.util.Observable</tt> interface, and on hearing that's why I chose it he said something like, "Oh, that makes sense." I'd also used a set of awkwardly-named methods like "_obs_foo_bar" but that's because I didn't want them overridden and Perl doesn't give you private methods. (At least, not by default.)</p><p>Unfortunately, I had to bail during MJD's presentation -- not because I couldn't take it anymore, but because it was early on in Barb's pregnancy and I had a strict time limit on how long I could be away from home. (Long story.) And because I came in late I couldn't explain this to MJD, but I figured that Casey, Tom or Rob would have told him I wasn't the shinking violet sort. (I did tell him later in an email.)</p><p>Anyway, I figured that was the end I'd hear of it until the book came out, and given the lead time of HOP I was comfortable with a few years for that. Until I got an email from Rob Blackwell: "You're an international red flag" along with a link to MJD's <a href="">YAPC::EU presentation</a>.</p><p>Ouch. Yeah, that me. But in my defense I think my overengineering tendencies have been greatly curbed in the last few years. And the few recent times at work I've strayed close to the overdesign line I've actually been rewarded when a changed or new requirement came up and it was a piece of cake to handle. We talk about "code smells" like they're so cut-and-dried, but they're not. In everyday work you often get to choose one way of doing things over another, and IMO it's experience with similar choices more than anything else that dictates which one will bear fruit, how successful your choices will be.</p><p>Wish I would have been there to see the whole presentation<nobr> <wbr></nobr>:-)</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-09-16T20:20:35+00:00 journal Happy eight months, stinkyface! <a href="">(view image: </a><a href="">Ella the movie star</a>) <p>Eight months ago today we met Ella, and we've been remarkably lucky since. She's growing and learning like crazy that her time with us is both compressed and expanded: it seems like such a short time ago we brought her home, scared and jubilant at this new life, it seems like such a long time ago that she last slept in her swing, or couldn't pick herself up off her back.</p><p>The only way we could be happier is if she picked the winning powerball numbers last weekend.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-27T19:33:01+00:00 journal Dirges for Java <p> <a href="">Russell</a> seemed to kick off lots of discussion over Java's future; two of the better ones (from my POV) are from <a href="">Joe Gregorio</a> and <a href="">Rafe Colburn</a>.</p><p>I've been thinking about this off and on over the weekend. And one thing I kept coming back to (even disregarding ideas about the technical future that my eight-month old keeps stealing from my mushy brain) is a discussion of community and open source. Has there ever been a development platform that died out having such a large and diverse open source community?</p><p>People who are firmly in the scripting camp and have never used Java may not realize the size and scope of the community. That may be because there's no central repository (like CPAN), or because there are so many large companies out there that might look to the naive to steal the oxygen from the ecosystem.</p><p>But right now I think of the Java community identically to how I think of Perl and CPAN: if there's some system I need to talk to, or some general task I need to accomplish, there will be an open source, business-usable library out there for it. I have bet my technical future on this with both platforms and haven't been disappointed yet.</p><p>Further, dismissing Java-the-language but grudgingly accepting Java-the-platform makes no sense. If I'm running JRuby, or Scala, or plain old Java, the community and the wealth of libraries is what supports my project and team.</p><p>Lastly and IMO, that the official JDK is open source makes it that much stronger. And that all editions of the platform , from mobile phones on up, are open source is underappreciated because of the carping that it took them too long (it sure did) and there are apparently some leftover licensing issues (IANAL). One of the wonderful things about open source is that people pretzel your project in areas and ways you never anticipated, and that all those pretzels produce benefits you can't even conceive. I think we'll see lots of these in the next few years, particularly as mobile devices get more powerful and people start playing with little dev kits that can run Java.</p><p>I have some other thoughts on this general topic (mostly related to the amount of risk projects/hiring are willing to assume with other platforms), but I'm going to have to wait a bit on those. Hopefully my eight-month old won't steal those, too.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-27T19:17:39+00:00 journal Dates and times, and specification examples <p>Scheduling is a big part of our kickass product for nursing homes (coming soon!). Generally there are:</p><ul> <li>appointments (Mrs. Slugworth has a beauty shop appointment on Tuesday at 4:30),</li><li>recurring appointments (Mr. Dahl has a dialysis treatment every other Wednesday at 1:30),</li><li>many types of scheduled care (record weight every Sunday at 3:00 and the last Wednesday of every month at 3:00; do not give fluids for eight hours starting at 2 AM on August 13th; offer fluids every two hours between 6 AM and 9 PM from August 2 to September 15; etc.)</li></ul><p>One of my fundamendal tenets of software development is that anything dealing with dates and times sucks hard. You have to deal with weird measurements (leap years, inconsistent month lengths), timezones, synchronization, agreement on units of measurement, and it's one of the relatively few areas of ubiquitous low level computing that can be <a href="">influenced by human politics</a>. Fortunately many other people much smarter than me have come to the same conclusion and have developed libraries and specifications to deal with the suck.</p><p>The infantry library for us is <a href="">Joda Time</a>, which is in my top five open source Java libraries ever. Partially because what it replaces -- the datetime handling in the JDK -- is so awful. But it's also because it's designed by people who have actually used dates and times in the real world, and because it encourages good practices by using immutable objects as the default and making everything threadsafe.</p><p>But that only deals with dates and times, not recurrences. The 800-pound gorilla in the recurrence space is <a href="">RFC 2445</a>, "Internet Calendaring and Scheduling Core Object Specification" or "iCalendar". iCalendar deals with every aspect of scheduling I can think of, and one of the trickiest is recurring schedules. The formal definition for the 'RRULE' (section 4.3.10) is a page and a half, and that doesn't even scratch the surface of what it actually means. The description of each field fills up another two pages: more useful, but still a little abstract for practical use.</p><p>For me, the best part comes later, in section It includes <b>six pages</b> of explicit examples, like these three:</p><blockquote><div><p> <tt>&nbsp; &nbsp;Every 10 days, 5 occurrences:<br>&nbsp; &nbsp; &nbsp;DTSTART;TZID=US-Eastern:19970902T090000<br>&nbsp; &nbsp; &nbsp;RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5<br> <br>&lt;p&gt;&nbsp; &nbsp; &nbsp;==&gt; (1997 9:00 AM EDT)September 2,12,22;October 2,12<br> <br>&lt;p&gt;<br>&nbsp; &nbsp;The first Saturday that follows the first Sunday of the month,<br>&nbsp; &nbsp; forever:<br> <br>&lt;p&gt;&nbsp; &nbsp; &nbsp;DTSTART;TZID=US-Eastern:19970913T090000<br>&nbsp; &nbsp; &nbsp;RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13<br> <br>&lt;p&gt;&nbsp; &nbsp; &nbsp;==&gt; (1997 9:00 AM EDT)September 13;October 11<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(1997 9:00 AM EST)November 8;December 13<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(1998 9:00 AM EST)January 10;February 7;March 7<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(1998 9:00 AM EDT)April 11;May 9;June 13...<br>&nbsp; &nbsp; &nbsp;...<br> <br>&lt;p&gt;<br>&nbsp; &nbsp;Every 3 hours from 9:00 AM to 5:00 PM on a specific day:<br> <br>&lt;p&gt;&nbsp; &nbsp; &nbsp;DTSTART;TZID=US-Eastern:19970902T090000<br>&nbsp; &nbsp; &nbsp;RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z<br> <br>&lt;p&gt;&nbsp; &nbsp; &nbsp;==&gt; (September 2, 1997 EDT)09:00,12:00,15:00</tt></p></div> </blockquote><p>When writing any type of documentation it's easy to assume your reader consumes what you've written as carefully as you've produced it -- from front to back, paying attention to your highlights and thinking deeply about your assumptions and goals. But IME few people have the inclination or luxury of reading that way -- it's, "How can I do job X?" Examples are the best way to do this; if your library is good enough, they'll get to the other (still important) parts later.</p><p>(BTW, the library we're using for recurrences is <a href="">Google's RFC 2445 implementation</a>. It's okay (it has Joda Time integration!), but IMO needs some usability improvements. When I get a few minutes to breathe this fall I hope to try and contribute...)</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-16T04:16:45+00:00 journal Hooray for standard formats! <p>IDEA 7 has a nifty feature called 'Shelve changes'. Some SCM systems have this -- it's the ability to take a set of changes and have the SCM 'forget' about them so you can do other work independent of them. You can then reintegrate them back in one fell swoop. The typical use case is to move aside changes for a big feature to implement one or more small features at the same time so you don't accidentally bring the 'big feature' changes in with the small ones.</p><p>(From what I understand this is built-in to most distributed SCM systems -- branches aren't the heavyweight things they are in Perforce, so every feature becomes its own branch and has its own changesets associated with it. Cool.)</p><p>Anyway, somehow IDEA lost track of a shelf I'd made a week or two ago -- I hit Alt-9 to see the changes, then Alt-RightArrow twice to the see the 'Shelf' tab, only to see there was no 'Shelf' tab. Shit! I tried to remember everything I did, and while it wasn't a huge amount it was an hour of work plus testing.</p><p>Before I started on that path I went to the directory where IDEA stores all of my stuff: <tt>~/.IntelliJIdea70</tt>. Under <tt>config/shelf</tt> was a single file with the extension of<nobr> <wbr></nobr><tt>.patch</tt> and the name I'd given the shelf. Sure enough, the tried-and-true patch format sat there, and after choosing 'Version Control | Apply patch...' my changes were brought back in. Awesome!</p><p>It would have been really easy for the folks at Jetbrains to create their own format for shelved changes, and to tightly couple the 'reintegrate shelf' functionality with the file itself, disallowing its use anywhere else. That they didn't shows, again, how much they know how developers work. The fact that I also could have applied them with the command-line <tt>patch</tt> tool is also great, and another argument for sticking with standard formats where possible.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-14T13:41:06+00:00 journal It had to happen: lolcode <p> <a href="">lolcode</a>, with <a href="">t-shirts</a> and everything:</p><blockquote><div><p> <tt>HAI<br>CAN HAS STDIO?<br>PLZ OPEN FILE "LOLCATS.TXT"?<br>&nbsp; &nbsp; AWSUM THX<br>&nbsp; &nbsp; &nbsp; &nbsp; VISIBLE FILE<br>&nbsp; &nbsp; O NOES<br>&nbsp; &nbsp; &nbsp; &nbsp; INVISIBLE "ERROR!"<br>KTHXBYE</tt></p></div> </blockquote><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-10T19:46:17+00:00 journal Resolved: ignore anyone who says... <p>"face it" when trying to convince someone of anything. As in, "Let's face it, everybody knows that furbles blorbicate way more than they nooble." Declaring a fact correct doesn't make it so</p><p>Inspired by <a href="">chromatic's recent post</a>, where multiple commenters tried this, like "Face it the main languages used today are Java, C/C++,C#, and Python." or "Face it -- by the time they release it [Perl6] (around the time when Duke Nukem comes out, I'm sure), Ruby will have already overtaken Perl5."</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-08-07T18:50:19+00:00 journal Collections + Generics = autovivification? <p>One of the many nice things about Perl is autovivification -- you don't need to assume a hash key exists before you can assign to it, as many times as you like. So you can do something like:</p><blockquote><div><p> <tt>my %employees = ();<br>$employees{'Steve McQueen'}-&gt;{salary} = 50000;</tt></p></div> </blockquote><p>And the intermediate hash attached to the key 'Steve McQueen' will be created along the way for you. Now, like a lot of things in Perl this can lead to silent failures -- if I now do this:</p><blockquote><div><p> <tt>my %employees = ();<br>$employees{'Steve Mcqueen'}-&gt;{department} = 'Kicking ass';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;^^^</tt></p></div> </blockquote><p>...a whole new hash would be created and the data won't be where I expect. But there are many ways to get around this, most of which you should be doing anyway (case-insensitive keys, IDs as keys, tests, etc.). Perl will let you shoot yourself in the foot.</p><p>The equivalent in Java would be:</p><blockquote><div><p> <tt>Map&amp;lt;String,EmployeeData&gt; employees = new HashMap&amp;lt;String,EmployeeData&gt;();<br>employees.get( "Steve McQueen" ).setSalary( 50000 );</tt></p></div> </blockquote><p>Instead, I need to do:</p><blockquote><div><p> <tt>if ( ! employees.containsKey( "Steve McQueen" ) ) {<br>&nbsp; &nbsp;employees.put( "Steve McQueen", new EmployeeData() );<br>}<br>employees.get( "Steve McQueen" ).setSalary( 50000 );</tt></p></div> </blockquote><p>Or even more egregious, because all we're asking the language to do is pick a reasonable default implementation of an interface:</p><blockquote><div><p> <tt>Map&amp;lt;Integer,List&amp;lt;Work&gt;&gt; workByID = new HashMap&amp;lt;String,List&amp;lt;Work&gt;&gt;();<br>Work work = getWorkFromSomewhere();<br> <br>&lt;p&gt;// one line<br>workByID.get( 15 ).add( work );<br> <br>&lt;p&gt;//<nobr> <wbr></nobr>...vs four lines<br>if ( ! workByID.containsKey( 15 ) ) {<br>&nbsp; &nbsp;workByID.put( 15, new ArrayList&lt;Work&gt;() );<br>}<br>workByID.get( 15 ).add( work );</tt></p></div> </blockquote><p>I know some frameworks do this -- in particular, object creation frameworks that map data coming in (over HTTP, via an XML/JSON graph, etc.) to objects. But should you really need a framework for this, each with its own quirks? (Yes, OGNL, or at least OGNL + Webwork, is quirky.) Shouldn't the language and data structure be smart enough to figure that it can pick a reasonable List implementation for you if there's none specified by use? Or that it can use the no-arg constructor for random JavaBeans?</p><p>It winds up encouraging the use of lots of little classes. By itself that's not such a bad thing, I'm a fan of using lots of little classes. But not when most of them do no more than add null checks to the standard library's data structures.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-06-07T21:19:22+00:00 journal A couple of the things I miss most from perl... <p>At this point in my career I'm probably 50/50 in the time I've spent using Java and Perl. When I first got into Java my brain tried to map Perlisms to Java, but I think I'm now fluent to the same degree in each.</p><p>That said, even after six years of doing Java FT there are still some things from Perl I dearly miss, and they break down into syntax and constructs.</p><p> <b>Syntax:</b> And I've said many times that, barring extreme cases, disliking a language because of its syntax is like disliking a spoken language because of a dialect. After a while of reading or hearing it, you get acclimated. What was once jarring becomes the norm. </p><p>That said, the things I miss most are <tt>next</tt>, <tt>last</tt>, and <tt>unless</tt>. The first two are just lingo preferences both: <tt>next</tt> and <tt>last</tt> are more humane (and informational) than their equivalents, <tt>continue</tt>, and <tt>break</tt>. (Seeing 'break' in a program is still occasionally funny, as if you're attempting to induce a random bug with a single verb.)</p><p>But <tt>unless</tt> is different. One of my pet peeves with Java libraries is that there's never an 'isNot' for every 'is' property. So you wind up mixing metaphors, using a terse negation operator with a verbose boolean property invoked as a method. For example, if I wanted to process a list only if it had data, I'd do:</p><blockquote><div><p> <tt>List thingies = getThingies();<br>if &lt;b&gt;( ! thingies.isEmpty() )&lt;/b&gt; {<br>&nbsp; &nbsp;// do stuff with thingies<br>}</tt></p></div> </blockquote><p>Besides the mixing metaphors, there's more of a logistical problem (and source of a future rant): with most developers' weird whitespace preferences, the negation becomes very difficult to see because it's rendered as:</p><blockquote><div><p> <tt>List thingies = getThingies();<br>if &lt;b&gt;(!thingies.isEmpty())&lt;/b&gt; {<br>&nbsp; &nbsp;// do stuff with thingies<br>}</tt></p></div> </blockquote><p>Putting the negation in the method is better, either as:</p><blockquote><div><p> <tt>List thingies = getThingies();<br>if &lt;b&gt;(thingies.isNotEmpty())&lt;/b&gt; {<br>&nbsp; &nbsp;// do stuff with thingies<br>}</tt></p></div> </blockquote><p>or you can have a more readable positive version, which suffers because it's not a valid JavaBean property and therefore either un- or differently-usable by lots of tools and libraries:</p><blockquote><div><p> <tt>List thingies = getThingies();<br>if &lt;b&gt;(thingies.hasItems())&lt;/b&gt; {<br>&nbsp; &nbsp;// do stuff with thingies<br>}</tt></p></div> </blockquote><p>Both of these move the negation right, into the property. Perl moves it left, into the condition declaration:</p><blockquote><div><p> <tt># assume that $thingies is a list object with methods<br>my $thingies = get_thingies();<br>&lt;b&gt;unless ($thingies-&gt;is_empty())&lt;/b&gt; {<br>&nbsp; &nbsp;// do stuff with thingies<br>}</tt></p></div> </blockquote><p>But that's just the beginning. Where it really shines is with prefix operations in loops where you want to skip items, or stop iterating entirely. To take an example from my daily work, say you have a plan of care for a nursing home resident and you want to only use that plan if the resident is not 'on leave' (out of the home) or discharged. In Java, this might look like:</p><blockquote><div><p> <tt>Listlt;Plan&gt; plans = getPlans();<br>for ( Plan plan : plans ) {<br>&nbsp; &nbsp; &lt;b&gt;if ( plan.getResident().isNotActive() ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; continue;<br>&nbsp; &nbsp; }&lt;/b&gt;<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...</tt></p></div> </blockquote><p>(Note that a nice object designer put the negative condition as a method!)</p><p>I could have put the 'continue' at the end of the line, eliminating the braces, but then it gets lost. Perl gets around this by putting it at the front, so you have:</p><blockquote><div><p> <tt>my @plans = get_plans();<br>foreach my $plan ( @plans ) {<br>&nbsp; &nbsp; &lt;b&gt;next unless ( $plan-&gt;resident()-&gt;is_active() );&lt;/b&gt;<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...</tt></p></div> </blockquote><p>Reducing the number of lines (from 3 to 1) is secondary to making your intent much clearer, and that's what I dearly miss. One of the 'features' built-in to Perl (and its culture) is TMTOWTDI. It makes non-regular Perl users frustrated, but IMO it can actually make for much more readable programs because your intent can be more clearly stated.</p><p> <b>Constructs:</b> The other two items, <tt>grep</tt> and <tt>map</tt> are kissing cousins, and represent the ability to do something on a bunch of stuff (an Iterable, in Java terms). That something might be to conditionally include it into another bunch of stuff, or to pull common data out of each of the bunch, or whatever.</p><p>There are libraries that kinda-sorta do this (like <a href="">commons collections</a> or <a href="">jga</a>), but they're clunky as hell. It's not necessarily their fault, in many cases Java makes this necessary. But the result is the same: the clunkiness discourages the sort of active use that, again, expresses intent much more clearly. For instance, say I wanted to pull out the ID from every resident given the list of plans above. I could do it the long way:</p><blockquote><div><p> <tt>List&amp;lt;Integer&gt; residentIDs = new ArrayList&lt;Integer&gt;();<br>for ( Plan plan : getPlans() ) {<br>&nbsp; &nbsp; residentIDs.add( plan.getResident().getID() );<br>}</tt></p></div> </blockquote><p>whereas in Perl, it might be:</p><blockquote><div><p> <tt>my @residentIDs = map { $_-&gt;resident()-&gt;id() } get_plans();</tt></p></div> </blockquote><p>To the uninitiated, <tt>map</tt> is scary, using the infamous <tt>$_</tt> that non-Perl folks seem to instinctively hate at first sight. I always tell them, "Just substitute 'it' where you see dollar-underscore." So your block now reads "get the resident from it, then get the ID from the resident and return that." Not so scary, and after you see it and use it a few times it's second nature -- you get acclimated.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-04-04T17:43:59+00:00 journal How did you find your jobs? <p>People always talk about how they want to find jobs, but not that often about how they've actually done it. So here's me.</p><p>Before/during college, it was:</p><ul> <li>replying to newspaper ads (bookstore worker/manager, waiter, bartender)</li><li>tagging along with a buddy who knew somebody (shady 'charity' telemarketing, dishwasher at nursing home, making concrete)</li><li>knowing my mother (two internships at the National Geographic Society)</li> <li>randomly applying to a job without knowing what was open (Pitt library)</li></ul><p>Since college, I've got most of my jobs through responding to want ads. But I suspect that as I get older I'll do that less, just because companies like to hire senior developers they're comfortable with.</p><p> <b>1992, Research Assistant</b>: Responding to an ad posted on the Political Science Department bulletin board at Pitt for a position at George Mason University (outside Washington, DC, about 4 hours away). I don't know how widely the ad was circulated, or if they had a lot of applicants for the position.</p><p> <b>1993, Transportation Planner</b>: Referral to a family member by someone I worked for. The early 90s were a difficult job market. After my previous position's contract expired I went through a few temp jobs while applying to a ton of jobs and got a few interviews. One temp job was at the Institute of Medicine. I must have done a good job because the woman I worked for gave her husband (who was high up in the Montgomery County Planning Department) my resume, and I got an interview and a position shortly after that. Planning wasn't something I aimed to get into but the writing, research, and public focus group interaction wound up being a pretty good job.</p><p> <b>1995, Writer</b>: Found this through a want ad in the Washington Post. I applied because of my experience over the previous two years with transportation -- this was at a non-profit, transit advocacy organization. The main part of the job was writing (articles for a trade magazine, whitepapers, memos), but one thing that set me apart was my familiarity with bulletin board systems (dialup, not internet). The position evolved into more IT stuff as I became the Netware admin, hooked up GroupWise to a single dialup account multiplexed for email, and put the first website up along with some dynamic.</p><p> <b>1997, Webmaster</b>: Another Washington Post ad, although I knew someone who worked at the educational non-profit. I'd gained enough experience with the web at the previous job to do it full-time, although I also had to do some helpdesk and other IT work (including building cheapo computers with unfinished metal, ouch).</p><p> <b>1998, Software Developer</b>: I started a company with a couple of the guys I worked at in the previous position, so this was definitely through personal connections.</p><p> <b>2000, Software Developer</b>: Company found my resume on the <a href="">Pittsburgh Technology Council</a> website. The position was kind of ill-defined and shortly wound up using Java, which I didn't know going in</p><p> <b>2004, SQA</b>: Found posting on Pittsburgh Technology Council website. I didn't have any explicit SQA experience but I was interested in being part of a software process. And I liked the company so much that I figured if SQA didn't work out I could move somewhere else...</p><p> <b>2005, Software Developer</b>:<nobr> <wbr></nobr>...which happened 9 months later when I applied to a position on a much smaller team looking into new markets for our technology...</p><p> <b>2006, Software Developer</b>:<nobr> <wbr></nobr>...the first new venture of which was spun off bout 9 months later, where I'm the lead architect on a rewrite of the server-side software.</p><p>How about you?</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2007-01-28T23:35:15+00:00 journal Hello to Ella Mae Winters <p>Ella Mae Winters was brought into the world on December 27 at 10:07 PM, weighing in at a hefty 10 pounds, 1 ounce and 21.5 inches long. Her extra two weeks in the womb were apparently dedicated to making her not only amazingly cute and alert, but also to growing her head of brown hair.</p><p>Despite <a href="">prediction/hope from my last post</a>, the labor was fairly long and at times difficult, but Barb is recovering very well. And Ella has been healthy and very strong throughout, which may be a testament to the prodigious amounts of 8th Continent soymilk that Barb has consumed in the last nine months. (Don't let anyone tell you a mother has to eat meat to produce a big baby!)</p><p>About her name: Ella is for my mom (Pamela), who passed away in 1999 and who would be bursting with happiness (and advice!) right about now. Mae is another form for Barb's maternal grandmother's name, Mary. Like all parents, we don't anticipate using both except in exasperation, although the potential pen names ("E. M. Winters", "E. Mae Winters") sound pretty good.</p><p>Photos are being uploaded to <a href="">flickr</a> literally as I type this, and you can subscribe to the <a href="">all-Ella, all-the-time show</a> as you wish.</p><p>Sorry for not following up my last post sooner, but some of these "21st century" hospitals still don't have internet access!</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-12-29T20:29:06+00:00 journal Recent book: The Hot Kid, Elmore Leonard <p>I borrowed <a href="">The Hot Kid</a> from a co-worker just because it was Elmore Leonard. I haven't read any of his books for a while, but I went through a period in the 90s where I devoured a dozen or so. This one is different: rather than being set in Miami, LA or Detroit, it's in Oklahoma and Kansas. And rather than being 70s/80s/90s/current, it's set in the 30s. But it's still Leonard, through and through.</p><p>What does that mean? For one, you know you're getting little exposition and tons of sharp dialogue. So rather than an omniscient narrator telling you that Carl is getting shaky because someone else depends on him for the first time in your life, and rather than relying on the description of his "quavering voice" or that he has to "steady himself on the porch railing", you get it through dialogue. And if you breeze through it you'll miss a lot of subtlety and those turning points where the characters change and grow (or regress).</p><p>Recommended.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-12-18T12:25:42+00:00 journal Patent craziness: the linked list <p>You think I'm kidding? <a href=";Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=7028023.PN.&amp;OS=PN/7028023&amp;RS=PN/7028023">Check it out</a>:</p><blockquote><div><p>What is claimed is: <br> 1. A computerized list that may be traversed in at least two sequences comprising: a plurality of items that are contained in said computerized list; and a primary pointer and an auxiliary pointer for each of said items of said computerized list such that each of said items has an associated primary pointer and an associated auxiliary pointer, said primary pointer functioning as a primary linked list to direct a computer program to a first following item and defining a first sequence to traverse said computerized list, said auxiliary pointer functioning as an auxiliary linked list to direct said computer program to a second following item and defining a second sequence to traverse said computerized list.</p></div> </blockquote><p> if you needed further proof that the patent system is fundamentally broken.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-12-01T17:46:44+00:00 journal JavaScript talk to <p>I gave a talk to the <a href="">Pittsburgh Perl Mongers</a> tonight about JavaScript. So no, every talk doesn't need to be about Perl, although drawing references to perl constructs helps<nobr> <wbr></nobr>:-) Anyway, <a href="">here are the slides</a> (PDF, 1.5MB).</p> lachoy 2006-11-09T15:04:24+00:00 journal Small teams++ <p>From "The Business of Software" in the September 2006 Communications of the ACM (<a href=";coll=ACM&amp;dl=ACM&amp;idx=1167838&amp;part=periodical&amp;WantType=periodical&amp;title=Communications%20of%20the%20ACM&amp;CFID=4378871&amp;CFTOKEN=34661004">abstract</a>), summarizing findings from the <a href="">2006 QSM Software Almanac</a>:</p><blockquote><div><p>The effectiveness of large teams is seriously questioned by the data in this analysis. Large teams (29 people) create around six times as many defects as small teams (three people) and obviously burn through a lot more money. Yet the large team appears to produce about the same amount of output in only an average of 12 days less time....</p></div> </blockquote><blockquote><div><p>The "best in class" projects compared to the "worst in class" in this study tracked over the following ranges:</p></div> </blockquote><blockquote><div><p> Effort: 15x less effort <br> Schedule: 1/5 of the duration <br> Team Size: The "best" teams were much smaller (9% &gt; 10 people, versus 79% &gt; 10 people on the "worst in class" teams).</p></div> </blockquote><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-25T16:55:27+00:00 journal Removing 'My Bluetooth Places': piece of cake! <p>From <a href="">PC World Forums:</a> </p><blockquote><div><p>To Remove the "My Bluetooth Places" icon from desktop, simply right click on desktop and then go to properties/desktop/customize desktop/clean desktop now. Then tick the box: "My Bluetooth Places" and press next. The icon should then be in a folder called unused desktop items on your desktop. You can then delete the folder if you wish too, it's that easy.</p></div></blockquote><p>Is it possible that any nomal human would discover this on their own? On a Mac, you know what the instructions would be? "Drag the icon to the trash." It would Just Work.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-25T15:59:11+00:00 journal Come December, it's all changing... <p>That thing I mentioned? Mid-December Barb is due with our first baby. Everything's gone swimmingly so far, and she's in that phase of being happy but cranky due to having constant indigestion and general discomfort.</p><p>By choice we don't know yet if it's a boy or girl and while we have a few names on the shortlist, I'll keep those under my hat for now. And the list might change, to which I'm more amenable than Barb just because she's actually prepared for things.</p><p>But I think we have a lot of the big decisions made and have been throwing gobs of money at the house to prepare -- the stairs and second floor are now carpeted, and we had some environment people rip out all the drywall in the basement because of some mold. (I didn't want to do it myself and wind up as a CSI-type exhibit.) That said, you're never really prepared.</p><p>Nauseating baby photos to follow in a couple months...</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-21T03:00:10+00:00 journal Some things I've liked recently (view image: <a href="">Fatboy Slim Greatest Hits</a>) <p>No sorting, just to keep it interesting:</p><ul> <li>The first five or so songs from <a href="">Fatboy Slim's</a> greatest hits. Most of them inspire, "What movie did we hear that in?", but I can't get them out of my head. They're in my 'ocd' playlist that only has 8 or 10 songs I play all day for weeks on end. Sick.</li><li>My job: I really like the people I work with, smart funny people the lot, and all in different ways. We're getting into a Get Lots of Cool Shit Done phase. A year from now I'll be looking back on now as the start of great, hard working times that are resulting in a kickass product and system.</li><li>"Unwritten," Natasha Bedingfield: poppy goodness</li><li>"Hallelujah", Jeff Buckley</li><li>Listening to the Steelers on the radio. During one or two games this year where I've watched on TV and turned down the volume, the TV and radio have been ridiculously out of sync -- like on the order of eight seconds. But I realized at one point that I'd rather have the radio with no TV than the TV with no radio. And at least I can do something mildly productive while listening to the radio.</li><li>House, the TV show. I have a hard time keeping up with weekly shows (no tivo still) and I missed the first three or four seasons (whatever it's at) so I'm catching up on syndication. It's getting a little repetitive, which is kinda redundant after saying "TV show", but it hasn't worn thin yet.</li><li>"God Only Knows", Beach Boys, followed a few miles back by the rest of <a href="">Pet Sounds</a> </li><li>Hooking up with the local Java community at Code Camp last weekend. It's different than Perl -- on the whole more "professional" and interested in getting things done by learning tools, but individually pretty varied and curious. IME Perl people are interested in silly or weird programming tricks, but that's a <a href="">good thing</a>.</li> <li>...and one more thing, which deserves its own post (in a second)</li></ul><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-21T02:45:44+00:00 journal Nice Swing! (view image: <a href="">screenshot</a>) <p> <a href=""> Simple Tools For Simple Tasks... With Cool UIs</a> - Romain Guy has been posting some really nifty Swing tools, presentation slides and videos recently. I'm no GUI programmer, but it's not your father's AWT anymore. (He's also got some <a href="">great photos</a> around too.)</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-21T02:04:40+00:00 journal Useful Postgres tip: log_min_duration_statement log_min_duration_statement (integer) <p> Logs the statement and its duration on a single log line if its duration is greater than or equal to the specified number of milliseconds. Setting this to zero will print all statements and their durations. Minus-one (the default) disables the feature. For example, if you set it to 250 then all SQL statements that run 250ms or longer will be logged. <b>Enabling this option can be useful in tracking down unoptimized queries in your applications.</b> </p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-17T20:22:30+00:00 journal At Pittsburgh Code Camp tomorrow Tomorrow I'll be at Pitt attending the <a href="">Pittsburgh Code Camp</a>, a day-long set of practical talks about Java. And it's free! Maybe I'll see you there? (I might bring my camera like I did for <a href="">PPW</a>.) <p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-14T01:44:56+00:00 journal Autosave in webapps <p>Auto save is implemented in lots of desktop applications. It's just the idea that every so often (seconds or minutes) the applications will store your work someplace safe, and you can get it back if the application crashes, or if you accidentally close it and click through the multiple 'Are you sure?' dialogs.</p><p>But what if you didn't even have a 'Save' option -- why do you even have to manage that? Isn't that why we have computers? Why can't the computer automatically store every change so that you never have to think about it? It's not so far out: Quicken has done this for a long time. It has the benefit of clearly demarcated transactions, but that's just a convenience.</p><p>But AFAIK autosave isn't seen so often in webapps. Entire frameworks are built up around translating the bag of text you get when the user clicks the 'Save' button into usable data (e.g., using an actual date object instead of '2006-10-05' or 'next Tuesday'). And the frameworks themselves are typically record- or object-centric, presenting a data record as a consistent, whole item so it can be mapped (with hopefully a minimum of dissonance) onto an HTML form.</p><p>What would happen if a webapp dealt with the individual pieces of data, rather than entire records? So if you check a checkbox, we send a message to the server saying, "activate the data element represented by the checkbox"; if you type in a person's name and tab to the next item, we send the name to be updated. If you figure out halfway through your edits that you're editing the wrong record you can just click 'Undo' and it'll roll back your changes since you loaded the form.</p><p>Since we're treating the web form as an active data editor we can remove concerns like validation from the browser. And treating data items individually would likely make it easier to create components to handle most of the work for you.</p><p>There are certainly problems with the approach. It means you have to version individual fields, which can be an interesting data management problem. (This also has a positive effect: stale-data conflicts become much more granular and easily resolved.) Some pieces of data are combinations of fields which may not make sense (logically or transactionally) to update independently, which means more things to manage. Managing 'Undo' functionality adds complexity as well. And a low-latency, always-on data connection between the browser and server is a requirement -- in fact, it might only work for intranet-type applications.</p><p>It's an interesting idea; while I'm not sure it's practical, it's a pretty good usability goal to shoot for.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-10-13T13:28:50+00:00 journal SOA motivations <p> <a href="">The Dark Side Of SOA</a> - Not a terribly interesting article (at least not for the 30 seconds I devoted to skimming it), but I think they forgot an option on the last bar chart:</p><p> (view image: <a href="">The real bar chart</a>) </p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-09-06T18:02:24+00:00 journal Work + open source: getting the point <p>At work I've been working on rearchitecting a server platform for <a href="">AccuNurse</a>. And as I <a href="">wrote before</a> I think <a href="">REST</a> offers a really useful way to let our systems and external systems interact with our data.</p><p>While there are <a href="">layers</a> that sit on top of existing platforms to allow you develop "RESTfully", there are also projects that are built from the ground-up with the REST architectural style in mind.</p><p>AFAICT the main REST platform in Java is <a href="">Restlet</a>. It can run on top of Jetty (5 or 6, the Simple web framework, Async web, or in a servlet container. And while it's currently at 1.0 beta 18 the API still undergoes fairly substantial changes from release to release.</p><p>One of the (IMO) glaring omissions is the presence of a sample application that actually does something, even something trivial. The docs talk about how to get the server configured and running, but not so much about how you use the different types of objects to do work.</p><p>So I built one, which you can grab from <a href="">here</a>. And I submitted some minor documentation and code patches. And only then did I think that I should clarify what Vocollect's policy on working on opensource for work purposes. We do have a policy that you can work on opensource software in your own time, as long as it doesn't duplicate what you do at your job. But not what you do on the job.</p><p>So I posed the question up the chain. And the answer I got back was very gratifying. Paraphrased, it was: "We have as part of our business plan to lower costs by using open source operating systems and platforms. Part of using open source means participating in the process, which means giving back. So as long as it doesn't take too much time and it's appropriate to work, go ahead."</p><p>Good stuff.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-09-03T18:01:58+00:00 journal An addition to Brooks A quick search will find <a href="">plenty of references</a> for the classic Brooks quote:<blockquote><div><p>Show me your flowchart and conceal your tables and I shall continue to be mystified. Show me your tables and I won't usually need your flowchart, it'll be obvious.</p></div> </blockquote><p>I think substituting 'messages' for 'tables' preserves the meaning while bringing it forward into what seems to becoming a service-driven era. Guy Steele <a href="">did something similar</a> a few years ago, except specifying object interfaces instead. Too much coupling, messages work better<nobr> <wbr></nobr>:-)</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-08-28T13:01:19+00:00 journal Reminder for p4 filetypes <p>You can tell Perforce to automatically mark certain files as type 'ktext', which is necessary to expand the RCS-like keywords. Unfortunately you have to do this on a per-depot basis[1] and I forget to do so when creating/using a new one. So this post is to remember two things:</p><ol> <li>The command for editing the mapping of depot + extension to file type is 'p4 typemap'; it's not anywhere that I saw in the Win32 GUI so don't even try looking.</li><li>If you forget to add your filetype before importing a bunch of stuff, there's hope. <a href=""></a> </li><li><p> This perl script will invoke the 'p4' command-line client to modify the filetype for those file extensions you specify. The only requirement is <a href="">IPC::Run</a>, which at least on ActivePerl is there by default.</p></li> </ol><p>[1] Technically you don't have to (you can use the '//...' depot map) but if you're working in an org with many different development groups, some of which don't have much contact with one another, it's pretty rude to create a global type map.</p><p>Posted from <a href=""></a>; <a href="">read original</a> </p> lachoy 2006-08-18T01:33:02+00:00 journal