<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Just wondering.... &#187; technical</title>
	<atom:link href="http://sworddance.com/blog/category/technical/feed/" rel="self" type="application/rss+xml" />
	<link>http://sworddance.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 08 Sep 2010 05:40:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>How to do variable/conditional SQL sorting order of results</title>
		<link>http://sworddance.com/blog/2010/07/25/how-to-do-variableconditional-sql-sorting-order-of-results/</link>
		<comments>http://sworddance.com/blog/2010/07/25/how-to-do-variableconditional-sql-sorting-order-of-results/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 18:48:49 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[help notes]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=657</guid>
		<description><![CDATA[I was jazzed today. I figured out how to conditional order of SQL results. Specifically being able to vary change the sorting order within the results based on a database field. Specifically, Create two tables Main and Secondary create table &#8230; <a href="http://sworddance.com/blog/2010/07/25/how-to-do-variableconditional-sql-sorting-order-of-results/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was jazzed today. I figured out how to conditional order of SQL results. Specifically being able to vary change the sorting order within the results based on a database field. </p>
<p>Specifically, </p>
<ol>
<li>Create two tables <em>Main</em> and <em>Secondary</em>
<ul>
<li><code>create table Main ( ID bigint, ordering varchar(3));</code></li>
<li><code>create table Secondary ( Main_ID bigint, Secondary_Value bigint);</code></li>
</ul>
<li>Insert Values:
<ul>
<li><code>insert into Main (ID, ordering) values (1, 'u'),(2,'d'),(3,'n');</code></li>
<li><code>insert into Secondary (Main_ID, Secondary_Value) values ( 1, 11),(1,21),(1,41),(1,31),(1,71),(1,61),(1,51),(2,62),(2,42),(2,82), ( 3,3), (3, 1), (3, 5);</code></li>
</ul>
</li>
<li>Create a query that orders the results by Main.ID, Secondary.Secondary_Value based on Main.ordering value. If the Main.ordering is:
<ul>
<li>&#8216;u&#8217; then the corresponding Secondary_Value is ordered ascending,</li>
<li>&#8216;d&#8217; then the corresponding Secondary_Value is ordered descending,</li>
<li>&#8216;n&#8217; then the corresponding Secondary_Value is unordered</li>
</ul>
</li>
</ol>
<p>The solution is:</p>
<blockquote><p><code>select * from Main join Secondary on ( Main.ID = Secondary.Main_ID ) order by Main.ID, (case MAIN.ordering when 'u' then 1 when 'd' then -1 else 0 end) * Secondary.Secondary_Value;</code></p></blockquote>
<pre>
+------+----------+---------+-----------------+
| ID   | ordering | Main_ID | Secondary_Value |
+------+----------+---------+-----------------+
|    1 | u        |       1 |              11 |
|    1 | u        |       1 |              21 |
|    1 | u        |       1 |              31 |
|    1 | u        |       1 |              41 |
|    1 | u        |       1 |              51 |
|    1 | u        |       1 |              61 |
|    1 | u        |       1 |              71 |
|    2 | d        |       2 |              82 |
|    2 | d        |       2 |              62 |
|    2 | d        |       2 |              42 |
|    3 | n        |       3 |               1 |
|    3 | n        |       3 |               5 |
|    3 | n        |       3 |               3 |
+------+----------+---------+-----------------+
13 rows in set (0.00 sec)
</pre>
<p>Variable ordering within a single result set! woo-hoo!</p>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/07/25/how-to-do-variableconditional-sql-sorting-order-of-results/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where to start learning Java if you are a PHP person?</title>
		<link>http://sworddance.com/blog/2010/06/09/where-to-start-learning-java-if-you-are-a-php-person/</link>
		<comments>http://sworddance.com/blog/2010/06/09/where-to-start-learning-java-if-you-are-a-php-person/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 20:07:37 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[how to]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=630</guid>
		<description><![CDATA[Over at StackOverflow, the question was asked : Where to start with Java when coming from PHP? PHP5 has the concept of objects, interfaces and exceptions. These are similar enough to Java&#8217;s version of objects, interfaces and exceptions for basic &#8230; <a href="http://sworddance.com/blog/2010/06/09/where-to-start-learning-java-if-you-are-a-php-person/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://stackoverflow.com/questions/3002701/where-to-start-learning-java" rel="nofollow">Over at StackOverflow, the question was asked : Where to start with Java when coming from PHP?</a></p>
<p><a href="http://php.net/manual/en/language.oop5.php">PHP5 has the concept of objects, interfaces and exceptions.</a> These are similar  enough to Java&#8217;s version of objects, interfaces and exceptions for basic learning purposes.</p>
<p>Once you get the PHP5 equivalent understood then crossover to Java.</p>
<p>Since everyone starts with a Hello world program,</p>
<ol>
<li>Set up eclipse (J2EE version)</li>
<li>Use the Java tooling to create a new class that is your Hello world.</li>
<li>Figure out the basics of debugging with eclipse</li>
<li>Figure out the basics of objects, interfaces, exceptions and inheritance.</li>
<li>Understand the basic language differences PHP vs. Java&#8217;s</li>
<li>Understand the differences between a static typed language and the dynamic-typed languages that you are used to.</li>
<li>Learn the classes in java.lang.* and java.util.* packages.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/06/09/where-to-start-learning-java-if-you-are-a-php-person/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multi-threaded Homework Problem</title>
		<link>http://sworddance.com/blog/2010/06/01/multi-threaded-homework-problem/</link>
		<comments>http://sworddance.com/blog/2010/06/01/multi-threaded-homework-problem/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 17:43:27 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[how to]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=613</guid>
		<description><![CDATA[Occasionally I have been asked about learning multithreaded programming. My standard suggested problem is to create a &#8220;simplistic&#8221; TCP/IP block ordering library. This is a variant of the standard producer/consumer problem that shows up in interviews. This problem is a &#8230; <a href="http://sworddance.com/blog/2010/06/01/multi-threaded-homework-problem/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Occasionally I have been asked about learning multithreaded programming. </p>
<p>My standard suggested problem is to create a &#8220;simplistic&#8221; TCP/IP block ordering library. This is a variant of the standard producer/consumer problem that shows up in interviews. This problem is a standard multiple-producer/multiple-consumer problem with a twist and goes way beyond what can be handled in an interview. </p>
<p><em><strong>Problem #1</strong></em></p>
<p>Use case:</p>
<ul>
<li>each block as a conversation Id and a sequence id within the conversation. </li>
<li>All blocks are received on a single queue.</li>
<li>Blocks are separated by conversation and then ordered by sequence number.</li>
<li>Blocks arrive semi-random order &#8211; the sequence id will be within +/-2 of the previous block (in the same conversation)&#8217;s sequence id. But there will be no gaps in the sequence id for a given conversation.</li>
<li>sequence id 0 starts the conversation, sequence id 99 ends the conversation</li>
</ul>
<p>Sample sequence: (1,0), (1,2), (2,0), (1,3), (2,2), (1,1), (2,1), &#8230;.  </p>
<p><em><strong>Problem #2:</strong></em></p>
<p>Extending Problem #1 with these additional requirements:</p>
<ul>
<li>Conversations where the 0 block has not been seen are discarded.</li>
<li>Blocks may be repeatedly sent. Duplicates are discarded.</li>
<li>Conversations are now buffered when doing the ordering ( represents buffering within the TCP/IP stack )</li>
<li>Each conversation chunk can only hold 3 blocks.</li>
<li>Each buffer when complete is dispatched in order to a dummy thread ( represents the application ) &#8211; which has a random delay and then tests and discards the data.</li>
</ul>
<p>Sample data (for single conversation):</p>
<p>(1,0) <em>- buffer#1</em>; (1, 5)<em> &#8211; buffer#2</em>; (1,6) <em>- buffer#3</em>; (1,1)<em> &#8211; buffer #1</em>; (1,2)<em> -buffer #1 (dispatched)</em>; (1,1)<em> &#8211; duplicate (discarded)</em>; (1,3)<em> &#8211; buffer #2</em>; (1,7)<em> &#8211; buffer #3 ( cannot be dispatched because buffer #2 has not been dispatched)</em>; (1,4)<em> &#8211; buffer #2 and #3 are both dispatched</em>; (1,10)<em> &#8211; buffer #1 is now reavailable</em>; &#8230;.</p>
<p><em><strong>Problem #3:</strong></em></p>
<p>Additional requirements:</p>
<ul>
<li>Each conversation now has the sequence variation by +/-10 (bell curve)</li>
<li>Each conversation (on the consumer side) has only 2 buffers available to it</li>
<li>Blocks that can not be sequentially placed in the conversation buffers are discarded.</li>
<li>When the consumer threads detect 3 failures to complete the buffer, the consumer notifies the producers that the missing block needs to be resent.</li>
<li>Conversations have an indeterminate length. Additional flag signals the last block in the conversation.</li>
<li>Conversations that have not sent data in the last 30 seconds are terminated. All uncompleted buffers are discarded. Any further TCP/IP blocks are discarded.</li>
<li>Producers have a 5 buffers per conversation available</li>
</ul>
<p>Things to look for:</p>
<ul>
<li>Starvation &#8211; conversation is not being processed in spite of buffers being available</li>
<li>Effective I/O rate</li>
<li>Retry rate because of dropped buffers</li>
</ul>
<p><em><strong>Update:</strong></em></p>
<p>Some resource suggestions from <a href="http://nl.linkedin.com/in/ronaldvermeij">Ronald Vermeij</a>:</p>
<blockquote><p>
<a href="http://www.tutorialspoint.com/java/java_multithreading.htm">Simple very basic tutorial</a></p>
<p><a href="http://www.doc.ic.ac.uk/~jnm/book/index.html">Concurrency: State Models &#038; Java Programs Book</a></p>
<ul>
<li><a href="http://www.doc.ic.ac.uk/~jnm/book/slides.html">slides, notes and lectures</a></li>
<li><a href="http://www.doc.ic.ac.uk/~jnm/book/book_applets/concurrency.html">demo programs with GUI interaction and source-codes</a></li>
</ul>
<p><a href="http://refcardz.dzone.com/refcardz/core-java-concurrency">Nice &#8220;Concurrency RefCard&#8221; at Devzone</a></p></blockquote>
<p><em>Update 2</em></p>
<p>The homework problem is actually fiendishly difficult. The problem is similar to a real world problem I had constructing a network switch monitoring program. The switches run a http server on a low priority thread. The http server respond slowly, occasionally they just drop a request. In the test lab, the switches are not under high load but in the field they are. Under high load, the http server may not respond in a timely manner. Different switch models responded differently. Determining the monitoring program&#8217;s response to a switch&#8217;s behavior or (non) behavior was &#8220;interesting&#8221; &#8211; panic and tell the operator that the switch has crashed? Do we delay the failure notification (turning switch status to red)? How often to poll the switch ( we don&#8217;t want to add to the overloaded switch&#8217;s work ). We also had to process the incoming data as fast as possible so the switch doesn&#8217;t drop the connection because the response is not being processed.</p>
<p><em><strong>Extra credit:</strong></em></p>
<ul>
<li>Separate out the producer and consumer portions into 2 different programs</li>
<li>Each conversation is on a separate Java NIO connection</li>
<li>100+ producer threads (in the producer program), 5 consumer threads in the consumer program</li>
<li>each conversation&#8217;s producer produces data at a random rate (will be bursty).</li>
<li>The conversation&#8217;s consumer must consume the produced data fast enough so the producer always has an available buffer to write to ( producer has 2 buffers &#8211; but try reducing the producer&#8217;s available buffers ). Consumer&#8217;s per conversation buffers can be higher than previous problem.</li>
<li>Producer may arbitrarily stop sending data </li>
<li>Use Java NIO</li>
</ul>
<p>Notice: </p>
<ul>
<li>When setting up, the connection the consumer must quickly complete establishment of the connection otherwise the connection will be dropped. [Hint: Have a dedicated consumer thread do just the connection establishment. Many Java NIO sample programs try to have the same thread establish connections and do the read operations those connections.]</li>
<li>Consumer must be aggressive about processing incoming data.</li>
<li>Consumer needs to have a  &#8220;give up and retry&#8221; mechanism</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/06/01/multi-threaded-homework-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8230; and I nailed the javadoc</title>
		<link>http://sworddance.com/blog/2010/01/07/and-i-nailed-the-javadoc/</link>
		<comments>http://sworddance.com/blog/2010/01/07/and-i-nailed-the-javadoc/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 18:44:08 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[help notes]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=563</guid>
		<description><![CDATA[Yesterday was a red letter day. I found multiple bugs in the javac and javadoc. (1.6.0_17) This javadoc issue occurred when there is a class that has no package line ( it is in the default package). Annoyingly enough it &#8230; <a href="http://sworddance.com/blog/2010/01/07/and-i-nailed-the-javadoc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Yesterday was a red letter day. I found multiple bugs in the javac and javadoc. (1.6.0_17)</p>
<p>This javadoc issue occurred when there is a class that has no package line ( it is in the default package). Annoyingly enough it occurred when I was trying to create a test case for <a href="http://www.sworddance.com/blog/2010/01/07/woot-i-crashed-the-javac/">this javac</a> bug. I was running maven 2.2.1 at the time.<br />
<code>
<pre>
java.lang.NullPointerException
       at com.sun.tools.doclets.formats.html.PackageUseWriter.generatePackageUse(PackageUseWriter.java:180)
       at com.sun.tools.doclets.formats.html.PackageUseWriter.generatePackageList(PackageUseWriter.java:124)
       at com.sun.tools.doclets.formats.html.PackageUseWriter.generatePackageUse(PackageUseWriter.java:110)
       at com.sun.tools.doclets.formats.html.PackageUseWriter.generatePackageUseFile(PackageUseWriter.java:99)
       at com.sun.tools.doclets.formats.html.PackageUseWriter.generate(PackageUseWriter.java:78)
       at com.sun.tools.doclets.formats.html.ClassUseWriter.generate(ClassUseWriter.java:116)
       at com.sun.tools.doclets.formats.html.HtmlDoclet.generateOtherFiles(HtmlDoclet.java:92)
       at com.sun.tools.doclets.internal.toolkit.AbstractDoclet.startGeneration(AbstractDoclet.java:122)
       at com.sun.tools.doclets.internal.toolkit.AbstractDoclet.start(AbstractDoclet.java:64)
       at com.sun.tools.doclets.formats.html.HtmlDoclet.start(HtmlDoclet.java:42)
       at com.sun.tools.doclets.standard.Standard.start(Standard.java:23)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at com.sun.tools.javadoc.DocletInvoker.invoke(DocletInvoker.java:269)
       at com.sun.tools.javadoc.DocletInvoker.start(DocletInvoker.java:143)
       at com.sun.tools.javadoc.Start.parseAndExecute(Start.java:340)
       at com.sun.tools.javadoc.Start.begin(Start.java:128)
       at com.sun.tools.javadoc.Main.execute(Main.java:41)
       at com.sun.tools.javadoc.Main.main(Main.java:31)
</pre>
<p></code></p>
<p>Solution was to put the java code into a package.</p>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/01/07/and-i-nailed-the-javadoc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Woot! I crashed the javac</title>
		<link>http://sworddance.com/blog/2010/01/07/woot-i-crashed-the-javac/</link>
		<comments>http://sworddance.com/blog/2010/01/07/woot-i-crashed-the-javac/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 18:35:10 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[help notes]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=556</guid>
		<description><![CDATA[My javac crash: An exception has occurred in the compiler (1.6.0_17). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you. &#8230; <a href="http://sworddance.com/blog/2010/01/07/woot-i-crashed-the-javac/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My javac crash:</p>
<p><code>An exception has occurred in the compiler (1.6.0_17). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.</p>
<pre>
java.lang.AssertionError: isSubtype 15 ( 15 = TypeTags.WILDCARD )
	at com.sun.tools.javac.code.Types$5.visitType(Types.java:347)
	at com.sun.tools.javac.code.Types$5.visitType(Types.java:328)
	at com.sun.tools.javac.code.Types$DefaultTypeVisitor.visitWildcardType(Types.java:3163)
	at com.sun.tools.javac.code.Type$WildcardType.accept(Type.java:416)
	at com.sun.tools.javac.code.Types$DefaultTypeVisitor.visit(Types.java:3161)
	at com.sun.tools.javac.code.Types.isSubtype(Types.java:324)
	at com.sun.tools.javac.code.Types.isSubtype(Types.java:308)
	at com.sun.tools.javac.code.Types.isSubtypeUnchecked(Types.java:288)
	at com.sun.tools.javac.code.Types.isSubtypeUnchecked(Types.java:460)
	at com.sun.tools.javac.comp.Infer.checkWithinBounds(Infer.java:388)
	at com.sun.tools.javac.comp.Infer.instantiateExpr(Infer.java:241)
	at com.sun.tools.javac.comp.Check.instantiatePoly(Check.java:356)
	at com.sun.tools.javac.comp.Check.checkType(Check.java:324)
	at com.sun.tools.javac.comp.Attr.check(Attr.java:160)
	at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1276)
	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1210)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:377)
	at com.sun.tools.javac.comp.Attr.visitAssign(Attr.java:1550)
	at com.sun.tools.javac.tree.JCTree$JCAssign.accept(JCTree.java:1342)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:384)
	at com.sun.tools.javac.comp.Attr.visitExec(Attr.java:1017)
	at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1074)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.visitIf(Attr.java:1009)
	at com.sun.tools.javac.tree.JCTree$JCIf.accept(JCTree.java:1050)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.visitForLoop(Attr.java:740)
	at com.sun.tools.javac.tree.JCTree$JCForLoop.accept(JCTree.java:818)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.visitIf(Attr.java:1009)
	at com.sun.tools.javac.tree.JCTree$JCIf.accept(JCTree.java:1050)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.visitIf(Attr.java:1009)
	at com.sun.tools.javac.tree.JCTree$JCIf.accept(JCTree.java:1050)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:634)
	at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:639)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
	at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:2697)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2628)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2564)
	at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1036)
	at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:765)
	at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:730)
	at com.sun.tools.javac.main.Main.compile(Main.java:353)
	at com.sun.tools.javac.main.Main.compile(Main.java:279)
	at com.sun.tools.javac.main.Main.compile(Main.java:270)
	at com.sun.tools.javac.Main.compile(Main.java:69)
	at com.sun.tools.javac.Main.main(Main.java:54)
