tag:blogger.com,1999:blog-52155687181934249002024-03-18T21:01:22.412-07:00Sound and FuryTom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.comBlogger24125tag:blogger.com,1999:blog-5215568718193424900.post-25677262495736337352013-06-25T10:39:00.000-07:002013-06-25T10:39:44.216-07:00Postbox: How not to do customer supportI am generally suspicious of large organizations, and I am often in areas with poor wifi access, so I have never totally bought in to the idea of relying on Gmail to keep track of my mail for me. While I do use their product, I prefer to use a Desktop client to back up my messages and give me a little more flexibility in how I use my email.<br /><br />Unfortunately I am in the minority, and desktop mail applications are dying off rapidly. Thunderbird has largely been abandoned. The developers of Sparrow have stopped working on it after Google acquired the company. Postbox is one of the few options left, and for the most part I like the product. It works cleanly with Gmail and has a pleasant interface, as my tastes go. There are a few bugs, as there are with all products, though nothing out of the ordinary.<br /><br />However, they have cut themselves off from their customers as completely as they can. If you look at <a href="http://support.postbox-inc.com/entries/21694767-How-to-Get-Help-with-Postbox">http://support.postbox-inc.com/entries/21694767-How-to-Get-Help-with-Postbox</a>, every option there is designed to avoid the burden of dealing with their customers. There is no way to report issues or even to post on a forum. A year-old message reports "we're currently evaluating a number of different Forum solutions that will enable Postbox users to collaborate and share ideas."<br /><br />Dealing with customers can be annoying; ignoring them is fatal.<br /><br />Nothing is more irritating to users than having a problem and not even being able to report it. The company has no way of learning about which issues matter to their customers, or even learning about these issues in the first place unless they themselves have the same problems. It is a damning flaw in a fine product, and it is likely to cripple Postbox going forward. I hope that they address it in the near future, though I am not hopeful.<br /><br /><br />Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-51462326019395572652013-05-22T10:40:00.000-07:002013-05-22T10:40:13.347-07:00Tales of DRMThe struggle to find a balance between the rights of artists and the rights of their customers seems to be ongoing. Each new medium seems to go through a struggle before the balance is found. Music seems to have settled, or at least to be quiescent. Video and books are still a little more turbulent.<br /><br />Rewarding artists for their efforts is important, but in my own experiences, DRM-free content has been a great tool for making me aware of new content <i>and getting me to part with my hard-earned dollars.</i> On the other hand, content locked down has driven me away from some purchases. Some examples:<br />
<ul>
<li>MP3.com first introduced me to a huge variety of independent music. Through that site, I developed a taste for Celtic music and ordered albums from a dozen artists that I would never have come across otherwise. In one particular case, I discovered a band that was playing at a bar three blocks from my apartment. I went to their show and bought all three of their albums at the show. (I wept when MP3.com was destroyed).</li>
<li>On another front, I have stopped buying videos from iTunes due to issues with DRM. My previous apartment complex provided pathetically slow download speeds, so streaming videos were not a realistic option. But when I purchased an HD version of "Downton Abbey" through iTunes, I discovered that I was unable to play it on my screen. Emailing support, they nicely informed me that I would have to buy an Apple monitor. In the meantime, I could watch the content I had purchased on my iPhone...</li>
<li>While I have paid for locked-down content on my Kindle, my purchase of tech books has skyrocketed since I discovered several sites that sell their content DRM-free. The Kindle works great, but for technical books I like to read them and mark them up using iAnnotate on my iPad.</li>
</ul>
The internet provides a wonderful way for consumers to find new content, but the freedom for customers to use that content on the devices of their choosing can be an important selling point. DRM too often restricts many important use cases.<br /><br />Of course, lack of DRM on a product can lead to an increase in casual piracy. I came across a PDF of <a href="http://www.lua.org/pil/">Programming in Lua</a> by Roberto Ierusalimschy. After reading through it for a bit, I noticed "Prepared for [name redacted]" written across the bottom of each page. With a pang of conscience, I deleted the PDF.<br /><br />Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-38068396780817347432013-04-14T21:59:00.000-07:002013-04-15T09:09:54.535-07:00Reading "Zorro"Today I finished my Amazon.com preview of Isabelle Allende's "El Zorro". I am not a native Spanish speaker, so this is s significant accomplishment for me -- I've read roughly 10% of the book.<br />
<br />
I have always been a fan of swashbuckling tales, and I wanted to develop my Spanish, so this book was an obvious choice. I bought a paper version of the book 7 years ago, shortly after it came out. As of this last Christmas, I had made it through about 4 pages with a supreme amount of effort. It is not that the story was not engaging, but my Spanish was simply not up to the task. With a thick Spanish-English dictionary in hand, it would take me roughly an hour a paragraph.<br />
<br />
So what changed? Did I suddenly move to Mexico? Spanish immersion classes perhaps? Nope. I got a Kindle for Christmas.<br />
<br />
I bought a Spanish-English dictionary for the Kindle, and with that in hand, looking up a word just involves a click of a button. It has made more of a difference than I ever expected. Starting from the beginning again, I had passed up my old position in an evening, and completed the first chapter in a weekend. I have not read every day or even every week, but nonetheless after 3 and a half months, I have finished my sample.<br />
<br />
I have now purchased the book, and I am expecting to speed up even more. Previously, the dictionary lacked several words, and the translation option was disabled for a book sample. I ended up losing time trying to deduce an unknown word by context. Now I can translate whole paragraphs with just a couple of clicks.<br />
<br />
I wonder what this will mean for the future of foreign language eduction. Will a Kindle (or equivalent) become a requirement for every serious language student?<br />
<br />Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-6804265913878225732013-01-29T15:15:00.001-08:002013-01-29T15:15:56.262-08:00Vim, Emacs, and RomeAfter visiting France, my wife and I spent a week visiting Florence and Rome before returning back to the States. The architecture of Europe is amazing. Even small towns have cathedrals about like we have Starbucks -- one on every corner. However, of all that I have seen, Rome's subway system struck me as the most awe-inspiring engineering feet that I have seen.<br /><br />That is not to say that Rome has a particularly <i>good</i> subway system. In fact, it struck me as pitiful compared to Paris or London. In Paris, the subway will take you within a block or two of wherever you want to go. In Rome, there are only two lines in the entire city, which form a giant plus. You are lucky if your destination is six or seven blocks away from the closest stop.<br /><br />The problem is that Rome has a rich and ancient history, and any time you dig twenty fit down, you will probably hit some of it. Work must stop so that an archaeological team can investigate it. In this context, it strikes me as nothing short of miraculous that someone could cut a continuous line across Rome. Twice. Whoever had the vision, the political savvy, and the sheer force of will to accomplish it is a force to be reckoned with, and a (wo)man to be feared.<br /><br />Returning home, I discussed editors with one of my friends. He and I are both editor junkies and have had phases of being Vim and Emacs fanboys. However, my friend has recently been experimenting with SublimeText. When I asked him why he was switching, he responded that it was for ease of writing extensions.<br /><br />Both Vim and Emacs are highly extensible. Both are old, even ancient as editors go. Despite the extensibility of these editors, their age makes them difficult to adapt sometimes. I was struck with a parallel to Rome and its challenges building its subway system.<br /><br />Is it possible to streamline and revitalize these editors? Or are all large, successful software projects doomed to be mired in their own histories?<br /><br /><br />Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-87228275501689527922012-11-01T01:37:00.000-07:002012-11-01T01:44:42.545-07:00Election time is coming soon. In a few more weeks, I'll be able to turn on my radio without hearing election ads. Sweet bliss...<br />
<br />
For the most part, I think everyone knows which candidates they will vote for. You like Obama, you like Romney, or you like neither and have to hold your nose when you vote. Either way, you probably were decided on your choice months ago. I know that I was.<br />
<br />
The California propositions are a different story. They are generally confusing, and often deliberately so. Personally, I am not a fan of the proposition system in general -- a lot of bad laws seem to come from good intentions. But that is another rant.<br />
<br />
When the propositions come up, I like to look at the endorsements coming from different newspapers. Each newspaper is at least a somewhat disinterested party, and it is the paper's business to understand the issues for each proposition. This time, I thought that it would be fun to go about it a little more formally.<br />
<br />
I went to Wikipedia and took <a href="http://en.wikipedia.org/wiki/List_of_newspapers_in_the_United_States_by_circulation">the list of California's largest papers by circulation</a>. I then visited each paper's website and searched for their endorsements. (I was not able to find the endorsements for the Orange County Register, Investor's Business Daily, or La Opinión). The results are summarized below:<br />
<style>
<!--table
{mso-displayed-decimal-separator:"\.";
mso-displayed-thousand-separator:"\,";}
.font5
{color:windowtext;
font-size:8.0pt;
font-weight:400;
font-style:normal;
text-decoration:none;
font-family:Verdana;
mso-generic-font-family:auto;
mso-font-charset:0;}
td
{padding-top:1px;
padding-right:1px;
padding-left:1px;
mso-ignore:padding;
color:windowtext;
font-size:10.0pt;
font-weight:400;
font-style:normal;
text-decoration:none;
font-family:Verdana;
mso-generic-font-family:auto;
mso-font-charset:0;
mso-number-format:General;
text-align:general;
vertical-align:bottom;
border:none;
mso-background-source:auto;
mso-pattern:auto;
mso-protection:locked visible;
white-space:nowrap;
mso-rotate:0;}
ruby
{ruby-align:left;}
rt
{color:windowtext;
font-size:8.0pt;
font-weight:400;
font-style:normal;
text-decoration:none;
font-family:Verdana;
mso-generic-font-family:auto;
mso-font-charset:0;
mso-char-type:none;
display:none;}
</style>
<br />
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; width: 689px;">
<colgroup><col style="mso-width-alt: 6290; mso-width-source: userset;" width="172"></col>
<col span="7" style="mso-width-alt: 1718; mso-width-source: userset;" width="47"></col>
<col style="mso-width-alt: 1718; mso-width-source: userset;" width="47"></col>
<col span="3" style="mso-width-alt: 1718; mso-width-source: userset;" width="47"></col>
</colgroup><tbody>
<tr height="13">
<td height="13" width="172"><span style="font-size: xx-small;">Proposition:</span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>30</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>31</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>32</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>33</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>34</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>35</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>36</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>37</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>38</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>39</u></span></td>
<td style="text-align: center;" width="47"><span style="font-size: xx-small;"><u>40</u></span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.latimes.com/news/opinion/endorsements/">Los Angeles Times</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.mercurynews.com/recommendations">San Jose Mercury News</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.sfgate.com/endorsements/">San Francisco Chronicle</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.utsandiego.com/news/2012/oct/07/let-the-voting-begin-our-ballot-recommendations/">San Diego Union-Tribune</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">-</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.sacbee.com/2012/10/31/4950070/sacramento-bee-endorsements-for.html">Sacramento Bee</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.pe.com/opinion/editorials-headlines/20121029-election-the-p-e-endorses.ece">The Press-Enterprise</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.fresnobee.com/2012/10/25/3042399/list-of-bees-recommendations-for.html">Fresno Bee</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.dailynews.com/opinions/ci_21871375/los-angeles-daily-news-endorsements">Los Angeles Daily News</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
<tr height="13">
<td height="13"><span style="font-size: xx-small;"><a href="http://www.presstelegram.com/opinions/ci_21871411/2012-election-long-beach-press-telegram-endorsements">Long Beach Press-Telegram</a></span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">no</span></td>
<td style="text-align: center;"><span style="font-size: xx-small;">YES</span></td>
</tr>
</tbody></table>
<br />
<br />
There is a surprising amount of consensus between the papers. For almost half of the propositions, the choice was unanimous. Here is the breakdown for different issues.<br />
<br />
Unanimous for:<br />
<ul>
<li>Prop 36: Revise 3 strikes law.</li>
<li>Prop 40: State senate redistricting.</li>
</ul>
Strong support:<br />
<ul>
<li>Prop 30: Governor's tax increase.</li>
<li>Prop 31: Legislative reforms.</li>
<li>Prop 34: End death penalty.</li>
</ul>
Contentious:<br />
<ul>
<li>Prop 32: Paycheck protection.</li>
<li>Prop 35: Human trafficking.</li>
<li>Prop 39: Out-of-state corporate tax.</li>
</ul>
Unanimous against:<br />
<ul>
<li>Prop 33: Auto insurance.</li>
<li>Prop 37: GMO labeling.</li>
<li>Prop 38: Munger tax plan.</li>
</ul>
<br />
Prop 37 is particularly interesting. Judging by the number of signs I see around town, it would seem to enjoy strong support among voters. While there have been a number of seemingly disingenuous ads attacking it, the papers raise some fairly cogent arguments against the proposition. Even the Santa Cruz Sentinel (not on the list) <a href="http://www.santacruzsentinel.com/opinion/ci_21715506/editorial-no-37-flawed-measure-could-prove-costly">opposes it</a>:<br />
<blockquote class="tr_bq">
Citizens would be empowered to sue grocers they believe to be selling unlabeled GE foods, without needing to prove any damages. Clearly, this provision would create even more lawsuits. And who would this benefit? Lawyers. That's what happened after voters in 1986 approved Prop. 65, requiring disclosure of toxic chemicals. The result has been more than 16,000 legal actions. Some were warranted, others were aimed at forcing businesses to settle quickly rather than pay for court costs. <br />
...<br />
The initiative may be well intentioned, but it creates more problems than it solves. Vote no on Proposition 37.</blockquote>
<br />
The comments on the article are perhaps predictable:<br />
<ul>
<li>"It just goes to show you the hands of the biggest corporations (Monsanto, Dupont, etc) reach far and wide."</li>
<li>"Who paid for this article to be published? Could it be the no on prop 37 group??"</li>
<li>"I guess when you don't have the truth on your side, your only option is to confuse people."</li>
<li>"Absolutely Irresponsible journalism."</li>
</ul>
<br />
Politics as usual. :-)Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-53239787473014471562012-07-20T16:25:00.002-07:002012-07-20T16:25:44.810-07:00Why is there an app for that?I've noticed a disturbing trend lately when I browse the internet with my iPhone or iPad. It seems like every site that I visit wants me to download their custom iPhone/iPad app. <a href="http://itunes.apple.com/us/app/san-jose-mercury-news-for/id479955259?mt=8">News</a> <a href="http://itunes.apple.com/us/app/sfgate.com-for-iphone/id458081345?mt=8">sites</a> <a href="http://itunes.apple.com/us/app/the-miami-herald/id366466705?mt=8">seem</a> <a href="http://itunes.apple.com/us/app/wall-street-journal-mobile/id311822183?mt=8">particularly</a> <a href="http://itunes.apple.com/us/app/wash-post/id352509417?mt=8">guilty</a> <a href="http://itunes.apple.com/us/app/nytimes/id284862083?mt=8">of</a> <a href="http://itunes.apple.com/gb/app/the-guardian/id409128287?mt=8">this</a> <a href="http://itunes.apple.com/us/app/al-jazeera-english/id504847776?mt=8">quirk</a>.<br /><br />The main purpose for these apps seems to be storing data offline. If you have a number of articles cached, you can go read them in your favorite wifi-free park. Of course, many of these apps seem poorly designed.<br /><br />
<a href="http://flipboard.com/">Flipboard</a> works quite well, which eliminates any valid reason for a news-related iPhone app that I can dream up. Since it is <a href="http://www.bgr.com/2012/06/22/flipboard-android-download-launch-google-play-smartphones/">now available on Android</a>, it would seem to be much wiser for news sites to focus on creating a quality version of the site for mobile users, and leave the app development to Flipboard.<br /><br />Also, why don't browsers allow for the same functionality that Flipboard provides? If users want to be able to review content offline, shouldn't developers be given the tools to create that experience?<br />Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-48595167195122872512012-03-07T14:23:00.000-08:002012-03-07T14:23:25.564-08:00Free My PhoneSprint is a distant third in the iPhone market. In a somewhat desperate move, they have launched a series of ads about their unlimited data plans.<br />
<br />
<i>crickets.</i><br />
<br />
I still have unlimited data with AT&T. I have not exactly been ecstatic about the service, but I have stayed with them. Verizon seems to be more popular these days, but AT&T has marginally better coverage in the areas I care about. More to the point, switching plans is a marginal pain, and I have never seen a reason to bother.<br />
<br />
Is unlimited data worthwhile to me? No. I'd drop it in a heartbeat if a better offer came by. So what would it take?<br />
<br />
UNLOCK. MY. PHONE.<br />
<br />
I paid for an expensive phone and I cannot take it with me we when I change networks. That irritates me immensely. Sprint, unlock my phone, and I'll switch to your network in a heartbeat.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-82856574824781450732012-01-04T16:11:00.000-08:002012-01-04T16:11:06.861-08:00The Ethics of PiracyI'm not especially interested in the strict legality of "piracy". The information age has put the rights of artists and the rights of end users into conflict. The courts and the legislatures of the world are working on sorting it all out. Things will change, and a new balance will be established. I have definite feelings about what the balance <i>should</i> be, but in the meantime, what is the path of the righteous?<br />
<br />
I have watched movies and TV shows online for free. When possible, I try legitimate channels. I am a fan of Hulu and Netflix. Some networks make their shows available online. However, there are times that legitimate channels do not work. Either the show is not available for free, or there are absurd restrictions.<br />
<br />
While I was in France, I was not able to watch several shows online since I was not in the United States. Why should that matter? Why should the pilot of the Walking Dead only be available to me if I am in the United States? Companies are free to make their content available to whomever they wish, though the restriction does seem odd.<br />
<br />
I have DVDs in my collection with Chinese subtitles. I have watched movies on YouTube that are almost certainly not authorized. Where should I draw the line?<br />
<br />
Entertainment companies have been vicious in protecting their cartel. I have little love for them, and I have no ethical qualms about removing their restrictions for materials that I have purchased. Nonetheless, my actions have not always been ethical.<br />
<br />
Is it ethical to buy DVDs from China? Is it ethical to watch YouTube videos of copyrighted material? I believe that the answer is no.<br />
<br />
Is it ethical to support a corrupt system that is taking away the rights of its users? I am not totally sure. For the time being, it seems the lesser of two evils.<br />
<br />
Perhaps the best bet is to limit yourself to free material. Libraries make a great deal available. Video rentals are cheap.<br />
<br />
We live in dangerous times. We need to be vigilant for our rights, and respectful of the rights of others. The convenience of the internet makes it easy to violate both.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com1tag:blogger.com,1999:blog-5215568718193424900.post-83246737359764616132011-10-12T07:48:00.000-07:002011-10-12T07:48:56.023-07:00I have a Hidden Markov Model... Now What?I have been working on creating hidden Markov models (HMMs) for computer viruses. Now that I have them, I'm running into an interesting complication. Namely, what can I do with them?<br />
<br />
With an HMM, you can get the statistical probability for any particular series of observations. For a very simple case, consider a loaded die. 50% of the time, it will roll a 6. Otherwise, it will roll a number between 1 and 5 (10% chance each). Once you have your model built up, you can determine the probability of a series of rolls.<br />
<br />
So, continuing the example, pretend that you observe 10 sixes being rolled in succession. What are the odds that this sequence would have been rolled with the loaded die? (1/2) ^ 10, or 1 in 1024. Given these observations, is it likely that you are using the loaded die?<br />
<br />
Well... it depends. What are the other models? The probability for the same sequence with a fair die would be 1 in 6,0466,176. On the other hand, if you suspect that the die might be loaded so that it rolls sixes 90% of the time, the observations fit much better with that model.<br />
<br />
My first exposure to HMMs was in linguistics. I built up two language models for classified advertisements -- one for Spanish and one for English. By comparing the probabilities of any random classified ad, I could guess fairly easily whether an ad were English or Spanish. But if it happened to be in French or Vietnamese, my tool would have failed miserably. (On a side note, one of my friends faced with a similar problem for news stories used a simpler solution -- he counted the number of 'the's and contrasted that to the number of 'el's and 'la's. I never heard of a single bad identification with his approach. It goes to show, the sophisticated solution might not always be what is needed).<br />
<br />
This raises some interesting questions for me in the context of computer viruses. HMMs seem to be a compelling option for virus detection, but what do they compare against? You can imagine a series of models built for different virus families, but what if the file is not a virus? It does not seem realistic to build a model for 'all benign programs'. Neither does it seem realistic to build a model for each type of benign program.<br />
<br />
There is likely a clean, well-known solution. I just don't know it yet.<br />
<br />
Otherwise, life in Laval has been fun. My wife has arrived, and we've started to explore the surrounding town together. The Lavalloise seem to be a little shy about their town. Compared to Rennes or some of the other larger towns, perhaps Laval is a little sleepy. But somehow it is very cool to sit and have a glass of wine at the foot of an 800 year old castle. Coming from the western United States, where 100 years seems like a long time, the history of Laval is amazing.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-3686478044897847322011-09-30T08:56:00.000-07:002011-09-30T08:56:29.798-07:00The Virus WarIn <a href="http://www.esiea.fr/">ESIEA</a>, I am doing research on metamorphic viruses. It is a new area for me, so I have been reading up on lots of new material. I am fascinated at some of the gambits and defenses that are happening in the war between virus writers and antivirus researchers.<br />
<br />
In the past week, I have been experimenting with virus construction kits, octave (free version of matlab), and reading reams of papers on computer viruses, hidden Markov models, etc. I feel like I am going in about 12 directions at once. But as my master's thesis adviser once told me, "that's research".<br />
<br />
A quick history of viruses...<br />
<br />
The classic viruses were fairly easy to detect through a method known as "signature detection". Essentially, virus scanners look for a bit pattern associated with a virus to identify a corrupted file. This method is still the predominant one, but newer viruses are being designed to evade this method.<br />
<br />
"Encrypted viruses" attempt to evade scanners by encrypting the body of the virus. Typically, this would be done with a XOR operation, so that the same procedure can be used to both encrypt and decrypt the body of the virus. By itself, this approach is not especially useful -- the virus scanner can still identify the signature of the encryption/decryption code.<br />
<br />
"Polymorphic viruses" improve on encrypted viruses by mutating the decrypter function. A simple version of the signature detection approach will then fail totally. Except... Modern scanners will decrypt the virus body, and then scan the virus. (I am still a little fuzzy on how they know when to decrypt the virus body.)<br />
<br />
But polymorphic viruses point the way to a far more interesting approach. Rather than relying on encryption, "metamorphic viruses" mutate the body of the virus. This strategy can evade signature detection approaches without relying on encryption. (Interestingly, DRM systems are apparently exploring this technique to defy reverse engineering efforts).<br />
<br />
Detecting metamorphic viruses is fairly challenging. Fortunately, most of the metamorphic viruses today have not been particularly good. But some are. <a href="http://vx.netlux.org/vx.php?id=tn02">NGVCK</a> (Next Generation Virus Construction Kit) was designed (apparently) as a proof of concept. It produces harmless, but hard to detect viruses. (Its last release was in 2002 -- virus scanners might have caught up to it these days).<br />
<br />
Current research has been exploring statistical models, especially hidden Markov Models (HMM). The results seem promising, but the battle is not over. <a href="http://www.springerlink.com/content/3231224064522083/">Some research</a> suggests that attackers could tune the mutations to emulate benign files. Virus scanners are then left with the unpleasant choice of rejecting benign files or accepting some malicious files (and probably some of both).<br />
<br />
Anyway, it is an exciting new realm for me!Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-83486872500392338872011-09-25T09:21:00.000-07:002011-09-25T09:21:46.194-07:00An American in Laval<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWT96fvfjpGkcUg6WQLX66dAtj0fDnpftN2nYEH82lcu7uEzuUAGKV2sEpw8o4_74zyX07Hx94H47ceBwwsxclDM_PmYzl3hTwqhbz1j1XsKl86_x78PlyZ1hBt88qOySeMwdOJ-kyZo/s1600/IMG_0454.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWT96fvfjpGkcUg6WQLX66dAtj0fDnpftN2nYEH82lcu7uEzuUAGKV2sEpw8o4_74zyX07Hx94H47ceBwwsxclDM_PmYzl3hTwqhbz1j1XsKl86_x78PlyZ1hBt88qOySeMwdOJ-kyZo/s320/IMG_0454.JPG" width="320" /></a></div>After finishing up a fantastic summer at Mozilla, I hopped on board a plane to France to begin my 3 month odyssey abroad. I was still exhausted from the all hands meeting at Mozilla. I woke up at 4am to catch the shuttle to the airport, with a layover in Philly, followed by an hour shuttle from Charles de Gaulle to the train station at Montparnasse, followed by a 2 hour train ride to Laval, finally to arrive at my destination at about noon the following day. I think I am just finally catching up on sleep now.<br />
<br />
I have been in France for almost a week, and I've been overwhelmed by my reception. The people here have been uniformly friendly, and have gone out of their way to make me feel welcome. The town of Laval is lovely, and the food has been delicious.<br />
<br />
The Saturday market in Laval was overwhelming. In California, we have farmer's markets, but these are pitifully small compared to Laval. There was fresh-baked bread, giant tubs of paella, seafood so fresh that it was literally trying to escape, and produce that has to be seen to be believed. I think the produce section alone would be equivalent to 3 or 4 farmer's markets back home. I think I will enjoy my time here.<br />
<br />
So far, the biggest difference that I have noticed is that there is a sharp divide between work and play. In the states, we buy huge cups of coffee and take them to go so that we can go back to work. Half the time, 'work' might consist of Facebook and Farmville, but the pressure to be at our desks is very strong.<br />
<br />
In France, cups of coffee are small, and no one gets them to go. You sit and chat with friends, and when you are finished, you go back to work. And then you work. I'm not sure who comes out ahead in terms of production, but I am gaining an appreciation for the French approach.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0Mayenne, France48.077863 -0.7701379999999744547.660565 -1.3649534999999746 48.495161 -0.1753224999999744tag:blogger.com,1999:blog-5215568718193424900.post-61875476249010111472011-02-15T17:27:00.000-08:002011-02-15T17:27:13.495-08:00Counting Tiger Vim Fu, Macro Monkey Vim FuIn my travels, I have seen many masters of their text editors, but none to match the masters of the ancient and complex art of Vim Fu. In contrast to the arts from <a href="http://www.eclipse.org/">The Land of The Darkened Sun</a> or the <a href="http://www.embarcadero.com/products/jbuilder">Builders</a>, the art of Vim Fu has great subtlety and variety. If you were to see two different masters of Vim Fu, you might not even realize that they were practicing the same art. And so, in this article, I attempt to chronicle several of the more common types of Vim Master that you may encounter.<br />
<br />
The <b>Counting Tigers</b> have a straightforward, powerful style. With a near Rain Man like ability to count at a glance, practitioners of this style will frequently use commands like <span style="font-family: "Courier New",Courier,monospace;">5dd</span> or <span style="font-family: "Courier New",Courier,monospace;">2y{</span>. To Counting Tigers, the world may be broken up into units and numbers.<br />
<br />
The masters who follow the <b>Path Of One Thousand Stars</b> (though they use an equal number of question marks, pluses, dots, and other meta characters) eschew the straight-forward approach of the Counting Tigers, instead opting for the elegance of patterns. Their forte will be commands like <span style="font-family: "Courier New",Courier,monospace;">yt,</span>. And <span style="font-family: "Courier New",Courier,monospace;">:%s/old/new/gc</span> is deeply ingrained into their muscle memory.<br />
<br />
The <b>Masters of the Hidden Mark</b> rely on <span style="font-family: "Courier New",Courier,monospace;">mx</span> and <span style="font-family: "Courier New",Courier,monospace;">'x</span> extensively, whereas the Counting Tigers would remember the line number and type <span style="font-family: "Courier New",Courier,monospace;">166G</span>. <b>The Visionaries</b> rely extensively on visual mode, highlighting relevant sections and applying their commands to all the region. Members of this clan frequently rely on column mode editing, an art that other masters often see as being of little value.<br />
<br />
<b style="font-family: inherit;">The Way of the Macro Monkey</b> leads practitioners to define mini programs of character sequences, constantly creating ephemeral, custom scripts to achieve their goals. <b>The Pure</b> take this craft to another level, constantly redefining the basic art of Vim Fu to the point that it is not recognizable by other Vim Fu practitioners. Their <span style="font-family: "Courier New",Courier,monospace;">.vim/plugin/</span> directories may have thousands of <span style="font-family: "Courier New",Courier,monospace;">.vim</span> files. They can also be readily identified by their fierce, nearly fanatical refusal to use any other tool.<br />
<br />
In great contrast to The Pure, there are a number of <b>Wandering Masters</b>. While Vim is their first weapon of choice, they will use Eclipse, NetBeans, or any other tool that makes their task easier. They eschew the more esoteric features of Vim Fu, instead seeking to synthesize features of other arts with the core basics of the Vi Path.<br />
<br />
Here I feel I must make a special mention of the masters of the <a href="http://www.emacswiki.org/emacs/ViperMode"><b>Viper Clan</b></a>. Though not proper Vim Fu masters, they seek to join the great art with techniques gleaned from the masters from the strange, twisted lands of Emacs. Some consider their art an abomination. Others hope that they will bring civility to Emacs. Yet others prophesy of a chosen one that will at last bring true peace and unity to the House of Vim and the House of Emacs.<br />
<br />
Lastly are those of "No Style". Borrowing from <a href="http://www.fightingmaster.com/masters/brucelee/quotes.htm#On%20JKD%20not%20being%20a%20style">the philosophies of Bruce Lee</a>, these rare few strive to master all aspects of Vim Fu, and yet limiting themselves to no one approach. These masters can do things with their Vim Fu that seem magical even to other Vim Fu masters. While it is not meant for all of us to truly master the art of Vim Fu to this degree, by aspiring to perfection, and constantly extending our mastery of our craft, we can become better practitioners of the Noble Art.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-52903671223723598822011-01-28T12:14:00.000-08:002011-01-28T12:14:16.513-08:00Switching to LaTeXI am giving up on Word. After many years of use, I've gotten too irritated with its many quirks. The final straw for me was when it inserted section breaks in the middle of my novel and would not let me delete them.<br />
<br />
So instead, I am now using Aquamacs and LaTeX. When I started the process of converting over my novel, I was not sure if it was really a good idea. LaTeX is great for technical papers (especially greek-letter heavy ones that we are so fond of in programming languages research), but I was not sure if it would really offer much for a fiction writer.<br />
<br />
Almost immediately I found the benefits. Although there are some hassles, the precise control of formatting is fantastic, and that alone makes the trade very worth while. Also, being able to use my vi key bindings with emacs viper mode has been a true delight. And I can actually track my changes through source control.<br />
<br />
It has also been interesting what I have <i>not</i> found useful. I had expected that variables would be a useful feature. For instance, I could make a command for a character's name, and then allow myself to change it easily if I thought of a better one. I tried this for one of my characters briefly, but found it to be more of an irritation than anything else.<br />
<br />
But there is one feature that I did not give much thought, and yet has me fully committed to a life using LaTeX for all of my non-technical documents. And that is comments....<br />
<br />
It seems so obvious now, but before I had a wide variety of text files and hand written note-cards; all of these have been collapsed into the .tex file itself. I use simple line comments for things like 'fix up this section' with no worries about cluttering up the document for anyone I ask to review it. For more complex notes, like outlines and lists of my characters, I make new commands. When I set the command to do nothing, the notes are invisible. But when I change it to output the text, I can share those details with anyone who wishes to review it.<br />
<br />
LaTeX is not a program for everyone. But if you are familiar with it, don't be afraid to use it for less technical documents. Many of the same benefits will still carry over.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-82359967222868121682010-08-13T15:53:00.000-07:002010-08-13T15:53:39.751-07:00Narcissus addon availableToday I uploaded a plugin for Narcissus JavaScript. Details can be found <a href="http://www.bias2build.com/narcissus/">here</a>.<br />
<br />
It requires Firefox 4, so to test this out, you will need to build from source for the time being. Longer term, the plan is to swap out the JS engine at will. But, it is at least usable for experimenting currently. Enjoy!Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com2tag:blogger.com,1999:blog-5215568718193424900.post-31800629456934170812010-07-20T18:59:00.000-07:002010-07-20T18:59:31.994-07:00More Awesomeness: jstests.pyIn working with Narcissus, I've uncovered a jewel of a resource in Mozilla's <a href="https://developer.mozilla.org/en/SpiderMonkey/Running_Automated_JavaScript_Tests">JavaScript unit tests</a>. The value of unit tests is well understood. The most critical quality, however, is that they are maintained. Mozilla has done an exemplary job of this. The unit tests are constantly growing. As I write this, there are just shy of 3000 unit tests. All of them pass with the Tracemonkey engine.<br />
<br />
The organization of the tests is well thought out. Each version of JavaScript has its own test directory. So if you don't care about certain batches of tests, it is easy to ignore them.<br />
<br />
Unfortunately, as with many other things at Mozilla, there is an abundance of out of date documentaion. The JS Test Library page refers to a Perl script, which appears to be more or less abandoned. Instead, there is a python script <a href="https://developer.mozilla.org/en/SpiderMonkey/Running_Automated_JavaScript_Tests">'jstests.py'</a>, written by <a href="http://blog.mozilla.com/dmandelin/">Dave Mandelin</a> in his copious amounts of free time. Unfortunately, the old version of unit testing documentation comes up first when searching for it on Google. Alas.<br />
<br />
One thing that is sadly <i>not</i> emphasized is just how easy it is to plug in a different engine to use these tests. In fact, I have a <a href="http://hg.mozilla.org/tracemonkey/file/6d7b95761119/js/src/njs">"shell" for Narcissus JS</a>, written in 30-some lines of Python code.<br />
<br />
To hook into the testing framework, you need a "shell" that supports two command line options:<br />
1) <b>-e</b>, which interprets a string of JavaScript code.<br />
2) <b>-f</b>, which handles a JavaScript file.<br />
It must be possible to support multiple files and strings of code, though this is not a particularly difficult challenge.<br />
<br />
Some tricks:<br />
<ul><li>The -m option will let you specify your own module of JS tests. This is also a convenient way to insert a little JavaScript into the testing process to handle tests relying on non-standard JS features.</li>
<li>The -x option allows you to ignore a list of tests. Since Mozilla includes tests for special Firefox-only features, you will want to use this.</li>
<li>The --failure-file option will write the failing unit tests to the specified file, useful as input for the -x option.</li>
</ul><br />
On another note, Narcissus now runs without special extensions in Firefox 4. Huzzah! Now to make it interact smoothly with the DOM...Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com6tag:blogger.com,1999:blog-5215568718193424900.post-15490075950678894742010-06-24T18:28:00.000-07:002010-06-24T18:44:16.700-07:00<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6zM2q8qt9H1vw_O5onyPZu2tlqrLk9JwFYWaGgF_iYdIUTnJvsZq1yXQy8OlpGOTfoipbuJLGalFAEMnv1JvUR3zhfivoP_6NpxMgE-2_BBuNnesmXHrlgXrF1HSzKmWBYSuIAGwtR8/s1600/IMG_0142.JPG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5486517974714999634" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6zM2q8qt9H1vw_O5onyPZu2tlqrLk9JwFYWaGgF_iYdIUTnJvsZq1yXQy8OlpGOTfoipbuJLGalFAEMnv1JvUR3zhfivoP_6NpxMgE-2_BBuNnesmXHrlgXrF1HSzKmWBYSuIAGwtR8/s200/IMG_0142.JPG" style="cursor: pointer; float: right; height: 200px; margin: 0pt 0pt 10px 10px; width: 150px;" /></a><br />
This summer I am working at Mozilla. It is an awesome, awesome place to be. The people here are friendly and amazingly bright. Plus there is a dinosaur in the lobby. How can you beat that?<br />
<br />
My work has been looking at Narcissus JavaScript. Narcissus is a JavaScript implementation written in JavaScript, and as such, it is an ideal vehicle for playing around with the language.<br />
<br />
Narcissus relies on a few special extensions, which require a special build. It is not hard to build, but it is not all that well documented either. Here is the process that I use (in OSX):<br />
<br />
<span style="font-family: courier new;"> $hg clone http://hg.mozilla.org/tracemonkey/</span><span style="font-family: courier new;"><br />
$cd tracemonkey/js/src/</span><span style="font-family: courier new;"><br />
$autoconf213</span><span style="font-family: courier new;"><br />
$./configure --enable-narcissus</span><span style="font-family: courier new;"><br />
$make</span><br />
<br />
With that, you are good to go. From the command line, <span style="font-family: courier new;">./js</span> will give you a tracemonkey shell. Here, you can use <span style="font-family: courier new;">evaluate(prog)</span> to test out narcissus.<br />
<br />
With some adjustments, Narcissus should run within a standard Firefox build. I am down to a handful of failing unit tests. After that, running Narcissus within a browser should be as simple as loading the Narcissus js code.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com9tag:blogger.com,1999:blog-5215568718193424900.post-703524040349589412009-12-17T16:35:00.000-08:002009-12-17T16:43:40.277-08:00NetBeans -- The Least Terrible IDEMy favorite text editor is <a href="http://code.google.com/p/macvim/">MacVim</a>. It lays a nice Aqua interface over the top of the classic editor. It is not perfect. I could rant for hours on its shortcomings, but it is still a shorter rant than I have for <a href="http://aquamacs.org/">Aquamacs</a> and <a href="http://macromates.com/">TextMate</a>, and these are the only two other text editors that I find even usable.<br /><br />But text editors and IDEs are not the same thing, despite the fact that they do many of the same tasks. When I start working with a Java or Scala project, I want the advanced functionality that a full-featured IDE offers. (And yes, I am aware of <a href="http://eclim.org/">Eclim</a>, but that does not really change the fact that an IDE has been brought into the process.)<br /><br />I have played around with a number of IDEs over the years; I have yet to settle on one. <a href="http://www.eclipse.org/">Eclipse</a> is the classic, with extensions and plugins for about everything. Now that <a href="http://www.jetbrains.com/idea/">IntelliJ</a> has an open-source version, I have been spending a good deal of time with that. Nonetheless, <a href="http://www.netbeans.org/">NetBeans</a> is still, in my opinion, the best.<br /><br />It is not that it is the prettiest. In fact, it is by far the ugliest of the three on any other system besides OSX, and still not that pretty even then.<br /><br />It is not that it has the best Scala plugin. While I have had more success with the NetBeans plugin than the Eclipse one, I have found IntelliJ's to be more full-featured (albeit a little more of a hassle to install, since the version offered through their plugin manager does not seem to work. But that is another rant...).<br /><br />And while I love some of the plugins available (the <a href="http://jvi.sourceforge.net/">jVi</a> plugin in particular being the best vi emulator that I have seen for any IDE or editor), they still pale compared to the wealth offered by Eclipse.<br /><br />No, these are pluses, but relatively minor points. The reason that I keep returning to NetBeans, in a word, is <a href="http://ant.apache.org/">Ant</a>.<br /><br />There is a fantastic article by Jeff Atwood titled <a href="http://www.codinghorror.com/blog/archives/000988.html">"F5 is not a build process"</a>. This comes close to the core of the issue: every project should have a build process that functions outside of the IDE. This is a problem I have seen even with some open-source projects. Instructions like "start up NetBeans" or "download the Eclipse plugin" should never appear for any tool that is not specific to an IDE.<br /><br />Unlike Eclipse and IntelliJ, NetBeans does not have its own special build tools. It defers this to Ant (or yes, you can use Maven instead). As a result, the build process is available outside of NetBeans. In my experience, projects designed with the other IDEs only create a build process as an afterthought.<br /><br />This is huge. It means that the IDE actually takes care of the build process for you, as is just and proper. It also, however, allows you some extra options when things go wonky.<br /><br />I do some weird things with my IDE. Using Scala is one of the more tame uses, but even that can start causing problems when you combine it with Antlr or JavaCC. And God help you if you want to add unit tests into this mix. I have managed to confuse and break every IDE I have used, to one degree or another. (To be fair, IntelliJ has generally handled more weird stuff than the others).<br /><br />The beautiful thing about NetBeans is that when it stumbles, it can still function. For one project, NetBeans gave me hundreds of spurious errors, but the build process still worked.<br /><br />NetBean's generated ant files include a number of hooks where you can add in your own ant tasks, a feature that I have found invaluable. Furthermore, if something in NetBean's ant files is horribly broken, you can replace it with your own; not something that I would recommend, but it can save you in extreme cases.<br /><br />And so, despite NetBeans numerous quirks and limitations, I still list it as my favorite IDE. And while I believe the NetBeans team will address the product's current limitations sooner or later, I doubt that either the IntelliJ or Eclipse teams will ever fix what I see as a fundamentally broken architectural decision.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com13tag:blogger.com,1999:blog-5215568718193424900.post-2438685837639723852009-04-20T12:33:00.000-07:002009-04-20T12:49:24.587-07:00What main method?I've been looking for an excuse to learn more Scala for a while. Currently, I am working on implementing the <a href="http://www.cis.upenn.edu/%7Ebcpierce/tapl/">TAPL</a> interpreters in Scala.<br /><br />I ran into a problem that took me a while to figure out. To illustrate, I'll give a simple example. Consider this main method:<br /><br /><span style="font-family: courier new;"> def main(args: Array[String]) = {</span><br /><span style="font-family: courier new;"> var sum = 0</span><span style="font-family: courier new;"><br /> for (s <- args) {</span><span style="font-family: courier new;"> sum += s.toInt</span><span style="font-family: courier new;"> }</span><span style="font-family: courier new;"><br /> if (args.length > 0) {sum/args.length} else 0</span><span style="font-family: courier new;"><br /> }</span><br /><br />This simply averages a list of numbers specified from the command line. But when I try to run it, I get this error:<br /><br /><span style="font-family: courier new;"> Exception in thread "main" java.lang.NoSuchMethodError: main</span><br /><span style="font-family: courier new;"> Java Result: 1</span><br /><br />With a very slight change, this will work:<br /><br /><span style="font-family: courier new;"> def main(args: Array[String]) = {</span><span style="font-family: courier new;"><br /> var sum = 0</span><span style="font-family: courier new;"><br /> for (s <- args) {</span><span style="font-family: courier new;"> sum += s.toInt</span><span style="font-family: courier new;"> }</span><span style="font-family: courier new;"><br /> println(if (args.length > 0) {sum/args.length} else 0)</span><span style="font-family: courier new;"><br /> }</span><br /><br />This just prints out the average, no complaints.<br /><br />So what is the difference? Why does printing out the result make a difference? The answer requires a little understanding of the way that Scala works.<br /><br />Scala relies on <span style="font-style: italic;">type inference</span>. This means that it tries to determine the types of your variables (including methods) from analyzing your program. This is not the same as dynamically typed languages like Perl or Ruby -- the type checking is still done at compile time. The compiler is smart enough to infer the types of your variables from the context.<br /><br />But there is a problem here. It also has <span style="font-style: italic;">implicit returns</span>. The program will automatically return the last executed expression in the program. This has been a popular feature in many programming languages, including the Lisps, Ruby, and the various ML dialects (of which Scala itself is something of a shirttail cousin). Personally I despise this feature, but I am in the minority.<br /><br />Combining these features with Java programmer expectations leaves a nice little trap. The main method must not return anything. (Or if you rather, its return type must be Unit). If we copy the second version into the interpreter, we will see this:<br /><br /><br /><span style="font-family: courier new;"> main: (Array[String])Unit</span><br /><br />The second version works because it prints out the results -- println has a return type of Unit. However, the if statement in this example has a return type of Int. The first version of the program, although it looks nearly identical, has a different type:<br /><br /><span style="font-family: courier new;"> main: (Array[String])Int</span><br /> <br />As a result, Scala looks for <span style="font-family: courier new;">main: (Array[String])Unit</span> but cannot find it and returns an error message. This is easy to fix:<br /><br /><span style="font-family: courier new;"> def main(args: Array[String]): Unit = { ... }</span><br /><br />Or better yet, we can just remove the equals sign from the original:<br /><br /><br /><span style="font-family: courier new;"> def main(args: Array[String]) { ... }</span><br /><br />Interestingly, the original version actually catches a problem in my code; I am calculating an average, but then I do nothing with it. More often than not, if you see this error, you are probably doing something wrong -- why calculate a value for no reason?<br /><br />Still, when you are learning a language, a stumbling block like this can be confusing. The error message is clear enough to anyone who understands Scala. My only suggestion would be to add a special case for main specifically. It is a slight hair in the implementation, but it can save clueless newbies (like me) a little frustration, and really... what other kind of method would be named "main"?Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-47796708213150680002008-08-26T15:52:00.000-07:002008-08-26T16:10:01.694-07:00Building Hyype.net with Helma Object PublisherToday, <a href="http://www.hyype.net/">Hyype.net</a> was launched. Hyype.net is a micro-blogging sports site. It is designed to encourage loud, boisterous, trash-talking about each others favorite teams. We have some ideas of where we'd like to expand to, but the first part is completed and live.<br /><br />This blog entry is not about Hyype.net though. This is about <em>building</em> Hyype.net, and more specifically, about my experiences with <a href="http://helma.org/">Helma Object Publisher</a>. Helma is a web-development framework using Mozilla's Rhino JavaScript as the server-side language.<br /><br />Disclaimer: I am not an expert at using Helma. There may be better ways to organize things. Hopefully, some of the Helma guys will step in and point out where I did things the stupid way. This entry is about a newbie's experience learning the framework and building something useful with it.<br /><h1>Getting Started</h1>After having struggled with installing a number of different frameworks, Helma was absolute bliss to get up and running. Inside of a minute I was able to download it, configure it, and get it running. At that time, I was presented with this:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtMsjTqVjL6fvqE9L9rtaUZAs9Nj2PxTCBmyF5D7e4N7M503pLivuFS2vztAH_7h5gKWx6BJBAlXRGaJGtI6OZ7ZgdPsh1rqTp-g29Q-7wBYUEQe3GgQkZJQuE9LnyXOi9n8y0vCsimRU/s1600-h/basePage.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtMsjTqVjL6fvqE9L9rtaUZAs9Nj2PxTCBmyF5D7e4N7M503pLivuFS2vztAH_7h5gKWx6BJBAlXRGaJGtI6OZ7ZgdPsh1rqTp-g29Q-7wBYUEQe3GgQkZJQuE9LnyXOi9n8y0vCsimRU/s400/basePage.png" alt="" id="BLOGGER_PHOTO_ID_5238964093493470018" border="0" /></a><br />It was a powerful feel-good moment. Not only was it easy to get up and running, but I was presented with something that was <em>actually useful</em> instead of some stupid splash page. This page also has links to <a href="http://helma.org/docs/tutorial/">a tutorial</a> and <a href="http://helma.zumbrunn.net/reference/">documentation.</a><br /><br />The tutorial was a great place to start, and after an hour of going through that, I felt like I knew what to do.<br /><h1>HOPped up on objects</h1>At about this point, my romance with Helma began to sour. <em>What exactly is a HopObject? Why is there 'Root' and 'Global'? Why the @#$@! do my macros work here, but not there?</em><br /><br />The organization of a Helma project at first seems bizarre. Combined with some subtle differences in how functions work (<em>Why doesn't renderSkin() work like this.renderSkin()?</em>), I slowly developed the feeling that Helma was well-polished on the surface, but buggy and horribly organized. I compared it to PHP, which is about the dirtiest insult you can hurl at a Java-land framework.<br /><br />And then, all of a sudden, I got it. The pieces clicked together, the organization made sense, and I was left reeling. I had to lie down for a minute until the world stopped spinning.<br /><br />Here is the key thing you need to understand about Helma: it is an object-oriented framework.<br /><br />That might not sound like a big point. After all, most frameworks today are built with object-oriented languages and overrun with objects. But that is not quite the same thing. Take Rails, for instance. It has a clean organization with model objects, controller objects, and views (which are probably objects too—I don't really know).<br /><br />In contrast, each Helma application is one massive, amorphous object. It is like the difference between classes and prototypes. This is the type of organization that makes complete sense if you are thinking in a JavaScripty way.<br /><br />One subtle distinction about JavaScript programs is that each one runs in the global object. It has no name, we never really see it, but it is there. (This was a crucial point when I was building JOMP—top-level functions are methods of the global object and need no special handling). Helma has just taken this idea and build a web framework on top of it. <a href="http://www.bias2build.com/thesis/javascript_mop_expanded.html">My master's thesis</a> spends a great deal of time extolling the benefits of JavaScript's object system, so I was a little embarrassed that it took me so long to grock Helma's organization.<br /><br />Each folder in Helma corresponds to some type of HopObject. These folders will hold the database configuration (if needed), the actions (more on those later), the methods, and the skins (html templates).<br /><br />Global is the global object where all JavaScript objects live. Before I understood it properly, I had a fair amount of the skins stored there. Now, I have only a single macro. I'm not really sure I even need that. This is probably good form — global===bad, as <a href="http://www.crockford.com/">Douglas Crockford</a> would say.<br /><br />Root is the single massive object that <em>is</em> the web application. This was the single most crowded directory for Hyype.net. Anything that did not clearly belong to a single object ended up here.<br /><br />There is also HopObject, which serves as the parent object of all other Helma objects, including Root itself. I probably should have used this more, but this directory is empty for Hyype.net.<br /><br />Every other directory corresponds to some object specific to your application. As it turns out, Hyype.net really only needed 3: Users, Profiles, and Thread.<br /><br />For the rest of this article, remember that everything is owned by some object. A skin or an action belongs to some object—HopObjects are not passive lumps of data like they are in other webdev frameworks.<br /><h1>Persistence</h1>The core use of objects in almost any web framework is to serve as containers for data. This is easy to do in Helma. It does take some configuration, but that is pretty minimal. Here is the User configuration for Hyype.net:<br /><pre><br />_db = myDataSource<br />_table = user<br />_id = id<br /><br />username = username<br />password = password<br />email = email<br />verified = verified<br />createdAt = created_at<br />updatedAt = updated_at<br /><br />profile = object (Profile)<br />profile.foreign = user_id<br />profile.local = id<br /><br /></pre>This is a little more work than it would be in Rails, but it is not too bad. It would be nice if Helma could generate a base config, but it would really only save a minute of work. Better yet would be if it could default to the same names as the DB fields. The associations are also a little trickier than in Rails, but not bad. The documentation is fantastic, however, so I was able to figure things out without too much trouble.<br /><br />One note: In good Helma form, the database field names should have been in all caps. I ignored that, but it would have made the configuration a little clearer. With all lowercase, it is not as obvious which side is which.<br /><h1> HACking something together</h1>Every action corresponds to a url. While there are different ways to do it, the standard approach (and the one I used) is to create a separate .hac file for each action. Here is a simple one:<br /><pre>res.data.title = "About Hyype.net";<br />res.data.selected = "about";<br /><br />res.data.body = this.renderSkinAsString("about");<br /><br />this.renderSkin("layout");<br /></pre><p><br /></p><p>"res" stands for "response". The data property stores the variables that your template will need. The renderSkin methods will write out the templates.<br /></p><p>I would have liked Rails' style layouts. If there is a built-in setup for this in Helma, I could not find it. Rolling my own was easy enough though. I did this by creating a skin cleverly named "layout". Within it, there is a body variable. Using "renderSkinAsString" I could fill out this spot and then render the layout itself.<br /></p><h1>Skins</h1>My last project involved JavaServer Faces. Before that, it was a PHP project. They represent the two extremes. JSF is rigid and unfriendly (and, perhaps worst of all, not html). PHP lets you do whatever you like, even things you should never, never do.<br /><br />Helma's skins take a nice middle ground. They don't allow arbitrary code, but they do allow you to call macros (special JavaScript functions). The result is that no code bleeds into the html. Some html did bleed into the code, however, but I managed to keep this relatively minimal.<br /><br />One really cool thing about Helma's organization is that objects can render themselves. They can contain their own skins. For example, Thread has templates for being rendered as clips (displayed on the left rail), details (for a more complete view of the thread), and myClip (for the "My Hyype" page). Within the main page, each thread is rendered with 'str += hyype.renderSkinAsString(clipSkin);' The current thread is displayed on the center of the page with 'res.data.body = selectedThread.renderSkinAsString("details");'<br /><br />It seems like an unusual way of organizing templates, but I found it very effective. Unlike objects in other frameworks, HopObjects know how to dress themselves.<br /><br />Here is the template for Hyype.net's threads in clip view.<br /><pre><br /> <div class="bb-box"><div class="ctl"><div class="ctr"></div></div><div class="pad"><br /> <a href="<% rootPath %><% this.posterProfileHref %>"><img src="<% this.smallPic %>" alt="<% this.poster %>" title="<% this.poster %>" class="bb-img" /></a><br /> Posted by<br /><br /> <a href="<% rootPath %><% this.posterProfileHref %>" class="lnk-green"><% this.poster %></a><br /> in <a href="<% rootPath %>main?cat=<% this.categoryName %>" class="lnk-green"><% this.categoryName %></a><br /><br /> on <% this.postedOn %><br /> <div class="comm"><a href="<% rootPath %>main?threadID=<% this.id %>&pageNum=<% request.pageNum %>" class="clip-title"><% this.title %></a></div><br /> <% this.agreeDisagree %><br /> </div><div class="cbl"><div class="cbr"></div></div></div><br /></pre><br /><h1>Utilities</h1>Helma offers a rich set of utilities as part of its core and a number of optional extensions. And if that is not enough for you, the <a href="http://dev.orf.at/trac/jala/wiki/">Jala Project</a> offers a bunch more modules. For the most part, these are well-documented and easy to use. The one time I had a problem, a note to the Helma mailing list quickly answered my question.<br /><br />One problem spot I did run into was trying to include Java code in my project. For the most part, this is not needed. Rhino allows you to call Java. However, I wanted to get the MD5 hash of a string for comparing passwords. I could not call the methods I needed in Rhino, since it was ambiguous to Rhino which method I was calling.<br /><br />I wrote the method I needed in Java, but there was no good place to store the class file. Instead, I put the class file in a jar and added it to the lib/ext/ directory. This was not the cleanest process in the world, especially since it is shared by all projects, but it did the job.<br /><h1>Deployment</h1>Once we had the application ready to deploy, life got a touch more challenging. We went off the beaten path a bit by not using Antville. Things went more or less smoothly until we tested out uploading images.<br /><br />The server crashed. We reconfigured a few things. It crashed again. After several hours of research and troubleshooting, we nailed down the problem to our version of Java. Specifically, it was using GNU's implementation, which ignored some of the flags we were passing it. I still have not totally forgiven GNU.<br /><br />While I think Helma is blameless for this, it is one risk of using a framework that is not as widely used as PHP, JSF, etc. Fortunately, the community is friendly and active, which usually more than makes up for this.<br /><h1>Conclusion</h1>Helma has gotten to be my favorite webdev framework. Given any choice in the matter, this is what I'd use for a new project. Helma seems to be in active development, and I'll be excited to see where it goes from here. If you have a new project coming up, give Helma a look.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-27947392623149553962008-06-23T17:32:00.000-07:002008-06-24T11:24:07.822-07:00Yes, We're Open90% of the time when I need some work done on my car, I take it to Sears' Automotive Center. This is despite the fact that they are usually unable to fix anything more than the basics.<br /><br />The main reason I keep going there is that it is incredibly <span style="font-style: italic;">convenient.</span> When I have tire problems driving home on a Friday night, they are open. If I want to drop my car off on a Saturday and then walk to the movie theater in the same shopping mall, I can do it.<br /><br />In contrast, the Ford dealership has generally done a better job of fixing more complicated problems. But they are only open 9-5, and they are in the middle of nowhere. I can only read outdated snowboarding magazines for so long. Also, they charge twice as much, so I take my car there only in desperation.<br /><br /><h2>Convenience Matters</h2>This should not come as a surprise. Unfortunately, the state of many software projects out there would suggest otherwise. Far too many of them have terrible installation instructions and horrid documentation.<br /><br />If you want people to use your tools, put yourself in the position of your new users. What are the pain points? Where is this confusing? You won't catch all possible problems, but the more you do catch, the more users you will be able to win over.<br /><br />I've been working on XMUltra lately. My initial efforts have largely been focused on just this part -- how to make it easy for a new user to get started. I have a ways to go yet, but I think the initial public launch had much better tips for getting started than the internal documentation.<br /><br /><h2>Eclipse vs. Emacs</h2>These two have very different strengths. Emacs is the more powerful of the too, or so the Emacs elite claim. (Not being an Emacs power-user myself, I have to take their word for it).<br /><br />Eclipse is decidedly easier to get started with. For one, it uses the standard key bindings, so that ctrl-x, ctrl-c, ctrl-v, ctrl-s, etc. all work as you would expect. In addition, it is decidedly prettier. It has nice file open dialogs and more or less intuitive preferences settings.<br /><br />Actually, <a href="http://aquamacs.org/">Aquamacs</a> comes pretty close here. It takes advantage of the fact that Macs have both a command and a ctrl key, so you can still use command-x, command-v, etc like you would in any other program, but use ctrl for emacs key sequences. It also has nice GUI interfaces overlaying the Gnu Emacs versions, so you can get decent looking file open dialogs (in addition to the regular Gnu emacs versions).<br /><br />But Emacs and all of its touted power fails miserably in actually being able to <span style="font-style: italic;">transfer</span> that power. Yes, I'm sure it is much easier to write an Emacs plugin than to write an Eclipse plugin, but that is only half of the story. After I write one, someone else has to install it, or nobody but me benefits from it.<br /><br />In Eclipse, I have to type in a url into a package manager.<br /><br />For Emacs, let's take a look at a couple of examples of installation instructions:<br /><ul><li><a href="http://jdee.sourceforge.net/install.html">JDEE</a> includes steps like "Download the latest versions of Eric Ludlam's speedbar, eieio, and semantic bovinator packages and install them on your system, each in their own directory." Great.</li><li><a href="http://www.emacswiki.org/cgi-bin/wiki/HtmlModeDeluxe">HtmlModeDeluxe</a>: "First, you must install all four modes needed. The php-mode I tested so far and which seem to work well are Turadg Aleahmad's 1.0.2 and 1.0.4. As I had several reports during the last few weeks that the current mmm-mode cvs does NOT work, I now recomment to first try..."</li><li><a href="http://www.dzr-web.com/people/darren/projects/emacs-webdev/#install-lisp">Emacs WebDev</a>: "You will need the following packages: *psgml *mmm *generic-x *php-mode *css-mode *xxml *tidy"</li></ul>Hmm... So do I have semantic bovinator installed on my system already? How do I tell? What version do I have? And, most importantly...<br /><br /><span style="font-weight: bold;">WHEN THE @#$%! DID I BECOME A FLIPPIN PACKAGE MANAGER!!!</span><br /><br />This is the single biggest failure point of Emacs. <a href="http://tromey.com/elpa/index.html">There are some attempting to fix this</a>, but one really, really, really needs to be made part of the Gnu Emacs code base.<br /><br /><h2>A Tale of Two Frameworks</h2>I'm a big fan of Rhino JavaScript. Enough so that I built a <a href="https://rhinofaces.dev.java.net/">JSF-based web framework</a> for it. I spent some time looking around at what other frameworks existed.<br /><br />One of the first I found was <a href="https://phobos.dev.java.net/">Phobos</a>. They have nice webcasts, and it looks pretty cool. But... For one, Java.net is painfully slow to load. Some might be turned off before they ever see the homepage. But if you have some patience, you might make is as far as <a href="https://phobos.dev.java.net/download.html">the download page</a> and see this in the installation instructions: "You need to have the NetBeans IDE installed."<br /><br />Wow. So in one fell swoop, the Eclipse users have already been turned away. But maybe this is just for tool support. Perhaps this will work just fine as long as Glassfish is installed. And what does the website say? <cue the crickets><br /><br />In contrast, let's take a look at <a href="http://dev.helma.org/">Helma.</a> Here we have a nice, prominent download link. After downloading it and following the instructions, I had Helma running with a useful admin tool <span style="font-weight: bold;">inside of a minute</span>. It even has a default file-system persistence setup in case you don't have a database installed. The first experience is lots of happy juju.<br /><br />So take a wild guess which framework I am using now.<br /><br />Helma takes some getting used to, but it is worth the effort. The organization is very cool... but very different. While I did some head scratching before I figured it out, I made the effort because Helma had already won me over. I <span style="font-style: italic;">wanted</span> to like Helma, and so I spent the time to find its cool features. Also, the documentation pointed out those features for me. (And seriously... If you are a Rhino fan, check out Helma -- I actually prefer it over Ruby on Rails.)<br /><br /><h2>As Simple As Possible, But Not Simpler</h2>One final note... Sometimes you cannot make things as simple as you would like. If you are building a complicated product, it may be that a complex installation is required. But challenge every pain point. Would a Rails-style sensible default be a wise move? The answer is usually yes.<br /><br />Back to my mechanic... Before Sears, I went to a private mechanic. The work was fantastic, the prices were fair, and I went there despite the hassle of driving to and waiting in the middle of nowhere.<br /><br />Unfortunately, he went out of business.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com3tag:blogger.com,1999:blog-5215568718193424900.post-36215262107709168502008-05-05T18:16:00.000-07:002008-05-08T16:49:03.243-07:00XMUltra<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJRt-35aeVjEfGLm97E4wrwADtsXO_Hud3D208X7W-_uxxcvIlFUPGcfkdV8cRnZrLtgmj98nv7okrBErSmrQTV1trt7IX3FgmKIIIXlMMKYRd0ShD44Nqa0qN6N-3j68kNe-1gqJawoE/s1600-h/xmultra_team.gif"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJRt-35aeVjEfGLm97E4wrwADtsXO_Hud3D208X7W-_uxxcvIlFUPGcfkdV8cRnZrLtgmj98nv7okrBErSmrQTV1trt7IX3FgmKIIIXlMMKYRd0ShD44Nqa0qN6N-3j68kNe-1gqJawoE/s400/xmultra_team.gif" alt="XMUltra framework team" id="BLOGGER_PHOTO_ID_5197075462286302850" border="0" /></a>Recently, XMUltra was released on SourceForge.net. This had been the feed processing engine for Knight Ridder Digital, the online division of the once-mighty Knight Ridder newspaper company. (No, we don't make talking cars).<br /><br />Although originally designed for news feeds, it was expanded for use in a number of other areas. It has acquired a fairly large number of utilities, including tools for transferring files, running scripts, compressing files, etc.<br /><br />In short, it has become to feed processing what Ant is to build processes.<br /><br />XMUltra is available at <a href="http://xmultra.sourceforge.net/">http://xmultra.sourceforge.net</a> now. If you are involved in Java-based data feed processing, you should check it out. However, I thought I'd talk a little about the history of the product today.<br /><h2>In The Beginning...</h2>Before XMUltra, KRD processed news feeds with a collection of Perl scripts, shell scripts, C code, and (for some odd reason) the print spooler. These scripts did their job, but they were becoming increasingly difficult to maintain. We were becoming a Java shop, and it was decided that we should have a Java-based feed processing engine.<br /><br />Total rewrites tend to fail. Usually, you are better off refactoring your existing code base. In this case, however, XMUltra was a complete success. It was hailed as a triumph, not only by Knight Ridder, but even by the <a href="http://www.naa.org/Resources/Articles/Tech-Ops-New-Media-Award-KRs-Multilingual-Markup/Tech-Ops-New-Media-Award-KRs-Multilingual-Markup.aspx">Newspaper Association of America</a>.<br /><h2>The Architect<span style="display: block;" id="formatbar_Buttons"><span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"></span></span></h2><a href="http://www.wwweber.com/">Wayne Weber</a> was the perfect person to head this charge. He had a clear long-term vision for the product, a passion for technology, and perhaps most critically, an amazing mind for details.<br /><br />I've thought about the best way to describe Wayne, but I think the best way is to show an excerpt of his code:<br /><pre><br />try {<br /> // Using reflection to avoid compiler warnings for "stop" (heh, heh).<br /> Class classObj = Thread.class;<br /> Method method = classObj.getMethod("stop", null);<br /> method.invoke(processorThread, null);<br />} catch (Exception e) {<br />...<br /></pre><br />My first thought was to nominate this for The Daily WTF. Except, it is not really a WTF. It can't be when there is a clear comment about what exactly he was doing. There was a section I left out that explained the reasoning for using the deprecated method.<br /><br />More importantly, it speaks to something deeper. Wayne went through some elaborate hoops just to avoid any compile warnings. Despite the large number of classes, there were absolutely zero warnings and no methods or classes without JavaDoc comments. No one else was allowed to get away with anything less than perfection.<br /><h2>Expansion</h2>XMUltra was primarily designed for news feeds. Among other things, it featured a whole plugin architecture for news feeds. However, it also had a variety of extra general-purpose utilities, and gradually we began to use XMUltra wherever we could.<br /><br />This is really where I first became involved. I extended XMUltra for processing classified ads. Writing new processors was somewhat painful at the time, but it was well worth it. Over time, through the efforts of the KRD team, XMUltra gathered a richer and richer collection of utilities.<br /><h2>Mothballed</h2>There was one problem with XMUltra. It aged. Codebases become out of date if they are not maintained. And while we spent our efforts on adding new tools, we did not have the luxury of updating the core architecture.<br /><br />It shows in a few areas. Built before log4j was well-established, XMUltra features its own custom logging framework. There was a well established bulk-test, but no unit-tests. When Java 5 was released, XMUltra went from warning-free to having several hundred warnings.<br /><br />XMUltra seemed doomed after McClatchy merged with Knight Ridder. McClatchy Interactive was a Perl and Ruby shop, and Java applications have gradually been phased out. XMUltra is still in fairly heavy production use, but it is clear that it does not have a future within the organization.<br /><br />Wayne himself has left McClatchy Interactive now. Most of the rest of the core XMUltra team was gone already. I am the last.<br /><h2>Resurrection</h2>McClatchy Interactive agreed to let me open source XMUltra. Before he left, Wayne and I spent a couple of days cleaning up the build process, stripping out MI/KRD specific components, adding some examples, and updating the documentation. It is not in perfect condition, but it is in a form ready for public consumption.<br /><br /><a href="http://xmultra.sourceforge.net/">Check it out!</a> I hope you find it as useful as I have.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com1tag:blogger.com,1999:blog-5215568718193424900.post-59496437104917343952008-03-31T23:35:00.000-07:002008-03-31T23:38:15.817-07:00OperatorsIt is fairly easy to design a flexible language. You can create any object, module, class, or function you like in most programming languages. JavaScript 1.x only has objects and functions, but can mimic the other constructs easily enough. Methods in Java are fairly limited compared to other languages, but you can emulate them easily enough with functors. Objects don't exist as a core port of all languages, but in most you can do things in an object-oriented fashion -- it just is a matter of how much you have to fight with the language to do so.<br /><br />The point is, all of these constructs are <span style="font-style: italic;">open.</span> I can create as many classes, objects, and functions as I like.<br /><br />This is not true of operators. Operators don't fit smoothly in with the rest of the language's design. Because of their unique behavior, they must be fixed at the moment that a program is parsed. This means that they are almost always closed.<br /><br />There are some interesting exceptions, however. Many languages allow operator overloading. This allows you to change the behavior of an operator and, more importanly, it allows you to apply operators to new classes. (If Java had this feature, you could add two BigIntegers with '+').<br /><br />This is only a partial solution, however. While it does let you expand the usage of an operator, you still cannot create a new one.<br /><br />The Lisp family takes a novel approach to this issue by simply not having any. As a plus, the core of the language(s) remains small, clean, and elegant. But there is a trade-off. Now, instead of being able to type:<br /><br /> 42 + 3/4;<br /><br />You have:<br /><br /> (+ 42 (/ 3 4))<br /><br />Lisp advocates will be quick to argue that Lisp's form is unambiguous, and often more concise than the infix notation that we are all familiar with. This is why Lisp people never get invited to any parties.<br /><br />Scala, however, has cleverly done away operators and yet still maintained the **appearance** of them. It does this by making both parenthesis and the dot optional. As a result, this works just fine:<br /><br /> scala> 42 + 3/4.0<br /> res2: Double = 42.75<br /><br />Despite the appearance, there are no operators. This is essentially the same statement:<br /><br /> scala> 42.+(3./(4.0))<br /> res4: Double = 42.75<br /><br />The genius of this is that operators essentially become an open class. However, what happens to the rules of precedence? That is another major complication of operators. If we reverse the order, we will most likely get 3./((4.0).+(42)), right?<br /><br /> scala> 3/4.0 + 42<br /> res3: Double = 42.75<br /><br />Hmm. So what is happening here? Well, the answer is that Scala looks at the first character of a method. If it starts with '+', it is lower in precedence than a method starting with '*'. With some clever tricks, Scala has operators that are both open and intuitive.<br /><br />So is Scala perfect? No. While it has essentially made operators an open class, it still has fixed rules for the precedence. As a result, some things are missing in Scala.<br /><br /> scala> var i = 4<br /> i: Int = 4<br /><br /> scala> i++<br /> <console>:5: error: value ++ is not a member of Int<br /> val res6 = i++<br /> ^<br />The reason for this is that the results would not be what you would expect. Consider this <span class="blsp-spelling-error" id="SPELLING_ERROR_0">pseudocode</span> statement:<br /><br /> x = 5<br /> y = 7<br /> x = x * y++<br /><br />At the end of this code, you would expect x=35 and y=8. But in <span class="blsp-spelling-error" id="SPELLING_ERROR_1">Scala</span> (if the ++ method existed) it would translate to:<br /><br /> var x = 5<br /> var y = 7<br /> x = (x.*(y)).++<br /><br />While <span class="blsp-spelling-error" id="SPELLING_ERROR_2">Scala</span> has made an impressive step, the problem is still not totally solved.</console>Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0tag:blogger.com,1999:blog-5215568718193424900.post-17131451665345378542008-01-29T17:52:00.000-08:002008-05-08T23:26:36.883-07:00Ruby BacklashI suppose it was about time. Ruby and Rails had been a little too highly touted, and now the backlash has begun. <a href="http://zedshaw.com/rants/rails_is_a_ghetto.html">Zed's blog entry</a> was the biggest slap to the Ruby/Rails communities, but there have been others.<br /><br />I love Ruby. I have never found another programming language that has been as easy to use. I've played with Lisp. I've written some small utilities in Python. I've used PHP, Java, and Perl for production sytems. In terms of pure programming pleasure, the only language that has even come close for me is Rhino JavaScript.<br /><br />As for Rails, I have my objections, but I have yet to find a framework that I like better. DHH hit on something, and there are a lot of frameworks out there that have been trying to copy the Rails formula. I've played with a number of others, but the ones I like best tend to follow Rails in the ease of DB access and the clean organization.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Ruby vs. Python</span></span><br />One common thread among the Ruby backlashers is "I already know Python". There is something to be said for this. When I started working with Ruby, I knew a little Python, but I was still just learning. If I had been introduced to Ruby a year later, it might be a different story. Python is an amazingly beautiful language, and it is hard to be wowed by Ruby after learning Python.<br /><br />Nonetheless, there are a few places where I think Ruby shines in comparison.<br /><ol><li>Regular expression support. I rely on regular expressions heavily. In data feed processing and linguistic work, they are a wonderful tool. Python has decent libraries, but... They feel tacked on. In Ruby, they are a core part of the language. Ruby is the only language I know that can go toe-to-toe with Perl in this area.</li><li>Object-oriented syntax. This is a minor point, but Python's OO syntax has always kind of bugged me. Passing 'self' as the first parameter seems, well... pretty friggin' lame. You get used to it, drink the kool-aid, and then spend your time telling everyone that "it's not a bug, it's a feature". Ruby does not have this, um, feature.</li><li>Erb (embedded Ruby). Equivalents to this exist in almost every major language these days, but the key distinctions of Erb is that it can be used from the command line. This is huge. For one example, I replaced a 2108 line XML configuration file with a 473 line erb file.</li><li>Ruby blocks. Python is only getting bashed on this point because it is first in the list... The biggest thing I miss when using other languages is Ruby's ability to pass blocks of code. Blocks are closures, and this is huge. All of the boilerplate code that you can't avoid in other languages is easy to sidestep with Ruby. (Neal Gafter's proposal for closures in Java will bring the same benefits -- I hope he succeeds).</li></ol>Now, to be fair, Python has some strengths as well. A real Python guru could probably add a few more, but these were the ones I noted from my Python experience.<br /><ol><li>Whitespace sensitive. This is often listed as a criticism of Python, and I've never been sure why. I think there is a huge value in tying the actual logic of the program to its apparent logic. We use whitespace to organize things -- why shouldn't the computer follow suit? The arguments against this seem to be a) it makes embedded Python difficult and b) tabs v. spaces becomes a real problem. Point A seems valid, but there are a number of Python web-dev frameworks out there. They must have solved it somehow. As for B... If you open a file and edit it, but don't match the whitespace, you are getting off easy with broken code. Personally, I think it a hangable offense.</li><li>No implicit returns. This is another minor point, but since I criticized Python for its OO syntax, it seems only fair to mention it. I don't like implicit returns. If I want to return something, I'll @#$! well type 'return'. I wish the rest of the Ruby community would too. It seems a bad idea to me that you are returning values when you might not mean to. What happens if others start relying on that behavior?</li></ol><span style="font-size:130%;"><span style="font-weight: bold;">Ruby vs. Java/Perl</span></span><br />Matching Java and Perl may strike many as odd. However, Ruby combines some of the best of both worlds. On the other side, both Java and Perl have the advantages that come with being well-established, fire-tested, battle-hardened languages<br /><br />What appeals to me about Ruby and Perl over Java:<br /><ol><li>Great regex support. I mentioned this under Python already. Perl is king of regular expression support. I'm vaguely aware that Perl has some extras that Ruby does not, but I could not tell you what they are. The biggest difference that <span style="font-style: italic;">is</span> noticeable is that regular expressions are objects in Ruby, which means you can set them as arguments, add methods to them, etc.</li><li>Easy to experiment with. Any project I do becomes object-oriented when it hits a decent size. However, in Ruby and Perl I don't <span style="font-style: italic;">have</span> to do so until I am ready. When I am experimenting, I can just start typing commands. When it gets a little larger, I can toss in a stand-alone function or two. When I have more that that, it is time to bring in the objects. You can't do that in Java. Your best bet then is to use <a href="http://www.beanshell.org/">BeanShell</a>.</li><li>Good support for hashes/arrays. In Java, there is some support for creating Arrays succinctly, but it is limited. There is no succinct way to create any kind of Map. In Java, you need a property file a lot sooner than you do for any other language.</li></ol>What appeals to me about Ruby and Java over Perl:<br /><ol><li>Simple syntax for objects. Perl's OO system is a bless-ed mess.</li><li>Arrays of Hashes, Hashes of Arrays, etc. One surprising complication in Perl is getting a collection out of a collection. There are so many '$'s and '%'s that it looks like cartoon swearwords. I have to look the syntax up every time that I do it.</li></ol>Where Ruby fails short of Java and Perl:<br /><ol><li>Performance. Ruby is slow. Most of the time, this is not a factor for me... But not always. Once, I wrote a part of speech tagger in Ruby. I ran it on a large amount of data, and it took well over an hour to run. I ported the code to Java. The new program was 4 times the size, but ran in about 15 minutes, which I thought was a nice illustration of the strengths of both languages.</li><li>Libraries. Java and Perl have a massive collection of libraries. Whatever you want to do, you can at least find one library for it. That is not always true for Ruby.</li></ol>Off subject, but... Perl is the only language I know of that has not been ported to the JVM. There are JVM implementations of Ruby, Python, JavaScript, and a whole mess of Lisps. A huge number of new languages have been written for the JVM. Library support is always the key. Perl's support is every bit as good as Java's, so why would anyone bother?<br /><br /><span style="font-weight: bold;font-size:130%;" >Ruby vs. Rhino</span><br />These have become my two favorite languages. Both have <a href="http://www.bias2build.com/thesis/ruby_v_js_MP.html">rich metaprogramming features</a>. Whenever I use one, I miss features from the other.<br /><br />Where Ruby rocks:<br /><ol><li>Blocks. JavaScript functions are closures, but it is not enough. As Neal Gafter would say, "you can't just slap a pair of curly-braces around it".</li><li>Class-based object system. This is likely to change soon, but Rhino currently does not use a class-based object system. Prototypes are cool. I even took advantage of this to build a <a href="http://www.bias2build.com/thesis/javascript_mop_expanded.html">metaobject protocol for JS</a>. However, classes are easier for programmers to understand. It is nice not to have to do the mind-shift to the world of prototypes. This is a minor point for me, but important for some.</li><li>Server-side programming? Or maybe not... There is <a href="http://www.blogger.com/img/gl.link.gif">Helma</a> and <a href="https://phobos.dev.java.net/overview.html">Phobos</a>, and possibly one day we will actually get to see <a href="http://steve-yegge.blogspot.com/2007/06/rhino-on-rails.html">Rhino on Rails</a>. Rails still seems to have more of the world's attention, but that could change.</li></ol>Where Rhino tramples Ruby:<br /><ol><li>JVM support. JRuby has been making rapid progress, and it could end up matching Rhino here one day. Maybe. But in a lot of small ways, JS is a lot closer to Java. Simple things like the use of CamelCase instead_of_underscores make Java programmers feel more at home.</li><li>Getting/Setting unknown variables. In JS, you can get or set a property easily if you have the variable name in a string. This is doable in Ruby, but not as easily. You need to use the 'method' method and then use the 'call' method on the returned method:<br /><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > property_to_print = :bar<br /> </span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" >f = Object.new<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > def f.bar</span><span style=";font-family:courier new;font-size:85%;" ><br /> 42<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > end<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > puts f.method(property_to_print).call</span><br /><br /> In JS, we can do the same thing more easily:<br /><span style=";font-family:courier new;font-size:85%;" ><br /> </span><span style=";font-family:courier new;font-size:85%;" > </span><span style="font-size:85%;">var propertyToPrint = 'bar';<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > </span><span style="font-size:85%;">var f = {};<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > </span><span style="font-size:85%;">f.bar = 42;<br /></span><span style=";font-family:courier new;font-size:85%;" > </span><span style=";font-family:courier new;font-size:85%;" > </span><span style="font-size:85%;">print(f[propertyToPrint]);</span><br /><br /> This seems somewhat trivial, but it comes up surprisingly frequently.</li></ol><br /><br /><span style="font-weight: bold;font-size:130%;" >Ruby on Rails Vs. PHP</span><br />Ruby is overwhelmingly better as a general-purpose language. PHP is overwhelmingly better as a framework-less web development language. A more informative comparison is to compare Rails to PHP. But this is not really fair either. Rails is a framework, and PHP is a language. It would be more even to pit Rails against CakePHP or Zend. The fundamental problem here is that I don't know either of those frameworks. But so it goes.<br /><br />PHP is unusual. It seems like half a language and half a web development framework. Initially I felt nothing but disdain for it, but I've been slowly coming to appreciate its strengths, particularly after reading <a href="http://www.manning.com/reiersol/">"PHP in Action"</a>.<br /><br />I do miss a number of Ruby's features when doing PHP. In particular, the lack of first-class functions is frustrating. PHP has create_function, but it is less than pleasant to use. Worse, it does not work for creating methods on the fly (at least not in PHP 5).<br /><br />However, when it comes to creating an initial mockup, there is no language I like better. I have a Mac, and with PHP pre-installed, I can just start typing html, embedding chunks of code where it simplifies things. It is ugly and crude, but extremely easy. The ability to get something in front of the customer quickly is tremendously useful for getting feedback.<br /><br />Once the demo hits a database, I throw PHP away and switch to Rails. There is no reason you could not use a PHP framework instead, but at this point you begin to need the clean organization that a (decent) framework provides.<br /><br />I only have one substantial application running on PHP, and I lost a lot of time re-inventing the wheel. However, I'm glad I did it. It was a great learning experience for me. With most frameworks, you are protected from the little details. With straight PHP, you can feel the bones of the web underneath. I made a number of mistakes in my design, but I'm a hell of a lot better web developer now as a result of having made those mistakes. Building a decent-sized website without the benefit of a framework is something that every web developer should do once.<br /><br /><span style="font-weight: bold;font-size:130%;" >Conclusion</span><br />So should you learn Ruby, if you don't already? That is up to you. If you are interested in Rails, or if you would like a language with strong regex support (and you don't already know Perl), you should think seriously about it. Don't be turned off by the backlash -- it comes from success.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com1tag:blogger.com,1999:blog-5215568718193424900.post-27827152936310787682008-01-08T18:39:00.000-08:002008-02-20T16:24:56.639-08:00Reinventing the WheelIn college, I met several friends who had built their own PCs. I had never so much as opened the case of mine. As a graduation present to myself, having both a little time and a little money on hand, I decided to finally build my own machine.<br /><br />It was a frustrating experience at times. Not everything went smoothly, but in the end I had **my** machine. I built it, I customized it, and I was very proud of it.<br /><br />Of course, that was several machines ago. I have not bothered to build another one. My time is too precious, and it is not something I particularly enjoy doing. Let Dell do it for me. Nonetheless, I'm glad to have done it once. I'm not afraid to work on my machines anymore, and I've upgraded them frequently. More importantly, I know a lot more about what is happening under the hood.<br /><br />Recently I've been cleaning up a PHP project. It was the first time that I put together a site without using a framework of some kind. I did just about everything wrong. I ignored the MVC pattern, and the code I put together is a total mess. (Well.... Maybe not total. My database setup is actually passable. It still shows a lack of understanding of PHP, but the organization there is clean -- swapping out MySQL for another DB should be a snap).<br /><br />Frameworks are good. If done right, they remove the drudgery from your work. You can just focus on the creative parts. Not that this ever really happens, but it is a wonderful ideal. I will never build a site without one again.<br /><br />But I'm glad I did this one. Before, I could speak at least semi-intelligently on the pluses and minuses of a few different frameworks, but I only understood them at a superficial level. Now I've gotten my hands dirty in the guts of a web application, and I'm a better web developer for the experience.<br /><br />Right now, I'm working on my own framework, extending Rhino JavaScript and JavaServer Faces. It may never hit prime-time, but I've managed to get an even deeper understanding through this project. Reinventing the wheel is a hell of a way to learn about wheels.Tom Austinhttp://www.blogger.com/profile/10364059537596441041noreply@blogger.com0