Continuous deployment sounds terrifying. It means that with each commit you make to your version control, your code is pulled down, all tests are run, and, if everything passes, that code is then pushed to production. Let me repeat: that happens with every single commit.

We can all see the risks here. HHStuffedHand-lg.jpgOne slightly screwy checkin could create a bug that's not covered by unit tests. That code then goes live to your production environment, where customers see it and get angry. They then cancel their service, your company goes out of business, and you're forced to eat nothing but Hamburger Helper for the rest of your life.

I was well aware of these risks, but when I came onboard as CTO of Famigo, I was determined to give continuous deployment a try. Why? Well, I was initially intrigued by Eric Ries' writings on the subject. The more I thought about it, the more advantages I discovered.

First, continuous deployment makes deployment a non-event. Before Famigo, I worked for a great company called Grasshopper. There, we would deploy around a dozen separate projects to nearly 50 machines every 2 weeks. Even though we deployed relatively frequently, it wasn't uncommon for our deployments to last 10 hours and cause enormous stress on the team.

There were a number of reasons why deployment was such a pain point. The structure of our environment required a lot of manual intervention for deploying. Also, we included a lot of manual testing at various points within the deployment so we could rollback quickly if we spotted an issue. The great thing about continuous deployment is that it addresses both of these problems, as you have no choice but to automate everything. If a deployment fails, it fails quickly.

Second, continuous deployment forces you to build great tests. There's simply no way around this. As developers, we all know that we should be religiously writing tests for our code, but it's incredibly easy to cheat and say, "I'll catch up on my tests later," or "This test can fail for right now." The problem is that we never, ever clean that up. With continuous deployment, you absolutely can't operate in that manner. Without repeatable and thorough testing, continuous deployment is continuous nightmare.

Will you encounter production bugs that you didn't catch with a test? Of course, you will. At that point, you write a test that covers the bug, you watch the test fail, you fix the bug, you watch the test pass, and then you commit. Like magic, the fix goes out to production and you have a little more confidence in your code.

beverly_hills_cop_ii.jpgWhat if your code currently has horrendous test coverage? How do you get around the problem? Simple: start writing tests. I spent nights and weekends writing unit and integration tests for Famigo's API before I started work officially. I fully expected that time investment to pay immediate dividends once I was ready to start pushing my work for our third party mobile developers, and it has.

Third, continuous deployment encourages good source control practices. You know what would be hilarious? Another Beverly Hills Cop movie. You know what would be even more hilarious? Someone trying to continuously deploy with 50 developers all checking into the trunk all the time.

All non-idiotic source control systems have branches; use them! If you're building something great, you're going to have to make breaking changes to your code. I'm a big fan of branching for these breaking changes/big features/huge refactors, and then merging that back into the trunk once you've stabilized the code. Not only does that keep the build happy, that keeps your teammates happy because they don't have to suffer through you sending out emails to everybody saying, "I know I broke the trunk, it'll be fixed in 2 days or I'll come to work dressed as a leprechaun." So far, this branching strategy has been crucial to scaling the deployment process to larger teams.

Another good source control practice that's enforced through continuous deployment is tagging. It's trivial to script your deployment out so that it tags each release you push to production. That is very helpful in the event you need to rollback.

Fourth, and most importantly, continuous deployment is fun. You know what I love about making software? It's when someone tells me about a major problem that I can fix simply. I am inundated with warm, fuzzy feelings when I see that simple, but important change go live just a few minutes after I commit. It makes me feel like I'm making a difference.

Not only is that sort of immediacy fun and rewarding, it actually makes you more productive. Imagine you do monthly deployments. Are you actually writing new code every day of that month? Of course not. Once you get close to the release, you do a code freeze and then you test for a while. If there's a bug with something you wrote 3 weeks ago, you have to figure it all out again and then start up the testing cycle once more.

If you're deploying continuously, you shorten that loop considerably because there's so little work in progress. You don't have to code freeze, and you don't have to test for a week to ensure the build is stable. That wasted time goes away.

How do you set up continuous deployments? It's simpler than you might think. First, download a continuous integration service; I really like Hudson, which is free and easy to administer. Once you have your continuous integration service installed, create a job inside of it that polls your source control repository every few minutes for changes. When changes are found, you want to build your code (if necessary) and run your unit tests. So far, this is straight up continuous integration.

