Friday, December 21, 2007

c++ cheat sheet

Here’s a refresher sheet I made for C++ to remind me of a bunch of syntax details that I always seem to forget when I've switched to another programming language for too long. It's less of a complete reference and more of a "you better not hose these things during an interview". Let me know if you find it helpful or if you see any mistakes.

C++ Refresher (PDF)

(Also: what else would you add? What are the first details to erode when you haven't used a language in a while?)

Wednesday, July 11, 2007

great concurrency article

Here's a great article about concurrency by Herb Sutter:

(If you're a C++ programmer and you haven't read Herb's books, get on it! They showed me a whole higher level of thinking about C++.)

Saturday, July 7, 2007

software project wobble

Your project is spinning smoothly along like a top. It reacts to small bumps by righting itself, always moving, always keeping on course. Life is good and those options are looking pretty sweet.

Then the top starts to wobble.

How does it start? Sometimes you've run out of design - your construction has moved off your map into uncharted territory. Sometimes unchecked changes demanded by the customer push the requirements out from under your program. And always, a level of schedule stress (a release, a review, a demo) has pushed you into cranking out code faster than you really can. You've hit the wall.

The wobble is easy to recognize: you panic program. You start cutting and pasting code instead of making routines or base objects. You start putting in magic numbers instead of using constants. You start to see code like this:

char buffer[1000]; // figure out the real size


private static int xxx;

You start fixing bugs by randomly changing code to see if it helps (the poke/compile desperation strategy). You know you need to stop, because once the top starts to wobble it's doomed.

This is where I'd like to tell you about a silver bullet. But you know the only real solution is to slow down, take a deep breath and start working at a pace that lets you do good work. Easier to say than to do, so sometimes you need to just try to compartmentalize your panic programming so it's easier to fix later. And at some point you have to accept that a schedule slip is the lesser of two evils.

Friday, April 20, 2007

stagnation test

Here's a test for the coders: find some code you wrote two years ago and take a look at it.

Does it make you cringe? It's good if it does - it means you've been elevating your game. If you weren't any better then it would look just fine.

Tuesday, March 6, 2007

lock in, bad idea or ill-advised?

I've been using a free version of a password management program. This app doesn't play well with Vista so I decide to migrate all my password information to a new program.

Hmmm. It seems the free version doesn't have an export command. There is an export command in the "pro" version, which runs about $40. If I were a suspicious type I'd think they were trying to shake me down for forty bucks to avoid retyping all of my random character passwords.

No problemo, I think (really, "no problemo"). There's a free thirty day trial of the pro version so I can install it, run it once to export my passwords and uninstall.

The download trial version is fully functional. Except for the export command.

Now I don't need to be all that suspicious to think they're holding my data hostage. I send an e-mail to the support address asking how I might get my data out of their program. They reply that if I want I can send them my password file and master password and they'll send me back my data.

Um, no thanks.

Besides the fact that I don't really trust this company any more, I'm also not that keen on the keys to my entire life being sent in cleartext in an e-mail. (I know, they could have used public key encryption to send it to me, but how likely is that?)

What's the takeaway from this experience? That if you want to completely alienate your customers and make sure they never, ever recommend your product or your company, go ahead and trap them into using your product. Shake them down for whatever you can whenever you can.

Joel Spolsky wrote in his excellent book "Joel on Software" that Microsoft Excel finally got over its adoption hump when it gained the feature to not only read Lotus 123 files, but write them. Users felt safe trying out the software knowing they could get their data back into the old format.

It may seem like a good idea to lock in your customers, but when they find out the ill will you generate will make it not worth it...

Wednesday, February 28, 2007

survivor answers

[By popular request, here are the questions to the answers in this post.]

1. Why are manhole covers round?

2. There are three switches in one room and one light bulb in another. How can you tell which switch controls the bulb if you can only make one trip from the switch room to the bulb room?

3. If a plane crashes right on the border of the US and Canada, in which country would you bury the survivors?

4. You have two fuses which burn unevenly (not at a constant rate). You do know that it takes one minute for each fuse to burn completely when lit at one end. How do you measure 45 seconds?

5. You have four people (A, B, C & D) who have to cross a bridge. One or two can cross at once and they travel at the speed of the slower person. There's one flashlight which is needed to cross the bridge. A takes one minute, B takes two minutes, C takes five minutes and D takes ten minutes to cross. How do you get all of the people across in 17 minutes?

6. How far apart are the hands of a clock at 3:15?

And the ever popular:

7. Tell me one of your faults.

Tuesday, February 27, 2007

mr. biteme, of the nantucket bitemes?

I was helping my stepfather install the new version of real player (yeah, I know) because he absolutely had to play some ra files. At one point - and apparently I wasn't aware of this technical limitation in CODECs - it's critical that Real Networks have his e-mail address in order to play an audio file.

Of course, I entered It said that address was in use.

So I changed it to And that address also was in use.

Finally I added a bunch of random characters to the domain and got through. You think maybe Real Networks could figure out that people don't really want to give out their e-mail just to listen to some bird calls?

Wednesday, February 21, 2007

idiotic ui choices

Imagine if you will a website, belonging to a bank. As part of their new security policy they give you a series of questions for which you are supposed to provide the answer. One of these questions asks for a name of a particular family member.

Which I enter.

And the website tells me my answer must be 4 characters long. But the name isn't. So the right answer to the question violates the input requirements. What am I supposed to do? Make up something longer (I was thinking "biteme" might be a good choice)? Then I won't be able to remember it.

Bad user interfaces (particularly on the web) make me want to get a job as a fishing guide or something.

Friday, February 16, 2007

google v. help

[I've since found that Jeff Atwood already did a much better article on this. Go read it instead.]

When's the last time you tried to find something in an application's help system?

Being typical, I rarely seek help (or driving directions). When I do get stymied enough to venture into an application's help system, I inevitably end up more stymied, plus pissed off. It's rare that I actually find a useful answer.

Typing the application name plus my question into Google search seems to have a much better win/loss record.

Bonus question: what does this mean for help in your application? Should you skip the perfunctory lame attempt at a CHM file and just let the user Google your forum? Or should you try to come up with a help system that actually works?

mike gunderloy's "coder to developer"

This is the book you wish all the junior programmers you've ever worked with had read. Actually, a lot of senior programmers could use a good whack in the head from this book too. Mike describes many of the practices you need to implement to move past the "good coder" stage to "good developer" - things like bug tracking, source code control, automated testing, documentation, IDE extensions.

Instead of just saying "do this or suffer", the book includes specific tools, many open source or free, to implement the practices. Of course, the tools mentioned in the book are almost immediately out of date, but you should be able to find the latest best of breed tools for each category without much trouble (one place to look is Mike's blog, The Daily Grind).

If you (or your employer or your clients) comes up short on the Joel Test, this book is an excellent resource for flipping those particular bits.

Friday, February 9, 2007

bad windows explorer ui

Who thought it would be a good idea to pop up a dialog box when I drag something across a folder in Windows 2003 (note: not drop into but go over). I was trying to copy a file and had the misfortune of a target just below the "My Shared Folders". Every time I dragged (drug?) the file over "My Shared Folders" it popped up a dialog about logging on to Windows Live to...blah...blah...blah.

Of course I had to dismiss the dialog, canceling the drag operation. Then repeat three times (after all, insanity is repeating the same actions and expecting a different outcome). I finally had to sneak up on my target folder from below, dragging the file around the outside of the window and approaching from beneath.


Of course I was doing this via VPN over a mediocre connection so it was that much harder to maneuver. Nice job with the UI, guys.

Monday, February 5, 2007

guy kawasaki video

There's a good video of Guy Kawasaki on startups. His blog is interesting reading, too.

degrees of broken

I'm reading the recently released Dreaming in Code, by Scott Rosenberg. So far it's entertaining and insightful about software development. I was struck by this sentence, from chapter zero:

Their work is one percent inspiration, the rest sweat-drenched detective work; their products are never finished or perfect, just various degrees of "less broken."

Which is as true a statement about software creation as I've ever heard. Our work is never finished and never perfect, just "less broken." If you hear someone describe their program as "bug-free" you know they've still got dirt on them from the turnip truck.

I'm off to make something a little less broken today...

Monday, January 29, 2007

the accidental user

People won't use your software how you think.

Sometimes you lovingly plan, spec, prototype, usability test and construct your software to do something - something so wonderful that your users will dance ecstatically through the streets and erect statues in your honor. And sure enough some people are using your program - in ways you absolutely didn't expect.

I wrote the system configuration utility for Windows as a vendor (you can see it on an XP or 2003 machine by choosing "run" from the start menu and entering "msconfig"). It was designed to be a support tool for assisted support scenarios, when you're talking with the help desk and they direct you to run the tool to disable things and work out the problem with the system. It dealt with services, edited the boot.ini file plus a bunch of other things. It was designed to work this way by a series of program managers and usability experts.

So of course everyone just uses it to turn off their startup programs.

If we were designing a startup program, um, turner...offer, we would have done it differently. It's not a particularly elegant tool for the job. On reboot it announces itself and tries to run again, something that makes complete sense for the original scenario but a pain if you're just turning off startup items (fortunately it's easy to tell it to stop). But since it is built into the OS it's easy for users to instruct others on how to run it.

This kind of re-purposing happens all the time in pharmaceuticals: side effects discovered during clinical trials turn into the main use of the drug. It's a happy accident when users find your software's benevolent side effects but there are some steps you can take to make this more likely:


First, you can build in extensibility. This can be through something like a plug-in architecture or a scripting language (a few of the requirements for Steve Yegge's living software). Let your enthusiastic users mold your software to do new things. It's more work to build in extensibility but for significant systems it's worth it. Photoshop wouldn't be the ubiquitousness tool it is today without it.

Listen to Your Users

There are some obvious ways of doing this - running forums, e-mail links in your program to send comments, etc. Be sure you monitor those channels. You can also build some of this into your application, automatically collecting data on how it's being used. Be careful with this, though, and make sure your users know what sort of information you're collecting and what it's used for. Your users need to be able to turn this off (and you should never turn it on without asking them).

Finally, your bug reports can give you valuable information on what areas of the program are being used the most. And whenever you close a bug "by design", ask yourself why the user would have made the assumption he or she did. Should your application work how they expected?

Release Often

It doesn't go any good to listen to your users if you can't change the software. If you have a web app this is easy (just post the new code). It's harder for traditional applications but you can make it a little easier. The more thorough and automatic your tests are the better you can sleep at night during fast release cycles (you've certainly heard this before). Most modern software needs to be able to check on the net for new versions and inform the user (again, get permission from the user to make this check - it is not cool to make random net accesses your users don't expect).

Some day your software might adapt might be smart enough to see how people are using it and change the underlying architecture and code to work that way. Better than it was before. Better, stronger, faster.

But we probably ought to fix the buffer overflows first...

Wednesday, January 24, 2007

you don't bury survivors

(Overheard at a recent interview:)

So, Jeremy, tell me a little about yourself.

Because they'll roll and they can't fall down the hole. And because manholes are round.

Um, okay, how about your most recent project?

Turn on two switches, wait a while and turn one off. If the bulb is on, it's the one left on. If the bulb is off and warm, it was the one you switched off. Otherwise it's the one you didn't touch.

How big was the team you were on?

You don't bury survivors.

Uh, what was your contribution to the team?

Light both ends of fuse one and one end of fuse two. When fuse one burns out, light the other end of fuse two.

How would you deal with adding a feature to a late project?

A and B cross, A comes back, C and D cross, B comes back, A and B cross.

How would you handle a conflict between coworkers?

They're seven and a half degrees apart.

What programming languages are you most comfortable with?

Sometimes I'm too much of a perfectionist and I expect too much from my teammates.

You're hired.

Sunday, January 21, 2007

namm 2007

Most years I meet up with some friends (scattered across the country) and we head to southern California for the NAMM convention. The National Association of Music Merchants is held each year in the Anaheim convention center and brings manufacturers of musical instruments and equipment from around the world to show their newest inventions. Some of which are pretty weird.

The crowd at the show is one of the more eclectic you'll find: Chinese businessmen in suits, manufacturers in logoed polo shirts, music store owners, rock stars (current, past and wannabe) and their inappropriately dressed girlfriends. We always have fun trying to spot musicians ("Hey, there's Neal Scon from Journey. And Michael Anthony from Van Halen") and working at getting into the manufacturer's parties.

The level of talent around the show is always mind boggling and reminds me what a total hack I am. In the course of a couple of hours I can go from Doyle Dykes ripping it up in the Taylor guitar booth, to Keb Mo at a manufacturer's party. Then walk out of the party to find Johnny Hiland just smoking on a stage in the hotel lobby. Even the guys playing demos are fantastic (well, almost all of them).

This year was kind of lacking in stupid new gear. Sure, there were the usual ridiculous guitars and insanely priced acoustics with more abalone and mother of pearl than wood. But there was nothing to match the toilet seat guitar, or the backwards guitar, or the first time I saw the flavored sax reeds.

Well, there's always next year...

Wednesday, January 17, 2007

it might seem like a good idea...

To take your laptop and phone with you on vacation. But it really isn't.

Trust me on this.

Monday, January 15, 2007


Consider how an engineer designs a bridge. There's a lot of analysis and math, plus there's a big game of "what's the worst thing that could happen":

"What if there were a fire here, fueled by the natural gas line, how hot could it get? What would it melt? What if a big truck smacked into this support? (Engineers LOVE using technical terms like "smacked into" or "walloped".) How many beams could we lose here and still have the bridge stand? What would happen to the bridge in an earthquake? What if it were a deep earthquake instead of a shallow one? Where's the worst place a bomb could be planted? How fast can the wind get here, are there any harmonics we need to worry about? What about Godzilla? Can we conclusively rule out Godzilla?"

Have you ruled out Godzilla for your code?

It's about designing for the unexpected. Making code that not only works now, but keeps working when the conditions change (or at least calls definitive attention to itself). For an example, let's come up with a simple-minded method to add a string to the start of a linked list:

   1: void AddString(char * s)
2: {
3: Node * p = new Node(s);
4: p->next = this->head;
5: this->head = p;
6: }
This sample represents level 0 of robustness - what you can crank out without thinking. At first glance this might seem to be enough, especially if you're the only one calling this function. You know you'll only pass in good parameters. This breeds a false sense of security, though...someone else might eventually call this code, or you might call it nine months from now when you've forgotten all the assumptions you made.

The next level represents some basic debug-build robustness. (For those unfamiliar with the idiom, an assert is a function that fires when its expression is false, stopping the program in the debugger so the programmer can figure out what went wrong. Typically it's only checked on the slower, debug builds used for testing - not the fast release builds that are shipped to customers.)
   7: void AddString(char * s)
8: {
9: Assert(s != null && s[0] != '\0'); // don't allow null or empty strings
10: Node * p = new Node(s);
11: Assert(p != null); // the allocation might have failed
12: p->next = this->head;
13: this->head = p;
14: }
This is great for catching bugs during development but it isn't much use to the end user running your software she just downloaded. For that, you need some checks that are done for release builds:
  15: void AddString(char * s)
16: {
17: if (s == null || s[0] == '\0') // don't allow null or empty strings
18: {
19: // Error: do something.
20: }
22: Node * p = new Node(s);
24: if (p == null) // the allocation might have failed
25: {
26: // Maybe you weren’t listening: DO something.
27: }
29: p->next = this->head;
30: this->head = p;
31: }
(It isn’t easy to figure out what to do when you detect an error. It's a complicated subject that deserves an article of its own.) Sometimes you'll see this type of code with the asserts still included, just to break to the debugger if "impossible" situations are encountered.

How can you make it even more robust? You can introduce the idea of pre and post conditions for your functions. These are the contracts you're agreeing to with your function and you can include code to enforce these contracts (back to asserts to keep things short):
  32: void AddString(char * s)
33: {
34: Assert(IsValidListWithNoCycles(this->head)); // we're assuming this is true when the function starts
35: int startSize = GetListLength(this->head);
37: Node * p = new Node(s);
38: p->next = this->head;
39: this->head = p;
41: Assert(IsValidListWithNoCycles(this->head)); // this better still be true
42: Assert(GetListLength(this->head) + 1 == startSize); // and we can check that we added something
43: }
What more can be done? How about adding another thread to watchdog the data structure?
  44: void ListWatcherThreadFunction(Container * c)
45: {
46: while (1) // or check for an exit flag
47: {
48: Assert(IsValidListWithNoCycles(c->head));
49: Sleep(); // or wait or whatever
50: }
51: }
This might very well be overkill, but it might be warranted in some situations. Are there any other ideas for making this more robust?

Of course there are some drawbacks to adding this robustness. You add complexity and you add more lines of code to maintain (and debug). You might introduce performance problems, but those really should be measured and any really slow sections of code can be made "debug build only".

When you do a code review with your team (you do have code reviews, right?) what level of robustness do you expect to see? Has your team ever worked out what's appropriate for the project? Maybe you should call a truce in the vicious battles over bracket placement (let me settle the arguments for you: my way is the right way) and devote some time to debating what kind of robustness should be designed into the product.

And whatever you do, do NOT forget the hazards of Godzilla.

Saturday, January 13, 2007

welcome to code slate (or is that code's late?)

I kind of like the ambiguity in the the blog name (and domain). If you read it as "code slate", it's about writing software on a clean slate. If you read it as "code's late", well, that's also about writing software.

So here's the first post - the post which nobody will read since the blog is brand spanking sparkly new. Well, somebody might (hi Mom!). Along with the usual funny pictures and random thoughts, I'm planning on writing about how to make excellent software.

What's excellent software? Well, it's small, fast, intuitive, has an easy user interface, is robust, has beautiful code. It's trustworthy, helpful, friendly, courteous, obedient and cheerful. Yes, excellent software is like a boy scout, but generally with fewer fart jokes. I'll be writing about coding and user interface design (for which I have a lot of experience). I'll also sometimes write about marketing and the state of the software industry (for which I have, um, a lot of opinions).

A brief bit about me: I went to school at the University of Washington where I majored in computer science (back when it was still in the crappy building). Since then I've written a lot of software - I was the director of product development for a medical software company, and I've been a consultant since around 1995 (including writing msinfo and msconfig as a vendor for Microsoft).

By the way, that picture of me over there? It's the best one I could find but I seem to be wearing a tie in it. Which means either somebody got married or somebody died.