Archive for the 'Programming' Category

Squash the Bug, Then Close the Window

(This message was pre-recorded.)

I usually edit two pieces of code when I’m squashing a bug. First I fix the specific bug, and then I go on a hunt for ways to prevent similar bugs in the future.



Can I make the code fail faster?

cockroach.jpg

Bugs that happen earlier in the execution path are easier to investigate.

If an invariant was destroyed, the sooner you detect it the better. It’s great if you can check for the invariant right after you modify the data. If you have complex invariants then you might consider adding a CheckInvariants() function that gets called periodically.

If the bug doesn’t throw an exception, can you test for it and throw an exception when the condition occurs? Exceptions codify error conditions. If you collect exception reports then you’ll know how popular a bug is, you can see patterns of occurrence, you’ll know for certain when it’s fixed, and so on.



Can I make the bug more apparent?

costofbugs.jpg

The worst bugs only appear if the user is running Japanese Windows and singing in the shower while holding the control key. As a programmer I don’t do that often so the bug won’t be caught until release. Bugs get exponentially more expensive the longer it takes to find them. You will fix bugs earlier if you can make them more apparent, and everybody wins.

This principle is true even at the small scale. There’s a product category just for apps that tell you when you broke the build one minute after it happened. [1] You get to fix it quickly, instead of getting the email from your annoyed coworker one hour later. There are real dollars there.



Can I make this bug easier to fix in the future?
You might be able to make the bug cheaper to fix if it reappears two months later. Add a comment block detailing how the bug happened and how you fixed it. Reference the bug’s ticket number. Modify the code to include more relevant info in the error report.

One of the things I hate about C# (and Java too?) is that you can’t get the locals of a stack frame. This feature would save us lots of time and money when deciphering error reports from the field.



Can I make the bug impossible?
Wow, wouldn’t it be great if you could do this for every bug??

We don’t use static code analysis at Xobni yet, but that’s something I’d love to change. It can catch so many simple problems. You hard coded a string instead of putting it in the internationalization string table. You write ‘if(x == null) x.Foo()’ instead of !=.


weirdo.jpg

Can I make the bug more obvious to humans?

Great software design makes bugs obvious. Is there some refactoring I can do to make the bug scream at anyone who reads or writes it?



Bonus!
I also like to comment out all exceptions before shipping a release build. That way users never see any errors! [2]



Notes

[1] This idea is called continuous builds. We recently implemented continuous builds and we all have fewer headaches.

[2] (From the joke department.)

Controlled Fires and Source Control

I deleted a big chunk of code recently. It was written months ago and just wasn’t in use, so it needed to go. There’s always an emotional attachment to code, though, so deleting it is like burning up your old love letters. You know you should probably do it, but you’re conflicted and it’s painful.

I bet the people who set off controlled forest fires have a similar feeling. They have to burn down trees and fauna that they helped create. But you’ve got to toss out the old to make room for the new.

Luckily, though, there’s source control! You can delete whatever you want and it will still be in your revision history. You’ll never go back and restore deleted code, but knowing that you could helps you do what’s necessary.

As I write this, I remember that there’s a whole namespace in XobniCommon that needs to die. I’ll take care of that tomorrow.

Why Engineers Suck at Selling

I’ve been thinking about why programmers/engineers are bad at selling things – products, ideas, themselves.

Suspension Bridge

First, engineers suck at spin. They deal in facts, not emotions. The suspension bridge is going to stay up or collapse. The software works or it doesn’t, and no amount of framing, rhetoric, or rapport will change the facts. An engineer who spins things to themselves or others would be a bad engineer; facts are king.

It gets worse. Not only do engineers focus on facts, they focus on the negative.

Programmers survive by paying attention to the ugliness in their code. If you wake me up in the middle of the night and ask what I’m dreaming about, I’ll probably tell you what the two ugliest parts of our code are, and how I’m going to fix each of them.

So when someone asks me about the code, my instinct is to describe the bugs. They’re just the first order of business! We have a natural tendency to look for and focus on the things that are not perfect.

Redemption

Redemption

Luckily entrepreneurs know that they need to be able to wear many hats. If you’re already an engineer, you just need to learn how to sell the company, what you’re doing, and the product to people when you’re hiring, raising money, or talking to customers. You need new skills to do this selling.

It’s quite possible to pull it off.

I went to a talk by Bob Metcalfe at MIT in aug-05 where he talked about selling. He recalled his personal journey of learning how to sell. Remember, Bob came into the entrepreneurship world from MIT and Xerox PARC.

Bob said he went through four stages of learning how to sell:

  1. Build a better mouse trap and the world will beat a path to your door
  2. Once he realized that doesn’t happen, he’d argue with the customer. “You really need this product.” He would win the argument, but that left the customer with a bad taste in their mouth. He told the customer they were wrong.
  3. So that didn’t work. He switched to Suffering fools gladly. Tell them what they want to hear. Over promise and under deliver.
  4. Finally, nirvana. Listen to the customers, understand their problems, and make sure you can create value for them. Under promise and over deliver.


I’d say I’m at about stage 2.5. When I’m talking to a recruit, my basic pitch is “Your life would be better if you joined us. We kick ass and you’d find much more fun/responsibility/learning here.”

I think this can improve. I’m working on it.

The Ugliest Hack I’ve Ever Pulled Off