The deployment angle comes in after the tests have been run. Here, I just wrote a simple shell script that my Hudson job calls before it completes. The script zips up the current production code and moves it to an archive directory, then it copies the files over from my continuous integration environment to our production environment. We do multiple projects in a couple of seconds this way. It took me an hour or two to figure out this shell script, so allow time for experimentation here.

Continuous deployment is an ideal solution in any environment where you must me able to iterate very quickly. At our startup, that is a must. If you give it a shot with one of your simpler projects, I think you'll soon be won over, just as I've been.

If you're going to be in Austin and want to talk lean startup or mobile development, shoot me an email (cody at cody powell dot com) or ping me on Twitter! First beer's on me.

Work Clean!

| 2 Comments | 1 TrackBack

If we as software developers want to both build great products and have fun doing so, we must be able to focus on the task at hand. Thus, our code should always compile. Our unit tests should always pass. We shouldn't have to battle a ton of misleading warnings and errors as our code is executed. In short, we must hold ourselves and our teammates to a high standard.

Why is all of that important? It's because writing software, and doing a good job of it, is hard. It's difficult enough just to implement a single new feature; it becomes a truly monumental task when, in addition to implementing the new feature, you have to figure out why the code no longer compiles, the database scripts error out, and why this one unit test, written 2 years ago, causes the build server to spit out a bunch of logs in Afrikaans and then burst into flames. Everything besides that feature is a distraction that will keep you from doing a great job on the task at hand while frustrating the lederhosen off of you.

I don't think any of that was a shocker to anyone. (If it was, you have my sympathy.) What's interesting to me is that this idea of keeping all of your working materials in line all of the time actually applies to a lot of different professions. 2008_01_bourdain.jpg Check out this great example, from a seriously delightful book:

"As a cook, your station, and its condition, its state of readiness, is an extension of your nervous system - and it is profoundly upsetting if another cook or, God forbid, a waiter disturbs your precisely and carefully laid-out system. The universe is in order when your station is set up the way you like it: you know where to find everything with your eyes closed, everything you need during the course of the shift is at the ready at arm's reach, your defenses are deployed. If you let your mise-en-place run down, get dirty and disorganized, you'll quickly find yourself spinning in place and calling for backup.

I worked with a chef who used to step behind the line to a dirty cook's station in the middle of the rush to explain why the offending cook was falling behind. He'd press his palm down on the cutting board, which was littered with peppercorns, spattered sauce, bits of parsley, bread crumbs and the usual flotsam and jetsam that accumulates quickly on a station if not constantly wiped down with a moist side towel. "You see this?" he'd inquire, raising his palm so that the cook could see the bits of dirt and scraps sticking to his chef's palm. "That's what the inside of your head looks like now. Work clean!" - Anthony Bourdain, Kitchen Confidential

