<?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>Thu, 24 Jul 2008 17:00:00 -0800</lastBuildDate>
      <pubDate>Thu, 24 Jul 2008 17:00:00 -0800</pubDate>
      <generator>http://www.movabletype.org/?v=2.661</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" /><item>
         <title>Coding Without Comments</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001150.html</link>
         <description><![CDATA[<p>
If peppering your code with lots of comments is good, then having <b>zillions of comments</b> in your code must be <i>great</i>, right? Not quite. Excess is one way <a href="http://www.codinghorror.com/blog/archives/000130.html">good comments go bad</a>:
<p>
<pre>
'*************************************************
' Name: CopyString
'
' Purpose: This routine copies a string from the source
' string (source) to the target string (target).
'
' Algorithm: It gets the length of "source" and then copies each
' character, one at a time, into "target". It uses
' the loop index as an array index into both "source"
' and "target" and increments the loop/array index
' after each character is copied.
'
' Inputs: input The string to be copied
'
' Outputs: output The string to receive the copy of "input"
'
' Interface Assumptions: None
'
' Modification History: None
'
' Author: Dwight K. Coder
' Date Created: 10/1/04
' Phone: (555) 222-2255
' SSN: 111-22-3333
' Eye Color: Green
' Maiden Name: None
' Blood Type: AB-
' Mother's Maiden Name: None
' Favorite Car: <a href="http://www.codinghorror.com/blog/archives/000321.html">Pontiac Aztek</a>
' Personalized License Plate: "Tek-ie"
'*************************************************
</pre>
<p>
I'm constantly running across comments from developers who don't seem to understand that the code is already there to tell us how it works; <a href="http://www.codinghorror.com/blog/archives/000749.html">we need the comments to tell us <i>why</i> it works.</a> Code comments are so widely misunderstood and abused that you might find yourself wondering if they're worth using at all. Be careful what you wish for. Here's some code with <b>no comments whatsoever</b>:
<p>
<pre>
r = n / 2;
while ( abs( r - (n/r) ) &gt; t ) {
  r = 0.5 * ( r + (n/r) );
}
System.out.println( "r = " + r );
</pre>
<p>
Any idea what that bit of code does? It's perfectly readable, but <i>what the heck does it do?</i>
<p>
Let's add a comment.
<p>
<pre>
// square root of n with Newton-Raphson approximation
r = n / 2;
while ( abs( r - (n/r) ) &gt; t ) {
  r = 0.5 * ( r + (n/r) );
}
System.out.println( "r = " + r );
</pre>
<p>
That must be what I was getting at, right? Some sort of pleasant, middle-of-the-road compromise between the two polar extremes of no comments whatsoever and carefully formatted epic poems every second line of code? 
<p>
Not exactly. Rather than add a comment, I'd refactor to this:
<p>
<pre>
private double SquareRootApproximation(n) {
  r = n / 2;
  while ( abs( r - (n/r) ) &gt; t ) {
    r = 0.5 * ( r + (n/r) );
  }
  return r;
}
System.out.println( "r = " + SquareRootApproximation(r) );
</pre>
<p>
I haven't added a single comment, and yet this mysterious bit of code is now perfectly understandable.
<p>
While comments are neither inherently good or bad, they are frequently used as a crutch. <b>You should always write your code as if comments didn't exist.</b> This <i>forces</i> you to write your code in the simplest, plainest, most self-documenting way you can humanly come up with.
<p>
When you've rewritten, refactored, and rearchitected your code a dozen times to make it easy for your fellow developers to read and understand -- when you can't possibly imagine any conceivable way your code could be changed to become more straightforward and obvious -- then, and <i>only then</i>, should you feel compelled to add a comment explaining what your code does.
<p>
As <a href="http://steve-yegge.blogspot.com/2008/02/portrait-of-n00b.html">Steve points out</a>, this is one key difference between junior and senior developers:
<p>
<blockquote>
In the old days, seeing too much code at once quite frankly exceeded my complexity threshold, and when I had to work with it I'd typically try to rewrite it or at least comment it heavily. Today, however, I just slog through it without complaining (much). When I have a specific goal in mind and a complicated piece of code to write, I spend my time making it happen rather than telling myself stories about it [in comments].
</blockquote>
<p>
Junior developers rely on comments to tell the story when they should be relying on the <i>code</i> to tell the story. Comments are narrative asides; important in their own way, but in no way meant to replace plot, characterization, and setting.
<p>
Perhaps that's the dirty little secret of code comments: <b>to write good comments you have to be a good writer</b>. Comments aren't code meant for the compiler, they're words meant to communicate ideas to other human beings. While I do (mostly) love my fellow programmers, I can't say that effective communication with other human beings is exactly our strong suit. I've seen three-paragraph emails from developers on my teams that practically melted my brain. <i>These</i> are the people we're trusting to write clear, understandable comments in our code? I think maybe some of us might be better off sticking to our strengths -- that is, writing for the compiler, in as clear a way as we possibly can, and reaching for the comments only as a method of last resort.
<p>
Writing good, meaningful comments is hard. It's as much an art as writing the code itself; maybe even more so. As Sammy Larbi said in <a href="http://www.codeodor.com/index.cfm/2008/6/18/Common-Excuses-Used-To-Comment-Code-and-What-To-Do-About-Them/2293">Common Excuses Used To Comment Code</a>, if your feel your code is too complex to understand <i>without</i> comments, <b>your code is probably just bad.</b> Rewrite it until it doesn't need comments any more. If, at the end of that effort, you still feel comments are necessary, then by all means, add comments. Carefully.
<p>
It's OK to end up with comments in your code, but never, ever <i>start</i> with comments.
<p>
<table><tr><td class="sidead">
[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning <a href="http://smartbear.com/codecollab.php?chblog1" rel="nofollow">Code Collaborator</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001150.html</guid>
         <pubDate>Thu, 24 Jul 2008 17:00:00 -0800</pubDate>
      </item>
      <item>
         <title>Building Tiny, Ultra Low Power PCs</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001156.html</link>
         <description><![CDATA[<p>
In previous posts, I've talked about <a href="http://www.codinghorror.com/blog/archives/000905.html">building your own desktop PC</a>, and <a href="http://www.codinghorror.com/blog/archives/001107.html">building your own home theater PC</a>. I'm still very much in love with that little HTPC I built. Not only does it have a modern dual-core CPU, and fantastic high-definition capable integrated video -- it's an outstanding general purpose media sharing server, too. But the real punchline is that I eventually got that box down to <b>an insanely low 44 watts at idle</b>. That's <a href="http://www.codinghorror.com/blog/archives/001099.html">in the ballpark</a> for a powerful laptop, and far better than your garden variety desktop PC, which will draw <a href="http://www.codinghorror.com/blog/archives/000353.html">somewhere between 100 to 200 watts of power</a>.
<p>
44 watts is impressive, but what if you want to build a PC that uses even less power -- radically less?
<p>
That's when you turn to something like AMD's Geode platform <a href="http://www.codinghorror.com/blog/archives/000482.html">in the Nano-ITX form factor</a>. It uses <b><font color="red">five watts</font> of power at idle</b>. That's almost <i>ten times less</i> than my HTPC build I was so proud of!
<p>
<a href="http://www.dpbolvw.net/click-2338938-10440897?url=http%3A%2F%2Fwww.newegg.com%2FProduct%2FProduct.aspx%3FItem%3DN82E16813153096%26nm_mc%3DAFC-C8Junction%26cm_mmc%3DAFC-C8Junction-_-Motherboard%2B%2F%2BCPU%2B%2F%2BVGA%2BSets-_-JETWAY-_-13153096&cjsku=N82E16813153096"><img alt="Nano-ITX motherboard" src="http://www.codinghorror.com/blog/images/nanoitx-motherboard.jpg" width="550" height="590" border="0" /></a>
<p>
This is the <a href="http://www.dpbolvw.net/click-2338938-10440897?url=http%3A%2F%2Fwww.newegg.com%2FProduct%2FProduct.aspx%3FItem%3DN82E16813153096%26nm_mc%3DAFC-C8Junction%26cm_mmc%3DAFC-C8Junction-_-Motherboard%2B%2F%2BCPU%2B%2F%2BVGA%2BSets-_-JETWAY-_-13153096&cjsku=N82E16813153096">JetWay J8F9 AMD Geode LX800 motherboard</a>. I can't say "this is actual size" with a straight face without knowing the size and aspect ratio of your monitor, but it's probably darn close. The actual dimensions are just under five inches on each side. It may not look like much, but consider the specs: 
<p>
<ul>
<li>500 Mhz <a href="http://en.wikipedia.org/wiki/Geode_(processor)">AMD x86 Geode</a> LX 800 CPU
<li>200 pin SO-DIMM memory slot, 1 GB DDR-400 max
<li>Two ATA-100 drive connections
<li>mini-PCI expansion slot
<li>CompactFlash memory card slot
<li>onboard audio / VGA / fast ethernet / USB
</ul>
<p>
This thing is, for all intents and purposes, <b>a complete, standalone x86 PC that fits in the palm of your hand and sips five watts of power</b>. Well, assuming you have an enormous hand. 
<p>
You will need memory and a storage device, of course. You could pick up a laptop hard drive, but another clever thing about this board is that it allows you to use a cheap CompactFlash card as your storage medium -- for the optimal low power, no moving parts install.
<p>
<ol>
<li><a href="http://www.dpbolvw.net/click-2338938-10440897?url=http%3A%2F%2Fwww.newegg.com%2FProduct%2FProduct.aspx%3FItem%3DN82E16813153096%26nm_mc%3DAFC-C8Junction%26cm_mmc%3DAFC-C8Junction-_-Motherboard%2B%2F%2BCPU%2B%2F%2BVGA%2BSets-_-JETWAY-_-13153096&cjsku=N82E16813153096">AMD Geode LX 800 Nano ITX Motherboard/CPU Combo</a> $154
<li><a href="http://www.tkqlhce.com/click-2338938-10440897?url=http%3A%2F%2Fwww.newegg.com%2FProduct%2FProduct.aspx%3FItem%3DN82E16820231045%26nm_mc%3DAFC-C8Junction%26cm_mmc%3DAFC-C8Junction-_-Memory%2B%28Notebook%2BMemory%29-_-G.SKILL-_-20231045&cjsku=N82E16820231045">512MB 200-pin SO-DIMM DDR-400</a> $20
<li><a href="http://www.dpbolvw.net/click-2338938-10440897?url=http%3A%2F%2Fwww.newegg.com%2FProduct%2FProduct.aspx%3FItem%3DN82E16820211191%26nm_mc%3DAFC-C8Junction%26cm_mmc%3DAFC-C8Junction-_-Memory%2B%28Flash%2BMemory%29-_-A-DATA-_-20211191&cjsku=N82E16820211191">4GB compact flash card</a> $14
<li><a href="http://www.trcelectronics.com/Phihong/psa-15r-120p.shtml">12vdc AC/DC external wall wart</a> $18
</ol>
<p>
So we can put together our own tiny utility PC for right at 200 bucks. Not bad. Unbox it, snap in the memory and CF card, plug in the wall wart, and you're ready to install and boot your operating system of choice. It's that simple.
<p>
Naturally, <b>you won't get barn-burning performance</b>, but if you remember the Pentium II 300 Mhz systems of yesteryear, you'll know what to expect. You may recall those now-ancient boxes were still able to do some pretty amazing things in their day. I would not build an ultra-lower power PC assuming it will be tolerable for day-to-day web browsing and email reading, unless you're comfortable using text mode or command-line interfaces exclusively.
<p>
This must be a market segment JetWay specializes in; they have <a href="http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&N=50001521&Description=mini-itx&name=JETWAY">a surprisingly large number of Mini-ITX motherboards</a> to choose from. I don't think you'll find anything more power-efficient than the Geode LX 800 model, though, but there are some lesser expensive choices that get close. Lots of variety!
<p>
If the 5" x 5" profile of the Nano-ITX is far too large for your tastes, <a href="http://www.mini-itx.com/reviews/pico-itx/default.asp?page=4">how do you feel about Pico-ITX?</a> It's even smaller at 10cm x 7.2cm.
<p>
<a href="http://www.mini-itx.com/reviews/pico-itx/default.asp?page=1"><img alt="picoitx-epia-px10000.jpg" src="http://www.codinghorror.com/blog/images/picoitx-epia-px10000.jpg" width="400" height="243" border="0" /></a>
<p>
I've been following the ultra low power, tiny form factor PC segment for quite a few years now. With the emergence of <a href="http://en.wikipedia.org/wiki/Silverthorne_(CPU)">Intel's Atom</a> and <a href="http://en.wikipedia.org/wiki/Netbook">"netbooks"</a> like the ASUS Eee, it's a segment that is dangerously close to becoming mainstream. If you're interested, <a href="http://www.mini-itx.com/">mini-itx.com</a> is still one of the best sources of hands-on reviews, information, and community projects. It's fun stuff. 
<p>
What could <i>you</i> do with a tiny, highly efficient x86 PC that boots up in under a minute? 
<p>
<table><tr><td class="sidead">
[advertisement] Peer code review without meetings, paperwork, or stopwatches?  No wonder <a href="http://smartbear.com/codecollab.php?chblog4">Code Collaborator</a> won the Jolt Award.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001156.html</guid>
         <pubDate>Tue, 22 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Web Development as Tag Soup</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001155.html</link>
         <description><![CDATA[<p>
As we work with <a href="http://www.asp.net/mvc/">ASP.NET MVC</a> on Stack Overflow, I find myself violently thrust back into the bad old days of tag soup that I remember from my tenure as a classic ASP developer in the late 90's. If you're not careful bordering on manically fastidious in constructing your Views, you'll end up with <b>a giant mish-mash of HTML, Javascript, and server-side code</b>. Classic tag soup; difficult to read, difficult to maintain.
<p>
I don't mean tag soup in the sense of <a href="http://en.wikipedia.org/wiki/Tag_soup">badly formed HTML</a>, or the <a href="http://www.codinghorror.com/blog/archives/000723.html">malformed world</a> we live in. I mean tag soup in the sense of <b>mixing HTML markup and server-side code</b>. Now you can double your pleasure: badly formed HTML, meet badly written code.
<p>
The tag soup problem seems to be <b>endemic to all modern web development stacks</b>. I see that Ruby on Rails apps have the same problem; here's a slice of representative <a href="http://wiki.rubyonrails.org/rails/pages/UnderstandingViews">RHTML</a> from <a href="http://typosphere.org/projects/show/typo">Typo</a>, a Ruby blogging engine.
<p>
<img alt="Ruby RHTML markup and code" src="http://www.codinghorror.com/blog/images/ruby-rhtml-markup-and-code.png" width="645" height="706" border="0" />
<p>
Do you find this readable? Can you see where the code begins and the markup ends? Are you confident you could change the code structure without breaking the HTML, or change the HTML structure without breaking the code?
<p>
Sometimes editing this stuff makes me feel like I'm playing <a href="http://en.wikipedia.org/wiki/Operation_(game)">Operation</a>. I have to ever so carefully maneuver my metal tweezers into one tiny slice of code or HTML and make my changes without touching the edges and setting off that blasted electrical buzzer.
<p>
<img alt="Operation game" src="http://www.codinghorror.com/blog/images/operation-game.jpg" width="500" height="500" border="0" />

<p>
I'm not trying to single out Rails or Typo here; I could easily show you a ASP.NET MVC view that's just as confusing (or as "clear", if you think that's perfectly readable, I guess). Tag soup is everywhere; take a look at the Python <a href="http://www.djangoproject.com/documentation/templates/">Django framework templates</a>:
<p>
<pre>
&lt;h1&gt;Archive for {{ year }}&lt;/h1&gt;

{% for date in days %}
    {% ifchanged %}&lt;h3&gt;{{ date|date:"F" }}&lt;/h3&gt;{% endifchanged %}
    &lt;a href="{{ date|date:"M/d"|lower }}/"&gt;{{ date|date:"j" }}&lt;/a&gt;
{% endfor %}
</pre>
<p>
Perhaps when it comes to mixing HTML and server-side code, some form of soup is unavoidable, a necessary evil. The soup can be quite palatable; maybe even delicious. It's certainly possible to write <i>good</i> tag soup and <i>bad</i> tag soup. 
<p>
But I have to wonder: <b>is there a better way?</b> Is there something beyond RHTML, Views, and Templates? What examples would you point to of web development stacks that <i>avoided</i> degenerating into yet more hazardous, difficult to maintain tag soup? Is there anything truly better on the horizon?
<p>
Or is this year's newer, fancier, even-more-delicious iteration of tag soup as good as it ever gets for web development?
<p>
<table><tr><td class="sidead">
[advertisement] Read the largest case study ever published about lightweight peer code review in <i><a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+3" rel="nofollow">Best Kept Secrets of Peer Code Review</a></i>.  Free book, free shipping.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001155.html</guid>
         <pubDate>Sun, 20 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Dealing With Bad Apples</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001154.html</link>
         <description><![CDATA[<p>
Robert Miesen sent in this story of a project pathology:
<p>
<blockquote>
I was part of a team writing an web-based job application and screening system (a job kiosk the customer called it) and my team and our customer signed on to implementing this job kiosk using Windows, Apache, PHP5, and the ZendFramework -- everyone except one of our team members, who I will refer to as "Joe". Joe kept advocating the use of JavaScript throughout the technology deliberation phase, even though the customer made it quite clear that he expected the vast majority of the job kiosk to be implemented using a server-side technology and all the validation should be done using server-side technology.
<p>
The fact that the customer signed off on this, however, did nothing to deter Joe from advocating JavaScript -- abrasively. Every time our project hit a bump in the road, Joe would go off on some tirade on how much easier our lives would be if we were only writing this job kiosk in JavaScript. Joe would constantly bicker about how we were all doing this all wrong because we weren't doing it in JavaScript, not even bother to learn the technologies we were actually using, and, whenever fellow teammates would try and gently bring him back into the fold (usually via email), Joe would just flame the poor guy. At the height of Joe's pro-JavaScript bigotry, he would regularly belt off comments like, "Well, if we had only done it in JavaScript," to such an extent that the team would have been better off if he had just quit (or was reassigned or fired.)
</blockquote>
<p>
After reading this story, I had to resist the urge to lean forward, hand placed thoughtfully under my chin, brow furrowed, and ask -- <a href="http://thedailywtf.com/Articles/Straight_Shooter_for_Upper_Management.aspx">have you tried JavaScript?</a>
<p>
Robert thought this story was a cautionary tale about technology dependence, but I see something else: <b>a problem team member, a classic bad apple</b>.
<p>
<img alt="an apple goes bad" src="http://www.codinghorror.com/blog/images/apple-goes-bad.jpg" width="640" height="180" border="0" />
<p>
I'm sure "Joe" had the best of intentions, but at the point where you're actively campaigning against the project, and working against your teammates -- <b>you're a liability to the project</b>.
<p>
The cost of problem personnel on a project is severe, as noted in Chapter 12 of McConnell's <a href="http://www.amazon.com/dp/1556159005/?tag=codinghorror-20">Rapid Development: Taming Wild Software Schedules</a>.
<p>
<blockquote>
If you tolerate even one developer whom the other developers think is a problem, you'll hurt the morale of the good developers. You are implying that not only do you expect your team members to give their all; you expect them to do it when their co-workers are working against them.
<p>
In a review of 32 management teams, Larson and LaFasto found that <b>the most consistent and intense complaint from team members was that their team leaders were unwilling to confront and resolve problems associated with poor performance by individual team members.</b> (Larson and LaFasto 1989). They report that, "more than any other single aspect of team leadership, members are disturbed by leaders who are unwilling to deal directly and effectively with self-serving or noncontributing team members." They go on to to say that this is a significant management blind spot because managers nearly always think their teams are running more smoothly than their team members do.
</blockquote>
<p>
How do we identify problem personnel? It's not difficult as you might think. I had a friend of mine once describe someone on his team as -- and this is a direct quote -- "a cancer". At the point which you, or anyone else on your team, are using words like <i>cancer</i> to describe a teammate, you have a serious project pathology. You don't have to be friends with everyone on your team, <a href="http://www.codinghorror.com/blog/archives/001033.html">although it certainly helps</a>, but a level of basic personal and professional respect is mandatory for any team to function normally.
<p>
Steve outlines a few warning signs that you're dealing with a bad apple on your team:
<p>
<ol>
<li>They cover up their ignorance rather than trying to learn from their teammates. "I don't know how to explain my design; I just know that it works." or "My code is too complicated to test." (These are both actual quotes.)
<p></p>
<li>They have an excessive desire for privacy. "I don't need anyone to review my code."
<p></p>
<li>They are territorial. "No one else can fix the bugs in my code. I'm too busy to fix them right now, but I'll get to them next week."
<p></p>
<li>They grumble about team decisions and continue to revisit old discussions long after the team has moved on. "I still think we ought to go back and change the design we were talking about last month. The one we picked isn't going to work."
<p></p>
<li>Other team members all make wisecracks or complain about the same person regularly. Software developers often won't complain directly, so you have to ask if there's a problem when you hear many wisecracks.
<p></p>
<li>They don't pitch in on team activities. On one project I worked on, two days before our first major deadline, a developer asked for the day off. The reason? He wanted to spend the day at a men's clothing sale in a nearby city -- a clear sign he hadn't integrated with the team.
</ol>
<p>
Let me be quite clear on this point: if your team leader or manager isn't dealing with the bad apples on your project, <b>she isn't doing her job</b>.
<p>
You should never be afraid to remove -- or even fire -- people who do not have the best interests of the team at heart. You can develop skill, but you can't develop a positive attitude. The longer these disruptive personalities stick around on a project, the worse their effects get. They'll slowly spread poison throughout your project, in the form of code, relationships, and contacts. 
<p>
Removing someone from a team is painful; it's not fun for anyone. But <b>realizing you should have removed someone six months ago</b> is far more painful.
<p>
<table><tr><td class="sidead">
[advertisement] Complimentary paperback book on lightweight peer code review.  10 essays from industry experts.  Free shipping.  <a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+2" rel="nofollow">Order <i>Best Kept Secrets of Peer Code Review</i></a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001154.html</guid>
         <pubDate>Thu, 17 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>The Ultimate Software Gold Plating</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001153.html</link>
         <description><![CDATA[<p>
Some developers love to <a href="http://www.codinghorror.com/blog/archives/000150.html">gold plate their software</a>. There are various shades of .. er, gold, I guess, but it's usually considered wasteful to fritter away time gold plating old code in the face of new features that need to be implemented, or old bugs that could be squashed.
<p>
<blockquote>
Developers are fascinated by new technology and are sometimes anxious to try out new features of their language or environment or to create their own implementation of a slick feature they saw in another product -- whether or not it's required in their product. The effort required to design, implement, test, document, and support features that are not required lengthens the schedule. 
</blockquote>
<p>
But gold plating your code isn't <i>all</i> bad. Perhaps the most remarkable tale of successful developer gold plating I've ever read is <a href="http://www.bytecellar.com/archives/000158.php">the one Blake Patterson outlines</a>:
<p>
<blockquote>
Not long ago I purchased a new-in-box <a href="http://en.wikipedia.org/wiki/Atari_Jaguar">Atari Jaguar</a>, complete with <a href="http://en.wikipedia.org/wiki/Jeff_Minter">Jeff Minter's</a> psychedelic sequel to Tempest, <a href="http://en.wikipedia.org/wiki/Tempest_2000">Tempest 2000</a>. It's an amazing game that's been ported to many other platforms, but the consensus is that none are as solid as the Jaguar original. Having played several of the ports, I'd have to agree.
<p>
<img alt="tempest 2000" src="http://www.codinghorror.com/blog/images/tempest-2000.jpg" width="320" height="217" border="0" />
<p>
An interesting thing about "the world's first 64-bit console" -- its controller was, as the Brits would say, fairly pants. It was large, sported a calculator-button array for game overlays (like the <a href="http://en.wikipedia.org/wiki/Intellivision">Intellivision</a> controller), had no shoulder buttons, and featured only a D-pad for directional control. (ed: certainly one of the weirdest members of the <a href="http://www.axess.com/twilight/console/">game console controller family tree</a>, to be sure)
<p>
<img alt="atari jaguar controller" src="http://www.codinghorror.com/blog/images/jaguar-controller.jpg" width="320" height="277" border="0" />
<p>
As the arcade original is controlled with a rotary spinner knob, the D-pad falls rather short of providing ideal game control.
<p>
<img alt="tempest spinner" src="http://www.codinghorror.com/blog/images/tempest-spinner.jpg" width="179" height="242" border="0" />
<p>
But, of course, being such a savvy chap, Jeff Minter realized this.
<p>
<b>Jeff wrote in support for an analog rotary controller ... <i>that did not exist</i>.</b> Neither Atari nor third party manufacturers produced such a controller in the Jaguar's heyday. Jeff, as I understand it, hacked his own together by wiring an <a href="http://www.atariage.com/2600/controllers/con_AtariPaddles.jpg">Atari paddle controller</a> into a Jaguar controller. In the years since the Jaguar's passing, a few small operations have offered <a href="https://www.goatstore.com/info.php?id=151420">modified Jaguar controllers</a> with spinners wired into them for purchase.
</blockquote>
<p>
Jeff Minter's an interesting historical figure in the computer gaming community, as the author of several 8-bit computer era game classics. I've talked about his <a href="http://www.codinghorror.com/blog/archives/000511.html">long-standing interest in audio visualization</a> here once before. He's still creating games today; his latest is the Xbox Live downloadable title <a href="http://en.wikipedia.org/wiki/Space_Giraffe">Space Giraffe</a>. Jeff <a href="http://stinkygoat.livejournal.com/">has a blog</a> that he updates fairly regularly. 
<p>
Still, I'm amazed that Jeff added code to a commercially shipped console game to support <b>a completely optional homebrew spinner controller of his own creation</b>. That's the very definition of "not required". This code lied dormant in the game until a handful of enthusiasts, fourteen years later, cobbled together custom controllers to play the game as it was originally intended by the author.
<p>
If that isn't the ultimate case of gold plating your software, I don't know what is. My hat is off to you, Mr. Minter.
<p>
<table><tr><td class="sidead">
[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning <a href="http://smartbear.com/codecollab.php?chblog1">Code Collaborator</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001153.html</guid>
         <pubDate>Tue, 15 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Maybe Normalizing Isn't Normal</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001152.html</link>
         <description><![CDATA[<p>
One of the items we're struggling with now on <a href="http://stackoverflow.com">Stack Overflow</a> is how to maintain near-instantaneous performance levels in a relational database as the amount of data increases. More specifically, how to <a href="http://www.pui.ch/phred/archives/2005/06/tagsystems-performance-tests.html">scale our tagging system</a>. Traditional database design principles tell you that well-designed databases are always <a href="http://en.wikipedia.org/wiki/Database_normalization">normalized</a>, but I'm not so sure.
<p>
Dare Obasanjo had an excellent post <a href="http://www.25hoursaday.com/weblog/CommentView.aspx?guid=cc0e740c-a828-4b9d-b244-4ee96e2fad4b">When Not to Normalize your SQL Database</a> wherein he helpfully provides a <b>sample database schema for a generic social networking site</b>. Here's what it would look like if we designed it in the accepted normalized fashion:
<p>
<img alt="social network database example, normalized" src="http://www.codinghorror.com/blog/images/dare-social-database-normalized-example.png" width="671" height="596" border="0" />
<p>
Normalization certainly delivers in terms of limiting duplication. Every entity is represented once, and only once -- so there's almost no risk of inconsistencies in the data. But this design also requires a whopping <i>six joins</i> to retrieve a single user's information.
<p>
<pre>
select * from Users u
<b>inner join</b> UserPhoneNumbers upn
on u.user_id = upn.user_id
<b>inner join</b> UserScreenNames usn
on u.user_id = usn.user_id
<b>inner join</b> UserAffiliations ua
on u.user_id = ua.user_id
<b>inner join</b> Affiliations a
on a.affiliation_id = ua.affiliation_id
<b>inner join</b> UserWorkHistory uwh
on u.user_id = uwh.user_id
<b>inner join</b> Affiliations wa
on uwh.affiliation_id = wa.affiliation_id
</pre>
<p>
(<font color="red">Update:</font> this isn't intended as a real query; it's only here to visually illustrate the fact that you need six joins -- or six individual queries, if that's your cup of tea -- to get all the information back about the user.)
<p>
Those six joins aren't doing anything to help your system's performance, either. Full-blown normalization isn't merely difficult to understand and hard to work with -- it can also be quite slow.
<p>
As Dare points out, the obvious solution is to <b>denormalize</b> -- to collapse a lot of the data into a single Users table.
<p>
<img alt="Social database example, denormalized" src="http://www.codinghorror.com/blog/images/dare-social-database-denormalized-example.png" width="232" height="515" border="0" />
<p>
This works -- queries are now blindingly simple (<code>select * from users</code>), and probably blindingly fast, as well. But you'll have a bunch of gaping blank holes in your data, along with a slew of awkwardly named field arrays. And all those pesky data integrity problems the database used to enforce for you? Those are all your job now. Congratulations on your demotion!
<p>
Both solutions have their pros and cons. So let me put the question to you: <b>which is better -- a normalized database, or a denormalized database?</b>
<p>
Trick question! The answer is that <i>it doesn't matter!</i> Until you have millions and millions of rows of data, that is. <a href="http://www.codinghorror.com/blog/archives/000957.html">Everything is fast for small n</a>. Even a modest PC by today's standards -- let's say a dual-core box with 4 gigabytes of memory -- will give you near-identical performance in either case for anything but the very largest of databases. Assuming your team can write reasonably well-tuned queries, of course.
<p>
There's no shortage of fascinating database war stories from companies that made it big. I do worry that these war stories carry an implied tone of "I lost 200 pounds and so could you!"; please assume the tiny-asterisk disclaimer <b>results may not be typical</b> is in full effect while reading them. Here's a series that Tim O'Reilly compiled:
<p>
<ul>
<li><a href="http://radar.oreilly.com/2006/04/web-20-and-databases-part-1-se.html">Second Life</a>
<li><a href="http://radar.oreilly.com/2006/04/database-war-stories-2-bloglin.html">Blogline and Memeorandum</a>
<li><a href="http://radar.oreilly.com/2006/04/database-war-stories-3-flickr.html">Flickr</a>
<li><a href="http://radar.oreilly.com/2006/04/database-war-stories-4-nasa-wo.html">NASA World Wind</a>
<li><a href="http://radar.oreilly.com/2006/04/database-war-stories-5-craigsl.html">Craigslist</a>
<li><a href="http://radar.oreilly.com/2006/05/database-war-stories-6-oreilly.html">O'Reilly Research</a>
<li><a href="http://radar.oreilly.com/2006/05/database-war-stories-7-google.html">Google File System and BigTable</a>
<li><a href="http://radar.oreilly.com/2006/05/database-war-stories-8-findory.html">Findory and Amazon</a>
<li><a href="http://radar.oreilly.com/2006/05/database-war-stories-9-finis-b.html">MySQL</a>
</ul>
<p>
There's also the <a href="http://highscalability.com/">High Scalability</a> blog, which has its own set of database war stories:
<p>
<ul>
<li><a href="http://highscalability.com/youtube-architecture">YouTube</a>
<li><a href="http://highscalability.com/plentyoffish-architecture">PlentyOfFish</a>
<li><a href="http://highscalability.com/google-architecture">Google</a>
<li><a href="http://highscalability.com/myspace-architecture">MySpace</a>
<li><a href="http://highscalability.com/amazon-architecture">Amazon</a>
<li><a href="http://highscalability.com/scaling-twitter-making-twitter-10000-percent-faster">Twitter</a>
</ul>
<p>
First, a reality check. It's partially an act of hubris to imagine your app as the next Flickr, YouTube, or Twitter. As <a href="http://teddziuba.com/2008/04/im-going-to-scale-my-foot-up-y.html">Ted Dziuba so aptly said</a>, <i>scalability is not your problem, getting people to give a shit is.</i> So when it comes to database design, do measure performance, but try to err heavily on the side of <b>sane, simple design</b>. Pick whatever database schema you feel is easiest to understand and work with on a daily basis. It doesn't have to be all or nothing as I've pictured above; you can partially denormalize where it makes sense to do so, and stay fully normalized in other areas where it doesn't.
<p>
Despite copious evidence that normalization rarely scales, I find that many <b>software engineers will zealously hold on to total database normalization on principle alone</b>, long after it has <a href="http://www.paradox1x.org/weblog/kmartino/archives/009703.shtml">ceased to make sense</a>.
<p>
<blockquote>
When growing Cofax at Knight Ridder, we hit a nasty bump in the road after adding our 17th newspaper to the system. Performance wasn't what it used to be and there were times when services were unresponsive.
<p>
A project was started to resolve the issue, to look for 'the smoking gun'. The thought being that the database, being as well designed as it was, could not be of issue, even with our classic symptom being rapidly growing numbers of db connections right before a crash. So we concentrated on optimizing the application stack.
<p>
I disagreed and waged a number of arguments that it was our database that needed attention. We first needed to tune queries and indexes, and be willing to, if required, pre-calculate data upon writes and avoid joins by developing a set of denormalized tables. <b>It was a hard pill for me to swallow since I was the original database designer. Turned out it was harder for everyone else!</b> Consultants were called in. They declared the db design to be just right - that the problem must have been the application.
<p>
After two months of the team pushing numerous releases thought to resolve the issue, to no avail, we came back to my original arguments. 
</blockquote>
<p>
Pat Helland notes that <a href="http://blogs.msdn.com/pathelland/archive/2007/07/23/normalization-is-for-sissies.aspx">people normalize because their professors told them to</a>. I'm a bit more pragmatic; I think you should normalize when the <i>data</i> tells you to:
<p>
<ol>
<li>Normalization makes sense to your team.
<li>Normalization provides better performance. (You're automatically measuring all the queries that flow through your software, right?)
<li>Normalization prevents an onerous amount of duplication or avoids risk of synchronization problems that your problem domain or users are particularly sensitive to.
<li>Normalization allows you to write simpler queries and code.
</ol>
<p>
Never, never should you normalize a database out of some vague sense of duty to <a href="http://en.wikipedia.org/wiki/Boyce-Codd_Normal_Form">the ghosts of Boyce-Codd</a>. Normalization is not magical fairy dust you sprinkle over your database to cure all ills; it often creates as many problems as it solves. Fear not the specter of denormalization. Duplicated data and synchronization problems are often overstated and relatively easy to work around with cron jobs. Disks and memory are cheap and getting cheaper every nanosecond. Measure performance on your system and decide for yourself what works, free of predispositions and bias.
<p>
As the old adage goes, <b>normalize until it hurts, denormalize until it works</b>.
<p>
<table><tr><td class="sidead">
[advertisement] Peer code review without meetings, paperwork, or stopwatches?  No wonder <a href="http://smartbear.com/codecollab.php?chblog4">Code Collaborator</a> won the Jolt Award.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001152.html</guid>
         <pubDate>Mon, 14 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Monkeypatching For Humans</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001151.html</link>
         <description><![CDATA[<p>
Although <a href="http://www.codinghorror.com/blog/archives/000634.html">I love strings</a>, sometimes the <code>String</code> class can break your heart. For example, in C#, there is no <code>String.Left()</code> function. Fair enough; we can roll up our sleeves and write our own function lickety-split:
<p>
<pre>
public static string Left(string s, int len)
{
    if (len == 0 || s.Length == 0)
        return "";
    else if (s.Length &lt;= len)
        return s;
    else
        return s.Substring(0, len);
}
</pre>
<p>
And call it like so:
<p>
<pre>
var s = "Supercalifragilisticexpialidocious";
s = Left(s, 5);
</pre>
<p>
Fairly painless, right?
<p>
But with the advent of C# 3.0, there's an even better way -- <a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx">extension methods</a>. With an extension method, we "extend" the <code>String</code> to add the missing function. The code is fairly similar; I'll highlight the changed parts in red.
<p>
<pre>
public static string Left(<font color="red">this</font> string s, int len)
{
    if (len == 0 || s.Length == 0)
        return "";
    else if (s.Length &lt;= len)
        return s;
    else
        return s.Substring(0, len);
}
</pre>
<p>
And now we can call it <b>as if this very method existed on the String class as shipped</b>:
<p>
<pre>
var s = "Supercalifragilisticexpialidocious";
s = <font color="red">s.Left(5);</font>
</pre>
<p>
Pretty slick. It's difficult not to fall in love with extension methods, as they allow you to mold classes into exactly what you think they should be. This is fairly innocuous in C#, as <b>extension methods only allow you to add new functionality to classes</b>, not override, remove, or replace anything.
<p>
But imagine if you <i>could</i>.
<p>
Well, that's exactly how it is in other, more dynamic languages such as Javascript, Python, Perl, and Ruby. Something as prosaic as C# extensions is old hat to these folks. In those languages, <i>you could redefine everything in the <code>String</code> class if you wanted to</i>. This is commonly known in dynamic language circles as <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkeypatching</a>.
<p>
<img alt="monkey patching" src="http://www.codinghorror.com/blog/images/monkey-patching.jpg" width="512" height="354" border="0" />
<p>
If the idea of monkeypatching scares you a little, it probably should. Can you imagine debugging code where the <code>String</code> class had subtly different behaviors from the <code>String</code> you've learned to use? Monkeypatching <a href="http://avdi.org/devblog/2008/02/23/why-monkeypatching-is-destroying-ruby/">can be incredibly dangerous in the wrong hands</a>, as Avdi Grimm notes:
<p>
<blockquote>
Monkey patching is the new black [in the Ruby community].  It's what all the hip kids are doing.  To the point that smart, experienced hackers reach for a monkey patch as their tool of first resort, even when a simpler, more traditional solution is possible.
<p>
I don't believe this situation to be sustainable.  Where I work, <b>we are already seeing subtle, difficult-to-debug problems crop up as the result of monkey patching in plugins.</b> Patches interact in unpredictable, combinatoric ways.  And by their nature, bugs caused by monkey patches  are more difficult to track down than those introduced by more traditional classes and methods.  As just one example: on one project, it was a known caveat that we could not rely on class inheritable attributes as provided by ActiveSupport.  No one knew why.  Every Model we wrote had to use awkward workarounds.  Eventually we tracked it down in a plugin that generated admin consoles.  It was overwriting <code>Class.inherited()</code>.  It took us months to find this out.
<p>
This is just going to get worse if we don't do something about it.  And the "something" is going to have to be a cultural shift, not a technical fix.  I believe it is time for experienced Ruby programmers to wean ourselves off of monkey patching, and start demonstrating more robust techniques.
</blockquote>
<p>
Try to imagine a world where <b>every programmer you know is a wannabe language designer, bent on molding the language to their whims</b>. When I close my eyes and imagine it, I have a vision of the apocalypse, a perfect, pitch-black storm of utterly incomprhensible, pathologically difficult to debug code.
<p>
I was just looking at random PHP plugin code the other day, and it was, frankly, crap. But that's because <i>most code is crap</i>. <a href="http://www.codinghorror.com/blog/archives/000099.html">Including my own</a>. It is, sadly, the statistical norm. That's why <a href="http://www.codinghorror.com/blog/archives/000824.html">sites like The Daily WTF</a> are guaranteed to have more material than they can possibly ever publish for the next millennia. (Note to self: invest in this website). I can only imagine what that PHP plugin code would have looked like, had its developer been granted the ability to redefine fundamental PHP keywords and classes at will. These are the sort of thoughts that drive me to drink <a href="http://www.amazon.com/dp/B000NY30P0/?tag=codinghorror-20">Bawls</a>. And that stuff is disgusting.
<p>
You might say that PHP, sans the fundamental dynamic language ability to monkeypatch, is <a href="http://weblog.raganwald.com/2006/10/are-we-blub-programmers.html">just another crappy Blub language</a>. But there's also a ton of <a href="http://www.codinghorror.com/blog/archives/001119.html">incredibly useful PHP code out there</a>. So it seems to me that the ability to monkeypatch doesn't stop people from producing a huge volume of useful code, even in a kind of.. horrible language. Some of it is even good!
<p>
While I acknowledge the power and utility of dynamic language monkeypatching, I know enough about programmers -- myself <i>absolutely</i> included -- to know the vast majority of us have absolutely no business whatsoever re-designing a programming language. There's a reason some of the <a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg">most</a> <a href="http://en.wikipedia.org/wiki/John_McCarthy_%28computer_scientist%29">deeply</a> <a href="http://en.wikipedia.org/wiki/Dennis_Ritchie">respected</a> <a href="http://en.wikipedia.org/wiki/Guido_van_Rossum">computer</a> <a href="http://en.wikipedia.org/wiki/Niklaus_Wirth">scientists</a> in the world end up as language designers.
<p>
Perhaps then, given the risks, <b>monkeypatching should mean reaching for the meta-hammer as infrequently as humanly possible</b>. This is a position that Avdi himself espouses <a href="http://weblog.raganwald.com/2008/02/1100inject.html#8589089242300871488">in a followup comment</a>:
<p>
<blockquote>
I'm afraid a lot of people have missed the actual meat of my argument -- that dynamic extension of classes is currently overused in Ruby, in ways that are:
<p>
<ul>
<li>Needless - another technique (such as a mixin, or locally extending individual objects) would have worked as well or better.
<li>Overcomplicated - the use of a monkey patch actually created more work for the author.
<li>Fragile - the solution is tightly bound to third-party internals, reducing the usefulness of the plugin or gem because it is prone to breakage.
<li>Excessively wide in scope - by hardcoding extensions to core classes, the author takes the choice to scope the change out of the plugin/gem user's hands, further limiting utility.
</ul>
<p>
My point is that there are alternatives - often alternatives which are actually easier to implement and will make your plugin or gem more useful to the user.
</blockquote>
<p>
While I enjoy the additive nature of C# extensions, even those are enough to make me a little nervous, as mild as they are. Full-blown dynamic language monkeypatching goes even further; it might even be the ultimate expression of programming power. Is there anything more pure and godlike than <b>programming your own programming language?</b>
<p>
But if wielding that power doesn't scare and humble you a little, too, then maybe you should leave the monkeypatching to the <a href="http://www.paulgraham.com/langdes.html">really smart monkeys</a>.
<p>
<table><tr><td class="sidead">
[advertisement] Read the largest case study ever published about lightweight peer code review in <i><a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+3" rel="nofollow">Best Kept Secrets of Peer Code Review</a></i>.  Free book, free shipping.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001151.html</guid>
         <pubDate>Sat, 12 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>iTunes is Anti-Web</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001149.html</link>
         <description><![CDATA[<p>
Ever find yourself clicking on links to music or videos and getting <b>blasted in the face with this delightful little number?</b>
<p>
<img alt="We are unable to find iTunes on your computer." src="http://www.codinghorror.com/blog/images/unable-to-find-itunes-on-your-computer.png" width="414" height="290" border="0" />
<p>
That's right -- links to any sort of music, TV shows, movies, podcasts, audiobooks or anything else available through Apple's iTunes store <i>requires custom software</i> to be installed on your computer before they will display thing one to you.
<p>
Is it so unreasonable to expect links in your browser to resolve to, oh, I don't know, <b>web pages containing information about the thing you just clicked on?</b> Is there anything more anti-web than demanding users install custom software to display information that could have just as easily been delivered through the browser? 
<p>
So here's what we know:
<p>
<ul>
<li>Apple wants us to install iTunes.
<li>iTunes is necessary to sync media with Apple's iPods and iPhones.
<li>iTunes is only available for Windows and OS X.
<li>iTunes is required to browse or buy anything from the iTunes Store.
</ul>
<p>
That's all well and good for people who own iPods and iPhones -- and happen to be running Windows or OS X, I suppose. 
<p>
But what about the rest of the world? Why lock them out with <a href="http://www.codinghorror.com/blog/archives/000881.html">the ultimate login barrier</a>? We might like to browse the iTunes Store, too. At the very least, I might want some basic information about the media I just clicked on. Right here in my browser where I already am. Information like what the heck it is, some artwork, maybe some audio clips, how much it costs -- sweet talk me. Make me want to buy it through the Apple Store. Dazzle me with your simplicity and ease of use. Beguile me with your wares!
<p>
Or, you could <b>bludgeon me with the digital equivalent of a giant stop sign</b>.
<p>
Hey, "it just works". Except when it doesn't.
<p>
I'm certainly able to click through to eminently purchaseable media on dozens of other places on the web using nothing more than my web browser. Let's imagine, for a moment, how utterly ridiculous it would be if I had to <b>install the Amazon application</b> to browse and purchase media from Amazon.
<p>
<img alt="unable to find Amazon on your computer" src="http://www.codinghorror.com/blog/images/unable-to-find-amazon-on-your-computer.png" width="414" height="290" border="0" />
<p>
And yet this is exactly how the iTunes Store works. Or doesn't work, depending on your perspective.
<p>
I can understand requiring iTunes once you want to sync your media with Apple hardware devices -- although I would argue syncing should really be a fundamental, built in function of the operating system. But I'm not trying to sync anything! All I did was click on a link. It's <b>downright user hostile to demand installation of a special application merely to browse the store</b>, and it is most certainly against everything the web stands for and was built on.
<p>
The last "application" I can recall needing to install to get to things online was AOL.
<p>
<a href="http://www.mikerichardson.name/oldaol/"><img alt="AOL 2.5 main menu" src="http://www.codinghorror.com/blog/images/aol-25-main-menu.png" width="514" height="362" border="0" /></a>
<p>
And we all know <a href="http://www.codinghorror.com/blog/archives/000898.html">how great that turned out</a>.
<p>
For all the buzz about the Apple "it just works" mystique, the current iTunes Store design surely doesn't -- at least <b>not the same way the rest of the web does</b>. And I, for one, <a href="http://www.25hoursaday.com/weblog/2008/07/07/AListOfCompaniesWorkingHardToScrewUpMyWebExperience.aspx">can't get behind that</a>.
<p>
<table><tr><td class="sidead">
[advertisement] Complimentary paperback book on lightweight peer code review.  10 essays from industry experts.  Free shipping.  <a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+2" rel="nofollow">Order <i>Best Kept Secrets of Peer Code Review</i></a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001149.html</guid>
         <pubDate>Wed, 09 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Spartan Programming</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001148.html</link>
         <description><![CDATA[<p>
As I grow older and <s>wiser</s>even older as a programmer, I've found that my personal coding style has trended heavily toward minimalism.
<p>
I was pleased, then, to find many of the coding conventions I've settled on over the last 20 years codified in <a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming">Spartan programming</a>.
<p>
<img alt="300-movie.jpg" src="http://www.codinghorror.com/blog/images/300-movie.jpg" width="512" height="384" border="0" />
<p>
No, not that sort of <a href="http://en.wikipedia.org/wiki/Spartan_Army">Spartan</a>, although it is historically related. The particular meaning of <b>spartan</b> I'm referring to is this one:
<p>
<blockquote>
(adj) ascetic, ascetical, austere, spartan (practicing great self-denial) <i>"Be systematically ascetic...do...something for no other reason than that you would rather not do it"</i> - William James; <i>"a desert nomad's austere life"; "a spartan diet"; "a spartan existence"</i>
</blockquote>
<p>
I've tried to <a href="http://www.codinghorror.com/blog/archives/000791.html">code smaller</a>, even going so far as to write <a href="http://www.codinghorror.com/blog/archives/000878.html">no code at all</a> when I can get away with it. <a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming">Spartan programming</a> aligns perfectly with these goals. You strive for <b>simultaneous minimization</b> of your code in many dimensions:
</p>
<ol>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Horizontal_complexity%2C_spartan_reduction_of">Horizontal complexity</a>. The depth of nesting of control structures.
</li>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Vertical_complexity%2C_spartan_reduction_of">Vertical complexity</a>. The number of lines or length of code.
</li>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Token_count%2C_spartan_reduction_of">Token count</a>.
</li>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Character_count%2C_spartan_reduction_of">Character count</a>.
</li>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Parameters%2C_spartan_reduction_of">Parameters</a>. The number of parameters to a routine or a generic structure. 
</li>
<li><a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Variables%2C_spartan_reduction_of">Variables</a>.
</li>
<li>Looping instructions. The number of iterative instructions and their nesting level.  
</li><li>Conditionals. The number of <code>if</code> and multiple branch <code>switch</code> statements.
</li></ol>
</blockquote>
<p>
The discipline of spartan programming means <b>frugal use of variables</b>:
<p>
<ol>
<li>Minimize <i>number</i> of variables. Inline variables which are used only once. Take advantage of <code>foreach</code> loops.</li>
<li>Minimize <i>visibility</i> of variables and other identifiers. Define variables at the smallest possible scope.</li>
<li>Minimize <i>accessibility</i> of variables. Prefer the greater encapsulation of <code>private</code> variables.</li>
<li>Minimize <i>variability</i> of variables. Strive to make variables <code>final</code> in Java and <code>const</code> in C++. Use annotations or restrictions whenever possible.</li>
<li>Minimize <i>lifetime</i> of variables. Prefer ephemeral variables to longer lived ones. Avoid persistent variables such as files.</li>
<li>Minimize <i>names</i> of variables. Short-lived, tightly scoped variables can <a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Terse_variable_naming">use concise, terse names</a>.</li>
<li>Minimize <i>use of array</i> variables. Replace them with collections provided by your standard libraries.</li>
</ol>
<p>
It also means <b>frugal use of control structures</b>, with early <code>return</code> whenever possible. This is probably best illustrated with an actual example, starting with raw code and refactoring it using the spartan programming techniques:
<p>
<ul>
<li>Applying Spartan programming techniques <a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/Spartan_programming_C_example">to a C File</a>
<li>Applying Spartan programming techniques <a href="http://ssdl-wiki.cs.technion.ac.il/wiki/index.php/SendAnEmail_case_study">to a Java function</a>
</ul> 
<p>
I don't agree with all the rules and guidelines presented here, but I was definitely nodding along with the majority of the page. <b>Minimalism isn't always the right choice, but it's rarely the <i>wrong</i> choice.</b> You could certainly do worse than to adopt the discipline of spartan programming on your next programming project.
<p>
(hat tip to Yuval Tobias for sending this link my way)
<p>
<table><tr><td class="sidead">
[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning <a href="http://smartbear.com/codecollab.php?chblog1">Code Collaborator</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001148.html</guid>
         <pubDate>Tue, 08 Jul 2008 04:00:00 -0800</pubDate>
      </item>
      <item>
         <title>The Problem With Code Folding</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001147.html</link>
         <description><![CDATA[<p>
When you join a team, it's important to <b>bend your preferences a little to accommodate the generally accepted coding practices of that team.</b> Not everyone has to agree on every miniscule detail of the code, of course, but it's a good idea to dicuss it with your team and decide on overall approaches and philosophy beforehand. It promotes team harmony, and more than that, it's just common courtesy. As they say, <i><a href="http://en.wikipedia.org/wiki/When_in_Rome">when in Rome</a>, do as the Romans do.</i>
<p>
I've always been wary of cowboy coders who rolled into an ongoing project on fresh horses and immediately started dictating terms. It's a very short trip indeed from there to <a href="http://www.codinghorror.com/blog/archives/000992.html">Who Wrote This Crap</a>, and the predictable, inevitable finger-pointing at the foolhardy programmers who came before you begins. Don't be that guy or gal. <a href="http://www.yafla.com/dennisforbes/Effectively-Integrating-Into-Software-Development-Teams/Effectively-Integrating-Into-Software-Development-Teams.html">Work with your team</a>, not against it.
<p>
Still, there are some coding preferences people may feel.. <i>strongly</i>.. about. If that's the case, try to clear the air and address those strong preferences up front, as early as possible. Don't let them simmer. For me, the use of <a href="http://www.google.com/search?q=c%23+region">#region</a> is one of those things. I tried to make myself clear in <a href="http://twitter.com/codinghorror/statuses/837284151">this twitter message</a>:
<p>
<a href="http://twitter.com/codinghorror/statuses/837284151"><img alt="Twitter message from codinghorror about #regions" src="http://www.codinghorror.com/blog/images/twitter-codinghorror-regions.png" width="571" height="220" border="0" /></a>
<p>
So what is <code>#region</code>? It's a named hint you place in C# or VB.NET code to set a <b>code folding point</b>. Any code placed inside that region is, by default, collapsed when you re-open it in the editor. Here's a random example from the <a href="http://logging.apache.org/log4net/download.html">Log4Net project</a>:
<p>
<img alt="C# region example, log4net.Util.NativeError" src="http://www.codinghorror.com/blog/images/csharp-region-example-log4net-util.png" width="465" height="517" border="0" />
<p>
Immediately I have a problem: <b>I can't see anything!</b> I have to manually expand those sections to browse any of the code in this class. It is possible to configure the Visual Studio IDE to not fold any of the regions when files are opened, but this is the out of box behavior, so that's what most developers will see. And of course there are keyboard shortcuts to deal with the regions:
<p>
<table cellpadding=4 cellspacing=4>
<tr>
<td>
Ctrl+M, Ctrl+M
<td>
Collapse or expand the block you're currently in.
</tr>
<tr>
<td>
Ctrl+M, Ctrl+O
<td>
Collapse all blocks in the file
</tr>
<tr>
<td>
Ctrl+M, Ctrl+L
<td>
Expand all blocks in the file
<tr>
<td>
Ctrl+M, Ctrl+P
<td>
Stop outlining mode. (Ctrl+M, Ctrl+O resumes)
</tr>
</table>
<p>
Here's the really sick part: once you expand the above log4net code there's <b>literally three pages worth of code there!</b> After you strip out all the massive XMLDoc comments and the dozen or so #region directives, you <i>could</i> have had all the code at your fingertips with a minor flick of the mouse wheel, in a simple scrollable layout.
<p>
I daresay being able to <i>see the damn code</i> is more important than having it meticulously segmented into six pointless little named buckets, but apparently a lot of programmers can't get enough of stuffing their code into pointless little named buckets. It's as if they've forgotten what the scroll bar -- and <a href="http://www.codinghorror.com/blog/archives/000432.html">incremental search</a> -- is for.
<p>
The <code>#region</code> directive drives me bonkers. It's not evil, per se, but I feel it is criminally overused in practice and heavily prone to abuse. I strongly urge you to think about how you're using code folding, because as I see it, there are a lot of downsides:
<p>
<ol>
<li><b>Folding directives are glorified comments</b>. <code>#region</code> has zero meaning to the compiler; it's a hint to the editor to allow code folding. It doesn't do any namespacing or scoping. Why, exactly, are we writing code to accommodate the editor? It boggles my mind that we'd add significant lines of code to our project that do nothing but offer organizational hints to the editor. Even traditional comments are a better value for your keystroke, because they can be more expressive. And folding is certainly no substitute at all for bona-fide refactoring.
<p>
<li><b>Folding is used to sweep code under the rug</b>. Got a bunch of boring boilerplate code that makes your eyes water? A slew of ugly, gnarly code that nobody in their right mind wants to look at? Hide it in a region and fold that sucker into oblivion! Problem solved, right? Hardly. Your project is now full of crappy code that <i>you can't see</i>. That's worse. Much worse! Code that hides from you is code that will rot in the most putrescent and painful way possible. Your code should be front and center at all times -- exposed to as many programmers' eyes, and as much healing light, as possible.
<p>
<li><b>Folding is used to mask excessive length.</b> The presence of folded code can lull developers into a false sense of what clean code looks like. Under the cover of folding, you can end up writing long, horrible spaghetti code blocks. If the code needs the crutch of folding to <i>look</i> organized, it's bad code.
<p>
<li><b>Folding can hide deficiencies in your editor.</b> The presence of so-called "standard" boilerplate regions like "Public Constructors" and "Public Properties" and "Events" is not a feature. It's a bug. The editor should <i>automatically</i> offer to fold up these common structural blocks for you! I'm continually amazed that programmers spend time doing this scutwork when they could be writing useful code. Or at least demanding a smarter code editor.
</ol>
<p>
I urge developers to <b>write code that doesn't <i>need</i> folding to be readable, clear, and concise</b>. I'm sure there are sane uses for code folding out there somewhere, but I rarely see them. 
<p>
<table><tr><td class="sidead">
[advertisement] Peer code review without meetings, paperwork, or stopwatches?  No wonder <a href="http://smartbear.com/codecollab.php?chblog4">Code Collaborator</a> won the Jolt Award.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001147.html</guid>
         <pubDate>Sun, 06 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Investing in a Quality Programming Chair</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001146.html</link>
         <description><![CDATA[<p>
In <a href="http://www.codinghorror.com/blog/archives/000240.html">A Developer's Second Most Important Asset</a>, I described how buying a quality chair may be one of the <b>smartest investments you can make as a software developer</b>. 
<p>
<blockquote>
In fact, after browsing chairs for the last few years of my career, I've come to one conclusion: you can't expect to get a decent chair for less than $500. If you are spending less than that on seating -- unless you are getting the deal of the century on dot-bomb bankruptcy auctions -- <i>you're probably making a mistake</i>.
</blockquote>
<p>
I still believe this to be true, and I urge any programmers reading this to seriously consider the value of what you're sitting in while you're on the job. In our profession, seating <i>matters</i>:
<p>
<ul>
<li><b>Chairs are a primary part of the programming experience.</b> Eight hours a day, every day, for the rest of your working life -- you're sitting in one. Like it or not, whatever you're sitting in has a measurable impact on your work experience.
<p>
<li><b>Cheap chairs suck</b>. Maybe I've become spoiled, but I have yet to sit in a single good, cheap chair. In my experience, the difference between the really great chairs and the cheap stuff is enormous. A quality chair is so comfortable and accommodating it effortlessly melts into the background, so you can focus on your work. A cheesy, cheap chair constantly reminds you how many hours of work you have left.
<p>
<li><b>Chairs last.</b> As I write this, I'm still sitting my original Aeron chair, which I purchased in 1998. I can't think of any other piece of equipment I use in my job that has lasted me <i>ten full years</i> and beyond. While the initial sticker shock of a quality chair may turn you off, try to mentally amortize that cost across the next ten years or more.
</ul>
<p>
Choice of seating is as fundamental and constant as it gets in a programming career otherwise marked by relentless change. They are long term investments. Why not take the same care and consideration in selecting a chair as you would with the other strategic directions that you'll carry with you for the rest of your career? Skimping yourself on a chair just doesn't make sense.
<p>
Although I've been quite happy with my <a href="http://www.amazon.com/dp/B0006NUB5U/?tag=codinghorror-20">Herman Miller Aeron chair</a> over the last 10 years, I've always been a little disenchanted with the way it became associated with <a href="http://www.slate.com/id/2085064/">dot-com excess</a>:
<p>
<blockquote>
In the '90s, the Aeron became an emblem of the dot-com boom; it symbolized mobility, speed, efficiency, and 24/seven work weeks. The Aeron was a must-have for hot startups precisely because it looked the least like office furniture: It was more like a piece of machinery or unadorned engineering. The black Pellide webbing was durable, and hid whatever Jolt or Red Bull stains you might get on it. Held taut by an aluminum frame, the mesh allowed air to circulate and kept your body cool. What's more, the chair came in three sizes, like a personalized tool. Assorted knobs and levers allowed you to adjust the seat height, tilt tension, tilt range, forward tilt, arm height, arm width, arm angle, lumbar depth, and lumbar height. The Aeron was high-tech but sexy -- which was how the dot-commers saw themselves.
<p>
<a href="http://www.amazon.com/dp/B0006NUB5U/?tag=codinghorror-20">
<img alt="aeron chair" src="http://www.codinghorror.com/blog/images/chair-aeron.jpg" width="240" height="327" border="0" /></a>
<p>
But baby-faced CEOs weren't drawn to the Aeron only for the way it looked. The Aeron was a visual expression of the anti-corporate zeitgeist, a non-hierarchical philosophy about the workplace. An office full of Aerons implicitly rejected the Fortune 500, coat-and-tie, brick-and-mortar model in which the boss sinks back in an overpriced, oversized, leather dinosaur while his secretary perches on an Office Max toadstool taking notes.
</blockquote>
<p>
I recently had the opportunity to sit in a newer <a href="http://www.amazon.com/dp/B0002K11BK/?tag=codinghorror-20">Herman Miller Mirra chair</a> on a trip, and I was surprised how much more comfortable it felt than my classic Aeron.
<p>
<a href="http://www.amazon.com/dp/B0002K11BK/?tag=codinghorror-20"><img alt="chair-mirra" src="http://www.codinghorror.com/blog/images/chair-mirra.jpg" width="300" height="413" border="0" /></a>
<p>
The Mirra chair was an excellent recliner, too. I've been disappointed by how poorly the Aeron reclines. I actually broke my Aeron's recline pin once and had to replace it myself. So I've retrained myself not to recline, which is awkward, as I'm a natural recliner.
<p>
All this made me wonder if I should retire my Aeron and upgrade to something better. I liked the Mirra, but the comments to <a href="http://www.codinghorror.com/blog/archives/000240.html">my original chair post</a> have a lot of other good seating suggestions, too. Here are pictures and links to <b>the chairs that were most frequently mentioned as contenders</b>, in addition to the Mirra and Aeron pictured above:
<p>
<a href="http://www.amazon.com/dp/B000REGDRS/?tag=codinghorror-20">Steelcase Think Chair</a>
<p>
<a href="http://www.amazon.com/dp/B000REGDRS/?tag=codinghorror-20"><img alt="steelcase think chair" src="http://www.codinghorror.com/blog/images/steelcase_think_chair.jpg" width="263" height="376" border="0" alt="Steelcase Think Chair"/></a>
<p>
<a href="http://www.amazon.com/dp/B000RE7MGE/?tag=codinghorror-20">Steelcase Leap Chair</a>
<p>
<a href="http://www.amazon.com/dp/B000RE7MGE/?tag=codinghorror-20"><img alt="steelcase leap chair" src="http://www.codinghorror.com/blog/images/steelcase-leap.jpg" width="287" height="454" border="0" /></a>
<p>
<a href="http://www.amazon.com/dp/B0014DPL9C/?tag=codinghorror-20">Ergohuman Mesh Chair</a>
<p>
<a href="http://www.amazon.com/dp/B0014DPL9C/?tag=codinghorror-20"><img alt="ergohuman chair" src="http://www.codinghorror.com/blog/images/chair-ergohuman.jpg" width="327" height="489" border="0" /></a>
<p>
<a href="http://www.amazon.com/dp/B001BPX1E0/?tag=codinghorror-20">HumanScale Freedom Chair</a>
<p>
<a href="http://www.amazon.com/dp/B001BPX1E0/?tag=codinghorror-20"><img alt="humanscale freedom chair" src="http://www.codinghorror.com/blog/images/chair-freedom-1.jpg" width="260" height="436" border="0" /></a>
<p>
<a href="http://www.amazon.com/dp/B000NTF7OW/?tag=codinghorror-20">HumanScale Liberty Chair</a>
<p>
<a href="http://www.amazon.com/dp/B000NTF7OW/?tag=codinghorror-20"><img alt="humanscale liberty chair" src="http://www.codinghorror.com/blog/images/chair-liberty-1.jpg" width="276" height="447" border="0" /></a>
<p>
There were also some lesser known recommendations, such as the <a href="http://www.haworth.com/zody">Haworth Zody chair</a>, <a href="http://www.nightingalechairs.com/html/cxo/cxo_home.html">Nightingale CXO chair</a>, <a href="http://www.ergo4me.com/">BodyBilt ergo chairs</a>, <a href="http://www.hag.no/">Hag kneeling chair</a>, <a href="http://www.igoergo.com/_site/products.php?cat=02">NeutralPosture ergo</a>, and something called <a href="http://www.relaxtheback.com/the-swopper-product-6370282-1894">the swopper</a>.
<p>
Chair fit is, of course, a subjective thing. If you're investing $500+ in a chair, you'd understandably want to be sure it's "the one". The thing to do is find a local store that sells all these chairs and try them all out. Well, good luck with that. Don't even bother with your local big-box office supply chain. Your best bet seems to be <b>back stores</b>, as they tend to stock many of the more exotic chairs. Apparently they have a clientele of people who are willing to spend for comfort.
<p>
Reviews of individual chairs are relatively easy to find, but aren't particularly helpful in isolation. What we need is a multi-chair review roundup. The only notable roundup I know of is Slate's late 2005 <a href="http://www.slate.com/id/2131646/">Sit Happens: The Search for the Best Desk Chair</a>. It's not as comprehensive as I would like, but it does have most of the main contenders. Notably, Slate's winner was the <a href="http://www.amazon.com/dp/B000NTF7OW/?tag=codinghorror-20">HumanScale Liberty</a>. <font color="red">Update:</font> I found another good <a href="http://www.crunchgear.com/2006/12/28/workspace-roundup-ergonomic-chairs/">multiple chair roundup at CrunchGear</a> as well.
<p>
If this is all a bit too much <a href="http://furnitureporn.com/">furniture porn</a> for your tastes, I understand. As for me, I'm headed off to my local friendly neighborhood back store to figure out which of these chairs will best replace my aging Aeron. By my calculations, the Aeron cost me about $7 per month over its ten year lifetime; I figure my continued health and comfort while programming are worth at least that much.
<p>
<table><tr><td class="sidead">
[advertisement] Read the largest case study ever published about lightweight peer code review in <i><a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+3">Best Kept Secrets of Peer Code Review</a></i>.  Free book, free shipping.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001146.html</guid>
         <pubDate>Fri, 04 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Why Can't Microsoft Ship Open Source Software?</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001144.html</link>
         <description><![CDATA[<p>
In <a href="http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/">Codeplex wastes six months reinventing wheels</a>, Ryan Davis has a bone to pick with Microsoft:
<p>
<blockquote>
I saw an announcement [in March, 2007] that CodePlex, Microsoft's version of Sourceforge, has <a href="http://blogs.msdn.com/codeplex/archive/2007/03/26/announcing-the-codeplex-source-control-client.aspx">released a source control client</a>.
<p>
This <i>infuriates</i> me. This cool thing they spent six months (six!) writing is called <a href="http://subversion.tigris.org/">Subversion</a>, and it had a 1.0.0 release [in early 2004]. Subversion had its first beta in late 2003, so the Codeplex folks are waaay behind the state of the art on this one.
<p>
As a whole, I think the state of software is abysmal. The only way to make it better is to <b>stop writing new code</b>. New code is always full of bugs, and its an expensive path to get from blank screen to stable program. We need to treat programming more like math, we need to build on our results. Development tools is a special market, as our needs are all very similar, and when we need a tool, we have the skills to make it. 
</blockquote>
<p>
It's a great rant -- you should <a href="http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/">read the whole thing</a> -- but I'm not sure I entirely agree.
<p>
While I do empathize with the overall sentiment that Ryan is expressing here, I also found myself nodding along with Addy Santo, who left this comment:
<p>
<blockquote>
Author seems to think that all software development is done in basements and dorms. The reality is that software is an industry like any other - and follows the same simple rules of economics. How many brands of sports shoes are there? How many different MP3 players? Flavors of toothpaste ? If you can walk down the soft drink isle and not be "infuriated" by Vanilla Cherry Diet Doctor Pepper then you might just be a hypocrite.
</blockquote>
<p>
So if you think Microsoft's particular flavor of source control is redundant, <b>you'll <i>really</i> hate Diet Cherry Chocolate Dr. Pepper</b>.
<p>
<img alt="Diet Cherry Chocolate Dr. Pepper" src="http://www.codinghorror.com/blog/images/diet-cherry-chocolate-dr-pepper.jpg" width="147" height="400" border="0" />
<p>
(I am now required by law to link Tay Zonday's <a href="http://www.youtube.com/watch?v=2x2W12A8Qow">Cherry Chocolate Rain</a> video. My apologies in advance. And if that makes no sense to you, <a href="http://en.wikipedia.org/wiki/Chocolate_Rain">see here</a>.)
<p>
Are there meaningful differences between Microsoft's Team Foundation flavor of version control and Subversion? The short answer is that there aren't -- <b>if all you're looking for is a carbonated beverage</b>. If all you require is run of the mill, basic centralized source control duties, they're basically the same product. So why not go with the free one?
<p>
But Team Foundation is much more than just source control. Of course there are open source equivalents to much of the functionality offered in Team System, as Ryan is quick to point out.
<p>
<blockquote>
The Codeplex staff stated they needed to write their own client in order to integrate with the TFS server infrastructure. According to an MSDN article (<a href="http://msdn.microsoft.com/msdnmag/issues/06/00/TeamSystem/default.aspx">Get All Your Devs In A Row With Visual Studio 2005 Team System</a>), TFS seems to be a complicated tool to help manage your developers. Reading the description, TFS is an issue tracker, unit tester, continuous integration, source control system, and Visual Studio plugin. So, basically a combination of <a href="http://trac.edgewall.org/">Trac</a>, <a href="http://www.nunit.org/">NUnit</a>, <a href="http://cruisecontrol.sourceforge.net.">CruiseControl.NET</a>, <a href="http://subversion.tigris.org/">Subversion</a>, and a Visual Studio plugin. Why not just write the Visual Studio plugin, and hook into the tools people are already using? All those tools have rich plugin-architectures that would probably support any sensible addition you'd want to make. 
</blockquote>
<p>
The answer, of course, is that Microsoft does all that painful integration work for you -- at a price.
<p>
If you have the time to look closer, you'll find more flavorful differences between Subversion and TFS source control. Differences more akin to, say, Dr. Pepper and Mr. Pibb.
<p>
<img alt="Mr. Pibb" src="http://www.codinghorror.com/blog/images/mr-pibb.jpg" width="234" height="406" border="0" />
<p>
I'm not going to enumerate all the subtle and not-so-subtle differences between the two here; picking a fight between two modern centralized version control systems is not my goal. They're both great. Choose whatever modern source control system you prefer, and <a href="http://www.ericsink.com/scm/source_control.html">take the time to learn it in depth</a>. Source control is the <a href="http://www.codinghorror.com/blog/archives/000660.html">bedrock of modern software engineering</a>, and I've found precious few developers that truly understand how it works. All that time we were going to spend arguing whether your source control system can beat up my source control system? I've got a radical idea: let's spend it on <i>learning the damn stuff</i> instead.
<p>
Still, there is a much deeper, more endemic problem here that Ryan alludes to, and it deserves to be addressed.
<p>
One of Microsoft's biggest challenges in the last few years has been that <b>its competitors are free to ship what are, by now, fairly mature open source components as parts of their operating systems.</b> When was the last time you ever saw any open source <i>anything</i> shipping in a Microsoft product? On some deep, dark corporate level, Microsoft must feel compelled to rewrite everything to completely own the source code. Sometimes -- a more cynical person might say "often" -- this results in poor quality copies instead of actual innovation, such as Microsoft's <a href="http://blogs.msdn.com/nnaderi/archive/2007/02/01/mstest-vs-nunit-frameworks.aspx">much-maligned MSTest unit test framework</a>. It's a clone of <a href="http://www.nunit.org/index.php">NUnit</a> with all new bugs and no new features, but it <i>can</i> be included in the box with Visual Studio and integrated into the product. It's a one step forward, two steps back sort of affair.
<p>
Everybody I know -- including our own Stack Overflow team -- who has tried to use the MSTest flavor of unit tests has <b>eventually thrown up their arms and gone back to NUnit</b>. It's just too painful; the commercial clone lacks the simplicity, power, and community support of the original open source version. There's simply no <i>reason</i> for MSTest to exist except to satisfy some bizarre corporate directive that Microsoft never ship open source code in their products. Furthermore, this blind spot hampers obvious integration points. Microsoft could build first-class integration points for NUnit into Visual Studio. But they haven't, and probably never will, because so much effort is poured into maintaining the second-rate MSTest clone.
<p>
In fact, the more I think about this, the more I think Microsoft's utter inability to integrate open source software <i>of any kind whatsoever</i> into their products <b>might just end up killing them</b>. It's a huge problem, and it's only going to get worse over time. Open source seems to evolve according to a different power law than commercial software. If I worked in the upper echelons of Microsoft, I'd be looking at the graph of open source software growth from the years of 1999 to 2008 and crapping my pants right about now.
<p>
It's a shame, because the best way to "beat" open source is to join 'em -- to integrate with and ship open source components as a part of your product. Unfortunately, that's the one route that Microsoft seems hell bent on never following.
<p>
<font color="red">Update:</font> For background, do read Jon Galloway's explanation: <a href="http://weblogs.asp.net/jgalloway/archive/2007/05/02/why-microsoft-can-t-ship-open-source-code.aspx">Why Microsoft Can't Ship Open Source Code</a>.
<p>
<table><tr><td class="sidead">
[advertisement] Complimentary paperback book on lightweight peer code review.  10 essays from industry experts.  Free shipping.  <a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+2">Order <i>Best Kept Secrets of Peer Code Review</i></a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001144.html</guid>
         <pubDate>Wed, 02 Jul 2008 23:59:59 -0800</pubDate>
      </item>
      <item>
         <title>Alan Turing, the Father of Computer Science</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001143.html</link>
         <description><![CDATA[<p>
Charles Petzold was kind enough to send me a copy of his new book, <a href="http://www.amazon.com/dp/0470229055/?tag=codinghorror-20">The Annotated Turing: A Guided Tour Through Alan Turing's Historic Paper on Computability and the Turing Machine</a>.
<p>
<a href="http://www.amazon.com/dp/0470229055/?tag=codinghorror-20"><img alt="The Annotated Turing: A Guided Tour Through Alan Turing's Historic Paper on Computability and the Turing Machine" src="http://www.codinghorror.com/blog/images/the-annotated-turing-cover.jpg" width="330" height="495" border="0" /></a>
<p>
One look at <a href="http://www.turingarchive.org/viewer/?id=466&title=01a">the original title page</a> of Turing's paper is enough to convince me that we're fortunate to have a guide as distinguished and patient as Charles. You know you're in trouble when the very first page opens with <a href="http://en.wikipedia.org/wiki/Entscheidungsproblem">"Entscheidungsproblem"</a>.
<p>
<a href="http://www.turingarchive.org/viewer/?id=466&title=01a"><img alt="on computable numbers with an application to the Entscheideungsproblem" src="http://www.codinghorror.com/blog/images/on-computable-numbers-with-an-application-to-the-entscheideungsproblem-1.jpg" width="600" height="89" border="0" /></a>
<p>
The computer you're using to read this post is <b>based on the mathematical model laid out in that thirty-six page 1936 paper</b>. As are all other computers in the world. The terms <a href="http://en.wikipedia.org/wiki/Turing_machine">Turing Machine</a> and <a href="http://en.wikipedia.org/wiki/Turing_completeness">Turing Complete</a> are both derived from that one historic paper.
<p>
Needless to say, we owe <a href="http://en.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> a lot. 
<p>
<a href="http://en.wikipedia.org/wiki/Alan_Turing"><img alt="photo of Alan Turing" src="http://www.codinghorror.com/blog/images/alan-turing-photo-1.jpg" width="300" height="330" border="0" /></a>
<p>
Not only is Alan Turing <b>the father of all modern computer science</b>, he also was the single individual most responsible for <a href="http://www.ellsbury.com/enigmabombe.htm">breaking the Enigma code</a> during World War II, and he laid the foundation for artificial intelligence by <a href="http://en.wikipedia.org/wiki/Turing_test#Alan_Turing">posing the Turing Test</a> in 1950.
<p>
Unfortunately, Alan Turing was also terribly persecuted for the "crime" of being a homosexual. He was arrested in 1952 for having sex with another man. It pains me greatly to <a href="http://www.charlespetzold.com/blog/2008/06/Gay-Rights-and-the-Prosecution-of-Alan-Turing.html">read about the degrading and inhumane treatment</a> one of our greatest scientific minds was subjected to. Alan Turing ultimately committed suicide not long afterwards at the age of 42.
<p>
The "nobel prize of computing" was founded in Turing's name in 1966. Reading the list of <a href="http://en.wikipedia.org/wiki/Turing_Award">Turing Award</a> recipients is humbling indeed, a reminder of not only how far we've come, but how far we have to go.
<p>
<img alt="Alan Turing statue" src="http://www.codinghorror.com/blog/images/alan-turing-statue.jpg" width="386" height="434" border="0" />
<p>
The <a href="http://en.wikipedia.org/wiki/Alan_Turing_Memorial">Alan Turing Memorial</a>, erected in 2001, bears this Bertrand Russell quote:
<p>
<blockquote>
Mathematics, rightly viewed, possesses not only truth, but supreme beauty -- a beauty cold and austere, like that of sculpture.
</blockquote>
<p>
You'll note that the statue depicts Turing holding an apple in his right hand, a reference to the way he chose to end his life -- by eating a cyanide-laced apple. That was Turing's last message to the world, with clear parallels not only to the legendary scientific knowledge of Isaac Newton, but also the biblical interpretation of forbidden love.
<p>
Petzold's <a href="http://www.amazon.com/dp/0470229055/?tag=codinghorror-20">Annotated Turing</a> is a gripping testament to the amazing mind of Alan Turing. Writing the book was a <a href="http://www.charlespetzold.com/blog/2008/06/Hot-Off-the-Presses.html">nine year labor of love</a>, and it shows. It may be his <a href="http://www.charlespetzold.com/blog/2008/05/The-300-Page-Ideal.html">shortest book</a> -- but it could also be his best yet.
<p>
<table><tr><td class="sidead">
[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning <a href="http://smartbear.com/codecollab.php?chblog1">Code Collaborator</a>.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001143.html</guid>
         <pubDate>Tue, 01 Jul 2008 19:15:58 -0800</pubDate>
      </item>
      <item>
         <title>Open Wireless and the Illusion of Security</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001141.html</link>
         <description><![CDATA[<p>
<a href="http://en.wikipedia.org/wiki/Bruce_Schneier">Bruce Schneier</a> is something of a legend in the computer security community. He's the author of the classic, oft-cited 1994 book <a href="http://www.amazon.com/exec/obidos/ASIN/0471117099/codinghorror-20">Applied Cryptography</a>, as well as several well-known cryptography algorithms.
<p>
<a href="http://geekz.co.uk/shop/store/show/schneier-tshirt"><img alt="Bruce Schneier knows Alice and Bob's shared secret" src="http://www.codinghorror.com/blog/images/bruce-schneier-knows-alice-and-bobs-shared-secret.png" width="237" height="381" border="0" /></a>
<p>
The cheeky <a href="http://www.chucknorrisfacts.com/">Norris</a>-esque design above is a reference to the actor names commonly used in examples of <a href="http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange#Description">shared secret key exchange</a>.
<p>
What I find most interesting about Bruce, however, is that he has moved beyond treating computer security as a problem that can be solved with increasingly clever cryptography algorithms:
<p>
<blockquote>
<b>Schneier now denounces his early success as a naive, mathematical, and ivory tower view of what is inherently a people problem</b>. In <a href="http://www.amazon.com/exec/obidos/ASIN/0471117099/codinghorror-20">Applied Cryptography</a>, he implies that correctly implemented algorithms and technology promise safety and secrecy, and that following security protocol ensures security, regardless of the behavior of others. Schneier now argues that the incontrovertible mathematical guarantees miss the point. As he describes in <a href="http://www.amazon.com/exec/obidos/ASIN/0471453803/codinghorror-20">Secrets and Lies</a>, a business which uses RSA encryption to protect its data without considering how the cryptographic keys are handled by employees on "complex, unstable, buggy" computers has failed to properly protect the information. An actual security solution that includes technology must also take into account the vagaries of hardware, software, networks, people, economics, and business. 
</blockquote>
<p>
This is the programming equivalent of <b>realizing that <a href="http://www.codinghorror.com/blog/archives/000601.html">Peopleware</a> is ultimately a much more important book than <a href="http://www.codinghorror.com/blog/archives/001034.html">The Art of Computer Programming</a>.</b> The shift in focus from algorithms to people is even more evident if you frequent <a href="http://www.schneier.com/blog/">Bruce's excellent blog</a>, or read his newest books <a href="http://www.amazon.com/exec/obidos/ASIN/0471223573/codinghorror-20">Practical Cryptography</a> and <a href="http://www.amazon.com/exec/obidos/ASIN/0387026207/codinghorror-20">Beyond Fear</a>.
<p>
As much as I respect Bruce, I was surprised to read that <a href="http://www.schneier.com/blog/archives/2008/01/my_open_wireles.html">he intentionally keeps his wireless network open</a>.
<p>
<blockquote>
Whenever I talk or write about my own security setup, the one thing that surprises people -- and attracts the most criticism -- is the fact that I run an open wireless network at home. There's no password. There's no encryption. Anyone with wireless capability who can see my network can use it to access the internet.
</blockquote>
<p>
I've advocated WiFi encryption from the day I owned my first wireless router. As I encountered fewer and fewer open WiFi access points over the years, I viewed it as tangible progress. Reading Bruce's opinion is enough to make me question those long held beliefs.
<p>
It's a strange position for a respected computer security expert to advocate. But I think I get it. Security is a tough problem. If you take the option of mindlessly flipping a <a href="http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access">WPA</a> or <a href="http://en.wikipedia.org/wiki/Wired_Equivalent_Privacy">WEP</a> switch off the table, you're now forced to think more critically about the security of not only your network, but also the fundamental security of the data on your computers. By advocating the radical idea that your wireless network should be <i>intentionally</i> kept open, Bruce is attempting to <b>penetrate the veil of false algorithmic security</b>.
<p>
I may understand and even applaud this effort, but I don't agree. Not because I'm worried about the security of my data, or any of the half-dozen other completely rational security arguments you could make against intentionally keeping an open wireless network. My concerns are more prosaic. <b>I desperately want to protect the thin sliver of upstream bandwidth my provider allows me</b>. Some major internet providers are also <a href="http://tech.slashdot.org/article.pl?sid=08/05/08/1410231">talking about monthly download caps</a>, too. Bruce's position only makes sense if you have effectively unlimited bandwidth in both directions. Basically, I'm worried about <a href="http://en.wikipedia.org/wiki/Tragedy_of_the_commons">the tragedy of the bandwidth commons</a>. As much as I might like my neighbors, they can pay for their own private sliver of bandwidth, or knock on my door and ask to share if they <i>really</i> need it.
<p>
So, to me at least, enabling wireless security is my way of ensuring that I get every last byte of the bandwidth I paid for that month.
<p>
It's worth realizing, however, that wireless security is no panacea, even in this limited role. Given a sufficiently motivated attacker, <a href="http://docs.lucidinteractive.ca/index.php/Cracking_WEP_and_WPA_Wireless_Networks">every wireless network is crackable</a>.
<p>
<a href="http://docs.lucidinteractive.ca/index.php/Cracking_WEP_and_WPA_Wireless_Networks"><img alt="Aircrack screenshot" src="http://www.codinghorror.com/blog/images/aircrack-screenshot.png" width="512" height="321" border="0" /></a>
<p>
With that in mind, here are a few guidelines.
<p>
<ol>
<li><b>WEP = Worthless Encryption Protocol</b>
<p>
WEP, the original encryption protocol for wireless networks, is so fundamentally flawed and so deeply compromised it should arguably be removed from the firmware of every wireless router in the world. It's possible to <a href="http://www.practicallynetworked.com/security/041207wpa_vs_wep.htm">crack WEP in under a minute</a> on any vaguely modern laptop. If you choose WEP, you have effectively chosen to run an open wireless network. There's no difference.
<p>
<li><b>WPA <i>requires</i> a very strong password</b>
<p>
The common "personal" (PSK) variant of WPA is quite vulnerable to brute force dictionary attacks. It only takes a trivial amount of wireless sniffing to obtain enough data to attack your WPA password <i>offline</i> -- which means an unlimited amount of computing power could potentially be marshalled against your password. While <a href="http://www.codinghorror.com/blog/archives/000986.html">brute force attacks are still for dummies</a>, most people are, statistically speaking, dummies. They <a href="http://www.schneier.com/blog/archives/2006/12/realworld_passw.html">rarely pick good passwords</a>. If ever there was a time to take my advice on <a href="http://www.codinghorror.com/blog/archives/000360.html">using long passphrases</a>, this is it. Experts recommend you <a href="http://wifinetnews.com/archives/002452.html">shoot for a 33 character passphrase</a>.
</ol>
<p>
In the end, perhaps wireless security is more of a deterrent than anything else, another element of defense in depth. It's important to consider the underlying message Bruce was sending: if you've enabled WEP, or WPA with anything less than a truly random passphrase of 33 characters, you don't have security.
<p>
You have the <i>illusion</i> of security.
<p>
And that is far more dangerous than no security at all.
<p>
<table><tr><td class="sidead">
[advertisement] Peer code review without meetings, paperwork, or stopwatches?  No wonder <a href="http://smartbear.com/codecollab.php?chblog4" rel="nofollow">Code Collaborator won the Jolt Award.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001141.html</guid>
         <pubDate>Sun, 29 Jun 2008 01:00:00 -0800</pubDate>
      </item>
      <item>
         <title>Regular Expressions: Now You Have Two Problems</title>
         <dc:creator>Jeff Atwood</dc:creator>
         <link>http://www.codinghorror.com/blog/archives/001016.html</link>
         <description><![CDATA[<p>
I love regular expressions. No, I'm not sure you understand: <a href="http://www.codinghorror.com/blog/archives/000245.html">I really <i>love</i> regular expressions</a>.
<p>
You may find it a little odd that a hack who grew up using <a href="http://blogs.vertigosoftware.com/jatwood/archive/2005/10/05/1514.aspx">a language with the ain't keyword</a> would fall so head over heels in love with something as obtuse and arcane as regular expressions. I'm not sure how that works. But it does. <b>Regular expressions rock</b>.They should absolutely be a key part of every modern coder's toolkit.
<p>
If you've ever talked about regular expressions with another programmer, you've invariably heard this 1997 chestnut:
<p>
<blockquote>
Some people, when confronted with a problem, think "I know, I'll use regular expressions."  Now they have two problems. 
</blockquote>
<p>
The quote is from Jamie Zawinski, a world class hacker who I admire greatly. If he's telling us not to use regular expressions, should we even bother? Maybe, if you live and die by soundbites. But there's a bit more to the story than that, as evidenced by <a href="http://regex.info/blog/2006-09-15/247">Jeffrey Friedl's exhaustive research on the Zawinski quote</a>. Zawinski himself <a href="http://regex.info/blog/2006-09-15/247#comment-3085">commented</a> on it. Analyzing the full text of Jamie's posts in the original 1997 thread, we find the following:
<p>
<blockquote>
Perl's nature encourages the use of regular expressions almost to the exclusion of all other techniques; they are far and away the most "obvious" (at least, to people who don't know any better) way to get from point A to point B.
</blockquote>
<p>
The first quote is too glib to be taken seriously. But this, I completely agree with. Here's the point Jamie was trying to make: <b>not that regular expressions are evil, per se, but that <i>overuse</i> of regular expressions is evil.</b>
<p>
I couldn't agree more. Regular expressions are like a particularly spicy hot sauce -- to be used in moderation and with restraint only when appropriate.  Should you try to solve every problem you encounter with a regular expression? Well, no. Then you'd be writing <a href="http://en.wikipedia.org/wiki/Perl">Perl</a>, and I'm not sure you need those kind of headaches. If you drench your plate in hot sauce, you're going to be very, very sorry later.
<p>
<img alt="hot sauce" src="http://www.codinghorror.com/blog/images/hotsauce.jpg" width="460" height="445" border="0" />
<p>
In the same way that I can't imagine food without a dash of hot sauce now and then, I can't imagine programming without an occasional regular expression. It'd be a bland, unsatisfying experience.
<p>
But wait! Let me guess! The last time you had to read a regular expression and figure it out, your head nearly exploded! Why, it wasn't even code; it was just a bunch of unintelligible <a href="http://www.codinghorror.com/blog/archives/000214.html">Q*Bert line noise!</a>
<p>
Calm down. Take a deep breath. Relax.
<p>
Let me be very clear on this point: If you read an incredibly complex, impossible to decipher regular expression in your codebase, <b>they did it wrong</b>. If you write regular expressions that are difficult to read into your codebase, <b><i>you</i> are doing it wrong</b>.
<p>
Look. Writing so that people can understand you is <i>hard</i>. I don't care if it's code, English, regular expressions, or Klingon. Whatever it is, I can show you an example of someone who has written something that is pretty much indistinguishable from gibberish in it. I can also show you something written in the very same medium that is so beautiful it will make your eyes water. So the argument that regular expressions are somehow fundamentally impossible to write or read, to me, holds no water. Like everything else, it just takes a modicum of skill.
<p>
Buck up, soldier. Even Ruby code is hard to read until you learn the symbols and keywords that make up the language. If you can learn to read code in whatever your language of choice is, you can <i>absolutely</i> handle reading a few regular expressions. It's just not that difficult. I won't bore you with a complete explanation of the dozen or so basic elements of regular expressions; Mike already covered this ground better than I can:
<p>
<ul>
<li><a href="http://immike.net/blog/2007/04/06/the-absolute-bare-minimum-every-programmer-should-know-about-regular-expressions/">The absolute bare minimum every programmer should know about regular expressions</a>
<li><a href="http://immike.net/blog/2007/04/06/5-regular-expressions-every-web-programmer-should-know/">5 regular expressions every web programmer should know</a>
<li><a href="http://immike.net/blog/2007/06/21/extreme-regex-foo-what-you-need-to-know-to-become-a-regular-expression-pro/">Extreme regex-fu: what you need to know to become a regular expression pro</a>
</ul>
<p>
I'd like to illustrate with an actual example, a regular expression I recently wrote to strip out dangerous HTML from input. This is extracted from <a href="http://refactormycode.com/codes/333-sanitize-html">the SanitizeHtml routine</a> I posted on RefactorMyCode.
<p>
<pre>
var whitelist =
 @"&lt;/?p&gt;|&lt;br\s?/?&gt;|&lt;/?b&gt;|&lt;/?strong&gt;|&lt;/?i&gt;|&lt;/?em&gt;|
  &lt;/?s&gt;|&lt;/?strike&gt;|&lt;/?blockquote&gt;|&lt;/?sub&gt;|&lt;/?super&gt;|
  &lt;/?h(1|2|3)&gt;|&lt;/?pre&gt;|&lt;hr\s?/?&gt;|&lt;/?code&gt;|&lt;/?ul&gt;|
  &lt;/?ol&gt;|&lt;/?li&gt;|&lt;/a&gt;|&lt;a[^&gt;]+&gt;|&lt;img[^&gt;]+/?&gt;";
</pre>
<p>
What do you see here? The variable name whitelist is a strong hint. One thing I like about regular expressions is that they generally look like what they're matching. You see a list of HTML tags, right? Maybe with and without their closing tags? 
<p>
Honestly, is this so hard to understand? To me it's perfectly readable. But we can do better. In most modern regex dialects, you can flip on a mode where whitespace is no longer significant. This frees you up to <b>use whitespace and comments in your regular expression</b>, like so.
<p>
<pre>
var whitelist =
 @"&lt;/?p&gt;|
   &lt;br\s?/?&gt;| (?# allow space at end)
   &lt;/?b&gt;|
   &lt;/?strong&gt;|
   &lt;/?i&gt;|
   &lt;/?em&gt;|
   &lt;/?s&gt;|
   &lt;/?strike&gt;|
   &lt;/?blockquote&gt;|
   &lt;/?sub&gt;|
   &lt;/?super&gt;|
   &lt;/?h(1|2|3)&gt;| (?# h1,h2,h3)
   &lt;/?pre&gt;|
   &lt;hr\s?/?&gt;|  (?# allow space at end)
   &lt;/?code&gt;|
   &lt;/?ul&gt;|
   &lt;/?ol&gt;|
   &lt;/?li&gt;|
   &lt;/a&gt;|
   &lt;a[^&gt;]+&gt;|  (?# allow attribs)
   &lt;img[^&gt;]+/?&gt; (?# allow attribs)
   ";
</pre>
<p>
Do you understand it now? All I did was add a smattering of comments and a lot of whitespace. The same exact technique I would use on any code, really.
<p>
But how did I cook up this regular expression? How do I know it does what I think it does? How do I test it? Well, again, I do that the same way I do with all my other code: I use a tool. My tool of choice is <a href="http://www.regexbuddy.com/">RegexBuddy</a>.
<p>
<a href="http://www.regexbuddy.com/"><img alt="regexbuddy whitelist example" src="http://www.codinghorror.com/blog/images/regexbuddy-whitelist-example.png" width="303" height="472" border="0" /></a>
<p>
Now we get <b>syntax highlighting</b> and, more importantly, <b>real time display of matches</b> there at the bottom in our test data as we type. This is huge. If you're wondering why your IDE doesn't automatically do this for you with any regex strings it detects in your code, tell me about it. I've been wondering that very same thing for years.
<p>
RegexBuddy is far and away the best regex tool on the market in my estimation. Nothing else even comes close. But it does cost money. If <a href="http://www.codinghorror.com/blog/archives/001097.html">you don't use software that costs money</a>, there are plenty of <a href="http://regexpal.com/">alternatives</a> out there. You wouldn't read or write code in notepad, right? Then why in the world would you attempt to read or write regular expressions that way? Before you complain how hard regular expressions are to deal with, <b>get the right tools!</b>
<p>
This trouble is worth it, because regular expressions are incredibly powerful and succinct. How powerful? I was able to write a no-nonsense, special purpose HTML sanitizer in about 25 lines of code and four regular expressions. Compare that with a general purpose HTML sanitizer which would take hundreds if not <i>thousands</i> of lines of procedural code to do the same thing.
<p>
I do have some tips for keeping your sanity while dealing with regular expressions, however:
<p>
<ol>
<li><b>Do <u>not</u> try to do everything in one uber-regex.</b> I know you <i>can</i> do it that way, but you're not going to. It's not worth it. Break the operation down into several smaller, more understandable regular expressions, and apply each in turn. Nobody will be able to understand or debug that monster 20-line regex, but they might just have a fighting chance at understanding and debugging five mini regexes.
<p>
<li><b>Use whitespace and comments.</b> It isn't 1997 any more. A tiny ultra-condensed regex is no longer a virtue. Flip on the <code>IgnorePatternWhitespace</code> option, then use that whitespace to make your regex easier for us human beings to parse and understand. Comment liberally.
<p>
<li><b>Get a regular expression tool.</b> I don't stare at regular expressions and try to suss out their meaning through sheer force of will. Neither should you. It's a waste of time. I paste them into my regex tool of choice, RegexBuddy, which not only tells me what the regular expression does, but lets me step through it, and run it through some test data. All in real time as I type.
<p>
<li><b>Regular expressions are not Parsers.</b> Although you can do some amazing things with regular expressions, they are weak at balanced tag matching. Some regex variants <a href="http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx">have balanced matching</a>, but it is clearly a hack -- and a nasty one. You can often make it kinda-sorta work, as I have in the sanitize routine. But no matter how clever your regex, don't delude yourself: it is in no way, shape or form a substitute for a real live parser.
</ol>
<p>
If you're afraid of regular expressions, don't be. Start small. Used responsibly and with the right tooling they are big, powerful -- dare I say, <i>spicy</i> -- wins. If you make regular expressions a part of your toolkit, you'll be able to write less code that does more. It'll just.. taste batter.
<p>
You might enjoy them so much, in fact, that you completely forget about that "second problem".
<p>
<table><tr><td class="sidead">
[advertisement] Read the largest case study ever published about lightweight peer code review in <a href="http://smartbearsoftware.com/codecollab-code-review-book.php?howheard=Coding+Horror+Blog+3" rel="nofollow">Best Kept Secrets of Peer Code Review</a>. Free book, free shipping.
</td></tr>
</table>
<p>]]></description>         
         <guid>http://www.codinghorror.com/blog/archives/001016.html</guid>
         <pubDate>Fri, 27 Jun 2008 10:00:00 -0800</pubDate>
      </item>

   <feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetFeedData?uri=codinghorror</feedburner:awareness></channel>
</rss>