</pre>
<p></code></p>
<p>I was not successful at reducing this crash to a simple test case.</p>
<p>However, the line that triggered the crash was:</p>
<p><code></p>
<blockquote><p>ProxyMapperImplementor&lt;?,?> childProxy = this;</p></blockquote>
<p></code></p>
<p>Some points:</p>
<ul>
<li><a href="http://www.sworddance.com/blog/2010/01/06/generic-annoyances-in-java/">Once again</a> (<a href="http://www.sworddance.com/blog/2007/08/13/explain-this/">and again</a>) the eclipse compiler is more robust than the sun javac</li>
<li>ProxyMapperImplementor is defined as:<br />
<code><br />
<blockquote>interface ProxyMapperImplementor&lt;I, O extends I></p></blockquote>
<p></code></li>
<li>Removing the wildcards so the line looks like solved the problem:<code><br />
<blockquote><p>ProxyMapperImplementor childProxy = this;</p></blockquote>
<p></code></p>
<p>Update (email from sun):</p>
<blockquote><p>This issue is related to Bug ID: 6738538. You can review this bug at:</p>
<p>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6738538</p>
<p>This problem has been fixed in Java SE 7.0. Consider downloading a free copy at http://download.java.net/jdk7/binaries/ and checking if the problem persists. If the problem persists do let us know and we shall investigate this furthur.</p>
<p>We greatly appreciate your efforts in identifying areas in the Java Standard Edition where we can improve upon and I would request you to continue doing so.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/01/07/woot-i-crashed-the-javac/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Generic annoyances in java</title>
		<link>http://sworddance.com/blog/2010/01/06/generic-annoyances-in-java/</link>
		<comments>http://sworddance.com/blog/2010/01/06/generic-annoyances-in-java/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 01:14:31 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[help notes]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=548</guid>
		<description><![CDATA[For some reason, the type variable &#60;O> cannot flow through from an external caller through a callee to another called method. This compiles just fine in eclipse, but once again sun&#8217;s javac is temperamental. The three solutions seem to be: &#8230; <a href="http://sworddance.com/blog/2010/01/06/generic-annoyances-in-java/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For some reason, the type variable &lt;O> cannot flow through from an external caller through a callee to another called method.</p>
<p>This compiles just fine in eclipse, but <a href="http://www.sworddance.com/blog/2007/08/13/explain-this/">once again sun&#8217;s javac is temperamental.</a> </p>
<p>The three solutions seem to be:</p>
<ol>
<li>pass an object of type &lt;O> to the subcallee method (m0(), p0() )</li>
<li>use wildcard instead of &lt;O> &#8211; which is o.k. if O is not needed in the body of the method</li>
<li>assign to a variable with no generic information (universal backup solution to java generic wierdness)</li>
</ol>
<p>I filed a bug with Sun.</p>
<p>(Technical details: javac 1.6.0_17 )</p>
<p><code></p>
<pre>public class Foo {
    public <I, O extends I, R extends FooInterface<I, O>> I m(I i) {
/*line3*/        R r = (R) p(i);
        return i;
    }
    public <I, O extends I, R extends FooInterface<I, O>> R p(I i) {
        return null;
    }

    public <I, O extends I, K extends FooInterface<I, O>> I m0(O o) {
        K r= (K) p0(o);
        return o;
    }
    public <I, O extends I, K extends FooInterface<I, O>> K p0(O o) {
        return null;
    }

    public <I, K extends FooInterface<I, ? extends I>> I m1(I i) {
        K r= (K) p1(i);
        return i;
    }
    public <I, K extends FooInterface<I, ? extends I>> K p1(I i) {
        return null;
    }

    public <I, K extends FooInterface<I, ? extends I>> I m2(I i) {
/*line 27*/        K r= (K) p2(i);
        return i;
    }
    public <I, O extends I, K extends FooInterface<I, O>> K p2(I i) {
        return null;
    }
    interface FooInterface<I, O extends I> {

    }
}
</pre>
<p></code></p>
<p><code>Foo.java:3: incompatible types; inferred type argument(s) I,java.lang.Object do not conform to bounds of type variable(s) O,R<br />
found   : <O,R>R<br />
required: java.lang.Object<br />
/*line3*/        R r = (R) p(i);<br />
                            ^<br />
Foo.java:27: incompatible types; inferred type argument(s) I,java.lang.Object do not conform to bounds of type variable(s) O,K<br />
found   : <O,K>K<br />
required: java.lang.Object<br />
        K r= (K) p2(i);<br />
                   ^</code></p>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2010/01/06/generic-annoyances-in-java/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Gmail and the Electrical Grid: Looks the same</title>
		<link>http://sworddance.com/blog/2009/09/02/gmail-and-the-electrical-grid-looks-the-same/</link>
		<comments>http://sworddance.com/blog/2009/09/02/gmail-and-the-electrical-grid-looks-the-same/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 18:03:51 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=515</guid>
		<description><![CDATA[GMail had a large-scale cascading failure yesterday: At about 12:30 pm Pacific a few of the request routers became overloaded and in effect told the rest of the system &#8220;stop sending us traffic, we&#8217;re too slow!&#8221;. This transferred the load &#8230; <a href="http://sworddance.com/blog/2009/09/02/gmail-and-the-electrical-grid-looks-the-same/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://gmailblog.blogspot.com/2009/09/more-on-todays-gmail-issue.html">GMail had a large-scale cascading failure yesterday</a>:</p>
<blockquote><p>At about 12:30 pm Pacific a few of the request routers became overloaded and in effect told the rest of the system &#8220;stop sending us traffic, we&#8217;re too slow!&#8221;. This transferred the load onto the remaining request routers, causing a few more of them to also become overloaded, and within minutes nearly all of the request routers were overloaded.</p></blockquote>
<p>This cascading failure sounds exactly like that other universal network we all share: The electrical grid.</p>
<p>Large blackouts are cascading failures compounded by the failure of the &#8220;fuses&#8221; meant to isolate still functioning parts of the grid from the failed part.</p>
<p>Sounds a lot like what happened to gmail. </p>
<p>Interestingly the smart people at Google have recognized exactly that:</p>
<blockquote><p>we have concluded that request routers don&#8217;t have sufficient failure isolation (i.e. if there&#8217;s a problem in one datacenter, it shouldn&#8217;t affect servers in another datacenter) and do not degrade gracefully (e.g. if many request routers are overloaded simultaneously, they all should just get slower instead of refusing to accept traffic and shifting their load).</p></blockquote>
<p>Sounds like a good start. But what happens if a datacenter catestrofically fails. The routers stop accepting requests because they are gone ( or can&#8217;t respond ). Prepare for the next GMail failure. </p>
<p><a href ="http://en.wikipedia.org/wiki/Power_outage" rel="nofollow">As wikipedia notes:</a></p>
<blockquote><p>Modern power systems are designed to be resistant to this sort of cascading failure, but it may be unavoidable (see below). Moreover, since there is no short-term economic benefit to preventing rare large-scale failures, some observers have expressed concern that there is a tendency to erode the resilience of the network over time, which is only corrected after a major failure occurs. It has been claimed that reducing the likelihood of small outages only increases the likelihood of larger ones. In that case, the short-term economic benefit of keeping the individual customer happy increases the likelihood of large-scale blackouts.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2009/09/02/gmail-and-the-electrical-grid-looks-the-same/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mac OSX  &#8212; the most insecure OS around</title>
		<link>http://sworddance.com/blog/2009/08/07/mac-osx-the-most-insecure-os-around/</link>
		<comments>http://sworddance.com/blog/2009/08/07/mac-osx-the-most-insecure-os-around/#comments</comments>
		<pubDate>Fri, 07 Aug 2009 08:35:12 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[broken]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=476</guid>
		<description><![CDATA[A year ago, I gave up on Windows. I was tired of the nervous eggshell feeling with anti-virus software, security patches, and a machine that would mysteriously be slower and slower no matter what I did. Because of MacOSX Unix &#8230; <a href="http://sworddance.com/blog/2009/08/07/mac-osx-the-most-insecure-os-around/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A year ago, I gave up on Windows. I was tired of the nervous eggshell feeling with anti-virus software, security patches, and a machine that would mysteriously be slower and slower no matter what I did.</p>
<p>Because of MacOSX Unix roots, I made the switch to MacOSX confident that my personal computer would be safe.</p>
<p>This faith has been severely shaken. I now regard MacOSX as one of the most INSECURE operation systems.</p>
<p>MacOSX has a dangerous default DNS/DHCP configuration. Even worse, this dangerous configuration can not be fixed from the UI. Even the command line fix is difficult. And worst of all Apple is aware of this and does nothing.</p>
<p>There are 5 bits of background you should know:</p>
<ol>
<li>DNS is a fundamental part of the internet. DNS is the &#8216;name resolution&#8217; service that converts &#8216;mail.google.com&#8217; into the ipaddress: &#8217;74.125.19.19&#8242; which is what your computer really uses to contact GMail servers so you can read your email. This conversion from the human readable &#8216;mail.google.com&#8217; to  &#8217;74.125.19.19&#8242; is analogous to the post office converting the postal address on your snail mail envelope to a Zip+4 encoding that is printed at the bottom of the envelope. This encoding is what is actually read by the postal service mail sorting machines to determine where your snail mail goes. Now imagine that the postal service&#8217;s encoding machine was compromised. This compromised postal encoding machine was changed so that no matter what the Zip+4 code was supposed to be the machine always encoded the location of Dick Cheney&#8217;s house. As a result, all your mail that was processed by that compromised postal service would go first to Dick Cheney. Dick Cheney would get a chance to open all your snail mail, read it, copy it, etc. He could then reseal the original envelope, reencode the envelope with the correct barcode and put the envelope back in the postal service system to be delivered to the correct address.  so that no matter what address you had actually printed on your envelope. All this would happen without you being aware of the problem nor able to stop it from happening.
<p>Everything internet related depends on correct translation of &#8216;apple.com&#8217; or &#8216;bankofamerica.com&#8217; to the correct IP address, not some third party server.  How does the your machine know that it is communicating with apple.com and not some evil server? Your computer relies on the DNS lookup being correct. If the DNS lookup is compromised then when your software update runs to check for the latest security patches it is really installing a virus from evilserver.com not apple.com.</p>
<p>There has been recent concern about DNS spoofing. ( links ). Being the cautious person that I am, I decided to explicitly listed <a href="http://opendns.org">opendns.org</a>&#8216;s DNS servers (208.67.222.222 and 208.67.220.220) as the DNS Servers to trust in my Network configuration. I felt pretty cocky and safe.</li>
<li>The second bit of the puzzle is DHCP. In order to talk to the world, computers need to have their own personal unique ipaddress (it&#8217;s very own ZIP+4 code). Every time you go into an internet cafe and pop open your laptop, your laptop uses the DHCP service to figure out what unique ipaddress (192.168.1.101)  it should use while you are in that cafe. DHCP is nice because otherwise you would have to manually figure out and set an ipaddress for your computer that is different than everyone else&#8217;s laptop. And if someone else picks the same address as you did, all of a sudden your internet connection starts behaving odd. In addition to supplying a ipaddress, the DHCP server also supplies a DNS server that should be used. This is useful when you have your laptop at work and you need to go to an internal website such as http://go/wave Notice there is no &#8216;.org&#8217;, or &#8216;.com&#8217; after &#8216;http://go/&#8217; this means that &#8216;go&#8217; is only visible when you are at work and can access the internal DNS server using the information that the corporate DHCP server supplied to your laptop.
<p>So to summarize DHCP supplies your laptop with the information needed for the world to talk to your laptop ( by assigning an ipaddress to your computer) , and  helps you find out about the world (by telling your computer about the corporate DNS server). DNS servers enables your laptop talk to the world by giving your laptop a &#8216;go-to-machine&#8217; for all its addressing questions.</li>
<li>Third, DNS servers are usually big expensive computers secured by &#8220;smart people&#8221;. However, the DHCP server is really just a bit of software running on a Linksys router at your internet cafe. Your internet cafe&#8217;s Linksys router probably has the default password and no one ever checks on it. There are millions of this routers, with minimal security, no one checking on them and your laptop is trusting these unsecured routers with the keys to your kingdom. Your laptop is asking this router &#8212; &#8220;tell me which DNS server to trust?&#8221;</li>
<li>Fourth, Lets say that you are paranoid enough to say &#8221; ohh this is bad. I am not going to trust such a router in a greasy, dark corner with telling my precious laptop which DNS server to trust.&#8221; So if you are like me you configure your laptop with an explicit list of DNS servers thinking that your laptop, especially your oh-so-secure Mac would never disobey you about something so critical as DNS.</li>
<li>Fifth, you would be wrong. The insecure MacOSX does disobey and it does trust that greasy spoon router over you. MacOsX doesn&#8217;t let the user (YOU!) say that only certain machines are allowed to be your laptop&#8217;s DNS servers! Furthermore even if you have supplied your own custom DNS servers that you trust, the insecure MacOSX trusts the greasy spoon DHCP server&#8217;s DNS servers over your trusted DNS servers. And there is NO way to convince MacOSX otherwise.</li>
</ol>
<p>This means that if the DHCP server at your internet cafe has been compromised you are as well. </p>
<p><strong>How I found out</strong></p>
<p>So here I am feeling all cocky and safe. I type in my company&#8217;s web address, &#8216;amplafi.net&#8217; and amplafi.net resolved to <strong>113.29.236.168</strong> which offered that the website was for sale!&#8230; I freaked out!</p>
<p><img src="http://www.sworddance.com/blog/wp-content/uploads/2009/08/hacked-dns-300x187.jpg" alt="hacked-dns" title="hacked-dns" width="300" height="187" class="alignnone size-medium wp-image-475" /></p>
<p>I discovered my MacOSX laptop  was insisting on trusting these <strong>EVIL DNS servers 206.13.28.12 206.13.31.12</strong> . Was the 10.5.8 OSX patch that was installed 6 hours ago really what it seemed? Who knows? When I installed updates to Firefox plugins was I really installing the correct versions or a compromised version that would report back to some site in Russia all my bank account information? I have no way of knowing.</p>
<p>This is the really scary part about everything.<a href="http://www.macosxhints.com/article.php?story=20080725172011439&#038;mode=print"> John Simpson reports</a>:</p>
<blockquote><p>Under 10.4 and earlier, when I specified a custom nameserver, the system would use only the nameserver(s) I specified. However, under 10.5 Apple has apparently changed that behavior, and uses my specified nameservers in addition to the DNS servers specified by the DHCP server. It shows the DHCP-provided server IP on the list, greyed out, so you can&#8217;t delete it. </p>
<p>For a while, I adopted a &#8220;grin and bear it&#8221; attitude &#8212; after all, the DHCP server at home is handing out the IP of my internal Linux server (also running djbdns) as the DNS server, so I was only unsafe when I used the laptop outside the house. However, with the recently announced <a href="http://www.kb.cert.org/vuls/id/800113">vulnerability in the DNS protocol</a>, <a href="http://it.slashdot.org/it/08/07/08/195225.shtml">the massive world-wide patch effort by major DNS vendors</a>, and the fact that many networks haven&#8217;t applied the patches yet, I don&#8217;t really feel safe relying on anybody else&#8217;s nameservers.</p>
<p><em><strong>I tried calling Apple about this, but it turns out that my AppleCare contract doesn&#8217;t cover technical support such as this.</strong> </em></p>
<p>My next approach was to just brute-force search the system for anything relating to DHCP. It took a while, but I was able to find the file which needed to be changed, and figure out the necessary changes. Basically, I found a file which controls which options are used by the DHCP client when handling a response from a DHCP server. I removed the DNS-related options from this list, and after rebooting the system, the laptop now ignores the DNS server options being sent by the DHCP server. </p>
<p>The file I found is named IPConfiguration.xml, and it&#8217;s buried in this folder: /System/Library/SystemConfiguration/IPConfiguration.bundle/Contents/Resources. You need to create a copy of that file, edit the copy, and remove a few entries in the DHCPRequestedParameterList key. (The entries to remove are those for 6, 15, and 119.) I have added full details on this process to my djbdns setup page, in the section titled Disabling DNS servers from DHCP. </p></blockquote>
<p>Thankfully I found <a href="http://qmail.jms1.net/djbdns/osx.shtml#dhcp-nameserver">this web page from 2008(!) that showed how to fix this problem (thanks John M. Simpson)</a>:</p>
<blockquote><p>
It is possible to make the DHCP client ignore the &#8220;DNS server&#8221; options in the DHCP response. It&#8217;s not for the faint of heart, but if you&#8217;ve been able to handle the rest of the instructions on this page, you can handle this bit as well.</p>
<p>I have done this on my own laptop (a MacBook Pro) and it does work.</p>
<p>Be aware that this is a GLOBAL change. If you do this, your machine will not use the DNS servers specified by any DHCP server. This may affect your machine&#8217;s ability to easily work with corporate networks (especially those using Windows Active Directory) or other networks which use private DNS namespaces.</p>
<pre>
$ sudo -s
Password: You will not see your password as you enter it.
# cd /System/Library/SystemConfiguration/IPConfiguration.bundle/Contents/Resources
# vi IPConfiguration.xml

Find this block...

        &lt;key>DHCPRequestedParameterList&lt;/key>
        &lt;array>
                &lt;integer>1&lt;/integer>
                &lt;integer>3&lt;/integer>
                &lt;integer>6&lt;/integer>
                &lt;integer>15&lt;/integer>
                &lt;integer>119&lt;/integer>
                &lt;integer>95&lt;/integer>
                &lt;integer>252&lt;/integer>
                &lt;integer>44&lt;/integer>
                &lt;integer>46&lt;/integer>
                &lt;integer>47&lt;/integer>
        &lt;/array>
</pre>
<p>Comment out the 6, 15, and 119 entries. The result should look like this:</p>
<pre>
        &lt;key>DHCPRequestedParameterList&lt;/key>
        &lt;array>
                &lt;integer>1&lt;/integer>
                &lt;integer>3&lt;/integer>
                &lt;!-- commented out so that Bad DNS servers coming from DHCP servers
                are not used.
                &lt;integer>6&lt;/integer>
                &lt;integer>15&lt;/integer>
                &lt;integer>119&lt;/integer>
                -->
                &lt;integer>95&lt;/integer>
                &lt;integer>252&lt;/integer>
                &lt;integer>44&lt;/integer>
                &lt;integer>46&lt;/integer>
                &lt;integer>47&lt;/integer>
        &lt;/array>
</pre>
<p>Save your changes.
</p></blockquote>
<p>Be sure to flush the DNS cache.</p>
<p>On MacOsX:</p>
<blockquote><p>dscacheutil -flushcache</p></blockquote>
<p>I have tried John&#8217;s suggestion and those scary DNS servers are no longer present. But has my machine been compromised already? I will be visiting the apple store in a few hours asking for answers.</p>
<p>The story continues. I was sitting next to a customer. On her windows box she was picking up the same bad DNS servers. It wasn&#8217;t until later when I got home that I discovered all this information. I suspect (but am not completely certain) that windows will not override an explicitly specified DNS server.</p>
<p>Update: So after talking with some people, its pretty clear that MacOsX shares this issue with Windows XP because offering out internal DNS servers is part of what DHCP does. However with Windows XP, it is easy to explicitly lock down the DNS servers.  </p>
<p>How to lock down a Windows XP box with safe DNS servers:</p>
<p>On Windows:</p>
<p><img src="http://www.sworddance.com/blog/wp-content/uploads/2009/08/network-connections-step1.JPG" alt="network-connections-step1" title="network-connections-step1" width="803" height="300" class="aligncenter size-full wp-image-490" /></p>
<p><img src="http://www.sworddance.com/blog/wp-content/uploads/2009/08/before-changing-dns-step2.JPG" alt="before-changing-dns-step2" title="before-changing-dns-step2" width="799" height="300" class="aligncenter size-full wp-image-491" /></p>
<p><img src="http://www.sworddance.com/blog/wp-content/uploads/2009/08/use-opendns-dns-servers-step3.JPG" alt="use-opendns-dns-servers-step3" title="use-opendns-dns-servers-step3" width="404" height="300" class="aligncenter size-full wp-image-492" /></p>
<p>To clear Windows DNS cache:</p>
<blockquote><p>ipconfig /flushdns</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2009/08/07/mac-osx-the-most-insecure-os-around/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Code Review #8: When to comment</title>
		<link>http://sworddance.com/blog/2009/03/16/when-to-comment/</link>
		<comments>http://sworddance.com/blog/2009/03/16/when-to-comment/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 18:10:10 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[code review]]></category>
		<category><![CDATA[management]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=357</guid>
		<description><![CDATA[The last ? in a series of posts about commenting. See &#8220;the why&#8221;. See &#8220;not commenting is career threatening&#8221;. And the comment that started this off! This post should have really been the second one I wrote. The first post &#8230; <a href="http://sworddance.com/blog/2009/03/16/when-to-comment/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The last ? in a series of posts about commenting. See <a href="http://www.sworddance.com/blog/2009/03/04/code-review-7-comment-the-why-not-the-what/">&#8220;the why&#8221;</a>. See <a href="http://www.sworddance.com/blog/2009/03/04/not-commenting-code-is-dangerous-to-your-career/">&#8220;not commenting is career threatening&#8221;</a>. And <a href="http://www.sworddance.com/blog/2007/05/29/thoughts-on-how-to-evaluate-code/#comment-16341">the comment that started this off</a>!</p>
<p>This post should have really been the second one I wrote. The <a href="http://www.sworddance.com/blog/2007/05/29/thoughts-on-how-to-evaluate-code">first post was about who a developer needs to keep happy</a> &#8211; the client or <a href="http://www.sworddance.com/blog/2009/03/04/not-commenting-code-is-dangerous-to-your-career/">the manager</a>.</p>
<p>But commenting everything is both hard, excessive, and wasteful of time. In &#8220;the why&#8221; post, I cover what should be in the comments &#8211; implicitly I was limiting comments to just the places where knowing &#8220;the why&#8221; is important.</p>
<p>However, still the question is &#8220;when&#8221; should a developer comment?</p>
<p>Here is my rule of thumb:</p>
<ul>
<li>Any developer had to spend time figuring out what the code did. Refactor it and if still not clear comment the code with questions and assumptions. (Just in case the refactoring introduced a bug or caused an existing bug to appear.)</li>
<li>Another developer asks the implementing developer (or the current &#8220;owner&#8221;/responsible developer) about the code, interfaces, package. The developer asking the question copy the explanation into the code, cleaning up the chat log/email response and adding further edits and explanation as needed.</li>
<li>The code is not going to have further development for a while. Comment the code enough so that when development is resumed, the restart is faster.</li>
<li>The code is being handed off from one developer to another.</li>
<li>Key interfaces that are used by multiple groups.</li>
</ul>
<p>And managers give developers time to wrap up and add these comments.</p>
<p>Conversely, what is not worth commenting:</p>
<ul>
<li>Code that is actively, daily, being changed rearchitected. Every developer already knows what the comments would say and the structure is changing fast enough that the comments would become outdated.</li>
<li>Code that does not impact data integrity and end-user experience in a horrid way.</li>
<li>Utility classes/ methods.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2009/03/16/when-to-comment/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why and when to wrap external library classes</title>
		<link>http://sworddance.com/blog/2009/03/16/why-and-when-to-wrap-external-library-classes/</link>
		<comments>http://sworddance.com/blog/2009/03/16/why-and-when-to-wrap-external-library-classes/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 17:47:09 +0000</pubDate>
		<dc:creator>patrick</dc:creator>
				<category><![CDATA[code review]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.sworddance.com/blog/?p=315</guid>
		<description><![CDATA[At some point, every developer starts using an external library. They then have to decide if that external library should be wrapped in their own custom interfaces and classes. If the external library would be pervasively imported in throughout the &#8230; <a href="http://sworddance.com/blog/2009/03/16/why-and-when-to-wrap-external-library-classes/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At some point, every developer starts using an external library. They then have to decide if that external library should be wrapped in their own custom interfaces and classes. </p>
<p>If the external library would be pervasively imported in throughout the code then the answer is empathically YES &#8212; the external library should be wrapped.</p>
<p>At Amplafi, <a href="http://hibernate.org" target="_blank">hibernate</a> is just such a library. Without wrapping every time the hibernate library changed its structure or behavior, the change would have a large impact. However, by wrapping the libraries hibernate became loosely coupled.</p>
<p>This also enabled us to solve other more major issues with Hibernate Query and Session.</p>
<p>Specifically:</p>
<ul>
<li>control when a transaction could be committed. We wanted to count how many times a tx was &#8220;started&#8221; and only commit when the tx was &#8220;ended&#8221; the same number of times it was started. Useful for code that doesn&#8217;t know if it needs to start a transaction. Now any code that needs a tx just &#8220;starts&#8221; one and ends it when done.</li>
<li>Performance metrics gathering.</li>
<li>Delaying starting the transaction until it is known that something will actually be done.<br />
More gentle behavior for query.uniqueResult() ( default Hibernate behavior is to throw an exception if there is more than one row returned. Amplafi&#8217;s wrapper logs the non-uniqueness + ids of the extra rows. ) </li>
</ul>
<p>How we did this:</p>
<ol>
<li>Create an interface (AmplafiQuery) that extends Query</li>
<li>Create a class (AmplafiQueryImpl) that extends AmplafiQuery and wraps a org.hibernate.Query</li>
<li>Create a Txmanager that returns a Tx.</li>
<li>Tx has the various createQuery methods and returns AmplafiQuery</li>
</ol>
<p>We also took the opportunity to add to AmplafiQuery:</p>
<ul>
<li>a &#8220;asList()&#8221; that is a generic enabled version of Query.list()</li>
<li>a &#8220;unique()&#8221; that is a generic enabled version of Query.uniqueResult()</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sworddance.com/blog/2009/03/16/why-and-when-to-wrap-external-library-classes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
