<?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>Dave Smith&#039;s Blog</title>
	<atom:link href="http://thesmithfam.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://thesmithfam.org/blog</link>
	<description>Your blog is probably better than mine.</description>
	<lastBuildDate>Mon, 05 Jul 2010 04:44:43 +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 give a killer demo</title>
		<link>http://thesmithfam.org/blog/2010/07/04/how-to-give-a-killer-demo/</link>
		<comments>http://thesmithfam.org/blog/2010/07/04/how-to-give-a-killer-demo/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 04:17:38 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>
		<category><![CDATA[Miscellany]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=701</guid>
		<description><![CDATA[You&#8217;ve been there. You&#8217;re sitting in a demo where the lead engineer is presenting a new product to the customer. With laser pointer blazing, he shows off the 300 features of the new Blarney Gadget. He&#8217;s going a million miles an hour, switching between PowerPoint and the product on the screen as fast as the [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;ve been there. You&#8217;re sitting in a demo where the lead engineer is presenting a new product to the customer. With laser pointer blazing, he shows off the 300 features of the new Blarney Gadget. He&#8217;s going a million miles an hour, switching between PowerPoint and the product on the screen as fast as the keyboard will allow. 50 slides later, he finally finishes, crossing the demo finish line like an Olympic sprinter. He sits down, glad the demo is over, and takes a deep breath. At this point, the audience&#8217;s heads turn slowly, like spectators at Wimbledon, to look at the customer, hoping for approval. The customer sits quietly for a moment, leans forward, and asks, &#8220;Does this have a new Blarney Gadget?&#8221;</p>
<p>This was not a killer demo. I&#8217;ve sat through a lot of these, and I&#8217;m sure you have too. Fortunately, you can do a few simple things to make sure your demo goes better than this. I have most experience with intimate demos involving an audience of fewer than 30 people. These suggestions work best with that kind of audience.</p>
<h2>1. Explain the Setup</h2>
<p>Any product worth its salt is complicated, at least under the hood. You&#8217;ve just spent a lot of time building a new product with a team of engineers. If it were simple, you wouldn&#8217;t need to do a demo to show it off. So you&#8217;ve got to explain the background. Here&#8217;s a checklist of things that you ought to explain before diving into the demo:</p>
<ul>
<li>Physical configuration
<ul>
<li>Are there cables involved?</li>
<li>Explain how everything&#8217;s connected</li>
<li>Explain the computers involved and where they are</li>
<li>Explain all the software involved, with diagrams if it helps</li>
</ul>
</li>
<li>List improvements since last time, if applicable
<ul>
<li>&#8220;Do you remember how the product used to do X?, and that sucked?&#8221;</li>
<li>&#8220;In the past when I clicked this button, it took 30 seconds to process. Now it&#8217;s done in 3 seconds&#8221;.</li>
<li>&#8220;Users told us that this used to be confusing. We&#8217;ve tried to make the feature more approachable and user friendly.&#8221;</li>
</ul>
</li>
</ul>
<h2>2. Tell the Future</h2>
<p>Don&#8217;t expect your audience to know whether the demo worked or not. Tell them what&#8217;s going to happen when you click that magical button, <b>before you click it</b>, so they can participate in the demo success when it works.  Get them to feel the excitement of anticipation, and when it works, they ought to instantly think, &#8220;Yes, it worked!&#8221;, just like you do. To make this emotional connection, you have to tell the future. Here&#8217;s an example of telling the future:</p>
<p><b>&#8220;When I click this button, you will see that light blink (point at it), an on-screen spinner will begin to turn, and about 10 seconds after that, a message will appear with the number forty-two. Any questions on what&#8217;s going to happen?&#8221;</b></p>
<p>Take time to listen for questions. Make sure the audience is completely clear on what&#8217;s about to happen <b>before</b> you click that button. Don&#8217;t rush this.</p>
<p>Then, click the button.</p>
<p>After the process finishes, don&#8217;t jump in and say, &#8220;See? It worked.&#8221; Instead, let the audience come to that conclusion themslves. You gave them enough information to evaluate whether it worked, and if you &#8220;told the future&#8221; correctly, they will see for themselves. This way, they will believe more seriously that your product works (they verified the results themselves, after all).</p>
<h2>3. Face Checks</h2>
<p>Take time during your demo to make eye contact with each member of the audience, if possible. If you have more than about 20 people in your audience, you&#8217;ll have to limit this exercise. Check for the following expressions in the audience:</p>
<ul>
<li>Confusion: A furrowed brow, looking downward, or a pained grimace</li>
<li>Boredom: Eyes glazed over, looking at nothing in particular, or head bobbing</li>
<li>Excitement: Eyebrows raised, lots of motion, smiling, or the &#8220;ah hah&#8221; look</li>
</ul>
<p>If you catch someone bored or confused, it&#8217;s time to engage them. Start asking questions. If you can&#8217;t think of a question to ask, try this one:</p>
<p><b>Any questions?</b></p>
<p>Followed by a 10-second pause. 10 seconds is a long time in a demo. Count it down in your head, &#8220;10 Mississippi, 9 Mississippi, 8 Mississippi, &#8230;&#8221;</p>
<p>Another list of engaging questions:</p>
<ul>
<li>Does this seem like a good approach to you?</li>
<li>Do you think your organization will be able to make use of this?</li>
<li>In your opinion, are we on the right track?</li>
<li>Are there any concerns with what I&#8217;ve presented so far?</li>
<li>Do you feel like there&#8217;s something we could have improved?</li>
</ul>
<p>By the way, don&#8217;t be afraid to take the conversation in a new direction based on the responses to these questions.</p>
<p>You should do a round of face checks after making important points in your demo. Take a look at each face and spend about 1 second looking for the expressions listed above. Just looking at their faces can cause them to better engage in the demo. The audience needs to feel like they are participating in an interactive experience, and not just &#8220;along for the ride&#8221; like some kind of academic lecture.</p>
<h2>4. Slow the Tempo</h2>
<p>Presenters almost always go too fast, especially during demos. I think there are two reasons for this:</p>
<ol>
<li>They are nervous</li>
<li>The technology is more familiar to the presenter than the audience</li>
</ol>
<p>As a presenter, you should go slower than you think. You almost can&#8217;t go too slow. Here are a few tips:</p>
<ul>
<li>Allow silent moments
<ul>
<li>Just look at the screen and look at the audience.</li>
<li>This will let the audience absorb.</li>
<li>Don&#8217;t fear the silence. Embrace it.</li>
</ul>
</li>
<li>Ask what the audience thinks
<ul>
<li>If you get no answer, you are going too fast</li>
</ul>
</li>
<li>Draw on a whiteboard
<ul>
<li>This will naturally slow things down</li>
</ul>
</li>
<li>For long demos, plan regular breaks</li>
</ul>
<h2>5. Easy on the Superlatives</h2>
<p>Avoid words like &#8220;fantastic&#8221; and &#8220;spectacular.&#8221; Let the demo speak for itself, and let the audience come to their own &#8220;fantastic&#8221; conclusions. Instead use phrases like &#8220;isn&#8217;t that neat?&#8221; and &#8220;we thought you&#8217;d like this.&#8221; If the demo is pitched properly, the audience will see how &#8220;fantastic&#8221; it is without you cramming it down their throat. If you start tossing around superlatives, and the audience doesn&#8217;t agree, it will solidify a strong opposition to your product in their mind, and they might think of you as a slimy marketing <a href="http://www.google.com/images?q=weasel">weasel</a>.</p>
<p>This is one place where <a href="http://en.wikipedia.org/wiki/Steve_Jobs">Steve Jobs</a> excels. He uses phrases like, &#8220;we think you&#8217;ll like this,&#8221; and &#8220;this is really neat,&#8221; and &#8220;wasn&#8217;t that cool?&#8221; It&#8217;s startling when people get up after Steve and start tossing words around like &#8220;phenomenal&#8221; and &#8220;amazing&#8221;. When I hear words like that, I think, &#8220;hey, you just show me the product, and I&#8217;ll decide whether it&#8217;s phenomenal.&#8221;</p>
<p>You <b>can</b> use accurate superlatives like &#8220;totally new&#8221; and &#8220;unprecedented&#8221;, but be careful to stick to accurate words and don&#8217;t venture into the realm of hyperbole.</p>
<h2>6. Repeatedly Repeat Yourself</h2>
<p>It&#8217;s okay to repeat yourself. Don&#8217;t worry about insulting the audience&#8217;s intelligence. Most people go too fast and shower the audience with so much new information that they get hopelessly lost. Err on the side of too much repetition rather than too little. If your face checks reveal that the audience is bored, you might be repeating yourself too much, but this is unlikely.</p>
<h2>7. Trade Vocal Cords</h2>
<p>Don&#8217;t talk too much. It&#8217;s human nature to support ideas when you feel like you invented them. You can use this principle when giving a demo by letting the audience talk through ideas. By letting them talk, you are letting them take ownership of the product, which is a good thing if you want them to be your supporter.</p>
<p>Be a good listener, but be careful not to lose control of the demo.</p>
<p>Pay attention to industry terminology they use, and try to use the same terminology in your presentation.</p>
<p>I think a good ratio is about 1/3 to 2/3. You should talk about 1/3 of the time, and let them talk about 2/3 of the time. This guarantees that they are engaged, and it really helps them solidify all the concepts in their mind. As an added bonus, you just might gain an insight into how they operate, which can help you make your software better for them.</p>
<h2>8. Spend Your Time Wisely</h2>
<p>A good demo has lots of audience discussion. Getting the ratio right is key. Here&#8217;s roughly how I divide my time during demos:</p>
<ul>
<li>1/4: Setup and background</li>
<li>1/4: The actual demo</li>
<li>1/2: Discussion and Q&#038;A</li>
</ul>
<p>Notice that it usually takes about as much time to explain the background as it does to give the actual demo. Sometimes, the background actually takes <b>longer</b>, and that&#8217;s perfectly fine.</p>
<p>Also notice that about half the time should be spent discussing and answering questions.</p>
<h2>Happy Demoing</h2>
<p>These tips have helped me demo successfully, and I hope they help you. If you have anything to add, please let me know. I&#8217;d love to work new suggestions into this article.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/07/04/how-to-give-a-killer-demo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Many Meanings of the C++ &#8220;Static&#8221; Keyword</title>
		<link>http://thesmithfam.org/blog/2010/06/12/the-many-meanings-of-the-c-static-keyword/</link>
		<comments>http://thesmithfam.org/blog/2010/06/12/the-many-meanings-of-the-c-static-keyword/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 05:06:03 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=882</guid>
		<description><![CDATA[In C++, the static keyword has a lot of meanings. Let&#8217;s go over all of them: Meaning 1: Private Linkage This one comes from C, and it lets you mark a variable as &#8220;file private&#8221;. Example: static int i = 42; void doSomething() { cout &#60;&#60; i; } In this example, static tells the compiler [...]]]></description>
			<content:encoded><![CDATA[<p>In C++, the <tt>static</tt> keyword has a lot of meanings. Let&#8217;s go over all of them:</p>
<p><b>Meaning 1: Private Linkage</b></p>
<p>This one comes from C, and it lets you mark a variable as &#8220;file private&#8221;.</p>
<p>Example:</p>
<pre>
static int i = 42;
void doSomething()
{
    cout &lt;&lt; i;
}
</pre>
<p>In this example, <b>static</b> tells the compiler to not make the variable <b>i</b> available from other source files. If another file tries to use <b>i</b>, perhaps using the <tt>extern</tt> keyword, it would generate a linker error (unresolved external symbol). The same concept applies to functions whose access you want to limit to the current file.</p>
<p><b>Uses:</b></p>
<p>This is very handy for creating &#8220;file private&#8221; variables and functions. I recommend using static for any file-only functions. This way, you can name them whatever you like without risking a naming collision in the global namespace.</p>
<p><b>Gotchas:</b></p>
<p>Unfortunately, you can&#8217;t declare a class as static. Also, the language makes no guarantee about the order in which static variables are initialized. In my experience, static variables in the same file are initialized in a &#8220;sane&#8221; order, so you can do things like this:</p>
<pre>
static int i = 42;
static int j = i + 1;
</pre>
<p><b>Meaning 2: Function Call Spanning</b></p>
<p>This one also comes from C, and it lets you give a function-local variable a long lifespan. Here&#8217;s an example:</p>
<p>Example:</p>
<pre>
void foo()
{
    static int callCount = 0;
    callCount++;
    cout &lt;&lt; "foo has been called " &lt;&lt; callCount &lt;&lt; " times" &lt;&lt; endl;
}
</pre>
<p><b>Uses:</b></p>
<p>it&#8217;s a great way to keep track of how many times a function has been called, so it works well for generating unique ID numbers (watch out for thread-safety!). It&#8217;s also useful to keep track of whether a function is being called for the first time ever, like this:</p>
<pre>
void foo()
{
    static bool firstTime = true;
    if(firstTime)
    {
        // Do something special here
        firstTime = false;
    }
}
</pre>
<p><b>Gotchas:</b></p>
<p>Static function-local variables are initialized the <b>first time</b> the function is called, not before. Using these kinds of variables can often make your code not thread safe and not re-entrant, so take care before using them. You can put static variables within scope blocks (like inside an <b>if</b> or <b>for</b> statement). I&#8217;m not totally sure what the implications are, and frankly I&#8217;ve never felt the need to limit the scope of a variable so aggressively.</p>
<p><b>Meaning 3: Per-Class Data</b></p>
<p>When you declare a class member as static, it now belongs to the class at large, and not a particular instance.</p>
<p>Example:</p>
<pre>
// In the .h file:
class MyClass
{
    public:
        static int FavoriteNumber;
        static void foo();
};

// In the .cpp file (to initialize the static variable):

int MyClass::FavoriteNumber = 42;

void MyClass::foo()
{
    // can't access member variables here!
}
</pre>
<p><b>Uses:</b></p>
<p>It&#8217;s very common to store class-level constants this way. You can declare class functions as static as well, so they would be callable from anyone who has access to your class, even if they don&#8217;t have an instance. This is handy for helper functions. I generally like to make class functions static if they don&#8217;t need to operate on any instance data, typically for private helper functions.</p>
<p><b>Gotchas:</b></p>
<p>Static members are initialized very early in your program&#8217;s execution, before <b>main()</b> is even called actually. You also have <a href="http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12">no guarantee about the order</a> in which they are initialized between classes in different files. Be careful not to initialize one static class variable from another (possibly not-yet-initialized) static class variable. Also, you can&#8217;t access instance data from <b>this</b> within a static class function (unless someone passes you a <b>this</b> pointer). Lastly, you have to initialize your static class variables in your implementation (.cpp) file. Otherwise, the compiler doesn&#8217;t know how to allocate them (see the example above).</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/06/12/the-many-meanings-of-the-c-static-keyword/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Some Thoughts on Readability</title>
		<link>http://thesmithfam.org/blog/2010/05/31/some-thoughts-on-readability/</link>
		<comments>http://thesmithfam.org/blog/2010/05/31/some-thoughts-on-readability/#comments</comments>
		<pubDate>Mon, 31 May 2010 16:54:41 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=860</guid>
		<description><![CDATA[Communication is everything in software development. Unless you work on a team of one, it&#8217;s important that your code communicates easily to your team members. Even if you do work on a team of one, it&#8217;s important to communicate to your future self. Yeah, everyone has to read their own code once in a while, [...]]]></description>
			<content:encoded><![CDATA[<p>Communication is everything in software development.</p>
<p>Unless you work on a team of one, it&#8217;s important that your code communicates easily to your team members. Even if you do work on a team of one, it&#8217;s important to communicate <b>to your future self</b>. Yeah, everyone has to read their own code once in a while, and unless your brain is a steel trap, you&#8217;ll forget stuff.</p>
<p>So do yourself and your team a favor. Choose names carefully. Here are some examples.</p>
<p><b>Example 1: Use enumerations instead of booleans</b></p>
<p>This example is C++. Let&#8217;s pretend you&#8217;re writing a <tt>parse()</tt> function that looks like this:</p>
<p><tt>bool parse(const char *file_name, employee *e, bool validate_only)</tt></p>
<p>That seems pretty clear, doesn&#8217;t it? Let&#8217;s break it down:</p>
<p>Inputs:</p>
<ul>
<li>The path to the file to parse (called <tt>file_name</tt>)</li>
<li>The employee struct to populate with the parsing results</li>
<li>A flag to control whether to actually parse the file, or just dry-run (<tt>validate_only</tt>)</li>
</ul>
<p>Outputs:</p>
<ul>
<li>A true or false return value to indicate success or failure</li>
<li>The <tt>out</tt> structure, populated on success</li>
</ul>
<p>So far so good? Yeah, probably.</p>
<p>Reading the code so far, the purpose of each parameter is very clear, but don&#8217;t make people read your header files if they don&#8217;t have to. Consider the code that actually <b>calls</b> this function. It would look something like this:</p>
<pre>
employee e;
bool ret = parse("/tmp/foo.txt", &#038;e, true);
if (ret) {
   ...
</pre>
<p>Without looking back at the header file, can you tell me what this function does? For the most part, it&#8217;s obvious, but that <tt>true</tt> parameter is not  clear. I&#8217;m also not happy with the boolean return value (though it is the lesser of the two offenders).</p>
<p>Don&#8217;t make me think so hard. If I stumble across the code above, I shouldn&#8217;t have to go hunt down a header file just to figure out what it does. We can make this easier on developers by changing those <tt>bool</tt>s to <tt>enum</tt>s, like so:</p>
<pre>
enum parse_result { success, failure };
enum parse_mode { validate_only, full_parse };
parse_result parse(const char *file_name, employee *e, parse_mode mode);
</pre>
<p>By making these changes, callers would see this instead:</p>
<pre>
employee e;
parse_result result = parse("/tmp/foo.txt", &#038;e, validate_only);
if (result == parse_success) {
   ...
</pre>
<p>Instead of <tt>true</tt>, we read <tt>validate_only</tt>, and it&#8217;s immediately clear what this function is doing. The returned value is also very clear. There is no need to consult documentation or other header files to figure it out.</p>
<p><b>Example 2: Mutants</b></p>
<p>In Python, you can remove white space from strings with the <tt>strip()</tt> function. However, if I stumbled across code like this, I probably wouldn&#8217;t realize that it had a bug:</p>
<pre>
s = "   foobar   "
s.strip()
print s # What does this print?
</pre>
<p>That&#8217;s because the <tt>strip()</tt> function doesn&#8217;t actually strip whitespace from the string, but rather it <b>returns a new string</b> with the whitespace stripped.</p>
<p>In this case, I would recommend that <tt>strip()</tt> be renamed <tt>stripped()</tt> or <tt>tostripped()</tt> to make it more clear that it returns a new string.</p>
<p>For methods that <b>mutate</b> their instances, I recommend present-tense verbs like <b>strip()</b>, <b>rename()</b>, or <b>clear()</b>. But for methods that return modified copies of the instance, I recommend past-participle names like <b>stripped()</b>, <b>renamed()</b>, or <b>cleared()</b>.</p>
<p>Qt4 got this right with their changes to <tt>QString</tt>. Under Qt3, <tt>QString</tt> had a method called <tt>stripWhiteSpace()</tt>, so bugs like this were common:</p>
<pre>
QString str = "   foobar   ";
str.stripWhiteSpace();
// BUG: Is str actually stripped now?
</pre>
<p>In version 4, they renamed this method to <tt>trimmed()</tt>, so now there&#8217;s no question:</p>
<pre>
QString str = "   foobar   ";
str.trimmed();
// The bug is more obvious now
</pre>
<p><b>Example 3: Be specific</b></p>
<p>When reading others&#8217; code it is common to come across words like <b>data</b> or <b>ret</b> or <b>node</b>. While there are exceptions to this rule, these words usually aren&#8217;t specific enough to communicate your intent.</p>
<p>For example, let&#8217;s say I&#8217;m writing a Python program to run Linux commands and store their results in a map. Perhaps I make a function like this:</p>
<pre>
def run_commands(commands):
    data = {}
    for command in commands:
        output = subprocess.Popen(command,
            stdout=subprocess.PIPE).communicate()
        data[command] = output[0]
    return data
</pre>
<p>This just runs each command given to the function and puts the command&#8217;s output into a dictionary. Obviously, this is a tiny function, and as such, it may be an exception to the rule. However, if this were a more complicated function, perhaps one that executed each command in a separate thread and aggregated the results, <b>data</b> would not be very clear. Instead, I&#8217;d recommend renaming <b>data</b> to <b>command_results</b>. I might even go so far as to name it <b>command_results_dict</b> so it could be perfectly clear. Obviously, this rule can be taken too far. I would not recommend, for example, using a variable name like <b>command_subprocess_stdout_result_dict</b>. That would be insane.</p>
<p><b>Conclusion</b></p>
<p>So there you have it. Just a few pointers that are probably obvious to most of you already. We can all stand to clean up our communication now and then, so take this as a chance clean up the code you write today. I know I will.</p>
<p>Happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/05/31/some-thoughts-on-readability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>If you like writing lots of code, TDD is for you</title>
		<link>http://thesmithfam.org/blog/2010/05/23/if-you-like-writing-lots-of-code-tdd-is-for-you/</link>
		<comments>http://thesmithfam.org/blog/2010/05/23/if-you-like-writing-lots-of-code-tdd-is-for-you/#comments</comments>
		<pubDate>Sun, 23 May 2010 15:58:41 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=827</guid>
		<description><![CDATA[If there&#8217;s one thing you can&#8217;t argue about Test Driven Development, it&#8217;s that it creates more code than software written without it. Not just unit test code, either. To make code testable, developers often introduce extra layers of abstraction to make their code accessible, in isolation, from within their unit test code. This can be [...]]]></description>
			<content:encoded><![CDATA[<p>If there&#8217;s one thing you can&#8217;t argue about Test Driven Development, it&#8217;s that it creates more code than software written without it. Not just unit test code, either. To make code testable, developers often introduce extra layers of abstraction to make their code accessible, in isolation, from within their unit test code. This can be a good thing, but can also lead to a code explosion.</p>
<p>On second thought, I imagine someone actually would argue that, over time, a TDD codebase will have less code, for various reasons, possibly because it is easier to maintain, possibly because it encourages less code duplication, and so on. That&#8217;s fine, but this article is about the <strong>initial set of code</strong> that gets you to a shipping state, from scratch. We&#8217;re talking about version <strong>one point oh</strong>. The first set of working code that gets your product out the door, for the first time.</p>
<p>Okay, all clear?</p>
<p><strong>How about an example?</strong></p>
<p><a href="http://twitter.com/schuchert">Brett L. Schuchert</a>, who publishes on <a href="http://blog.objectmentor.com/">ObjectMentor&#8217;s blog</a> wrote an interesting piece of <a href="http://schuchert.wikispaces.com/Tdd.HelloWorld.Cpp">using TDD with C++ to write &#8220;Hello, world!&#8221;</a>.</p>
<p>Yes, seriously: &#8220;Hello world!&#8221;</p>
<p>You know, the program that&#8217;s so simple, you can write it practically from memory?</p>
<p>With your eyes closed.</p>
<p>With one hand tied behind your back.</p>
<p>Yeah, this one:</p>
<pre>
#include &lt;iostream&gt;
int main() {
   std::cout &lt;&lt; "Hello, world!" &lt;&lt; std::endl;
   return 0;
}
</pre>
<p>Mr. Schuchert decided to create &#8220;Hello, world!&#8221;, from scratch, by strictly following principles from Test Driven Development. An interesting idea.</p>
<p>The result?</p>
<p>Nearly <strong>80 lines of code</strong>, counting a Makefile that he felt compelled to create because it got too bothersome to compile with a single command.</p>
<p>Let&#8217;s look at that visually. Here are a couple graphs comparing the number of lines of code and the number of bytes used by the two approaches, TDD vs. Regular:</p>
<p><img src="/images/tdd-hello-world-graph-loc.png" width="350"/></p>
<p><img src="/images/tdd-hello-world-graph-bytes.png" width="350"/></p>
<p>After looking at this example, I&#8217;d like to consider a couple questions:</p>
<ul>
<li>Where would a bug most likely appear in this code?</li>
<li>What are the odds of a 79-line code base containing a bug compared to a 5-line codebase?
</li>
</ul>
<p>Let&#8217;s consider these questions in order:</p>
<p><b>Where would a bug most likely appear in this code?</b></p>
<p>Of the 79 line of code in the TDD codebase, only 2 lines are actually being tested, namely:</p>
<pre>std::cout &lt;&lt; "Hello, world!" &lt;&lt; std::endl;</pre>
<p>And</p>
<pre>return 0;</pre>
<p>The other 77 lines of code are well represented by lines like this:</p>
<pre>
TEST(HelloWorld, CorrectOuputPutToCout) {
    mainImpl(0, 0);
    STRCMP_EQUAL("Hello World!\n", stream->str().c_str());
}
</pre>
<p>And this:</p>
<pre>
int main(int argc, char **argv) {
    return mainImpl(argc, argv);
}
</pre>
<p>In the added TDD code, we find function calls with multiple arguments, string conversions between <tt>std::string</tt> and <tt>const char*</tt> types, unit test macros, and so on.</p>
<p>In this example, the added TDD code is actually <b>more complex</b> than the code under test. If I were a gambling man, I would bet that, given a randomly introduced bug, it would pop up in the <b>added TDD code</b> and not the code under test. Sadly, a bug in TDD code can render your tests useless.</p>
<p><b>What are the odds of a 79-line code base containing a bug compared to a 5-line codebase?</b></p>
<p>Unfortunately, I don&#8217;t have any empirical evidence to support an answer to this question. However, I have read and written a lot of code over the past 10 years. One thing I can say with confidence: A larger codebase is generally likely to contain more bugs than a smaller codebase. Obviously, there are exceptions to this rule. Some code is, by its nature, more complicated and bug-prone than other code. But, generally speaking, more code is likely to have more bugs than less code. In this example, we are dealing with more than a <b>10-fold code explosion</b>. While I wouldn&#8217;t argue that we should expect a 10-fold bug increase, I would suggest that there will be added bugs, when compared with the smaller codebase.</p>
<p>But what about over time?</p>
<p>Yes, overtime, your unit tests, if properly written, can prevent new bugs from being introduced to existing code, for certain kinds of codebases. For, &#8220;Hello, world!&#8221;, however, this is most certainly not true. I can&#8217;t imagine a case where even the least skilled developer would introduce a bug into this code. So, if you agree with me on that statement, then the argument that TDD reduces long-term maintenance costs is completely lost on this example.</p>
<p><b>Conclusion</b></p>
<p>Mr. Schuchert argues that using TDD for this example was the &#8220;right thing to do&#8221;, I have to respectfully disagree. Mr. Schchert concludes that TDD helped by removing business logic from main(), which is generally a good thing to do. In this example, however, I disagree. I feel that the business logic (i.e., printing &#8220;Hello, world!&#8221; and returning 0) is so simple and unlikely to change in the future, that the added complexity of  unit tests only makes the implementation less tractable and the code more costly to maintain. He introduces a build-dependency (the unit test framework) and added a layer of indirection for future readers to follow when learning the code. Further, the probability of introducing bugs has increased by the sheer volume of added TDD code. I conclude that while this was an interesting exercise into the TDD practice, I don&#8217;t think that TDD adds value in this example.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/05/23/if-you-like-writing-lots-of-code-tdd-is-for-you/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s Wrong With This Dialog?</title>
		<link>http://thesmithfam.org/blog/2010/05/16/whats-wrong-with-this-dialog/</link>
		<comments>http://thesmithfam.org/blog/2010/05/16/whats-wrong-with-this-dialog/#comments</comments>
		<pubDate>Mon, 17 May 2010 03:55:36 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=806</guid>
		<description><![CDATA[Sometimes I can&#8217;t help myself. This week, I read a blog post asking what was wrong with a dialog. I found plenty of stuff wrong, so I decided to write a response and create a replacement dialog. This is not intended as an attack on the dialog author. I hope it&#8217;s not received that way. [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes I can&#8217;t help myself. This week, I read a <a href="http://lateral.netmanagers.com.ar/weblog/posts/BB889.html">blog post asking what was wrong with a dialog</a>. I found plenty of stuff wrong, so I decided to write a response and create a replacement dialog. This is not intended as an attack on the dialog author. I hope it&#8217;s not received that way. Rather, I just felt an itch to answer the question posted with my own opinion on the subject.</p>
<p>Read on for the gory details.</p>
<p><b>Deciding what&#8217;s wrong</b></p>
<p>When I find myself asking if a feature is &#8220;wrong&#8221;, the first thing I do is ask if the feature should even exist. That is especially important with dialogs. Dialogs interrupt a user&#8217;s work flow, and for whatever non-deterministic-human-psychological reason, in-line GUI elements tend to interrupt humans less than pop-up dialogs. I try to avoid dialogs, and pop-ups, almost religiously. So when I find myself asking, &#8220;what&#8217;s wrong with this dialog?&#8221;, the next question I ask is &#8220;should this dialog even exist?&#8221;. Unfortunately, in this article, I can&#8217;t tell whether that&#8217;s the case, so I&#8217;ll assume it must exist.</p>
<p><b>The litany</b></p>
<p>In my view, this dialog contains many mistakes. Its core functionality is certainly accessible, but it&#8217;s not as easy as it should be. Here&#8217;s my list of mistakes:</p>
<p><a href="/images/dialog-fixes-old.png"><img src="/images/dialog-fixes-old.png" /></a></p>
<p>Now I&#8217;ll try to explain myself in prose rather than pixels.</p>
<p><strong>Mistake 1: Too many buttons</strong></p>
<p>This dialog provides a simple <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> user interface, but it has <b>6 buttons</b>. That&#8217;s too many buttons for such a simple task</p>
<p><b>Mistake 2: Wasted space</b></p>
<p>Don&#8217;t get me wrong. I&#8217;m a fan of liberal white space between elements. I think it puts users at ease, when used properly. But in this case, there is too much wasted space.</p>
<p><b>Mistake 3: Misalignment</b></p>
<p>The 6 buttons all have icons, but none of the buttons or text align vertically. This forces the human eye to read more carefully, causing unnecessary stress.</p>
<p><b>Mistake 4: No way to revert</b></p>
<p>If I make a mistake with this dialog, my only option is to manually revert my changes. Sometimes this approach is okay, especially with simple dialogs like this one, but as a user, I find it comforting when there is a &#8220;cancel&#8221; button to rescue me from my own fat fingers. I realize that the GNOME project usually follows the &#8220;apply-as-you-type&#8221; paradigm, but I prefer the OK/Cancel/Apply approach.</p>
<p><b>Mistake 5: Editing, Deleting, and Re-ordering is too hard</b></p>
<p>Although the &#8220;focus-and-click&#8221; method for editing, deleting, and re-ordering has seen a lot of use over the years, I find it dated and confusing to users. I much prefer to inline the &#8220;edit&#8221; and &#8220;remove&#8221; buttons as close to their respective elements as possible, reducing confusion about exactly what will be deleted when I click a button. Also, clicking &#8220;Up&#8221; and &#8220;Down&#8221; to move the focused item in the list is old school. Much better to drag and drop in modern user interfaces.</p>
<p><b>The Proposal</b></p>
<p>If I woke up in the UI designer&#8217;s shoes tomorrow, and this dialog was my number one priority, I would probably refactor it as follows:</p>
<p><a href="/images/dialog-fixes-new.png"><img src="/images/dialog-fixes-new.png" /></a></p>
<p><b>Improvement 1: Easy editing</b></p>
<p>The actions of the &#8220;Edit&#8221; and &#8220;Remove&#8221; buttons are super obvious. To edit an item, click the &#8220;Edit&#8221; button right on it. No ambiguity. You also don&#8217;t have to worry about graying out buttons when there is no selection.</p>
<p><b>Improvement 2: Drag and drop</b></p>
<p>To re-order items in the list, just drag &#8216;em.</p>
<p><b>Improvement 3: Cancel</b></p>
<p>If you don&#8217;t like your changes, click &#8220;Cancel&#8221;. Also, if you want to see the effect of your changes without closing the dialog, click &#8220;Apply&#8221;. Very handy if you want to try out lots of little changes without having to re-open the dialog between each change.</p>
<p><b>Improvement 4: No focusing</b></p>
<p>Now that the &#8220;Edit&#8221; and &#8220;Remove&#8221; buttons are in-line with the list items, there&#8217;s no need for a selection/focus model at all. That&#8217;s one less thing the user has to worry about.</p>
<p><b>Improvement 5: Simpler layout</b></p>
<p>The layout is essentially vertical. The user sees two areas, one above the other, and the two areas do <b>only one thing each.</b> The top area contains the list of editable items. The bottom area deals with saving your changes (the &#8220;add&#8221; button is a small exception). I think this design is more approachable and easier for a user to understand quickly.</p>
<p><b>Conclusion</b></p>
<p>So that&#8217;s what I propose. A simpler, cleaner approach using modern methods to make the editing task easier on users. It doesn&#8217;t make them think <strong>about the user interface</strong>, but rather they are freed to think about the <strong>task they want to accomplish</strong> with the user interface.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/05/16/whats-wrong-with-this-dialog/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Smart Folder Synchronization with Python</title>
		<link>http://thesmithfam.org/blog/2010/05/12/smart-folder-synchronization-with-python/</link>
		<comments>http://thesmithfam.org/blog/2010/05/12/smart-folder-synchronization-with-python/#comments</comments>
		<pubDate>Thu, 13 May 2010 03:15:40 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=787</guid>
		<description><![CDATA[I have various files that download to my computer automatically. They arrive at different times of the day or night. When they do, I like to transfer them to a network drive on another computer automatically. But there's a wrinkle. When the files auto-download to my computer, they go into one folder automatically, but when [...]]]></description>
			<content:encoded><![CDATA[<p>I have various files that download to my computer automatically. They arrive at different times of the day or night. When they do, I like to transfer them to a network drive on another computer automatically.</p>
<p>But there's a wrinkle.</p>
<p>When the files auto-download to my computer, they go into <strong>one</strong> folder automatically, but when I transfer them to my network drive, I like them to go into <strong>different</strong> folders, based on their file name.</p>
<p>Python to the rescue.</p>
<p>I whipped out this little script that runs from cron every 5 minutes on my Mac, rsync'ing files from my "Downloads" folder into a specific subfolder of "/Volumes/Shared", following a set of rules. In this script, any file with the string "dave" in its name gets copied to the "/Volumes/Shared/Dave Stuff" folder. Any file with "bob" in its name gets sent to "/Volumes/Shared/Files for Bob", and so on.</p>
<p>Here it is for  your enjoyment:</p>
<div class="igBar"><span id="lpython-2"><a href="#" onclick="javascript:showPlainTxt('python-2'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PYTHON:</span>
<div id="python-2">
<div class="python">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Filename filters, and which folders to send them to:</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">filters = <span style="color: black;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Filename&nbsp; :&nbsp; Dest Folder</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #483d8b;">'dave'</span>&nbsp; &nbsp; &nbsp; : <span style="color: #483d8b;">'Dave Stuff'</span>,</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #483d8b;">'bob'</span>&nbsp; &nbsp; &nbsp; &nbsp;: <span style="color: #483d8b;">'Files For Bob'</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #483d8b;">'frank'</span>&nbsp; &nbsp; &nbsp;: <span style="color: #483d8b;">'Franks Junk'</span>,</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: black;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">src&nbsp; &nbsp;= <span style="color: #483d8b;">'/Users/Dave/Downloads'</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">dest&nbsp; = <span style="color: #483d8b;">'/Volumes/Shared'</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">rsync = <span style="color: #483d8b;">'rsync --times '</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># ----------------------------------------------------------</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">subprocess</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Only show progress when we're running in a terminal (and not cron):</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">isatty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; rsync = rsync + <span style="color: #483d8b;">'--progress '</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #008000;">dir</span>, dirs, files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span>src<span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> files:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> filename.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">"."</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> filename.<span style="color: black;">endswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">".part"</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">continue</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; fullpath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">dir</span>, filename<span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #008000;">filter</span>, destfolder <span style="color: #ff7700;font-weight:bold;">in</span> filters.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> filename.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #008000;">filter</span><span style="color: black;">&#41;</span>&gt;= <span style="color: #ff4500;color:#800000;">0</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fulldest = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>dest, destfolder<span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">"Copying '"</span> + filename + <span style="color: #483d8b;">"' to folder '"</span> + destfolder + <span style="color: #483d8b;">"'"</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">cmd</span> = rsync + <span style="color: #483d8b;">' &quot;'</span> + fullpath + <span style="color: #483d8b;">'&quot; &quot;'</span> + fulldest + <span style="color: #483d8b;">'/.&quot;'</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span>, shell=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyboardInterrupt</span>:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; process.<span style="color: black;">kill</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;color:#800000;">1</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">break</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Could not find a home for file &quot;'</span> + filename + <span style="color: #483d8b;">'&quot;'</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>When this script runs, it just blindly tells rsync to transfer the files, but rsync will only transfer them if they are newer in the "src" folder than the "dest" folder. That's thanks to rsync's "--times" argument, which tells rsync to preserve the file times when it does the transfer.</p>
<p>So far it's working great. I called it "sync-download-files" and created a crontab file called /Users/Dave/etc/crontab, that looks like this:</p>
<p><code>*/5 * * * * ~/bin/sync-download-files >/dev/null 2>&#038;1</code></p>
<p>Then I ran this crontab command to install the job:</p>
<p><code>crontab /Users/Dave/etc/crontab</code></p>
<p>And voila! Files now auto-sync to /Volumes/Shared every 5 minutes. When there are no files to sync, the script completes in a couple seconds.</p>
<p>By the way, in my case, /Volumes/Shared is a Samba mounted network share to a WDTV Live box.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/05/12/smart-folder-synchronization-with-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenWrt gets Qt SQL Support</title>
		<link>http://thesmithfam.org/blog/2010/04/18/openwrt-gets-qt-sql-support/</link>
		<comments>http://thesmithfam.org/blog/2010/04/18/openwrt-gets-qt-sql-support/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 14:57:25 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=756</guid>
		<description><![CDATA[On US tax day 2010, OpenWrt's "qt4" feed got support for MySQL and SQLite. And there was much rejoicing among Qt developers. A big thanks to Mirko Vogt for porting the build system to OpenWrt and letting me help out with the SQL stuff.]]></description>
			<content:encoded><![CDATA[<p><img src="/images/qt-logo.png" style="float:right; margin-left: 10px;" />On US tax day 2010, OpenWrt's "qt4" feed got <a href="https://dev.openwrt.org/changeset/20879">support for MySQL and SQLite</a>. And there was much rejoicing among Qt developers.</p>
<p>A big thanks to Mirko Vogt for porting the build system to OpenWrt and letting me help out with the SQL stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/04/18/openwrt-gets-qt-sql-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using scp between Linux and Mac OS X</title>
		<link>http://thesmithfam.org/blog/2010/04/11/using-scp-between-linux-and-mac-os-x/</link>
		<comments>http://thesmithfam.org/blog/2010/04/11/using-scp-between-linux-and-mac-os-x/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 23:57:41 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=746</guid>
		<description><![CDATA[For a while, I haven't been able to get scp to work between Linux and Mac OS X. This only happened when I used the scp command on my Linux box, with Mac OS X acting as the ssh server. Here's the symptom: On Linux: $ scp user@192.168.1.5:~/Documents/Some/File.txt /tmp/. Password: $ It disconnected me after [...]]]></description>
			<content:encoded><![CDATA[<p>For a while, I haven't been able to get <b>scp</b> to work between Linux and Mac OS X. This only happened when I used the <b>scp</b> command on my Linux box, with Mac OS X acting as the ssh server. Here's the symptom:</p>
<p>On Linux:</p>
<p><b>$ scp user@192.168.1.5:~/Documents/Some/File.txt /tmp/.<br />
Password:<br />
$</b></p>
<p>It disconnected me after entering my password without transferring the file. In the Gnome File Browser (nautilus), if I tried to connect to the Mac OS X box using <b>ssh://</b> in the address bar, the <b>gvfsd-sftp</b> process would consume 100% of the CPU until I killed it.</p>
<p>Here's the solution:</p>
<p>On the Mac OS X computer, in my <b>~/.bashrc</b> file, I was <b>echo</b>'ing some text just to say that my <b>.bashrc</b> had been sourced. Removing that <b>echo</b> line fixed the problem and now both the <b>scp</b> command and the Gnome File Browser work just fine.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/04/11/using-scp-between-linux-and-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maiden Flight of ParkZone Habu</title>
		<link>http://thesmithfam.org/blog/2010/04/10/maiden-flight-of-parkzone-habu/</link>
		<comments>http://thesmithfam.org/blog/2010/04/10/maiden-flight-of-parkzone-habu/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 03:58:10 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[RC Planes]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=723</guid>
		<description><![CDATA[After a stress-free build, the ParkZone Habu gave me two stress-free maiden flights. I'll let the video do all the talking:]]></description>
			<content:encoded><![CDATA[<p>After a stress-free build, the ParkZone Habu gave me two stress-free maiden flights. I'll let the video do all the talking:</p>
<p><object style="margin-left: -140px" width="640" height="385"><param name="movie" value="http://www.youtube.com/v/k6UbP8hIhkU&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/k6UbP8hIhkU&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/04/10/maiden-flight-of-parkzone-habu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Reminder: Don&#8217;t Hard Code It</title>
		<link>http://thesmithfam.org/blog/2010/04/06/reminder-dont-hard-code-it/</link>
		<comments>http://thesmithfam.org/blog/2010/04/06/reminder-dont-hard-code-it/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 02:35:48 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Code and Cruft]]></category>

		<guid isPermaLink="false">http://thesmithfam.org/blog/?p=715</guid>
		<description><![CDATA[Today's reminder comes from the "magic number" department, where we remind you to never hard-code a magic number in your software. For example, the value for ETIMEDOUT on Linux can vary depending on your C library. glibc, for example, defines it as 110, but uClibc defines it as 145. This tends to matter when you [...]]]></description>
			<content:encoded><![CDATA[<p>Today's reminder comes from the "magic number" department, where we remind you to never hard-code a magic number in your software. For example, the value for <strong>ETIMEDOUT</strong> on Linux can vary depending on your C library. <strong>glibc</strong>, for example, defines it as 110, but <strong>uClibc</strong> defines it as 145. This tends to matter when you are using a return value from, for example, libusb, at an important branching point in your software. Of course, this whole exercise is hypothetical. I would never hard code a number like that, of course not.</p>
<p><strong>The upside:</strong><br />
The <a href="http://www.libusb.org/browser">libusb source code</a> is available for the world to see.</p>
<p><strong>The downside:</strong><br />
The <a href="http://libusb.sourceforge.net/doc/">libusb documentation</a> <a href="http://www.google.com/search?q=etimedout+site:libusb.sourceforge.net">makes no mention</a> of <strong>ETIMEDOUT</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thesmithfam.org/blog/2010/04/06/reminder-dont-hard-code-it/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
