<?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/"
	>

<channel>
	<title>NomadNet, Inc. Blog</title>
	<atom:link href="http://nomadnetinc.com/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://nomadnetinc.com/blog</link>
	<description>Software in a World of Information</description>
	<pubDate>Mon, 31 May 2010 13:46:23 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Skills Transcend Language</title>
		<link>http://nomadnetinc.com/blog/2009/03/17/skills-transcend-language</link>
		<comments>http://nomadnetinc.com/blog/2009/03/17/skills-transcend-language#comments</comments>
		<pubDate>Tue, 17 Mar 2009 17:54:04 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[choosing technology]]></category>

		<category><![CDATA[project management]]></category>

		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=208</guid>
		<description><![CDATA[A common tendency when looking for software developers is to focus closely on their background in specific programming languages.  As previously discussed in Why Do You Hire Programmers?, unnecessary focus on a specific language can lead to other, more appropriate options being overlooked.
A second hazard arises in that, by looking for language-specific experience, this [...]]]></description>
			<content:encoded><![CDATA[<p>A common tendency when looking for software developers is to focus closely on their background in specific programming languages.  As previously discussed in <a href="http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers/">Why Do You Hire Programmers?</a>, unnecessary focus on a specific language can lead to other, more appropriate options being overlooked.</p>
<p>A second hazard arises in that, by looking for language-specific experience, this practice contains an implicit assumption that programming languages stand alone, with little relation to one another, and that learning a new one is a major undertaking.</p>
<p>These issues are two sides of the same coin, both flawed in their failure to recognize that, while programming languages are the means used to develop software, they are not the primary skills of software development.</p>
<h3>The Right Tool For The Job</h3>
<p>A commonly-used metaphor, and one which would have been appropriate to the points made in <a href="http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers/">Why Do You Hire Programmers?</a>, is that of a carpenter&#8217;s toolbox.  &#8220;<i>When you want to build a house, you look for a carpenter who builds houses, not a carpenter who has 5 years of experience using hammers and 2 years using nailguns with preference given to candidates who are also familiar with screwdrivers.</i>&#8221;</p>
<p>While this metaphor does make a good point, that the craftsman&#8217;s skills go beyond the specific tools used and that you should trust him to use the right tool at the right time, I still have minor issues with it in that it preserves the misconception that each software development tool is fundamentally different from the others.  Although there is some overlap between the skills of using hammers, nailguns, or screwdrivers, they are, by and large, three distinct activities.  The skills of writing software in C, Java, or Smalltalk, on the other hand, overlap by much more than they differ.</p>
<h3>Something A Little Less Prosaic</h3>
<p>A much more apt metaphor would be to compare the programmer to the poet.</p>
<p>Skilled poets can write in many forms.  A master of the sonnet can also be expected to competently produce ballads or limericks when called for and would likely be able to write a mean haiku with very little practice.  The core skills of handling meter and rhyme or choosing the right words to paint a vivid image apply broadly across all poetic forms.</p>
<p>Similarly, a well-rounded developer is proficient in a variety of programming languages and can apply his core skills in logic and program structure to new languages with a minimum of difficulty.  The techniques do vary from one language to another, with some placing more emphasis on one type of logic and others emphasizing structure more heavily, just as rhyme is everything to a limerick and irrelevant to a haiku, but this is generally a minor obstacle, if any at all.</p>
<h3>Learning The Language</h3>
<p>There is a common case where this falls apart, however:  Programmers who only know a single language.  Although it&#8217;s not inevitable, this often indicates someone who has solely learned that language without also learning the more general techniques of software development and how they apply beyond the one language.</p>
<p>The primary skills needed in software development are ways of thinking, of finding solutions for problems, and of structuring those solutions.  They are not the vocabulary or syntax of particular programming languages.  You will often be much better off with someone who has extensive experience with a wide range of technologies, but doesn&#8217;t know your particular language, than with someone who has extensive experience with your language, but has never used anything else.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/03/17/skills-transcend-language/feed</wfw:commentRss>
		</item>
		<item>
		<title>And Now A Brief Word From Our Author</title>
		<link>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author</link>
		<comments>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author#comments</comments>
		<pubDate>Mon, 09 Mar 2009 15:21:01 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[Software Development]]></category>

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

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

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

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

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=414</guid>
		<description><![CDATA[Just two quick updates today:
1.  A Correction To Last Tuesday&#8217;s Post
In Off the Record: Passwords, I recommended the use of SHA1 rather than MD5 hashes when storing passwords.  Since then, I have encountered a persuasive argument in favor of abandoning both of them and using bcrypt instead, as it&#8217;s designed to be less [...]]]></description>
			<content:encoded><![CDATA[<p>Just two quick updates today:</p>
<h3>1.  A Correction To Last Tuesday&#8217;s Post</h3>
<p>In <a href='http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords/'>Off the Record: Passwords</a>, I recommended the use of SHA1 rather than MD5 hashes when storing passwords.  Since then, I have encountered a persuasive argument in favor of abandoning both of them and using bcrypt instead, as it&#8217;s designed to be <i>less</i> time-efficient, thus dramatically reducing the number of potential passwords that a brute-force attack can attempt in a given amount of time.</p>
<p>As this can make your passwords much more secure against attackers while still keeping single-hash generation running at a reasonable pace, I have revised that post to recommend the use of bcrypt over SHA1 where available.</p>
<h3>2.  I&#8217;m Not Disappearing</h3>
<p>New posts to this blog have slowed down substantially over the last couple weeks because the stockpile which I prepared prior to launching the blog have all been published and my new writing process, which I expect to work out much better in the long run, is taking longer than the old one to produce completed posts, ready to publish.  If all goes as it appears that it will, the rate of new posts should pick up again by the end of next week if not sooner.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author/feed</wfw:commentRss>
		</item>
		<item>
		<title>Off the Record: Passwords</title>
		<link>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords</link>
		<comments>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords#comments</comments>
		<pubDate>Tue, 03 Mar 2009 16:46:40 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

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

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

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

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

		<category><![CDATA[software development]]></category>

		<category><![CDATA[war stories]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=132</guid>
		<description><![CDATA[In 1999, I accepted a programming job with a company selling voicemail service.  When it came time for the boss to demo the company&#8217;s product for me in full, he wanted to show me some feature that needed my PIN to be entered.  Rather than having me enter it, he turned to his [...]]]></description>
			<content:encoded><![CDATA[<p>In 1999, I accepted a programming job with a company selling voicemail service.  When it came time for the boss to demo the company&#8217;s product for me in full, he wanted to show me some feature that needed my PIN to be entered.  Rather than having me enter it, he turned to his computer, brought up my account information, and read the PIN off the screen.</p>
<p>Although I didn&#8217;t say a word, I just about died on the spot.  Although he wasn&#8217;t aware of it, <i>he now knew the PIN for my bank account!</i></p>
<p>Granted, I should have known better than to reuse a PIN (and I do know better now!), but it&#8217;s a very common practice nonetheless, especially as the number of PINs and passwords that each of us needs to keep track of seems to be increasing daily.</p>
<h3>Back To The Present</h3>
<p>More recently, there has been discussion on the debian-user mailing list of ways to log the passwords entered on unsuccessful login attempts.  While this seems innocuous at first glance, and an effective way of seeing what passwords are being tried by brute-force attackers, it will also catch passwords entered incorrectly by legitimate users.  These mistyped passwords will generally only be off by a letter or two, thus giving anyone with access to these logs the ability to much more easily guess the correct version.</p>
<p>Despite the potential advantages in being able to revise your password requirements to improve their strength against the latest dictionary attacks, the issue of password reuse remains.  These kinds of system logs are generally locked down well enough that they&#8217;re only accessible to system administrators whose legitimate powers are broad enough that knowing other users&#8217; passwords will not allow them to do any additional damage locally beyond what they can already do using their own account, but granting them knowledge of others&#8217; passwords also potentially allows them to impersonate the user on <i>other</i> systems.</p>
<p>Trusting them with this information is not necessary for them to perform their legitimate duties.  It allows them to do additional harm, but does not expand their powers for good.  Therefore, it should be kept from them and any security-conscious sysadmin or developer should recognize this.  (Personally, I have, on several occasions, cut off users who were about to tell me their passwords and explained that I would not allow them to do so.)</p>
<h3>Avoiding Password Leakage</h3>
<p>To maintain secrecy, user-entered passwords should <i>never</i> be recorded in plaintext.  I can&#8217;t think of any situations in which there would be a legitimate need to be able to recover an actual user password, but, should such a case exist, there are plenty of good, reversible encryption methods which can be used to store it, safe from prying eyes or casual glances.</p>
<p>The proper and generally-accepted method of dealing with passwords is to pass them through a non-reversible cryptographic hashing function, such as <strike>SHA1<sup>1</sup></strike> bcrypt<sup>2</sup>, then storing the hash rather than the password itself.  Use of reversible encryption would still leave the password vulnerable to anyone with access to the encryption key and the will to use it.  A <strike>SHA1</strike> bcrypt hash allows you to determine whether the entered password matches the correct password without ever knowing (or being able to know) what the correct password is.</p>
<h3>Afterword: Honeypots and Testing</h3>
<p>I did mention, above, that there are potential benefits to being able to see what passwords are being attempted by attackers.  If this information is needed, it can be obtained without compromising the security of your actual users&#8217; passwords by setting up a honeypot system with no valid user accounts (or at least none which accept password-based logins over the network).  Since no legitimate logins will be attempted, you can safely record the passwords without giving away information about legitimate users&#8217; accounts.</p>
<p>The other situation in which I&#8217;ve seen it suggested that it is appropriate to record passwords is when testing or debugging software under development to ensure that input (including the password) is being received and processed correctly.  Safeguarding actual user credentials is again easily done by means of not having any actual user data (or at least not any actual passwords) in the testing environment.</p>
<p>&nbsp;</p>
<hr width=75%>
<sup>1</sup> MD5 has been widely used for many years, but weaknesses are finally being found in it, so SHA1 is now considered a better choice for this purpose.</p>
<p><sup>2</sup> Shortly after making this post, I ran across <a href='http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/'>this article, which makes an excellent case for using bcrypt</a> rather than MD5 or SHA1.  If a bcrypt library is available in the environment where you&#8217;re operating, use it.  If it&#8217;s not available, see if you can get it added.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords/feed</wfw:commentRss>
		</item>
		<item>
		<title>Optimizing Software From 20,000 Feet</title>
		<link>http://nomadnetinc.com/blog/2009/02/27/optimizing-software-from-20000-feet</link>
		<comments>http://nomadnetinc.com/blog/2009/02/27/optimizing-software-from-20000-feet#comments</comments>
		<pubDate>Fri, 27 Feb 2009 16:54:41 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[project management]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[war stories]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=130</guid>
		<description><![CDATA[The First Rule of Program Optimization: Don&#8217;t do it.
The Second Rule of Program Optimization (for experts only!): Don&#8217;t do it yet.”
- Michael A. Jackson
If you spend much time with people who have any involvement with software development, you&#8217;re going to run across a conversation about optimizing software.  Either the program is too big or [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><i>The First Rule of Program Optimization: Don&#8217;t do it.<br />
The Second Rule of Program Optimization (for experts only!): Don&#8217;t do it yet.”</i><br />
- Michael A. Jackson</p></blockquote>
<p>If you spend much time with people who have any involvement with software development, you&#8217;re going to run across a conversation about optimizing software.  Either the program is too big or too slow or too chatty on the network or too <i>something</i> and somebody wants to do a little optimization to improve on that.</p>
<p>It usually starts with the natural impulse of geeks to tinker with their systems, but project leads, marketing departments, and managers are often drawn in by the promise of a better product.</p>
<p>Should you find yourself in that position, contemplating either undertaking an optimization project or authorizing one, stop and consider what the proposed optimization is and how much it will actually improve things.</p>
<h3>Optimizing Line-By-Line Is Rarely Worth It</h3>
<p>Micro-optimizations are generally not worth the time it takes to make them.  Shaving off a couple milliseconds from a function that only runs once is entirely pointless - it will produce no perceptible improvement, yet it comes at a potentially high cost in development time.  Simple optimizations of this type are often already done automatically by the programming language behind the scenes anyhow, while more complex attempts may backfire.</p>
<p>The primary exception to this is when the code in question will be repeated many, many times in rapid succession.  (Programmers often call this a &#8220;tight loop&#8221;.)  If the code will run 10,000 times, then making it take a millisecond less each time will save a total of 10 seconds.  If your user is sitting and waiting for the task to complete, that 10 seconds is an eternity.  On the other hand, if it&#8217;s part of a 6-hour non-interactive process to close out your monthly books, the 10 seconds saved is meaningless despite the repetition.</p>
<h3>Optimizing Algorithms Works Much Better</h3>
<p>Several years ago, as I was just starting my programming career, I had a job doing data entry on a system which needed to run a check for duplicate records before posting completed tasks into its archival database.  For performance reasons, it checked only those active records which were marked complete - and it still took nearly half an hour to run.</p>
<p>Eventually, the programmer who wrote the system left the company and I inherited his responsibilities for it.  One of the first things I did was take a hard look at the duplicate checking code.</p>
<p>The duplicate check, as originally written, looked at every single record in the archival database for each active record that was being checked.  Testing 10 active records for duplication against a 10,000-record archive database required 100,000 record-level comparisons.  No wonder it was slow.  It used an extremely inefficient algorithm.</p>
<p>Within a day, I had rewritten it with a better algorithm which only needed to make one pass over each database.  With 1,000 active records and 10,000 archived, it could test <i>every</i> active record (not just the completed ones) with only around 11,000 record-level comparisons.  It also used the databases more efficiently, bringing total run time down to roughly 15 seconds.  Vastly improved performance, plus a more thorough check.  A truly worthwhile optimization!</p>
<h3>The Most Important Optimization</h3>
<p>If I were to revise the original version of that duplicate check today, I could do even better.  I&#8217;m confident that I could get it under 5 seconds and probably down into the 1-2 second range, while still running on the same, now horribly outdated, hardware and software.</p>
<p>Why are such extreme improvements possible?  Because, at the time, I was able to devise a better algorithm than the original programmer had and because I now have several more years experience behind me than I did then.</p>
<p>If presented with my revised version, though, I would argue against further optimization of that code.  Since it was just run once a week, it wouldn&#8217;t be worth the effort involved in bringing it down from 15 seconds to 5, maybe not even if it could get down to 1.  Rewriting to eliminate the need to run the check at all might be worthwhile, but making the check faster would not.</p>
<p>The most important optimization is to optimize the skills and experience of your developers.  Software development is not a commodity product.  Getting someone with the skill to choose the right algorithms and the experience to know when an optimization wouldn&#8217;t produce sufficient improvement to justify the time invested will get you better results, in less time, and often for a lower overall cost.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/27/optimizing-software-from-20000-feet/feed</wfw:commentRss>
		</item>
		<item>
		<title>Email Address Validation</title>
		<link>http://nomadnetinc.com/blog/2009/02/25/email-address-validation</link>
		<comments>http://nomadnetinc.com/blog/2009/02/25/email-address-validation#comments</comments>
		<pubDate>Wed, 25 Feb 2009 16:00:13 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

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

		<category><![CDATA[data collection]]></category>

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

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

		<category><![CDATA[software development]]></category>

		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=219</guid>
		<description><![CDATA[In Validation Vexation, I wrote a bit about ways that validation rules for user-entered data can go awry by being too narrowly-defined.  This post adds three more principles for dealing with data validation which are primarily focused on the results of the validation rather than the rules used to do it.  The examples [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href='http://nomadnetinc.com/blog/2009/02/23/validation-vexation/'>Validation Vexation</a>, I wrote a bit about ways that validation rules for user-entered data can go awry by being too narrowly-defined.  This post adds three more principles for dealing with data validation which are primarily focused on the results of the validation rather than the rules used to do it.  The examples used are rather specific to handling email addresses, but the principles themselves still apply much more broadly.</p>
<h3>Incorrect Validation Is Worse Than No Validation</h3>
<p>A recurrent question I&#8217;ve seen on a couple different programming sites is &#8220;What regular expression can I use to validate an email address?&#8221;  They&#8217;ve gotten a lot of responses explaining ways to examine an email address and reject it if it&#8217;s &#8220;invalid&#8221;.  The only problem is that every one of them that tried to be more restrictive than just checking for the presence of an &#8220;@&#8221; was wrong.</p>
<p>The most common flaw was failing to accept &#8220;+&#8221; in the local-part of an address, causing many perfectly valid, deliverable email addresses to be rejected.  There were also several which failed on top-level domains (TLDs) which were four or more characters long, such as <i>.info</i> or <i>.museum</i>.</p>
<p>On the flip side, there were users accustomed to using disposable email addresses of the form <i>username+foo@domain.com</i> or with addresses automatically generated from their surname of <i>O&#8217;Malley</i> - including the apostrophe - complaining about sites refusing to accept their &#8220;invalid&#8221; (but syntactically correct and perfectly functional) email addresses.</p>
<p>Rejecting these addresses may only shut out a percent or two of the world, but is that really an acceptable cost to pay in an attempt to shut out truly bogus addresses?  Particularly given that&#8230;</p>
<h3>Valid Does Not Imply Correct</h3>
<p>Let&#8217;s say that you&#8217;ve managed to find yourself a perfect validation algorithm which is 100% accurate at determining whether email addresses are syntactically valid, even for the O&#8217;Malleys.  You&#8217;re getting only good email addresses, right?</p>
<p>Wrong.</p>
<p><i>abcde@fghi.jkl</i> is syntactically valid, but utterly bogus.  There isn&#8217;t even a .jkl TLD!</p>
<p>&#8220;OK,&#8221; you say, &#8220;I&#8217;ll just add a DNS lookup to my perfect validator so that it rejects domains that don&#8217;t exist or don&#8217;t have a mail exchanger (MX) record defined.&#8221;</p>
<p>Still no good.  <i>dave.sherohman@whitehouse.gov</i> is syntactically valid. It points to a domain that exists and accepts mail.  It&#8217;s still no good.</p>
<p>&#8220;No problem.  I&#8217;ll connect to the mail server and validate that the user account exists.&#8221;</p>
<p>I can still give you a bad email address.  Try <i>president@whitehouse.gov</i> on for size.  The account exists, but it&#8217;s certainly not mine.</p>
<h3>If There&#8217;s Any Chance Of An Incorrect Rejection, Don&#8217;t Pre-Validate</h3>
<p>The <i>only</i> way to authoritatively validate the correctness of an email address is to send email to the address and request that the user respond to it in some manner to confirm receipt.</p>
<p>You may still benefit from doing a preliminary validation to avoid the trouble of sending out mail that could never possibly be received, but this pre-validation cannot reasonably be considered authoritative and should, therefore, only be used to filter out the most blatantly incorrect cases.  Attempting to make it more restrictive will only introduce an unnecessary risk of rejecting genuine, correct, deliverable addresses.</p>
<p>The cost of performing the authoritative validation is low and the cost of rejecting an address which is incorrectly flagged as invalid by a flawed pre-validation is high, so don&#8217;t pre-validate beyond the point at which you are absolutely, 100% certain that it will not fail anything which might pass the authoritative validation.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/25/email-address-validation/feed</wfw:commentRss>
		</item>
		<item>
		<title>Validation Vexation</title>
		<link>http://nomadnetinc.com/blog/2009/02/23/validation-vexation</link>
		<comments>http://nomadnetinc.com/blog/2009/02/23/validation-vexation#comments</comments>
		<pubDate>Mon, 23 Feb 2009 16:37:41 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Technical]]></category>

		<category><![CDATA[User Experience]]></category>

		<category><![CDATA[data collection]]></category>

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

		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=116</guid>
		<description><![CDATA[Be liberal in what you accept, and conservative in what you send.
- Postel&#8217;s Prescription
Previous posts here have discussed reducing the burden of data entry on your application&#8217;s users by cutting down on the number of items that they are required to provide and, even if something is required, allowing it to remain incomplete for as [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><i>Be liberal in what you accept, and conservative in what you send.</i><br />
- Postel&#8217;s Prescription</p></blockquote>
<p>Previous posts here have discussed reducing the burden of data entry on your application&#8217;s users by cutting down on the number of items that they are required to provide and, even if something is required, allowing it to remain incomplete for as long as possible, only enforcing that &#8220;required&#8221; status when the time comes that it is actually needed.</p>
<p>But what about the values that are entered, whether required or not?</p>
<p>The next step in minimizing the burden placed upon your users is to &#8220;be liberal in what you accept&#8221;.  Do not impose validation rules which must be satisfied unless they are unavoidable.  If you really must require them, make sure that the rules themselves are complete and correct.</p>
<h3>Don&#8217;t Validate Formatting</h3>
<p>The biggest, most common, and most annoying case of pointless validation rules are those which impose restrictions on how the user must format his entry.  Any programming language worth its salt can effortlessly remove spaces from a string or insert a space after every fourth digit, so there is <i>absolutely no good reason</i> for credit card validations to care whether you enter the card number as &#8220;1234 5678 9012 3456&#8243; or as &#8220;1234567890123456&#8243;, or even &#8220;12 3 45678901 234 56&#8243;.</p>
<p>Phone numbers can trip you up here, too.  Does the program want them entered as (555)555-1212 or 555-555-1212 or +15555551212 or what?  The correct answer, again, is that it should accept any of these formats (and more), which is easily implemented by simply removing any non-numeric characters and then adding or removing a leading &#8220;1&#8243;, depending on whether you want the country code in your database.  This will also accommodate international phone numbers, which may have their digits grouped in patterns you don&#8217;t expect.</p>
<p>As long as it&#8217;s the right set of digits, let the user group them however he wants to.</p>
<h3>Remember The Rest Of The World</h3>
<p>When I moved from the US to Sweden, I paid my bank a visit to change my address with them.  It went reasonably well and their system was smart enough to recognize that, since my new address was outside the US, the &#8220;state&#8221; could be left blank.</p>
<p>But it still required a ZIP code.  Beyond that, it required the ZIP code to be formatted as a string of five digits with no intervening characters.  While it does just so happen that my Swedish postal code is 5 digits, they&#8217;re grouped &#8220;226 47&#8243;.  Also, the postal code goes before the city here, so we ended up having to enter the city as &#8220;226 47 Lund&#8221;, with a ZIP code of &#8220;00000&#8243;.  This is obviously incorrect, but it was the only option for satisfying the US-centric validation rules.</p>
<h3>Trust the User</h3>
<p>Speaking of ZIP codes, ZIP code-to-city databases are pretty nice.  They can be great for letting users enter their ZIP code and then automatically filling in a default city for them.</p>
<p>Note the word &#8220;<i>default</i>&#8220;.  The last US city I lived in was Eagan, MN, ZIP code 55122.  About half the ZIP code databases out there correctly list 55122 as Eagan.  The other half list it as St. Paul, which is a good 10 miles north of Eagan.  I knew I lived in Eagan, and the post office knew I lived in Eagan, but several websites insisted I was in St. Paul and provided no way for me to correct their mistake.</p>
<p>Looking up data instead of making the user enter it is good, but your database <i>will</i> be wrong sometimes.  Allow the user to correct the lookup results when this happens.</p>
<p>&nbsp;<br />
I do have a bit more to say on ways that data validation can go wrong, but that&#8217;s a topic for another post.  Until next time, what issues have you run into where too-strict or too-lax data validation has caused you problems?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/23/validation-vexation/feed</wfw:commentRss>
		</item>
		<item>
		<title>Open Source or No?</title>
		<link>http://nomadnetinc.com/blog/2009/02/18/open-source-or-no</link>
		<comments>http://nomadnetinc.com/blog/2009/02/18/open-source-or-no#comments</comments>
		<pubDate>Wed, 18 Feb 2009 20:47:26 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[choosing technology]]></category>

		<category><![CDATA[open source]]></category>

		<category><![CDATA[project management]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=262</guid>
		<description><![CDATA[Free/Open Source Software (FOSS) has taken the world by storm.  Startups everywhere have built their businesses upon a foundation of FOSS products, with the LAMP (Linux-Apache-MySQL-Perl/PHP/Python) platform being the best-known among them, and some have gone beyond using FOSS to producing it.  Even some of the more traditional, established companies are contributing to [...]]]></description>
			<content:encoded><![CDATA[<p>Free/Open Source Software (FOSS) has taken the world by storm.  Startups everywhere have built their businesses upon a foundation of FOSS products, with the LAMP (Linux-Apache-MySQL-Perl/PHP/Python) platform being the best-known among them, and some have gone beyond using FOSS to producing it.  Even some of the more traditional, established companies are contributing to existing FOSS projects and releasing their own products as FOSS.</p>
<p>Going open source can bring major benefits for your software and your company, but it can also invite disaster if you&#8217;re not familiar with both the concepts and the culture behind it.  So let&#8217;s clear up some of the common misconceptions surrounding open source:</p>
<h3>You Still Own Your Code</h3>
<p>Whatever code you write (or pay someone to write for you as a &#8220;work for hire&#8221;) belongs to you, unless other arrangements are made.  As the owner of the copyright on that code, you will never be legally bound by the terms of the code&#8217;s license, so you will still be able to use it in whatever non-open way you might desire.</p>
<p>Until you accept someone else&#8217;s patch.</p>
<p>If you release a FOSS project and I submit code for it, then I still own the copyright on my submission.  By incorporating my changes into your project, you become bound by the project&#8217;s licensing terms because you no longer own the whole thing.  The one exception to this is if I assign rights over my contribution to you above and beyond those in the FOSS license, most often through the use of a <a href='http://en.wikipedia.org/wiki/Contributor_License_Agreement'>Contributor License Agreement</a>.</p>
<h3>You <i>Can</i> Sell FOSS</h3>
<p>FOSS licenses place no restrictions on who can distribute the software covered by the license or how.  Their restrictions apply to those who make changes to it.  Depending on the license, anyone making modifications may be required to do such things as:</p>
<ul>
<li>make the source code available to anyone they distribute the software to</li>
<li>provide attribution to the original author</li>
<li>submit the changes back to the original author</li>
</ul>
<p>&nbsp;<br />
Even if you are subject to the FOSS license, you can still sell or give the software to whoever you like.  But they can also sell or give it to whoever <i>they</i> like, so the cost will tend to drop to zero rather quickly unless you can provide some additional value to encourage people to pay you for your version when they can get it free (and legally) from someone else.</p>
<p>One common way of doing this is to make use of a Contributor License Agreement, as mentioned above, which allows the original copyright holder to sell the project under a commercial license in addition to free distribution under a FOSS license.</p>
<h3>Open Source Is Sharing</h3>
<p>Open source is not a gimmick for getting programmers around the world to write a program for free which you can then turn around and sell.  Unless the programmers gain some benefit from contributing to your project, they are unlikely to do so and, worse, you may get bad press in the FOSS community for trying to take advantage of them.</p>
<p>For this reason, FOSS licensing tends to work better for software which potential developers are likely to run on their own computers, not for the custom portions of an online service or other &#8220;unique&#8221; offering that&#8217;s intended to only run in one place.</p>
<p>I recently advised someone who wanted to set up a web-based service and sell subscriptions for access, but also to make it open source so that outside developers would contribute and improve on it.  Although basing the commodity portions of such a system on existing FOSS projects works extremely well - that&#8217;s the heart of LAMP, after all - trying to present the service itself as FOSS would have gone quite poorly.</p>
<p>I explained that developers would have no reason to make free contributions to his for-pay service and, even if they did, they would need to set up their own working installations of the service to develop against, at which point they would be in a position to compete against him by offering the same service at no cost.  This was a case for which FOSS was simply not well-suited to his objectives.</p>
<p>&nbsp;<br />
Have you considered using FOSS licenses for any of your projects or do you have further questions about FOSS which have not been addressed here?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/18/open-source-or-no/feed</wfw:commentRss>
		</item>
		<item>
		<title>Looking Beyond the Obvious</title>
		<link>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious</link>
		<comments>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious#comments</comments>
		<pubDate>Mon, 16 Feb 2009 16:21:59 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

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

		<category><![CDATA[case study]]></category>

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

		<category><![CDATA[lessons learned]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[war stories]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=136</guid>
		<description><![CDATA[Near its end, the CyberPenguin case study mentions the discovery of &#8220;some small accounting inaccuracies&#8221;.  To be exact, users were occasionally being double-charged for sessions.
If you&#8217;ve done much software development, that statement alone should be enough to have you thinking &#8220;concurrency issue&#8221; or, more specifically, &#8220;race condition&#8221;.  Given that the application involved both [...]]]></description>
			<content:encoded><![CDATA[<p>Near its end, the <a href='http://nomadnetinc.com/CyberPenguin/'>CyberPenguin case study</a> mentions the discovery of &#8220;some small accounting inaccuracies&#8221;.  To be exact, users were occasionally being double-charged for sessions.</p>
<p>If you&#8217;ve done much software development, that statement alone should be enough to have you thinking &#8220;concurrency issue&#8221; or, more specifically, &#8220;race condition&#8221;.  Given that the application involved both a web-based management interface and a once-a-minute scheduled task to handle accounting, the obvious point of conflict was for the problems to result when an operator submitted an update through the web interface while the accounting task was running.</p>
<p>So off I went to ensure that such a conflict wouldn&#8217;t cause issues, then sent the revised code off to the client.  He reported back the next day that it hadn&#8217;t had any effect.</p>
<p>After looking harder at the code, I came up with a way that this conflict could conceivably have still occurred under some contrived circumstance, eliminated that possibility, and sent it off.  Still no improvement.</p>
<p>We went through maybe half a dozen rounds of this before I ran out of ways that the web application and accounting task could conflict, no matter how far I stretched the bounds of probability, and finally took a closer look at the application&#8217;s logs.  Once I started looking at them as a whole, instead of just records of single users, I quickly noticed that these mischarges came in clusters, affecting several users at once, not random individuals.  These clusters also tended to hit right on the hour.</p>
<p>Checking in with the client, it turned out that the specific times when the problems occurred matched up with the times when the per-minute rates changed.</p>
<p>To keep the accounting simple, the application deals with rate changes by closing out each active user&#8217;s session, charging it at the old rate, and then opening a new session at the new rate.  With larger numbers of users logged in, this process was taking more than a minute to complete.  The conflict wasn&#8217;t between the web interface and the scheduled accounting task, it was between two (or more&#8230;) copies of the accounting task!  This also explained why I was never able to reproduce the problem in my own development and testing environment, as I had never simulated enough concurrent users in my tests to produce the problem.</p>
<p>Once the correct culprit had been identified, it was a simple enough matter to resolve by adding a check to prevent multiple instances of the accounting task from running concurrently.</p>
<p>The moral of the story:</p>
<p>Even if the cause of an issue seems clearly obvious, don&#8217;t forget to fully examine the system to verify that you&#8217;re solving the right problem before you spend too much time solving the wrong one.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious/feed</wfw:commentRss>
		</item>
		<item>
		<title>Customize or Build to Order?</title>
		<link>http://nomadnetinc.com/blog/2009/02/13/customize-or-build-to-order</link>
		<comments>http://nomadnetinc.com/blog/2009/02/13/customize-or-build-to-order#comments</comments>
		<pubDate>Fri, 13 Feb 2009 16:58:34 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[choosing technology]]></category>

		<category><![CDATA[project management]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=128</guid>
		<description><![CDATA[You have a project that you need to have developed and you know why you&#8217;re going to hire a programmer.  Don&#8217;t forget to discuss with your developer how you want to have your project built.
It doesn&#8217;t much matter whether your project is the latest addition to the world&#8217;s surplus of data-entry systems or the [...]]]></description>
			<content:encoded><![CDATA[<p>You have a project that you need to have developed and you know <a href='http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers/'>why you&#8217;re going to hire a programmer</a>.  Don&#8217;t forget to discuss with your developer how you want to have your project built.</p>
<p>It doesn&#8217;t much matter whether your project is the latest addition to the world&#8217;s surplus of data-entry systems or the next killer application which will revolutionize our lives, it&#8217;s going to involve a lot of common functions either way.  Common functions which have already been implemented, dozens if not hundreds of times over.  How much of that can and should you make use of?</p>
<p>There are existing frameworks which handle these common functions in broadly generic ways which can generally be customized to get an application based on them up and running relatively quickly and at a low cost.  Most good frameworks also allow for plug-ins to expand on their base feature set similarly easily.</p>
<p>The other major option is to build a fully-custom application.  This route is more expensive and takes longer to complete, but it ensures that you can get any desired features without being restricted by a framework&#8217;s underlying design or the availability of plug-ins.  In the long term, it also can provide greater flexibility for your application if it is done correctly.</p>
<p>In some cases, it can be appropriate to combine both approaches, first building a framework-based prototype, then replacing it with a fully-custom final version.  Due to the additional time and expense involved, this is generally only an option for large or business-defining projects, but the improved quality of the final result can justify those costs in such cases.</p>
<h3>Characteristics of Framework-Based Development</h3>
<ul>
<li>Faster initial implementation</li>
<li>Lower cost</li>
<li>Provides a solid, well-tested foundation for basic functionality</li>
<li>Potentially more secure, due to lessons learned from attacks against other applications based on the same framework</li>
<li>Many good frameworks are available for free under Open Source licenses, but some licenses may place requirements on how you use framework-based code</li>
<li>Some frameworks include a &#8220;standard&#8221; look and feel, which is good for getting something that looks decent built quickly, but may ultimately limit design options</li>
</ul>
<h3>Characteristics of Fully-Custom Development</h3>
<ul>
<li>Can produce whatever you desire</li>
<li>Higher performance, as it will contain only what you need</li>
<li>Potentially more secure, due to not being a well-known and thoroughly-analyzed target, provided the developer pays attention to security</li>
<li>You will fully own the end result and can set your own licensing terms</li>
</ul>
<p>&nbsp;<br />
What other advantages or disadvantages of either approach are there beyond what I&#8217;ve listed?  Which do you tend to prefer?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/13/customize-or-build-to-order/feed</wfw:commentRss>
		</item>
		<item>
		<title>AJAX Gone Awry</title>
		<link>http://nomadnetinc.com/blog/2009/02/11/ajax-gone-awry</link>
		<comments>http://nomadnetinc.com/blog/2009/02/11/ajax-gone-awry#comments</comments>
		<pubDate>Wed, 11 Feb 2009 16:19:48 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Technical]]></category>

		<category><![CDATA[User Experience]]></category>

		<category><![CDATA[bad technology]]></category>

		<category><![CDATA[choosing technology]]></category>

		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=32</guid>
		<description><![CDATA[If you're developing or deploying software, then it should have a purpose.  Unless you're doing cutting-edge research, then that purpose is probably not to provide a tech demo, nor to show off how many buzzword-laden features you can pack into it...]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re developing or deploying software, then it should have a purpose.  Unless you&#8217;re doing cutting-edge research, then that purpose is probably not to provide a tech demo, nor to show off how many buzzword-laden features you can pack into it.</p>
<p>I&#8217;m often surprised at how readily people will forget this.</p>
<p>In late January, I ran across a question on <a href='http://www.linkedin.com/in/dsherohman'>LinkedIn</a> which related to a website the asker had developed which was 100% AJAX-driven.  The site itself looked nice enough, but it was a disaster technically.  Unless JavaScript was enabled, it didn&#8217;t even display its front-page content, just a (non-functional) navigation bar.</p>
<p>With JavaScript on, the content did appear, but it turned out to be nothing more than a standard six-page site which could have been done statically with plain HTML pages and regular links to navigate among them without using JavaScript at all.  The only thing lost would have been having the old page&#8217;s content fade out, then the new page fade in, when you navigate from one page to another.</p>
<p>Yes, the fade in/out is a nice effect.  Yes, it looks cool.  And, yes, AJAX is a very buzzwordy &#8220;Web 2.0&#8243; technology.  But it was used all wrong on this site.  It added nothing to the functionality or usability of the site, at the cost of making it inaccessible to a substantial segment of potential users<sup>1</sup>.  If you&#8217;re into SEO, this choice of technology also killed that by making the site essentially invisible to search engines.</p>
<p>I&#8217;m sure you&#8217;ve also seen sites which use Flash, SilverLight, or another &#8220;more interactive&#8221; technology in a way which does nothing beyond what traditional HTML can provide and makes no use of interactivity at all.  Once again, such designs limit the ability of users to access the site and its content, shut out search engines from indexing the site, and add no actual value.</p>
<p>This is not to say that AJAX or Flash or SilverLight or whatever are intrinsically evil, or even suspect, but rather that you need to know what you&#8217;re trying to accomplish with your site or software and then choose appropriate technology - and an appropriate <i>use</i> of that technology - to support that goal.  Just using technology for its own sake or because it&#8217;s the hottest thing at the moment will, in 99% of cases, do nothing to support the software&#8217;s purpose and is likely to detract from it.</p>
<p>What&#8217;s the most useless (mis-)use of technology you&#8217;ve seen lately?</p>
<p>&nbsp;</p>
<hr width=75%>
<sup>1</sup>  <a href='http://www.w3schools.com/browsers/browsers_stats.asp'>w3schools.com</a> estimates that 5% of users currently have JavaScript disabled, but most reports I&#8217;ve found from web server admins who have checked on it report 13-20% or more of their users have it off.  Even if it is only 5%, though, do you really want to shut out one of every twenty potential visitors to your site?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/11/ajax-gone-awry/feed</wfw:commentRss>
		</item>
		<item>
		<title>Why Do You Hire Programmers?</title>
		<link>http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers</link>
		<comments>http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers#comments</comments>
		<pubDate>Mon, 09 Feb 2009 18:46:13 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[project management]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=84</guid>
		<description><![CDATA[Why do you hire programmers? Seriously, why? Think about it for a minute.
If your answer is &#8220;to write code&#8221;, then think about it some more. I don&#8217;t know what your reason is, but I&#8217;m pretty sure that&#8217;s not it.  Writing code is merely a means to an end, not an end in itself.
Do you [...]]]></description>
			<content:encoded><![CDATA[<p>Why do you hire programmers? Seriously, why? Think about it for a minute.</p>
<p>If your answer is &#8220;to write code&#8221;, then think about it some more. I don&#8217;t know what your reason is, but I&#8217;m pretty sure that&#8217;s not it.  Writing code is merely a means to an end, not an end in itself.</p>
<p>Do you want to create internal systems that keep your company running? Or are you looking to produce a product for sale to customers? Maybe you&#8217;re doing something else entirely?</p>
<p>I&#8217;ve seen this question presented from the marketing side a few times, usually in terms of &#8220;features&#8221; vs. &#8220;benefits&#8221;<sup>1</sup>, but the same principle applies here.  Just as you need to present a benefit to your customers when selling to them, you also need to consider the benefit that you want to obtain when you&#8217;re buying.</p>
<p>Probably the most common issues I see in this area are companies looking for a programmer who knows a specific language, or uses a specific database, or has experience with some other particular tool rather than focusing on the actual objective of the project: the functionality that they require.</p>
<p>This is not to say that you should never look for someone who can use specific tools.  If you&#8217;re adding on to an existing Java application or if you have an existing team of Java developers that you mean to add to, then you&#8217;re probably going to want someone who can work with Java, and for good reason.</p>
<p>If you&#8217;re building something new, though, then you&#8217;re likely to be better served by finding someone with broad experience and the ability to create what you&#8217;re looking for, then asking him what the most appropriate tools would be.  Since you&#8217;re hiring an expert, use his expertise.  Any genuine expert should be able to clearly explain the advantages and disadvantages of different options to you in terms you can understand, no matter how technical or non-technical those terms may be.</p>
<p>Just don&#8217;t be surprised if the best option ends up not being the one that you would have chosen if you had started by picking the tool.</p>
<p>What have you hired programmers for in the past and what would you want to hire one for today?</p>
<p>&nbsp;</p>
<hr width=75%>
<p><sup>1</sup> Basically, the concept is that you don&#8217;t want to sell the feature &#8220;our product has X&#8221;, but instead you should sell the benefit that &#8220;our product allows you to do Y&#8221;.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/09/why-do-you-hire-programmers/feed</wfw:commentRss>
		</item>
		<item>
		<title>Case Study: CyberPenguin</title>
		<link>http://nomadnetinc.com/blog/2009/02/06/case-study-cyberpenguin</link>
		<comments>http://nomadnetinc.com/blog/2009/02/06/case-study-cyberpenguin#comments</comments>
		<pubDate>Fri, 06 Feb 2009 16:25:15 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[case study]]></category>

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

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

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=163</guid>
		<description><![CDATA[In late 2007, I ran across a guy who was preparing to open a Linux-based internet cafe named &#8220;CyberPenguin&#8221; in the Philippines.  After discussing his needs, he asked me to write a custom billing and workstation management system for the cafe&#8217;s use.  In 2008, he came to me again to request some additional [...]]]></description>
			<content:encoded><![CDATA[<p>In late 2007, I ran across a guy who was preparing to open a Linux-based internet cafe named &#8220;<span class=companyName>CyberPenguin</span>&#8221; in the Philippines.  After discussing his needs, he asked me to write a custom billing and workstation management system for the cafe&#8217;s use.  In 2008, he came to me again to request some additional features, which I was quite happy to help him with.  With that expansion complete, he has prepared a case study on the project, which is now available in both <a href='/CyberPenguin/'>online (HTML)</a> and <a href='/CyberPenguin.pdf'>printable (PDF)</a> versions.</p>
<p>Looking back over it, I have to say that I really enjoyed this project.  Not only was <span class=companyName>CyberPenguin</span>&#8217;s owner great to work with and provided some of the best specs I&#8217;ve seen from any of my clients, but he was also always willing to discuss their content and to consider any suggestions I had for improving on his design.</p>
<h3>Features</h3>
<p>The case study itself provides fairly complete lists of the original functionality and what was added in the expansion project.  The only thing that stands out as missing was the one part that I was least sure of being able to work in smoothly:  Promotions.</p>
<p>The original spec called for an extremely flexible promotions structure, allowing operators to define various combinations of times of day, days of the week/month, minimum purchase amounts, etc. under which a user receives either a flat bonus amount or a percentage bonus to purchases of credit on his account.</p>
<p>Previous experience with calendars and scheduling software gave me a pretty good idea of how to handle the infrastructure behind the promotions functionality, and even to make it more flexible, allowing the criteria for promotion eligibility to be mixed and matched in any way desired rather than only the specified combinations.  But I expected designing an interface to control this flexibility without overwhelming the user to be a somewhat more daunting task.</p>
<p>In the end, I was able to come up with a clear, simple way for users to specify a promotion to be, say, &#8220;Top up account by P10.00 and get 15% extra from midnight until 6:00 every 4th Monday, Wednesday, Friday.&#8221;  And, yes, the interface is also able to describe the promotion details in English - that sentence was copied and pasted directly from it.</p>
<h3>Technology</h3>
<p><span class=companyName>CyberPenguin</span> runs on Ubuntu, which is derived from Debian GNU/Linux - my preferred operating system - so I was already very familiar with the server environment that I&#8217;d be working with.  The workstations also run Ubuntu, under the control of DRBL (&#8221;Diskless Remote Boot in Linux&#8221;), which was new to me, but I was already familiar with other Linux-based thin client and diskless workstation setups, so it didn&#8217;t present any issues.</p>
<p>In addition to the Linux operating system, the rest of the application was built on Apache 2, MySQL 5, and Perl 5.8, making up a standard LAMP (Linux/Apache/MySQL/Perl) environment.  In addition to LAMP for the web interface, the application makes use of Perl programs run as scheduled tasks (by cron) each minute and each day to handle the billing and accounting details.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/06/case-study-cyberpenguin/feed</wfw:commentRss>
		</item>
		<item>
		<title>Why Save Partial Data?</title>
		<link>http://nomadnetinc.com/blog/2009/02/02/why-save-partial-data</link>
		<comments>http://nomadnetinc.com/blog/2009/02/02/why-save-partial-data#comments</comments>
		<pubDate>Mon, 02 Feb 2009 16:08:23 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Technical]]></category>

		<category><![CDATA[User Experience]]></category>

		<category><![CDATA[data collection]]></category>

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

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=43</guid>
		<description><![CDATA[In Minimize Data Requirements, I talked a bit about allowing users to save incomplete data because there&#8217;s no reason to insist that all data must be provided before any of it is accepted.
While that may be a good negative reason (&#8221;there&#8217;s no reason not to&#8221;), there are also positive reasons for allowing this:
It makes your [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://nomadnetinc.com/blog/2009/01/27/minimize-required-data/">Minimize Data Requirements</a>, I talked a bit about allowing users to save incomplete data because there&#8217;s no reason to insist that <i>all</i> data must be provided before <i>any</i> of it is accepted.</p>
<p>While that may be a good negative reason (&#8221;there&#8217;s no reason not to&#8221;), there are also positive reasons for allowing this:</p>
<h3>It makes your users&#8217; lives easier.</h3>
<p>Are you perfectly organized at all times?  I know I&#8217;m not.</p>
<p>Requiring that saved data must be complete and valid (or at least valid-looking) at all times demands perfect organization from your users.  It makes them collect all of the information you want up front and have it all available at the same time when they enter it.  Removing that requirement means that they can enter as much as they know right now, then find the rest and come back later to finish.</p>
<h3>It provides a record of user actions which were started, but not completed.</h3>
<p>Suppose you have an online store for which users go through a series of three pages in the course of placing an order.  Do you persistently store the partial data at each stage of the process or do you just keep it in the active session and write it all to the database at once when the final form is complete?</p>
<p>If you&#8217;re smart, you&#8217;ll make a permanent record of it at each stage.  This information about what items a user started the purchase process for, but didn&#8217;t actually buy, can provide valuable insight into buying habits.  If you&#8217;re using a recommendation engine (&#8221;people who bought X also liked Y&#8221;), then information about what users <i>almost</i> bought is almost as valuable as information about what they <i>actually</i> bought.</p>
<p>More importantly, though, this incomplete transaction data can highlight issues with your site&#8217;s effectiveness.  If 90% of your users are starting a transaction, but abandoning it after the second step, then perhaps you should take a hard look at the third step (and, while you&#8217;re at it, make sure that the server is completing step two in a timely fashion) to determine why they&#8217;re not continuing at that point.</p>
<h3>Incomplete or invalid data can show what mistakes your users are making.</h3>
<p>Users will make mistakes and they will submit invalid data.  That&#8217;s as inevitable as death and taxes.</p>
<p>Most software ignores invalid submissions, beyond throwing it back at the user along with an error message.</p>
<p>If yours saves it anyhow, though, then these invalid submissions give you a window into your users&#8217; experience that will show you what mistakes they&#8217;re making.  Once you know what mistakes are being made, you can attempt to determine the cause of the mistakes and make it easier for the users to get it right the first time instead of just scolding them for doing it wrong.</p>
<p>Like the data I&#8217;ve been talking about, I&#8217;m sure that this post is also incomplete.  What other benefits or drawbacks are there to saving partial or incorrect data instead of rejecting it?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/02/why-save-partial-data/feed</wfw:commentRss>
		</item>
		<item>
		<title>The Temptation of the Untried</title>
		<link>http://nomadnetinc.com/blog/2009/01/30/the-temptation-of-the-untried</link>
		<comments>http://nomadnetinc.com/blog/2009/01/30/the-temptation-of-the-untried#comments</comments>
		<pubDate>Fri, 30 Jan 2009 15:41:10 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[bad technology]]></category>

		<category><![CDATA[choosing technology]]></category>

		<category><![CDATA[lessons learned]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=27</guid>
		<description><![CDATA[The technology industry, by and large, is inhabited by early adopters.  It&#8217;s how most of us got here, after all.  You learn to work with &#8220;high-tech&#8221; equipment by doing it and you do it because you want to play with the latest shiny new toys.
But the latest, of course, is also the least [...]]]></description>
			<content:encoded><![CDATA[<p>The technology industry, by and large, is inhabited by early adopters.  It&#8217;s how most of us got here, after all.  You learn to work with &#8220;high-tech&#8221; equipment by doing it and you do it because you want to play with the latest shiny new toys.</p>
<p>But the latest, of course, is also the least stable.  The most likely to have problems.  The biggest risk.</p>
<p>Staying on top of the latest-and-greatest tech works out well on your own time, at least for those of us who like to tinker and don&#8217;t mind doing a bit of troubleshooting when the inevitable problems arise.  As a professional, though, that&#8217;s rarely what&#8217;s best for clients.</p>
<p>On the other hand, stagnation isn&#8217;t good for anyone.  Newer technology is needed to take advantage of the improved tools and techniques which are constantly being developed.  Fifty-year-old mainframes running code in languages just as old are not a strong target for new development today, no matter how stable they may be.</p>
<p>This creates a constant tension between the desire to make use of the new and the need to retain the reliability of the not-so-new.  It&#8217;s a tricky balance to get right and I see a lot of software developers who give in to the lure of the latest version, only to get burned when it crashes.</p>
<p>I even succumbed recently myself&#8230;</p>
<p>About two months ago, I was debating with myself whether to clean up the web application framework that has grown up out of several projects I&#8217;ve done and continue using it or to switch over to an existing framework.  (I had previously looked at the major existing frameworks and found them wanting, but I make a habit of checking in on them once or twice a year to see if either they or I have changed enough that I&#8217;d want to use them.)  As it turned out, I found that there was a new framework in town, created by a well-known developer with experience in such things, which avoided many of the pitfalls of the existing frameworks, so I decided to pitch in and help out with development and debugging.</p>
<p>It turned out to be much less complete than I had initially believed and, a month later - practically to the day - it pretty much disappeared.</p>
<p>During the time I was initially evaluating it, I had also been discussing a project with a potential new client and had mentioned it to her.  She also thought it sounded great and was very interested in having me base her project on this new framework.  Fortunately for me, the project ultimately didn&#8217;t happen, because, if I had committed myself to build it based on this shiny new framework, I would not have been able to do so without having to invest far more work than expected into completing the framework first.</p>
<p>How do you prefer to maintain a balance between the latest-and-greatest and the tried-and-true?  Have you ever been bitten by this preference?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/01/30/the-temptation-of-the-untried/feed</wfw:commentRss>
		</item>
		<item>
		<title>Minimize Required Data</title>
		<link>http://nomadnetinc.com/blog/2009/01/27/minimize-required-data</link>
		<comments>http://nomadnetinc.com/blog/2009/01/27/minimize-required-data#comments</comments>
		<pubDate>Tue, 27 Jan 2009 20:48:40 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Technical]]></category>

		<category><![CDATA[User Experience]]></category>

		<category><![CDATA[data collection]]></category>

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

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=33</guid>
		<description><![CDATA[There&#8217;s a long-standing tendency for software to enforce completeness and consistency in stored data.  It has never truly been necessary in the real world and it has become something of a monster with the rise of the internet as websites seem to be constantly outdoing each other to collect every conceivable piece of information [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a long-standing tendency for software to enforce completeness and consistency in stored data.  It has never truly been necessary in the real world and it has become something of a monster with the rise of the internet as websites seem to be constantly outdoing each other to collect every conceivable piece of information about anything of interest (usually, but not always, their users) and make every item &#8220;required&#8221;, refusing to accept <i>any</i> data until <i>all</i> data is provided.</p>
<p>This is the wrong approach.  As application designers and developers, we should be minimizing the effort we require from our users, not adding to it.</p>
<p>I recently encountered a blog post on <a href="http://www.kotsego.com/blog/2009/01/21/rethinking-the-comment-form/">Rethinking the Comment Form</a> which, among other things, suggested that there&#8217;s no reason for a blog comment form to require - or even request, really - an email address unless the user requests to be notified of additional comments.  This is a step in the right direction and provides my first principle for minimizing requirements:</p>
<h3>If you will never use the information, don&#8217;t request it.</h3>
<p>In most cases, that can be expanded slightly to &#8220;if you will never use the information <i>for the user&#8217;s benefit</i>&#8220;.  If your only use for the information is to sell it to spammers or &#8220;marketing partners&#8221;, that doesn&#8217;t count.</p>
<p>The second principle expands slightly on the first:</p>
<h3>If you won&#8217;t use the information immediately, don&#8217;t require it.</h3>
<p>The first was pretty conventional, at least if you&#8217;re not talking to marketers.  The second is a bit bigger of a step.  It means that, if you&#8217;re not going to be sending someone postal mail today, then it&#8217;s perfectly OK for them to enter an address with no ZIP code.  Or a phone number with no area code.</p>
<p>Yes, yes, I know&#8230;  &#8220;What about data integrity?!?&#8221;</p>
<p>Which is a good question.  What about data integrity?  If you&#8217;re not going to use the information yet, then why does it matter?  Sure, you definitely do need to get that ZIP code before sending them a letter, but, until you have a letter to send?  So what if you don&#8217;t have it?</p>
<p>This then leads to:</p>
<h3>Even if you do need the information, accept its omission.</h3>
<p>Let the user leave it blank.  Really.  You can remind them each time they log in about important information that needs to be completed, but there is no excuse for refusing to let users enter partial information now and then come back and finish it up later.</p>
<p>The only potential exceptions are a username and either a password or an email address (so you can send them a password).  This is sufficient to allow them to return and provide whatever other information may be needed at a later time.</p>
<p>Of course, if you use the email address as their username, then that leaves exactly one piece of required information.  You can&#8217;t get much more minimal than that.</p>
<p>Do you have any other suggestions for good ways to minimize the load on your users of providing information?</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/01/27/minimize-required-data/feed</wfw:commentRss>
		</item>
		<item>
		<title>What I Do</title>
		<link>http://nomadnetinc.com/blog/2009/01/26/what-i-do</link>
		<comments>http://nomadnetinc.com/blog/2009/01/26/what-i-do#comments</comments>
		<pubDate>Mon, 26 Jan 2009 20:27:36 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

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

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=12</guid>
		<description><![CDATA[I always seem to have a difficult time explaining to people the sort of work that I do.  I write software, but focus on behind-the-scenes functionality, not the up-front interface that everyone sees.  No matter how carefully I try to explain this, it always ends up with me describing a website that I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>I always seem to have a difficult time explaining to people the sort of work that I do.  I write software, but focus on behind-the-scenes functionality, not the up-front interface that everyone sees.  No matter how carefully I try to explain this, it always ends up with me describing a website that I&#8217;ve worked on and then the person I&#8217;m talking to will, more often than not, seem to conclude that I&#8217;m a web designer.</p>
<p>There was a recent post on <a href="http://freelanceswitch.com/">Freelance Switch</a> titled <a href="http://freelanceswitch.com/finding/questions-answers-how-to-describe-what-you-do/"><i>Questions &#038; Answers: How to Describe What You Do</i></a> on this general topic, so apparently it&#8217;s a problem which is shared by others with closer-to-mainstream specialties.  Here are my answers to that article&#8217;s questions:</p>
<h3>1. What kind of work do you do?</h3>
<p>I write software to help clients manage information, technology, and/or business processes.  Given the current state of the business world, this very frequently means writing web-based applications, but this does not mean I am a web developer.  I primarily create software which sometimes happens to have a web interface, not websites which happen to have functionality behind them.</p>
<p>It can be a subtle (and, arguably, pedantic) distinction, but it means that I am equally comfortable setting up websites or creating software which just sits in the background, doing its thing (e.g., monitoring access logs or auditing user activity) with no human direction required and no user interface at all aside from writing to a log or sending out email notifications to tell you when it finds something amiss.</p>
<p>This distinction also means that web layout and graphic design are not really my specialty.  If you&#8217;re building a website and know what you want it to do and what you want it to look like, I can make that happen, but, if you ask me to decide what it should look like, you&#8217;re likely to get something that looks fairly spartan (some might even say &#8220;boring&#8221;).</p>
<h3>2. What makes you unique?</h3>
<p>For starters, my preference to specialize in back-end processing rather than user interface design seems rather unique.</p>
<p>I&#8217;ve been developing software a long time - as I write this, I&#8217;ve been programming for 30 years total, 15 years professionally - and I have a breadth and depth of experience that few can match.  I&#8217;ve worked in several different industries over the course of my career and learned not only how to write software, but also how to assess a situation and identify <i>what</i> software should be written.  On top of that, I&#8217;ve worked some years in systems and network administration, giving a solid understanding of the environments in which software runs and how to ensure that it will do so reliably.</p>
<p>I also write software with a distinct eye towards future maintainability and expandability.  I know that someone will have to fix or change it within the next year or two and I know that, more often than not, that someone will be me.  This isn&#8217;t anything unique within the realm of traditional software development projects, but it is often sorely lacking in the &#8220;results now, don&#8217;t worry about tomorrow&#8221; world of far too many online projects.</p>
<h3>3. What kind of clients do you have?</h3>
<p>Mostly small-to-medium businesses.  Organizations which are big enough to afford custom software development, but not large enough to have the available technical manpower to do such projects in-house.</p>
<p>I also do quite a bit of work with web designers who need an expert partner to help them out with projects that require heavier or more in-depth back-end development.</p>
<h3>4. How much do you charge?</h3>
<p>I normally prefer to bill hourly for my time, but I am willing to do fixed-bid projects if provided with a sufficiently-detailed specification of the project.  Even with a good spec, though, I have found that hourly rates help to avoid potential conflicts over what work is or isn&#8217;t within the project scope.</p>
<p>Reduced rates are available for projects which are to be released under a Free/Open Source license or for which I will retain ownership of intellectual property rights after project completion.</p>
<h3>5. What kind of business relationship will we have?</h3>
<p>I primarily work independently and off-site, but will consider other arrangements provided that travel and other expenses are covered, including payment of my normal hourly rate for time spent in transit.</p>
<p>To avoid confusion caused by conflicting information, you will be expected to designate a single point of contact who will provide all direction on your project.</p>
<h3>6. How do I pay you?</h3>
<p>I am currently billing clients through <a href="http://aurenav.com/">Aurenav, LLC</a>, as this allows me to focus on my clients&#8217; projects without being distracted by invoicing, collections, or payroll issues.  We will agree to a schedule for billing as part of the initial project contract and Aurenav will issue invoices according to that schedule.  Payment on each invoice will be due within 30 days after it is issued.</p>
<h3>7. How long have you been in business?</h3>
<p>NomadNet, Inc. was founded in October, 2004.</p>
<h3>8. Where are you located, and what are your hours?</h3>
<p>I am a U.S. citizen currently resident in Lund, Sweden, but I typically work remotely, so you won&#8217;t have to worry about the expenses involved in getting me from Sweden to your site!  On the contrary, the substantial majority of my clients have never met me in person, but instead have dealt with me entirely via <a href="/contact.html">email, phone, and/or Skype</a>.</p>
<p>I am a bit of a night owl, but, thanks to the magic of time zones, this puts my most common working hours roughly in sync with standard business hours in the U.S.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/01/26/what-i-do/feed</wfw:commentRss>
		</item>
		<item>
		<title>Welcome to the NomadNet Blog</title>
		<link>http://nomadnetinc.com/blog/2009/01/26/welcome-to-the-nomadnet-blog</link>
		<comments>http://nomadnetinc.com/blog/2009/01/26/welcome-to-the-nomadnet-blog#comments</comments>
		<pubDate>Mon, 26 Jan 2009 17:22:03 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

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

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

		<category><![CDATA[NomadNet::Blog]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=7</guid>
		<description><![CDATA[There are a lot of blogs out there and many people are saying that they&#8217;re the top new way for a business to communicate with its customers (and potential customers), or at least a way to maintain a nice flow of content to keep yourself in the search engines&#8217; eyes, so here&#8217;s another one going [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of blogs out there and many people are saying that they&#8217;re the top new way for a business to communicate with its customers (and potential customers), or at least a way to maintain a nice flow of content to keep yourself in the search engines&#8217; eyes, so here&#8217;s another one going into the mix.</p>
<p>I&#8217;ve seen some very good, very successful company blogs out there which have led me to the decision to start this one.  The blogs I have in mind are those which visibly contribute to the success of the (small) business which runs them.  These businesses have the common factor that the blog itself can serve to showcase the owner&#8217;s skills in that business - writers, business coaches, self-help gurus&#8230;</p>
<p>But I don&#8217;t do any of that.  I write software.  Writing software on the blog or blogging about how to write software would be a great way to contribute to the software development community, but it would have no relevance to anyone who might require my services.  Conversely, a blog that was all about marketing would produce very little actual value, not to mention that it would be largely inauthentic of me to do so.</p>
<p>To resolve this, I&#8217;ve settled on creating a two-pronged blog.  (All the pro bloggers who write about focusing on a single topic and never straying from one well-defined niche may now collectively gasp in dismay.)  All posts will be categorized as either &#8220;Technical&#8221; or &#8220;Non-Technical&#8221;.
<ul>
<li>&#8220;Technical&#8221; posts will be those which directly relate to the actual process of crafting software.  The first few in this category will be design- and usability-focused, but coding techniques and the like will appear there, too.</li>
<li>&#8220;Non-Technical&#8221; posts will cover anything else.
</ul>
<p>Feel free to subscribe to only one category&#8217;s RSS feed if the other doesn&#8217;t interest you.  It won&#8217;t bother me in the least.  Honest.</p>
<p>That still doesn&#8217;t address the issue of showcasing my skills on the blog, though.</p>
<p>I&#8217;ve decided that the way to accomplish that is to make <i>the blog itself</i> a demonstration of my skills by writing my own blog software, to be known (somewhat unimaginatively) as NomadNet::Blog.  It&#8217;s not going quickly, as I don&#8217;t have that much free working time to do it in, so I&#8217;ve decided to start out with using WordPress rather than waiting until NN::Blog is ready to face the world.  Going this route will also pretty much force me to write an import tool which will convert a WordPress blog&#8217;s data into something usable by NN::Blog; I expect that having this capability will greatly increase the odds of anyone other than me using it.</p>
<p>So that&#8217;s where we&#8217;re starting from.  Stick around and I hope you enjoy your stay.<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
<i>P.S.  Getting this blog to match the look of the rest of my site involved a bit of ad hoc tweaking to WordPress beyond simply editing the base Sandbox theme.  If you happen to notice any dark corners of the blog which don&#8217;t look quite right, please contact me and let me know so that I can get them cleaned up.</i></p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/01/26/welcome-to-the-nomadnet-blog/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
