raganwald
Tuesday, November 28, 2006
  Don't overthink the interview process
You’re sitting in an interview. The interviewer hands you a marker and points you to the whiteboard. “Please write a sort routine” she asks.

Now let’s assume you haven’t looked at sort algorithms since your undergraduate days. You sort in the database. Or you use a library sort. You are a firm believer that writing your own sort routine is a case of premature optimization.

I agree, you ought to point that out. But still… do your best to write a sort routine.

Why get into the philosophy of whether you should be writing sort routines on the job? Yes, almost everybody knows that you need to be thinking about other stuff most of the time. But the interviewer wants to know if you’re smart, and for better or for worse she’s selected a sort routine to see how you think.

Here’s my suggestion: do your best as cheerfully as possible. Talk through your code aloud. Ask a reasonable number of questions, enough to show you think through cases and requirements in more depth than the other 199 people who submitted a resume.
On one interview, I was asked to do a substring search. I did the usual routine, but I explained that there was a faster method. I couldn’t remember that it was Boyer-Moore, but I explained that it used lookup tables to advance more than one character at a time. I asked whether I should work out the exact routine as best I could. The interviewer was happy that I knew there was a faster way, and especially that I could discuss the tradeoffs of building a table against the size of the search space. I wasn’t asked to write Boyer-Moore, but I was offered the position.

This is all to say that even if you don’t have QuickSort memorized (I don’t, and it’s two freaking lines in any language worth learning), there’s lots you can do to answer the basic questions “Is this person smart?” and “Are they experienced?”

Your goal is to show this off. Even if you don’t think the question is the best way to interview candidates, nothing is stopping you from using the question to demonstrate that you are smart and experienced:Good luck!
(This was inspired by this discussion on Joel’s discussion board).
 

  People want software that is cheap, buggy, and first

People reward developers who deliver software that is cheap, buggy, and first. That's because people want fancy new gadgets now. They don't want inconvenience, don't want to learn new ways of interacting with their computers, don't want delays in delivery, and don't want to pay extra for quality (unless it's obvious up front--and often not even then).

Bjarne Stroustrup, The Problem with Programming

 

Friday, November 24, 2006
  What is managing software development?
Here’s a very simple question: What does it mean to manage software development?

This question is important, because many times different people have very different answers. And if one of them is accountable to the other, there is bound to be trouble.

In this brief essay, I will give my own personal definition. It is certainly not a universal definition, and I’m not suggesting it is necessary to agree with this definition to be successful in your career or on your project. However, I suggest that thinking about the answer to this question and being in agreement with everyone else on your team and in your organisation will help you succeed.

The fundamental definition: “Management” is accountability for results, authority over resources, and making decisions based on judgement.

Accountability for Results

You are accountable for something (even if you’re working alone on a personal project, you’re holding yourself accountable). Now, what are you accountable for?

If you’re accountable for adhering to a specific process or plan or following directions, you are not managing. You’re administering. With any luck the plan is in writing. This is true even if you wrote the plan yourself. Ask yourself this simple question: is your job following the plan or developing software?

If you are managing software development, you must be accountable for the results of the development: you must be accountable for the software itself. Good management is based on measurement: being able to measure success in an objective way. You might now ‘own’ the metric for success: someone else might declare that success is hitting a certain date, meeting certain requirements, or even shipping with a certain feature list. But whatever the metric is, if you are accountable for results, you must understand and endorse the metric.

If you don’t understand the metric for success, you’re guessing, not managing. And if you don’t endorse it, you’re subverting, not managing.

Authority over Resources

Everyone has resources. For a programmer, resources are a development system, a compiler, an editor, and so forth. For a team leader, resources include other developers. Now, do you or don’t you have authority over those resources? If someone else tells them what to do, if they come and go at someone else’s discretion, if someone else dictates what you’ll use and how you’ll use it, you don’t have authority over your resources and you aren’t managing.

