<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
   <channel>
      <atom:link href="http://feeds.feedburner.com/codinghorror/" rel="self" type="application/rss+xml" />
      <title>Coding Horror</title>
      <link>http://www.codinghorror.com/blog/</link>
      <description>programming and human factors - Jeff Atwood</description>
      <language>en-us</language>
      <lastBuildDate>Tue, 07 Jul 2009 23:59:59 -0800</lastBuildDate>
      <pubDate>Tue, 07 Jul 2009 23:59:59 -0800</pubDate>
      <generator>http://www.movabletype.org/?v=4.25</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <image>
      <title>Coding Horror</title>
      <url>http://www.codinghorror.com/blog/images/coding-horror-official-logo-small.png</url>
      <width>100</width>
      <height>91</height>
      <description>Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.</description>
      <link>http://www.codinghorror.com/blog/</link>
      </image>

      <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
         <title>Testing With "The Force"</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001285.html</link>
         <description><![CDATA[<p>
Markdown was one of the <a href="http://www.codinghorror.com/blog/archives/001116.html">humane markup languages</a> that we evaluated and adopted for Stack Overflow. I've been pretty happy with it, overall. So much so that I wanted to implement a tiny, lightweight subset of Markdown for comments as well.
<p>
I settled on these three commonly used elements:
<p>
<pre>
*italic* or _italic_
**bold** or __bold__
`code`
</pre>
<p>
I <a href="http://www.codinghorror.com/blog/archives/001016.html">loves me some regular expressions</a> and this is exactly the stuff regex was born to do! It doesn't <i>look</i> very tough. So I dusted off <a href="http://www.regexbuddy.com/cgi-bin/affref.pl?aff=jatwood">my copy of RegexBuddy</a> and began.
<p>
I typed some test data in the test window, and whipped up a little regex in no time at all. This isn't my first time at the disco.
<p>
<a href="http://www.regexbuddy.com/cgi-bin/affref.pl?aff=jatwood"><img alt="regexbuddy-naive-regex.png" src="http://www.codinghorror.com/blog/images/regexbuddy-naive-regex.png" width="478" height="339" border="0" /></a>
<p>
Bam! Yes! Done and <i>done!</i> By gum, <a href="http://code.google.com/events/io/sessions/MythGeniusProgrammer.html">I must be a genius programmer!</a>
<p>
Despite my obvious genius, I began to have some small, nagging doubts. Is the test phrase...
<pre>
I would like this to be *italic* please.
</pre>
<p>
... <i>really</i> enough testing? 
<p>
Sure it is! I can feel in my bones that this thing freakin' works! It's almost like I'm being pulled toward shipping this code by some inexorable, dark, testing ... force. It's so <i>seductively easy!</i>
<p>
<img alt="come-to-the-dark-side-vader.jpg" src="http://www.codinghorror.com/blog/images/come-to-the-dark-side-vader.jpg" width="327" height="331"  />
<p>
But wait. <b>I have this whole database of real world comments</b> that people have entered on Stack Overflow. shouldn't I perhaps try my awesome regular expression on that corpus of data to see what happens? Oh, fine. If we must. Just to humor you, nagging doubt. Let's run a query and see.
<p>
<pre>
select Text from PostComments
where dbo.RegexIsMatch(Text, '\*(.*?)\*') = 1
</pre>
<p>
Which produced this list of matches, among others:
<p>
<blockquote>
Interesting fact about math: x <font color="red">* 7 == x + (x *</font> 2) + (x * 4), or x + x &gt;&gt; 1 + x &gt;&gt; 2.  Integer addition is usually pretty cheap.
<p>
Thanks.  What I needed was to turn on Singleline mode too, and use .<font color="red">*? instead of .*</font>.
<p>
yeah, see my edit - change select <font color="red">* to select RESULT.*</font>  one row - are sure you have more than one row item with the same InstanceGUID?
<p>
Not your main problem, but you are mix and matching wchar_t and TCHAR.  mbstowcs() converts from char <font color="red">* to wchar_t *</font>.  
<p>
aawwwww.... Brainf<font color="red">**</font>k is not valid. :/
</blockquote>
<p>
Thank goodness I listened to my midichlorians and let <b>the light side of the testing force</b> prevail here!
<p>
<img alt="come-to-the-light-side-skywalker.jpg" src="http://www.codinghorror.com/blog/images/come-to-the-light-side-skywalker.jpg" width="325" height="325"  /></form>
<p>
So how do we fix this regex? We use the light side of the force -- brute force, that is, against a ton of test cases! My job here is relatively easy because I have over 20,000 test cases sitting in a database. You may not have that luxury. Maybe you'll need to go out and find a bunch of test data on the internet somewhere. Or write a function that generates random strings to feed to the routine, also known as <a href="http://en.wikipedia.org/wiki/Fuzz_testing">fuzz testing</a>.
<p>
I wanted to leave the rest of this regular expression as an exercise for the reader, as I'm a sick guy who finds that sort of thing entertaining. If you don't -- well, what the heck is wrong with <i>you</i>, man? But I digress. I've been criticized for not providing, you know, "the answer" in my blog posts. Let's walk through some improvements to our italic regex pattern. 
<p>
First, let's make sure we have <b>at least one non-whitespace character inside the asterisks</b>. And more than one character in total so we don't match the ** case. We'll use <a href="http://www.regular-expressions.info/lookaround.html">positive lookahead and lookbehind</a> to do that.
<p>
<pre>
\*<font color="red">(?=\S)</font>(.+?)<font color="red">(?&lt;=\S)</font>\*
</pre>
<p>
That helps a lot, but we can test against our data to discover some other problems. We get into trouble when there are unexpected characters in front of or behind the asterisks, like, say, <code>p*q*r</code>. So let's specify that <b>we only want certain characters outside the asterisks</b>.
<p>
<pre>
<font color="red">(?&lt;=[\s^,(])</font>\*(?=\S)(.+?)(?&lt;=\S)\*<font color="red">(?=[\s$,.?!])</font>
</pre>
<p>
Run this third version against the data corpus, and wow, that's starting to look pretty darn good! There are undoubtedly some edge conditions, particularly since we're unlucky enough to be talking about code in a lot of our comments, which has wacky asterisk use.
<p>
This regex doesn't have to be (and probably <i>cannot</i> be, given the huge possible number of human inputs) perfect, but running it against a large set of input test data gives me reasonable confidence that I'm not totally screwing up.
<p>
So by all means, test your code with the force -- brute force! It's good stuff! Just <b>be careful not to get sloppy, and let the dark side of the testing force prevail</b>. If you think one or two simple test cases covers it, that's taking the easy (and most likely, buggy and incorrect) way out.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001285.html</guid>
         <pubDate>Tue, 07 Jul 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Code: It's Trivial</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001284.html</link>
         <description><![CDATA[<p>
Remember that Stack Overflow thing we've been working on? Some commenters on a recent <a href="http://news.ycombinator.com/item?id=678398">Hacker News article</a> questioned the pricing of <a href="http://stackexchange.com">Stack Exchange</a> -- essentially, a hosted Stack Overflow:
<p>
<blockquote>
Seems really pricey for a relatively simple software like this. Someone write an open source alternative? it looks like something that can be thrown together in a weekend.
</blockquote>
<p>
Ah, yes, the stereotypical programmer response to most projects: <b>it's trivial!</b> I could write that in a week!* 
<p>
It's even easier than that. Open source alternatives to Stack Overflow <a href="http://meta.stackoverflow.com/questions/2267/so-clones">already exist</a>, so you've got a head start. <b>Gentlemen, start your compilers! Er, I mean, <i>interpreters!</i></b>
<p>
No, I don't take this claim seriously. Not enough to write a response. And fortunately for me, now I don't need to, because <a href="http://blog.bitquabit.com/">Benjamin Pollack</a> -- one of the few people outside our core team who has access to the Stack Overflow source code -- already <a href="http://blog.bitquabit.com/2009/07/01/one-which-i-call-out-hacker-news/">wrote a response</a>. Even if I had written a response, I doubt it would have been half as well written as Benjamin's.
<p>
<blockquote>
Developers think cloning a site like StackOverflow is easy for the same reason that open-source software remains such a horrible pain in the ass to use. <b>When you put a developer in front of StackOverflow, they don't really see StackOverflow</b>. What they actually see is this:
<p>
<pre>
create table QUESTION (ID identity primary key,
                       TITLE varchar(255),
                       BODY text,
                       UPVOTES integer not null default 0,
                       DOWNVOTES integer not null default 0,
                       USER integer references USER(ID));
create table RESPONSE (ID identity primary key,
                       BODY text,
                       UPVOTES integer not null default 0,
                       DOWNVOTES integer not null default 0,
                       QUESTION integer references QUESTION(ID))
</pre>
<p>
If you then tell a developer to replicate StackOverflow, what goes into his head are the above two SQL tables and enough HTML to display them without formatting, and that really <i>is</i> completely doable in a weekend. The smarter ones will realize that they need to implement login and logout, and comments, and that the votes need to be tied to a user, but that's still totally doable in a weekend; it's just a couple more tables in a SQL back-end, and the HTML to show their contents. Use a framework like Django, and you even get basic users and comments for free.
<p>
But that's <i>not</i> what StackOverflow is about. Regardless of what your feelings may be on StackOverflow in general, most visitors seem to agree that the user experience is smooth, from start to finish. They feel that they're interacting with a polished product. Even if I didn't know better, I would guess that very little of what actually makes StackOverflow a continuing success has to do with the database schema--and having had a chance to read through StackOverflow's source code, I know how little really does. There is a <i>tremendous</i> amount of spit and polish that goes into making a major website highly usable. A developer, asked how hard something will be to clone, simply <i>does not think about the polish, because the polish is incidental to the implementation</i>.
</blockquote>
<p>
I have zero doubt that <b>given enough time, open source clones will begin to approximate what we've created with Stack Overflow</b>. It's as inevitable as evolution itself. Well, depending on what time scale you're willing to look at. With a smart, motivated team of closed-source dinosaurs, it is indeed possible to outrun those teeny tiny open-source mammals. For now, anyway. Let's say we're those speedy, clever <a href="http://en.wikipedia.org/wiki/Velociraptor">Velociraptor</a> types of dinosaurs -- those are cool, right?
<p>
Despite Benjamin's well reasoned protests, the source code to Stack Overflow is, in fact, actually, kind of ... well, trivial. Although there is starting to be quite a lot of it, as we've been beating on this stuff for almost a year now. That doesn't mean our source code is  good, by any means; as usual, <a href="http://www.codinghorror.com/blog/archives/000099.html">we make crappy software, with bugs</a>. But every day, our tiny little three person team of speedy-but-doomed Velociraptors starts out with the same goal. Not to write the best Stack Overflow <i>code</i> possible, but to <b>create the best Stack Overflow <i>experience</i> possible.</b> That's our mission: make Stack Overflow better, in some small way, than it was the day before. We don't always succeed, but <b>we try very, very hard not to suck</b> -- and more importantly, <a href="http://www.codinghorror.com/blog/archives/001207.html">we keep plugging away at it, day after day</a>.
<p>
Building a better Stack Overflow experience does involve writing code and building cool features. But more often, it's anything but:
<p>
<ol>
<li>synthesizing cleaner, saner HTML markup
<li>optimizing our pages for speed and load time efficiency
<li>simplifying or improving our site layout, CSS, and graphics
<li>responding to support and feedback emails
<li>writing a <a href="http://blog.stackoverflow.com/">blog post</a> explaining some aspect of the site engine or philosophy
<li>being customers of our own sites, asking our own <a href="http://stackoverflow.com">programming questions</a> and <a href="http://serverfault.com">sysadmin questions</a>
<li>interacting with the community on our <a href="http://meta.stackoverflow.com/">dedicated meta-discussion site</a> to help gauge what we should be working on, and where the rough edges are that need polishing
<li><a href="http://blog.stackoverflow.com/2009/05/welcome-new-community-moderators/">electing community moderators</a> and <a href="http://blog.stackoverflow.com/2009/05/a-theory-of-moderation/">building moderation tools</a> so the community can police and regulate itself as it scales
<li>producing <a href="http://blog.stackoverflow.com/category/cc-wiki-dump/">Creative Commons dumps</a> of our user-contributed questions and answers
<li>coming up with schemes for <a href="http://www.codinghorror.com/blog/archives/000893.html">responsible advertising</a> so we can all make a living
<li>producing the <a href="http://itc.conversationsnetwork.org/series/stackoverflow.html">Stack Overflow podcast</a> with Joel
<li>helping set up logistics for the <a href="http://stackoverflow.carsonified.com/">Stack Overflow DevDays</a> conferences
<li>setting up <a href="http://blog.stackoverflow.com/2009/05/the-stack-overflow-trilogy/">the next site in the trilogy</a>, and figuring out where we go next
</ol>
<p>
As programmers, as much as we might want to believe that
<p>
<pre>
lots_of_awesome_code = success;
</pre>
<p>
There's nothing particularly magical about the production of source code. In fact, <a href="http://www.codinghorror.com/blog/archives/000710.html">writing code is a tiny proportion of what makes most businesses successful</a>.
<p>
<blockquote>
Code is meaningless if nobody knows about your product. Code is meaningless if the IRS comes and throws you in jail because you didn't do your taxes. Code is meaningless if you get sued because you didn't bother having a software license created by a lawyer.
</blockquote>
<p>
Writing code <i>is</i> trivial. And fun. And something I continue to love doing. But if you <i>really</i> want your code to be successful, you'll <b><a href="http://www.codinghorror.com/blog/archives/000878.html">stop coding</a> long enough to do all that other, even <i>more</i> trivial stuff around the code that's necessary to <i>make</i> it successful.</b>
<p>
<small>* Although, to be fair, I really could write Twitter in a week. It's so ridiculously simple! Come on!</small>
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001284.html</guid>
         <pubDate>Mon, 06 Jul 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Oh, You Wanted "Awesome" Edition</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001283.html</link>
         <description><![CDATA[<p>
We recently upgraded our database server to 48 GB of memory -- because <a href="http://www.codinghorror.com/blog/archives/001198.html">hardware is cheap, and programmers are expensive</a>.
<p>
Imagine our surprise, then, when we rebooted the server and saw only 32 GB of memory available in Windows Server 2008. Did we install the memory wrong? No, the BIOS screen reported the full 48 GB of memory. In fact, the system information applet even reports 48 GB of memory:
<p>
<img alt="sodb1-system-summary.png" src="http://www.codinghorror.com/blog/images/sodb1-system-summary.png" width="541" height="95" />
<p>
But there's only 32 GB of <i>usable</i> memory in the system, somehow.
<p>
<p>
<img alt="sodb1-taskman-memory.png" src="http://www.codinghorror.com/blog/images/sodb1-taskman-memory.png" width="280" height="286" />
<p>
Did you feel that? A great disturbance in the Force, as if 17 billion bytes simultaneously cried out in terror and were suddenly silenced. It's so profoundly sad.
<p>
That's when I began to suspect the real culprit: <b>weasels</b>.
<p>
<img alt="marketing-weasel.jpg" src="http://www.codinghorror.com/blog/images/marketing-weasel.jpg" width="397" height="395"  />
<p>
No. Not the cute weasels. I'm referring to angry, evil <b><i>marketing</i> weasels</b>.
<p>
<img alt="weasels-ripped-my-flesh.jpg" src="http://www.codinghorror.com/blog/images/weasels-ripped-my-flesh.jpg" width="397" height="395"  />
<p>
That's more like it. Those marketing weasels are <i>vicious</i>.
<p>
We belatedly discovered post-upgrade that we are foolishly using Windows Server 2008 <b>Standard</b> edition. Which has been <a href="http://www.sadtrombone.com/">arbitrarily limited to 32 GB of memory</a>. Why? So the marketing weasels can <a href="http://www.joelonsoftware.com/articles/CamelsandRubberDuckies.html">segment the market</a>.
<p>
<blockquote>
It's sort of like if you were all set to buy that new merino wool sweater, and you <i>thought</i> it was going to cost $70, which is well worth it, and when you got to Banana Republic it was on sale for only $50! Now you have an extra $20 in found money that you would have been perfectly happy to give to the Banana Republicans!
<p>
Yipes!
<p>
That bothers good capitalists. Gosh darn it, if you're <i>willing to do without it</i>, well, give it to me! I can put it to good use, buying a SUV or condo or Mooney or yacht one of those other things capitalists buy!
<p>
In economist jargon, capitalists want to capture the <a href="http://en.wikipedia.org/wiki/Consumer_surplus">consumer surplus</a>.
<p>
Let's do this. Instead of charging $220, <b>let's ask each of our customers if they are rich or if they are poor. If they say they're rich, we'll charge them $349. If they say they're poor, we'll charge them $220.</b>
<p>
Now how much do we make? Back to Excel. Notice the quantities: we're still selling the same 233 copies, but the richest 42 customers, who were all willing to spend $349 or more, are being asked to spend $349. And our profits just went up! from $43K to about $48K! NICE!
<p>
Capture me some more of that consumer surplus stuff!
</blockquote>
<p>
How many versions of WIndows Server 2008 are there? <a href="http://www.microsoft.com/windowsserver2008/en/us/editions-overview.aspx">I count at least six</a>. They're capturing some <i>serious</i> consumer surplus, over there in Redmond.
<p>
<ul>
<li>Datacenter Edition
<li>Enterprise Edition
<li>Standard Edition
<li>Foundation
<li>Web
<li>HPC
</ul>
<p>
Already, I'm confused. <b>Which one of these versions allows me to use all 48 GB of my server's memory?</b> There are no less than six individual "compare" pages to slice and dice all the different features each version contains. Just try to <a href="http://www.microsoft.com/windowsserver2008/en/us/editions-overview.aspx">make sense of it all</a>. I dare you. No, I double dog dare you! Oh, and by the way, there's <i>zero</i> pricing information on any of these pages. So open another browser window and factor that into your decisionmaking, too.
<p>
I don't mean to single out Microsoft here; lots of companies use this segmented pricing trick. Even Web 2.0 darlings <a href="http://www.basecamphq.com/signup">37 Signals</a>.
<p>
<img alt="BaseCamp pricing" src="http://www.codinghorror.com/blog/images/37signals-basecamp-pricing.png" width="582" height="218" />
<p>
Heck, our very <i>own</i> product <a href="http://stackexchange.com/">segments the market</a>.
<p>
<img alt="Stack Exchange pricing" src="http://www.codinghorror.com/blog/images/stack-exchange-pricing.png" width="582" height="161" />
<p>
37signals just does it .. prettier, that's all. They're still asking you if you're poor or rich, and charging you more if you're rich.
<p>
Eric Sink also advocates the same <a href="http://www.ericsink.com/bos/Product_Pricing.html">"rich customer, poor customer" software pricing policy</a>:
<p>
<blockquote>
In an ideal world, the price would be different for every customer. The "perfect" pricing scheme would charge every customer a different amount, extracting from each one the maximum amount they are willing to pay.
<p>
<ul>
<li>The IT guy at Podunk Lutheran College has no money: Gratis.
<li>The IT guy at a medium-sized real estate agency has some money: $500.
<li>The IT guy at a Fortune 100 company has tons of money: $50,000.
</ul>
<p>
You can never make your pricing "perfect," but you can do much better than simply setting one constant price for all situations. By carefully tuning all these details, you can <b>find ways to charge more money from the people who are willing to pay more</b>.
</blockquote>
<p>
This sort of pricing seems exploitative, but it <a href="http://www.codinghorror.com/blog/archives/000323.html">can also be an act of public good</a> -- remember that the <i>poorest</i> customers are paying less; with a one-size-fits-all pricing policy, they might not be able to afford the product at all. Drug companies often follow the same pricing model when selling life-saving drugs to third-world countries. First-world countries end up subsidizing the massive costs of drug development, but the whole world benefits.
<p>
What I object to isn't the money involved, but the mental overhead. The whole thing runs so contrary to the spirit of <a href="http://www.codinghorror.com/blog/archives/000377.html">Don't Make Me Think</a>. Sure, don't make us customers think. Unless you want us to think about <b>how much we'd like to pay you</b>, that is. 
<p>
And what are we paying for? The privilege of flipping the magic bits in the software that say "I am <i>blah</i> edition!" It's all so.. anticlimactic. All that effort, all that poring over complex feature charts and stressing out about pricing plans, and for what? Just to get the one simple, stupid thing I care about -- using all the memory in my server. 
<p>
Perhaps these complaints, then, point to one unsung advantage of open source software:
<p>
<b>Open source software only comes in one edition: <i>awesome</i>.</b>
<p>
The money is irrelevant; the expensive resource here is my brain. If I choose open source, I don't have to think about licensing, feature matrices, or recurring billing. I know, I know, <a href="http://www.codinghorror.com/blog/archives/001097.html">we don't use software that costs money here</a>, but I'd almost be willing to pay for the privilege of not having to think about that stuff <i>ever again</i>.
<p>
Now if you'll excuse me, I'm having trouble deciding between <a href="http://www.penny-arcade.com/comic/2007/02/02/">Windows 7 Smoky Bacon Edition and Windows 7 Kenny Loggins Edition</a>. Bacon is delicious, but I <i>also</i> love that <a href="http://www.imdb.com/title/tt0087277/">Footloose</a> song..
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001283.html</guid>
         <pubDate>Wed, 01 Jul 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>All Abstractions Are Failed Abstractions</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001281.html</link>
         <description><![CDATA[<p>
In programming, <a href="http://www.advogato.org/person/Bram/diary.html?start=43">abstractions are powerful things</a>:
<p>
<blockquote>
 Joel Spolsky has <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">an article</a> in which he states
<p>
<blockquote>
<i>All non-trivial abstractions, to some degree, are leaky.</i>
</blockquote>
<p>
This is overly dogmatic - for example, bignum classes are exactly the same regardless of the native integer multiplication. Ignoring that, this statement is essentially true, but rather inane and missing the point. Without abstractions, all our code would be completely interdependent and unmaintainable, and abstractions do a remarkable job of cleaning that up. <b>It is a testament to the power of abstraction and how much we take it for granted that such a statement can be made at all</b>, as if we always expected to be able to write large pieces of software in a maintainable manner. 
</blockquote>
<p>
But they can cause problems of their own. Let's consider a particular <a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx">LINQ to SQL</a> query, designed to retrieve the most recent 48 Stack Overflow questions.
<p>
<pre>
var posts = 
  (from p in DB.Posts
  where 
  p.PostTypeId == PostTypeId.Question &&
  p.DeletionDate == null &&
  p.Score >= minscore
  orderby p.LastActivityDate descending
  select p).
  Take(maxposts);
</pre>
<p>
The big hook here is that <b>this is code the compiler actually understands</b>. You get code completion, compiler errors if you rename a database field or mistype the syntax, and so forth. Perhaps best of all, you get an honest to goodness <code>post</code> object as output! So you can turn around and immediately do stuff like this:
<p>
<pre>
foreach (var post in posts.ToList())
{
    Render(post.Body);
}
</pre>
<p>
Pretty cool, right?
<p>
Well, that Linq to SQL query is functionally equivalent to this old-school SQL blob. More than functionally, <b>it is <i>literally</i> identical</b>, if you examine the SQL string that LINQ generates behind the scenes:
<p>
<pre>
string query = 
  "select top 48 * from Posts
  where 
  PostTypeId = 1 and 
  DeletionDate is null and 
  Score >= -4
  order by LastActivityDate desc";
</pre>
<p>
This text blob is of course totally opaque to the compiler. Fat-finger a syntax error in here, and you won't find out about it until runtime. Even if it does run without a runtime error, processing the output of the query is awkward. It takes row level references and a lot of tedious data conversion to get at the underlying data. 
<p>
<pre>
var posts = DB.ExecuteQuery(query);

foreach (var post in posts.ToList());
{
   Render(post["Body"].ToString());
}
</pre>
<p>
So, LINQ to SQL is an abstraction -- we're <b>abstracting away raw SQL and database access in favor of native language constructs and objects</b>. I'd argue that Linq to SQL is a <i>good</i> abstraction. Heck, it's <a href="http://www.codinghorror.com/blog/archives/000033.html">exactly what I asked for five years ago</a>.
<p>
But even a good abstraction can break down in unexpected ways.
<p>
Consider this optimization, which is trivial in the old-school SQL blob code: instead of pulling down every single field in the post records, why not pull just the id number? Makes sense, if that's all I need. And it's faster -- much faster!
<p>
<table width="400">
<tr>
<tr><td>select top 48 <font color="red">*</font> from Posts<td align="right">827 ms</tr>
<tr><td>select top 48 <font color="red">Id</font> from Posts<td align="right">260 ms</tr>
</table>
<p>
Selecting all columns with the star (*) operator is expensive, and that's what LINQ to SQL always does by default. Yes, <a href="http://mkdot.net/blogs/thearchitect/archive/2008/04/24/lazy-load-in-linq-to-sql.aspx">you can specify lazy loading</a>, but not on a per-query basis. Normally, this is a non-issue, because selecting all columns for simple queries is not all <i>that</i> expensive. And you'd think pulling down <b>48 measly little post records</b> would be squarely in the "not expensive" category!
<p>
So let's compare apples to apples. What if we got just the id numbers, then retrieved the full data for each row?
<p>
<table width="400">
<tr><td>select top 48 Id from Posts<td align="right">260 ms</tr>
<tr><td>select * from Posts where Id = 12345<td align="right">3 ms</tr>
</table>
<p>
Now, retrieving 48 individual records one by one is sort of silly, becase you could easily construct a single <code>where Id in (1,2,3..,47,48)</code> query that would grab all 48 posts in one go. But even if we did it in this naive way, the total execution time is still a very reasonable (48 * 3 ms) + 260 ms = 404 ms. <b>That is <i>half</i> the time of the standard select-star SQL emitted by LINQ to SQL!</b>
<p>
An extra 400 milliseconds doesn't sound like much, but <a href="http://radar.oreilly.com/2009/06/bing-and-google-agree-slow-pag.html">slow pages lose users</a>. And why in the world would you perform a slow database query on every single page of your website when you don't have to?
<p>
It's tempting to blame Linq, but is Linq really at fault here? These seem like <i>identical</i> database operations to me:
<p>
<blockquote>
1. Give me all columns of data for the top 48 posts.
</blockquote>
<p>
or
<p>
<blockquote>
1. Give me just the ids for the top 48 posts.<br/>
2. Retrieve all columns of data for each of those 48 ids.
</blockquote>
<p>
So why in the wide, wide world of sports would one of these <b>seemingly identical operations</b> be twice as slow as the other?
<p>
The problem isn't Linq to SQL. The problem is that <b>we're attempting to spackle a nice, clean abstraction over a database that is full of highly irregular and unusual real world behaviors.</b> Databases that:
<p>
<ul>
<li>may not have the right indexes
<li>may misinterpret your query and generate an inefficient query plan
<li>are trying to perform an operation that doesn't fit well in available memory
<li>are paging data from disks which might be busy at that particular moment
<li>might contain irregularly sized column datatypes
</ul>
<p>
That's what's so frustrating. We can't just pretend all our data is formatted into neat, orderly data structures sitting there in memory, lined up in convenient little queues for us to reach out and casually scoop them up. As I've demonstrated, even trivial queries can have bizarre behavior and performance characteristics that are not at all clear.
<p>
To its credit, Linq to SQL is quite flexible: we can use strongly typed queries, or we can  use SQL blob queries that we cast to the right object type. That flexibility is critical, because <b>so much of our performance depends on these quirks of the database</b>. We default to the built-in Linq language constructs, and drop down to hand-tuning ye olde SQL blobs where the performance traces tell us we need to.
<p>
Either way, it's clear that you've <i>got</i> to know what's happening in the database every step of the way to even begin understanding the performance of your application, much less troubleshoot it. 
<p>
I think you could make a fairly solid case that Linq to SQL is, in fact, a leaky and failed abstraction. Exactly the kind of thing Joel was complaining about. But I'd also argue that <b>virtually <i>all</i> good programming abstractions are failed abstractions</b>. I don't think I've ever used one that didn't leak like a sieve. But I think that's an awfully <a href="http://www.codinghorror.com/blog/archives/000165.html">architecture astronaut</a> way of looking at things. Instead, let's ask ourselves a more pragmatic question:
<p>
<blockquote>
Does this abstraction make our code at least a <i>little</i> easier to write? To understand? To troubleshoot? Are we better off <i>with</i> this abstraction than we were without it?
</blockquote>
<p>
It's our job as modern programmers not to abandon abstractions due to these deficiencies, but to embrace the useful elements of them, to adapt the working parts and construct ever so slightly <i>less</i> leaky and broken abstractions over time. Like desperate citizens manning a dike in a category 5 storm, <b>we programmers keep piling up these leaky abstractions, shoring up as best we can, desperately attempting to stay ahead of the endlessly rising waters of complexity.</b>
<p>
As much as I may curse Linq to SQL as yet another failed abstraction, I'll continue to use it. Yes, I may end up soggy and irritable at times. But it sure as <i>heck</i> beats drowning. 
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001281.html</guid>
         <pubDate>Tue, 30 Jun 2009 05:01:29 -0800</pubDate>
      </item>

      <item>
         <title>The iPhone Software Revolution</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001280.html</link>
         <description><![CDATA[<p>
The original iPhone was for <s>suckers</s> <a href="http://www.codinghorror.com/blog/archives/000896.html">hard-core gadget enthusiasts only</a>. But as I predicted, 12 months later, the iPhone 3G rectified all the shortcomings of the first version. And now, with the iPhone 3GS, we've reached the <a href="http://www.seattlepi.com/business/palm18.shtml">mythical third version</a>:
<p>
<blockquote>
A computer industry adage is that Microsoft does not make a successful product until version 3. Its Windows operating system was not a big success until the third version was introduced in 1990 and, similarly, its Internet Explorer browsing software was lackluster until the third version.
</blockquote>
<p>
The platform is now so compelling and polished that <b>even I took the plunge</b>. For context, this is the first Apple product I've owned <a href="http://www.codinghorror.com/blog/archives/001051.html">since 1984</a>. Literally.
<p>
I am largely ambivalent towards Apple, but it's impossible to be ambivalent about the iPhone -- and in particular, <a href="http://www.apple.com/iphone/iphone-3gs/">the latest and greatest iPhone 3GS</a>. It is the Pentium to the 486 of the iPhone 3G. A landmark, genre-defining product, no longer a mere smartphone but an honest to God fully capable, no-compromises <i>computer</i> in the palm of your hand.
<p>
Here's how far I am willing to go: <b>I believe the iPhone will ultimately be judged a more important product than the original Apple Macintosh</b>.
<p>
<a href="http://www.apple.com/iphone/iphone-3gs/"><img alt="iphone3gs1.jpg" src="http://www.codinghorror.com/blog/images/iphone3gs1.jpg" width="325" height="401" border="0" /></a>
<p>
Yes, I am dead serious. Just check back here in fifteen to twenty years to see if I was right. (Hint: I will be.)
<p>
There's always been a weird tension in Apple's computer designs, because they attempt to control every nuance of the entire experience from end to end. For the best Apple<sup>tm</sup> experience, you run custom Apple<sup>tm</sup> applications on <a href="http://www.codinghorror.com/blog/archives/001044.html">artfully designed Apple<sup>tm</sup> hardware dongles</a>. That's fundamentally at odds with the classic hacker mentality that birthed the general purpose computer. You can see it in the wild west, anything goes Linux ecosystem. You can even see it in the Wintel axis of evil, where a million motley mixtures of hardware, software, and operating system variants are allowed to bloom, like little beige stickered flowers, for a price. 
<p>
But a cell phone? It's a closed ecosystem, by <i>definition</i>, running on a proprietary network. By <b>a status quo of incompetent megacorporations who wouldn't know user friendliness or good design if it ran up behind them and bit them in the rear end of their expensive, tailored suits</b>. All those things that bugged me about Apple's computers are utter non-issues in the phone market. Proprietary handset? So is every other handset. Locked in to a single vendor? Everyone signs a multi-year contract. One company controlling your entire experience? That's how it's always been done. Nokia, Sony/Ericsson, Microsoft, RIM -- these guys clearly had no <i>idea</i> what they were in for when Apple set their sights on the cell phone market -- a market that is a nearly perfect match to Apple's strengths.
<p>
<b>Apple was <i>born</i> to make a kick-ass phone</b>. And with the lead they have, I predict they will dominate the market for years to come.
<p>
Consider all the myriad devices that the iPhone 3GS can sub for, and in some cases, outright replace:
<p>
<ul>
<li>GPS
<li>Netbook (for casual web browsing and email)
<li>Gameboy
<li>Watch
<li>Camera
<li>MP4 Video Recorder
<li>MP3 player
<li>DVD player
<li>eBook reader
</ul>
<p>
Oh yeah, and I heard you can make phone calls with it, too. Like any general purpose computer, it's a jack of all trades. 
<p>
As <a href="http://www.anandtech.com/gadgets/showdoc.aspx?i=3587">impressive as the new hardware is</a>, the software story is even bigger. If you're a software developer, the iPhone can become a <b>career changing device</b>, all thanks to one little teeny-tiny icon on the iPhone home screen:
<p>
<a href="http://www.apple.com/iphone/apps-for-iphone/"><img alt="app_store.jpg" src="http://www.codinghorror.com/blog/images/app_store.jpg" width="281" height="330" border="0" /></a>
<p>
The <a href="http://www.apple.com/iphone/apps-for-iphone/">App Store</a> makes it <i>brainlessly</i> easy to install, upgrade, and purchase new applications. But more importantly, any software developer -- at the mild entry cost of owning a Mac, and signing up for the <a href="http://developer.apple.com/iPhone/program/">$99 iPhone Developer Program</a> -- can build an app and sell it to the worldwide audience of iPhone users. Apple makes this stuff look <i>easy</i>, when historically it has been anything but. How many successful garage developers do you know for Nintendo DS? For the Motorola Razr? For Palm? For Windows Mobile?
<p>
Apple has never been particularly great at supporting software developers, but I have to give them their due: with the iPhone developer program, <b>they've changed the game</b>. Nowhere is this more evident than in software pricing. I went on a software buying spree when I picked up my iPhone 3GS, ending up with almost three pages of new applications from the App Store. I was a little worried that I might rack up a substantial bill, but how can I resist when cool stuff like ports of the <a href="http://toucharcade.com/2009/05/15/pinball-dreaming-pinball-dreams-gets-a-lite-version/">classic Amiga Pinball Dreams</a> are available, or the <a href="http://toucharcade.com/2009/05/25/guru-meditation-a-peaceful-retro-relaxer/">historic Guru Meditation</a>? The list of useful (and useless) apps is almost endless, and growing every day.
<p>
My total bill for 3 screens worth of great iPhone software applications? <b>About fifty bucks</b>. I've paid more than that for Xbox 360 games I ended up playing for a total of maybe three hours! About half of the apps were free, and the rest were a few bucks. I think the most I paid was $9.99, and that was for <a href="http://blog.sangsara.net/2009/05/comparing-ebooks-classics-stanza-and.html">an entire library</a>.  What's revolutionary here isn't just the development ecosystem, but the economics that support it, too. <b>At these crazy low prices, why <i>not</i> fill your phone with cool and useful apps?</b> You might wonder if developers can really make a living selling apps that only cost 99 cents. Sure you can, if you sell hundreds of thousands of copies:
<p>
<blockquote>
Freeverse, one of the leading developers and publishers of iPhone games, <a href="http://news.freeverse.com/archives/2009/06/22/freeverses-flic.php">sold the millionth copy of its Flick Fishing game over the weekend</a>, making Flick Fishing the first paid application to reach the one million download milestone. Flick Fishing, which costs 99 cents, allows iPhone and iPod touch users to take a virtual fishing trip with the flick of a wrist. The game uses the iPhone's accelerometer to recreate a casting motion, then a combination of bait choice and fishing skill helps players land the big fish. 
<p>
Preliminary weekly reports for the period from 23 March to 19 April indicate that Flight Control <a href="http://firemintgames.blogspot.com/2009/04/flight-control-sales-numbers.html">sold a total of 587,485 units during this time</a>. We estimate total sales are now over 700,000 units, with the bulk of sales occurring in a 3 week period.
Flight Control 
</blockquote>
<p>
That's an honorable way to <a href="http://www.codinghorror.com/blog/archives/000872.html">get rich programming</a>, and a nice business alternative to the dog-eat-dog world of advertising subsidized apps.
<p>
I love nothing more than <a href="http://www.codinghorror.com/blog/archives/000735.html">supporting my fellow software developers</a> by voting with my wallet. it does my heart good to see so many indie and garage developers making it big on the iPhone. (Also, I'm a <a href="http://www.codinghorror.com/blog/archives/001135.html">sucker for physics games</a>, and there are a bunch of great ones available in the App Store). I'm more than happy to pitch in a few bucks every month for a great new iPhone app. 
<p>
If this has all come across as too rah-rah, too uncritical a view of the iPhone, I apologize. There are certainly things to be critical about, such as the App Store's weird enforcement policies, the lack of support for emulators, or Flash, or anything else that might somehow undermine the platform as decided in some paranoid, secretive Apple back room. Not that we'd ever hear about it.
<p>
I didn't write this to kiss Apple's ass. I wrote this because I truly feel that the iPhone is a key inflection point in software development. We will look back on this as the time when "software" stopped being something that geeks buy (or worse, bootleg), and <b>started being something that <i>everyone</i> buys, every day</b>. You'd have to be a jaded developer indeed not to find something magical and transformative in this formula, and although others will clearly follow, the iPhone is leading the way.
<p>
"There's an app for that." Kudos, Apple. From the bottom of my hoary old software developer heart.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001280.html</guid>
         <pubDate>Wed, 24 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Scaling Up vs. Scaling Out: Hidden Costs</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001279.html</link>
         <description><![CDATA[<p>
In <a href="http://www.codinghorror.com/blog/archives/001195.html">My Scaling Hero</a>, I described the amazing scaling story of plentyoffish.com. It's impressive by any measure, but also particularly relevant to us because we're on the Microsoft stack, too. I was intrigued when Markus <a href="http://plentyoffish.wordpress.com/2009/06/14/upgrades-themes-date-night/">posted this recent update</a>:
<p>
<blockquote>
Last monday we upgraded our core database server after a power outage knocked the site offline. I haven't touched this machine since 2005 so it was a major undertaking to do it last minute. We upgraded from a machine with 64 GB of ram and 8 CPUs to <b>a HP ProLiant DL785 with 512 GB of ram and 32 CPUs</b> ...
</blockquote>
<p>
The <a href="http://h10010.www1.hp.com/wwpc/us/en/en/WF05a/15351-15351-3328412-241644-3328423-3716072.html">HP ProLiant DL785 G5</a> <i>starts</i> at $16,999 -- and that's barebones, with nothing inside. Fully configured, as Markus describes, it's <a href="http://h18004.www1.hp.com/products/quickspecs/13046_na/13046_na.html">kind of a monster</a>:
<p>
<ul>
<li>7U size (a typical server is 2U, and mainstream servers are often 1U)
<li>8 CPU sockets
<li>64 memory sockets
<li>16 drive bays
<li>11 expansion slots
<li>6 power supplies
</ul>
<p>
It's unclear if they bought it pre-configured, or added the disks, CPUs, and memory themselves. The most expensive configuration shown on the HP website is $37,398 and that includes only 4 processors, no drives, and a paltry 32 GB memory. When topped out with ultra-expensive 8 GB memory DIMMs, 8 high end Opterons, 10,000 RPM hard drives, and everything else -- by my estimates, it probably <b>cost closer to $100,000</b>. That might even be a lowball number, considering that <a href="http://www.tpc.org/results/individual_results/HP/HP_DL785_300G_11-17-2008_ES.pdf">the DL785 submitted to the TPC benchmark website</a> (pdf) had a "system cost" of $186,700. And that machine only had 256 GB of RAM. (But, to be fair, that total included another major storage array, and a bunch of software.)
<p>
At any rate, let's assume $100,000 is a reasonable ballpark for the monster server Markus purchased. It is the very definition of <b>scaling up</b> -- a seriously big iron single server.
<p>
But what if you <b>scaled out</b>, instead -- <a href="http://hadoop.apache.org/">Hadoop</a> or <a href="http://labs.google.com/papers/mapreduce.html">MapReduce</a> style, across lots and lots of inexpensive servers? After some initial configuration bumps, I've been happy with the inexpensive Lenovo ThinkServer RS110 servers we use. They're no match for that DL785 -- but they aren't exactly chopped liver, either:
<p>
<table width="400">
<tr>
<td>Lenovo ThinkServer RS110 barebones</td>
<td>$600</td>
</tr>
<tr>
<td>8 GB RAM</td>
<td>$100</td>
</tr>
<tr>
<td>2 x eBay <a href="http://www.codinghorror.com/blog/archives/001200.html">drive brackets</a></td>
<td>$50</td>
</tr>
<tr>
<td>2 x 500 GB SATA hard drives, mirrored</td>
<td>$100</td>
</tr>
<tr>
<td>Intel Xeon X3360 2.83 GHz quad-core CPU</td>
<td>$300</td>
</tr>
</table>
<p>
Grand total of <b>$1,150</b> per server. Plus another 10 percent for tax, shipping, and so forth. I replace the bundled CPU and memory that the server ships with, and then resell the salvaged parts on eBay for about $100 -- so let's call the total price per server $1,200.</p>
<p>
Now, assuming a <b>fixed spend of $100,000</b>, we could build <b>83</b> of those 1U servers. Let's compare what we end up with for our money:
<p>
<table width="400">
<tr>
<td>&nbsp;
<td align="right"><b>Scaling Up</b>
<td align="right"><b>Scaling Out</b>
</tr>
<tr>
<td>CPUs
<td align="right">32
<td align="right">332
</tr>
<tr>
<td>RAM
<td align="right">512 GB
<td align="right">664 GB
</tr>
<tr>
<td>Disk
<td align="right">4 TB
<td align="right">40.5 TB
</tr>
</table>
<p>
<i>Now</i> which approach makes more sense?
<p>
(These numbers are a bit skewed because that DL785 is at the absolute extreme end of the big iron spectrum. You pay a hefty premium for fully maxxing out. It is possible to build a slightly less powerful server with <i>far</i> better bang for the buck.)
<p>
But there's something else to consider: software licensing.
<p>
<table width="400">
<tr>
<td>&nbsp;
<td align="right"><b>Scaling Up</b>
<td align="right"><b>Scaling Out</b>
</tr>
<tr>
<td>OS
<td align="right">$2,310
<td align="right">$33,200*
</tr>
<tr>
<td>SQL
<td align="right">$8,318
<td align="right">$49,800*
</tr>
</table>
<p>
(If you're using all open source software, then of course these costs will be very close to zero. We're assuming a Microsoft shop here, with the necessary licenses for Windows Server 2008 and SQL Server 2008.)
<p>
<i>Now</i> which approach makes more sense?
<p>
What about the power costs? Electricity and rack space isn't free.
<p>
<table width="400">
<tr>
<td>&nbsp;
<td align="right"><b>Scaling Up</b>
<td align="right"><b>Scaling Out</b>
</tr>
<tr>
<td>Peak Watts
<td align="right">1,200w
<td align="right">16,600w
</tr>
<tr>
<td>Power Cost / Year
<td align="right">$1,577
<td align="right">$21,815
</tr>
</table>
<p>
<i>Now</i> which approach makes more sense?
<p>
I'm not picking favorites. This is presented as food for thought. There are at least a dozen other factors you'd want to consider depending on the particulars of your situation. Scaling up and scaling out are <i>both</i> viable solutions, depending on what problem you're trying to solve, and what resources (financial, software, and otherwise) you have at hand.
<p>
That said, I think it's fair to conclude that <b>scaling out is only frictionless when you use open source software</b>. Otherwise, you're in a bit of a conundrum: scaling up means paying less for licenses and a lot more for hardware, while scaling out means paying less for the hardware, and a <i>whole</i> lot more for licenses.
<p>
<small>* I have <i>no</i> idea if these are the right prices for Windows Server 2008 and SQL Server 2008, because <a href="http://www.microsoft.com/Sqlserver/2005/en/us/licensing.aspx">reading about the licensing models makes my brain hurt</a>. If anything, it could be substantially more.</small>
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001279.html</guid>
         <pubDate>Tue, 23 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Monty Hall, Monty Fall, Monty Crawl</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001278.html</link>
         <description><![CDATA[<p>
Remember <a href="http://www.codinghorror.com/blog/archives/001203.html">The Problem of the Unfinished Game</a>? And the almost 2,500 comments those two posts generated? I know, I like to pretend it didn't happen, either. Some <a href="http://paulbuchheit.blogspot.com/2009/01/question-is-wrong.html">objected to the way I asked the question</a>, but it was a simple question asked in simple language. I think what they're <i>really</i> objecting to is <b>how unintuitive the answer is</b>.
<p>
Which reminds me of another question that you've probably heard of: 
<p>
<blockquote>
Suppose the contestants on a game show are given the choice of three doors: behind one door is a car; behind the others, goats. After a contestant picks a door, the host, who knows what's behind all the doors, opens one of the unchosen doors, which reveals a goat. He then asks the contestant, "Do you want to switch doors?"
<p>
<img alt="monty-hall-problem-doors.jpg" src="http://www.codinghorror.com/blog/images/monty-hall-problem-doors.jpg" width="626" height="357" />
<p>
<b>Should the contestant switch doors?</b>
</blockquote>
<p>
This is, of course, <a href="http://en.wikipedia.org/wiki/Monty_Hall_problem">the Monty Hall problem</a>. It's been covered to death, and quite well I might add, by dozens of writers who are <a href="http://www.codingthewheel.com/archives/21-and-the-monty-hall-paradox">far</a> <a href="http://dilbertblog.typepad.com/the_dilbert_blog/2008/04/monte-hall-prob.html">more</a> <a href="http://www.letsmakeadeal.com/problem.htm">talented</a> than I.
<p>
What's interesting about this problem, to me at least, is not the solution, but the vehemence with which people react to the solution -- as described in <a href="http://www.amazon.com/dp/0375424040/?tag=codinghorror-20">The Drunkard's Walk: How Randomness Rules Our Lives</a>.
<p>
<a href="http://www.amazon.com/dp/0375424040/?tag=codinghorror-20"><img alt="the-drunkards-walk-cover.png" src="http://www.codinghorror.com/blog/images/the-drunkards-walk-cover.png" width="294" height="405" border="0" /></a>
<p>
<blockquote>
It appears to be a pretty silly question. Two doors are available -- open one and you win; open the other and you lose -- so it seems self-evident that whether you change your choice or not, your chances of winning are 50/50. What could be simpler? The thing is, Marilyn <a href="http://www.marilynvossavant.com/articles/gameshow.html">said in her column</a> that it is better to switch.
<p>
Despite the public's much-heralded lethargy when it comes to mathematical issues, Marilyn's readers reacted as if she'd advocated ceding California back to Mexico. Her denial of the obvious brought her an avalanche of mail, 10,000 letters by her estimate. If you ask the American people whether they agree that plants create the oxygen in the air, light travels faster than sound, or you cannot make radioactive milk by boiling it, you will get double-digit disagreement in each case (13 percent, 24 percent, and 35 percent, respectively). But on this issue, <b>Americans were united: Ninety-two percent agreed Marilyn was wrong.</b>
</blockquote>
<p>
Perhaps the public can be forgiven their ignorance, but what of the experts? Surprisingly, the mathematicians fare little better.
<p>
<blockquote>
Almost 1,000 Ph.D.s wrote in, many of them math professors, who seemed especially irate. "You blew it," wrote a mathematician from George Mason University. From Dickinson State University came this: "I am in shock that after being corrected by at least three mathematicians, you still do not see your mistake." From Georgetown: "How many irate mathematicians are needed to change your mind?" And someone from the U.S. Army Research Institute remarked, "If all those Ph.D.s are wrong the country would be in serious trouble." Responses continued in such great numbers and for such a long time that after devoting quite a bit of column space to the issue, Marilyn decided she whould no longer address it.
<p>
The army PhD who wrote in may have been correct that if all those PhDs were wrong, it would be a sign of trouble. But Marilyn <i>was</i> correct. When told of this, <a href="http://en.wikipedia.org/wiki/Paul_Erdos">Paul Erdos</a>, one of the leading mathematicians of the 20th century, said, "That's impossible." Then, when presented with a formal mathematical proof of the correct answer, he still didn't believe it and grew angry. Only after a colleague arranged for a computer simulation in which Erdos watched hundreds of trials that came out 2-to-1 in favor of switching did Erdos concede that he was wrong.
</blockquote>
<p>
You may recognize Paul Erdos from a <a href="http://xkcd.com/599/">particularly obscure XKCD cartoon</a> last week. So if <i>you</i> feel like an idiot because you couldn't figure out the Monty Hall problem, take heart. <b>The problem is so unintuitive one of the most notable mathematicians of the last century couldn't wrap his head around it.</b> That's ... well, that's <i>amazing</i>.
<p>
How can something that seems so obvious be so wrong? Apparently our brains are not wired to do these sorts of probability problems very well. Personally, I found the text of Jeffrey Rosenthal's <a href="http://www.probability.ca/jeff/writing/montyfall.pdf">Monty Hall, Monty Fall, Monty Crawl</a> (pdf) to be the most illuminating, because it asks us to consider some related possibilities, and how they might affect the outcome:
<p>
<blockquote>
<b>Monty Fall Problem</b>: In this variant, once you have selected one of the three doors, the host slips on a banana peel and accidentally pushes open another door, which just happens not to contain the car. Now what are the probabilities that you will win, either by sticking with your original door, or switching doors?
<p>
<b>Monty Crawl Problem</b>: Once you have selected one of
the three doors, the host then reveals one non-selected door which does not contain
the car. However, the host is very tired, and crawls from his position (near Door #1)
to the door he is to open. In particular, if he has a choice of doors to open, then he opens the smallest number available door. (For example, if you selected Door #1 and the car was indeed behind Door #1, then the host would always open Door #2, never Door #3.) Now what are the probabilities that you will win the car if you stick versus if you switch?
</blockquote>
<p>
Paul Erdos was brilliant, but even he realized his own limits when presented with the highly unintuitive Monty Hall problem. For his epitaph, he suggested, in his native Hungarian, "Végre nem butulok tovább". This translates into English as "I've finally stopped getting dumber."
<p>
If only the rest of us could be so lucky.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001278.html</guid>
         <pubDate>Sun, 21 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>We Done Been ... Framed!</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001277.html</link>
         <description><![CDATA[<p>
In my previous post, <a href="http://www.codinghorror.com/blog/archives/001276.html">Url Shorteners: Destroying the Web Since 2002</a>, I mentioned that one of the "features" of the new generation of URL shortening services is to frame the target content.
<p>
Digg is one of the most popular sites to implement this strategy. Here's how it works. If you're logged in to <a href="http://digg.com/">Digg</a>, every target link you click from Digg is a shortened URL of their own creation. If I click through to a Stack Overflow article someone else has "Dugg", I'm sent to this link.
<p>
<a href="http://digg.com/d1tBya">http://digg.com/d1tBya</a>
<p>
<img alt="diggbar-stack-overflow-screenshot.png" src="http://www.codinghorror.com/blog/images/diggbar-stack-overflow-screenshot.png" width="720" height="170"  />
<p>
For logged in users, every outgoing Digg link is framed inside the <a href="http://digg.com/tools/diggbar">"DiggBar"</a>. It's a way of dragging the Digg experience with you wherever you go -- while you're reading the target article, you can vote it up, see related articles, share, and so forth. And if you share this shortened URL with other users, they'll get the same behavior, provided they also hold a Digg login cookie.
<p>
At this point you're probably expecting me to rant about how evil the DiggBar is, and how it, too, is destroying the web, etcetera, etcetera, so on, and so forth. But I can't muster the indignant rage. I can give you, at best, ambivalence. Here's why:
<p>
<ol>
<li>The DiggBar is not served to the vast majority of anonymous users, but only to users who have opted in to the Digg experience by signing up.
<li>The <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=139394">new rel="canonical" directive</a> is used on target links so search engines can tell which links are the "real", authoritative links to the content. They won't be confused or have search engine juice diluted by Digg's shortened URLs. At least that's the theory, anyway.
<li>No Digg ads are served via the DiggBar, so the framed content is not "wrapped" in ads.
<li>I believe Digg users themselves can opt out of DiggBar via a preferences setting.
</ol>
Digg is trying to build a business, just like we are with Stack Overflow. I can't fault them for their desire to extend the Digg community outward a little bit, given the zillions of outgoing links they feed to the world. Particularly when they attempted to do so in a semi-ethical way, actively soliciting community feedback along the way.
<p>
In short, Digg isn't the problem. But even if they <i>were</i> -- if you don't want to be framed by the DiggBar, or any other website for that matter, you could <b>put so-called "frame-busting" JavaScript</b> in your pages.
<p>
<pre>
if (parent.frames.length > 0) {
    top.location.replace(document.location);
}
</pre>
<p>
Problem solved! This code (or the many frame-busting variants thereof) <i>does</i> work on the DiggBar. But not every framing site is as reputable as Digg. What happens when we put on our hypothetical black hats and start <a href="http://www.codinghorror.com/blog/archives/001123.html">designing for evil?</a>
<p>
I'll tell you what happens. <a href="http://coderrr.wordpress.com/2009/02/13/preventing-frame-busting-and-click-jacking-ui-redressing/">This happens</a>.
<p>
<blockquote>
<pre>
   var prevent_bust = 0  
   window.onbeforeunload = function() { prevent_bust++ }  
   setInterval(function() {  
     if (prevent_bust > 0) {  
       prevent_bust -= 2  
       window.top.location = 'http://server-which-responds-with-204.com'  
     }  
   }, 1)  
</pre>
<p>
On most browsers a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">204 (No Content) HTTP response</a> will do nothing, meaning it will leave you on the current page. But the request attempt will override the previous frame busting attempt, rendering it useless. If the server responds quickly this will be almost invisible to the user.
</blockquote>
<p>
When life serves you lemons, make a lemon cannon. Produce frame-busting-<i>busting</i> JavaScript. This code does the following:
<p>
<ul>
<li>increments a counter every time the browser attempts to navigate away from the current page, via the <code>window.onbeforeonload</code> event handler
<li>sets up a timer that fires every millisecond via <code>setInterval()</code>, and if it sees the counter incremented, changes the current location to an URL of the attacker's control
<li>that URL serves up a page with HTTP status code 204, which does not cause the browser to navigate anywhere
</ul>
<p>
Net effect: frame-busting busted. Which might naturally lead you to wonder -- <b>hey buster, can you bust the frame-busting buster?</b> And, if so, <a href="http://www.youtube.com/watch?v=Iw3G80bplTg">where does it end?</a>
<p>
<blockquote>
In the 1998 movie, <a href="http://www.imdb.com/title/tt0120609/">The Big Hit</a>, the protagonists kidnap the daughter of an extremely wealthy Japanese businessman. When they call to deliver the ransom notice, they turn to Gump who employs a brand name Trace Buster to prevent police from tracing the call.
<p>
<a href="http://www.imdb.com/title/tt0120609/"><img alt="the-big-hit-cover.jpg" src="http://www.codinghorror.com/blog/images/the-big-hit-cover.jpg" width="403" height="463" border="0" /></a>
<p>
Unbeknownst to Gump, the father has a Trace-Buster-Buster at his disposal. This in turn triggers Gump to use his Trace-Buster-Buster-Buster in an ever escalating battle to evade detection. 
</blockquote>
<p>
What's really scary is that <a href="http://stackoverflow.com/questions/958997/frame-buster-buster-buster-code-needed">near as I can tell</a>, <b>there is no solution</b>. Due to cross-domain JavaScript security restrictions, it is almost impossible for the framed site to block or interfere with the parent page's evil JavaScript that is intentionally and aggressively blocking the framebusting.
<p>
<b>If an evil website decides it's going to frame your website, you <i>will</i> be framed. Period.</b> Frame-busting is nothing more than a false sense of security; it doesn't work. This was a disturbing revelation to me, because framing is the first step on the road to <a href="http://en.wikipedia.org/wiki/Clickjacking">clickjacking</a>:
<p>
<blockquote>
A clickjacked page tricks a user into performing undesired actions by clicking on a concealed link. On a clickjacked page, the attackers show a set of dummy buttons, then load another page over it in a transparent layer. <b>The users think that they are clicking the visible buttons, while they are actually performing actions on the hidden page.</b> The hidden page may be an authentic page, and therefore the attackers can trick users into performing actions which the users never intended to do and there is no way of tracing such actions later, as the user was genuinely authenticated on the other page.
<p>
For example, a user might play a game in which they have to click on some buttons, but another authentic page like a web mail site from a popular service is loaded in a hidden iframe on top of the game. The iframe will load only if the user has saved the password for its respective site. The buttons in the game are placed such that their positions coincide exactly with the select all mail button and then the delete mail button. The consequence is that the user unknowingly deleted all the mail in their folder while playing a simple game. Other known exploits have been tricking users to enable their webcam and microphone through flash (which has since been corrected by Adobe), tricking users to make their social networking profile information public, making users follow someone on Twitter, etc.
</blockquote>
<p>
I've fallen prey to <a href="http://dsandler.org/wp/archives/2009/02/12/dontclick">a mild clickjacking exploit</a> on Twitter myself! It really does happen -- and it's not hard to do.
<p>
Yes, Digg frames ethically, so your frame-busting of the DiggBar will appear to work. But if the framing site is evil, good luck. When faced with a determined, skilled adversary that wants to frame your contnet, all bets are off. I don't think it's possible to escape. So consider this a wakeup call: you should build clickjacking countermeasures as if your website could be framed <i>at any time</i>.
<p>
I was a skeptic. I didn't want to believe it either. But once shown the exploits on our own site  -- fortunately, by a white hat security expert -- I lived to regret that. <b>Don't let frame-busting code lull you into a false sense of security, too.</b>
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001277.html</guid>
         <pubDate>Wed, 17 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Url Shorteners: Destroying the Web Since 2002</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001276.html</link>
         <description><![CDATA[<p>
Is anyone else as sick as I am of all the mainstream news coverage on <a href="http://twitter.com">Twitter</a>? Don't get me wrong, I'm a Twitter fan, and I've been a <a href="http://twitter.com/codinghorror">user</a> since 2006. To me, it's a form of <a href="http://www.codinghorror.com/blog/archives/000840.html">public instant messaging</a> -- yet another way to <a href="http://www.codinghorror.com/blog/archives/000854.html">maximize the value of my keystrokes</a>. Still, I'm a little perplexed as to the media's near-<i>obsession</i> with the service. If a day goes by now without the New York Times or CNN mentioning Twitter in some way, I become concerned. Am I really getting <i>all</i> the news? Or just the stupid, too long, non-140-character version of the news? 
<p>
I guess I should be pleased that I was a (relatively) early adopter and advocate of software that has achieved the rarest of feats in the software industry -- critical mass. Adoption by the proverbial "average user". Whatever you may think of Twitter, consider this: as a software developer, you'll be fortunate to build <i>one</i> project that achieves critical mass in your entire life. And even then, only if you are a very, <i>very</i> lucky programmer: in the right place, at the right time, with the right idea, working with the right people. Most of us never get there. I don't think I will.
<p>
There is one side effect of this unprecedented popularity, though, that I definitely wouldn't have predicted: <b>the mainstreaming of URL shortening services</b>. You can barely use Twitter without being forced into near-mastery of URL shortening. For example, this is the super-secret, patented formula I often use when composing <a href="http://twitter.com/codinghorror">my Twitter messages</a>:
<p>
<blockquote>
"brief summary or opinion" [link for more detail]
</blockquote>
<p>
Twitter only allows 140 characters in each status update. Some might view this as a limitation, but I consider it Twitter's best feature. I am all for enforced brevity. Maybe that's due to the pain of living through <a href="http://www.codinghorror.com/blog/archives/001191.html">a lifetime of e<s>m</s>fail</a>. But depending on the size of the comment and the URL (and some URLs can be ridiculously long), I can't <i>quite</i> fit everything in there without sounding like an SMS-addled teenage girl. This is where URL shortening comes in.
<p>
Now, I know what you're thinking. You're a clever programmer. <i>You</i> could implement some kind of fancy jQuery callback to shorten the URL, and replace the longer URL with the shorter URL right there in the text as the user pauses in typing. But you don't even have to be that clever; most of the URL shortening services (that aren't in their infancy) deliver a rather predictable size for the URLs they return. You could simply estimate the size of the URL post-shortening -- maybe adding 1 character as a fudge factor for safety -- and allow the update.
<p>
Twitter, I can assure you, is far more brain damaged than you can possibly imagine. It will indeed shorten URLs that fit in the 140 character limit (whoopee!), but it does <i>nothing</i> for URLs that don't fit -- it will not allow you to submit the message. All part of its endearing charm.
<p>
Lame, yes, but it means that the typical, mainstream browser-based Twitter user <b>is forced to become proficient with URL shortening services</b>.  Due to the increased exposure they've enjoyed through Twitter's meteoric rise to fame, the number of URL shortening services has exploded, and rapidly evolved -- they're no longer viewed as utility services to make URLs more convenient, but <b>a way to subjugate, control, and perhaps worst of all, "monetize" the web experience</b>.
<p>
This is dangerous territory we're veering into now, <a href="http://joshua.schachter.org/2009/04/on-url-shorteners.html">as Joshua Schachter explains</a>.
<p>
<blockquote>
So there are clear benefits for both the service (low cost of entry, potentially easy profit) and the linker (the quick rush of popularity). But URL shorteners are bad for the rest of us.
<p>
The worst problem is that shortening services add another layer of indirection to an already creaky system. A regular hyperlink implicates a browser, its DNS resolver, the publisher's DNS server, and the publisher's website. With a shortening service, you're adding something that acts like a third DNS resolver, except one that is assembled out of unvetted PHP and MySQL, without the benevolent oversight of luminaries like Dan Kaminsky and St. Postel.
</blockquote>
<p>
The web is little more than a maze of hyperlinks, and if you can insert yourself as an intermediary in that maze, you can transform or undermine the experience in fundamental ways. Consider the <a href="http://en.wikipedia.org/wiki/URL_shortening#History">disturbing directions newer URL shortening services are taking</a>:
<p>
<ul>
<li>NotifyURL sends an email when the link is first visited.
<li>SnipURL introduces social bookmarking features such as usernames and RSS feeds.
<li>DwarfURL generates statistics.
<li>Adjix, XR.com and Linkbee are ad-supported models of URL shorteners that share the revenue with their users.
<li>bit.ly offers gratis click-through statistics and charts.
<li>Digg offers a shortened URL which includes not just the target URL, but an iframed version that includes a set of Digg-related controls called the Digg bar.
<li>Doiop allows the shortening to be selected by the user, and Unicode can be used to achieve really short URLs.
</ul>
<p>
Believe it: <b>the humble hyperlink, thanks to pervasive URL shortening, can now be wielded as a weapon</b>. The internet is <a href="http://www.codinghorror.com/blog/archives/001132.html">the house that PageRank built</a>, and it's all predicated on hyperlinks. Once you start making every link your special flavor of "shortened" link, framing the target content -- heck, maybe wrapping it in a few ads for good measure -- you've completely turned that system on its head.
<p>
What's aggravating to me is that <b>the current situation is completely accidental</b>. If Twitter had provided a sane way to link a single word, none of these weaselly URL shortening clones would have reared their ugly heads at all. Consider how simple it is to decouple the hyperlink from the display text in, say, phpBB, or Markdown, or even good old HTML markup itself:
<p>
<pre>
&lt;a href="http://example.com"&gt;foo&lt;/a&gt;
[url=http://example.com]foo[/url]
[foo](http://example.com)
</pre>
<p>
Every tiny URL is <b>another baby step towards destroying the web as we know it</b>. Which is exactly what you'd want to do if you're attempting to <a href="http://www.readwriteweb.com/archives/bitly_alternative_to_tinyurl.php">build a business on top of the ruins</a>. Personally, I'd prefer to see the big, objective search engines who naturally sit at the center of the web offer their own URL shortening services. Who better to generate <a href="http://www.codinghorror.com/blog/archives/000935.html">short hashes of every possible URL</a> than the companies who already have cached copies of every URL on the internet, anyway?
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001276.html</guid>
         <pubDate>Tue, 16 Jun 2009 03:08:15 -0800</pubDate>
      </item>

      <item>
         <title>The Wrong Level of Abstraction</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001275.html</link>
         <description><![CDATA[<p>
In <a href="http://www.codinghorror.com/blog/archives/001267.html">Why Isn't My Encryption.. Encrypting?</a> we learned that your encryption is only as good as your <i>understanding</i> of the encryption code. And that the best encryption of all is <i>no</i> encryption, because you kept everything on the server, away from the prying eyes of the client.
<p>
In <a href="http://www.codinghorror.com/blog/archives/001268.html">The Bathroom Wall of Code</a> we learned the potential danger of copy-pasting code from the internet, and the continued importance of regular peer review for every line of code that enters your codebase, from whatever source.
<p>
I didn't anticipate this series becoming a trilogy, but apparently it has, because Thomas Ptacek of Matsano Security <a href="http://www.matasano.com/log/1749/typing-the-letters-a-e-s-into-your-code-youre-doing-it-wrong/">wrote a long blog entry about it</a>. A blog entry masquerading as an overly dramatic college screenplay, but still. These guys, unlike us, are real security experts, so it's worth reading. 
<p>
But you don't have to read that screenplay, because I'm going to reveal the twist in the final act right here. 
<p>
<ol>
<li>The root problem <i>wasn't</i> failing to understand the encryption.
<li>The root problem <i>wasn't</i> copy and pasting code from the internet.
<li>The root problem <i>wasn't</i> failing to peer review the code.
</ol>
<p>
Mr. Ptacek is absolutely right. The root problem was that <b>we were working at the wrong layer of abstraction</b>.
<p>
Rather than construct code from the low-level cryptography primitives provided in .NET, <b>we should have used a library to handle our encryption needs</b>. I'm reminded of a <a href="http://stackoverflow.com/questions/471597/is-jquery-always-the-answer">common Stack Overflow joke</a>:
<p>
<blockquote>
Q: How do I write this in JavaScript?
<p>
A: You don't. You use <a href="http://jquery.com/">JQuery</a>.
</blockquote> 
<p>
You can save a tremendous amount of time and effort by using the browser-independent framework that JQuery has spent untold man-hours testing, debugging, and proving in the field. While there's nothing <i>wrong</i> with writing JavaScript, why not speed your development time by writing to the library instead? As I've always said, <a href="http://www.codinghorror.com/blog/archives/001145.html">don't reinvent the wheel, unless you plan on learning more about wheels</a>.
<p>
Abstractions are important. You could view most of computer programming history as slowly, painfully clawing our way up the evolutionary tree of abstraction -- from assembly language, to C, to Java, to JavaScript, all the way up to JQuery, where the air starts to get pretty darn thin. We've already layered an operating system, web browser, <i>and</i> interpreted scripting language on top of each other to get to this point. It's a <a href="http://www.codinghorror.com/blog/archives/000277.html">testament to the power of abstraction</a> that any of it works at all.
<p>
Getting back to specifics: how can you stop programmers from working at the wrong layer of abstraction? One solution would be to <b>disallow the .NET encryption primitives entirely</b>. This is akin to Steve Gibson's <a href="http://technet.microsoft.com/en-us/library/cc751041.aspx">holy crusade against raw socket programming in Windows XP</a>. That's one way to do it, I suppose. But putting roadblocks in front of programmers is tantamount to a challenge; why not offer them more attractive alternatives, instead?
<p>
Hiding the low-level encryption primitives feels like a temporary solution. That said, I'd <i>strongly</i> recommend marking some of the older encryption methods as <b>deprecated</b>, so programmers who do stumble down some dusty old code path at least have some warning sign that they're using an algorithm with a lot of known vulnerabilities. I'm envisioning a <a href="http://www.codinghorror.com/blog/archives/000424.html">Clippy that pops up</a> with something like:
<p>
<blockquote>
"Hey! It looks like you're using a method of encryption that's widely regarded as insecure by security experts! Would you like to see alternatives?"
</blockquote>
<p>
One of those alternatives would be a full-blown library, perhaps something like <a href="http://www.bouncycastle.org/">Bouncy Castle</a>, or <a href="http://www.keyczar.org/">Keyczar</a>, or <a href="http://www.cs.auckland.ac.nz/~pgut001/cryptlib/">cryptlib</a>. What could be easier than a <code>EncryptStringForBrowser()</code> method which has security and tamper-resistance built in, that's part of a proven, domain-expert-tested set of code that thousands if not millions of developers already rely on?
<p>
Using encryption libraries doesn't mean that crucial encryption mistakes will magically disappear overnight. But these libraries, because they force developers to work at a higher level of abstraction, do make it <i>harder</i> to misuse cryptography. And perhaps more importantly, usability improvements to the library can be better handled by the specialists who created the library, rather than the generalists working on the .NET framework itself.
<p>
So the next time you set out to write code -- not just encryption code, <i>any</i> code -- ask yourself: <b>am I working at the right level of abstraction?</b>
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001275.html</guid>
         <pubDate>Thu, 11 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Regular Expressions for Regular Programmers</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001274.html</link>
         <description><![CDATA[<p>
If you've followed my blog for any length of time, you know that <b>I am a total regular expression fanboy</b>. It's almost <a href="http://www.codinghorror.com/blog/archives/000245.html">embarrassing</a> how much I love the damn things. I'm pretty sure my teammates roll their eyes every time they see yet another class I've touched that has <code>using System.Text.RegularExpressions</code> at the top. You might as well rename it to <code>JeffHasBeenHere</code>.
<p>
I say that because I end up writing a lot of string handling code, even when people <a href="http://www.codinghorror.com/blog/archives/001172.html">tell me I shouldn't</a>. Now, I only advocate <a href="http://www.codinghorror.com/blog/archives/001016.html">responsible and judicious use of regular expressions</a> when you happen to be dealing with strings. In the wrong hands, regular expressions can be dangerous. You might end up wondering <a href="http://www.codinghorror.com/blog/archives/000214.html">if Q*Bert just vomited all over your source code</a>. Or you might be programming in Perl. Is there any difference? (<a href="http://www.instantrimshot.com/">instant rimshot</a>)
<p>
But I digress. Although I love regex, I've never been a fan of the classic regular expression reference book, Friedl's <a href="http://www.amazon.com/dp/0596528124/?tag=codinghorror-20">Mastering Regular Expressions</a>. I found it dry, a bit academic, and lacking in practical real world examples. It just didn't speak to me as a working programmer in the way that regular expressions themselves did, and I found that disappointing.
<p>
That's why I was so excited to discover that two of the gnarliest regex gurus I knew -- <a href="http://www.just-great-software.com/aboutjg.html">Jan Goyvaerts</a> (author of <a href="http://www.regexbuddy.com/cgi-bin/affref.pl?aff=jatwood">RegexBuddy</a> and <a href="http://www.regular-expressions.info/">regular-expressions.info</a>) and <a href="http://blog.stevenlevithan.com/">Steven Levithan</a> (author of <a href="http://blog.stevenlevithan.com/code">XRegExp</a> and <a href="http://regexpal.com/">RegexPal</a>) -- were putting their heads together to create <b>a regular expression reference for the rest of us</b>. I <i>immediately</i> pre-ordered it sight unseen.
<p>
That book is <a href="http://www.amazon.com/dp/0596520689/?tag=codinghorror-20">Regular Expressions Cookbook</a>. It arrived a few days ago, and although my expectations were high, I think this book has exceeded even the loftiest expectations I had. It is <i>outstanding</i>.
<p>
<a href="http://www.amazon.com/dp/0596520689/?tag=codinghorror-20"><img alt="regular-expressions-cookbook.png" src="http://www.codinghorror.com/blog/images/regular-expressions-cookbook.png" width="350" height="459" border="0"  /></a>
<p>
What I love about this book is two things:
<p>
<ol>
<li>It's filled with <b>practical, real world examples of RegEx use</b>. At every step of the way, from beginner to master level, you're building regular expressions that are actually useful in the wild, and not just abstract, obtuse academic exercises in solving string matching puzzles.<br/><br/>
<li>It covers all the <b>common gotchas</b> that you inevitably run into when you start building non-trivial regular expressions. Things like the sometimes massive (and painful) differences between regex libraries in various languages, subtle regex flavor quirks, catastrophic backtracking, unicode support, and so forth. These are all presented in context of the solutions, exactly as you'd encounter them in real programming. I know because I have the scars to prove it.
</ol>
<p>
<a href="http://www.amazon.com/dp/0596520689/?tag=codinghorror-20">Regular Expressions Cookbook </a> manages to be simultaneously accessible and almost <i>ridiculously</i> comprehensive. I consider myself a fairly advanced regex user and about 50 pages in I've already had three big "oh, wow, I didn't realize that" moments. In my mind, at least, this completely replaces the Friedl book as the go-to reference for programmers of any skill level or background who seek regular expression enlightenment.
<p>
Needless to say, <i>recommended</i>.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001274.html</guid>
         <pubDate>Mon, 08 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Unix is Dead, Long Live Unix</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001273.html</link>
         <description><![CDATA[<p>
<a href="http://www.computerworld.com/action/article.do?command=printArticleBasic&taxonomyName=Operating+Systems&articleId=9133570&taxonomyId=89">Unix turns 40: The past, present and future of a revolutionary OS</a> is fascinating reading.
<p>
<blockquote>
Forty years ago this summer, a programmer sat down and knocked out in one month what would become one of the most important pieces of software ever created.
<p>
<img alt="ken-thompson-and-dennis-ritchie.jpg" src="http://www.codinghorror.com/blog/images/ken-thompson-and-dennis-ritchie.jpg" width="311" height="202"  />
<p>
In August 1969, <a href="http://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a> (pictured at left), a programmer at AT&T subsidiary Bell Laboratories, saw the month-long departure of his wife and young son as an opportunity to put his ideas for a new operating system into practice. He wrote the first version of Unix in assembly language for a wimpy Digital Equipment Corp. (DEC) PDP-7 minicomputer, spending one week each on the operating system, a shell, an editor and an assembler.
</blockquote>
<p>
The article is accompanied by <a href="http://commons.wikimedia.org/wiki/File:Unix_history-simple.png">a graph from wikipedia</a>, illustrating the lineage of the Unix family.
<p>
<a href="http://commons.wikimedia.org/wiki/File:Unix_history-simple.png"><img alt="unix-family-tree.png" src="http://www.codinghorror.com/blog/images/unix-family-tree.png" width="720" height="519" border="0" /></a>
<p>
To me, Unix has become synonymous with <a href="http://en.wikipedia.org/wiki/Linux">Linux</a>, and the open source movement in general. The last *nixes standing shake out as follows:
<p>
<table width="500">
<tr><td><b>Open Source</b><td><b>Mixed / Shared Source</b><td><b>Closed Source</b></tr>
<tr>
<td valign="top">
Minix<br/>
Linux<br/>
FreeBSD<br/>
NetBSD<br/>
OpenBSD<br/>
OpenSolaris
<td valign="top">
Mac OS X
<td valign="top">
AIX<br/>
OpenServer<br/>
HP/UX
</tr>
</table>
<p>
I didn't realize there were that many closed source Unix variants still surviving in the wild. It's also odd how OS X brings us full circle with the original Unics and BSD licensing. If it's lonely in the "Closed" column, imagine the existential angst of being the only vendor in the "Mixed / Shared Source" column. (NB: I think the currently tiny category Apple occupies represents the future of commercial software, but that's a topic for another blog post.)
<p>
I've been primarily a Windows developer since the early 90s, but over time, <b>I've developed a grudging <a href="http://www.codinghorror.com/blog/archives/001046.html">respect</a> for Unix</b>. I think Michael Feathers <a href="http://beautifulcode.oreillynet.com/2008/01/on_loving_c.php">summarized it best</a>:
<p>
<blockquote>
There's something deep in software development that not everyone gets but the people at Bell Labs did. It's the undercurrent of "the New Jersey Style", "Worse is Better", and "the Unix philosophy" - and it's not just a feature of Bell Labs software either. You see it in the original Ethernet specification where packet collision was considered normal.. and the same sort of idea is deep in the internet protocol. It's deep awareness of design ramification - <b>a willingness to live with a little less to avoid the bigger mess and a willingness to see elegance in the real rather than the vision</b>. 
</blockquote>
<p>
I find this to be deeply and profoundly true in everything I've ever worked on as a programmer, and to the extent that Unix reflects these philosophies, it is undeniably on the right path. Unlike Rich Skrenta, <a href="http://www.skrenta.com/2007/05/giving_up_on_microsoft.html">I didn't grow up as a Unix developer</a>, so I have come late in life to this appreciation. Joel Spolsky's take on the Unix / Windows divide, after reading <a href="http://www.amazon.com/dp/0131429019/?tag=codinghorror-20">The Art of UNIX Programming</a>, is <a href="http://www.joelonsoftware.com/articles/Biculturalism.html">this</a>:
<p>
<blockquote>
What are the cultural differences between Unix and Windows programmers? There are many details and subtleties, but for the most part it comes down to one thing: Unix culture values code which is useful to other programmers, while Windows culture values code which is useful to non-programmers. This is, of course, a major simplification, but really, that's the big difference: are we programming for programmers or end users? Everything else is commentary.
</blockquote>
<p>
So on one side, you have hundreds of command line applications, built in wildly different styles, with thousands of arcane command line parameters, all of which can be flexibly combined together to accomplish almost anything. And on the other side, you have the <a href="http://www.codinghorror.com/blog/archives/000939.html">windows registry</a> and <a href="http://en.wikipedia.org/wiki/Microsoft_Foundation_Class_Library">MFC</a>.
<p>
Sometimes, <a href="http://www.codinghorror.com/blog/archives/000796.html">you just can't win</a>.
<p>
So, yes, I'm a fan of Unix. And I'm also a fan of Windows. I think it's worth studying what both are getting right and wrong, because as a programmer, I'm a fan of whatever the heck <i>works</i>.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile" rel="nofollow">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001273.html</guid>
         <pubDate>Sun, 07 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>Sharing Files With BitTorrent</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001272.html</link>
         <description><![CDATA[<p>
<a href="http://www.codinghorror.com/blog/archives/000795.html">Everybody loves BitTorrent</a>. And rightfully so.
<p>
<blockquote>
With <a href="http://en.wikipedia.org/wiki/BitTorrent">BitTorrent</a>, you also start by placing your large file on a central server. But once the downloading begins, something magical happens: as clients download the file, they share whatever parts of the file they have with each other. Clients can opportunistically connect with any other client to obtain multiple parts of the file at once. And it scales perfectly: as file size and audience size increases, the bandwidth of the BitTorrent distribution network also increases. Your server does less and less work with each connected client. It's an elegant, egalitarian way of sharing large files with large audiences.
<p>
BitTorrent radically shifts the economics of distribution. It's one of the most miraculous ideas ever conceived on the internet. As far as I'm concerned, there should be a Nobel prize for computing, and <a href="http://en.wikipedia.org/wiki/Bram_Cohen">the inventor of BitTorrent</a> should be its first recipient. 
</blockquote>
<p>
I've been a happy <a href="http://www.codinghorror.com/blog/archives/000978.html">consumer of files distributed via BitTorrent</a> for years; it was only natural that I would turn to BitTorrent to distribute our cc-wiki licensed Stack Overflow data. I figured serving a several-hundred megabyte file with BitTorrent wouldn't be much harder than downloading one. Boy, was I ever wrong. <b>Sharing files with BitTorrent is <i>way</i> more complicated than downloading them!</b> After two frustrating hours, I finally came up with a relatively straightforward way to share a file via BitTorrent, and in the interests of saving future readers a little time, I'm documenting it here.
<p>
Now, I'm going to show you an easy way, but it isn't technically the <i>easiest</i> way. The easiest way is to let someone else do the sharing for you. If you own content that you want to share, <a href="http://legaltorrents.com/">LegalTorrents is the obvious choice</a>:
<p>
<blockquote>
LegalTorrents<sup>tm</sup> is an online digital media community.
<p>
We discover and distribute high quality open-license (Creative Commons) digital media and art, and provide support to Content Creators. We host creative content in its entirety, ensure fast, reliable downloads, and enable users to directly sponsor Content Creators and their work.
<p>
We distribute content with the full permission of the rights holders and use the peer-2-peer file-sharing technology called Bittorrent. 
</blockquote>
<p>
The site is still in beta, but signup is a snap, because <a href="http://www.codinghorror.com/blog/archives/001121.html">they support OpenID</a>! I encourage anyone interested to check it out. If nothing else, <b>get the furtive thrill of actually downloading <i>legal</i> content through BitTorrent for once!</b> Yes, it can happen. Shocking, I know. Don't worry, you crazy kids can get right back to your regular non-copyright-respecting torrenting ways immediately afterwards.
<p>
Anyway, you can't start sharing files on LegalTorrents without some kind of special email-us-please permission, and I was in a hurry. I wanted to share files via BitTorrent <i>right now</i>. I did, and you can too! But you'll need a few things first:
<p>
<ol>
<li>A copy of <a href="http://www.utorrent.com/">uTorrent</a> (it's free!)<br/>
<br/>
<li>Your <b>external IP address</b>; if you don't know what it is, use <a href="http://www.whatismyipaddress.com/">http://www.whatismyipaddress.com</a> to find out.<br/>
<br/>
<li>The uTorrent <b>listen port</b>. This is under Options | Preferences | Connection. This is typically set randomly every time uTorrent starts, so you may want to specify a more memorable value here.<br/>
<br/>
<li>You must have <b>port forwarding properly configured</b> so the outside world can get to your IP address and the port specified above. A full discussion of how to do this is outside the scope of this post, but it usually starts with your firewall settings and/or router configuration. uTorrent has a fairly nice help page at Options | Speed Guide that's a good start; just click the <b>Test if port is forwarded properly</b> button on that dialog to begin.
</ol>
<p>
Here's where I hit a major roadblock: to share files via BitTorrent, <a href="http://en.wikipedia.org/wiki/BitTorrent_tracker">you need a tracker</a>. 
<p>
<blockquote>
A BitTorrent tracker is a server that assists in the communication between peers using the BitTorrent protocol. It is also, in the absence of extensions to the original protocol, the only major critical point, as <b>clients are required to communicate with the tracker to initiate downloads</b>. Clients that have already begun downloading also communicate with the tracker periodically to negotiate with newer peers and provide statistics; however, after the initial reception of peer data, peer communication can continue without a tracker.
</blockquote>
<p>
Without a tracker, you're sort of hosed, as clients will never be able to find your file, much less each other. Unfortunately, most of the freely open, public trackers out there are sort of.. disreputable. And the LegalTorrents tracker won't track files unless they are on its creator whitelist, which involves that manual sign-up process. You've got precious few legit options for tracking, unless you're willing to take a trip to the wrong side of town, and associate yourself and your files with that kind of .. neighborhood. I wasn't.
<p>
Fortunately, uTorrent has a solution: <b>you can become your own tracker!</b>
<p>
<ol>
<li>in uTorrent, go to Options | Preferences | Advanced. 
<li>Scroll down to <code>bt.enable_tracker</code> and set it to <code>True</code>
<li>Restart uTorrent.
</ol>
<p>
<img alt="utorrent-enable-tracker-advanced-options.png" src="http://www.codinghorror.com/blog/images/utorrent-enable-tracker-advanced-options.png" width="505" height="392"  />
<p>
Now, let's create the torrent for the file we want to host, which will point to our newly created tracker.
<p>
<ol>
<li>In uTorrent, click the Create New Torrent button.
<li>Select the file or directory you want to share.
<li>Enter your tracker in this format: <b>http://my-ip-address:my-port/announce</b>
<li>That's it! Click Create and save the new *.torrent file you've created.
</ol>
<p>
<img alt="create-new-torrent-self-tracker.png" src="http://www.codinghorror.com/blog/images/create-new-torrent-self-tracker.png" width="481" height="557" />
<p>
Now go forth and share your *.torrent file with the world. Share it with anyone and everyone! The more the merrier! Any client that opens your *.torrent file <b>will attempt to connect to <i>your</i> tracker, download your file, and share it with other downloading clients in classic BitTorrent stylee</b>. Pat yourself on the back; you just shared a file with the world using the transformative distribution power of BitTorrent! 
<p>
But you do have to keep uTorrent running as a desktop application all the time, which is sort of a bummer. What if you wanted to <b>share your file on a server</b>, or via a silent background process? No problem. It's just a few more steps:
<p>
<ol>
<li>Enable the uTorrent web interface under Preferences, Web UI. Note that the URL for it is, by default, <b>http://my-ip-address:my-port/gui/</b>, and it requires a username and password to be set here.<br/>
<br/>
<li>Obtain a copy of the <a href="http://support.microsoft.com/kb/137890">user-defined service utilities</a>, srvany.exe and instsrv.exe. Copy them to the same folder as uTorrent.exe.<br/>
<br/>
<li>Issue this command to make uTorrent run as a service:<br/>
<br/>
<pre>instsrv uTorrent "C:\uTorrent\srvany.exe"</pre>
<br/>
<li>Enter this registry file to set the path for the service named "uTorrent" you just created in the previous step:<br/>
<br/>
<pre>
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\uTorrent\Parameters]
"Application"="C:\\uTorrent\\uTorrent.exe"
</pre>
<br/>
<li>In Control Panel, Services, set the account that the uTorrent service will run under. Note that you must use the <i>same</i> account that you set uTorrent options with if you want the service to respect those settings, so plan accordingly.<br/>
<br/>
<img alt="utorrent-service-account-log-on.png" src="http://www.codinghorror.com/blog/images/utorrent-service-account-log-on.png" width="454" height="296" style="" />
<br/>
<br/>
<li>Start the uTorrent service.
</ol>
<p>
(Obviously, replace the above paths with the actual paths that you installed uTorrent to.)
<p>
Bam -- you're sharing files with the world using BitTorrent, even when you're not logged in.  You can control everything remotely, too, by navigating your browser to the WebUI URL.
<p>
Like so many things in Windows, it ain't pretty, but it gets the job done. It's ironic that BitTorrent, which is justly famous for equalizing the highly asymmetric nature of most people's internet connections, is itself so asymmetric when it comes to sharing: <b>trivially easy to consume, but awkward and confusing to share</b>. That's too bad, because BitTorrent is such a powerful tool for sharing. Hopefully this post demystifies the process a bit!
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Interested in <a href="http://www.atlassian.com/agile">agile</a>? See how a world-leading software vendor is practicing <a href="http://www.atlassian.com/agile">agile</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001272.html</guid>
         <pubDate>Wed, 03 Jun 2009 23:59:59 -0800</pubDate>
      </item>

      <item>
         <title>I Stopped Reading Your Blog Years Ago</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001271.html</link>
         <description><![CDATA[<p>
<a href="http://emrahdiril.com/">Emrah Diril</a> recently asked me this via email:
<p>
<blockquote>
Steve Yegge <a href="http://steve-yegge.blogspot.com/2009/05/programmers-view-of-universe-part-3.html">mentioned in the comments of his last post</a> that he gets quite a bit of hate directed his way.
<p>
<blockquote>
<i>Fake51: you underestimate the ability of people to get mad. Some people start mad and just take it out on you. The hating has gradually become a little too much for me.</i>
</blockquote>
<p>
I read the guy's blog too, but don't understand where this is coming from. Some people just have this tendency I suppose.
<p>
Do you have a similar experience? I don't see you wanting to quit blogging, so how do you deal with this? Is it just a matter of personality? Are you better able to ignore this stuff?
</blockquote>
<p>
I answered with one of my favorite quotes from <a href="http://download.srv.cs.cmu.edu/~pausch/">Randy Pausch's</a> </a><a href="http://www.youtube.com/watch?v=ji5_MqicxSo">Last Lecture</a>:
<p>
<blockquote>
And when it was all over, one of the other assistant coaches came over and said, yeah, Coach Graham rode you pretty hard, didn't he? I said, yeah. He said, that's a good thing. He said, when you're screwing up and nobody's saying anything to you anymore, that means they gave up. And that's a lesson that stuck with me my whole life: <b>when you see yourself doing something badly and nobody's bothering to tell you anymore, that's a very bad place to be. Your critics are your ones telling you they still love you and care.</b>
</blockquote>
<p>
Welcoming and appreciating reasonable criticism is the right attitude to have, but it's not the full story. Do I <i>love</i> criticism? Do I <i>seek it out?</i> No. I have many personality deficiencies, but masochism isn't one of them. I don't have fantasies of waking up every day to an <a href="http://www.google.com/search?q=r.+lee+ermey+doll">R. Lee Ermey</a> browbeating from commenters. Or, maybe I do. I should blog about that.
<p>
<a href="http://www.nytimes.com/imagepages/2007/04/04/opinion/05opart.html">
<img alt="diagram-of-a-blog.png" src="http://www.codinghorror.com/blog/images/diagram-of-a-blog.png" width="497" height="589" border="0" /></a>
<p>
Criticism, painful though it may be, is still a conversation. It means your readers and listeners are engaging with you, and <b>there's something to learn from following that conversation</b>. Those messages you're broadcasting out into the world are being received, in some form, by someone on the planet. Even if that person is, well .. this guy:
<p>
<blockquote>
<b>I stopped reading the blog a while a go.</b> Joel explains my reasoning nicely in <a href="http://www.joelonsoftware.com/items/2008/11/18.html">his latest post</a>.
</blockquote>
<p>
The mystery of the non-reading Coding Horror reader. Another NP-complete problem, I guess.
<p>
If you think something sucks to the extent that it's actively harming the world and you want it to go away, leaving comments to that effect is not the way. I know, because I bear the psychic scars of a million online flamewars, dating all the way back to 300 baud dualup modems and BBSes. I've been doing this a very long time. I've seen what works, and what doesn't.
<p>
I'm here to tell you that <b>there is something much more powerful than criticism</b> that you can bring to bear in these situations. Something <a href="http://kottke.org/08/07/just-dont-look">almost unimaginably powerful in its ability to shape human behavior</a>.
<p>
<blockquote>
The "just don't look" strategy [is] effective in any situation where someone or something runs on attention. On the web attention comes in the form of links and pageviews so "just don't look" translates roughly into "just don't link or read". If you don't like who's on the cover of Wired, just don't look. If no one talks about her, she'll go away. Think media gossip sites are ruining the web? Don't read them. Leggy blonde conservative got your knickers in a knot? Just don't look. Commenters ruining the internet? Moderate your comments or close them up. If some Web 2.0 blowhard says something stupid, just don't look. Hate blonde socialites? Just. Don't. Look.
</blockquote>
<p>
I am absolutely sick to death of hearing about Susan Boyle, both in the traditional media and online. Nothing personal, you understand, I'm sure she's a perfectly lovely person. But I don't talk about Susan Boyle, because talking about her gives Susan Boyle power and currency. I just ignore Susan Boyle. I wish I had two brains so I could ignore her twice as hard. <b>I. Just. Don't. Look.</b> And if we could convince enough people to ignore her, she .. <i>disappears</i>. Poof. Like magic.
<p>
One of my favorite books as a child was <a href="http://en.wikipedia.org/wiki/The_Great_Brain">the Great Brain series</a>, the story of a family in rural Utah, set in the late 1800s. In these books, there was a strange punishment the parents doled out to their children when they seriously misbehaved. For a period of a week, or longer -- depending on the severity of the misbehavior -- nobody in the family would talk to, acknowledge, or address in any way, that particular boy. It was called <b>"The Silent Treatment"</b>. This didn't seem like much of a punishment to me. In fact, as an introverted kid who loved solitary activities like computers and reading more than anything, it seemed kind of like a .. <i>reward</i>. I couldn't reconcile this feeling with the semi-biographical reality depicted in the books. To the Fitzgerald boys, the silent treatment was the worst possible punishment, far worse than a physical beating. They would go to incredible lengths to avoid getting the silent treatment. As punishments go, it must have been a doozy, though I couldn't quite wrap my geeky, socially maladjusted young head around exactly why.
<p>
The silent treatment was a punishment I didn't fully understand until years later in life. <i>That's</i> how you change the world. Not by arguing with people. Certainly not by screaming at them. You do it <b>by ignoring them.</b>
<p>
And if you feel strongly enough about me and what I do here, you can begin by ignoring this.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Improve Your <a href="http://www.atlassian.com/software/fisheye/?s_kwcid=codefish" rel="nofollow">Source Code Management</a> using Atlassian Fisheye - Monitor. Search. Share. Analyze. <a href="http://www.atlassian.com/software/fisheye/?s_kwcid=codefish" rel="nofollow">Try it for free!</a>
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001271.html</guid>
         <pubDate>Tue, 02 Jun 2009 05:33:18 -0800</pubDate>
      </item>

      <item>
         <title>The Girl Who Proved P = NP</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001270.html</link>
         <description><![CDATA[<p>
One of my all time favorite blog entries is a truly epic tale of dating gone wrong that culminates in <a href="http://www.joeydevilla.com/2003/04/07/what-happened-to-me-and-the-new-girl-or-the-girl-who-cried-webmaster/">the strangest reference to P=NP you'll probably ever encounter</a>.
<p>
<blockquote>
<b>Joey</b>: So you really did graduate from computer engineering?
<p>
<b>New Girl</b>: Yes I did, from UBC!
<p>
<b>Joey</b>: And you took the "Algorithms" course?
<p>
<b>New Girl</b>: Of course!
<p>
<b>Joey</b>: And you have all the papers you wrote?
<p>
<b>New Girl</b>: <i>Yes!</i> I kept them all, and I'll show them to you tomorrow!
<p>
<b>Joey</b>: I want to see the one we always called the "Hell Paper" at Queen's -- the mandatory fourth-year paper. You know the one, where we prove P = NP?
<p>
<b>New Girl</b>: <font color="maroon">I did that! I proved P = NP!</font> I placed near the top of the class, and the professor used my paper as an example!
<p>
<b>Joey</b>: You proved P = NP?
<p>
<b>New Girl</b>: Yes!
<p>
<b>Joey</b>: Gotcha.
</blockquote>
<p>
Poor Joey. Dating crazy people is one thing, but dating crazy people who <i>claim to have proved P=NP</i> is another matter entirely. I know, I know, <a href="http://www.codinghorror.com/blog/archives/001187.html">my track record with P=NP</a> is hardly any better. But at least you're not dating me, right?
<p>
NP completeness is <a href="http://www.claymath.org/millennium/P_vs_NP/">one of the great unsolved mysteries in computer science</a>; perhaps the best way to illustrate is through <a href="http://xkcd.com/287/">this xkcd cartoon</a>:
<p>
<img alt="np_complete.png" src="http://www.codinghorror.com/blog/images/np_complete.png" width="640" height="340" />
<p>
The defining characteristic of an NP-complete problem is that optimal solutions, using math and logic as we currently understand them, are effectively impossible. Sure, you can <a href="http://www.codinghorror.com/blog/archives/001187.html">approximate a solution</a>, but an <i>optimal</i> solution requires so many calculations as to be infeasible, even with computers that operated at, say .. the speed of light.
<p>
<blockquote>
In fact, one of the outstanding problems in computer science is determining whether questions exist whose answer can be quickly checked, but which require an impossibly long time to solve by any direct procedure. Problems like the one listed above certainly seem to be of this kind, but so far no one has managed to prove that any of them really are so hard as they appear, <b>i.e., that there really is no feasible way to generate an answer with the help of a computer.</b>
</blockquote>
<p>
It's doubtful <a href="http://www.cs.umd.edu/~gasarch/papers/poll.pdf">whether anyone will ever prove that P=NP</a> (pdf), but in the meantime it's useful to <a href="http://max.cs.kzoo.edu/~kschultz/CS510/ClassPresentations/NPCartoons.html">recognize problems that are NP complete</a>:
<p>
<blockquote>
 Unfortunately, proving inherent intractibility can be just as hard as finding efficient algorithms.
<p>
The theory of NP-completeness provides many straightforward techniques for proving that a given problem is "just as hard" as a large number of other problems that are widely recognize as being difficult and that have been confounding the experts for years. Armed with these techniques, you might be able to prove that the bandersnatch problem is NP-complete and march into your boss's office and announce:
<p>
<img alt="np-complete-cartoon.png" src="http://www.codinghorror.com/blog/images/np-complete-cartoon.png" width="352" height="224" />
<p>
<i>I can't find an efficient algorithm, but neither can all these famous people.</i>
<p>
At the very least, this would inform your boss that it would do no good to fire you and hire another expert on algorithms.
<p>
Now you can spend your time looking for efficient algorithms that solve various special cases of the general problem. You might look for algorithms that, though not guaranteed to run quickly, seem likely to do so most of the time. Or you might even relax the problem somewhat, looking for a fast algorithm that merely finds designs that meet most of the component specifications. Thus, the primary application of the theory of NP-completeness is to assist algorithm designers in directing their problem-solving efforts toward those approaches that have the greatest likelihood of leading to useful algorithms. 
</blockquote>
<p>
As with so many things in programming, <b>the first step is learning enough to know when you're <i>really</i> screwed</b>.
<p>
Unfortunately for poor Joey, this sad corollary to NP-completeness apparently applies to dating, too.
<p>
<table>
<tr><td class="welovecodinghorror">
[advertisement] Improve Your <a href="http://www.atlassian.com/software/fisheye/?s_kwcid=codefish" rel="nofollow">Source Code Management</a> using Atlassian Fisheye - Monitor. Search. Share. Analyze. <a href="http://www.atlassian.com/software/fisheye/?s_kwcid=codefish" rel="nofollow">Try it for free!</a>
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001270.html</guid>
         <pubDate>Mon, 01 Jun 2009 04:26:30 -0800</pubDate>
      </item>

   </channel>
</rss>
