As someone who spends 40-60 hours a week developing, I like to rip the vlog from real life. You can always tell when I'm not being productive at work, because then all of the entries here are about how much I hated Delta Burke on Designing Women. This week at work, we're gearing up to do some interviews for an opening on our team. The way we do it at work, the higher-ups ask the important, character-related questions ('Where do you see yourself in 5 years?'), while we technies get a chance to dig into the nitty gritty with the candidate ('If you had to marry one video game character, which one would it be?'). My own answer would be King Hippo from Mike Tyson's Punch Out.
Anyway, thinking about the whole interview process has got me to thinking about the ideal way to interview a developer. I've read lots of sample questions on the web, and I can group most of them into two groups: the trivial and the absurd.
Here's an example of the trivial (in C#): What's the difference between System.Array.CopyTo() and System.Array.Clone()? I don't understand what this question is supposed to tell you about the candidate. If she were sitting at a computer, she could probably figure that out in 60 seconds; it'd actually be a good question if you allowed the individual to figure it out that way. Without that, it's just a trivia question. It doesn't tell you anything about the person's skills as a developer, just about that person's ability to memorize footnotes.
Now an example of the absurd: if you had an infinite supply of water and a 5 quart and 3 quart pail, how would you measure out exactly 4 quarts? Unless the person is applying for chief water measurement officer, I don't see the relevance here. It's a riddle, some would contend, and it reveals a lot about a person's problem-solving skills. To me, it seems kinda masturbatory. Questions like these serve to inform the candidate of just how clever the interviewer is, not the other way around. That's not the point of an interview.
If you really want some insight into a person's problem-solving skills, as well as her knowledge in a particular technology, I can think of a better way to do it. How about a relevant, open-ended question? Maybe something like the following:
What's one project you've never gotten around to working on? Let's say you decide to start work on it one weekend. You can choose whatever technology you want to complete it. Walk me through your creation process.
I have very little experience as an interviewer, but quite a bit as the person being interviewed. When I was looking for a job, I know I would've really responded to a question like that, just because it's fun to think about. For me, that's not exactly the case when thinking about measuring water, given limited equipment. Any interview is bound to be imperfect, but you can at least attempt to learn something relevant about the person. Unless, of course, they answer the question correctly about marrying a video game character. If you hear someone else say King Hippo, that's a one way ticket to a corner office.
I'm not quite ready to continue working on error-handling; I trust all of you will have the courage to go on living until I can proceed with my work there. Instead, here's an interesting note I found about recursion in Code Complete:
"One problem with computer-science textbooks is that they present silly examples of recursion. The typical examples are computing a factorial or computing a Fibonacci sequence. Recusion is a powerful tool, and it's really dumb to use it in either of those cases. If a programmer who worked for me used recursion to compute a factorial, I'd hire someone else." - Steve McConnell, Code Complete, p. 397.
Someone's got a bee in his bonnet when it comes to recursion! And I wonder, if you had a bee in your bonnet when it comes to recursion and you take that bonnet off, do you find another bonnet containing another bee? Just food for thought.
Anyway, I do remember the first example of recursion I saw in college, and it was for computing Fibonacci numbers. The only examples I actually remember now are the really simple ones that McConnell mentions. The entire class had a hard time understanding exactly why we needed recursion in those situations, when we already knew about loops. That's one of the points that McConnell makes, that those simple recursive methods are harder to understand than the iterative version of those methods. He also says they're slow and they make the use of run-time memory unpredictable.
After I read that, I began to wonder just what recursion was good for. I know it's good for binary trees and whatnot, but it seems like there are almost always other, simpler approaches we can use. Then, today at work, I got in a tricky spot where I was trying to write some code that dealt with MIME attachments. I tried all kinds of loops and loops within loops and super mutant loops, and I just could not make it work. I was this close to turning my King Nerd crown and sulking home.
But then, on a lark, I tried to write the function recursively and it simplified the matter immediately. Suddenly, 150 lines of code went down to 15 lines. I could once again wear my crown with pride.
My point? I don't have one, except that I found it ironic that recursion came in handy just as I began doubting its validity entirely. It's like the developer gods were trying to teach me a lesson: just because you only know a few dumb applications of an idea doesn't mean the idea is completely worthless. Fine with me, unless that idea is flossing regularly or exercise; to me, those will always remain foreign concepts.
Last week, I said that error handling interested me, and that I'd probably delve into it some more here in this space. Well, let the record show that when I issue vague declarations from an unpopular website, I stand by them. Today, I'd like to discuss a specific error-handling technique of mine and why it's probably terrible.
My thesis with all of the error handling business is that most of us don't really know what we're doing. When we do design and code, we focus on the sexy stuff, like the cyborg interface to our missle defense APIs, not boring crap like error handling. That's maintenance, not development. Let the users find the errors, and then we can fix them while shaking our fists and yelling, "Learn to type, idiots!"
Since we don't pay attention to error handling, we get into bad habits; case in point, yours truly. I don't consider myself to be a complete idiot when it comes to programming; I can, after all, manipulate the LOGO turtle with the best of them. Nevertheless, I recently realized that one of my main error-handling techniques is completely idiotic. The only reason it works is because the code surrounding has been sufficiently idiot-proofed. That's probably not the right way to do that.
Most of the code I write accesses a database. Since those databases are pretty normalized, I write a lot of methods where I need to look up an identifier for some piece of data. One example: we take a status description ("Active"), and we need to return the status id for that description. Not only is it not brain science, but it wouldn't even qualify as pinkie toe science.
It is simple, but there's an issue here: what are we supposed to return if we don't find a record for that status description? Assuming we're returning an integer, I always returned -1 for that situation. The methods that call that status lookup process are aware of what -1 means, and so they act accordingly if they receive that as a return value.
At first glance, that's not too bad. It's not too good, but I'm not sawing the legs off of kitties or anything like that. But then, when I started thinking about it, I began to realize it was all wrong.
First, I'm using the same variable to return a value AND communicate an error code. If you were just picking up the code, how would know whether that value is an error or a valid return value? Basically, you'd have to come to my house and ask me, which would probably be an inconvenience to you. There's no instrinsic mechanism to inform the user that -1 is an error.
Second, this shows some bad design on my part. If I were to change the error code to be -5, I'd likewise have to change all of the methods looking for -1. It's not a very good example of information hiding, one of the key points behind object-oriented design. The idea behind information hiding is that the interface to a class should reveal as little about its inner-workings as possible; that maxim flops entirely here.
Okay, I think I've effectively demonstrated that the work I did was crappy. Crappy yes, but I recognize it's crappy and that's the first step towards recovery. How do we fix it? How do we cleanse the code of my good intentioned, but ultimately yucky error handling implementation? I have a few ideas. But to see these ideas, you will have to wait until next time. (In advertising terms, I am dangling the carrot there. Visit obsessively, or suffer sleepless nights for the rest of your life! Mwa ha ha ha!)
As I mentioned last week, I'm reading Code Complete right now, one of the great texts on software construction. In it, there's a lengthy chapter on error-handling, exceptions, and defensive programming (Ch. 8). Being the master of causing errors, it only makes sense that I also become the master of handling these errors. I found that section particularly interesting, largely because there's so much to it. Think for a moment about how much code you've written to handle errors. I write stuff like that almost every day, but I can't think of any shining (or even good) examples from all of that code; I'd wager my Yoda doll that there are others who operate similarly. Why is this? If we're writing so much error-handling code, why aren't we better at it?
Part of the issue is that error handling is never addressed as a real problem. I've taken plenty of computer science classes in my day, and while I've learned plenty about merge sorts and how to represent numbers in IEEE floating point format, I don't remember ever covering the right way to handle errors. Meanwhile, how many times have I had to implement a merge sort? I tried to do it for fun to sort the size of my socks, and when I woke up 8 hours later, I was in the neighbor's lawn. This subject deserves some class time (not my neighbor's lawn, but error handling).
The other part of the issue is the scope of the problem: it's humongous. Errors can occur in any part of a package, and all of these errors have to be handled in a logical, expected manner. Developers have to be both thorough and consistent across a gigantic chunk of code; that's not easy. And you can't just pick one or the other, you have to shoot for both. If you only opt for thorough, then you'll be rereading a lot of code to see how the developer handled the error in that specific instance. If you only opt for consistent, then some errors will make their way to the user. It's like a peanut butter and banana sandwich; if you don't have both ingredients, you're simply fooling yourself.
There are a lot of tools at our disposal here (exceptions, assertions, etc.), but we need some sort of framework for utilizing them. I think Code Complete provides a good start down that path, but I want to think about it myself and come to a few conclusions. Over the coming days, my plan is to write and dissect a couple of examples here, with the aim of educating myself and confusing/annoying the good people of the internet. It's a tall order, but if anyone were ever capable of edufusoying people, it's me. (And, of course, the merge sort.)
Okay, I'm having a hard time today. I am compelled to put something up here, a little dusting of that Cody Powell pixie dust, but I can't think up anything good. Looking at the archives, you can see that rarely stops me. Today, in lieu of an earth-shaker, how about a cool tip for Visual Studio .NET? And if that's not enough, then how about an ice cream sandwich?
Allow me to be honest here: sometimes I get in a hurry. I think that, along with the love of fried cheese, is only human. Occasionally when I'm work, someone will come to me and say they need some code RIGHT FRICKIN' NOW. Genius usually fails me in those moments, so I give them something that works. It works and it's serviceable, but no one is going to propose to it because of its beauty (I should note this happens rarely in software development anyway). Whenever I do one of those rush jobs, I like to make note of it in the code so I can go back and fix it later. Whether I go back and fix it later is another matter entirely, but that's what I like to do.
My problem was that I had a hard time finding those less-than-great chunks of code when I went back later. Unless I stuck to some standard comment format for my hacks, it could take me quite a while to locate them. Sure, I could think of a few choice phrases with which to mark them, but I began to worry what our clients would say if, every thousand lines of code, there was a comment that read "Developer's Note: what follows is a flaming pile of poop."
And then today, when messing around in Visual Studio .NET, it hit me. Not the IDE, but the way to comment my hacks. In Visual Studio, there's a task list into which you can add tasks you need to tackle. If you have that Task List open, you can right-click on it and go Show Tasks->Comment. Don't worry, we're not to the cool part yet.
Once you're showing your Comment tasks, go into your code, find one of your cruddy sections, and type "///HACK " and then a brief description of the yuckiness. Your HACK comment then appears in the Task List, as if ordained by some super powerful wizard! Too cool. Two other built-in keywords are TODO and UNDONE. I've been using those terms in my code for the past couple of months, and it really, really helps me in determining what work is left if I haven't looked at the code for a few weeks.
It's completely possible that this feature has been around a while now, and lots of people are already using it. It's my site though, so the posts can be as obvious as I want! And if I want to lie about giving you an ice cream sandwich, well, I can do that too. Here at codypowell.com, we play by prison rules.
Good afternoon, gentlemen and gentleladies. Just recently, I started reading Steve McConnell's development classic, Code Complete. As I get farther and farther into it, I may start sharing a few of the tips enclosed in said development classic, but not today. Today, however, we have smaller fish to fry. Specifically, I'd like to share one method in C# and VB.NET that, while not exactly obscure, is worth covering because of its simplicity and ubiquity. Just how simple and ubiquitous is it? Well, it may not be the main topic of discussion down at the beauty parlor or the saloon, but it scratches an itch that always seems to appear in the course of programming business applications. In fact, it is so successful at scratching this itch, I think of it as computational calamine lotion. Okay, enough build-up; I'm actually talking about the Parse method.
Bajillions of times throughout programming history, someone has tried to parse a string for a numeric value. Bajillions of times, a five line function has been written that may or may not contain serious defects. That's one of the reasons why I like Parse so much; not only does it prevent a lot of code rewrite, but since it's part of the framework, you know the testers at Microsoft have devoted some serious time in attempting to break it.
Let's look at an example of how one makes use of this method. Let's say we're working on the business logic for a billing system. The billing system takes verbose orders (eg, "23,000 Catalytic Converters"), and we need to capture the quantity of the order from that information. How do we do that? Well, we place a collect call to the Parse method. Here's an idea of the code.
long firstOrderQuantity = Int64.Parse(firstOrder, System.Globalization.NumberStyles.Any);
//firstOrderQuantity is now 23000.
The larger point here is that you can parse all kinds of stuff. The Parse method is a static method on any numeric value type (short, double, decimal, etc), so you can do the exact same thing for all different types of numbers. You can also parse numbers into bytes, characters into their unicode equivalents, and lots of other cool stuff. If you're curious about all of the options, just take a look at the destination datatype's parse method: byte.Parse(), decimal.Parse(), and so forth.
Writing a method of your own to do all of this could be incredibly daunting, especially when one considers all of the formats in which a number can be inputted. It's not as hard as bench-pressing a dump truck, but I'd hesitate to call it easy. Luckily, Microsoft has made such a method available in the framework. For this, I invite Bill Gates and the CLR team to my house for a corny dog. Not one corny dog each, but one to be shared across all of them; I'm not made out of cornmeal, people.