Machine learning (6.867) was my favorite class at MIT. I just ran across the report from my final project in that class: Friendship Prediction on Facebook.

A Hack

As part of my project, I wrote a web site that allowed someone to type in their name and get back a list of people I thought they were friends with in real life but not on facebook. I put together the web site between about 10pm and 8am the day the report was due. [1]

Facebook Friendship Prediction - The Machine



The web site was the ugliest hack I’ve ever pulled off; it was in the final hour and I just needed it to work. Once someone entered their name, a task record was created in a MySQL table. I had a Java process polling the DB for new requests. Once pulled, that Java process would create 6000 feature vectors, one for each person at MIT that the query user might be friends with. Those were saved to a file. Then I needed to invoke a program called Weka to evaluate the feature vectors and output yes or no for each one. Trying to do this Shell() from Java wasn’t working, so I had the Java app write out a Windows batch file with the appropriate command. I wrote a VB app to poll for batch files, and execute them as they came up. [2]

I had another Java app poll for result files, parse them, and put them into the DB.

Each request, end to end, would take a couple minutes if there wasn’t any other load. The first java app kept about 1.8 GB of data in RAM that it needed to determine how close two people were in the friendship network.

Meanwhile, the client was being shown a page with a <META REFRESH..> so every 20 seconds it would invoke PHP to poll the MySQL DB for results.

Ah the beauty of throw away code!



Notes

[1] One of my favorite essays talks about the productive pressure of a deadline. Indeed.

[2] Here’s the main part of the VB app!

Private Sub Timer1_Timer()
File1.Refresh
For i = 0 To File1.ListCount - 1
Path = File1.Path & "\" & File1.List(i)
Open Path For Input As #1
Input #1, toexec
Close #1
Kill Path

Dim k As Integer
Math.Randomize
k = Int(Math.Rnd() * 984)
On Error Resume Next
Kill "c:\a" & k & ".bat"
On Error GoTo 0
Open "c:\a" & k & ".bat" For Output As #2
Print #2, toexec
Print #2, ""
Close #2
Shell ("c:\a" & k & ".bat")

Next
End Sub


Reinventing Code

When it comes to ideas or products, you want to cover new territory. It’s the same in the programming world. You want to build on others’ abstractions.

Sometimes, though, you just can’t help it.

We’re writing our software on the .NET platform. In .NET, all user interface elements have their own window handle in the operating system. Window handles are expensive resources. Parts of our user interface needed a lot of user interface elements, but we couldn’t afford to allocate so many window handles.

sunset.JPG

So I started writing what a critic would call a reimplementation of the System.Windows.Forms namespace [1], but using a windowless model. Whereas the .NET top level interface element is called Control, ours was called LightControl. We also had LightButton, LightPictureBox, etc.

I was only implementing about 2% of the namespace, but I was still nervous. It should set off alarms whenever you’re doing something that is both low level, and similar to something that already exists. But I just couldn’t think of any alternative.

This was a few months ago.

I was relieved yesterday when I randomly stumbled upon a blog post by Raymond Chen in which he validates my strategy. Raymond Chen is the man.

This isn’t the first time this has happened.

I wrote our own file system about eight months ago because NTFS didn’t have the right performance characteristics. We needed to store lots of small files, but traditional file systems have horrid performance in this scenario. They seek the disk like crazy! We also didn’t need directories, shortcuts, or any operations other than { create, append, read entire file, delete }. Surprisingly, a good open source implementation didn’t exist, so we bit the bullet.


The Point

First, don’t be afraid to code a variant of something that already exists. Do your homework first, but do what you’ve gotta do.

Second, if you’re making something new, don’t hide power. You might be able to save someone from having to write new code. [2]



Notes

[1] This would take a hundred developers two years to finish. Luckily we don’t need all of the functionality, but more importantly we don’t need an uncrashable API.

[2] I’m not blaming MS on this one. Although many criticize them for not providing a windowless control framework, they couldn’t have done so just by exposing an extra option. They’re not hiding power; it’s just not there.


Complaints About Visual Studio

I love Visual Studio 2005. Microsoft repeatedly hits home runs it comes to IDEs. But it isn’t perfect; it has two thorns that prick me every day.

First, Visual Studio doesn’t have multimon support. I have three monitors, and only get to write code on one of them. You can open the same solution on multiple VS instances, but that doesn’t work because editing a file in one instance will confuse the other instance.

In contrast, Eclipse really nailed multi monitor support. You can have the same project open in multiple windows, and you can instantly see any edits in all the windows.

It’s funny that this bug impacts our hardware purchase decisions. Because VS 8 lacks multimon support, we prefer one huge monitor to multiple average ones. I’m running 1600×1200 vertical now, which means I can see 80 vertical lines of code at a time. I’m looking forward to getting even more in the near future.

Second, Visual Studio doesn’t have Edit And Continue support for anonymous functions. The code below executes as you would expect.

anonymousfunctions.png

Except that I’m from Texas. We don’t say “hello” in Texas; we say “howdy!” I didn’t see my mistake until I ran the code in debug mode, so I hit Pause and change “Hello” to “Howdy.” I hit Continue, but…

anonymousfunctionsbroken.png

I think that anonymous functions should be rarely used, but this bug really hampers my willingness to use them when they would otherwise make sense.

I am proud that C# has anonymous functions, though. Many languages don’t.