Monday, April 27, 2009

Tips on Hiring Agile Programmers

We're looking to hire another couple programmers here, and while I was talking about it with the coding crew, we had some thoughts, there was a rant or two, so now I'm here.

First, What is Agile Programming?

It's not a buzzword. Agile programming is a methodology, which is just a $10 way of saying it's a set of methods. What brings those methods together is that it makes programmers and the code they write more agile. As in flexible. Bendable. Responsive, dextrous, nimble. Agile programmers should be able to adapt the code they write to changing requirements. That's really the whole point. There's a subthread in discussions about "what is agile?" that basically says you won't understand a problem until you try to solve it, and so changing requirements are a natural outcome of exploring the solution domain until you understand it -- but that's not really my point here. We can argue that later.

Using interfaces and patterns is nice, but that's not agile programming. Interfaces and objects are just a part of object-oriented programming, and patterns appear in any programming language (although most well-known patterns are OO patterns).

One part of being agile is avoiding tight coupling. If there's a one-to-one relationship between two class hierarchies, then any time you add a class to one branch, to have to make a similar change to the other branch. This ties those two trees together; they're now tightly bound. One agile approach would be to use smaller bits, like methods (or delegates, in C#) instead. Or to embed the behavior of the second class in the first. Or to get rid of whatever it is that requires you to have two trees with all of the same class types in them.

Being agile means being responsive to change. Writing all your code through interfaces is nice in theory, but whenever you need a client to pull more information out of a subclass of that interface, you're stuck with a problem -- throw in a using clause, or what? Is the interface providing something specific? If there's a 1:1 mapping between interfaces and implementations, ie one interface class for every implementation class, then you haven't done jack. There's already a way to hide implementation from a client, and it's the fucking private keyword, you moron. If the client is going to break through the interface anyway, then get rid of it, it's not actually hiding anything. You should only write code once; there should only be one class exposed to your client. (A 'using' clause etc winds up exposing two classes.) This is the principle of Once And Only Once. If you've got an interface, there better be a reason for it other than "my teacher told me to." If you're doing something and you don't know why, then you better need to do it to get something to work. If you can skip a step that someone told you was required, and your code works just fine without that step, then you've got smaller, more nimble code. That is what Agile means. (And that your guru is full of it.)

Which gets me to the rant: some programmers do things just because they're supposed to. Like adding interfaces for everything, even if there's no hierarchy there. Or using patterns everywhere. I write patterns all the time, but I don't obsess over it. It just happens. If you have to scan through Gang of Four to figure out what pattern to use, then you're not yet a jedi. That's OK, but it's also not the best way to program. Understanding patterns is better than throwing patterns at a project. That's like throwing bailout money everywhere.

Likewise, you don't need a factory for every object. The constructor works just fine! Just call the constructor! I've seen this problem in programmers that have misunderstood the factory pattern. A builder is a class (or method) that assists with complex construction code; a factory is a class (or method) that can build one of several different objects, and returns them through a common base class (which might be an interface). Again, if a factory only builds one type of object, then why do you have the factory? If a class only has one constructor and construction is simple, then why do you have a builder? Both add to code bloat and complexity, and thereby inhibit the ability of future programmers to add new features or fix bugs. Or even understand what the hell you were doing. And here again is the benefit of agile programming: if your code is small and nimble, you can change it more easily.

Wait, I thought you were talking about hiring programmers?

Many academic programmers heed rules that they don't understand. You want the guys that have figured things out for themselves. There's a lot of clues here to figure out how to tell the first group from the second.

In general, the best way to hire programmers is to get them to do the job they're about to do. Give them a written test before the interview, or stand them in front of a whiteboard and ask them to pop out a design.

Not just a function; a design. The stuff that matters, for agile, is design -- not algorithms. (Algorithms are important, but ultimately agile isn't about algorithms. Test algorithm knowledge, sure, but that's not why you're reading this.) Good programmers have a sense not only of algorithms but also data structures. Good OO programmers can think in module-sized units (as well as class-sized units, method-sized units, or statement-sized units). Ask your candidates to express some designs. If you're interviewing a senior candidate, then he should understand framework-sized units. Ask him to sketch a framework for handling a large, complex data set and a wide variety of operations, probably something related to your personal problem domain. You don't really want a correct answer so much as strong thinking. (Don't judge a candidate by how closely they parrot your personal favorite design, or the one that your office has chosen. That's not what you're looking for here.)

For juniors, start with the simple stuff: persistance and streaming, three-tiered architecture stuff, de novo object creation, parsing. And ask them to get specific; where are the interfaces? What patterns do you use here?

And the money question: why?

The thing to look for is not their answer so much as how they answer. Is the candidate trying to think up a good reason for their answer, or are they just struggling to translate their understanding into words? The faster you can get a candidate to talk, the less rationalization goes on. It's ok if they're stumbling around their words or gesturing a lot with their hands, or just drawing circles on a white board and using too many pronouns -- this suggests that they're thinking of objects, not trying to reconstruct some quiz question a prof gave them once.

Object-oriented designs are inherently visual. They're visual creations. This is why whiteboards are a must in interviews, and why it's very difficult to assess a programmer over the phone.

Getting a candidate to explain what agile means is less important than hiring a candidate that inherently does agile things. And the way to test that is not to get him to talk, but to get him to do.

No comments: