raganwald
Monday, June 26, 2006
  Off Topic: Did Microsoft FUD and VapourWare throw the competition off track?
I read a comment on reddit suggesting that the alternatives to Windows "have all been racing to put in features to compete with what Vista was supposed to be." Is that really true?

I thought about it for a while, and while I have no idea whether the Linux crowd have been zealously trying to implement relational database backed file systems, I can say with confidence that if Apple has been working on this, it's been a better-than-usual secret.

The view from Ruby Slippers in Kentucky's Red River Gorge

Let's talk about the premise of the quote above: the idea that the alternatives to Windows have been racing to implement features that Microsoft has no intention of shipping. To quote a guy with an excellent perspective into FUD and VapourWare:
Think of the history of data access strategies to come out of Microsoft. ODBC, RDO, DAO, ADO, OLEDB, now ADO.NET - All New! Are these technological imperatives? The result of an incompetent design group that needs to reinvent data access every goddamn year? (That's probably it, actually.) But the end result is just cover fire. The competition has no choice but to spend all their time porting and keeping up, time that they can't spend writing new features.
Joel Spolsky, Fire and Motion
I don't think Apple fell for the big Vista head fake: where's the next generation FS? Where's the next-generation model for writing GUI applications? Apple ignored that stuff and concentrated on iPods and iterating releases.

If Apple had bought the fake, they would have gone into the woodshed and spent years on a ground-up rethink of their OS. It didn't happen.

If anything, maybe Microsoft fell victim to Fire and Motion. They seem to have spent all of their cycles on matching Apple's security and eye candy. As if Windows users really care about gadgets.

Bill Ray could have bought secuity by buying VMWare, and bought eye candy by buying Konfabulator. The Vista team could have gone ahead and implemented WinFS and Avalon, and everyone else would have been slammed. Apple would have been caught flat footed!

It's not like Apple can't be beaten with innovation. Ask any Java developer about the frustrations of developing on a Macintosh over the years: they have lagged in an area that is provably hot. Come to think of it, 90% of the attendees at RailsConf 2006 used Apples, and OS X ships with a broken implementation of Ruby! Apple can and does miss out on 'hot' trends because they are too busy following their own strategy to be sidetracked by hype.

But Microsoft... I'm thinking that they got caught responding to the competition instead of making the competition respond to them.

That's too bad, because I agree with Gruber: the world would be a better place if Vista rocked.
 

Thursday, June 15, 2006
  Let's be "Real Mac Users"
Hence the difficult situation faced by small-minded Windows users who do not get the appeal of the Mac; to admit that Mac users'’ strong preferences are reasonable would be to admit that they (the Windows users) are unable to perceive something that Mac users can.

That to concede that Mac users are reasonable wouldn'’t just imply that Mac OS X is in at least certain ways much better than Windows, but that Mac users in certain ways have a more refined sense of taste than Windows users, which in turn cuts way too close to implying that in certain ways Mac users are smarter, which is where things turn ugly because those certain ways are, to Mac users, the ways that really matter, and any chance at reasonable discourse evaporates because both sides feel deeply insulted by the other.

—--John Gruber, "And Oranges"
As goes the Mac vs. Windows debate, so goes the One True Programming Language debate.
I'm deeply suspicious of Mac users who claim to be perfectly happy with Mac OS X. Real Mac users, to me, are people with much higher standards, impossibly high standards, and who use Macs not because they'’re great, but because they suck less than everything else.
--—John Gruber, "And Oranges"
Let's be like John's "Real Mac Users." We aren't Lisp/Ruby/Python zealots, or Agile fanatics, or AJAX aficionados. We aren't perfectly happy with our tools. We don't boast of them because we can drive all day in them and not reach the edge of our imagination. We don't swagger because we are satisfied with merely outrunning our colleagues.

We are developers with impossibly high standards and we use our tools not because they're great but because they suck less.

And when we hear of new languages, new tools, or even improvements to approaches we have discarded in the past, let's approach them with an open mind. We may find that they contain little of interest, but to an open mind, anything at all of interest is an opportunity to learn and improve.

We are far better off finding one good idea in a new tool than blogging about 999 ways it is inferior to what we already have. It takes us closer to achieving our goals.

That's what matters.

Labels:

 

Wednesday, June 14, 2006
  Abstraction is a Bear
Peter Thomas has posted a very nice call stack showing how much of the run-time complexity of a typical J2EE operation is consumed by the framework and how little is consumed by the actual business logic. There's an awful lot of noise.

The comments are worth a read. I find the comments about how the JIT will rescue us from ourselves very interesting. I helped create an interesting product called JProbe, and we spent an awful lot of time thinking about server-side Java performance.

It is absolutely not true that inlining everything in sight makes the cost of indirection go away. It's true that it makes the cost of a method call go away. That's very expensive, and worth eliminating. [I'm curious: why does the Blub crowd appreciate the importance of inlining method calls to eliminate the cost of stack allocation, but dismiss tail call optimization as unimportant?]

However, indirection has another cost. When you have a reference to a reference to a reference to a reference to something you want, fetching the something at the end of the chain usually causes page faults. You have to do "pointer chasing." That is very expensive. Although that is not directly related to the number of framework elements in the call stack, I find that highly abstract frameworks seem to have a great deal of run time indirection built in, and that's also expensive.

Now, here's what I find very interesting: as seen in the comments, many developers shrug all this off as irrelevant given the network latency and relative sluggishness of the persistence engine. Given limited development time in many real-world projects, this may be an appropriate attitude to take.

It brings to mind a joke about two hikers:
Two hikers are surprised by an aggressive bear. One turns to run away. "What are you doing?" asks the other, "you can't outrun a bear!" The hiker carries on and sprints away. "I don't have to outrun the bear," are the hiker's only words, "I just have to out-run you."
(via Joey DaVilla. The post, that is. Don't blame him for the joke.)
 

Monday, June 12, 2006
  My favourite interview question
Some years back, I was interviewed by an interesting start-up in Palo Alto. I was really tempted to take their offer, mostly because:
  1. One of the interviewers was an avid Ultimate player;
  2. Stanford. In walking distance. (And the regular Stanford Friz-ball variant game);
  3. They asked me a question which has become my favourite interview question to ask and to answer.
The question they asked was:

How might you design a program that lets people play Monopoly with each other over the internet?


Of course there’s a lot to be learned on both sides when an interviewee is asked to design something and explain their design. Both parties learn a lot about each other’s communication styles and approach.

It works both ways: for example, if I were sketching out a design and the interviewers repeatedly interrupted me to discuss my UML notation, I could infer certain things about their culture.

Those kinds of issues apply to any reasonably sized design problem. Anything larger than, say, “write a procedure that reverses a string in place.” But let’s look at three of the characteristics of the game of Monopoly that I find attractive for this exercise:
First, Monopoly is poorly defined. Chess, for example, is rigorous. The official rules of Monopoly are silent on some critical questions and vague on others. A tournament-playing aficionado will realize this immediately, but it’s easy to guide a candidate to this realization by asking some of the well-known FAQ questions.

This ‘problem’ makes it a great interview question. It drives a lot of valuable interaction between the candidate and the interviewers. You have to ask questions, make assumptions, and know when to stop gathering requirements and start driving the design.

There have been some blog posts pointing out that even trivial requirements can have many hidden implications. A determined and finicky developer can drive questions for the length of the interview. I think Monopoly’s missing requirements actually improve its suitability as an interview question.

If the candidate uses up all of the interview time trying to obtain perfect requirements, we have a problem. In the software development I do, the requirements are never perfect. I don’t demand that a candidate try to create an agile, iterative process on the spot, but I look for someone who knows when to say “close enough, let’s move forward.”

Another good way to move forward for both interviewer and candidate is to say, “ok, we’ve covered the most important requirements. Let’s make a bunch of assumptions and document them. In a real-world situation we could obtain feedback on the assumptions after presenting an initial approach.”

After all, who’s to say that a programmer, designer, or architect is always 100% beholden to others for requirements?

The second reason I like this problem is that Monopoly requires more than just a simplistic object design. What I’m about to say will be blindingly obvious to the Enterprise crowd (sorry, not you over there with the Greasemonkey script that translates your web email to Klingon). The rules must be considered as carefully as the entities. Enterprise developers have known this for years: that’s why you see rules engines, table-driven designs, and visual workflow editors in many Enterprise applications.

Now let’s talk about ‘object-oriented programming’ for a second. 99% of the stuff you read discusses modeling real-world physical objects. Things. Nouns. It is a Kingdom of Nouns. Most candidates start every design by dutifully listing all of the nouns they can think of and then they spend the rest of the time available thinking about piling them into phyla, hierarchies of “IS-A” and “A-KIND-OF.”

This approach, which I will call “noun and verb,” is so limited I’ll dare to call it brain damaged. In fun. But seriously, competent software developers spend much more time on relationships, responsibilities, and constraints than they do on trying to prematurely optimize reuse through inheritance.



Object Design: Roles, Responsibilities, and Collaborations focuses on the practice of designing objects as integral members of a community where each object has specific roles and responsibilities. The authors present the latest practices and techniques of Responsibility-Driven Design and show how you can apply them as you develop modern object-based applications.

Now let’s ask a question about Monopoly (and Enterprise software). Where do the rules live? In a noun-oriented design, the rules are smooshed and smeared across the design, because every single object is responsible for knowing everything about everything that it can ‘do’. All the verbs are glued to the nouns as methods.

Let’s take a look at a simple rules question. If a player owns Baltic Avenue, can she add a house to it?

Well, there’s a bunch of stuff about whether she can afford it and whether there is a house available in the bank. Where does that live? In the bank object? And there is a bunch of stuff about whether it is either the player’s turn or between turns. Where does that live?

And there is a bunch of stuff about whether the property already has four houses. Where does that live? Somewhere in the property hierarchy? Sounds reasonable. Now what about mortgaged property? If Baltic is mortgaged, the answer is no. That’s easy. But what if Mediterranean Avenue is mortgaged? And what if, for example, Baltic has one house but Mediterranean has none? Where does that logic live? Both of these last two questions involve knowing something about the other properties of a colour group.

Now you can debate which verbs belong to which nouns, but here is an opportunity to step back a bit and consider the larger implications of maintaining such a ‘classical’ OO design.

Consider a ‘noun and verb’ design. First, an easy question. How well does the design document the actual game of Monopoly? If someone were to read the source code, do you think they could learn how to play the actual game?

Is this a stupid question? I think it strikes at the root of sustainable software development. In real world applications, software lives for a long time and teams change over that time. Programmers are often asked to maintain software with insufficient training in its intended use.

OO programs can be brilliant communicators in some designs (“here’s everything I need to know about a Money Transfer”) and terrible in others. I think this is part of the appeal and effectiveness) of the Domain Specific Language approach. It does a better job of communicating its intentions than a simple OO design.

I’m not saying that a DSL is right for Monopoly. Or wrong. Just that it’s valuable to consider this issue when discussing an approach. There is a lot of opportunity for a candidate and the interviewers to learn about each other’s thinking that goes way beyond coding if you spend a few moments discussing the importance (or irrelevance) of a design that communicates its intentions. And I think that makes Monopoly a good design subject.

Another issue about the rules. In software development, requirements often change. What kinds of requirements changes are easy with the design? What kinds are difficult?

I suspect it’s easy to change the prices and names of properties, but very difficult to change the fundamental rules. Well, it’s probably easy to introduce the popular ‘lottery’ variation where fines are paid into a pool and anyone landing on Free Parking’ scoops it up. But some of the more esoteric variations would require making lots of changes to many different classes.

The ‘noun and verb’ design is tightly coupled, and distributes the rules across the design. If you really want a mess, consider that popular computer versions of Monopoly allow you to pick and choose rules variations for each game.

The key to making this easy is to find another way to represent the rules. I generally provide hints along these lines by asking the candidate how they plan to implement the Chance and Community Chest cards. What is the relationship between the cards, special squares like “Luxury Tax,” and introducing variant rules?

(You can probably save yourself a lot of interview time. Instead of all this hoopla, ask the candidate to describe when they have actually used the Strategy, Visitor, and Command patterns outside of a framework.)
The bottom line is that designing a Monopoly game requires giving a lot of thought to representing the rules. There are a lot of ways to do that. I’ve hinted at two, and you I’ve heard of a lot of other interesting approaches. It’s a great chance to really go beyond OOP 101.

Now to close as rapidly as possible with what I consider an essential characteristic of a good design problem, and one that applies here. Monopoly is too large to solve in one interview. This is related to the vague requirements characteristic I mentioned above.

The reason this is important is that it forces the designer to pick and choose what elements of the design to solve in limited time. Some candidates will fail outright because their problem solving style is to consider all of the implications before starting. It’s easy to spend hours on a problem like Monopoly. But will you get up and apply the marker to the white board?

>Does a candidate start with the trivia? Who cares how to represent the colour of a property? CSS? A getter in each object? Yawn. I’ll prod him to move along.

Perhaps a candidate spends all of her time working in an area of the problem she knows well. Some candidates can spend forever engineering a Monopoly Online site up to Web 1.0 scale. Or building FTD.com-like reliability. Whatever.

I’m not saying that’s bad. Or good. But I will say that given a problem too large to solve in the time allotted, there’s fantastic value in evaluating what’s important. And that cuts both ways. If you think that some of the OO design choices are critical but the interviewers hand wave it and want to see how you plan to handle 10,000 requests per minute, that’s revealing.

Summary

I like asking (and being asked) about Monopoly because it provides fertile ground for discussing issues that are critical to judging both competence and cultural fit, like:
And now, if you have a moment, I’d like to ask for your feedback. Is there a better design question to ask? What is your perspective as an interviewee? What other issues about a design should be discussed during an interview?

I’m looking forward to hearing from you. Thanks in advance!

Update: A cautionary note

Some people have objected to this question because it may be a trivia challenge: how well does the candidate know the game of Monopoly? In the comments I mentioned that the question really only applies to candidates that already know the game.

Others have suggested it may be a form of “guess the design I’m thinking of” where there is exactly one right answer, the design the interviewer has already come up with. I think this is a legitimate concern.

It really applies to any interview question. For example: “name your three strengths” or “tell me about a challenge you faced in your last position and how you overcame the obstacles.” If an interviewer is looking for something specific, they can and will twist any interview question into a variation of “guess the answer I’m thinking of.”

I won’t say that Monopoly is somehow better than other questions in this regard, nor is it worse. If you have an interview based on reviewing a candidate’s past accomplishments, don’t you think there are some interviewers that will discount those that don’t fit their personal criteria for merit?

I once had an interview where the interviewer spent forty minutes talking to me about my education, and something like fifteen talking about my fifteen years (at that time) of actual career experience. Bias in an interviewer is orthogonal to the choice of interviewing technique.


What do these two cautions have in common? Only that the most important thing for a successful interview is that the interviewer be genuinely seeking out a view of the candidate’s strengths and weaknesses. All I can really say about this question is that if (and it’s a big if) the interviewer is sincerely attempting to evaluate a candidate’s technical ability, and if the candidate has some familiarity with the game, then the session can be very productive.

Update: Some relevant links

It would be ludicrous to think of hiring a juggler without first seeing him perform. That’s just common sense. Yet when you set out to hire an engineer or a designer or a programmer or a group manager, the rules of common sense are often suspended. You don’t ask to see a design or a program or anything. In fact, the interview is just talk.


Hiring a Juggler


The bottom line in my interviewing technique is that smart people can generally tell if they’re talking to other smart people by having a conversation with them on a difficult or highly technical subject, and the interview question is really just a pretext to have a conversation on a difficult subject so that the interviewer’s judgement can form an opinion on whether this is a smart person or not.


The Phone Screen


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.

Take control of your interview


In case you didn’t know this, about 1/3 of all technical interview questions worldwide are variants of “How do you fit 10 pounds of crap in a five-pound bag?” Examples: how do you reverse a string in place, how do you sort a billion numbers, how do you write a decent compiler back end for an architecture with only four frigging registers, how do you handle fair scheduling when someone just forked off 1000 copies of some Towers of Hanoi simulation, etc.

Interviewing Ruby programmers


I’m exaggerating a lot, but the point is, when you select 1 out of 200 applicants, the other 199 don’t give up and go into plumbing (although I wish they would… plumbers are impossible to find). They apply again somewhere else, and contribute to some other employer’s self-delusions about how selective they are.


Joel on Hiring


And then there is the issue of why would someone care if I knew how to write a file copy function, ahead of what the difference between an interface and an abstract class was. Or when would I use encapsulation? Or in my design, how would I choose between polymorphism or inheritance? Or what pattern would I recommend for dealing with a general or specific problem?


What’s with the programming test!?


I know lots and lots of interviewers, at many companies, who’ve decided that they can fully evaluate you based on whether you can solve some particular convex optimization problem (or graph-search problem, or logic problem, or whatever their pet Elephant Question is), and they ask every candidate this question regardless of their background or experience. In fact, I’d estimate that some 10% of all technical interviewers ask the same questions, year after year, and they could care less about your experience.

The Truth About Interviewing

Labels: ,

 

Monday, June 05, 2006
  An insight into the practice of judging value through the mechanism of comparison to the median of the requirements of the mediocracy
Two ranchers, a Canadian and an American, meet at a Cattle Convention. The American boasts "My ranch is so big, I can git' in my truck and drive for a day in any direction, and I'm still on ma' propuh-ty."

The Canadian nods. "I have a truck just like that."
 

Thursday, June 01, 2006
  The trade-off between power and ease of use in library interfaces
Rusty has another great contribution to the discussion about locking down interfaces (a/k/a "final good or bad" also a/k/a "concrete good, abstract bad").

Rusty points out that restricting an API makes it more accessible:
The I in API stands for interface, and interfaces are for people, not just machines. APIs can be complex, confusing things... The smaller and simpler the API is, the easier it is to learn and use; the more likely it is that the API will be used correctly.
I'm going to repeat and double underscore my suggestion that there are different approaches to the problem of designing software that other programmers must incorporate into their own designs.

Rusty points out the obvious: there is a far greater 'market' for smaller and simpler things than for powerful things:
For instance, you can switch a class from storing persistent data in a file to storing it in a database or vice versa. Sometimes this is important; but be honest: how many times have you really needed to do this? Out of the thousands of classes you’ve written, how many have had significant changes in their internal data structures? Maybe 1 in 10? And in how many have you actually needed multiple simultaneous implementations? Maybe 1 in 100, or less?
True. But ummm... Does it matter whether you want to do something like this once a day, once a week, one a month, or once during a project? If you ever want to do this, why shouldn't it be possible?

Let me jump in and answer the question for you: there's a trade off to be made between power and ease of use. The power to do unusual things (like climb roof cracks or modify frameworks) comes at the expense of ease of use (as measured by the narrowness of the interface).

So if you make it possible for me to do powerful things, you might make your code harder to use for some class of people who never need to do these things. I'm all for that. There's a knob you can turn when you create your design: power vs. accessibility for the masses.

(I don't say power vs. simplicity: thanks to the Turing Tar Pit, it is possible to make something extremely simple, but have extraordinary power because you have provided the basic building blocks that allows your client programmer to do almost anything. For example, the programming language Scheme has just five 'special forms'. Almost all of the resulting power in the language, including the ability to define new Domain Specific Languages, comes from the way these five elements can be combined to create new forms.)

I really think it comes down to thinking about your 'clientele' when you design frameworks or libraries. Remember that this started with someone calling for the final keyword to be deprecated from the Java language. C'mon. Java.

Think about the Java programming culture for a moment. If I were writing a Java library for widespread use, I would consider Rusty's position carefully. After all, most of the people who would lament any restrictiveness have probably bailed and are hacking rails right now. But the remaining Java folks want their IDE and their compiler to catch all of their bugs for them. So if you 'cut against the grain', you provide power nobody wants at the expense of the simplicity they need to be productive in their environment.

But if I were writing a Rails plugin... wait! You couldn't write a Rails plugin if DHH had locked rails down to begin with. Anyways, anything you do in the Ruby world should be far more open. You have a different clientele, with a different culture. It's really that simple.

Of course, there's a trivial argument that all that 'powerful but unrestricted stuff' only works in small teams. That once you have 100+ programmers hacking on something you need more safeguards than a Missile Silo.

All I can say in response is that (1) everything that has ever impressed me in software was done by small teams, not big ones. Just twenty-nine people created the entire Macintosh computer, for example. And (2) given that productivity diminishes sharply with team size, shouldn't we be trying to find ways to make big teams smaller, such as by giving them more powerful tools?

So I think that for a different programming culture, with a different kind of client programmer, you want and need to follow a different design philosophy that emphasizes trusting your client and providing as much power and flexibility as possible.

This isn't a 'bad practice you can get away with in a small team' any more than rear-wheel drive and a manual transmission are bad engineering choices that you can get away with if a driver actually knows how to drive. Or than Scrum is a bad practice you can get away with if your team is gelled and motivated. They are appropriate choices under specific circumstances for a specific clientele that has the requisite skills and attitude. This is my theory.

Conclusion:

So you ask me, is my theory bad? And I reply with a question, for whom?

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 /