Authority over resources means:

Making Decisions

You must have the freedom to “trim in flight:” if you wrote a plan, you must have the freedom to change the plan. If you don’t have the personal confidence and approval of your organisation to make decisions during the life of the project, you are not managing the project.

Accountability and authority are necessary but not sufficient conditions for management. You must employ your authority to achieve results by making decisions.

Furthermore, your decisions must be based on judgement. Many people use the word “decision” to describe the act of articulating the course of action for a team. Lots of people with the word “manager” in their title tell their reports what to do. But they aren’t making decisions if they are told what to say by their manager, or by the plan, or even by an essay they read on the Internet.

A decision is when there are two or more options, each of which has some merit, and you choose the option to pursue based on your own judgement.

A final thought: Courage

Finally, I want to emphasise the element of courage. If one course of action is obviously superior to all the others, articulate things and move on. But the act of management occurs when you have two or more meritorious options in front of you. It is especially difficult when the stakes are high and your decision could lead to success or disaster. That is when you are managing: when you exercise your courage.

There you are: you are being held accountable for results. So if your decision leads to poor results, you’ll take the blame without whining that you “followed the plan.” You have the authority to carry out your decision: you cannot later complain that “you had the right idea, but the team failed to follow through.” And you had several reasonable options, so you know that hindsight will reveal other options available to you.

But you have the courage, and you manage: you accept responsibility, you exercise authority, and you make a decision. That’s management.

(This originally appeared on my web site in 2002)
 

Wednesday, November 22, 2006
  The significance of the meta-circular interpreter
A self-interpreter is a “programming language interpreter written in the language it interprets.” A meta-circular interpreter is a special case of a self-interpreter that applies only to programs where the primary representation of the program is a primitive data type in the language itself (this property is called homoiconicity). Lisp is such a language because Lisp programs are lists of symbols and other lists. XSLT is such a language because XSLT programs are written in XML.

