<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Bitwise Evolution</title>
	<atom:link href="http://blog.ciscavate.org/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.ciscavate.org</link>
	<description>Musings of a Seattle-area hacker with a bent on improving digital lifestyles.</description>
	<pubDate>Sun, 02 Nov 2008 06:48:41 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Treat your mailing lists like reference documents, please.</title>
		<link>http://blog.ciscavate.org/2008/11/treat-your-mailing-lists-like-reference-documents-please.html</link>
		<comments>http://blog.ciscavate.org/2008/11/treat-your-mailing-lists-like-reference-documents-please.html#comments</comments>
		<pubDate>Sat, 01 Nov 2008 00:21:09 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/11/treat-your-mailing-lists-like-reference-documents-please.html</guid>
		<description><![CDATA[I desperately needed to find out why the tutorials I&#8217;ve been following for an Eclipse PDE task today kept referencing a startup.jar file that I could not locate.

A couple google searches later turned up this link:

http://dev.eclipse.org/newslists/news.eclipse.platform/msg62159.html

The poster in that thread had the same problem (back in Feb. 2007), and found the answer, but none of [...]]]></description>
			<content:encoded><![CDATA[<p>I desperately needed to find out why the tutorials I&#8217;ve been following for an Eclipse PDE task today kept referencing a startup.jar file that I could not locate.</p>

<p>A couple google searches later turned up this link:</p>

<p><a href="http://dev.eclipse.org/newslists/news.eclipse.platform/msg62159.html">http://dev.eclipse.org/newslists/news.eclipse.platform/msg62159.html</a></p>

<p>The poster in that thread had the same problem (back in Feb. 2007), and found the answer, but none of the content in that thread makes it trivial to locate the answer again.</p>

<p>The responder (with the answer) simply included a link to another mailing list:</p>

<p><a href="http://dev.eclipse.org/mhonarc/lists/cross-project-issues-dev/maillist.html">http://dev.eclipse.org/mhonarc/lists/cross-project-issues-dev/maillist.html</a></p>

<p>Notice that that page is <em>not</em> constant.  Today, it shows the most recent posts as of October 31st, 2008.  In order to figure out what had happened to startup.jar, I had to take into account the OP&#8217;s response (&#8221;Ok so this is <em>very</em> recent.&#8221;), the timestamp on the messages (Mon, 12 Feb 2007) and then navigate the mailing list archives to find that time period, and start reading.</p>

<p>Please don&#8217;t put people through this sort of crap.  It&#8217;s generally not difficult to find permlinks to a given email, or include a quick note with the actual answer.  I have the answer now (<a href="http://dev.eclipse.org/mhonarc/lists/cross-project-issues-dev/msg00873.html">startup.jar was replaced with org.eclipse.equinox.launcher in 3.3</a>), but there is no way that I can tie that answer to the conversation I&#8217;ve linked to above.</p>

<p>For the purposes of Google:</p>

<p>If you&#8217;re having this problem:</p>

<blockquote>
I&#8217;m trying to do some automation, but I&#8217;m running into a problem with the 3.3 integration build.<br /><br />

java -cp plugins\org.eclipse.platform_3.2.100.v20070126\startup.jar org.eclipse.core.launcher.Main<br /><br />

doesn&#8217;t do anything. It doesn&#8217;t say anything. The only information I&#8217;m getting is an exit status of 13. </blockquote>

<p>Then you need to use &#8220;java -jar plugins/org.eclipse.equinox.launcher_1.0.0.v20070207.jar&#8221; (adjusting the version numbers for your installation).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/11/treat-your-mailing-lists-like-reference-documents-please.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Auto-documenting OSGi CommandProviders</title>
		<link>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html</link>
		<comments>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html#comments</comments>
		<pubDate>Mon, 20 Oct 2008 23:08:54 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[OSGi]]></category>

		<category><![CDATA[eclipse]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html</guid>
		<description><![CDATA[(Edit: If you&#8217;re reading this after OSGi R4.2, then there is almost certainly a better way to accomplish the same thing)

I&#8217;ve been digging into OSGi a bit over the last week or so inorder to
create some Eclipse plugins that will automatically discover
eachother, and I&#8217;ve been generally impressed with the framework on the
whole.  The documentation [...]]]></description>
			<content:encoded><![CDATA[<p>(<strong>Edit:</strong> If you&#8217;re reading this after OSGi R4.2, then there is almost certainly a better way to accomplish the same thing)</p>

<p>I&#8217;ve been digging into OSGi a bit over the last week or so inorder to
create some Eclipse plugins that will automatically discover
eachother, and I&#8217;ve been generally impressed with the framework on the
whole.  The documentation is a bit lacking, but there are some good
blog posts about it.  (Specifically [Neil Bartlett's introduction to
OSGi][intro].)</p>

<p>One thing that bugged me is the repetition needed when you implement
the CommandProvider interface to add commands to the OSGi console.
CommandProvider defines one method you must supply:</p>

<div class="codecolorer-container java" style="height:35px;"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span></div></div>

<p>OSGi then uses reflection to extract each of the methods that starts
with an &#8220;<em>&#8220;, and supplies those methods to the command environment as
new commands.  (The &#8220;</em>&#8221; is trimmed, and the name of the method becomes
the command name.)  General practice is to include the name of the
method in the return value of <code>getHelp()</code>, along with a description of
what the method does, eg:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> SampleCommandProvider <span class="kw2">implements</span> CommandProvider <span class="br0">&#123;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">synchronized</span> <span class="kw4">void</span> _run<span class="br0">&#40;</span>CommandInterpreter ci<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">// do stuff.</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp;<span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> <span class="st0">&quot;<span class="es0">\t</span>run - execute a Runnable service&quot;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>This seems like a pain to maintain, so I took a quick look at
annotations, and propose a new syntax:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> SampleCommandProvider <span class="kw2">extends</span><br />
&nbsp; &nbsp;DescriptiveCommandProvider <span class="br0">&#123;</span><br />
<br />
&nbsp; &nbsp;@CmdDescr<span class="br0">&#40;</span>description=<span class="st0">&quot;execute a Runnable service&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">synchronized</span> <span class="kw4">void</span> _run<span class="br0">&#40;</span>CommandInterpreter ci<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">// do stuff.</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Here we&#8217;ve extracted the <code>getHelp()</code> method into a new superclass, so
our SampleCommandProvider now extends an abstract class instead of
implementing an interface.  It also makes use of an Annotation, which
we need to define:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="co2">import java.lang.annotation.ElementType;</span><br />
<span class="co2">import java.lang.annotation.Retention;</span><br />
<span class="co2">import java.lang.annotation.RetentionPolicy;</span><br />
<span class="co2">import java.lang.annotation.Target;</span><br />
&nbsp; &nbsp; <br />
@Retention<span class="br0">&#40;</span>RetentionPolicy.<span class="me1">RUNTIME</span><span class="br0">&#41;</span><br />
@Target<span class="br0">&#40;</span>ElementType.<span class="me1">METHOD</span><span class="br0">&#41;</span><br />
<span class="kw2">public</span> @<span class="kw2">interface</span> CmdDescr <span class="br0">&#123;</span><br />
&nbsp; &nbsp;<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> description<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div></div>

<p>Finally, we just need to define the superclass that implements
<code>getHelp()</code>:</p>

<div class="codecolorer-container java" style="height:280px;"><div class="codecolorer" style="font-family: monospace;"><span class="co2">import java.lang.reflect.Method;</span><br />
<span class="co2">import java.util.regex.Matcher;</span><br />
<span class="co2">import java.util.regex.Pattern;</span><br />
<br />
<span class="co2">import org.eclipse.osgi.framework.console.CommandProvider;</span><br />
<br />
<span class="kw2">public</span> <span class="kw2">abstract</span> <span class="kw2">class</span> DescriptiveCommandProvider <span class="kw2">implements</span> CommandProvider <span class="br0">&#123;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">private</span> <span class="kw2">static</span> <span class="kw2">final</span> Pattern CMD_PATTERN = Pattern.<span class="me1">compile</span><span class="br0">&#40;</span><span class="st0">&quot;^_(.*)&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> help = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">null</span> == help<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;help = buildHelp<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> help;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> buildHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; StringBuilder helpBuff = <span class="kw2">new</span> StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m : <span class="kw2">this</span>.<span class="me1">getClass</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getMethods</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>methodIsCmd<span class="br0">&#40;</span>m<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="nu0">0</span> != helpBuff.<span class="me1">length</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;helpBuff.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; helpBuff.<span class="me1">append</span><span class="br0">&#40;</span>getDocumentation<span class="br0">&#40;</span>m<span class="br0">&#41;</span><span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> helpBuff.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <span class="kw4">boolean</span> methodIsCmd<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> CMD_PATTERN.<span class="me1">matcher</span><span class="br0">&#40;</span>m.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">matches</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getDocumentation<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; StringBuilder methodHelp = <span class="kw2">new</span> StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; Matcher matcher = CMD_PATTERN.<span class="me1">matcher</span><span class="br0">&#40;</span>m.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>matcher.<span class="me1">matches</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;methodHelp.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\t</span>&quot;</span>+matcher.<span class="me1">group</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CmdDescr description = m.<span class="me1">getAnnotation</span><span class="br0">&#40;</span>CmdDescr.<span class="kw2">class</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">null</span> != description<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; methodHelp.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot; - &quot;</span>+description.<span class="me1">description</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> methodHelp.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Note that the actual reflection on the class only happens once &#8212; all
subsequent calls to <code>getHelp()</code> use a cached copy of the documentation.</p>

<p>[intro]: http://neilbartlett.name/blog/osgi-articles/<u style=display:none></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>It&#8217;s called a docking station, Joel :)</title>
		<link>http://blog.ciscavate.org/2008/09/its-called-a-docking-station-joel.html</link>
		<comments>http://blog.ciscavate.org/2008/09/its-called-a-docking-station-joel.html#comments</comments>
		<pubDate>Mon, 22 Sep 2008 21:12:19 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/09/its-called-a-docking-station-joel.html</guid>
		<description><![CDATA[The venerable Joel Spolsky asked recently why someone hasn&#8217;t made a device that clips to the back of a desk and:


    * It&#8217;s a power strip
    * It&#8217;s a network hub
    * It&#8217;s a USB hub
    * You clamp it onto the back [...]]]></description>
			<content:encoded><![CDATA[<p>The venerable Joel Spolsky asked recently why <a href="http://www.joelonsoftware.com/items/2008/09/20.html">someone hasn&#8217;t made a device</a> that clips to the back of a desk and:</p>

<blockquote>
    * It&#8217;s a power strip<br />
    * It&#8217;s a network hub<br />
    * It&#8217;s a USB hub<br />
    * You clamp it onto the back of any desk
</blockquote>

<p>The idea being that: </p>

<blockquote>This would make it easy to plug in laptops, USB peripherals, and all your rechargers at your desk without crawling around on the floor.</blockquote>

<p>He links to a device that does some of this, and runs ~$150/device.  At that price, I think a better solution is a docking station&#8211;when you get down to it, I don&#8217;t want to plug in 4 things every time I sit down even if it doesn&#8217;t involve crawling under the desk (power, video, usb, ethernet and possibly audio).  I think it&#8217;s unlikely that all the features needed above are really necessary when you just show up for a meeting, or hop over to your coworker&#8217;s office for a short hacking session.  Many conference rooms these days already have tables wired for ethernet / power and svga video to a projector.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/09/its-called-a-docking-station-joel.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>StackOverflow: Endorsing(?) content theft from day one</title>
		<link>http://blog.ciscavate.org/2008/09/stackoverflow-endorsing-content-theft-from-day-one.html</link>
		<comments>http://blog.ciscavate.org/2008/09/stackoverflow-endorsing-content-theft-from-day-one.html#comments</comments>
		<pubDate>Tue, 16 Sep 2008 06:48:47 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/09/stackoverflow-endorsing-content-theft-from-day-one.html</guid>
		<description><![CDATA[Joel Spolsky and Jeff Atwood just launched the public beta of Stackoverflow today, with the intent of building a community for high-quality technical questions and answers.  I&#8217;ve been using the site for about three weeks now, during the closed beta, and I&#8217;ve noticed a disturbing trend that was outlined in Joel&#8217;s announcement post today:


Want [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.joelonsoftware.com">Joel Spolsky</a> and <a href="http://www.codinghorror.com">Jeff Atwood</a> just launched the public beta of <a href="http://www.stackoverflow.com">Stackoverflow</a> today, with the intent of building a community for high-quality technical questions and answers.  I&#8217;ve been using the site for about three weeks now, during the closed beta, and I&#8217;ve noticed a disturbing trend that was outlined in Joel&#8217;s <a href="http://www.joelonsoftware.com/items/2008/09/15.html">announcement post</a> today:</p>

<blockquote>
Want to know an easy way to earn reputation? Find a question somewhere with several good, but incomplete, answers. Steal all the answers and write one long, complete, detailed answer which is better than the incomplete ones.
</blockquote>

<p>The site presents an interface where much of the functionality is hidden from new users.  You can&#8217;t comment on posts, for example, until you&#8217;ve earned 50 &#8220;rep&#8221;.  Voting up takes 15 rep, voting down takes 100 rep, and each downvote you place will cost you one rep.  You gain rep by posting questions and answers that other users vote up, or accept.  The result is an addictive system that, in theory, prevents <a href="http://en.wikipedia.org/wiki/Griefer">&#8220;Griefing&#8221;</a> (the system does <em>NOT</em> prevent griefing, by the way.  It is extremely easy to game.)</p>

<p>Because of this, it is tempting to re-post successful content from other sources, and nothing the creators (Atwood and Spolsky) have incorporated into the site, or the recent announcements, has indicated that this is objectionable.  Afterall, good content on Stackoverflow will improve their service, regardless of where it came from, and regardless of whether it is properly credited.</p>

<p>After using stackoverflow for a couple weeks, I think that they have created a useful service, but I also want to call them out for providing an environment that is encouraging plagiarism.  Duplication/copying of content <em>within</em> stackoverflow does not set easy with me, but I&#8217;m willing to accept that the content I create for stackoverflow is public domain, and is free to be copied at will.  <strong>However</strong> <a href="http://stackoverflow.com/questions/17512/computer-language-puns-and-jokes#47867">these</a> <a href="http://stackoverflow.com/questions/17512/computer-language-puns-and-jokes#45355">posts</a> <a href="http://stackoverflow.com/questions/17512/computer-language-puns-and-jokes#48783">are</a> <a href="http://stackoverflow.com/questions/35809/why-are-vi-and-emacs-popular#36007">not</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/09/stackoverflow-endorsing-content-theft-from-day-one.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Breaking away from Visio</title>
		<link>http://blog.ciscavate.org/2008/09/breaking-away-from-visio.html</link>
		<comments>http://blog.ciscavate.org/2008/09/breaking-away-from-visio.html#comments</comments>
		<pubDate>Thu, 11 Sep 2008 19:18:51 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/09/breaking-away-from-visio.html</guid>
		<description><![CDATA[The &#8216;proper&#8217; way to do user interface design is hotly contested in the OSS software development world, and the discussions usually boil down to three suggestions:


&#8220;Just write it &#8212; it&#8217;s not that hard&#8221;
&#8220;Use [glade&#124;qt designer&#124;netbeans&#124;&#8230;] &#8212; all the widgets are there&#8221;
&#8220;Just use pencil/pen/whiteboard/etc &#8212; it&#8217;s faster&#8221;


I don&#8217;t agree with any of these &#8212; (1) is [...]]]></description>
			<content:encoded><![CDATA[<p>The &#8216;proper&#8217; way to do user interface design is hotly contested in the OSS software development world, and the discussions usually boil down to three suggestions:</p>

<ol>
<li>&#8220;Just write it &#8212; it&#8217;s not that hard&#8221;</li>
<li>&#8220;Use [glade|qt designer|netbeans|&#8230;] &#8212; all the widgets are there&#8221;</li>
<li>&#8220;Just use pencil/pen/whiteboard/etc &#8212; it&#8217;s faster&#8221;</li>
</ol>

<p>I don&#8217;t agree with any of these &#8212; (1) is completely unreasonable.  Some people may be able to hack out a UI in their favorite language quickly, but when you suddenly need to move half the UI into a new dialog, or out of a dialog and into the main window, <em>and</em> change the tabs into a check list, with sample data, you&#8217;re screwed.  Once you finish manhandling your code to account for that change, you&#8217;ll need to add a component that is shaped like a septahedron with 7 distinct clickable areas and a tooltip that includes the latest stock quotes, and that tooltip needs to be scrollable.  The widget set places unreasonable restrictions on the design phase of your project.</p>

<p>Option (2) suffers from the same issues as (1) &#8212; you&#8217;re constrained by the widgets available, although this is less of an issue because it&#8217;s generally easier to add images, and the images can look like the widgets you&#8217;re missing.  However, since GUI UI development tools are, well, for development, they require you to do lots of irrelevant (at this stage) tasks, like specifying how objects will behave when they&#8217;re resized, and dealing with layout managers.  </p>

<p>(3) is the closest fit for my needs, and I <em>do</em> do lots of paper/whiteboard prototyping, but eventually, I need to show something that looks <em>real</em>, and sketches don&#8217;t cut it.  There simply isn&#8217;t enough resolution there to convey everything that needs to be included in the mock-ups I create.  </p>

<p>Hm.. perhaps I should go into what I <em>do</em> need, since my needs may be pretty esoteric.  If you&#8217;ve made it this far, you&#8217;re probably seething with anger, or you&#8217;ve got some idea of where I&#8217;m coming from.  I&#8217;m frequently in need of electronic versions of UI prototypes for remote collaboration, <a href="http://www.usabilitynet.org/tools/wizard.htm">&#8220;wizard of oz&#8221; testing</a>, or for inclusion in presentations and reports.  These mock-ups need to look &#8220;real&#8221; or the is a substantial risk of biasing any experiments, and there is an expectation of polish that can&#8217;t be reached with hand-drawn interfaces.  Since a lot of what I create is to solve novel problems in (at times) esoteric domains, we often need to use a mix of existing and novel widgets.</p>

<p>Generally, we use Visio to create these interfaces.  It offers a good balance between vector drawing capabilities and shape templates for common UI widgets / forms / etc. You are also able to import images, which is fairly critical when updating or adding to the UI of an existing tool.  (It&#8217;s easy to take a screenshot, clear out the details with the <a href="http://www.gimp.org/">Gimp</a>, and import as a background layer in Visio.)</p>

<p>Unfortunately, I&#8217;ve been unable to find any OSS tools that can fill this niche as well as visio.  There are a few, as recent posts from <a href="http://ask.slashdot.org/article.pl?sid=05/11/19/2234228">slashdot</a> and the old <a href="http://discuss.joelonsoftware.com/default.asp?joel.3.218003.15">Joel on Software forums</a> show:</p>

<ul>
<li><a href="http://dub.washington.edu:2007/denim/">DENIM</a>: Lets you sketch out interfaces with a tablet / mouse and create navigable web sites from those sketches.  Lacks in the &#8220;polish&#8221; area.</li>
<li><a href="http://www.evolus.vn/Pencil/Home.html">Pencil</a>: Firefox Plugin.  Peformance has been poor, in my experience. There are very few widgets (currently) available, and no image import capabilities (this is a huge flaw, IMHO).  Pencil could turn into something great, though.</li>
<li><a href="http://www.gnome.org/projects/dia/">DIA</a>: Last release was in March, 2007, but the svn repo does show some activity.  DIA lets you create things like network diagrams, UML, and flow charts, much like Visio, however, there are no UI stencils.  Instructions for creating new stencils (&#8216;shapes&#8217;) <a href="http://www.togaware.com/linux/survivor/Walkthrough_Creating0.html">exist</a>, but the svg support for shapes is very limited (no gradients, no rounded rectangles, etc..) and the documentation is even worse.</li>
<li><a href="http://www.koffice.org/kivio/">Kivio</a>: Much like dia, with essentially the same failings.</li>
<li>QT Designer | Glade | etc.: see above comments about GUI development tools.</li>
<li><a href="http://www.inkscape.org/">Inkscape</a>: Nominally a vector drawing tool, much like Adobe Illustrator, Inkscape has an active community, good documentation, and it is quite stable.  Unfortunately, it is not possible to customize the pallets / shapes available, and there is not much community support to make it a good UI design tool (aside from what can be done with any vector drawing app of this quality).</li>
<li><a href="http://developer.yahoo.com/ypatterns/wireframes/">Yahoo! UI Stencils</a> (YUI): Not really a tool, but rather a collection of svg images of common interface widgets.  </li>
</ul>

<p>None of these, on their own, do the job.  However, with nothing else looking bright, I&#8217;ve been digging into <a href="http://www.inkscape.org/">Inkscape</a> more over the last few days, and I think I&#8217;ve figured out a workflow that will do.</p>

<p>First off, the <a href="http://developer.yahoo.com/ypatterns/wireframes/">YUI</a> stencils are critical &#8212; but they are not in a format that can be easily imported and used as &#8220;widgets&#8221;.  Ideally, Inkscape would let me define custom shapes, complete with constraints on the sub-components of those shapes to influence resize and translation behaviors, but that isn&#8217;t yet available (to my knowledge).  You <em>can</em> get around this, somewhat, by using the open dialog as a pallet of sorts:</p>

<blockquote>&#8220;If you have a number of small SVG files whose contents you often reuse in other documents, you can conveniently use the Open dialog as a palette. Add the directory with your SVG sources into the bookmarks list so you can open it quickly. Then browse that directory looking at the previews. Once you found the file you need, simply drag it to the canvas and it will be imported into your current document.&#8221; (From the *Tips and Tricks* tutorial in Inkscape)</blockquote>

<p>This would work reasonably well, if the open dialog were not modal! (Ranting about modal dialog is another post, or two, at least.)  Thankfully, you <em>can</em> drag from the dialog into an inkscape instance even if they are running on different processes :).  Therefore, you can start up two inkscape processes (NOT via the &#8220;new document&#8221; option on the toolbar or file menu &#8212; you have to actually start up two instances separately or the dialog&#8217;s modality will still interfere with your work).  Once you have the processes going, and two inkscape windows, open the open dialog on one of them, go to the directory with your widgets, minimize the (now useless) inkscape window you opened the dialog from, and rock on with the YUI stencils &#038; whatever other tools you need to hack out your UI in the other inkscape instance.</p>

<p>There are a couple of things to keep in mind:</p>

<ul>
<li>Inkscape supports layers, so you can create stub data in a separate layer from the UI structure, and set the background content in another layer, etc.. so you don&#8217;t have to worry (as much) about grabbing the wrong thing and moving it out of place.</li>
<li><p>The drag-and-drop action from the open dialog will include everything in the dragged svg file &#8212; so the YUI stencils (or any custom shapes you make) need to be broken out into separate files. (I&#8217;ve done this for some of the components, and you can download those files here: (<a id="p45" rel="attachment" href="http://blog.ciscavate.org/2008/09/breaking-away-from-visio.html/broken-out-yui-stencils/" title="Broken out YUI stencils">Broken out YUI stencils</a>).  They are released under a <a href="http://creativecommons.org/licenses/by/2.5/">Creative Commons Attribution 2.5 License</a>.</p>

<p>Pencil (or one of the other options) may work better for you &#8212; many people have complained that their clients think an app is nearly finished because the UI looks &#8220;real&#8221;, and there are numerous ways to address that.  (eg: <a href="http://napkinlaf.sourceforge.net/">NapkinLAF</a> for Swing apps.) I haven&#8217;t had this problem, and something like NapkinLAF doesn&#8217;t address the problems I have, which are all related to pre-coding UI design.</p></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/09/breaking-away-from-visio.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Wrestling Python</title>
		<link>http://blog.ciscavate.org/2008/09/wrestling-python.html</link>
		<comments>http://blog.ciscavate.org/2008/09/wrestling-python.html#comments</comments>
		<pubDate>Fri, 05 Sep 2008 17:13:49 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/09/wrestling-python.html</guid>
		<description><![CDATA[With the launch of the StackOverflow beta I posed a question about python static analysis tools, as I have been playing with python and django recently for some side projects.  The responses at Stack Overflow quickly pointed to PyChecker, PyFlakes and PyLint.

Over all, it was a disappointing experience.  My experiences are outlined below, [...]]]></description>
			<content:encoded><![CDATA[<p>With the launch of the <a href="http://beta.stackoverflow.com">StackOverflow beta</a> I posed a question about python static analysis tools, as I have been playing with python and django recently for some side projects.  The responses at Stack Overflow quickly pointed to <a href="http://pychecker.sf.net">PyChecker</a>, <a href="http://divmod.org/trac/wiki/DivmodPyflakes">PyFlakes</a> and <a href="http://www.logilab.org/857">PyLint</a>.</p>

<p>Over all, it was a disappointing experience.  My experiences are outlined below, and they (more or less) reflect this more <a href="http://www.doughellmann.com/articles/CompletelyDifferent-2008-03-linters/index.html ">extensive review by Doug Hellman</a>.</p>

<p>Here are my first impressions of pyflakes, pychecker and pylint:</p>

<ul>
<li><p><strong>pychecker</strong>: It crashes frequently, most of the runs I tried resulted in Errors that originated in the pychecker code (eg: AttributeError or IndexError: list index out of range were the most common).  For some reason I had to set the DJANGO<em>SETTINGS</em>MODULE environment variable before it would even run on any of the app code, and the documentation is very sparse.</p></li>
<li><p><strong>pyflakes</strong>: &#8216;pyflakes &#8212;help&#8217; throws a TypeError &#8212; erm&#8230; Documentation is also very sparse, and pyflakes is very forgiving (as far as I can tell, it only reports compile errors, warnings, redefinitions, and some concerns about imports&#8212;such as unused and wildcards).  pyflakes also seems to repeat itself:</p>

<blockquote>
  <p>eventlist/views.py:4: &#8216;Http404&#8217; imported but unused<br />
      eventlist/views.py:4: &#8216;Http404&#8217; imported but unused<br />
      eventlist/views.py:5: &#8216;from eventlist.models import *&#8217; used; unable to detect undefined names
      eventlist/views.py:59: &#8216;authenticate&#8217; imported but unused<br />
      eventlist/views.py:61: redefinition of unused &#8216;login&#8217; from
  line 59<br />
      eventlist/views.py:5: &#8216;from eventlist.models import *&#8217; used;
  unable to detect undefined names <br />
     eventlist/views.py:4: &#8216;Http404&#8217; imported but unused</p>
</blockquote></li>
<li><p><strong>pylint</strong>: This seems to be the most capable of the tools suggested.  It has the best documentation.  LogiLab provides a tutorial, pylint has a help screen, and there is a (broken) link to a user manual, which would be extremely helpful.  There are some issues with applying pylint to django, since pylint doesn&#8217;t know about the django classes (such as models.Model).  This means that a fair number of otherwise valuable errors are generated about missing class fields.  eg:</p>

<blockquote>
  <p><code>E:105: get_events_by_tag: Class 'Tag' has no 'objects' member</code><br /></p>
</blockquote>

<p>Parsing these out automatically will be very difficult without some additional knowledge of the classes in use.  I&#8217;m not sure adding that is feasible, but it does seem likely that pylint is capable of dealing with this in the &#8220;right&#8221; way.  (I probably just need to point it to the django source, but there are no command line params that look likely, and, as mentioned earlier, the user manual is inaccessible.)</p></li>
</ul>

<p>For the moment, I&#8217;m still looking into pylint &#8212; pychecker and pyflakes need better documentation and they need to become more robust.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/09/wrestling-python.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Traveling to Patras</title>
		<link>http://blog.ciscavate.org/2008/07/traveling-to-patras.html</link>
		<comments>http://blog.ciscavate.org/2008/07/traveling-to-patras.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 11:52:30 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[greece]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/07/traveling-to-patras.html</guid>
		<description><![CDATA[

A groggy morning in Seattle started with the typical regional sunshine forcing its presence through heavy cloud cover&#8212;the first overcast day in nearly a week of clear, scorching weather.



Seattle to Newark, hustle off the plane, bad coffee, hustle to the next gate, and then encamp for the next 9 hours of travel across the Atlantic. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ciscavate.org/wp-content/uploads/2008/07/seatac-small.jpg" style="float:left; padding-right: 1em;"><img alt="Coffe and clouds in Seattle." src="http://blog.ciscavate.org/wp-content/uploads/2008/07/seatac-small.thumbnail.jpg" /></a></p>

<p>A groggy morning in Seattle started with the typical regional sunshine forcing its presence through heavy cloud cover&#8212;the first overcast day in nearly a week of clear, scorching weather.</p>

<p><a style="float:right; padding-right: 1em;" href="http://blog.ciscavate.org/wp-content/uploads/2008/07/patrasHills1-small.jpg"><img alt="The hills across the Gulf of Patras (looking North)" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/patrasHills1-small.thumbnail.jpg" /></a></p>

<p>Seattle to Newark, hustle off the plane, bad coffee, hustle to the next gate, and then encamp for the next 9 hours of travel across the Atlantic.  This leg was on a relatively empty 767, but I still can&#8217;t really sleep on planes.  I have become an overnight advocate for noise-canceling headphones though&#8212;they make the difference between muffling a sound and turning it off.  I found the Athens airport to be considerably less hyper than most US airports (with the exception of Syracuse, which is not much of a surprise), although I think it is universal that no one is particularly happy when at an airport, and that feeling seems to be contagious.  It&#8217;s unfortunate that it is so difficult to visit a place without first visiting an airport there.</p>

<p><a style="float:left; padding-right: 1em;" href="http://blog.ciscavate.org/wp-content/uploads/2008/07/moonAndBoats-small.jpg"><img alt="The morning view from the balcony" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/moonAndBoats-small.thumbnail.jpg" /></a></p>

<p>I few hours later I hopped on a tour bus to take everyone from the recent batch of flights off to our hotels in Patras&#8212;a wild 4-5 hour ride along the shoulders of &#8220;one of the worst roads in Greece&#8221; as some one here put it.  The careening along coastal roads was punctuated by hairpin turns in seaside villages with roads small enough to make any driver feel claustrophobic, and we were riding in a bus that would seat 30-40, with luggage.  It was much like watching a game of <a href="http://en.wikipedia.org/wiki/N-puzzle">Fifteen Puzzle</a>, with a key twist: every tile (car) was self-aware and initially greedy.</p>

<p>We did eventually make it to the <a href="http://www.hoteltzaki.gr/">Hotel Tzaki</a> almost exactly 24 hours after leaving Seattle.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/07/traveling-to-patras.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Cracking down on application clutter (or: my ${HOME} is my castle!)</title>
		<link>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html</link>
		<comments>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 23:25:21 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html</guid>
		<description><![CDATA[There was once a time when your home directory was treated as a nearly sacred place, a safe haven where you had near complete control.  This trust was only breached for very special reasons: user specific settings and background storage for applications could go in &#8220;dot-files&#8221;&#8212;the hidden files or directories that begin with a [...]]]></description>
			<content:encoded><![CDATA[<p>There was once a time when your home directory was treated as a nearly sacred place, a safe haven where you had near complete control.  This trust was only breached for very special reasons: user specific settings and background storage for applications could go in &#8220;dot-files&#8221;&#8212;the hidden files or directories that begin with a &#8220;.&#8221; and therefore don&#8217;t show up in normal directory listings.</p>

<p>Unfortunately, things began to change. I don&#8217;t know what kicked it off, but soon there was a Desktop (or desktop) folder.  It was glaring&#8212;many XFree86 window managers don&#8217;t even have the <em>concept</em> of a desktop, but the defaults environments were (and still are) often set to Desktop Managers.  Web browsers took after the DM&#8217;s, and soon we all had these glaring &#8220;Desktop&#8221; directories hanging out whether we wanted them or not.  I&#8217;ve managed to tolerate this infraction for years, and aside from the occasional frustration (eg: Ecilpse and NetBeans, with their request for a ~/workspace and ~/NetBeansProjects directories).</p>

<p>However, today things changed.</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ ls ~<br />
bin/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PDF/&nbsp; &nbsp;&nbsp; <br />
Desktop/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Pictures/&nbsp; <br />
development/&nbsp; &nbsp; &nbsp; Public/&nbsp; &nbsp;&nbsp; &nbsp; <br />
documents/&nbsp; &nbsp; &nbsp; &nbsp; src/&nbsp; &nbsp;&nbsp; <br />
Documents/&nbsp; &nbsp; &nbsp; &nbsp; shared/&nbsp; &nbsp;&nbsp; &nbsp; <br />
downloads/&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Templates/&nbsp;&nbsp; <br />
Mail/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Videos/&nbsp; &nbsp;&nbsp; &nbsp; <br />
Music/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; virtualMachines/ <br />
myapps/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;workspace/</div></div>

<p>Documents? (Ok, I can sort of understand that one.) Music? Pictures? Templates, PDF, Public, and Videos?! Did I suddenly become a master of multimedia? Keep in mind here, I&#8217;m a java hacker on a Linux box&#8212;this isn&#8217;t exactly a fine-tuned rendering/desktop publishing platform.   And of course, every one of those directories is empty.  Thankfully, I checked before deleting <code>documents</code> vs. <code>Documents</code> (I&#8217;ve been bitten there before&#8212;on a mac due to case conflation&#8212;but that&#8217;s another story).  </p>

<p>Why would I want a directory called PDF? I can understand (possibly) wanting to <em>tag</em> files with &#8220;PDF&#8221;, but as part of a single-dimensional sorting criteria? (Hey, lets store all my .h files in ~/H/ and all my .cpp files in ~/CPP/! It&#8217;ll be great!)</p>

<p>Needless to say, I&#8217;ve removed the offending directories, and this time I&#8217;m ready:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ kernel-filesystem-monitor-daemon-cat -v&nbsp; watch <span class="re0">$<span class="br0">&#123;</span>HOME<span class="br0">&#125;</span></span> | <br />
perl -ne <span class="st0">'{<br />
&nbsp; &nbsp;if( /^CREATE/ ) { # only report create events<br />
&nbsp; &nbsp; &nbsp; s|.*URL:<span class="es0">\.</span>/||g; <br />
&nbsp; &nbsp; &nbsp; if ( !/^<span class="es0">\.</span>/ ) { # don'</span>t report new dot-files<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print <span class="st0">&quot;$_ created @ &quot;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print `date`; <br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><span class="st0">' &gt; ~/whenCrapWentDown.txt</span></div></div>

<p>(newlines and comments introduced to improve clarity &#8212; if you&#8217;re pasting this into a shell, you&#8217;ll need to either add &#39;s or remove newlines.)</p>

<p><a href="http://freshmeat.net/projects/kfsmd/">KFSMD (kernel-filesystem-monitor-daemon)</a> is an app that does exactly what it&#8217;s 32-character name says. Whenever a filesystem change occurs, it knows about it.  The <code>-cat</code> part just tells it to print to stdout, and the hunk of perl does some minor processing, and introduces time stamps.</p>

<p>I&#8217;m actually running this in a sticky terminal that&#8217;s pinned to my E17 desktop, so if/when something starts building an empire in my home directory, I&#8217;ll be able to compare with what apps are running, and hopefully track it down.  (It would be nice to collect the PIDs of the process that actually issued the system call to touch the file system, but this is good enough for now.)</p>

<p><img id="image37" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/fsWatcher.png" alt="fsWatcher.png" width="474"/></p>

<p>Now we wait&#8230;</p>

<p>(<a href="http://www.linux.com/feature/124903">This article</a> got me going with KFSMD.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Creating Wizards in Java</title>
		<link>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html</link>
		<comments>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html#comments</comments>
		<pubDate>Tue, 01 Jul 2008 19:54:24 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/?p=35</guid>
		<description><![CDATA[A recent project at work required building a multi-step dialog to manage the interface between a user and an expert system (and some fairly advanced NLP to boot).  On the surface this looked like a fairly standard Wizard problem &#8212; design a bunch of screens with questions, and then collect the answers as the [...]]]></description>
			<content:encoded><![CDATA[<p>A recent project at work required building a multi-step dialog to manage the interface between a user and an expert system (and some fairly advanced NLP to boot).  On the surface this looked like a fairly standard Wizard problem &#8212; design a bunch of screens with questions, and then collect the answers as the user proceeded through the dialogs.  However, the Wizard APIs I found were either not very mature or (in the case of the <a href="http://wizard.dev.java.net">Java.net Wizards</a>) it was very difficult to create complex branching behaviors, and those branches were extremely resistant to change.  Both things are essentially show-stoppers when working with prototypes that frequently need modification.</p>

<p>In the end, I spent a weekend and a couple evenings building a new Wizard API for Java, called <a href="http://code.google.com/p/cjwizard">CJWizard</a>.  The library is released under the Apache V.2 license, so it should work for just about anything you want to use it for.  I would like to know if you&#8217;re using it, and what you&#8217;re using it for, just to sate my own curiosity :).  The project is hosted on code.google.com, so please submit issues, and feel free to contribute to the project.</p>

<p><a href="http://code.google.com/p/cjwizard">CJWizard</a> provides the structure needed to quickly create simple dialogs by implementing an abstract class (WizardPage) for each page of the dialog, and adding them to a PageFactory that can generate pages on-demand, as they are required.  This puts the programmer in full control of how the wizard proceeds.  The CJWizard architecture also makes it easy to add a wizard to an existing application (either via an additional JDialog, or embedding in some other component), and/or insert custom wrapper widgets around the dialog pages&#8212;meaning that you can quickly add customized navigational controls aside from the standard Previous/Next/Finish/Cancel buttons.</p>

<p>Some aspects were taken from the Java.Net wizard API, such as auto-detecting named components, and automatically collecting the values from them, but CJWizard takes a much simpler approach (and in some ways, a less powerful one &#8212; CJWizard does not listen to every key event, only collecting values when the user navigates away from a WizardPage). In most cases, you only need to name widgets prior to adding them to the WizardPage, and their values will be collected in a settings map automatically.</p>

<p>CJWizard was meant to provide a flexible way to generate professional-looking multi-step dialogs very quickly.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Day to day Memoization</title>
		<link>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html</link>
		<comments>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html#comments</comments>
		<pubDate>Mon, 28 Jan 2008 11:02:08 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/?p=33</guid>
		<description><![CDATA[Memoization (not memorization) is the process of remembering the
results of a computation for use later.  (I think of it as &#8220;making a
memo&#8221; to look back on later.)  Memoization is the core to any dynamic
programming implementation, and allows many simple algorithms to run
in linear or polynomial time when they would otherwise take an
exponential number [...]]]></description>
			<content:encoded><![CDATA[<p>Memoization (not <strong>memorization</strong>) is the process of remembering the
results of a computation for use later.  (I think of it as &#8220;making a
memo&#8221; to look back on later.)  Memoization is the core to any dynamic
programming implementation, and allows many simple algorithms to run
in linear or polynomial time when they would otherwise take an
exponential number of operations to complete.  This is most obvious in
the typical recursive Fibonacci example.  Consider the code:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> Fib<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;done: fib of &quot;</span>+args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>+<span class="st0">&quot;=&quot;</span>+<br />
&nbsp; &nbsp; &nbsp; fib<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> fib<span class="br0">&#40;</span><span class="kw4">int</span> n<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> rval = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n &amp;gt;= <span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rval = fib<span class="br0">&#40;</span>n - <span class="nu0">1</span><span class="br0">&#41;</span> + fib<span class="br0">&#40;</span>n - <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;fib(&quot;</span>+n+<span class="st0">&quot;) = &quot;</span>+rval<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> rval;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>This is a straight-forward recursive implementation of fib.  When run
with <code>n=4</code>, we see this:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ javac Fib.java &amp;&amp; java Fib <span class="nu0">4</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span> = <span class="nu0">3</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span> = <span class="nu0">5</span><br />
<span class="kw1">done</span>: fib of <span class="nu0">4</span>=<span class="nu0">5</span></div></div>

<p><strong>9</strong> invocations of <code>fib(n)</code>, but only 5 <strong>unique</strong> invocations.  Lets
memoize the results, and try this again:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ javac Fib.java &amp;&amp; java Fib <span class="nu0">4</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span> = <span class="nu0">3</span><br />
fib<span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span> = <span class="nu0">5</span><br />
<span class="kw1">done</span>: fib of <span class="nu0">4</span>=<span class="nu0">5</span></div></div>

<p><strong>Much</strong> better &#8212; 5 invocations, 5 unique sets of parameters.</p>

<p>Here&#8217;s the source with memoization:</p>

<div class="codecolorer-container java" style="height:280px;"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> Fib<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">static</span> Map&amp;lt;Integer, Integer&amp;gt; memos = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AHashMap+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">HashMap</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">// new</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;done: fib of &quot;</span>+args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>+<span class="st0">&quot;=&quot;</span>+<br />
&nbsp; &nbsp; &nbsp; fib<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> fib<span class="br0">&#40;</span><span class="kw4">int</span> n<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>memos.<span class="me1">containsKey</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="co1">// new</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">return</span> memos.<span class="me1">get</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span>;&nbsp; <span class="co1">// new</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> rval = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n &amp;gt;= <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rval = fib<span class="br0">&#40;</span>n - <span class="nu0">1</span><span class="br0">&#41;</span> + fib<span class="br0">&#40;</span>n - <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;fib(&quot;</span>+n+<span class="st0">&quot;) = &quot;</span>+rval<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; memos.<span class="me1">put</span><span class="br0">&#40;</span>n, rval<span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// new</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> rval;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Notice that we only needed to add 4 new lines of code in order to
memoize the results.  When <code>fib(n)</code> is called, it simply checks to see
if it has previously been called with n, and if so, that result is
used again.  If the parameter has never been seen before, the method
continues as normal, storing the computed result before returning.
Memoization turns this naive (and exponential) implementation of <code>fib(n)</code>
into an efficient (linear) operation.</p>

<h2>Memoization in the real world</h2>

<p>So, (un?)fortunately we don&#8217;t spend all day implementing cool new ways
of computing ever increasing entries of the fibinocci sequence &#8212; how
can memoization be put to use? After all, many algorithms are already
implemented in some fairly optimal fashion by the language APIs, and
you&#8217;d be a fool not to use those implementations.  What opportunity
will you have to memoize functions?</p>

<p>It turns out that you can memoize <em>anything</em>, as long as the function
is <em>pure</em> with respect to the memos (meaning: the function doesn&#8217;t depend on any thing that is not used to key the hash of memos).  If the function is not pure, then you can still use memoization, but either the memo hash must key on all the state and parameters that can affect the results of the function.  On the other hand, if f depends on some state that changes very rarely, then it may make more sense to simply discard all the stored memos each time that aspect of state is altered.</p>

<p>Memoization is extremely handy when you have very common operations that are
fairly expensive.  I recently needed to optimize some code that
compares strings based on the case-insensitive stems of the words,
with stopwords removed.  So the strings &#8220;he wanted an apple&#8221; and &#8220;he
wants apples&#8221; should be equal. (&#8220;an&#8221; is a stopword, and ignored)</p>

<p>This meant doing many, many calls to a string stemmer, each of which
is a fairly expensive operation.  Fortunately, hashing strings as
extremely cheap (on the order of 1/4th the time it took to stem a
string of the same length), and I had plenty of memory to store the
parameters and the results in a <code>Map</code>.  Adding memos to
the two primary time-hoggers (the stemmer and a tokenizer) cut the
execution time of the application down from 2 hours to just over 7
minutes.</p>

<h2>Summary</h2>

<p>You can memoize any function that only depends on it&#8217;s parameters and
constant state (or near-constant state &#8212; just don&#8217;t forget to discard your
memos when the state changes!).  If the function is invoked multiple
times you will probably see a performance improvement.</p>

<p>If you need to memoize a function with multiple arguments, then you
just need to nest Maps, or create a unique key by combining the
parameters in some way.</p>

<p>Memoization is an extremely easy way to improve performance under
certain circumstances, particularly if you have a solid grasp on when
state changes outside of your methods / functions, or program in a
functional style.  It can be memory intensive, however.  If the
results of your functions are large, or maintain references to large
objects, then memoization may <strong>penalize</strong> performance if you run out of
memory and have to make use of swap space.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
