<?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>Absolutely No Machete Juggling</title>
	<atom:link href="http://www.nomachetejuggling.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nomachetejuggling.com</link>
	<description>Rod Hilton's views on programming, technology, and life.</description>
	<lastBuildDate>Wed, 27 Jan 2010 01:53:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>You Have To Buy It Twice Before It’s Cheap</title>
		<link>http://www.rallydev.com/engblog/2010/01/26/you-have-to-buy-it-twice-before-its-cheap/</link>
		<comments>http://www.rallydev.com/engblog/2010/01/26/you-have-to-buy-it-twice-before-its-cheap/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 20:56:40 +0000</pubDate>
		<dc:creator>The Rally Software Engineering Blog</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[crossposted]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Estimating]]></category>
		<category><![CDATA[estimation]]></category>
		<category><![CDATA[Incremental Design]]></category>

		<guid isPermaLink="false">http://www.rallydev.com/engblog/?p=577</guid>
		<description><![CDATA[One of the most common sources of tension between product owners and developers is when product owners are surprised at how high an estimate for a story might be.  Usually this tension is easy to resolve by reiterating that the product owners really have no concept of how much something should cost.  However, [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most common sources of tension between product owners and developers is when product owners are surprised at how high an estimate for a story might be.  Usually this tension is easy to resolve by reiterating that the product owners really have no concept of how much something should cost.  However, there is one scenario I see over and over again: when a product owner protests the estimate of a story because it seems, to the PO, like it&#8217;s simply re-using an aspect of the system somewhere else.</p>
<p>&#8220;I already paid for that!&#8221; he or she might say, quite correctly.  A simple example recently for us here was our column picker.  Our grids allow you to select which columns you wish to see on any given grid.  Later on, we created the ability to have grids inside of panels on user dashboards.  Our product owner wanted to put the column picker on the settings pane of a grid panel.  To him, this was simply reusing the column picker that had already been created for an earlier story.  He was quite shocked when our estimate for the effort was just as high as it was the first time.</p>
<p>His frustration is completely understandable.  How is this possible?  Why isn&#8217;t it easy to just drop that component into another place and have it work?  After all, if we were good engineers, wouldn&#8217;t we have written that component to be reusable?</p>
<p>Actually, <strong>no</strong>.  It&#8217;s <strong>because</strong> we were good engineers that it wasn&#8217;t written in that way.  This is one of the hardest things for product owners to understand, and I hope to explain it in this post.</p>
<span id="more-672"></span>

<p><strong>Evolutionary Design</strong></p>
<p>Once upon a time, development teams worked in specific phases.  First they would design all of the code they were going to write; boxes would be drawn on whiteboards, sequences captured in documents, and so on.  Once the design was finished, the developers would go off and write the code for it.  Luckily, our industry has realized that this is a problematic way to write software.</p>
<p>It&#8217;s simply not likely that the team will discover all of the quirks of the design during the design phase.  It&#8217;s even more likely that requirements and features will change during the long span of time this process takes, forcing the developers to throw away work and go &#8220;back to the drawing board&#8221; on the design.  Splitting the design phase from the coding phase is a recipe for disaster.</p>
<p>Instead, it&#8217;s generally preferable to practice <a href="http://en.wikipedia.org/wiki/Continuous_design">evolutionary design</a>; allow the design to grow organically as the code is written.  This, combined with testing and refactoring, seems to be the best known way to ensure that the quality of the code remains high as a product grows.</p>
<p>Doing this makes it easier to deal with changes that effect design, and it prevents the team from wasting time going &#8220;back to the drawing board&#8221; in the event a problem is discovered.</p>
<p><strong>YAGNI</strong></p>
<p>One principle to follow as you code is the <a href="http://en.wikipedia.org/wiki/YAGNI">YAGNI</a> principle.  YAGNI means &#8220;You Ain&#8217;t Gonna Need It&#8221; and essentially it means that developers should discourage themselves from adding additional code to support something that is not, at the time, required.  Developers have a strong desire to add code here or there while editing code, and YAGNI helps us remember to resist the urge to add superfluous code or functionality.</p>
<p>Following this principle helps eliminate waste, and helps keep developers focused on adding value that product owners want.  But why?</p>
<p>If I&#8217;m editing <strong><em>Module A</em></strong> to add <strong><em>Functionality X</em></strong>, why not just add <strong><em>Functionality Y</em></strong> while I&#8217;m there?  It may delay the delivering of <strong><em>Functionality X</em></strong> in the short-term, but later when it&#8217;s decided that <strong><em>Functionality Y</em></strong> must be supported as well, it will be dirt cheap, right?</p>
<p>The trick to understanding why YAGNI helps is realizing that there are thousands upon thousands of potential <strong><em>Module A</em></strong>s in a system.  The truth is, <strong><em>Functionality Y</em></strong> may simply never be required.  And even if it is, <strong><em>Functionality Z</em></strong> may not be.  Adding that functionality would be a waste of time and resources if it&#8217;s never used.</p>
<p><strong>YAGNI Applied to Design</strong></p>
<p>The same principle behind YAGNI can be extended to aspects of high-level design.  When we originally designed the Column Picker component, it was not designed to be dropped into any part of the system.  This was intentional: if we had spent the time to make the Column Picker completely generic and reusable, but then had never needed to drop it into another part of the system, the additional effort required to make it super-generic would have been a wasted effort.  This is true for any aspect of the system being designed: we can spend the extra time and effort to make something extremely generic, but if that generality is never needed, that time is waste.  Many times developers will refer to something that&#8217;s overly generic as &#8220;over-engineered.&#8221;</p>
<p>This means that the description of the component can often be misleading.  We never built &#8220;a column picker&#8221; &#8211; we built &#8220;a column picker for a grid page&#8221;.  The column picker was written in a way that assumed it was part of a grid page.  Again, it could have been written more generically, but doing so would have potentially created waste (<em>this does not mean that it&#8217;s alright to design code that violates <a href="http://en.wikipedia.org/wiki/Solid_(Object_Oriented_Design)">principles of good design</a>.   Code can be well-designed but still not fully generic</em>).</p>
<p>So when it came time to put the component in a completely different context than the one for which it was designed, it was still a lot of work: almost as much as was originally required to make the first pass.  Though some time was saved simply because it was a known and well-understood problem for which we would leverage newly-developed knowledge, it still effectively required writing a whole new component: one that was much more generic and utilized what it could of the previous increment.</p>
<p>Essentially, to avoid having developers waste time, components should be &#8220;generic on demand&#8221;.  Once a component needs to be reused, then it should be refactored into something extremely generic, but not before.  The end result is that a product owner will have to pay for a component twice before it&#8217;s cheap.</p>
<p>This may seem counterintuitive to product owners, but it&#8217;s important to understand.  Because the team approaches coding in a way that causes the second time to be nearly as expensive as the first, the team is able to deliver <strong>everything else</strong> quickly.</p>
<p>The first time, it is costly because the developers have to solve unknowns and create something new from scratch.</p>
<p>The second time, it is costly because it has to be molded into something generic and reusable.</p>
<p>The third time, however, is cheap.</p>
<img src="http://www.rallydev.com/engblog/?ak_action=api_record_view&id=577&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.rallydev.com/engblog/2010/01/26/you-have-to-buy-it-twice-before-its-cheap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quantitatively Evaluating Test-Driven Development</title>
		<link>http://www.nomachetejuggling.com/2009/12/13/quantitatively-evaluating-test-driven-development/</link>
		<comments>http://www.nomachetejuggling.com/2009/12/13/quantitatively-evaluating-test-driven-development/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 05:50:46 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[Test-Driven Design]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=646</guid>
		<description><![CDATA[The thesis for my Master&#8217;s degree in Software Engineering is finished.
It&#8217;s the result of many months of research, I hope others may find it interesting and informative.
Abstract
Test-Driven Development is a Software Engineering practice gaining increasing popularity within the software industry. Many studies have been done to determine the effectiveness of Test-Driven Development, but most of [...]]]></description>
			<content:encoded><![CDATA[<p>The thesis for my Master&#8217;s degree in Software Engineering is finished.</p>
<p>It&#8217;s the result of many months of research, I hope others may find it interesting and informative.</p>
<p><strong>Abstract</strong></p>
<p>Test-Driven Development is a Software Engineering practice gaining increasing popularity within the software industry. Many studies have been done to determine the effectiveness of Test-Driven Development, but most of them evaluate effectiveness according to a reduction in defects. This kind of evaluation ignores one of the primary claimed benefits of Test-Driven Development: that it improves the design of code. To evaluate this claim of Test-Driven Development advocates, it is important to evaluate the effect of Test-Driven Development upon object-oriented metrics that measure the quality of the code itself. Some studies have measured code in this manner, but they generally have not worked with real-world code written in a natural, industrial setting. Thus, this work utilizes Open Source Software as a sample for evaluation, separating Open Source projects that were written using Test-Driven Development from those that were not. These projects are then evaluated according to various object-oriented metrics to determine the overall effectiveness of Test-Driven Development as a practice for improving the quality of code. This study finds that Test-Driven Development provides a substantial improvement in code quality in the categories of cohesion, coupling, and code complexity.</p>
<p><strong>Download</strong></p>
<p>If you&#8217;d like to read it, you can download it here:</p>
<p><a href='http://www.nomachetejuggling.com/files/tdd_thesis.pdf'>Quantitatively Evaluating Test-Driven Development by Applying Object-Oriented Quality Metrics to Open Source Projects</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/12/13/quantitatively-evaluating-test-driven-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Units are Not Classes: Improving Unit Testing By Removing Artificial Boundaries</title>
		<link>http://www.rallydev.com/engblog/2009/11/17/units-are-not-classes/</link>
		<comments>http://www.rallydev.com/engblog/2009/11/17/units-are-not-classes/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 20:53:42 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Automated Testing]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[crossposted]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[mocking]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[Refactoring]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.rallydev.com/engblog/?p=424</guid>
		<description><![CDATA[Many developers think of unit tests as tests that test a single class.  In fact, I myself once thought this way.  If I wanted to write unit tests for a two-class system in which a class used another class, I&#8217;d write two unit tests.  After all, if I created instances of both [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.rallydev.com%2Fengblog%2F2009%2F11%2F17%2Funits-are-not-classes%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.rallydev.com%2Fengblog%2F2009%2F11%2F17%2Funits-are-not-classes%2F" height="61" width="51" /></a></div><p>Many developers think of unit tests as tests that test a single class.  In fact, I myself once thought this way.  If I wanted to write unit tests for a two-class system in which a class used another class, I&#8217;d write two unit tests.  After all, if I created instances of both classes in my test, that wouldn&#8217;t <strong>really</strong> be a unit test, would it?</p>
<p>In recent years, I have revised my stance on this matter.  This distinction between what is and is not a unit test is one I no longer draw in the same way.</p>
<p>Unit Tests need to be:</p>
<ul>
<li><strong>Fast</strong> &#8211; Unit Tests should never run so slowly that they discourage developers from running them all the time.</li>
<li><strong>Focused</strong> &#8211; Unit Tests should focus on a single area so that they can isolate problems to that area when they fail.</li>
</ul>
<p>Once upon a time, I thought &#8216;focused&#8217; meant that it should be focused on a single class.  Instead, it should focus on an area, but that area can include multiple classes.</p>
<p><span id="more-424"></span></p>
<p><strong>An Example</strong></p>
<p>Let&#8217;s say we have a simple Calculator class with some tests (normally we&#8217;d write the tests first, but since we&#8217;re talking about the tests in this post we&#8217;re going to write them afterwards).  As with any example fabricated for demonstration purposes, the classes in this post have little need for the level of testing I will be applying to them, but they serve an illustrative purpose.</p>
<pre class="brush: java;">
package com.rallydev.engblog.unittesting;

public class Calculator {

  public int calculate(char operation, int operand1, int operand2) {
    switch (operation) {
    case '+':
      return operand1 + operand2;
    case '-':
      return operand1 - operand2;
    default:
      throw new UnsupportedOperationException(String.format(
          &quot;'%s' is not a known operation&quot;, operation));
    }
  }

}
</pre>
<p>Here is the test for this class:</p>
<pre class="brush: java;">
package com.rallydev.engblog.unittesting;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {

  private Calculator calculator;

  @Before
  public void setUp() {
    this.calculator = new Calculator();
  }

  @Test
  public void shouldAdd() {
    assertEquals(5, calculator.calculate('+', 2, 3));
  }

  @Test
  public void shouldSubtract() {
    assertEquals(1, calculator.calculate('-', 5, 4));
  }

  @Test(expected = UnsupportedOperationException.class)
  public void shouldThrowExceptionForUnknownOperation() {
    calculator.calculate('Q', 1, 2);
  }
}
</pre>
<p>But after thinking about it, we realize that the responsibility for parsing what the caller wants to do and the responsibility for actually performing that operation should be separated.</p>
<p>So we&#8217;re going to create a new class, CalculationProcessor, which actually handles the calculations themselves.</p>
<pre class="brush: java;">
package com.rallydev.engblog.unittesting;

public class CalculationProcessor {
  public int add(int operand1, int operand2) {
    return operand1 + operand2;
  }

  public int subtract(int operand1, int operand2) {
    return operand1 - operand2;
  }
}
</pre>
<p>The tests for this class should be obvious, so we won&#8217;t go into them.</p>
<p>We will also modify our Calculator class to be injected with CalculationProcessor at construction time, which it will use to perform the operations.  That looks like this:</p>
<pre class="brush: java;">
package com.rallydev.engblog.unittesting;

public class NewCalculator {
  private CalculationProcessor calculationProcessor;

  public NewCalculator(CalculationProcessor calculationProcessor) {
    this.calculationProcessor = calculationProcessor;
  }

  public int calculate(char operation, int operand1, int operand2) {
    switch (operation) {
    case '+':
      return calculationProcessor.add(operand1, operand2);
    case '-':
      return calculationProcessor.subtract(operand1, operand2);
    default:
      throw new UnsupportedOperationException(String.format(
          &quot;%s is not a known operation&quot;, operation));
    }
  }
}
</pre>
<p>So the question is, what should the test for <code>NewCalculator</code> look like?</p>
<p>If we follow the strict &#8220;One Unit Test, One Class&#8221; paradigm, we have to create a mock for the <code>CalculatorProcessor</code> and pass it into the <code>Calculator</code>.  </p>
<p>One possible way it could work is by mocking out the <code>add</code> and <code>subtract</code> methods so that they have mock implementations which actually perform the operations.  That solution really only works here because this example is so simple (the implementation of add is trivial).  Were this problem more real-world, mocking out the responses based on the inputs may not be feasible, so let&#8217;s imagine that we cannot do this for the purposes of this post (when mocking out the responses is possible, most of this post is rendered moot, as that is usually the best way to go).</p>
<p>The other way to write these tests would be to create a mock and verify that our <code>NewCalculator</code> delegates to <code>CalculationProcessor</code> appropriately.  It would like this:</p>
<pre class="brush: java;">package com.rallydev.engblog.unittesting;

import org.junit.Before;
import org.junit.Test;

import static org.mockito.Mockito.*;

public class NewCalculatorBadTest {
	private NewCalculator calculator;
	private CalculationProcessor mockCalculationProcessor;

	@Before
	public void setUp() {
		this.mockCalculationProcessor = mock(CalculationProcessor.class);
		this.calculator = new NewCalculator(mockCalculationProcessor);
	}

	@Test
	public void shouldAdd() {
		calculator.calculate('+', 2, 3);
		verify(mockCalculationProcessor).add(2,3);
	}

	@Test
	public void shouldSubtract() {
		calculator.calculate('-', 2, 3);
		verify(mockCalculationProcessor).subtract(2,3);
	}

	@Test(expected=UnsupportedOperationException.class)
	public void shouldThrowExceptionForUnknownOperation() {
		calculator.calculate('Q', 1, 2);
	}
}
</pre>
<p>I hate this test.  This test does little but double-check the implementation of <code>NewCalculator</code>.</p>
<p>This test is extremely brittle.  If the calculator had more responsibilities (say, multiplication, exponents, etc.) and the tests were more thorough (boundary checking, looking for division by zero, and so on) then changing the implementation of <code>NewCalculator</code> would require changing dozens of broken tests.</p>
<p><em>The tests are there to make us feel safe about refactoring the code, but virtually any refactoring breaks them, which requires us to manually fix the tests.</em>  When this happens, a refactoring effort loses its test harness: the code and the tests must <em>both</em> change together, rather than one at a time with the one verifying the correctness of the other.</p>
<p>Instead, I would prefer to leave the test as it was, only modifying the <code>setUp</code> method to correctly construct the <code>NewCalculator</code> with real instantiations of its dependency.</p>
<pre class="brush: java;">
package com.rallydev.engblog.unittesting;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class NewCalculatorBetterTest {
  private NewCalculator calculator;

  @Before
  public void setUp() {
    CalculationProcessor calculationProcessor = new CalculationProcessor();
    this.calculator = new NewCalculator(calculationProcessor);
  }

  @Test
  public void shouldAdd() {
    assertEquals(5, calculator.calculate('+', 2, 3));
  }

  @Test
  public void shouldSubtract() {
    assertEquals(1, calculator.calculate('-', 5, 4));
  }

  @Test(expected = UnsupportedOperationException.class)
  public void shouldThrowExceptionForUnknownOperation() {
    calculator.calculate('Q', 1, 2);
  }
}
</pre>
<p>There are a few things to notice about this test.  First and foremost, the bodies of the three test methods are now identical to how they were before the refactoring.  This means that the refactoring could have taken place while using the test to ensure it was correct, though the <code>setUp</code> method would have had to change.</p>
<p>Secondly, even though a real <code>CalculationProcessor</code> was instantiated for the test, it was not assigned to a field.  It is scoped exclusively to the <code>setUp</code> method.  This is because the test really has no reason to know about the class beyond the fact that it needs it to construct the <code>NewCalculator</code>.</p>
<p><strong>Blurring the Line</strong></p>
<p>Is this a unit test, or is it something else?  Unit-testing pedants would argue that it&#8217;s not a unit test, but an integration test.  <a href="http://www.michaelfeathers.com/">Michael Feathers</a> may disagree:</p>
<blockquote><p>
&#8220;In the industry, people often go back and forth about whether particular tests are unit tests. Is a test really a unit test if it uses another production class? I go back to the two qualities: Does the test run fast? Can it help us localize errors quickly?&#8221; (Source: <a href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052">Working Effectively with Legacy Code</a>)
</p></blockquote>
<p>The test above is extremely fast, but how effectively does it help us localize errors?  If it were the only failing test for a system full of classes and tests, it would help us narrow down the error pretty quickly: there is either a problem parsing the operator, or a problem performing the operation.</p>
<p>If we had a separate test for the CalculationProcessor itself, but it was passing, then we would know the error is in the parsing.  It didn&#8217;t help us localize the problem quite as quickly as the mocking test would have, but it is also a far stronger test, less likely to break under the strain of a refactoring.</p>
<p>It&#8217;s a trade-off, of course, but I now tend to lean toward creating instances of the dependency classes in the setup of the test in these situations.  I have simple guidelines to help me determine when I should create a mock versus a concrete instance of a class.</p>
<p><strong>Verify() is a Crutch</strong></p>
<p>When you&#8217;re writing a test, you go through three phases, which <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">BDD</a> proponents refer to as the Given, When, and Then.  First you write the Givens, which attempt to fabricate a pre-existing situation for the purposes of your test.  Then you write the Whens, which are the operations being tested.  Last you assert some Thens, which are the expected results of performing the operation.</p>
<p>In the case of our simple unit test above, the Given is that a <code>NewCalculator</code> exists.  The When is that <code>calculate</code> is called with some parameters.  And then Then, of course, is that we get the desired result.  But how do we write our Thens?</p>
<p>My feeling is that, if we reach into our toolbox and pull out a <code>verify</code> to write our Thens, we are cheating our tests out of the chance to be truly valuable.  When we reach for <code>verify</code>, we are creating brittle tests that resist refactoring rather than enable it.  We are using <code>verify</code> as a crutch, but we should only reach for it as a last resort.</p>
<p>Instead, reach for concrete instantiations of classes where possible.  Create a mock that will be used to verify method invocation for one of two reasons:</p>
<ol>
<li><strong>Speed</strong> &#8211; If creating an instance of the class will significantly slow down the test, it should be mocked out instead.  This is likely to be the case for classes that clearly turn tests into integration tests, such as classes that facilitate a connection to a database or over a network.  This may also be the case for classes that perform a great deal of processing.</li>
<li><strong>Complexity</strong> &#8211; Create a mock if creating an instance of a class requires creating a number of additional classes that it depends on, which in turn depend on more classes, and so on.  You do not want your setUp methods to contain thousands of lines of object instantiation to support your tests.  I recommend creating real objects as deeply down the dependency tree as possible, then mocking out the rest.  How far down the tree should you go?  That&#8217;s really a matter of taste, but I recommend trying two layers deep and no more.  When you do this, you are likely to find that you have no need to verify the calls on the mock objects (other tests already cover those scenarios), but instead can set up mock objects to respond in specific ways to method invocations, simulating their behavior for the purpose of the test so that your tests can verify actual results.</li>
</ol>
<p><strong>Going Forward</strong></p>
<p>Writing tests without the hard Unit/Class restriction allows us to write tests that enable the safe refactoring of classes, but come at the potential price of slowing down our tests and complicating the <code>setUp</code> methods for those tests.  There is a delicate balance there, but in general I recommend trying to err on the side of concrete class instantiation in tests, at least over method invocation verification (mocking out responses is always still preferred).</p>
<p>This view is, of course, subject to change (as it was when I felt that the restriction was valuable), but since blurring this line my tests have remained fast and, more importantly, allowed me to code faster by letting me refactor when necessary.</p>
<p>Agree?  Disagree?  Leave a comment.</p>
<img src="http://www.rallydev.com/engblog/?ak_action=api_record_view&id=424&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.rallydev.com/engblog/2009/11/17/units-are-not-classes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Verizon Droid vs T-Mobile G1</title>
		<link>http://www.nomachetejuggling.com/2009/11/06/verizon-droid-vs-t-mobile-g1/</link>
		<comments>http://www.nomachetejuggling.com/2009/11/06/verizon-droid-vs-t-mobile-g1/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 00:12:35 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[operating systems]]></category>
		<category><![CDATA[phone]]></category>
		<category><![CDATA[t-mobile]]></category>
		<category><![CDATA[verizon]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=596</guid>
		<description><![CDATA[Now that the Verizon Droid has been released, lots of blogs and technology sites are comparing it to the iPhone.  When I was researching the droid, I found most of these comparisons worthless, as I&#8217;ll never use an iPhone as long as Apple&#8217;s policies regarding the phone and its app store remain as they [...]]]></description>
			<content:encoded><![CDATA[<p>Now that the Verizon Droid has been released, lots of blogs and technology sites are comparing it to the iPhone.  When I was researching the droid, I found most of these comparisons worthless, as I&#8217;ll never use an iPhone as long as Apple&#8217;s policies regarding the phone and its app store remain as they are today.</p>
<p>But for the last year I&#8217;ve been a very happy T-Mobile G1 user.  I love the Android operating system, I love the Google integration, I love the (relative) openness of the device and the near perfect openness of the application market.  I cannot imagine using a phone that doesn&#8217;t run Andoid any time soon.  </p>
<p>Despite loving the software on the G1, I&#8217;ve never been completely crazy about the hardware itself.  The screen sliding feels a little cheap to me, the phone generally feels a bit sluggish, and the trackball becomes nearly worthless after significant use.  Overall, these are minor annoyances, but annoyances nonetheless.  The G1 always felt like something of a knockoff iPhone; it was the thing you got when you couldn&#8217;t afford a slick, sleek iPhone from Apple.  It has features like an iPhone, but generally inferior hardware.</p>
<p>So when I started seeing the Verizon Droid, I got excited.  I was eager to switch back to Verizon (I had switched from Verizon to T-Mobile to get the G1 when it first came out) due to Verizon&#8217;s superior network coverage and the fact that my wife is a Verizon user.  Moreover, the phone looked simply stunning to me.  Solid, industrial, sleek, thin (or at least thinner than the G1).  Overall, a bad-ass looking phone.</p>
<p>Unsurprisingly, I purchased a Droid the day it was released.  In fact, I suffered the early termination fee with T-Mobile in order to get it.</p>
<p>I&#8217;ve had the phone for a day now and I wanted to offer some comparisons between it and the G1.</p>
<p><span id="more-596"></span></p>
<p><strong>The Good</strong></p>
<p>The hardware of the Droid is solid.  It feels heavy and sturdy, sliding the screen to reveal the keyboard differs from the cheap spring of the G1 a great deal (it&#8217;s almost, but not quite, difficult to slide).  The phone is extremely fast and responsive.  Applications start quickly, process quickly, and generally seem speedier.  The screen of the Droid is significantly larger than with the G1, and the clarity and resolution of the Droid&#8217;s screen are simply stunning.  My wife&#8217;s contact picture actually looks like her.</p>
<p>The phone is only slightly thinner than the G1, but it makes a huge difference &#8211; it feels FAR less bulky in my pocket.  The obnoxious upward curve of the bottom of the G1 is gone, replaced by a solid boxy square on the Droid.  The front of the phone is devoted almost entirely to the screen.  The trackball of the G1 (which becomes less and less responsive over time) has been replaced by a directional pad, and that pad can be accessed only by sliding the keyboard out, devoting even more of the phone to the screen itself.  </p>
<p>The power button is in a more convenient place on the Droid as well.  Whereas the power/lock button on the G1 was somewhat awkward to use(I always worried about dropping the phone when pressing it to darken the screen before putting it back in my pocket), the Droid&#8217;s power/lock button is easy to push and encourages holding the phone in a more solid hand configuration.  The volume keys have been moved to the opposing side of the phone, but that doesn&#8217;t seem to make a difference either way.</p>
<p>Additionally, the vibration seems a bit stronger on the Droid.  I always leave my phone in vibrate mode, but the G1 vibration was pretty weak.  Often I&#8217;d get a text or a phone call and not even feel it in my pocket.  So far, that hasn&#8217;t been a problem with the Droid, whose vibration is powerful without being loud.  Battery life is far better with the Droid as well &#8211; a full day of use with the G1 left the battery dead if I didn&#8217;t charge it during the day at least a bit.  A full day of use with the Droid doesn&#8217;t even get the battery into the yellow, and that&#8217;s with the screen significantly brighter.</p>
<p>One feature I particularly like is that the Droid comes with a devoted headphone jack.  Listening to podcasts on the G1 was a pain, as it required using an awkwardly long adapter cable plugged into the USB port.  This also prevented me from charging the device while listening to something, something I often wanted to do in the car.  The Droid has a separate charging port and headphone jack, which is far easier to work with.</p>
<p>Most importantly, the phone connects to Verizon, so I have significantly better 3G coverage than I did with T-Mobile, especially in conference rooms at work (where I need the comfort of Google Reader the most).</p>
<p><strong>The Bad</strong></p>
<p>The Droid isn&#8217;t without it&#8217;s faults, unfortunately.  The Droid keyboard is vastly inferior to the G1&#8217;s keyboard.  Firstly, there are only 4 rows of keys on the Droid, as opposed to the G1&#8217;s five.  This means pressing numbers requires using an &#8216;ALT&#8217; key.  Not hugely irritating, but mildly so.  Far worse, however, is the fact that the keyboard keys have no gaps between them as they do on the G1, and the buttons themselves are flat rather than being slightly rounded.  Typos are far, far more common with the Droid phone, it&#8217;s nearly impossible for me to get through a simple text message without fat-fingering something.  To make matters worse, because the backspace key is DIRECTLY above the enter key, I find myself accidentally hitting enter when I&#8217;m trying to backspace, which means I&#8217;m sending a LOT of text messages that end in a typo, only to be followed by another text-message correcting the mistake.</p>
<div id="attachment_597" class="wp-caption alignright" style="width: 310px"><a href="http://www.nomachetejuggling.com/files/2009-11-06-16.56.31.jpg"><img src="http://www.nomachetejuggling.com/files/2009-11-06-16.56.31-300x224.jpg" alt="Fuck you, Motorola." title="Droid charger" width="300" height="224" class="size-medium wp-image-597" /></a><p class="wp-caption-text">Fuck you, Motorola.</p></div>
<p>Another irritation is that the Droid does not use a standard USB port.  It sure looks a hell of a lot like one, but it isn&#8217;t.  I could plug the G1 into anything that had a Mini-USB connector on the end.  Wall chargers, car chargers, even the cables my wife uses for HER phone (very convenient if I happened to need a quick charge in her car).  The Droid uses some proprietary connector, so you have to buy adapters for the thing if you want to charge it.  This is completely obnoxious and unnecessary &#8211; it&#8217;s clearly Motorola trying to suck a little bit more money out of me.  The real kick in the balls, however, is what the phone comes with in terms of chargers.  It comes with a basic USB connector to connect it to your computer, and a wall adapter FOR THE USB CABLE.  If you want to plug it into the wall, you must sacrifice the USB cable.  This is particularly obnoxious for me because I had my G1&#8217;s usb cable (a standard USB with mini adapter on the end) in my office downstairs, a wall charger in the bedroom so it could charge at night, a wall charger at work so I could charge at work, and a car charger in my car if I needed to make a call but had let my battery die.  The Droid&#8217;s supplied chargers give me ONE of these at any given moment, and I must separately purchase what I need for the other three.</p>
<p>UPDATE: A commenter has explained that the plug the Droid uses IS, in fact, an open standard, called Micro-B.  A quick search on Newegg revealed many cheap Micro-B cables that I could use with the phone.  So that&#8217;s much less annoying.  Still would have bee nice to have a separate wall charger that didn&#8217;t use up the one USB cable that comes with the phone, though.</p>
<p>The camera for the Droid is 5 Megapixels.  Seems impressive, except that so far I&#8217;ve had some pretty crappy luck with it.  In fact, the picture of the charger took me five tries to get right, and still came out blurry, even when I switched the focus mode for closeup shots.  The flash is basically worthless as well, it never seems to flash at the correct time, and it is effectively a &#8220;make this photo blurry&#8221; toggle.</p>
<p>Call quality on the Droid seems significantly worse as well.  I have not yet determined if the speaker is the problem, but so far it&#8217;s much more difficult to hear people during a call on the Droid.</p>
<p>Another annoyance is how close the row of four hardware buttons are to the bottom of the screen on the Droid.  I was using Twidroid and reading some private messages on my twitter account, then I hit menu.  The only menu item on this screen is for &#8220;Delete all messages&#8221;.  I decided I didn&#8217;t want to do that, and hit &#8220;back&#8221; to exit out of that menu.  Unfortunately, the &#8220;back&#8221; button is flush with the bottom of the screen, so my attempt to go &#8220;back&#8221; registered on the touchscreen as a click on the menu item, so Twitdroid proceeded to permanently delete all of my private messages.  I had to actually rip the battery out of the phone in a panic to interrupt it quickly enough, and I still lost my most recent thirty or so messages.  Annoying.</p>
<p><strong>Overall</strong></p>
<p>Many of the nicest features of the Droid are actually features of the Android 2.0 operating system, the next version of the OS running on the G1.  It remains unknown at this point if the G1 will get this version of the OS, but it&#8217;s what contains most of Droid&#8217;s coolest features, such as the turn-by-turn directions and other various improvements to Google Maps.  The 2.0 upgrade also comes with a cost: a few of my favorite apps such as &#8220;reddit is fun&#8221;, &#8220;K-9 Mail&#8221;, and &#8220;Pure Calendar&#8221; don&#8217;t actually work correctly, but that will likely be fixed in due time.</p>
<p>I also do not yet have the Multimedia Station charger/dock for the Droid, which I think would be awesome on my bedroom nightstand, nor do I have the car mount, both of which I want and I think will make me appreciate the Droid more.</p>
<p>As it stands though, I&#8217;m not sure the Droid is compelling enough on its own to warrant the switch from T-Mobile to Verizon.  I love the increased coverage, the devoted headphone jack, the screen improvements, and the overall feel of the phone, but I really dislike being nickel-and-dimed on chargers and I kind of really hate the keyboard (I&#8217;m hoping I get used to it).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/11/06/verizon-droid-vs-t-mobile-g1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Google Reader&#8217;s Creepy New Feature</title>
		<link>http://www.nomachetejuggling.com/2009/10/25/google-readers-creepy-new-feature/</link>
		<comments>http://www.nomachetejuggling.com/2009/10/25/google-readers-creepy-new-feature/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 19:26:02 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[weird]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=584</guid>
		<description><![CDATA[I&#8217;m a big user of Google Reader, so it annoyed me a bit when I started seeing things like &#8220;50 people liked this&#8221; and similar features peppering my Reader interface a while back.  I wasn&#8217;t alone, there&#8217;s a Google Groups thread where a number of people lament the inability to deactivate this &#8220;feature.&#8221;
But a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big user of Google Reader, so it annoyed me a bit when I started seeing things like &#8220;50 people liked this&#8221; and similar features peppering my Reader interface a while back.  I wasn&#8217;t alone, there&#8217;s a <a href="http://groups.google.com/group/google-reader-howdoi/browse_thread/thread/b5f96533a772faaa/73fe8efae51c7c2c?lnk=gst&#038;q=">Google Groups thread</a> where a number of people lament the inability to deactivate this &#8220;feature.&#8221;</p>
<p>But a few days ago, I saw the payoff: <a href="http://googleblog.blogspot.com/2009/10/reading-gets-personal-with-popular.html">Google Reader Recommendations</a>.  Recommendation engines are one of my favorite things about the new social web &#8211; Amazon&#8217;s book recommendations and Netflix&#8217;s movie recommendations have led me to find things I never would have discovered on my own.  So when I saw that Google Reader had recommendations of other blogs or RSS feeds for me, I was excited.</p>
<p><span id="more-584"></span></p>
<p>I figured, like most other recommendation engines, Google Reader now looked at what feeds I subscribe to and found other feeds that were subscribed to by people who subscribed to the feeds I like.  This is generally how recommendation engines work: if I love &#8220;Back to the Future&#8221; and 90% of Netflix users who rate that movie highly also highly rate &#8220;Ghostbusters&#8221; highly and I&#8217;ve never seen it, Netflix will recommend Ghostbusters to me.</p>
<p>But when I looked at my recommendations, a strange thing caught my attention.</p>
<p><a href="http://www.nomachetejuggling.com/files/creepy_reader.png"><img src="http://www.nomachetejuggling.com/files/creepy_reader-300x95.png" alt="Creepy Suggestions" title="Creepy Suggestions" width="300" height="95" class="aligncenter size-medium wp-image-585" /></a></p>
<p>There is a recommendation for a blog related to TeX in there.  If I scroll down, there are actually five or six other TeX resources.</p>
<p>This stood out because I don&#8217;t subscribe to <strong>ANY</strong> RSS feeds that related to TeX in any way, not even tangentially.  So why did Google so strongly suggest them?</p>
<p>Well, I don&#8217;t subscribe to TeX feeds, but I am working on my Master&#8217;s thesis, and I&#8217;ve had to do a lot of Googling for help on LaTeX.  A very large portion of searches I do in Google are LaTeX related, simply because I often need to troubleshoot a problem or look up how to format something.</p>
<p>So Google Reader&#8217;s recommendations are not merely based on feeds.  They are based in my search results as well, even though that&#8217;s &#8220;separate&#8221; from Reader.  It wouldn&#8217;t surprise me if people were getting recommendations based on the content of their Gmail accounts either.</p>
<p>Creepy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/10/25/google-readers-creepy-new-feature/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wedding Photos Online</title>
		<link>http://www.nomachetejuggling.com/2009/09/18/wedding-photos/</link>
		<comments>http://www.nomachetejuggling.com/2009/09/18/wedding-photos/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 22:32:44 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[photos]]></category>
		<category><![CDATA[wedding]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/2009/09/18/jb0959/</guid>
		<description><![CDATA[



JB0959

Originally uploaded by rodhilton


The photos from my wedding are up on Flickr.  Check &#8216;em out here.  Our photographer was excellent.  I highly recommend her.
The wedding was great.  Virtually nothing went wrong &#8211; we even just barely avoided some rain but avoided it nonetheless.  I was kind of dreading having to [...]]]></description>
			<content:encoded><![CDATA[<div style="float: right; margin-left: 10px; margin-bottom: 10px;">
<a href="http://www.flickr.com/photos/rodhilton/3932201814/" title="photo sharing"><img src="http://farm3.static.flickr.com/2439/3932201814_e67c8cb9b0_m.jpg" alt="" style="border: solid 2px #000000;" /></a><br />
<br />
<span style="font-size: 0.9em; margin-top: 0px;"><br />
<a href="http://www.flickr.com/photos/rodhilton/3932201814/">JB0959</a><br />
<br />
Originally uploaded by <a href="http://www.flickr.com/people/rodhilton/">rodhilton</a><br />
</span>
</div>
<p>The photos from my wedding are up on Flickr.  Check &#8216;em out <a href="http://www.flickr.com/photos/rodhilton/collections/72157621960411651/">here</a>.  Our <a href="http://www.annettedragonphotography.com/content.php">photographer</a> was excellent.  I highly recommend her.</p>
<p>The wedding was great.  Virtually nothing went wrong &#8211; we even just barely avoided some rain but avoided it nonetheless.  I was kind of dreading having to be social for a whole evening, but even the reception turned out to be a good time (though I had to go hide in order to eat my slice of cake).</p>
<p>Overall, being married doesn&#8217;t feel too much different from not being married.  I&#8217;ve known I&#8217;d marry Julia since second week we dated, and I knew she&#8217;d make a beautiful bride (she did).</p>
<p>It was great seeing family and merging my 7-person family with her 100-something-person family.  I also really loved how many of our friends from college were able to make it, including one of my professors.  It was great seeing everyone again.</p>
<p>My friend Dennis was a fantastic Best Man, and Julia&#8217;s sister Olivia did an wonderful job as Maid of Honor.  It was a truly unforgettable time.<br />
<br clear="all" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/09/18/wedding-photos/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>My Personal 3 Pillars of Job Satisfaction</title>
		<link>http://www.nomachetejuggling.com/2009/08/21/my-personal-3-pillars-of-job-satisfaction/</link>
		<comments>http://www.nomachetejuggling.com/2009/08/21/my-personal-3-pillars-of-job-satisfaction/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 19:33:50 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[job]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=533</guid>
		<description><![CDATA[As I grow through my career as a software developer, I have tried to remain aware of what makes me happy or unhappy at a job.   What I decided was that there were three factors in job satisfaction, so I found myself amazed that someone else had posted something similar: Alan Skorkin explains [...]]]></description>
			<content:encoded><![CDATA[<p>As I grow through my career as a software developer, I have tried to remain aware of what makes me happy or unhappy at a job.   What I decided was that there were three factors in job satisfaction, so I found myself amazed that someone else had posted something similar: Alan Skorkin explains his <a href="http://www.skorks.com/2009/08/the-3-pillars-of-job-satisfaction/">Three Pillars of Job Satisfaction</a>.</p>
<p>I agree that there are three pillars, but I disagree about what the pillars are, at least for myself.</p>
<p>I&#8217;ve found that these are the main three factors in determining how happy I am at a job:</p>
<ol>
<li>The People</li>
<li>The Project</li>
<li>The Company</li>
</ol>
<p>Some of these may seem redundant, so let me elaborate.</p>
<p><span id="more-533"></span></p>
<p><strong>The People</strong></p>
<p>The people I work with on a daily basis matter a great deal.  This doesn&#8217;t mean &#8220;everyone at the company&#8221;, it means the people who make up my immediate team.  I have to find them smart, interesting, motivated, hard-working, and challenging.  I need to feel like I&#8217;m improving because of them and that they are improving because of me.  I need to enjoy working with my fellow engineers, testers, product owners, immediate bosses, and so forth.  It&#8217;s interesting to note that I can consider this pillar satisfied if my average level of enjoyment is high enough.  I can be relatively lukewarm on everyone and be satisfied, or I can even get away with completely despising one member of the team as long as I like everyone else enough to make up for it.</p>
<p><strong>The Project</strong></p>
<p>I&#8217;m just not interested in working on run-of-the-mill financial accounting software.  It&#8217;s a personal failing, I think.  But I need to find the project, the thing I work on on a daily basis, to be intellectually engaging.  It should use frameworks I want to learn more about, it should regularly challenge me with requirements.  The project needs to be a series of puzzles I must solve, but it cannot be frustrating due to poor project development.  It needs to build easily, it needs to be easy to write tests, it needs to be checked into version control, and so forth.  It should be regularly challenging without being infuriating.</p>
<p><strong>The Company</strong></p>
<p>This may sound redundant, as what is a company if not for people and a project?  What I mean here is that I have to care about what the company is doing.  I have to care about the business model, I have to feel like the company that employs me is doing something valuable for society, making the lives of users better in some way.  I need to be excited by the company by hearing the overall business strategy, without meeting a single person or reading a single line of code.</p>
<p><strong>The 3 Pillars</strong></p>
<p>I&#8217;ve found that if I have a job that satisfies all <strong>three</strong> of these pillars, I&#8217;m extremely happy at a company.  I don&#8217;t look elsewhere, I don&#8217;t consider other job opportunities.  I can work there indefinitely (with one caveat, more on that in a bit).</p>
<p>If I have a job that satisfies <strong>two</strong> pillars, I&#8217;m reasonably satisfied.  I&#8217;m not unhappy, and I can come in every day excited to do my job.  But at the same time, I&#8217;m keeping an eye on various RSS feeds from <a href="http://indeed.com">indeed.com</a>, making sure I don&#8217;t miss a potential three-pillar job.</p>
<p>A job that satisfies only <strong>one</strong> pillar is a job that makes me unhappy.  I&#8217;m actively seeking another job and sending my resume out.  I dread coming into work, and I have a hard time motivating myself.</p>
<p>A job that satisfies <strong>zero</strong> pillars is completely miserable.  If I realized I was at a job that satisfies zero pillars, I&#8217;d quit on the spot, even without another job lined up.  Life&#8217;s too short.</p>
<p><strong>Deterioration</strong></p>
<p>What&#8217;s interesting is that a job that satisfies three pillars can eventually turn into a job that satisfies fewer as time goes on. </p>
<p>It&#8217;s always possible for the company to change directions and leave me unhappy with the company, though this is somewhat rare.</p>
<p>It&#8217;s also possible that I can get sick of the people I work with after working with them for a long time, but this is pretty rare as well.  However, if the turnaround for a company is high, it&#8217;s possible that the people I like may eventually leave the company to work elsewhere, which would cause the &#8220;People&#8221; pillar to eventually be unsatisfied unless I also enjoyed working with their replacements.</p>
<p>The really dangerous pillar is the second one, &#8220;The Project&#8221;.  Eventually I can get so familiar with a codebase that modifying it becomes boring.  The features that get added start to look alike, and I get to a point where I can work with the code on autopilot mode.  A legacy project may get refactored and cleaned up to a point where there simply aren&#8217;t that many &#8220;broken&#8221; areas of the code that require my attention or offer a challenge.  The work gets dull.  Skorks mentions the same thing (his &#8216;Type of Work&#8217; is my &#8216;The Project&#8217;).</p>
<p>Of the three, satisfaction with &#8220;The Project&#8221; is the one that is most likely to deteriorate.  At a 3-pillar company, this isn&#8217;t a big deal, but at a 2-pillar company, the moment I get bored with the project I find that I&#8217;m working at a 1-pillar company, which puts me into career panic mode.</p>
<p>Luckily, my current job is my first-ever three-pillar company.  It&#8217;s also my fourth job after college, and all three previous companies were two-pillar jobs, each one lacking a different pillar (which helped me develop the theory).</p>
<p>The main difference between my pillars and Skorks&#8217;s is that I don&#8217;t have a pillar for money, and I have an additional pillar for the business.  I have never been unsatisfied with money, so I don&#8217;t really even think about it.  I wouldn&#8217;t take a job that offered me too little to live on, and if I can live comfortably on my salary then I don&#8217;t even think about money.  I wonder if that will change as I advance in my career.</p>
<p>The difficulty with these pillars is that, when applying to a job you know nothing about the job except &#8220;The Company&#8221;, so only one pillar is known.  During the interview you have to try to size up the people and ask questions about the codebase to make a good guess about the other pillars.</p>
<p>Based on my differences from Skorks, I guess everyone has different pillars, but these are mine (at least, these are the ones I am currently aware of).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/08/21/my-personal-3-pillars-of-job-satisfaction/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>I&#8217;m Your Moon (Wedding Remix)</title>
		<link>http://www.nomachetejuggling.com/2009/08/17/im-your-moon-wedding-remix/</link>
		<comments>http://www.nomachetejuggling.com/2009/08/17/im-your-moon-wedding-remix/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 06:46:45 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[wedding]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=453</guid>
		<description><![CDATA[After I proposed to my girlfriend, I was tasked with finding a good first dance song for us.  This was not easy, as I typically listen to hard rock, with occasional smatterings of other genres.
I got quite lucky, however, when I went through my one of these other genres, my Jonathan Coulton folder, and [...]]]></description>
			<content:encoded><![CDATA[<p>After I proposed to my girlfriend, I was tasked with finding a good first dance song for us.  This was not easy, as I typically listen to hard rock, with occasional smatterings of other genres.</p>
<p>I got quite lucky, however, when I went through my one of these other genres, my Jonathan Coulton folder, and found a song called <a href="http://www.jonathancoulton.com/2006/08/25/thing-a-week-47-im-your-moon/">I&#8217;m Your Moon</a>.</p>
<p>It&#8217;s a super geeky little song about Pluto and it&#8217;s moon, Charon.  The chorus goes:</p>
<blockquote><p>
I&#8217;m your moon,<br />
you&#8217;re my moon,<br />
we go round and round.
</p></blockquote>
<p>Anyway, we both really liked this song because it was kind of nerdy and had a double meaning (to someone unaware of the science, it just sounds like a nice love song).</p>
<p><span id="more-453"></span></p>
<p>Unfortunately, there&#8217;s part of the song (after the second chorus) where the beat completely drops out.  This makes it very difficult to dance to.  Additionally, we weren&#8217;t crazy about the lyrics for this section of the song, as they were a bit too dark.</p>
<blockquote><p>
Who you were<br />
Long before<br />
They said you were<br />
No more
</p></blockquote>
<p>Obviously this is about Pluto being downgraded from &#8220;Planet&#8221; status, but since a lot of the attendees weren&#8217;t going to know that the song has anything to do with planets, we decided to cut this section of the song out.</p>
<p>Since Coulton released this song under<a href="http://wiki.creativecommons.org/Jonathon_Coulton"> Creative Commons </a>, I&#8217;ve decided to share my edited version of the song.</p>
<p><a href="http://www.zshare.net/audio/633601952fb5bc99/">Enjoy!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/08/17/im-your-moon-wedding-remix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Convert Audible .aa Files to .mp3 Quickly</title>
		<link>http://www.nomachetejuggling.com/2009/08/02/how-to-convert-audible-aa-files-to-mp3/</link>
		<comments>http://www.nomachetejuggling.com/2009/08/02/how-to-convert-audible-aa-files-to-mp3/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 17:36:45 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[audible]]></category>
		<category><![CDATA[audio books]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[conversion]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=500</guid>
		<description><![CDATA[I do not belong to the cult of iPod.  I use a nonstandard mp3 player and I hate iTunes.  If I&#8217;m going to use an mp3 player, it needs to show up as a USB drive on my Linux workstation, my Windows desktop, and my Mac laptop.  I need to be able [...]]]></description>
			<content:encoded><![CDATA[<p>I do not belong to the cult of iPod.  I use a nonstandard mp3 player and I hate iTunes.  If I&#8217;m going to use an mp3 player, it needs to show up as a USB drive on my Linux workstation, my Windows desktop, and my Mac laptop.  I need to be able to drag files over and be done with it.  So far, I&#8217;ve been successful at accomplishing this.</p>
<p>But the simplicity comes with a price.  I cannot download books from <a href="http://www.audible.com">Audible.com</a> and put them on my player to listen to them.  I have to convert all of the files I download from Audible into DRM-free mp3 files.  But most instructions on the internet advocate a cumbersome process, many involving that unholy beast iTunes, which effectively just plays the audio books while capturing the output stream.</p>
<p>I have developed an alternative to this method, which lets you convert your Audible audio book downloads to DRM-free mp3s in just a few minutes, with a very small amount of manual work.</p>
<p><span id="more-500"></span></p>
<p><strong>You Will Need</strong></p>
<ul>
<li>Windows (sorry, the programs needed only run in Windows)</li>
<li><a href="http://www.nero.com/enu/store-nero9.html">Nero</a> for Windows (cost: $70, free trial available)</li>
<li><a href="http://www.ezbsystems.com/ultraiso/">UltraISO</a> for Windows (cost: $30, free trial available)</li>
<li><a href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl">Ruby</a> for Windows (free)</li>
<li><a href="http://www.free-codecs.com/download/Lame_Encoder.htm">Lame</a> for Windows (free)</li>
<li>An <a href="http://www.audible.com">Audible.com</a> account</li>
<li>Some patience</li>
</ul>
<p><strong>Step 1: Download The .aa Files</strong></p>
<p>On Audible.com, find the book you want and download it.  Make sure that it downloads using the Audible Download Manager and results in you getting .aa files for the book.  If Audible tries to make you download something else, you may have to add a new device on Audible.com.  Pick something simple (not an iPod) and select &#8216;Format 4&#8242; for the desired type.</p>
<p><strong>Step 2: Burn to images using Nero</strong></p>
<p>Once you have your .aa file (or two), open up Nero.</p>
<p>Create a new compilation, select &#8216;CD&#8217; as the type, and scroll down to &#8216;Audiobook CD&#8217;</p>
<p><a href="http://www.nomachetejuggling.com/files/nero_audiobookselect.png"><img src="http://www.nomachetejuggling.com/files/nero_audiobookselect-300x226.png" alt="nero_audiobookselect" title="nero_audiobookselect" width="300" height="226" class="alignnone size-medium wp-image-503" /></a></p>
<p>Now drag your .aa file into the Nero.  Select &#8216;Image Recorder&#8217; from the list of recorders.  Then click Burn.</p>
<p><a href="http://www.nomachetejuggling.com/files/nero_compilation.png"><img src="http://www.nomachetejuggling.com/files/nero_compilation-300x234.png" alt="nero_compilation" title="nero_compilation" width="300" height="234" class="alignnone size-medium wp-image-506" /></a></p>
<p>Before the &#8216;discs&#8217; start burning, you&#8217;ll be asked for a name.  The default, &#8220;Image&#8217; is probably fine.  <strong>Make sure you are saving into a COMPLETELY EMPTY directory.</strong></p>
<p>You will be asked if you want to manually select new file names or Autocreate them.  Choose auto create so you can do something else while they are &#8216;burning&#8217;. </p>
<p>The goal here is to get the .aa files, which represent multiple burnable discs, into .nrg files, one file for each &#8216;disc&#8217;.  You&#8217;ll have to do this step once for every .aa file in your book (long books sometimes have two .aa files).  This is the most manual part of the process, after this it&#8217;s smooth sailing.</p>
<p><strong>Step 3: Convert to mp3</strong></p>
<p>Now, you have a directory somewhere that contains files that look like Image.nrg, Image02.nrg, Image03.nrg, etc.  Let&#8217;s call that directory <strong>c:\mybook</strong> for the purposes of this tutorial.</p>
<p>You will need to install some more software before you can proceed.  Download and install UltraISO and Lame (links above).  Let&#8217;s assume you have installed those to <strong>c:\program files\ultraiso\</strong> and <strong>c:\program files\lame\</strong>, respectively.  Also make sure you install Ruby.</p>
<p>You will also need to download this ruby script that I wrote (click &#8216;view source&#8217; in the top right, copy the contents, and paste into a new file using notepad):</p>
<pre class="brush: ruby;">
# Written by Rod Hilton, nomachetejuggling.com

# Modify these to be the paths to your copies of ultraiso.exe and lame.exe.
# Remember to do \\ for backslashes, and don't use /
ULTRAISO_PATH = &quot;c:\\program files\\ultraiso\\ultraiso.exe&quot;
LAME_PATH = &quot;c:\\program files\\lame\\lame.exe&quot;

# Read the directory to convert from the command line.
@workingdir = ARGV[0]
if @workingdir.nil? or not File.directory?(@workingdir)
	abort &quot;Usage: ruby #{File.basename(__FILE__)} &lt;path to directory&gt;&quot;
end

# Deletes a file
def delete(filepath)
	shortname = File.basename(filepath).slice(0..50)
	print &quot;  Deleting #{shortname}...&quot;;
	print File.delete(filepath) ? &quot;Done!\n&quot; : &quot;Failed!\n&quot;
end

# Convert method.  Converts all files in the working directory with
# a specific extension using a function block
def convert(extension, options = {}, &amp;function)
	Dir.foreach(@workingdir) do |file|
		if(file.match(/.#{extension}$/))
			filepath = File.join(@workingdir, file)
			command = function.call(filepath)
			print &quot;  Converting #{file.slice(0..50)}...&quot;
			retval = system command
			if(retval)
				print &quot;Done!\n&quot;
				delete(filepath) if options[:delete_after]
			else
				abort &quot;Failed!&quot;
			end
		end
	end
end

puts &quot;--Converting in #{@workingdir}--&quot;

puts &quot;Converting all .nrg files to .wav files...&quot;
convert(&quot;nrg&quot;, :delete_after=&gt;true) do |filepath|
	&quot;\&quot;#{ULTRAISO_PATH}\&quot; -in \&quot;#{filepath}\&quot; -extract \&quot;#{@workingdir}\&quot;&quot;
end

puts &quot;Converting all .wav files to .mp3 files...&quot;
convert(&quot;wav&quot;, :delete_after=&gt;true) do |filepath|
	&quot;\&quot;#{LAME_PATH}\&quot; --abr 56 -mm -S \&quot;#{filepath}\&quot;&quot;
end
</pre>
<p>This script basically uses UltraISO to extract .wav files from the .nrg files, then uses lame to convert the .wav files to .mp3 files.</p>
<p>If you installed UltraISO or Lame to different directories, change the top few lines to reflect their real paths.</p>
<p>Let&#8217;s assume you saved this file to &#8220;c:\nrg2mp3.rb&#8221;.</p>
<p>Now, open up a command prompt (Start->Run->type &#8216;cmd&#8217; and hit enter).  Type:</p>
<pre>
ruby c:\nrg2mp3.rb "c:\mybook"
</pre>
<p>Make sure that you use the quotes if you have spaces in your directory name.</p>
<p>Now just sit back and wait.  The script will convert all of the nrg files to mp3 files.  It will delete all of the .nrg files when it is done with them.  If you&#8217;d like to tell the script not to do that, modify line 43 to remove the :delete_after stuff, like so:</p>
<pre class="brush: ruby; first-line: 43;">
convert(&quot;nrg&quot;) do |filepath|
</pre>
<p>There are lots of ways to do this, but I believe this one involves the fewest number of manual steps, and I believe it is the only method that does no analog conversion (no recording your sound card as the file plays).  It is also, as far as I&#8217;m aware, the fastest method.  Ripping the wavs out using UltraISO only takes a few seconds for me, and converting them to mp3 doesn&#8217;t take very long at all.</p>
<p>If you can think of a way to make this process faster and require fewer non-free programs (or, ideally, a way to make this work in Linux), leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/08/02/how-to-convert-audible-aa-files-to-mp3/feed/</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
		<item>
		<title>Enhancement vs. Defect: More Than Pedantry</title>
		<link>http://www.nomachetejuggling.com/2009/08/01/enhancement-vs-defect-more-than-pedantry/</link>
		<comments>http://www.nomachetejuggling.com/2009/08/01/enhancement-vs-defect-more-than-pedantry/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 17:50:07 +0000</pubDate>
		<dc:creator>Rod Hilton</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[defects]]></category>
		<category><![CDATA[enhancements]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.nomachetejuggling.com/?p=493</guid>
		<description><![CDATA[Change is inevitable in the world of software.  In fact, the need for change and the related need to adapt to change are the driving forces behind the agile movement.  Requests for change generally come in one of two main forms: enhancements and defects.  A defect means &#8220;the software isn&#8217;t working the [...]]]></description>
			<content:encoded><![CDATA[<p>Change is inevitable in the world of software.  In fact, the need for change and the related need to adapt to change are the driving forces behind the agile movement.  Requests for change generally come in one of two main forms: enhancements and defects.  A defect means &#8220;the software isn&#8217;t working the way it says it will&#8221;, whereas an enhancement basically means &#8220;the software isn&#8217;t working the way the customer wants.&#8221;</p>
<p>The basic cycle of modern software development looks like this:</p>
<ol>
<li>The customer tells the development team (often through a product owner) what he or she wants the software to do.</li>
<li>The development team responds to this by telling the customer what it will do (via direct conversation, help documentation, the UI, etc).</li>
<li>The development team makes the software do it.</li>
<li>The customer tells the team how well it did.</li>
</ol>
<p>It&#8217;s step 4 that generates change requests.  The customer says that something isn&#8217;t working the way they want it to be working, and the cycle repeats.</p>
<p>Very often, you will hear developers whine about enhancements that are being filed as defects.  Product owners will often respond by saying that it doesn&#8217;t matter, it all has to be fixed.  A common phrase I hear is &#8220;they are all defects from the customer&#8217;s perspective.&#8221;  This mentality is echoed in <a href="http://www.pragprog.com/titles/pad/practices-of-an-agile-developer">Practices of an Agile Developer</a>.  The attitude is generally, defects and enhancements are basically the same thing, it&#8217;s all work that needs to be done, and programmers are being pedantic when they insist on making the distinction.</p>
<p>But here&#8217;s the deal: <strong>the programmers are right.</strong></p>
<p><span id="more-493"></span></p>
<p>I understand that it seems pedantic to distinguish between defects and enhancements.  I understand that the way it looks is that developers are trying to play the &#8220;blame game.&#8221;  The perception is that programmers feel that filed defects are their fault and filed enhancements are not, so when they complain about the line between the two things blurring, it seems like programmers are simply trying to prevent the company from blaming them.  This has some truth to it, of course, but there is far more to making the distinction than this oversimplification implies.</p>
<p>The fact of the matter is, it&#8217;s important to know when the defects start piling up.  If you&#8217;ve got a backlog of hundreds of defects, defects that are being filed more quickly than you can close them, your team clearly has a problem.  You need to <strong>solve that problem</strong>, but you cannot do so until you&#8217;ve determined exactly <em>what the problem is</em>.  To do this, you must know if the defects are really defects, or if they are enhancements disguised as defects.</p>
<p><strong>What&#8217;s the problem?</strong></p>
<p>A stack of <strong>defects</strong> means that there is a problem between steps 2 and 3.  The team makes a series of promises regarding what the software will do.  These promises may come in the form of public commitments, documentation, or UI that tells the user to expect certain things (sometimes subtlely). But then the team fails to make the software correctly perform those duties.  Actions don&#8217;t work, menu items cause crashes, commands result in incorrect responses, data is wrong, etc.  These are <strong>defects</strong>, and they indicate that the team is not going a good job making the software correctly do what it is supposed to, in terms of what the <strong>team</strong> wants it to do.</p>
<p>A stack of <strong>enhancements</strong>, on the other hand, means that there is a problem between steps 1 and 2.  The team looks over what the customer wants and then decides what to actually make the system do.  If what the system does is not what the customer really wanted, then the team has failed to adequately understand the customer&#8217;s needs, and enhancements will be filed.  Functionality is needed, interfaces need to be less confusing, data needs to be easier interpret (even though it was ultimately correct).  These are <strong>enhancements</strong>, and they indicate that the team is not doing a good job making the software correctly do what it is supposed to, in terms of what the <strong>customer</strong> wants it to do.</p>
<p>A stack of defects points to a problem in <em>code</em>.  When the team opens the toolchest to solve the problem, the tools that will emerge are automated testing, stricter builds, better engineering practices like test-driven development or pair programming, code reviews, root cause analysis, code coverage metrics, and so forth.</p>
<p>A stack of enhancements points to a problem in <em>software</em>.  When the team opens the toolchest to solve the problem, the tools that emerge are conversations, more in-depth acceptance criteria, usability testing, frequent iterations and demos, prototyping, contracting with UI designers, and so forth.</p>
<p><b>Code powers software, but it&#8217;s not the same as software</b>.  Software is what users see, code is what programmers see.  If you are going to solve a problem, you&#8217;re going to need to understand where the problem is.  Is it in your software, or your code?  The only way to know is to draw a clear line between defects and enhancements, then look at which of those two is taking up most of the team&#8217;s time.</p>
<p>Does it seem overly pedantic to draw the distinction?  Yes.  Is it crucial to improving the quality of what gets delivered to end-users?  Absolutely.</p>
<p><strong>How do we know the difference?</strong></p>
<p>I thought about concluding this article with some type of flow chart that asks questions to help determine if something is a defect or an enhancement.  I thought about all of the different rules I use when trying to make the determination, but ultimately what I wound up with is a lot simpler than I expected.</p>
<p>The customer has filed a complaint about the system.  The complaint states that they are expecting a certain thing to happen, but something else happens instead.</p>
<p>Ask yourself this: <strong>Does the something-else that&#8217;s happening violate the acceptance criteria of any user story that the team has ever implemented and had accepted?</strong></p>
<p>If the answer is <em>yes</em>, it&#8217;s a defect. The root cause is code quality.</p>
<p>If the answer is <em>no</em>, it&#8217;s an enhancement.  The root cause is software quality.</p>
<p>I really couldn&#8217;t think of a better way to draw a hard line between these two concepts, though I welcome visitors to comment with their own rules of thumb.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nomachetejuggling.com/2009/08/01/enhancement-vs-defect-more-than-pedantry/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