(If you have ever written an XSLT that transforms other XSLTs, then you immediately grasp the advantage of a meta-circular interpreter over an ‘ordinary’ self-interpreter: it is not just possible, but it is easy to write programs that write programs, because you don't have to fiddle with transforming each program into an abstract data structure (typically a tree) that can be manipulated by your program.)

This is interesting to both language theoreticians and hobbyists. But does it matter to those of us trying to get things done? What is the significance of meta-circular interpreters and self-interpreters?

The short answer is that if you are working on meta-programming, a self-interpreter makes all things not just possible, but practical. The lack of such an interpreter places a limit on how much you can accomplish using your implementation language.

Meta-programming

Let’s start our examination of the significance of self-interpreters with a review of meta-programming, or bottom-up programming. This is the practice of constructing a programming language tailored to your problem space. You get your language’s basics working by building it on top of a base, or implementation language, and then you build your solution in your solution language.

While meta-programming, you are working on two tiers either simultaneously or alternately: you work on expressing your solution in your solution language, and you work on the implementation (whether that be fun stuff like making it expressive or plumbing stuff like making it fast enough to be practical) in your implementation language.

An important and popular sub-domain of meta-programming is the practice of writing Domain-Specific Languages or DSLs. DSLs are solution languages tailored to resemble as closely as possible the human jargon of “domain experts.”

(Obie Fernandez has an excellent presentation on the rationale for and construction of DSLs.)

DSLs are commonly cited as useful in areas where programmers who are not domain experts collaborate with domain experts who are not programmer. In my own experience, DSLs are also valuable even when the programmers are themselves the domain experts. My rule of thumb for whether a DSL would be worthy of consideration is to ask how two programmers discussing the solution to a problem over an IM client would talk. If their language would closely resemble the natural constructs and idioms of their chosen implementation language, there is no need for a DSL.

This is not always the case. A very classic example is that of SQL. SQL is a DSL designed for programmers to express relational algebra rather than the imperative steps for performing queries and updates. Although complex cases are impenetrable to the journeyman, its general form closely follows the way even a non-technical person would express their thoughts about data that is stored in tables.

Another example of a successful DSL for programmers is the regular expression engine present in almost every language (whether baked in or as a commonly available library). Programmers do not discuss searching for text patterns in terms of backtracking and lookup tables and loops unless they are implementing a search library themselves.

Programmers talk about matching the string ‘Nokia’ followed by four digits, a forward slash, and two numbers separated by a period in the User-Agent Header. Regular expressions, while imperfect, match the way programmers think and talk about text matching much more closely than writing out the most efficient steps using strstr and for loops.

What about the meta-circular interpreter?

Meta-circular interpreters are nothing new. Lisp is most famous for its meta-circular interpreter. But do you know that one of the world’s most popular programming languages has the next best thing, a self-interpreter? The C programming language’s compiler is written in C. That’s interesting. But why is it significant?

Well, instead of heading up the ‘power continuum’ and talking about Lisp, let’s stay with C for a moment. If you’re a C programmer and you become very, very interested in building a better programming language, you have in your hands the tool to make changes as you see fit.

You might, for example, start with a pre-processor and implement the first version of your C++ language by mechanically translating a C++ program to C. Or you might bootstrap your C++ language by writing a compiler for C++ in C. Because you have in your hands all of the tools for going from source to running program, you can enhance and change its behaviour exactly as you please.

When a language is not implemented in itself, you have limitations on your ability to create new forms. One might argue that Lisp’s macros make it possible to build any other language paradigm on top of Lisp. This is partially correct, however macros alone are not a complete answer. Macros act to rewrite local sections of programs.

You cannot—to my knowledge—take a dialect of Lisp that does not support tail recursion and use macros to execute tail calls in constant space without rewriting every function using your macro. A similar argument holds for using macros to implement continuations. You must manually rewrite every function using your macros if you want to change the global behaviour of your program.

Manually blank every blank. This sounds an awful lot like something we can automate. Automatically transforming entire programs is the province of interpreters and compilers, isn’t it? If you wish to perform transformations that are global in scope, you want a custom interpreter. Of course, you can write one from scratch in your implementation language.

But… This sounds like we are headed towards the Turing Tar Pit. Isn’t it much easier to use the interpreter that’s built in? Implementation languages that provide an interpreter or compiler for themselves provide an industrial-strength, debugged platform for the construction of solution languages.

This is the other half of the power of Lisp: if you want to change deeper fundamental language features like whether you have a Lisp-1 or a Lisp-n, or whether all evaluation is lazy, or…, or…, or… you can, because Lisp interprets Lisp and Lisp compiles Lisp.

It is this reason that languages like Ruby, which is implemented mainly in C, provide less maximum power than languages like Smalltalk, which is implemented mainly in… Smalltalk. For example, there is talk—at this time—that continuations will be temporarily dropped from Ruby 1.9. If you have an application making heavy use of continuations, what is your upgrade path?

Of course, not everyone thinks they need all of a more powerful meta-programming implementation. You will have to decide for yourself whether a language without a meta-circular evaluator or self-interpreter offers other benefits that outweigh this significant feature.

Serving the self-interpreter to your canine companion

As Simen pointed out in a comment, Ruby does have a third-party project to interpret Ruby in Ruby called Rubinus. Assuming it graduates from its current status as an experimental work-in-progress, how is this different from having a self-interpreter baked into the language?

When a language is built on top of a self-interpreter, the language designers are forced to eat their own dog food.

Now it is not correct to say that Matz does not use Ruby. He does, and so he does eat his own dog food. And for the domains where he uses Ruby, he has optimized Ruby to be a useful tool. But since he doesn’t use Ruby to build Ruby, he does not have the same incentive to tune Ruby for the purpose of building languages.

An obvious example is Ruby’s performance. It is perfectly fine for building CRUD applications. However, it lacks really high performance when working with complex data structures in memory. This is the kind of thing that an interpreter or compiler has to do when parsing code or managing cactus stacks.

Imagine what would have happened had Matz become impatient waiting for Ruby to interpret itself when he was first building the language? I suggest that the implementation and language would both be tweaked to bring performance up an order of magnitude or more. Programmers are notoriously impatient with slow tools.

The implementation is not the only thing that improves when a language designer eats her own dog food by baking a self-interpreter into the language. The design of the language itself changes. Larry Wall has said that “Languages differ not so much in what they make possible, but in what they make easy.” When a designer builds their new language in itself, the language invariably makes building languages easy.

So I suggest that the presence of a self-interpreter baked right into the language, not bolted on as an after-thought forces a language to be useful for building solution languages.

(This is not a broad criticism of Ruby, or a suggestion that Ruby is not an excellent tool for building a wide variety of useful solution languages. I’m just trying to point out the salient distinction between baking a self-interpreter into a language from the beginning and bolting one on the side.)

But I’m a tool maven, not a language maven

Of course you are. So tell me, how does Eclipse do all of its magic with Java, a language lacking a self-interpreter?

The answer is here. The Eclipse team based Eclipse on VisualAge for Smalltalk. They were more than familiar with the benefits of having a self-interpreter, so they wrote most of one in themselves, in Java. Self-interpreters are also the basis for building advanced tools.

Labels: ,

 

Tuesday, November 21, 2006
  The world of selling products for developers who choose their own tools
Eric Sink on Borland spinning their development tools off into a separate company:
Welcome [back] to the world of selling products for developers who choose their own tools. This is SourceGear’s path as well. Lots of companies prefer to sell products for developers whose tools are chosen for them. Your parent company is one example. That strategy can be quite lucrative, but it’s not very satisfying.

It’s tough to sell products to developers. You get squeezed from both ends: lots of developers are cheapskates. Some are so religiously opposed to paying for tools that they stay up nights making free copies of commercial tools instead of inventing new ways to help developers.

And from the other end, companies that can fly upper management to Atlantic City have huge marketing budgets and work very hard convincing companies that they should dictate every last detail of the development process from the top down.

So building a business on the basis of developers (and development teams) who simultaneously have the freedom to choose their own tools and also are open to the idea of paying for high-quality tools that make their working lives better requires a huge amount of patience and passion.

I recall using TurboPascal many years ago to write a multi-user business application many, many years ago. I wish the descendants of that development team every success. And, if I ever find myself building a team within the MSFT ecosystem, I would certainly give SourceGear or TeamPrise a call.

If you’re going to commit to a career in harmony with your values, it’s nice to do business with people who have made the same commitment.
 

Friday, November 17, 2006
  The first seven books I would buy if my shelves were bare
Lucas Carlson won a $100 gift certificate on Amazon.com for his 2nd place entry at Rails Day (in collaboration with John Butler). Congratulations, Lucas!

Lucas asked for suggestions on spending the money. I tried suggesting a new iPod Nano loaded up with the SICP lectures in video podcast form. But as you would expect for someone working in a music-related venture, he has plenty of toys already.

So… here are the first seven books I would buy if my shelves were bare (in no particular order):
  1. Structure and Interpretation of Computer Programs. You can read it for free on line, but it’s even better as a physical book. One for the ages, it’s the kind of thing that ought to be bound in rich leather (if you go for that sort of thing) and kept in the library you build for your luxury castle.

  2. To Mock a Mockingbird. It seems you can’t raise micro-capital these days without understanding fixed point combinators. Here’s the most enjoyable text on the subject of combinatory logic ever written. What other textbook features starlings, kestrels, and other songbirds?

  3. The Media Lab: Inventing the Future at M. I. T.. Stewart Brand’s book captures the legendary think tank’s culture and ideas. Compare and contrast their view of broadcatch with today’s RSS feeds, or narrowcasting with today’s 500 channel television.

  4. On Intelligence A book that shook my views about how my brain works. To pick one nugget out of many, neurons are so slow that in the time it takes for us to react suddenly—say to duck a flying object—there is only time for a chain of at most 100 steps to complete. 100 steps do not permit us to perform any complex reasoning or look-up. Jeff explains how the neocortex can accomplish complex tasks using layers of parallel switches.

  5. Philip and Alex’s Guide to Web Publishing. While the technologies suggested (TCL, AOLServer) are unlikely to float your boat, this is the most beautiful technical book on my shelves. Philip’s advice on how to build software for web publishing and approach is still relevant several generations of web developers later. (Also available on line for free.)

  6. The Recursive Universe: Cosmic Complexity and the Limits of Scientific Knowledge. Although it seems to be out of print, hunt down a copy for yourself. A thrilling journey into the ideas of the great John Horton Conway and computation’s building blocks. Best of all, it’s explained beautifully using the legendary Game of Life. Who knew that puffer trains and spaceships are Turing Complete?

  7. QED: The Strange Theory of Light and Matter. Yes, the full Feynman Lectures are incomparable, and for further thrills you can listen to him give the lectures on audiobook. But in QED, Feynman does this one magical thing: he explains how a mirror reflects light. And in the process of explaining how light actually reflects off a mirror, Feynman deconstructs classical physics and rebuilds our understanding with Quantum Electrodynamics. For a moment, you can understand how little we really know about how the universe works.

Is there a book you would recommend? What’re your feelings about the books I’ve suggested?

p.s. Shane Sherman’s The 5 Books that Every Programmer Should Read

Labels: ,

 

Wednesday, November 08, 2006
  Take control of your interview
I’m helping some colleagues interview programmers, and for once I’d like to offer some suggestions to the interviewees and not the interviewers. This post is about using the interview to maximize your chance of landing the right job.

have an objective

First, you need to walk in with an objective. No, not “to secure a strategically progressive position leveraging your forward-going architectural vision and hands-on experience to advance the division’s mission,” but a simple, tactical objective for the interview.

Here’s what I suggest. Think of three things you want the interviewer to know about you that you think they are unlikely to find out if they ask all the questions.

The important ideas are that (a) you want the interviewer to know about each of the three things, and that (b) the interviewer is unlikely to ask about all three if you don’t exercise some control over the interview.

Let’s start by ruling a few things out. First, don’t bother with how many years of technical experience you have with the company’s tools and platforms. If they are using in-house Common Lisp macros compiled to C and then distributed on a grid with MapReduce, I guarantee that they will ask whether you have any Lisp or distributed programming experience all by themselves. (You can still take advantage of your experience, I’ll show you how below.)

Second, rule out anything that doesn’t really help sell them on you. Yeah, yeah, hockey is competitive and it takes a special kind of focus to be a goalie. I get that, but it really only sells when the interviewer is also a hockey player. My suggestion is put that kind of thing at the bottom of your resumé and let them ask about it if they care.

the three things

The three things you want to take into the interview should be stuff that matters to them but is hard for them to ask about. Stuff that doesn’t pop out of your resumé. I don’t have a pat formula for generating these items that I can share, but here are a couple of ideas to get you started.

Remember the technology buzz-phrases we rejected (“five years of JEE” “Common Lisp”)? Think about the difference between yourself, presumably an expert in these areas, and someone who has only worked on one project with the same technology. You both touched all the same tools and code, but there’s something special about you, your extra experience means something. What is it?

Joel Spolsky and Peter Norvig both suggest that you cannot pick up a new programming language or platform and become proficient overnight. That being said, if you tell me that you have five years of experience, I have no idea whether you have five years of experience or whether you simply did the same thing over and over again. What is it that you learned that makes you special? What secrets to you possess that can’t be listed on your resumé?

For each person, there will be different answers. One person might say that their “secret sauce” is that they have learned the ins and outs of the platform, they know what works and what doesn’t, they know how to work around the shortcomings. Another might emphasize the non-technical skills. I would personally be impressed with anyone who said that what makes them special is that they are very, very accurate when they estimate tasks and projects.

This leads naturally to another area I would mine for nuggets: Soft or non-technical skills.

99% of the dreck you read about interviewing programmers is about finding out whether they can actually write programs. Rightly or wrongly, most interviewers focus on the hard skills. But if they never get around to discovering your ability to juggle priorities, or write effective technical documentation, or analyze requirements, how will they know that you are far and away superior to the other five people they will interview this week?

You have to tell them, that’s how they’ll find out.

tell them about it

Walk into the interview with your three things. Now, the interview is a game. Presuming you don’t get thrown out or you don’t walk out before it ends, you win the game if the interviewer discovered all three of your things. If you like games as a metaphor, call them goals.

If the interviewer asks you about one of your things, that’s an easy goal. Take it.

If the interviewer asks you if there’s anything you’d like to mention about yourself, that’s an easy goal. Talk about one of your things.

If the interviewer asks you about something related to one of your things, answer the interviewer’s question and then ‘coat tail’ your thing onto the end. For example:

Interviewer: It says here you worked on JProbe, that’s a Java tool, right?

Interviewee: Absolutely. JProbe is a suite of tools for JEE Server-Side development (answers the interviewer’s question). Under my management, we released three consecutive versions on schedule. I’m really hoping that there’s an opportunity to apply my focus on hitting plan to this team (adds on).

Watch politicians “staying on message.” Now matter what question they are asked, they spit out their own pat statements. You don’t want to be that plastic, but you have to take responsibility for a a successful interview. And you know what? If the interview ends with your best features undisclosed, the company loses as well.

One more time with the coat tail:

Interviewer: What’s your experience with Ruby?

Interviewee: Well, I was the lead developer on the Certitude project. We built that with Rails and we included a fairly heavy dose of Ruby idioms, including a domain-specific language for pattern-matching and lots of dynamic meta-programming (answers the interviewer’s question). One of the things I discovered on that project was the importance of a bomb-proof quality control process when you have such a powerful language. I customized our continuous integration server to track changed files, tests, bugs in a unified report interface so we could monitor the most troublesome modules. It really saved our bacon late in the project when we had to really tighten up our risk management to ship on time (the add on, emphasizing the process).

if all else fails

Perhaps you didn’t get a good opportunity to mention your three things and the interview is winding down to a close. Don’t try a desperation coat tail where you try to stick two completely unrelated things together. Instead, try using a question to introduce one of your things indirectly.

Some examples:
Opportunities to ask questions should not be wasted on trivia like the company’s dental plan or whether they prefer cubicles to private offices (actually, neither are trivial, but they are not important until you have given the interviewer every reason to hire you).

My suggestion is to only ask questions about areas where you have something positive to contribute if the question leads to a spirited discussion. And the best way to make that happen is to plan in advance.

You have three things you want to say, and you should walk into the interview with three questions you can ask that will turn the conversation towards your agenda.

back to square one

So here’s how to get started.
  1. List your three things you want the interviewer to know about you that you think they are unlikely to find out if they ask all the questions;
  2. Write a one-paragraph description of for each thing that you could use to ‘coat tail’ onto another question;
  3. Think of a question you could ask for each thing that would naturally lead to a discussion.

Good luck.

Labels: ,

 

Reg Braithwaite


Nota Bene
A Brief History of Dangerous Ideas

Share
rewrite.rubyforge.org / ick.rubyforge.org / andand.rubyforge.org / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

Beauty
IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

Work
The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Buy Raganwald a Coffee
If you enjoy reading my weblog, please consider buying me a Darkhorse Double Espresso, for just $3.15 Thank you!

Management
Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

Notation
The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Opinion
Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

Whimsey
The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

History
06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /