Less opportunity to see how much hard work is necessary
There seems to be less and less opportunity to see how much hard work is necessary to achieve proficiency and (sometimes) success. The actions of a craftsman in wood, for example, can be seen by sitting at the side of a bench and being attentive. What works and what does not is equally visible. And if the craftsman has a the habit of talking to the work some of his interior worries and choices are available.
My children have no visibility into my work. I am a software programmer. I have been at this trade for 30 years but what can be seen of my efforts and the growth? There is nothing.
From my children's perspective there is no history there is only now and the future. No wonder they and the kids you write of think they can be famous. It requires so little effort.
Sending Growls from a remote host
There are times when I want a notification about the status of a long running process I have running on a remote system. I could have it send an email. I could have it send an instant message. I decided that, since I have a Mac, I would have it send a Growl notification. Growl's GNTP makes this easy and the language bindings available make it easier still.
The one obstacle I had was getting the IP address of the connecting host (i.e., my Mac). Commands like finger and who often show this data but I did not want to scrape the command output as it is different between operating systems. Digging into the code for who at koders.com I discovered that it used the user accounting database utmpx API for getting this data. And so, with all the parts needed, I coded up growler
#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use Growl::GNTP;
use User::Utmp qw(:constants :utmpx);
sub getRemoteHost() {
my @utmp =
sort { $b->{ut_time} <=> $a->{ut_time} } # reverse sort by time
grep { $_->{ut_user} eq getlogin() } # filter by current user
getutx(); # get user accounting data
( my $host = $utmp[0]->{ut_host} ) =~ s/:.*$//;
return $host;
}
my $title = "";
my $host = getRemoteHost();
my $port = 23053;
GetOptions(
'title|t=s' => \$title,
'host|h=s' => \$host,
'port|p=i' => \$port )
or do {
print STDERR "usage: $0 ",
" [ --title text ]",
" [ --host name/ip ]",
" [ --port number ]",
" message\n";
exit(1);
};
my $growl = Growl::GNTP->new(
AppName => "growler",
PeerHost => $host,
PeerPort => $port
);
$growl->register([ { Name => "growler" } ]);
$growl->notify(
Event => "growler",
Title => $title,
Message => join( ' ', @ARGV )
);
# END
My original installation of Growl was broken. This caused all manner of errors during testing. To finally get growler to work I had to uninstall Growl and then install Growl 1.4.
Refactoring Java classes with explicit serialVersionUIDs
An object's serialized form is defined in Java Object Serialization Specification. I really didn't want to read the specification: All that I really wanted was to see the differences between the class's pre-refactor stream and the post-refactor stream. So I used jdeserialize to dump the protocol encoding of the streams.
What was quickly apparent in the dump was that the order of the instance variables within the stream have no relation to their order in the class definition. I was not expecting this. During the refactoring I had renamed some instance variables to better reflect their purpose. Once I reverted the instance variable's names to their previous values the serialization was the same. Success.
A distressing aspect of this exploration was that two objects with the same serialVersionUID will be considered the same by the serialization implementation and so it will misinterpret the bytes in the stream for the bytes needed by the class. The end result is that you get an object that is initialized wrong. I would have expected an exception that indicated the mismatch between data in the stream and data expected by the class. Perhaps there is a command line switch or system property I can use to enforce a stricter pairing. Be very careful when refactoring a class with an explicit serialVersionUID to either remove or update its value before committing the changes.
The trifecta of low-ceremony document management
I too add dates to file names even though I know the creation date is part of the file's meta-data. When files are moved between systems the meta-data is not always preserved. This chance of loss is also what thwart me from using a tagging tool as I can not be assured that the tags will be preserved between systems. And so, the trifecta of low-ceremony document management are
- a good title,
- a date in the title, and
- a good full-text search.
I want more "geek lights"
However, geek-lights are incredibly useful for other kinds of information. Information that is different for you and me. For example, one to indicate if traffic is too heavy to venture out now. Another to tell me that I have email. Another to tell others that I am in a conference call and not just talking to myself again.
I would like to have a box of these geek-lights that I can use each for a specific purpose. The geek-light would be nothing more than a shallow and wide cylinder with the light on the top, temporary adhesive on the bottom, and the electronics sandwiched in between. Let's call them eyelets as they let you see something ordinarily invisible. Each eyelet is individually addressable by a short range wireless signal. An eyelet receives a signal that indicates whether it is illuminated or not. Eyelets don't send signals back. I can imagine the hardware being something akin to Logitech's Unifying receiver -- that is, unobtrusive.
The question now is, should eyelets have a battery charge indicator light?
"Acting like a startup" is overrated
A rose by any other name is incorrect: a rant on character sets and encodings
Now é is presented differently in different character-sets and in different character-encodings. For UTF-8 it is represented as two bytes, 0xC3 and 0xA9. For XML it is presented as the numbered entity "é" or "é". For HTML both the XML encodings can be used and the named entity "é" can be used. For percentage encoding within a URL's path and query it is represented as "%C3%A9". Within a domain name that uses punycode it is "xn--9ca". While these differences are not inherently problematic it has been my experience that their combined use very much is.
For example, if I have a URL that contains an é and I want to use this in an HTML A tag's href how do I encode it? All of the following are useable but only the first is correct:
- http://foo.com/bar?%C3%A9
- http://foo.com/bar?é
- http://foo.com/bar?é
- http://foo.com/bar?é
- An HTML named entity being used in XML.
- A entity double encoded, eg é is incorrectly encoded as &&eacute;.
- A french text, for instance, with question marks oddly scattered throughout.
- Be clear that you and your supplier know the difference between a character-set and a character-encoding.
- Don't ever accept bad data. Being generous and accepting (and "correcting") bad data never turns out well for either you or your supplier.
- Only accept percent character-encoding for URLs.
- Only accept numbered entities character-encoding for XML & HTML (except for <, >, &, and ").
- Only accept content for which there is a specified character-set. (For XML it is UTF-8 by default.) So, for HTML form elements make sure to use the accept-charset attribute. For HTTP requests make sure to require the charset attribute of the content-type header. If you can, only accept UTF-8 -- mostly because the supplier's tools will almost aways to the right thing with UTF-8.
- Never use a character-set in your byte-oriented repositories as anything other than UTF-8. (So, when you get a percent-encoded URL make sure to store it not as supplied but as its decoding.)
Need to paint my soldiers.
Library catalog, data: URIs, & bookmarklets
My original solution was to embed the barcode in a URL that mimicked the web application's form-based login. This URL was then bookmarked to allow for immediate access. This worked for a good number of years until the catalog software was updated. At which point the URL broke and I was unable to reproduce this solution using the updated software. (The obstacle seemed to be the need for a session identification that I could not contrive.) And so I needed a different approach.
The approach I took was to be able to show the barcode when I used the catalog. Having an absolute DIV positioned at the bottom the browser's window is easy to do with CSS. The problem was that to do this I needed to dynamically alter the catalog's HTML. I really did not want to install GreaseMonkey to accomplish this. The next best solution was to have a standalone page with an embedded IFRAME. This give me full control over what was on the page. The HTML is
<html>
<head>
<title>South Kingstown Library Catalog</title>
<style>
* {
margin: 0;
padding: 0;
border: 0;
}
#tab {
font-family: Verdana;
position: fixed;
bottom: 0px;
right: 4ex;
padding: 2ex;
border-top-left-radius: 1ex;
border-top-right-radius: 1ex;
color: white;
background: gray;
}
</style>
</head>
<body>
<div id="tab">
barcode: 123456789
</div>
<iframe
src="https://catalog.oslri.net/search/"
width="100%"
height="100%"
scroll="auto"
marginheight="0"
marginwidth="0"></iframe>
</body>
</html>
I didn't like having to store this page as a file on my local machine and storing it on a HTTP server seemed overkill. Clearly, I was over thinking, but this is what I do for my day job. It then occurred to me that I could encode the page as a data URI and, I hoped, that when I used this URI the browser would render the encoded page. I used David Wilkinson's data: URI creation tool to create the URI. And, to my wonderment, Safari, FireFox, and Chrome (all on OS X) did exactly as hoped for.
What this means is that my future bookmarklets can more sophisticated then I ever considered practical before. Perhaps you can use this discovery too.
Moving forward
A miniature wargamer begins
I am enamored with all things miniature wargame. Last year I dove into the world of boardgames (and card games) as my sons were now of an age where we could plays games that were enjoyable to each of us. Boardgaming is not, however, a hobby. A hobby requires hands-on creativity. (Aka, dirty hands.) A hobby is what you do between events. While I am up to the challenge of developing boardgames and card games it is too much of an intellectual challenge only and I have enough of that in my day-job. And further, I don't really want to do it.
As a young teenager I had a detailed model Great Western Railway in N gauge. I loved this hobby. It allowed for the creation of a whole world and one run with British timeliness. (Timeliness, is something that has vanished from the modern UK rail system, I am told.) Modeling railways and railroads are still something I look forward to doing again in my dotage, but not now.
What sparked my interest in miniature wargaming come from an unexpected encounter at the Hobby Bunker. This game store is near to my employer's office and so I went to it too look at their stock of boardgames. What I encountered was not, principally, a boardgame store but instead a miniatures wargaming store. As, as it turns out, the Hobby Bunker is one of the best such stores in the US. And so for two hours I wondered the aisles of shelves stocked with unpainted miniatures in plastic and metal of all historical periods; the selection of paints in acrylic and enamel; the shelves of books with the historical accounts of nations, armies, commanders, and battles; wargamer magazines; and wargame rules. (Hobby Bunker does also have a good collection of boardgames.)
That day I only bought an issue of Wargames Illustrated but the next time I bought some plastic saxons and the paint for them. And, like every good wargamer, they remain unpainted in the box still. But that is not because of waning interest but instead I have dove in the deep-end of the pool and am currently surrounded with magazines, military history books, wargaming books (mostly the foundational one), rule books, wargaming podcasts, and, soon to arrive, armies of vikings and saxons in 6mm.
As one of my sons noted, "you are serious about this dad!" I am.
HAVOC
I had a great time Saturday attending the Boston Battle Groups's Havoc Game Convention (HAVOC). My goal in attending was to see different historical periods and different rule sets in play. In the morning I watched Day of Battle rules payed out by Christopher Parker (the rule set's author), his brother, Jen, and Richard Brian. The game is driven by a unique combination of dice (d6) and a standard deck of cards. I need to see the rules played out in a tournament to make a judgement about them. I want to thank Chris and Dick for sharing their time and knowledge with me.
In the afternoon I watched a Punic wars battle played with the the De Bellis Antiquitatis (DBA) rules ((say what). This rule set seems most approachable. It had the feel of a boardgame but played with miniatures on an open table. Since returning from HAVOC I have spent the most time with this rule set. I want to thank Maureen, Spencer, Mike, and Harrison for a wonderful afternoon.
All in all, I met a wonderful group of people at HAVOC. All most willing to ofter advice and help. And Vic Gregoire invited me to join his "The Usual Gang of Idiots" for some wargames later in the year.
Why is Spring taking a perfectly good Set value and passing along a null?
<bean name="set" class="java.util.HashSet">
...
</bean>
<bean name="x" class="...">
<property name="y">
<map>
<entry key="z" value-ref="set"/>
...
</map>
</property>
</bean>
Where the property's setter is declared
void setY( Map<String,Object> y )
But every time setY() was called the key z's value was null. The problem's answer was very hard to track down. It comes from how Spring automatically converts objects to type specific property values. Spring has two ways of converting a value for use in a property's setter method. The first is based on converting a textual representation to an object via the java.beans.PropertyEditorSupport API. The second is based on Spring's own org.springframework.core.convert.converter.Converter API. I has used a Converter in an unrelated part of my application's Spring context. This was my application's first use of the Converter API. Turning the Converter API on, however, brought with it other conversions I was not expecting. The most detrimental was the Collection to Object converter. When Spring sees that the property expects an Object it tries to convert any value to an Object. (Even though every value is an object.) The Collection to Object converter converts an empty collection to null. Let me say that again .. with emphasis. The Collection to Object converter converts an empty collection to null. My set was empty. And so, a perfectly good empty set value was converted to a null. The correction is the change the setter for property y to
void setY( Map<String,?> y )And all works now. p.s. I would never have been able to debug this without Spring having open source. Thanks VWware, Spring Source, and all the contributors.
Need multiple-view calendar
The top chart contains my unique events over the last 2 and next 8 days. The second chart contains my common events over the last 2 and next 8 days. The bottom left chart is a list of common events for the next several weeks. And the bottom right chart is a list of unique events for the next several weeks.Since we have separated events that actually occupy the same timeline we need to rejoin them somehow. My initial thought was to add a ghost to each chart that signifies the presents of an event in another chart, but I am not wedded to this.
Does anyone make a calendar like this, either visually or purposefully?
A idea for fixing the flow of money in pharma. deseses
The electric utilities in the mid-1990's were split into three segments: generation, transmission, and local distribution. While the customer does not have a choice of local distribution and transmission they should have a choice of generation. Local generation and transmission continued to be regulated. Generation was deregulated to enable competition. This change was fundamental in the motivation to build wind farms, solar farms, etc.
The pharmaceutical companies need to be split into three segments: research and development (R&D), manufacturing, and distribution. No one company can be in more than one segment. Manufacturing and distribution are typically low-risk, low-margin businesses. They are also critical to continuing care and so will be regulated. The R&D segment is typically a high-risk, high-margin business. This will be unregulated (well, more like less regulated). Within R&D there are two means of funding. The first is the self-funding pharmaceutical industry we have today. The second kind of R&D companies are the startups financed by venture capital.
Given these segments how does the money flow to encourage innovation and discourage abandonment of established, low-margin markets. Firstly, by separating manufacturing and distribution these businesses can continue to exist and be profitable as they do not need to directly bare the costs of R&D. People, world over, continue to get sick with the same diseases!
How is R&D paid for? R&D works within a venture capitol environment. Money comes from outside the pharmaceutical industry and money comes from inside the pharmaceutical industry. The money from within the industry comes from the sale of drugs to manufactures and a royalty on retail sales. This money does not go directly to the R&D businesses. This money goes into a venture capital fund. This is one of the many funds that R&D businesses can pitch a therapy to. I do not know how the internal fund is managed. This might be a kind of utility with public oversight.
This segmentation and organization allows for the continuation of the high-risk and high-reward therapy R&D but takes out of R&D's control the manufacturing and distribution. A win for all interested parties -- and we are all interested parties in health.
Lawrence Lessig: How Money Corrupts Congress and a Plan to Stop It - The Long Now
Lawrence Lessig: How Money Corrupts Congress and a Plan to Stop It - The Long Now
Rants (aka Tweets) on resumes
A resume should not be a ouija board. Your mother might not need to understand it but I do. Make your work clear.
Your resume should tell me about the teams you were on; team size; team duration; role(s) you played; tools you used. Everything else is BS.
If your resume can't hook me on the first page the following pages are doing nothing more than annoying me.
I hope to god that I never see a 3 page resume again.
The realpath command line utility
#include <stdio.h>Save this to the file realpath.c and then build with make realpath.
#include <limits.h>
#include <stdlib.h>
int main( int argc, char** argv ) {
int i;
char _realpath[ PATH_MAX ];
for ( i = 1; i < argc; i++ ) {
if ( realpath( argv[i], _realpath ) != NULL ) {
printf( "%s\n", _realpath );
}
else {
exit( 1 );
}
}
exit( 0 );
}
Cloning a Subversion repository
# NOTE ROOT must be an absolute path
ROOT=/tmp
CLONE=$(ROOT)/clone
SANDBOX=$(ROOT)/sandbox
SOURCE=http://css-boilerplate.googlecode.com/svn/
all:
svnadmin create $(CLONE)
ln -s /usr/bin/true $(CLONE)/hooks/pre-revprop-change
ln -s /usr/bin/true $(CLONE)/hooks/start-commit
svnsync init file://$(CLONE) $(SOURCE)
svn co file://$(CLONE) $(SANDBOX)
svnsync sync file://$(CLONE)
( cd $(SANDBOX) ; svn update ; ls -l )
clean:
rm -rf $(CLONE) $(SANDBOX)
# END
Replace SOURCE with a value appropriate to you. (Here I am using a convenient, small, public repository.)