<?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 &#187; Technical</title>
	<atom:link href="http://nomadnetinc.com/blog/category/technical/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>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>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>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>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 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>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>
	</channel>
</rss>