The great thing here is that working cleanly is just accepted in the world of cooking. You can Google for hours and I'm confident that you'd never find a thousand post thread on the culinary equivalent of StackOverflow, asking, "Should I keep my mise-en-place clean? What if I clean it right before I need something? What if I just move to a new kitchen for each meal?" They get it, just like we need to get it. (And since I'm quoting Anthony Bourdain here, I feel like he is now obligated to come to my house and make me a grilled cheese sandwich.)

I get tempted, once a month or so, to just hack something together and check it in. I know this is happening when I say a line that's as evil as non-dairy creamer: "I don't have time to do it right!" When I do check this code in, almost inevitably, something will come up shortly thereafter. A feature, quite possibly something I didn't even touch, isn't working right. I start investigating and I see, "Oh, it's this function." I dig a little deeper, "Oh wait, it's the crappy code I did last week." I go further still, "Hang on, maybe it's not this crappy code. Or maybe it is that crappy code, and I just happened to break a whole lot of stuff without realizing it." It's a painful lesson over and over again that there's no such thing as a shortcut in the world of development.

During times like that, I wish someone would press their palm onto my spaghetti code and hold it up. Then they could say, "You see this? That's what the inside of your head looks like now!" They'd be right.

Your application is elegant and well designed.  It's covered by unit tests, the domain is effectively modeled, and your key algorithms are scalable and optimized.  
Jules Winnfield.jpg
You know the methods like Jules Winfield knows Ezekiel 25:17.  You may even be looking forward to pushing it to production, thinking, "Hey, we got it right for once!"  However, unless you have littered your beautiful codebase with thousands of hacked-up log lines for the most trivial operations, you don't stand a chance in hell of supporting this app.

What's the biggest difference between how developers and QA use a system versus how actual production users use the system?  It's simple: developer and QA know what the hell they're doing.  Production users are going to click every button at the wrong time, enter bizarre and incorrect information into forms, and fail to read any and all messaging from the system.  Not only will these barbarians be savaging your system, but there are thousands of them and they expect you to help them.

You can certainly try to support these users and fix the bugs they report without any logs.  After all, you have their data, you have your app, and you can just reproduce their errors manually.  That's nice thinking, but you're wrong.  Remember, you know how to use your system.  You're not going to load 87,000 records into your grid, or try to delete 87,000 records at once, or type an 87,000 word stream-of-consciousness diatribe about gluten-free products into a memo field.  Good luck reproducing that big ball of insanity via the user's data alone.

What are some of the benefits of excessive logging across your application?

First, you know exactly what users were doing when something blew up.  This is always much more helpful than a user-submitted bug report; the users submitting these bug reports have an imperfect knowledge of the system and they're not going to remember exactly what they were doing when catastrophe struck.  You can reproduce erroneous conditions exactly if you've been logging like a fiend, though.

Second, it's much easier to determine if a production issue is an actual bug or if it's some random hiccup in your production environment.  Databases crash, routers get rebooted, and third-party APIs go down for updates.  Maybe your production environment only experienced this hiccup for 1.5 seconds, but it could be the precise period where the CEO was hitting the Save button.  Good luck figuring that out without logs.

Third, voluminous, time-stamped logs can give you great insight into production performance.  If you write software like the rest of us, the load your system is under in the development and QA environment is nothing at all like the load it's under in production.  Once under that load, trivial things can slow down... a lot.  Think about a wooly mammoth, stuck in tar, dragging a Winnebago behind him, and know that'll be some random part of your system that you never expected.  If you collect time-stamped logs like my great aunt collects stray cats, then it's a cinch to find these culprits and then begin to tune them appropriately.  
Ziggy.jpg

I think we all agree now that logs are tremendously important. 
 If not, I encourage you to head over to check out the latest Ziggy comic and to leave the grown-up talk to the rest of us.  What exactly do we want to log then?

First, log every time your system goes out of process.  Thus, log all database, filesystem, OS, API, and web service calls.  Since you typically don't control these dependencies, you need to know exactly what you sent to them and what they sent back in order to troubleshoot any weirdness.

Second, log all user input.  It's hard to overestimate the variance you'll see when you start asking your users for information.   Don't be s
danaykroydofficial.jpg
hocked when you see that people are filling in the First Name prompt with 'hi my name is anthony and i am in the market for that crystal skull vodka that dan akroyd sells on the internet'.  Real users can submit strange, strange stuff.

Third, log the input and output for any non-trivial algorithms in your code.  Sure, you've tested this logic to Hades and back, but you'll still find some weird edge cases in production.  For example, one of my beautiful scheduling algorithms one time blew up in production because of a weirdness with Argentinian timezones.  I certainly didn't anticipate that.

Adding all of this logging into your code is certainly going to ugly it up.  It's a good kind of ugliness though, an ugliness that shows preparation for any and all crazy ass questions you'll have to field once you have real users.  And this ugliness definitely beats the alternative, which is slowly being driven insane by trying to fix bugs you can't reproduce.  Think of it as logging as self defense.
You can learn a lot about great functions by looking at horrible functions.  What's one of the antipatterns we see in horrible functions all the time?  How about this: the return type of the function is completely insane.  Yeah, I'm looking at you, Mr. Hash of Hashes!  This is a particularly huge problem when it comes to calling APIs whose code you can't actually read.

Last time, I talked about how the function name is the best spot to communicate the intent of a function.  Return type also comes in very handy there, because it's the proof that the function does what it claims to do.

Imagine you see a function called CalculateSubtotal in an API.  You think to yourself, "A-ha, this calculates a subtotal!"  And then you look a little closer at this function and you see that it's void, it doesn't actually return anything.  Wait, calculate what for the who-now?  Intent destroyed, dogs and cats are living together, and chaos reigns supreme!

Returning void from the function is usually too simple, but perhaps an even bigger problem is returning something too complex.  Imagine now that CalculateSubtotal returns an array of guids.  What in the world do those values correspond to?  They correspond to something, I realize, and perhaps I'm supposed to do something with them, but what and how?  Are these guids identifiers for something in the database?  Maybe they're lookup codes for errors in the logs?  Maybe they're just really beautiful guids that you thought I, a fellow data type enthusiast, would enjoy looking at?

What's the only way to actually see what those complex return-types from a closed API correspond to?  You have to run the code through a debugger.  When you do that, you're delivering a kick to the groin to the stated purpose of a good function: to encapsulate complexity.  Complexity is no longer encapsulated when I, the caller of the function, must first analyze your code to see what in the hell you are doing.  (I am harping on this because I am probably the world's worst offender here.)

There are many times when you will have to return a hash of hashes, or something equally complex, from your function.  What do you do then?  You should create a class.  It'll be an incredibly simple class that a monkey could write between glasses of Tang.  At the very least though, the OrderIDsToLineItemIDs class (or something along those lines) makes much more sense to the rest of Planet Earth than the monstrous, beastly hash of hash of hash of hashes you may be thinking about.

I love to listen to great developers talk about how they write software. If you like the same thing, then you should check out Coders at Work by Peter Seibel. Peter rounded up some amazing folks from the software development world to interview, like Jamie Zawinski, Guy Steele, Ken Thompson, Peter Norvig, and the ultimate shot caller himself, Donald Knuth.

I continue to find must-read passages in this book, like this selection from Peter's interview with Guy Steele. Guy Steele, of course, did hugely important work on Emacs, Scheme, Java, and Common Lisp. I love how he correlates the edge cases of fairy tales and software.

Guy Steele: And I think that the other problem is that people like to focus on the main thing they have in mind and not worry about the edge cases or the screw cases or things that are unlikely to happen. And yet it is precisely in those cases where people are most likely to disagree what the right thing to do is.

Sometimes I'll quiz a student, "What should happen in this case?" "Well, obviously it should do this." And immediately someone else will jump in and say, "No, no, it should do that." And those are exactly the things that you need to nail down in a programming specification of some process.

I think it's not an accident that we often use the imagery of magic to describe programming. We speak of computing wizards and we think of things happening by magic or automagically. And I think that's because being able to get a machine to do what you want is the closest thing we've got in technology to adolescent wish-fulfillment.

And if you look at the fairy tales, people want to be able to just think their minds what they want, waive their hands, and it happens. And of course the fairy tales are full of cautionary tales where you forgot to cover the edge case and then something bad happens.

Peter Seibel: Fantasia and the perils of recursion, of course.

GS: Fantasia and recursion, yes. Or, "I wish I was the richest man in the country" - well, that makes everybody else extremely poor and you're the same as you were before. That kind of thing happens in fairy tales because people forget that there's more than one way to do something. And if you just think about your main wish and don't think about the details, that leaves a lot not tied down.

PS: So the lesson from fairy tales is that the Gandalfs of the world got there by hard labor, learning the incantations, and there's no shortcut to that?

GS: Yeah.

I've never seen anyone make an analogy between these two bodies of work before, but we often do find ourselves creating software as if we were in the a fairy tale, paying little attention to what could go wrong. The entire book is loaded with great, insightful stuff like this. I encourage everyone to check it out.

There are a lot of ways to tell that a function is going to be less than great.  Perhaps the most obvious sign is the name of that function.  It's actually a lot like real life: if your name were Bedwetter McStupidpants, you're probably destined for a life of crime, insanity, and gum disease.

Here's an example: I spent several months working in a system where the critical function in the system was called... DoStuff2.  Unfortunately, I am being serious; it was a large, critical program for the energy industry and pretty much every use case you could ever draw up ran right through this bleak disaster of a function called DoStuff2.

We'll go through the specifics of just how horrible DoStuff2 was/is, but right now, I'm only looking at the name.  I don't even know where to start on the questions here.  What does DoStuff2 actually do?  And what is this stuff that it's doing this mysterious action to?  And, for the love of God, what happened to DoStuff1?

This is completely obvious, but a function name is your first and best chance to communicate the intent of your function.  If it's not clear from the name what your function does, no one will use it, the function rots, and it's quickly headed down the road of Bedwetter McStupidpants.

The whole idea of a function is to encapsulate complexity, right?  Start with that in your function name.  I don't care if, in the act of performing this function, it uses a worker thread or calls a web service or launches a nuclear strike against the people of the Arctic.  In the function name, I only want to know what it will do for me.

Let's say your function calculates a subtotal.  What should we name that?  Gee, I don't know, perhaps CalculateSubtotal?

Look at the naming convention there: it's verb then noun, and both words are as specific as possible.  It's like a command your dog would understand, if it had a slightly better grasp on vocabulary.  "Rover, eat food!  Rover, go potty!  Rover, calculate subtotal!" If you ever shouted, "Rover, do stuff!" he'd probably pee on your shoes out of spite.

gorillasuit.jpg
The nice thing about a specific verb-noun naming convention for your functions is that the naming never gets out of control.  You never get monstrosities like PerformCalculation (every calculation in the universe?), SubtotalGenerationInit (just init?  does it ever finish?), PleaseGiveMeAubtotalOrIWillHuntYouDown-AndMakeYouWearAGorillaSuitToWork (definite style points for that one, but slightly lengthy).

Let's conclude.  Your function name should be short, meaningful, and specific; if it's not that, come up with a better name or learn to live with a horrible function.
I used to go through the same experience once a week.  I'd open up some code that I wrote a couple of months ago, I'd read a bit of it to understand what I was trying to do, and then I'd conclude that I'm a complete moron.  
billydeesign.jpg
Based upon that crazy, kludgey mess I wrote just a few weeks back, I'd realize that, not only should I be barred from using a compiler from the rest of my life, but that I probably can't be trusted around shoelaces and sharp edges either.  Code like that is why they sell malt liquor.

Okay, most of my code wasn't that bad.  A great deal of it was fine, acceptable code.  However, when I looked back on existing code, I'd always find this one little corner of disturbing weirdness that just shouldn't be allowed to live.  At the time, I'm sure it made perfect sense, but looking later, I could only suspect that severe head trauma was involved.

Wouldn't it be great if we could catch ourselves each time we took a leap into Bizarro Code Land?  Wouldn't we save ourselves a great deal of frustration if these code abominations never made it into the codebase to begin with?  Wouldn't it be cool to look at old code and not have to stifle a sob?

The good news is that it's actually easy to spot these mistakes when you write them.  The bad news is that you're not going to be able to spot them yourself.  This, my friend, is why we all need code reviews.

Don't Be Afraid
Just the term "code review" gives some people the shakes.  
Pointy-Hair.jpg
It sounds like you have to present a detailed report (with footnotes! and a bibliography!) on every line in your application to a committee of pointy-haired bosses who are about to start flinging rotten fruit at you.  That's not it at all, though.

We're all into people over process, right?  A code review can be as simple as having someone watch over your shoulder for 45 minutes as you walk them through your work for the week.  No committees!  No lengthy reports!  No rotten fruit!  It's just you and someone else having a conversation about your code.

You may want something a little more formal if you're writing the firmware for the Space Shuttle, but simple and informal code reviews do wonders for the rest of us mortals. 

Good Code Reviews
What's the difference between a good code review and a bad code review?  In a bad code review, you leave feeling terrible about yourself.  In a good code review, you leave feeling terrble about yourself, but you also have a list of things to refactor.  Just kidding.

So what actually is a good code review?  For me, it all comes down to  a few practices that are easy and effective.

A good code review focuses on the code.  Some people seem to think you need to bring in all manner of class and sequence diagrams for a code review.  You don't, unless insanity by UML is your idea of a good time.  Just fire up the editor and start looking at code.

A good code review results in agreement.  There has to be give-and-take in a good review.  If you're reviewing my code, you can't just declare, "This sucks, rewrite the whole thing!"  Likewise, I can't just declare, "I hate you, you insufferable ass!  This code is perfect!"  A good review should produce a list of reasonable refactorings to make, and this should be a list that both the reviewer and the reviewee agree on.

A good code review is an intimate affair.  barry-white-1.jpgThat's not to say you should be doing code reviews in your underwear while listening to Barry White.  By intimate, I simply mean it should be you and one or two reviewers.  With a small group, you can go through the code quickly and easily, and the conversation doesn't spin out of control.  Otherwise, it's Review by Committee, and the Committee might quickly go from, "Hmm, this is interesting," to "Why doesn't our framework do this," to "Let's rewrite everything in Erlang!"

A good code review is limited in scope.  You've had too much Nyquil if you think you can cover an entire system in a 45 minute review.  Instead, focus on something that a person can reasonably understand in that time period, like one particular feature or a specific business process.  It's better to go deep than shallow.

A good code review isn't a one off event.  We want to do outstanding work and produce things that are so awesome that shiny medals and honorary keys to the city are in order, right?  You can't do that consistently if your code is reviewed once every 6 months.  Once you see how easy and interesting these simple code reviews are, weekly reviews with a teammate make perfect sense.

porky.jpg
A good code review has a good reviewer.  There's no point at all in doing a review if the reviewer doesn't know a string from Porky Pig's bowtie.  Pick someone you respect; it should be someone who's qualified to suggest changes in naming, variable scope, object oriented design, database schema, etc.  It should be someone who'll feel comfortable telling you, "What is this load of digital feces?"  Don't pick the intern.

The Final Practice
A good code review occurs.  If you aren't actively reviewing code, then stop reading this right now.  Walk over to the person next to you.  Ask them when they have an hour to look at some code.  If they are in the bathroom, sit there until they come back.  If they don't come back, knock on the bathroom door and ask if they need some Pepto Bismol.  Then ask if they have an hour to look at some code.

If you're scared by code reviews, it's only because you're not doing them.  Start today and help yourself build something great.

The idea of having fun and building something meaningful through software is much, much older than this little blog. Check out this quote from the dedication of Abelson and Sussman's absolute classic, Structure and Interpretation of Computer Programs:

I think that it's extraordinarily important that we in computer science keep fun in computing. When it started out, it was an awful lot of fun. Of course, the paying customers got shafted every now and then, and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don't think we are. I think we're responsible for stretching them, setting them off in new directions, and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all, I hope we don't become missionaries. Don't feel as if you're Bible salesmen. The world has too many of those already. What you know about computing other people will learn. Don't feel as if the key to successful computing is only in your hands. What's in your hands, I think and hope, is intelligence: the ability to see the machine as more than when you were first led up to it, that you can make it more. - Alan J. Perlis

Amen.

We all know and love the Joel Test, Joel Spolsky's quick quiz to determine the quality of a software team.  If you're searching for a job, it's a great idea to run potential employers through the Joel Test.

There's a problem with it, though.  Well, there are multiple problems.  First, who the hell cares about hallway usability testing?  Second, you're only checking for the good qualities of a team.  What about the horrendously bad qualities that will eventually drive you towards both insanity and a crippling dependency on cough syrup?  
10106989_0579f7be13.jpg
We need something like the Joel Test to measure the potential crappiness of a job, or else each of us might stumble into becoming Milton Waddams.

Ladies and gentlemen, I present to you the Codypo Test, aka 8 Questions To Identify A Lame Programming Job.  If you are in an interview, you give the company the Codypo test, and the job scores more than a 1 or 2, you need to pull the fire alarm and get the hell out of there.


1.  Would I be paid below market rates?

If they're looking for 10 years of hardcore, multithreaded C++ experience and they're offering 48k, these people have lost their minds.  Expect this sort of delusional thinking to appear in everything they do.

2.  Would I always be on call?

No one likes being on call, because as soon as you're on call, someone is going to page you at 3 AM on a Sunday because the Reset button on the support portal is a different shade of blue than they're expecting.  Occasional on call stints are both understandable and tolerable, but 24/7 is for doctors and exorcists.

3.  Am I the IT staff?

You are a programmer.  You make software.  You are happy to support your software.  
garfield_1.gif
This does not, however, mean you are a computational master of the universe, and just the guy to ask why the receptionist's laptop got all weird after she installed that Garfield screensaver.

4.  Would I work with a single monitor?

It's no longer 1998.  We don't have to stare at a single 17" boat anchor all day while rocking out to Smashmouth. You can buy huge, thin LCDs for $100 each.  If doubling your productivity isn't worth $200 to this company, then this company may just be a really elaborate practical joke played by an eccentric billionaire.

5.  Will I be maintaining any ancient system, and what's it written in?

If you dig deep, you may hear, "Yeah, we're going to get into Ruby on Rails, but first, we'll need you to bust out some VB 4."  It is never, ever that easy.  
rasputin.a.gif
That VB 4 system will refuse to die, just like Rasputin.

6.  Would my internet usage filtered or monitored?

Programmers solve problems, and to solve problems effectively, you need resources.  The internet is the single greatest usage available.  Any company that refuses to accept that and blocks you from Usenet/ Google/Stack Overflow/whatever is treating like you a child/deranged porn fiend.

7.  Would I be the only programmer?

More than anything else, I have grown as a programmer thanks to my peers.  We answer each others' questions, we review each others' code, we whiteboard together, and we come up with creative insults when somebody breaks the build.  If it's just you, you're not going to get any technical feedback and you're not going to get any better.  Also, you'll only be able to insult yourself when you break the build, which might get you reported to HR.

8.  Am I expected to travel every week?

A bit of travel is necessary from time to time, particularly for face to face meetings with customers or offsite colleagues.  However, expecting you to leave your home every farging week is absurd.  We have the internet now; it allows us to communicate virtually.  Let's use that instead of me becoming BFF with the night receptionist at the Best Western.


I think those 8 questions constitute a good sanity test for a potential job.  Sure, there are valid reasons for a job to score a 1 (eg, you might be the IT Staff or on call all the time at a startup).  However, once you get past one Yes to these questions, it's time to leave the interview through any means necessary, including faking a heart attack.

No matter how great the potential projects and teammates might be, I don't think you can do truly meaningful work in an environment where you, the developer, aren't empowered to succeed.  If a company doesn't get that, then they don't get software.
What in the heck is delightful software?  If you'd asked me a week ago, I would've said it's either the code used by Santa's elves to produce candy canes or the OS on Spongebob Squarepants' cell phone.  At first glance, the term is slightly ridiculous.
delightedspongebob.jpg

Think about this, though: software can be fun to make and use.  The code can be well-designed, covered thoroughly by unit tests, and utterly devoid of broken windows; the codebase can actually be a treat to contribute to.  The team working on the code can be upbeat and helpful.  When the users spend time with the product, they might feel just a little bit of life's stress melt away, knowing that this product will do something useful for the user without making the user think.  The software, in short, is a delight.

The delight doesn't come from the project itself.  After all, who giggles with glee when they're thinking about a billing system?  No, I think the pleasure here comes from attitudes and practices that we and our teams can adopt towards our craft.  Once adopted, the mere act of creating and using software becomes both more fun and more meaningful.

That's what we're going to talk about here.  We're going to talk about a scalable, fruitful, and rewarding way to build both software and a life in the software industry.  Once we cover that, we will then and only then investigate who wrote the OS on Spongebob Squarepants' cell phone.  (Preliminary guess: Nokia?)

About the Author

The Art of Delightful Software is written by Cody Powell. I'm just a guy in Austin who likes code, people, music, and wine.

Twitter: @codypo
LinkedIn: codypo's profile
Personal blog: Goulash
irc.freenode.net: codypo
Email: firstname + firstname lastname dot com

Recent Comments

  • Sadee: Hi. I treasured to drop you a quick note to read more
  • divide by 0: sounds good but how do you convince your boss to read more
  • Cody: Nope, not automating the act of rolling back just yet read more
  • Wllballs: What about rollbacks? Do you automate those to? read more
  • leduc.mike: Don't let Bourdain fool you I've worked in enough kitchens read more
  • Cody: Here's another great take on the same issue, from the read more
  • Caleb: Remember that logging can also adversely affect performance. I generally read more
  • Peter Schoenster: Bravo. It's our world. We do not need to suffer read more
  • Anonymous: Caveat: I did that once in a system and didn't read more
  • spizen: If you work in a corporate environment, one thing to read more

Categories

OpenID accepted here Learn more about OpenID