However, I strongly disagree with the "good code / bad code" dichotomy the author presents. Asynchronous, callback-based code is frequently more difficult to write, harder to reason with, more inflexible, and buggier than similar synchronous code. That said, moving to event-based code has generally been worth the cost for us, yielding improvements in performance and reliability that make up for the increase in developer time required.
The problem is that it's often very difficult to refactor synchronous code to be event-based since it requires an inversion of control. An attempt at changing clear, intention-revealing synchronous code to work asynchronously frequently results in ugly, hard-to-follow callback hell. Worse, a single piece of blocking code left inside the event loop can now render all of the work you've done moot, meaning such refactorings tend to sprawl.
This is why I think attempts to bridge this gap, making asynchronous read more-or-less the same way as asynchronous code, are very valuable. Scala's delimited continuations, coming in the upcoming 2.8 (http://www.scala-lang.org/node/2096), could help take a lot of the pain out of using event-based servers effectively.