tag:blogger.com,1999:blog-383638272008-05-12T03:56:07.212-07:00Code on the RoadJason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-38363827.post-57012114554690956662008-05-08T10:33:00.000-07:002008-05-08T11:05:36.878-07:00Laid off? The one thing you absolutely need to do on the first dayYou're in IT, right? So chances are you've been laid off at least once from some crappy company and it's going to happen again. Here is my one piece of advice to you. The single most important thing to do as soon as you make it back to your house with that box full of stuff: <p/> <div style='font-size:200%;font-weight:bold;text-align:center;border:solid 1px #ccc'>Book a flight</div> <p/> Seriously. Do it now, before the initial shock wears off and that logical side of your brain starts coming up with lame excuses. You will never have a better chance to get out and see the world than right now. You have a pile of saving and a severance package. You've got 6 months to a year before your skills start getting rusty. There is absolutely no reason to start looking for work immediately, and every reason to take that round-the-world trip you've always dreamed about. Right. Now. <p/> Trust me, your career will be just fine. <p/> <h3>Where to go</h3> This is the easiest question to answer: <a href="http://www.blogabond.com/Thailand/Bangkok">Bangkok</a>. Seriously, the mere fact that you had to ask the question indicates that you're probably not a seasoned traveler and therefore should be going to Thailand first. I know you always wanted to do Europe, but it's crazy expensive and frankly, it's just not relaxed enough for you right now. You're going to need some serious chilling to recover from a layoff. Southeast Asia has that in Spades. <p/> Make your way to Ko San Road, find a room, grab a Beer Chiang and talk to a few other travelers. Your trip will plan itself from there. <p/> <h4>Where to go if it's May</h4> Ok, one modification to the above. Thailand is thoroughly uninhabitable for a few months between May and July. In that case, you're going to Africa. Book a flight to Cape Town instead. Follow <a href="http://www.blogabond.com/TripView.aspx?tripID=6">this itinerary</a> up through Zambia, Malawi and Tanzania. Everybody there speaks English and you can get a room for $0.75. You'll do fine. <p/> <h3>How long to go for</h3> You're going to want to stay gone for 6-9 months. Less than that and it you'll be kicking yourself for not leaving enough time, and you'll be rushing through entire countries just to keep up with your itinerary. I know that this seems silly now, but somewhere along the way somebody will ask how long you've been in Vietnam for and you'll answer "Only one month." Timescales work differently on the road. <p/> In my experience (did I mention that I take about 9 months vacation a year and spend most of that traveling in the developing world?), I tend to start missing work after about 6 months away. By 9 months, I'm pretty much ready to commit to a real job in a real office just so that I can start using my brain again. Talking to other software guys on the road, it seems that this pretty common. You're going to want to come back eventually, so be sure to keep a few good contacts back home. <p/> Regardless of how long you plan to be gone, <a href="http://www.blogabond.com/CommentView.aspx?CommentID=8226">try to book your flight one-way</a>. It will give you unlimited flexibility with your travel plans and let you pick your return date later when you know what you actually want to do. As a last resort, pick the return date furthest in the future, since it's a lot easier to move it forward than to push it back. <p/> <h3>How much will it cost?</h3> I budget about $1,000 a month when I'm traveling in Southeast Asia, Central America, Africa or the Middle East. I seldom go through that much if I'm sticking to ground transport, but over the course of a year if you consider flights into the calculations, $1,000 a month is about right. <b>Stay away from the developed world</b> at all costs though, or you'll quickly triple that figure! <p/> <h3>How do I get another job when I get back?</h3> The nice thing about a 6 month timeframe is that it gives all of your ex-coworkers time to entrench themselves in other hopeless software companies. Email them and notice how everything around them seems to be on fire. They need you to start tomorrow. Line up a good offer based on one of their recommendations and book a flight home. <p/> <h3>Three Lame Excuses and why they're not valid:</h3> <h4>But I don't have any money saved...</h4> You can't possibly be serious. Are you saying that you've been working in IT for all these years and haven't put away a lousy ten grand??? Shame on you. Get a book on life skills and open a bank account fer cryin' out loud. <p/> <h4>But nobody will hire me after six months away...</h4> Not true. Nobody will hire you if you're bad at what you do and have terrible interviewing skills. Those things won't change over the course of six months, but you might possibly wind up more relaxed (and with some good stories to tell) and that's actually a benefit when it comes to interviewing. <p/> Regardless of what you may have heard, <a href="http://www.expatsoftware.com/articles/2007/02/two-weeks-vacation-is-only.html">skilled developers are very hard to find</a>. If you fit that category, there's very little that you can do to poison your resume. Certainly, heading off on your once-in-a-lifetime trip won't leave you unemployable. <p/> <h4>But I'm married with a family and a house...</h4> Ok, you win. You're screwed, but that's the life you chose for yourself so you're going to have to live it. It's worth noting, however, that most Europeans wouldn't consider that a reason not to travel. Right this second, there is a German couple pushing a stroller down a remote beach in Thailand, and they're not going home for another month. What's your excuse again? <p/> <h3>Why you're not actually going to do it</h3> When you get right down to it, you'll probably find a way to talk yourself out of taking that dream trip. You'll come up with some pretty believable excuses, but really it will come down to the fact that you're scared. <p/> That's cool. Travel is pretty scary when you look at it from the outside. But here's the thing. It stops being scary the moment your feet hit the pavement on Ko San Road in Bangkok. You're going to get blasted by 100 degree heat, power-wafted by smells of the most amazing street food one minute and an open sewer the next, assaulted with music from a thousand bars, and crammed into a tiny room overlooking it all with a fan that doesn't work. And you won't be able to wipe the silly grin off your face. <p/> Book the flight today, because every day you delay it is one more day wasted on the couch, and one more day to come up with lame excuses for why you shouldn't go. <p/> It is all good here. Get your ass on a plane. <p/>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-78531441896061553412008-05-03T08:43:00.000-07:002008-05-03T08:53:27.950-07:00No MagicPHP used to have a cool little feature where it would automatically detect single quotes in text strings and escape them for you whenever they needed to be. It was called Magic_quotes_runtime. Maybe you've heard of it. <a href="http://www.google.com/search?q=magic_quotes_runtime+bug">It was a disaster</a>. <p/> Countless developer hours were spent trying to chase down mysterious runtime errors where single quotes were either introduced, doubled up, or removed, causing disastrous crashes, data corruption and so much untold havoc that the feature was deprecated and eventually <a href="http://es.php.net/manual/en/info.configuration.php#ini.magic-quotes-runtime">removed from PHP entirely</a>. <p/> You would think that people would have learned their lesson. <p/> People are, by and large, dumb. We make the same dumb mistakes over and over again because we didn't bother to do any research or read about the last time that somebody tried whatever stupid idea we just re-invented. As a result, we have development frameworks and tools like <a href="http://www.google.com/search?hl=en&q=java+hibernate+bug">Hibernate</a>, ASP.NET's <a href="http://www.google.com/search?hl=en&q=smartnavigation+bug">SmartNav</a>, and Rails' <a href="http://www.google.com/search?hl=en&q=rails+activerecord+bug">ActiveRecord</a>, all trying to magically solve problems that weren't very hard in the first place, and silently making a lot of people's lives a lot harder without them even realizing it. <p/> The big problem with Magic tools is that they work fine the first time you try them. "Wow!", you say, " It posted the page back and scrolled my browser back down to the Submit button!" So you turn that feature on for all your pages and start to trust it. You get used to it. You take it for granted. You forget you're even using it. Then suddenly something weird starts happening with one of your pages and you can't figure out why. <p/> Examples of this sort of side effect abound, but nobody yet has taken a stand and done something about it. How many developer hours have been lost trying to figure out what magical SQL statement was running behind the scenes and only “Hibernating” half of an object? How many CPU cycles have been squandered (and slanderous blog entries written) because some poor developer didn’t realize that ActiveRecord was hitting the database three times for every single row in that recordset? Are we really so scared of Outer Joins that we allow ourselves to be subject to this torment? <p/> I’ll leave you with an axiom that I’ve been telling developers for years without much success. Call it Kester’s Caution: <p/> <div style="border:solid 1px #cccccc;padding:5px;margin:5px;background:#f0f0f0"> <b>Never use any language feature that describes itself as "Smart" or "Magic."</b> Such features will invariably be trying to abstract out some behavior that is not that hard to deal with anyway, and will make any number of incorrect assumptions about your application that will result in strange behavior cropping up that could possibly be described as "Magic", but certainly would never be labeled "Smart". </div>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-78274902992066062812008-03-21T13:34:00.000-07:002008-03-22T16:50:29.729-07:006 million hits a day. Time to think scale!<a href="http://twiddla.blogspot.com/2008/03/oh-yeah-we-won.html" style="float:right"><img src="http://img.twiddla.com/blog/2008_web_awards.jpg" border=0></a> <a href="http://www.twiddla.com/">Twiddla</a> has been getting a ton of attention this week. We picked up the <a href="http://2008.sxsw.com/interactive/web_awards/winners/">Technical Achievement award at SXSW Interactive</a>, and have been getting a bunch of good press ever since. 25,000 people have signed up for the service since the award was mentioned, with 7,500 of those signups happening in a single day. It's about to get good. <p/> For me though, it's been even better. We're finally getting enough traffic to start thinking about scaling issues. You might remember an article that I wrote a few months back, where I told people <a href="http://www.expatsoftware.com/articles/2007/06/getting-your-priorities-straight.html">not to sweat Performance and Scaling issues too much</a>, but rather to focus on Readability, Debugability, Maintainability, and Development Pace. The idea was that getting your product to market quickly and being able to move fast if necessary are more important than having the Perfect Dream System that takes forever to build. Of course, the implied point was that when and if that Big Day came, you'd be able to move fast enough to deal with Scalability and Performance concerns as they appeared. <p/> On March 12th, 2008, I got to see first hand whether I was talking out my arse… <p/> <h2>3/11/2008 7:00pm: 150 signups/hr, 50 hits/sec, 0-5% CPU</h2> It's the day after the awards, and the first brief announcements are out. Traffic has been building steadily all day, but we've seen worse. The only crisis at the moment is that we don't yet have a <a href="http://www.twiddla.com/wiki/about-us.ashx">Press Kit</a>, so we're seeing writeups with the old logo and screenshots from the old UI. D'oh! <p/> <h2>3/11/2008 11:00pm: 350 signups/hr, 120 hits/sec, 1-9% CPU</h2> Japan wakes up. The Asian press really liked us, so we saw a big spike in users from China and Japan the first few days. <a href="http://www.twiddla.com/Demo/Sandbox.aspx">The sandbox</a> is pretty clogged, and with 30 people drawing simultaneously it's starting to tax people's browsers. Every once in a while, somebody navigates the sandbox over to a porn site, and people write our support line to complain. We're wiping the sandbox every 5 minutes, but it's still not acceptable. Gotta get a handle on that. <p/> <a href="http://jas9.blogspot.com/2008/03/twiddla.html"><img src="http://img.twiddla.com/blog/twiddla_mr_sparkle.png" border=0></a> <p/> <h2>3/12/2008 9:00am: 300 signups/hr, 100 hits/sec, 1-6% CPU</h2> The sandbox is completely overloaded. There are 100 people in there, which is too many people communicating at once for any medium to really handle. Imagine 100 people drawing on a real whiteboard at the same time, or 100 people talking over each other on a conference call. It just doesn't work. To bring a little order into the picture, I fire up the Visual Studio.NET and add a little switcher that will direct traffic to any one of 5 sandboxes, each one holding 8 users. Throw that live, and now there are 5 overloaded sandboxes. <p/><h2> 3/12/2008 9:30am: 500 signups/hr, 300 hits/sec, 3-15% CPU</h2> I bump up the sandbox count to 10. Then think better of it and bump it up to 20 before pushing. Then think better of THAT and add a new page to show users in case all 20 of those sandboxes fill up. Push that live. <p/><h2> 3/12/2008 9:41am</h2> Testing out the above changes, I am immediately redirected to a page saying "Sorry, all the Sandboxes are full." Let me restate that: From the time I pushed those changes live to the time I could test them out, 160 people had beaten me into the sandboxes. Wow. <p/><h2> 3/12/2008 10:00am: 700 signups/hr, 500 hits/sec, 5-20% CPU</h2> Looking through the error logs, I'm starting to see our first concurrency issues. These are the little one-in-a-million things that you'd never find in test, but that happen every ten minutes under load. They're mostly low-hanging fruit, so I spend the next hour patching and re-deploying until the error logs go silent. <p/><h2> 3/12/2008 12:00pm: 600 signups/hr, 400 hits/sec, 5-17% CPU</h2> I'd been doing all of this from my sister's house up in Ft. Worth, who I had supposedly been visiting for a couple days, but whose house I had been mostly using for an office (thanks Lisa for tolerating that, and I promise to get out and visit sometime when I'm not trying to launch a new website!) Now I had to hop in the car and drive back to Austin to fly home. Our trusty server will be on its own for the next 12 hours, taking the beating of its life. I won't even know if it goes down. <p/><h2> 3/13/2008 4000 signups/day, 100 hits/sec, 3-10% CPU</h2> <a href="http://img.twiddla.com/blog/twiddla_art_1_800.jpg" style="float:right"><img src="http://img.twiddla.com/blog/twiddla_art_1.jpg" border=0><br>Twiddla Art</a>Back in a stable place, and ready to deal with the flood of feedback emails we've been getting. This part is fun, since most people have nice things to say, and it becomes readily apparent what features everybody wants to see. Nothing has broken, so I actually have some time to put a few minor features live. The "Wite-out" button was added this day, I think, and I re-did the way we handle snapshots and image exporting. <p/><h2> 3/14/2008 3000 signups/day, 100 hits/sec, 2-5% CPU</h2> I implemented a fix for the last little concurrency bug that we'd been seeing. Then, while profiling that fix on the server, I noticed that TwiddleBot was flipping out. TwiddleBot is the little service that runs the Guided Tour feature, and is also responsible for clearing out the sandboxes from time to time. Turns out, he was also pounding the database 20 times a second, asking for instructions. Hmm… Chill, TwiddleBot. Pushed a fix for that, and suddenly CPU usage dropped to zero. Like, ZERO! Every 5 seconds, it would spike up to 1%. Cool. I think we're gonna be able to scale this thing… <p/><h2> One week later, ~1000 signups per day, 50 hits/sec, 0% CPU</h2> In the end, we came through our first little scaling event rather well. We were actually a bit over-prepared. Our colocation facility (<a href="http://www.easystreet.com/">Easystreet</a> in Beaverton, Oregon) had a couple extra boxes waiting to go for us, and I had taken the time a week earlier to write up and test a little software load balancer to allocate whiteboard sessions to various boxes when needed. In the end, we didn't get to try any of that out. Hell, we never spiked the processor on our one server over 50%. I'd love to congratulate myself for the design choices I made all those months back when I wrote that article, but I think it's still too early in the game to conclude that we'll really scale when we ramp up to the next level. <p/> Still, it's worth noting that everything in Twiddla was built using the simple, Readable, Debuggable backend that we've been using on our more pedestrian sites for years, and it held up just fine under traffic. When it turned out that parts of that backend needed refactoring to handle the kind of concurrency we saw last week, it was a simple 5 minute task to crack open the code, find what needed to change, and change it. <p/> Readable, Debuggable, Maintainable. That's the plan. Thus far, that has enabled us to keep on top of any Performance and Scalability issues that have come along. With luck, things will continue to work that way!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-66824427195253895312008-02-16T03:16:00.000-08:002008-02-16T03:23:04.233-08:00Amazon goes down. Everybody flips out.Everybody in the world is talking about the <a href="http://www.techcrunch.com/2008/02/15/amazon-web-services-goes-down-takes-many-startup-sites-with-it/">Big Amazon Outage</a> yesterday. It hit us pretty hard. A few of our sites were serving broken image links for several hours yesterday, and a service we run that relies on SQS was completely dead in the water. <p/> You know what though? It's just not that big a deal. I think about how reliable my stuff was before I put it up on Amazon's machines, and really it wasn't any better. The only difference here is that I couldn't jump onto the server and do the hotfixing myself. I didn't get to spend all day writing a patch to some low-level shared thing that suddenly started misbehaving system wide. <p/> Hey, wait a minute. Scratch that. <p/> I didn't HAVE to do anything at all. It was somebody else getting that page at 3AM and scrambling to get my site back up. This is actually better from my perspective. <p/> So yeah, my sites still see the rare hour-long down window. But now it's not my problem anymore. <p/> Cool.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-45307712696473173242008-02-15T07:04:00.000-08:002008-02-15T07:20:31.353-08:00XSLT TestYou can safely ignore this post. I'm using it as a shortcut to get this page about <a href="http://www.blogabond.com/xsl/vistacular.xml">vistacular margarine</a> indexed as quickly as possible. <p/> If you're interested in what I'm up to, view source on that page. It's a test to see if it's feasible to publish content as simple XML documents that look like HTML, and do all the site navigation and chrome using client-side XSLT. <p/> At this point, I doubt it's going to work, but we'll see...Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-62740137540737363872008-02-12T06:02:00.000-08:002008-02-12T06:25:27.947-08:00S3stat in the spotlightAmazon's Jeff Barr was kind enough to do a writeup of <a href="http://www.s3stat.com/">S3stat</a> on the <a href="http://aws.typepad.com/aws/2008/02/s3-stat---usage.html">Amazon Web Services blog</a>. Thanks for that! <p/> I doubt that S3stat will ever bring in enough income to pay the rent, but it's nice to see that people are getting some use out of the thing. At the end of the day, that's sorta why we build software in the first place, right?Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-22419391835597687482008-02-06T13:32:00.000-08:002008-02-06T13:47:26.948-08:00A Naive Bayesian Spam Filter for C#Human-powered comment spam has been piling up recently at <a href="http://www.blogabond.com">Blogabond</a>, so I spent a few hours putting together a C# implementation of <a href="http://www.paulgraham.com/spam.html">Paul Graham's Naive Bayesian Spam Filter algorithm</a>. <p/> You can find a nice long-winded article along with the source code over at <a href="http://www.codeproject.com/">The Code Project</a>. Let me know if you find it useful. Here's a link: <p/> <a href="http://www.codeproject.com/KB/recipes/BayesianCS.aspx">http://www.codeproject.com/KB/recipes/BayesianCS.aspx</a> <br><br>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-87982374575392956312008-02-03T04:07:00.000-08:002008-02-03T04:42:21.882-08:00How to Watch the Superbowl over the InternetThe Superbowl may be the most important event in the American sports calendar, but most of the world just doesn't care about it. So what do you do if you're out of the country when it happens? <p/> I grew up in the Pacific Northwest, a place where it generally sucks to be most of the winter. As soon as I could do anything about it, I made a point of getting away for at least a month or so every winter. That did great things for my suntan, but I always seemed to be out of the country for the Superbowl. <p/> In most parts of the developing world, that wasn't such a big deal. In Honduras, I watched the game in a beach bar over marlin steaks and beers. In Malaysia, it was just a matter of banging on the door of the local "english pub", waking up the barman, and finding the game on TV. On the beach in Thailand, all it took was a 6am raid to kick on the generator at one of the beach bars, thus waking up the staff and asking for a large pot of coffee while I figured out how to work the TV. <p/> Europe, however, is a different matter. Try convincing the surly Basque behind the counter to keep his bar open until 2am on a Sunday, and you'll see what I mean. If you can find a hotel room with a TV, maybe you'll be in good shape, but only if they happen to have a good satellite provider that happens to carry the game. <p/> So here I am, with 11 hours to spare, furiously scouring the web, looking to find a way to stream the game to my laptop. If you're reading this article on Superbowl Sunday, chances are you're doing the same thing. Here's the story: <p/> The big players in streaming video don't seem to be much help. <a href="http://sports.yahoo.com/nflgamepass">Yahoo's NFL Game Pass</a> doesn't do postseason games. <a href="http://www.nfl.com/superbowl">The NFL</a> doesn't seem too interested in streaming their games, even after <a href="http://www.armchairgm.com/Petition_To_The_National_Football_League">a petition from football fans</a> asking for it. <a href="http://www.engadget.com/2007/08/29/nfl-and-directv-partner-on-streaming-games">DirectTV</a> will actually let you watch the Superbowl live! You just need to sign up for their $269 football season pass and then give them another $99 for their "SuperFan" program that gives you access to the Big Game. Uh... Thanks? <p/> <h2>Cricket to the rescue!</h2> What to do then? This obscure British website called <a href="http://www.livesporton.tv/drm/eventlist.asp?cat=football">Cricket on TV</a> will give you a pass to watch the Superbowl for $15. It's that easy. Just sign up at their site, give them your credit card details, and go start stocking up on beer & pretzels. Sorted. <p/> Again, for those just scanning down: <p/> <a href="http://www.livesporton.tv/drm/eventlist.asp?cat=football">This site has the Superbowl on Streaming Video for $15</a> <p/> Too bad you can't get it for free. But hey, if you're a football fan, you know that this is important. It's worth the money.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-14534734339298369672007-11-05T07:34:00.000-08:002007-12-14T02:37:15.175-08:00Roll your own Web Stats for Amazon S3<div style="border:solid 1px #cccccc;font-style:italic;padding:5px;background-color:#f0f0f0;font-size:90%;"> <b>Edit:</b> <br> <a href="http://www.s3stat.com/" title="Web Log Analysis and Statistics for Amazon S3" style="display:block;float:right;margin-left:20px;font-style:normal;text-align:center;"><img src="http://www.s3stat.com/images/logo_low_short.gif" border="0" style="border-width:0px!important" alt="Web Log Analysis and Statistics for Amazon S3"/><br>Web Stats for Amazon S3</a> This was written before we launched <a href="http://www.s3stat.com/">S3stat</a>, a service that parses your Amazon S3 server access logs and delivers usage reports back to your S3 bucket. <br><br> So if you're not interested in the technical details, and just want web stats for your S3 account, you can head over to <a href="http://www.s3stat.com/">www.S3stat.com</a> and save yourself a bunch of hassle. </div> <p/> Amazon's <a href="s3.amazonaws.com">Simple Storage Service</a> (S3) is a great content delivery network for those of us with modest needs. It's got all the buzzwords you could possibly want: geo-targeted delivery, fully redundant storage, guaranteed 99.9% uptime, and a bunch of other stuff that you could never pull off on your own. And it's dirt cheap. <p/> Of course, there's always a catch, and in S3's case you'll soon find that your $4.83 a month doesn't buy you much in the way of reports. With some digging around at Amazon's AWS site, you can find out how much you were charged last month, but that's about it. (OK, If you're persistent, you can download a CSV report full of tiny fractions of pennies that, when added together, tell you how much you were charged last month.) <p/> <h2>The Motivation</h2> I love my web statistics. I'm up and waiting at 12:07am every morning for the nightly Webalizer job to run so that I can see how many unique visitors came in to <a href="http://www.blogabond.com/">Blogabond</a> today (1227), and what they were searching for (<a href="http://www.blogabond.com/CommentView.aspx?CommentID=176">tourist trap in Beijing</a>). I've been hosting my user's photos out at S3 for a few months now, and though I've watched my bandwidth usage drop through the floor, I've also been missing my web stats fix for all those precious pageviews. Something had to be done. I started digging around through Amazon's AWS docs. <p/> It turns out that you can actually get detailed usage logs out of S3, and if you're willing to suffer through some tedium, you can even get useful reports out of them. <p/> <h2>Setting it up</h2> <!--<div style="border:1px solid #cccccc;padding:10px;margin:10px;width:40%;float:right;"><b>Edit:</b> I'm going to walk you through the process, and then I'm going to offer to do it for you. So if you don't really care how it works, and just want to see the pretty graphs, scroll down to the bottom of this article and click the link to <a href="http://www.s3stat.com/">get your stats</a> </div>-->Turning on Server Access Logging is just about the easiest thing that you can do in S3. If you've ever tried to use Amazon's APIs, you can translate that to mean that it's hard. It takes two steps, and unless you're looking at a Unix command prompt, you'll need to write some custom code to pull it off. Here's what you do: <p/> 1. Set the proper permissions for the bucket you'd like to log. You'll need to add a special Logging user to the Access Control List for the bucket, and give that user permission to upload and modify files. <p/> 2. Send the "Start Logging" command, including a little XML packet filled with settings for your bucket. <p/> The nice people at Amazon have put together a <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/LoggingHowTo.html">simple 4 page walkthrough</a> that you can follow to accomplish the above. I've run through it, and it works as advertised <p/> <h2>Parsing the logs</h2> Now we're getting to the fun part. Remember above where we noted that S3 has servers living all over the world delivering redundant copies of your content to users in different countries? Well now we get to pay the price for that. You see, Amazon sort of punted on the issue of how to put all those server logs back together into something you can use. Instead, every once in a while, each server will hand you back a little log fragment containing anywhere between 1 and 1,000,000 lines of data. Over a 24 hour period, you can expect to accumulate about 200 files, ordered roughly by date but overlapping substantially with one another. <p/> So, now in order to get a single day's logs into a usable form, we get to: <p/> 3. Download the day's logs. This is simple enough, as the S3 Rest API gives us a nice ListBucket() method that accepts a file filter. We can ask for, say all files that match the pattern "log/access_log-2007-10-25-*", and download each file individually. We'll end up with a folder containing something like this: <p/> <pre style="width:500px;overflow:auto;">10/30/2007 02:13 PM 21,380 access_log-2007-10-25-10-22-37-2C695527C7FEAEE5 10/30/2007 02:13 PM 19,653 access_log-2007-10-25-10-22-37-8FFF80109E278103 10/30/2007 02:13 PM 15,829 access_log-2007-10-25-10-23-24-D97886677E5A8670 10/30/2007 02:13 PM 185,195 access_log-2007-10-25-10-24-11-7F5172BFA139167D 10/30/2007 02:13 PM 94,795 access_log-2007-10-25-10-27-14-3EDC4E89A03E96EB 10/30/2007 02:13 PM 3,812 access_log-2007-10-25-10-32-20-DD96FC8F8B880232 10/30/2007 02:13 PM 121,863 access_log-2007-10-25-10-33-59-A44E699EE741CEF7 10/30/2007 02:13 PM 51,315 access_log-2007-10-25-10-39-52-313F98B8F52AA150 10/30/2007 02:13 PM 34,984 access_log-2007-10-25-11-18-37-DE9AB5D324881BC2 10/30/2007 02:13 PM 8,451 access_log-2007-10-25-11-22-16-BC5BCE4A49C4EC44 10/30/2007 02:13 PM 10,271 access_log-2007-10-25-11-22-54-54F77DE85AD20F84 10/30/2007 02:13 PM 14,949 access_log-2007-10-25-11-23-28-08D3DED923404EA5</pre> <p/> 4. Transform columns from S3's <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/LogFormat.html">Server Access Log Format</a> into the more useful <a href="http://httpd.apache.org/docs/1.3/mod/mod_log_config.html">Combined Logfile Format</a>. In the Unix world, we could easily pull this off with sed. In this case though, we might actually want to process each line by hand, since we still need to... <p/> 5. Concatenate and Sort records into a single file. There are lots of ways to accomplish this, and they're all a bit painful and slow. When I did this myself, I wrote a little combined transformer/sorter that spun through all the files at once and accomplished steps 4 and 5 in a single pass. Still, there's lots of room here for speed tweaking, so I'll leave this one as an exercise for the reader. <p/> 6. Feed the output from Step 5 into your favorite Web Log Analyzer. This is the big payoff, since you'll soon be looking at some tasty HTML files full of charts and graphs. I prefer the output produced by <a href="http://www.mrunix.net/webalizer/ ">The Webalizer</a>, but there are plenty of free and cheap options out there for this. <p/> <h2>Wrapping up</h2> And that's about it. Now all that's left is to tape it all together into a single script and set it to run as a nightly job. Keep in mind that S3 dates its files using Greenwich Mean Time, so, depending where you live, you might have to wait a few extra hours past midnight before you can process your logs. <p/> All together, this took me a little more than a day of effort to get a good script running. It wasn't easy, but then nothing about administering S3 ever is. <p/> <h2>Epilogue (the birth of S3<small>STAT</small>.com)</h2> I went through this pain and wrote this article about a week ago. Before posting it, it occurred to me that hardly anybody will ever actually follow the steps that I outlined above. It's just too much work, with too little payoff. <p/> What the world needs is a simple service that people can use to just automate the process. Type in your access keys and bucket name, and it will just set everything up for you. <p/> Let's see... People need this thing... I've already built it... ...umm... Hey! I've got an idea! <p/> <a href="http://www.s3stat.com/" title="Web Log Analysis and Statistics for Amazon S3" style="float:right;margin-left:20px;"><img src="http://www.s3stat.com/images/logo_low_short.gif" border="0" style="border-width:0px!important" alt="Web Log Analysis and Statistics for Amazon S3"/></a>So yeah, get yourself over to <a href="http://www.s3stat.com/">www.s3stat.com</a> and sign up for an account. It's a service that does everything I described above, and gives you pretty charts and graphs of your S3 usage without any setup hassle. At some point I'm going to start charging a buck a month to cover the bandwidth of moving all those log files around, but for now I just want to get some feedback as to how it's working. Let me know what you think!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-23665515121125549982007-10-15T10:55:00.000-07:002007-10-17T02:10:46.163-07:00How to do all that website optimizing stuff that Yahoo recommends if you're running ASP.NET and storing your content at Amazon S3<style type="text/css"> .csharpcode, .csharpcode pre { font-size: smaller; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; line-height:100%; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } </style> If you've come within 30 feet of the internet this last month, you'll have come across <a href="http://developer.yahoo.com/performance/rules.html">this list of best practices</a> at least a dozen times. Everybody seems to be writing about it and linking to it and <a href="https://addons.mozilla.org/en-US/firefox/addon/5369">building little tools that tell you you're not doing it right.</a> <p/> <a href="http://www.expatsoftware.com/articles/uploaded_images/performance_report-790251.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://www.expatsoftware.com/articles/uploaded_images/performance_report-790245.png" border="0" alt="" /></a>Most of the stuff on that list is low hanging fruit. You can spend 5 minutes in IIS, flipping compression on and telling all your /images/ directories not to expire content until we're all driving flying cars, and suddenly you'll find your site loading a lot faster. <p/> That's cool and all, but what if you also followed their advice and stuck a bunch of your static content out on Amazon S3? I guess you just fire up <a href="https://addons.mozilla.org/en-US/firefox/addon/3247">S3Fox</a> and start playing with the metadata on all those… whoa, hang on… hey, you can't change that stuff once it's written. Crap. You've gotta upload all those files again. And you can't use that cool Firefox tool to do it anymore, because it has no way to set an "Expires" header when you upload a file. Crap. Crap. Crap. <p/> Well if you're running C# and ASP.NET, you're in luck. Because I just went through that pain for <a href="http://www.twiddla.com/">a few</a> <a href="http://www.blogabond.com/">of my</a> <a href="http://www.rootdown.us/">sites</a>, and now I'm going to let you mooch off my code. <p/> <h2>First step: download the right library from Amazon</h2> In this case, you're going to need the <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=130&categoryID=47">Amazon S3 REST Library for C#</a>. No, not the SOAP library, because evidently <a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=67395">that one is crap</a>. Either drop the source straight into your project or build it elsewhere and link it in. <p/> <h2>Last step: swipe this code</h2> <a href="http://www.expatsoftware.com/freebies/S3Uploader.zip">This zip contains everything you'll need</a>. Just airlift it into your project and you'll be good to go. Now, since this is an article about programming, I'm legally obligated to provide at least one code sample for you to gloss over. So here is the meat of what we're doing: <p/> <div style="width:500px;border:solid 1px #cccccc;overflow:auto;"> <!-- code formatted by http://manoli.net/csharpformat/ --> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">void</span> PushToAmazonS3ViaREST(<span class="kwrd">string</span> bucket, <span class="kwrd">string</span> relativePath, HttpServerUtility server) { relativePath = relativePath.TrimStart(<span class="str">'/'</span>); <span class="kwrd">string</span> fullPath = _basePath + relativePath.Replace(<span class="str">@"/"</span>, <span class="str">@"\"); AWSAuthConnection s3 = new AWSAuthConnection(_publicKey, _secretKey); string sContentType = "</span>image/jpeg<span class="str">"; SortedList sList = new SortedList(); sList.Add("</span>Content-Type<span class="str">", sContentType); // Set access control list to "</span>publicly readable<span class="str">" sList.Add("</span>x-amz-acl<span class="str">", "</span><span class="kwrd">public</span>-read<span class="str">"); // Set to expire in ten years sList.Add("</span>Expires", GetHttpDateString(DateTime.Now.AddYears(10))); S3Object obj = <span class="kwrd">new</span> S3Object(FileContentsAsString(fullPath), sList); s3.PutObjectAsStream(bucket, relativePath, fullPath, obj.Metadata); } </pre> </div> <p/> There's only two lines you need to care about if you're using S3 to host web content, and they're both commented. One sets the file to be readable by the public, and the other tells it not to expire until after you've left the company. Sorted. <p/> I've included a cheesy .aspx page that you can use to push your files by hand. Hopefully you can figure out how to change which directories it's putting in the list, and how to add your own. It's actually pretty ugly code, but hey, it's just an admin tool that you'll only run a few times in your life. <p/> Be Warned though: I've stripped out the security that keeps people from the outside world (and GoogleBot) from hitting this page and bogging your server. If there's any chance that this might escape to the live site, be sure to lock it down so that you can't see it unless you're logged in as an admin! <p/> Anyway, I hope you find some use out of that code. I certainly wasn't planning to publish it, so please refrain from mentioning the 47-odd things in it that you <a href="http://www.expatsoftware.com/articles/2007/03/examplecode-productioncode.html">should never do in production</a>! <p/> Enjoy! <p/> <a href="http://www.twiddla.com/wiki/paint-chat-software.ashx">paint chat software</a>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-63929381789443408162007-09-17T03:12:00.000-07:002007-09-17T04:22:39.579-07:00How to Fail at Freelancing, in 5 Easy StepsLet's say you're a freelance web designer, and you come across a project description for, say, the redesign of a little site that lets you <a href="http://www.twiddla.com/">host web meetings</a>. This could be your ticket to fame and fortune. But how should you proceed? Well, frankly, you could have proceeded in just about any moderately professional way imaginable last week and scored that gig, but instead you did the following. All 200 of you. <p/> <div style="clear:both;"></div><div class='borderedPhoto' style='margin-left:10px;float:right;border:solid 1px #cccccc;padding:5px;font-size:90%;text-align:center;'><a href="http://www.expatsoftware.com/articles/uploaded_images/freelance_150-774296.gif"><img src="http://www.expatsoftware.com/articles/uploaded_images/freelance_150-774295.gif" border="0" alt="" style="border:1px solid #cccccc;" /></a><br>Solid Gold!!!</div>1. <b>Send out a Canned Proposal</b>. And not just any canned proposal, send a giant letter filled with the entire contents of your website, but without the proofreading. Make sure it reads like a long-form sales letter, complete with opening phrases such as "Webmaster, your search is over! We're just the candidate for you!!!", but with more exclamation points. Be sure to include links to at least 500 websites that you may have been remotely involved with. <p/> 2. <b>Send that Canned Proposal within the first 20 minutes</b>, because time is of the essence. You want to make the statement that "I Didn't Give This Any Thought At All!" And you want to make that statement fast. Good employers tend to hand out knowledge work on a first-come, first-served basis, so you want to make sure you end up on top of the stack. Extra credit for sending the same bid twice! <p/> 3. <b>Don't Read the Project Description</b>, or visit the site you're expected to be writing a proposal for. Bid on pieces that weren't up for bid. Ignore the direct questions asked of you in the project description. <p/> <div style="border:1px solid #cccccc;padding:10px;margin:10px;width:40%;float:right;"> <i><b>Honorable mention:</b><br/> To the guy in Florida who tallied up his hours, then tacked on the 5% overhead that this particular freelance site charges (expected to be borne by the freelancer, not the employer), then made a point of demanding payment up front. Good way to break the ice and build confidence.</i></div> 4. <b>Don't, under any circumstances, write any text specific to the project at hand</b>. If you somehow feel obligated to write a sentence or two to show how much thought you've put into your proposal, be sure to tack it on to the bottom. After your cheesy promo text, after that list of 50 links to your class projects, and after that special offer of a 20% discount if I ACT NOW because it's your Fall Sale! <p/> 5. <b>Quote an exact dollar figure</b>, after having completed the steps above. This is a nice final touch, as it shows that even though you didn't bother to skim through the project description before sending off your automated response, you still have a firm grasp on our needs. <p/> <h2>How to do it right:</h2> Freelancing on Guru, Elance, Rentacoder, etc. is all about first impressions. Your prospective client will no doubt be swamped with dozens if not hundreds of proposals, and you need to find a way to make yours stand out. This is surprisingly easy to do in the current climate, as even the slightest hint of professionalism will do it. Your competition is all trying to shout over the top of each other, thinking that's how you get heard. But you know what? Shouting "I'm an Idiot" at the top of your lungs may in fact get you heard, but it won't usually get you hired. <p/> So here's what you need to do if you actually want to hear back from a potential client: Write a simple, three paragraph proposal, from scratch. Spend the whole first paragraph summarizing the project and explaining why it's something you're good at. Go over your planned approach in the second paragraph, and end it with a ballpark estimate if the project description gave you enough information to do so. And finally, wrap up with a little pleasantry, and give the client a way of learning more about your operation and contacting you if they want to proceed. <p/> Sounds simple, eh? Well, I used to do a lot of freelancing, and got a lot of work with that approach. Trust me, nobody else is doing it. Behave like a professional, and you'll clean up!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-78058524210321087342007-09-07T04:10:00.000-07:002007-09-07T04:25:43.963-07:00Navigating The Minefield that is Visual Source SafeI have a new candidate for the Most Infuriating Feature Ever. It's an innocuous little part of the source control implementation for Visual Studio.NET. <p/> Let's say you're working on a new and risky set of changes to a project in Visual Studio.NET. You set off and start breaking things in existing files, safe in the knowledge that if you can't make it all work in the end, you'll be able to roll everything back in source control. Cut to half an hour later: things are hopelessly broken, and it's apparent that you're heading in the wrong direction. Best to cut your losses and start again from scratch, so you right click the solution in VS.NET and select "Undo Checkout" to roll everything back. As if to confirm, the following dialog pops up: <p/> <a href="http://www.expatsoftware.com/articles/uploaded_images/evil_dialog-796121.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://www.expatsoftware.com/articles/uploaded_images/evil_dialog-796118.gif" border="0" alt="" /></a> <p/> Note the default option. It's not really very descriptive, but what it's actually saying is <b>"Roll these changes back in a half-baked way that virtually guarantees I'll accidentally re-implement them all the next time I modify any of these files."</b> <p/> You see, what it's doing by default is leaving a copy of your broken code sitting on your local machine. Forever. Getting latest won't even overwrite it. Neither will checking the file out. So the next time you want to modify that file, it will pull up the changes you thought you had un-done and not even warn you about it. You'll make some innocuous little text modification, check in, and find that the whole application is broken. <p/> This is just one of many hazardous dialogs that developers running VSS have to tiptoe their way past every day. Dialogs with FIVE BUTTONS, only one of which does what Source Control was intended to do, and that one is hidden second from the left. It's enough to make you want to switch over to subversion. <p/> Oh, and in case you're wondering, the correct response (and the only one that anybody should ever use) to that dialog above is to tick the "Replace your local file…" radio button, check the box, and hit OK. Any other combination and you're screwed. <p> <i> ps. We're currently rebranding <a href="http://www.twiddla.com/">Twiddla</a> as a <a href="http://www.twiddla.com/wiki/design-collaboration-tool-for-distributed-teams.ashx">design collaboration tool for distributed teams</a>. If you're in the industry, we'd love to hear your feedback! </i>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-28549644123110907442007-08-23T23:05:00.000-07:002007-08-23T23:30:26.178-07:00Redundant is never Redundant enough.<div class='borderedPhoto' style='margin-right:10px;float:left;border:solid 1px #cccccc;padding:5px;font-size:90%;text-align:center;'><a href='http://flickr.com/photo_zoom.gne?id=268482207&size=m' target='preview' onclick='openPreviewWindow();'><img src='http://www.blogabond.com/UserPhotos/1/300/kitten.jpg' border=0></a><br>Common Housecat</div> <a href="http://www.blogabond.com/">Blogabond</a> went down for about 20 minutes on Friday. Our Five Nines of uptime were dashed to the ground by the uncommon treachery of the common housecat. We really need to get into a Colocation facility. <p/> It's amazing how industrious our servers are at removing themselves from the internet. We have redundant backups for everything, uninterruptible power to everything, tons of bandwidth and beefy boxes. Still, we keep getting nailed by silly things. Our RAID drives find a way to die at the precise second that we finish wiping the backup. Our old router knew to take itself offline as soon as it was sure the entire team was out of town. Everything from faulty house wiring to funky drive controllers have taken us offline at some point. <p/> But Friday took the cake. We suddenly found ourselves unable to reach the outside world. Somehow the router had gone down. But how??? It's on an Uninterruptible Power Supply! And we hadn't had a power outage in months! Ah, but on top of that UPS is a big red power button. <div class='borderedPhoto' style='margin-left:10px;float:right;border:solid 1px #cccccc;padding:5px;font-size:90%;text-align:center;'><a href='http://www.blogabond.com/Photos/PhotoView.aspx?imageID=15391' target='preview' onclick='openPreviewWindow();'><img src='http://www.blogabond.com/UserPhotos/1/300/spikedrouter.jpg' border=0></a><br><b>Cat Spikes</b> (artist's rendition)</div> And on that button sits the cat. Sure, it's not as warm as it was about 20 minutes ago, but it's still warmer than the rest of the house. <p/> Somebody needs to design a UPS that is not flat and comfortable, does not warm up nicely on a cold day, and does not have a hair-trigger OFF switch right on top of it. Either that or they need to ship it with cat spikes.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-10951915483611285942007-07-20T03:14:00.000-07:002007-07-20T03:46:42.252-07:00SprintingI didn't get anything done last week. Nothing at all. Most of my days were spent reading random stuff on the internet, making minor tweaks to <a href="http://www.blogabond.com">Blogabond</a>, and obsessing over traffic stats for <a href="http://www.twiddla.com/">Twiddla</a> (why did 5000 people suddenly show up from StumbleUpon in one day???) <p> This week, on the other hand, I've been on fire. In the last 4 days, here's what I've accomplished: <ul> <li> Built a Reddit clone from the ground up for <a href="http://www.rootdown.com/">Rootdown's</a> soon-to-be-live Clinical Pearls section. <li> Built a Google-Maps powered acupuncture chart, cut up 3000 tiles for it, incorporated effective Lat/Lon coordinates into Rootdown's database, and built a little Ajax data entry tool to drag & drop acupuncture points and meridians onto the chart. <li> Reworked the Photo uploading and Photo management pieces of Blogabond. <li> Tore out and streamlined the installation process for <a href="http://www.regressor.net">Regressor.NET</a> <li> Wrote this lame article </ul> Trust me, that's a lot of stuff. <p> I've noticed this same pattern happening over and over again. I think of it as Sprinting, and I think I'm getting better at harnessing it. There are a few factors that play into it, but I think the key is knowing that I have an entire day to Sprint on whatever it is that I want to do. Knowing Absolutely that the door to my office won't open, the phone won't ring, and no little IM popups will bother me for the Next Twelve Hours. Knowing that I'm free to get as deep into what I'm doing as I need to get whatever I'm doing Done and Done for good. Those are the days that I get the most accomplished. <p> <div style="float:right;border:solid 1px #cccccc;padding:5px;font-size:90%" ><a href='http://www.blogabond.com/Photos/PhotoView.aspx?imageID=1198'><img src='http://img.blogabond.com/UserPhotos/1/580/bulls01.jpg' width=280 border=0></a><br>Sprinting for a different reason:<br>Team Expat, Running with the Bulls in 1998</div> Another thing that seems to help, at least for me, is to have more than one ball in the air at a time. When I've only got one project, I seem more content to move slowly, check my email, read the occasional blog, and essentially stuff my productivity. But when I've got 3 things the Need to Get Done, and there just aren't enough hours in the day to do it all, I find that I work a lot faster. <p> Better still is to have something ELSE that I should really be doing. You <a href="http://www.expatsoftware.com/articles/2007/07/free-online-flash-card-software.html">should</a> <a href="http://www.expatsoftware.com/articles/2007/04/zero-to-dogfood-in-one-day.html">SEE</a> the days I spend blowing off paid work to Sprint on a side project. <p> But it more than just blowing off one project for another. The real advantage of having more than one project going at a time is that if I get blocked for any reason, I can switch over to another project and continue Sprinting at the same pace. If I'm motivated to move fast, it doesn't really matter all that much what I'm moving on, provided I'm moving. If I can ignore the little bottlenecks and keep Sprinting until the inspiration fades, I can get a lot more done overall. If I only had a single thing to work on, any minor distraction, such as missing graphics from a screen designer, could derail me and send me off to check Reddit (and thus get stuck there for six hours.) <p> I don't think that any of this is new. It's common knowledge that developers tend to work in bursts. I guess the difference for me is that I'm starting to work on ways to facilitate those bursts. To keep them going once they get started. To finally look up and find it's dark out, and I haven't eaten for 16 hours and wow, did I really get all that done in a single day??? That's where I want to be. That's Sprinting.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-59685026592985064912007-07-07T03:55:00.000-07:002007-07-07T09:49:35.975-07:00Free Online Flash Card SoftwareI've been taking Spanish lessons these last couple weeks. I'm getting to the point where I can usually communicate my thoughts, but my vocabulary is seriously lacking. No sweat, I thought, I'll just hop online and find a little Flash Card site. There's got to be half a dozen websites where you can make flash cards and test yourself with them, right? <p> Uh... Hang on. They all suck! And they're trying to sell me something. This is lame. <p> Fortunately for me, I write software for a living. Cut to six hours later, and we now have <a href="http://www.flash-card.org/">flash-card.org</a>, a site where you can actually make some flash cards and test yourself with them. It will even pay attention to your answers, and stop showing you cards that you always get right after a while. <p> <img src="http://www.flash-card.org/images/screen_01.gif" border="0" alt="Flash Card Software from www.flash-card.org" /> <p> I'm going to keep taking more classes, so I bet the site will get some more attention soon, as I become frustrated by things it can't do. And, since I can never leave things alone, it will probably get a few more useless bells and whistles tacked on. Check it out if you're a student or otherwise need to memorize stuff. Let me know what you think! <p> <a href="http://www.flash-card.org/">www.flash-card.org - Online Flash Cards</a>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-3976611365593193712007-06-03T10:56:00.000-07:002008-03-22T12:42:49.741-07:00Getting Your Priorities Straight. Scalability and Performance are the Least of your Worries.Back in my Contractor days, I would occasionally take a job bringing a bunch of C++ guys up to speed in C# and ASP.NET. Invariably, I would have to break them of old habits that they had picked up back in the days when memory and hard drive space were expensive, and applications had to run in real time. Most of these little battles were quickly won, so flat files were replaced by relational databases, bit masks gave way to association tables, and data access code was pulled out into its own layer. <p/> But one thing never went over well. <b>Performance</b>. Speed is largely irrelevant for a web application. Sure, it's important that your thing run fast, but there are a half dozen other things that are more important for a big web application. This is difficult to hear if your major skill is writing inline assembly for critical routines, but it's still the truth. Readability, Debugability, Maintainability and Development Pace are much more important than raw speed. <p/> To deal with this rift, I would ask the developers to list out the most important qualities of a piece of software, and to rank those qualities in order. I've hinted at my answer above, but I'll take a few minutes to list them out below. Everything you see in the list is important, but the things toward the top are relatively more important than the ones towards the bottom. For what it's worth, we're talking about Web Applications here, so clearly this list does not apply to Game Development or even Windows Apps. Here goes: <p/> <h3>Readability</h3> <p/> In my mind, this is the single most important quality of a piece of software. Assuming your thing is going to be around for a while, you're always going to need to return to a given piece of code from time to time and make modifications. The faster you can read and understand what's going on, the sooner you will be able to start making modifications and adding new functionality. Better still, if you can quickly figure out what the code is doing and why, you'll be less likely to break anything in the process. <p/> <h3>Debugability</h3> <p/> Your code is going to break. Often. That's how it goes, so you'd better structure things so that it's easy to step through and figure out what's going on. That means declaring variables instead of stringing together 17 object methods on a single line. That means using real IF/THEN/ELSE blocks with squiggly brackets instead of inlined immediate if's. And it means thinking twice before committing to some automagically generated database framework that sniffs out all your column names, writes its own SQL, and keeps your data in ArrayLists of ArrayLists. <p/> Keep your design simple enough that any exception will drop you into the debugger looking at a single line of code that does a single thing. Even if it turns out it's doing that single thing wrong, at least you'll be able to find and fix it. <p/> <h3>Maintainability</h3> <p/> Over time, new features are going to get added and old features are going to get dropped. Some of those new features will be stupid ones, with dorky business logic that rubs the fur the wrong way in your elegantly designed class structure. You want to be able to make those changes quickly, without breaking anything else. This means you need unit testing. You'll also want to refactor large sections of your backend to work in ways you had never anticipated, and you'll need to propagate those changes all the way out to the client code. For that, you'll need even more unit tests (and some good tools), but also you'll need an architecture that doesn't fall apart when you rip chunks out of it. <p/> <h3>Development Pace</h3> <p/> Modern applications are big and complicated. It doesn't matter how nicely written your thing is or how many simultaneous users it can support if you never manage to get it out the door. If you want to get your application shipped, you're going to need to put out a ton of code in a hurry. That means you're going to need the best tools available, and the most productive environment that you can find. <p/> <div style="border:1px solid #cccccc;padding:10px;margin:10px;width:40%;float:right;"> <i>Side Note: PHP might seem fast if you've never seen the alternatives, but let's see how many Ex-Ruby-on-Rails and Ex-ASP.NET guys you can find doing PHP development by choice.</i> </div> Keeping the above points in mind, you're going to want a development framework of some description. Here at Expat, we've rolled our own specifically to keep us fast without sacrificing Readability, Debugability, or Maintainability. I'd recommend doing the same, but there are any number of 3rd party frameworks out there that might fit the bill. Just make sure you keep those three qualities in mind when you are evaluating any new framework. <p/> <h3>Scalability</h3> <p/> At some point, your thing is going to get popular. Actually, chances are it won't, but you shouldn't architect your thing to preclude the possibility that people might start using it in the Millions. So how do you pull that off without undoing all those Important Things further up this list? Simple. Just be aware that one day you might need the ability to add more database and web servers to the mix. Add a few little abstractions such as a Database Connection Factory, and a Session wrapper that you can replace someday with something BEEFY. For now, they don't have to do anything fancier than wrapping the existing stuff in whatever framework you're using. But if you're diligent in using these wherever you would normally use the framework components, you might end up saving yourself a lot of headache down the road. <p/> For the most part though, don't worry too much about scalability. Having a million people that want to use your thing on a single day is a good thing. If you've done a little homework, you'll work things out when the time comes. <p/> <h3>Performance</h3> <p/> Computers are fast. Seriously, computers are faster than you think. If you try to imagine which piece of your application is slow, you're probably wrong. I once worked with a developer who spent the better part of 6 months hand optimizing an algorithm to do fast fuzzy string comparisons. It turned out that the server doing the text processing was only spending about 10% of its time actually processing text (even with a simplified, non-optimized algorithm), and 90% of its time battling database locks to get the results put away. He could have figured this out in one day with a profiler, and then spent a few hours tweaking database indices and optimizing queries. Instead, he spent half a year solving the wrong problem. <p/> So yeah, keep a profiler handy, and if you see something that is obviously taking a lot of extra time, go ahead and fix it. But don't spend too much time sweating performance issues. At least, wait until they present themselves as issues before you start sweating them! <p/> <h3>Life imitates Rant...</h3> <p/> As I write this, <a href="http://www.blogabond.com/">Blogabond</a> (one of my diversions from real work) is starting to show its first signs of scaling pain. Every once in a while, a misbehaved crawler will swing by and hit it 500 times in a second, causing SQL Server to time out on a specific long-running query. This is a good thing in my mind, as it gives me a chance to tackle a potential bottleneck before it starts affecting real users. <p/> Still, Blogabond has been up and running for almost two years now, and it is only now that I'm having to think about performance at all. Those other qualities though: Readability, Debugability, Maintainability, Development Pace. I'm seeing benefits from them every day.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-63647468703630087802007-05-30T04:20:00.000-07:002007-05-30T04:29:21.687-07:00How to rent an Apartment in Spain (if you're a clueless American and don't speak Spanish!)So the Expat Software offices have officially moved to Spain. It's sunny here every day. The buildings are made of stone. You can walk places. Name me one city in America where they have all that and maybe I'll move back. Oh, and you'll also need to find me a huge 3 bedroom apartment overlooking the town square of that city for less than a crappy studio would cost in the bad part of Seattle. <p> Getting this place was hard. At least, it was hard for me and my girlfriend because neither of us speaks Spanish. I mean sure, we can order beers and ask about hotel rooms and that sort of thing. But we were in no way prepared to deal with the hassle of buying real estate in a foreign land. Hopefully, if I spell out some of the things we didn't know, it might help somebody else! <p> <h2>Stupid simple things:</h2> <p> <b>Spanish people like their families</b>, so Spanish houses are HUGE. In the countryside, you'll have trouble finding anything with less than 6 bedrooms. Seriously. Renting a house is going to be hard. In cities and towns, homes are often the entire floor of a building. You can find smaller apartments, but they are still called a "Piso" (floor). So if you're looking to rent one, you're looking for a Piso en Alquilar. <p> <b>It's nearly impossible to find rental property in Spain on the Internet.</b> There are tens of thousands of websites devoted to finding holiday flats for Brits traveling to Costa Blanca, so any search for apartment rentals in Spain is futile. Here are a few sites we found locally that actually rent property to Spaniards: <p> <a href="http://www.inmof3.com/">http://www.inmof3.com/</a><br> <a href="http://www.inmobiliaria.com/">http://www.inmobiliaria.com/</a><br> <a href="http://www.enalquiler.com/">http://www.enalquiler.com/</a> <p> You can wander around your target town, looking for "en Alquilar" signs in windows and try making phone calls in a foreign tongue (hard), or you can go to the various "Immobilaria" (real estate) offices scattered around and ask them. It will still be a struggle, as nobody ever speaks English, but at least you can use hand gestures and point to things in dictionaries and so forth. <p> <b>Spanish leases are One Year Minimum</b>, so you're basically hosed if you want to find a place for 6 months. We spent an entire day walking around Pamplona trying to get around this fact, with no luck at all. If you're gonna go, go big. Nobody will rent to you for less than a year. <p> <h2>Painful details</h2> <p> <b>You'll need a Spanish bank account.</b> All the utilities and rent payments will need to be set up as direct debits from a Spanish bank. Overseas banks won't cut it. Even if you have a Barclays account at home, and there's a Barclays branch next door to the real estate agent, you're still screwed. International banking is not yet up to speed that way. You'll need to open an account locally, which is hard because… <p> <b>You'll need a Spanish address to open a bank account.</b> This seems more of a showstopper than it actually is. If you have a sympathetic real estate agent on your side, you'll hopefully be able to sit everybody down in the bank and work things out. In this case, it definitely helps to have an account with an overseas branch of the same bank. At least then it's sort of in the bank's best interest to help you out. <p> <b>You'll need permission to reside in Spain to open a bank account.</b> This one is tough for Americans, because it's hard to get a resident visa without a residence. And you need to get that visa before you leave home. We got lucky here because my girlfriend is English, and she was able to handwave around the issue with a bunch of broken Spanish about the UK technically being part of the EU and reciprocity and a bunch of other confusing stuff that exasperated the banker until he just signed the papers. I think I would have been screwed here had I been on my own. Likely I would have had to go from Bank to Bank until I found one that forgot to ask about my Resident status. <p> <b>You'll need permission to reside in Spain to stay there a whole year.</b> Uhh… Ask me about this in a couple months. The Spanish Embassy website is down right now, so I haven't quite gotten around to looking into this. Yeah… It's easier to ask forgiveness than permission, right? <p> <h2>Getting set up once you're here</h2> Assuming you're a small software development house staffed with Expat Americans, your first concern when you get here will be getting ADSL into your new apartment. For the task, this little page is Gold (use Google's language tools to translate it to English): <p> <a href="http://www.redaragon.com/informatica/adsl/">http://www.redaragon.com/informatica/adsl/</a> <p> That will give you a bunch of info you'll need to know about various DSL suppliers in Spain. If your place already has a land line, you should be able to limp through the online signup process for one of those providers. If, like me, you don't want any more hassle at this point, you can do it all in English through the phone company (though for a bit more money): <p> <a href="http://www.telefonicainenglish.com/">http://www.telefonicainenglish.com/</a> <p> You'll need a mobile phone too. That's easy though. Walk in to any phone shop on the street and try to look helpless. These people have one task in life: to supply mobile phones to those who don't yet have them. Things will work themselves out. (We're on HappyMovil, which seems to be really cheap compared to the others, with $.05 calls to the United States!) <p> There are a bunch of other things to set up too, but if you're lucky the real estate people will get them switched over for you. Here is some good info on utilities and stuff : <p> <a href="http://costablanca.angloinfo.com/countries/spain/services.asp">http://costablanca.angloinfo.com/countries/spain/services.asp</a> <p> Anyway, I can't imagine that this has made for enjoyable reading, but hopefully it will be helpful to anybody else trying to get set up in Spain. If you're planning to come out and have more questions, don't hesitate to drop me an email. It is all good here!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-7928347171343132652007-04-18T20:01:00.000-07:002007-04-18T20:10:09.070-07:00Twiddla - 1000 Signups on Day One!<a href="http://www.twiddla.com">Twiddla</a> has been getting enough attention this last week that I moved it out to its own blog. Check out this recap of <a href="http://twiddla.blogspot.com/2007/04/1000-signups-on-day-one.html">day one at Twiddla.com</a>. <p> Putting stuff up on Reddit seems to be a good plan. Twiddla got another 1000 signups this morning. Most of it was traffic flowing through that article. Damn. I wish I'd spent some time getting it ready to show off!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-34684661376900630102007-04-08T12:45:00.000-07:002007-04-11T11:35:05.305-07:00Zero to Dogfood in one dayIf you've been around software for any length of time, you've probably heard the term "Eating your own Dogfood." <a href="http://en.wikipedia.org/wiki/Eat_one's_own_dog_food">Other</a> <a href="http://www.joelonsoftware.com/articles/fog0000000012.html">people</a> have given better definitions of this than I can, but basically it means using your own application in house. <p/> So if your company is developing a little web-based word processor that it hopes will get bought out by Google, you would be well served to force your management and marketing teams to use that little word processor in lieu of Microsoft Word. The idea being that you'll quickly discover about 100 new top-priority bugs in your thing that are stopping the CEO from being able to write a simple letter to his lawyer. <p/> Now once you start thinking about your new thing in terms of Dogfood, you are immediately given a new goal for development: "We've got to get this thing to Dogfood." Meaning, our stupid new mail client has been in development for 3 years now, so why are we still using Outlook internally?!?? <p/> <h2>The Idea</h2> <a href="/images/800/jeeroday301.jpg" target="_blank"><img src="/images/300/jeeroday301.jpg" border=0 style="float:right"></a>Working with a distributed team is hard. I hate to say that, since it's sort of our thing here at <a href="http://www.expatsoftware.com/">Expat Software</a>, but it is true to an extent. We have a design team up in Portland doing mockups for the new <a href="http://www.rootdown.us/">Rootdown</a> look and feel. Down in LA, we would look at the designs that came in, mark them up and send them back to Portland, sometimes calling the designers on the phone, sometimes getting in touch via chat. It was taking forever. Just explaining the concept of "This button isn't necessary, and could you move the logo down to here" would take a couple days to get across. <p/> Over dinner one night, we were griping about this process, and somebody suggested WebEx as a solution. "Yeah, but <a href="http://reviews.cnet.com/WebEx_Meeting_Center/4852-3513_7-9755871.html">WebEx sucks</a>." "And it's expensive." "And it sucks." And yeah, all the real-time collaboration software out there really does suck. It's all got too many hoops to jump through to get up and working, and it's all too bloated with stuff you don't really need. All we want to do is draw lines on a web page. Why should that be hard? <p/> And that got us thinking. Why should it be hard? What would you need to do something like that in a Browser? Not much, really. All the technology is there. Hell, we've done most of what you'd need before. Like, back in 1998! It's got to be easy to reproduce that today. <p/> Thus, the seed was planted. <p/> <h2>The Provocation</h2> <p/> A few weeks back I wrote <a href="http://www.expatsoftware.com/articles/2007/03/examplecode-productioncode.html">an article</a> that touched on some of the effort we've put into our backend framework here at Expat. It got a lot of feedback, some of which asked how we could possibly be productive with such an expansive backend to maintain. This really took me by surprise, because our experience has shown that we're a lot faster now than we used to be before we had that infrastructure in place. In my mind, that framework is the reason that I was able to put up a site like <a href="http://www.blogabond.com/">Blogabond</a> in a few months of my free time, while it has taken <a href="http://www.techcrunch.com/2006/10/13/realtravel-trip-planner-cut-paste-share-travel-tips/">other companies</a> in the same space over a year to put up a similar site with a dozen developers and a million dollars in venture capital. <p/> So hey, if we're so fast and all that, and this little collaborative marker-upper is so easy, why can't we just build it? Like fast, even? <p/> Yeah. How about we set aside a day to do a little proof of concept and see how far we get. <p/> <h2>The Day</h2> 10am<br> <b>Technical proof of concept</b> <br/>First off, there are a few fundamental questions that need answering. What do we absolutely need? Can we layer a DIV over an IFrame? In every browser? Can we put a transparent-backround Canvas in that DIV and draw on it? Even using the IECanvas hack? Can we hook mouse events to it? Cool. We're in business. <p/> <a href="/images/800/jeeroalpha02.jpg" target="_blank"><img src="/images/300/jeeroalpha02.jpg" border=0 style="float:right"></a>12pm<br> <b>Silly Drawing App</b> <br/>Next up, we needed a quick and dirty little drawing application for marking up photos and web pages. One day we'll want to put some more effort into this piece, but for now all we needed to do was draw little scribbly lines on the canvas. <p/> 2pm<br> <b>The Proxy</b> <br/>We needed a simple proxy of some sort to show web pages on that IFrame, to avoid annoying Cross-Site-Scripting issues. It would need to mess with the HTML somehow to ensure that any clicks on those pages got redirected back to the proxy. <p/> For the time being, we just grabbed an open source ASP.NET proxy tool and plugged it in. (This got swapped out about 2 days later for a home built version that worked a lot better for what we were doing.) <p/> 3pm<br> <b>First Cut at the Backend</b> <br/> This was still a proof of concept, so we just mocked up a few basic objects and stored them in static memory on the server. Throw in a few little web services that the client can call to talk to the backend, and we're off to the races. (This piece was blown away and rebuilt the next morning to use a real data layer, but it kept us on task and out of the mire until we had the rest of the thing working.) <p/> <a href="/images/800/jeeroday13.jpg" target="_blank"><img src="/images/300/jeeroday13.jpg" border=0 style="float:right"></a>5pm<br> <b>Testing</b> <br/> First multi-user twiddle session. Basically, 3 guys in one room drawing words and pictures over Google's home page. I'm really glad we don't have screen captures of most of the things we were drawing. <p/> 6pm<br> <b>Chat</b> <br/> Somebody asked for Chat, so we threw in a little ghetto chat window. Nothing fancy, but at least you could see what people were saying (but not who was saying it!) <p/> 6:30pm<br> <b>Refactoring</b> <br/> Much polishing and refinement of the original concept. And we added a few more features like being able to choose what color you were drawing with. <p/> 7pm<br> <b>Outside users</b> <br/> At this point, things were looking basically usable, so we invited a few friends from the outside to try it out. Lots of childish graffiti was drawn, and a few more major issues were uncovered. <p/> <a href="/images/800/jeeroday14.jpg" target="_blank"><img src="/images/300/jeeroday14.jpg" border=0 style="float:right"></a>8pm<br> <b>Dogfood</b> <br/> Finally, with the last showstopper issues out of the way, it was time to get the design team in Portland on to the site. Somebody pulled up <a href="http://www.rootdown.us/">Rootdown.us</a> in the main window and we all started drawing lines on it and suggesting things to nudge around. <p/> Holy wow. We were using this thing to do real work! <p/> <h2>The Analysis</h2> So how did we pull it off? Simple. We cheated. <p/> The nice thing about Dogfood is that it doesn't have to be a finished product. It just needs to be useful for the task you're trying to accomplish. Sure, it needs to be stable enough to get stuff done, and it can't go losing critical data. But mostly, it just has to limp along well enough that you can start using it to do real work. <p/> Since we weren't trying to build the whole product all at once, we were able to cut a few corners to get that Dogfood version up as quickly as possible. You'll notice that we had to go back the next day and tape on a new back end, and that we had to throw out the crappy third party proxy we were using. Better still, in the version we used that night, you couldn't even log in or create new WhiteBoard sessions. We had a single session, and a hard-limit of 3 users. There was still loads of work to be done before we could let the general public see the thing. <p/> Another thing we had going for us was a really clear vision of what we were trying to accomplish. That vision was small enough to fit inside a single brain, and compact to the point that we could throw a single programmer at it for a day to get it implemented. You get a huge speed advantage with a team size of one. I doubt we would have finished in a day had we had three guys working on it. <p/> <h2>One Week Later</h2> <a href="/images/800/jeeroday401.jpg" target="_blank"><img src="/images/300/jeeroday401.jpg" border=0 style="float:right"></a>So here we are, a week later, with a big pile of bugs and feature requests in the hopper. All found through simply trying to use the application to get work done. We're on the thing every day reviewing designs with the guys in Portland, and every day I'll spend another couple hours tweaking the thing to be less annoying and more useful. <p/> <a href="/images/800/jeeroday501.jpg" target="_blank"><img src="/images/300/jeeroday501.jpg" border=0 style="float:left"></a>With all the positive feedback we've gotten from friends and family, we're starting to think about <a href="http://www.twiddla.com/">opening Twiddla up as a public Alpha</a>. Maybe even turning it into a real product at some point. <p/> Lucky for us, we have this little blog with its little readership of early-adopter types. I'd encourage anybody reading this to go to <a href="http://www.twiddla.com/">www.twiddla.com</a> and put our little whiteboard app through the paces. Naturally, we'll want to hear honest feedback about what you like and dislike about the thing. And hey, it's only been alive for a week now, so you're not going to hurt our feelings by telling us that it sucks. <p/> We know it sucks, and we have a good idea as to why. That's the power of eating your own dogfood. With luck, maybe you'll have ideas to make it suck less!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-57003068221810813442007-04-05T11:43:00.000-07:002007-04-05T12:09:05.319-07:00The West Coast Mobile Office<div class='borderedPhoto' ><a href='http://www.blogabond.com/Photos/PhotoView.aspx?imageID=8479' target='preview'><img src='http://www.blogabond.com/UserPhotos/1/580/westCoastMobile1.jpg' width=500 border=0></a><br></div><p style='clear:both;'/> Writing software is a lot like writing anything else. I think that's why so many computer programmers are unhappy working at companies that expect to see them typing away furiously for 8 hours a day, 40 hours a week. With any creative endeavor, inspiration tends to happen in bursts. In programming, these bursts tend to take the form of the 18 hour caffeine-fuelled marathon sessions that come to mind when you think of Internet startups. One of the (very few) things that those companies got right in the late 90s was to recognize this work pattern and find ways to accommodate it. (Unfortunately, most companies accommodated it by setting up pinball machines right in the middle of the dev space, thus wiping away any potential productivity gains in a sea of noise). <p> <div class='borderedPhoto' style='margin-right:10px;float:left;'><a href='http://www.blogabond.com/Photos/PhotoView.aspx?imageID=8476' target='preview' onclick='openPreviewWindow();'><img src='http://www.blogabond.com/UserPhotos/1/300/IMG2322.jpg' border=0></a><br></div> Anyway, back to the point at hand, the key to keeping up productivity as a developer is to find ways to foster these inspired bursts of creativity. With this in mind, we packed up the truck and left rainy, dismal Portland behind for a while. 20 hours south, we set up shop in Bishop, one of the most inspiring spots that the US has to offer. High alpine wilderness, tons of amazing rock climbing and Bouldering, pleasant secluded camping, and, amazingly, good EVDO coverage. Everything a climber/geek could want! <p style='clear:both;'/><div class='borderedPhoto' style='margin-left:10px;float:right;'><a href='http://www.blogabond.com/Photos/PhotoView.aspx?imageID=8475' target='preview' onclick='openPreviewWindow();'><img src='http://www.blogabond.com/UserPhotos/1/300/IMG2313.jpg' border=0></a><br></div>Free from the distractions of the city, we'd pull out the laptops in the morning, sipping espresso and knocking out new functionality until well after lunch. Thus creatively spent, we'd pull out the rock boots and head up the hill in search of Boulder problems on the amazing granite that Bishop is famous for. <p> What a week. What a place. we'll be back.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-80099226165316972982007-03-16T10:35:00.000-07:002007-03-16T11:24:58.843-07:00exampleCode != productionCode<style type="text/css"> .csharpcode, .csharpcode pre { font-size: smaller; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; line-height:100%; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } </style> Take a look at this little piece of code. It looks pretty innocuous, like it was taken straight from "Teach Yourself ASP.NET in 21 Days". Pull a list of Trips out of the database for a given user, and bind it to a select list. Nothing fancy. Teaches you a little bit about ADO.NET and databinding all in one place. <h3>Figure 1., Book Sample</h3> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> ExampleCode : System.Web.UI.Page { <span class="kwrd">protected</span> HtmlSelect selTripID; <span class="kwrd">private</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, System.EventArgs e) { <span class="kwrd">if</span> (!IsPostBack) { DataSet ds = <span class="kwrd">new</span> DataSet(); SqlConnection connection = <span class="kwrd">new</span> SqlConnection( <span class="str">"server=OurProductionServer;database=Payroll; UID=jimmy;PWD=j1mmy;"</span>); SqlDataAdapter adapter = <span class="kwrd">new</span> SqlDataAdapter( <span class="str">"select * from Trip where UserID="</span> + Request[<span class="str">"UserID"</span>], connection); adapter.Fill(ds); selTripID.DataSource = ds; selTripID.DataTextField = <span class="str">"TripName"</span>; selTripID.DataValueField = <span class="str">"TripID"</span>; selTripID.DataBind(); } } }</pre> Imagine my surprise, however, when I walked in to a small software shop recently and found a whole project written with code like the above. What were these guys thinking? Are they seriously relying on this fragile, unmaintainable mess in a real software product? <p> And then it dawned on me. Maybe nobody had ever told them that the little examples in the book are just that: Little Examples. <i>For teaching purposes</i>. <b><i>Never intended for use in the real world.</i></b> Come to think of it, it doesn't even tell you that in the book. It aught to be in block capitals across the cover of the book: <p> <b>WARNING: DO NOT PASTE THE SAMPLES FROM THIS BOOK DIRECTLY INTO PRODUCTION SOFTWARE!!!</b> <p> Somehow, it seems that this message never got through to a substantial portion of the software industry. Every time I see a "Senior Developer" writing ad-hoc SQL or referencing a hashtable with a string I just want to cry. <p> <p> So what do we do about it? I guess we try to get the message out. Here is some code I copied out of the <a href="http://www.blogabond.com/">Blogabond</a> source that is functionally equivalent to the above: <h3>Figure 2., Production Sample</h3> <pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> ProductionCode : System.Web.UI.Page { <span class="kwrd">protected</span> HtmlSelect selTripID; <span class="kwrd">private</span> <span class="kwrd">int</span> _userID; <span class="kwrd">private</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, System.EventArgs e) { <span class="kwrd">if</span> (!IsPostBack) { _userID = StringConvert.ToInt32( Request[User.Columns.UserID], 0); <span class="kwrd">if</span> (_userID != 0) { PopulateTripList(); } <span class="kwrd">else</span> { <span class="rem">// bail gracefully...</span> } } } <span class="kwrd">private</span> <span class="kwrd">void</span> PopulateTripList() { selTripID.DataSource = Trip.GetByUserID(_userID); selTripID.DataTextField = Trip.Columns.TripName; selTripID.DataValueField = Trip.Columns.TripID; selTripID.DataBind(); } }</pre> Short and to the point. And obviously only the tip of the iceberg. This bit of code goes deep, but we can learn a few things just by looking at it: <ol><li><b>We're using a Data Layer of some sort.</b> Somewhere in the back end lives a class that is wrapping a stored procedure for me. There's a ConnectionFactory back there someplace that knows to hand me a connection to the Production database because of a server setting. <p> The code that's handing me the DataSet I'm binding to can be reused by any page in the project, so I know that little select statement is only living in a single place. In fact, everything that touches that table is sitting in a single class back there. So if something changes in the schema I won't have to go hunting through the client code to fix it. <p> Best of all, because we've separated the database code out into its own place, we can drop all the boilerplate CRUD into <a href="http://www.codesmithtools.com/">CodeSmith</a> templates and let it auto-generate itself from the database schema. In the case of <a href="http://www.blogabond.com/">Blogabond</a>, I can flip a switch and watch as 50k lines of boilerplate C# and SQL in our backend gets blown away and recreated in about 30 seconds. And since it's also generating all the boilerplate Unit Tests for all that code, we can be sure that the datalayer and the database line up correctly. So if junior dev Jimmy comes by and unchecks a not-null constraint in Enterprise manager, we'll see the continuous build fail on an integrity check a few minutes later. <p> </li> <li><b>We're using Enums instead of inline strings</b> to reference our column names. This may not sound like a big deal, but it buys us a couple things. First, we've abstracted out the concept of the Typo. There is simply no way we can misspell "TripID", because the compiler will catch it for us. It will sit there underlined in red if we even try. We don't even have to remember what columns we have available, since Intellisense will tell us when we hit ctrl+space. <p> Second, and bigger, is that we buy the freedom to monkey with our tables and never worry that we're causing runtime errors someplace. I can rename the column "TripName" to "BlogName" if I want, re-generate the database wrappers, and watch as the project <b><i>fails to compile until I fix the references</i></b>. That is some powerful stuff. And what happens if I forget to re-generate the wrappers for that table? The continuous build will fail in about 5 minutes, since the unit tests that check to make sure the wrappers match the schema will fail. </li></ol> <h3>Where do we go from here?</h3> Copy and paste code reuse is bad. Everybody knows that. Ad-hoc SQL is bad. Everybody knows that. Inline strings are bad. Everybody knows that. <p> At least that's what I thought. But you know what? They don’t. And they should. And it's our job to tell them.Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-6273675054686980192007-03-02T19:33:00.001-08:002007-03-16T11:27:57.325-07:00New stuff at BlogabondJust pushed a few new features to <a href="http://www.blogabond.com">Blogabond</a> today. Most visible is the ability to embed your maps into external web sites, blogs, and wherever else you might want to stick a map of your travels: <p> <script src="http://www.blogabond.com/BlogMap.aspx?tripID=34&width=500&height=300"></script> <p> Groovy, eh? You can try it out on your own blog by running through the <a href="http://www.blogabond.com/TripBuilder.aspx">Trip Builder</a>, and copying out the code it gives you when you're done. Along the way you'll need to sign up for an account and name your trip, but it's still pretty quick to get a map up and running on your own site. <p> For the curious, here is the code you'd need to drop onto your page to display the map above: <p> &lt;script src="http://www.blogabond.com/BlogMap.aspx?tripID=34&width=500&height=300"&gt; <p> Enjoy!Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-35049475130336107232007-02-27T18:10:00.000-08:002007-03-16T11:29:45.765-07:00Two Weeks Vacation is only a Recommendation, not a RuleHow much vacation time did you take last year? If you're like most workers in the States, it was probably less than 3 weeks. That's all your company will give you, right? <p> Wrong. <p> 3 weeks is the amount of <span style="font-weight: bold;">PAID</span> vacation your employer will compensate you for. The actual amount you take has nothing to do with that number. In practice, the amount of vacation time you can take is directly related to your value to the company. And let me give you a little hint: <b>You are a lot more valuable to your employer than they are to you.</b> <p> I stumbled across this idea early in my career, and didn't even realize it. I was about 3 years out of school, working as an environmental engineer at a big consulting firm. It was the mid-90's, at the height of the downsizing era. Morale was low and people were leaving the company fast. <p> One day, I was looking at a little backpack I owned and it occurred to me that I could probably fit enough in that pack to live on for 3 months if I wanted to. Hmm… I hear the climbing in Southern <a href="http://www.blogabond.com/France">France</a> is pretty good. Maybe I'll look into a flight… <p> Two days later, ticket in hand, I strolled into the office of my department head. I caught the flash of exasperation on his face before he greeted me (he was fielding about one resignation a week at this point, so he probably expected the worst). "Don't worry," I said. "I'll be coming back in August." <p> That was it. No begging, pleading or anything. Just a bit of shuffling to make sure my plate was clean before heading out, and that was that. Life at the company didn't skip a beat, and 3 months later I picked up where I left off just like I would have after a week in <a href="http://www.blogabond.com/Mexico/Cancun">Cancun</a>. <p> At first, I figured that this must have been a special case. The company was in tough shape, and I was in a unique position to take advantage. Turns out though, that I kept finding myself in this position of advantage time and again over the years. So much so, that it finally dawned on me just how valuable a good employee really is to an organization. <p> Cut to 3 years later, and I'm on a small, tight programming team for a little dot-com startup. I've been there for almost a year, and it's time for a bit of R&R in Central America. 6 weeks off should just about do it. So I sit down with the boss, and start listening to the old "yeah… we're kind of in crunch mode right now… I'm not sure we can spare you for even 3 weeks, let alone Six…", so I just cut it short: <p> "Well, I'd really hoped I would be able to come back when I was done. I really like this company, and it's too bad to hear that I'll have to be leaving…" <p> And that was that. The tone of the meeting turned on a dime, and the next day I had a 4-week leave of absence approved and tacked on to my 2 week vacation request. <p> So here's the one thing you need to take away from this: <h3>You are more valuable to your employer than they are to you.</h3> It is nearly impossible to hire a good developer. Talk to anybody that's ever had to do any hiring in this industry and they'll tell you that there are simply no good candidates out there. It will take at least 6 months effort to hire a developer that can find his arse with both hands. If you are already in the door and delivering code, you can be assured that your company does not want to lose you. Sure, they'll do their best to make it sound like they don't care about you. They might even utilize the industry standard "Layoffs Are Coming!!! Panic NOW!!!" motivational techniques. But believe me, if push comes to shove, they'll find a way to keep you. <p> Tell them you're planning to take 2 months off. Don't ask. Tell them. Make it clear that you're going to go regardless of whether there's a job waiting when you get back. They'll accommodate you. Trust me. <p> A few Caveats to the above: <ul><li>You're not going to get paid for those 2 months off. You'll get the first 2 weeks or whatever paid for, but from there on out it's just a leave of absence. You'll need to save up a pile of cash ahead of time. If you've dug yourself so far into debt that you can't float along a measly 2 months without pay, I guess you're out of luck.<p></li> <li>This only works once every couple years. Don't get into the habit of storming into the boss's office every 3 months demanding another month off. You'll soon find yourself with all the free time you need.<p></li> <li>This only works if you are actually good at what you do. Take a quick self assessment first: Can you code your way out of a sack? Honestly? Cool, go for it then.<p></li> <li>This only works if you are prepared for the possibility that your employer will call your bluff. You may very well end up without a job as a result of doing this. If the prospect of having to look for work is that scary to you, then you should probably just sit tight and book that 5 night package holiday to <a href="http://www.blogabond.com/The-Bahamas">The Bahamas</a>. But then, if the idea of unemployment is really that scary, it's likely that you were fibbing a bit on that self assessment above. Jobs are plentiful for the truly skilled.</li> </ul>Jason Kesterhttp://www.blogger.com/profile/12989666544231246331noreply@blogger.comtag:blogger.com,1999:blog-38363827.post-1171585710534726632007-02-15T15:58:00.000-08:002007-03-16T11:30:51.098-07:00How Google killed SearchIt's official. It is now completely impossible to find things on the web using a search engine. Try this out. Go to Google and see if you can find a <p> <a href="http://www.google.com/search?hl=en&q=cheap+hotel+in+new+york">cheap hotel in new york</a> <p> What comes up? Any hotels? Not really. Just page after page of spammy affiliate sites that promise to find you great deals, but will really just send you off to other affiliate sites. Click along and you'll fall down this black hole of non-content and Google Ads with no hope of ever finding a real website where you can book a cheap hotel in New York. <p> I blame this phenomenon on Google's Pagerank algorithm and its reliance on link counts. The quickest way to get to the top of the rankings is to produce tons of empty pages all across the web, all linking back to your thing. So you get this huge global competition to see who can produce the most useless content and shove it out onto the web. Everybody knows it's not really content, but the game is to fool the search engines into indexing it anyway. Let this strategy play itself out for a few years and you get the Internet in its current state. 21,800,000 pages all wanting to tell me about cheap hotels in New York. Only 1 of which is Expedia.com (and it's not in the top 30.) <p> It's a lot like the state of professional boxing in the '80s. You had this kid who could fight, so you'd put him in against some guys you thought he could beat and he'd get some ranking points for himself. Then you'd find some highly ranked fighters who were on their way out and let him fight them, boosting his ranking some more. Then you'd get some other kids that weren't really all that good to start with, but you'd boost their rankings in the same way until they had enough points to put in against your guy. He'd beat them easily and get even more points for himself. <p> This would go on for a few years, with your kid steadily climbing the rankings without ever really fighting anybody good, since everybody you put him in against had had their ranking inflated by the same means. Finally, there comes the day when he's earned himself a title shot. What happens? Mike Tyson knocks him out in 18 seconds and that's the last you ever hear about him. (And Don King pockets another $20 Million.) <p> So maybe that's what Google needs, the SEO equivalent of the Tyson fight. If your site manages to weasel its way into the top 5 for a given keyword, you get some real people to put eyes on the thing and see if it can hang with the competition. That way, people like you and me would never have to sift through search engine results from www.dealz-4-hotelzz.pl just because they managed to link spam their way up the rankings. <p> <p> ps. I'm in no way guilt free in this area. Before writing this today, I spent the morning trolling around editme.com and picking up a couple high-ranking domains from them (<a href="http://travel.editme.com/">travel.editme.com</a> and <a href="http://wus.editme.com/">wus.editme.com</a>), which I am now using for shady SEO practices... <p> pps. Check out the new changes to the <a href="http://www.blogabond.com/WorldBrowser.aspx">World Browser</a> at <a href="http://www.blogabond.com/">Blogabond</a>!