November 24, 2009
…in which the title is a reference to Jeff Atwood’s greatest hit.
OK, you all know the story. Or, in case you don’t, here’s a bit of expository dialogue for ya. Joel Spolsky is an internet celebrity who has been blogging since about 20 seconds before there were blogs - usually on business-of-software-type themes. He’s an important read for people new (and old) to the development world for the three best reasons in the world: (1) he can write, (2) he has insightful things to say and (3) he’s confident without being arrogant - which is to say, he’s confident enough that he can see when the emperor isn’t wearing any clothes, and says so, but not so confident that he tries to sell you on solutions that are out of the reach of the ordinary programmer.
Sometime in 2006 he angered a lot of Ruby programmers by suggesting that Ruby was not quite ready for prime-time - because its ecosystem of libraries, third-party apps and expert advice from the community is almost, but not quite, up to scruff for real-world deployment. To make it all that much worse, in a throwaway line at the end of that entry he let slip that his own flagship application was written in a proprietary, private, in-house programming language called Wasabi. And if that weren’t bad enough, that Wasabi is a dialect of Basic that compiles down to VBScript and/or PHP, and has Ruby on Rails-like active records. For someone claiming that Ruby itself was not quite ready for prime time, it seemed hugely hypocritical.
There was an internet outcry, and Jeff Atwood joined the chorus with this entry’s namesake. Jeff and Joel have since buried what minor differences they ever had and now collaborate on the excellent StackOverflow.com, water under the bridge, etc. etc.
Well, the incident is over, so it’s way too late for pertinent comment, but I don’t mind saying that I think Jeff was wrong about Joel jumping the shark - for a number of reasons. First, Joel was right - both about Ruby and Wasabi. Ruby is indeed not quite ready for prime time. That’s as true now as it was then - and though industrial applications do get written in Ruby, I’m with Joel in not quite being willing to trust any mission-critical code to it. There are just too many holes - and intimations of holes - there that I couldn’t be sure one of them wouldn’t pop up right as it was time to ship. And he was right about Wasabi too. Writing your own compiler and having your own in-house language is an excellent solution to the portability problem because it means you can target as many new platforms as you like with exactly the same codebase. You can even target platforms that have yet to be invented with the same codebase. People misunderstood Joel here - he wasn’t compiling Wasabi down to machine code - but rather down to existing tools that had the requisite ecosystems he’d talked about.
Second, Jeff was misusing the term jump the shark. It doesn’t mean “produced something silly” exactly. Or if it does, then it’s a special kind of “produced something silly.” It’s produced something that’s unintentially silly as a side effect of being more concerned with attracting attention than saying something of substance. Applied to TV programs (its original domain), to say a show has “jumped the shark” is just to say that it’s inadvertantly let slip that it’s no longer interesting or vital because it had to step outside of its normal bounds to get attention. You know, the whole “tonight, on a very special episode of…” thing. Which is why the categories on the original jumptheshark.com website (now defunct) included things like “they had sex” or “they got married” or “they went to college.” It’s the kinds of plot devices that producers come up with rather than the show’s original writers, because where to the writers the show is an object of affection, to the producers it’s just a cash cow, and they’re trying to keep it going indefinitely, without any regard for its organic stopping point. “They went to college” is jumping the shark when it’s on a high school show - like Saved by the Bell. “They had sex” is jumping the shark when it happens on shows like the X-Files, where the unresolved sexual tension between the main characters was one of the drivers. Ditto “they got married” (cough Cheers cough). Jumping the shark isn’t just “running your course,” it’s refusing to admit that you’ve run your course, and failing to recognize that the boundaries you were never supposed to cross were there for a reason. When you’ve run out of chances for Mulder and Scully to just miss going to bed and you find them actually in bed, it’s time to cancel the show - because however logical that development is in character terms, it’s beyond the confines of what makes the show interesting.
It’s not clear that “jumping the shark” works for bloggers. It’s a television term, and I’m not sure how well it translates. I’m sure it doesn’t mean what Jeff was using it to mean - which was just “blogger x said something I think is silly.” But here’s what it might mean, if I can get enough people to agree with me: “blogger x produced a column that manufactures controversy for the purpose of drawing attention to himself long after he’s run out of important things to say.”
If that’s what it would mean to say that a blogger has “jumped the shark,” then I think Joel might plausibly (finally) have done it in September with the Duct Tape Programmer entry.
This one caused its share of stir on the internet too - though not as much as the other one, because people were already well aware of how inimical Joel can be to unit tests. The basic premise is that there is a tension in the programming community between people who get things up and working quickly and those who spend a lot of time planning before getting to work. People who get things done quickly - the “duct tape programmers” - tend to rely on old technologies that they know really well, so that even if the tool isn’t quite up to the job, they can make it work for now, at least long enough to get the application shipped; they’ll go back and fix the leaks later. The people who spend a lot of time planning before getting to work run the risk of never doing anything because even if they DO understand why all these hyperpowered tools that they’re recommending just because they’re trendy buzzwords (which they don’t necessarily have to and frequently don’t), they’re still wasting time learning how to use them. Or, more accurately, they’re learning how to use them at inappropriate times: best to learn the new tools after the app has shipped and apply them to making a better v2.0 than to delay releasing v1.0 for lack of training.
The entry seems almost calculated to piss off the Test Driven Development crowd. It’s the kind of thing that you write knowing you’ll get mail. And that’s OK if what you have to say is important. But once you start combing through Joel’s prose, you find very little that you can actually pin him down on. Case in point:
A 50%-good solution that people actually have solves more problems and survives longer than a 99% solution that nobody has because it’s in your lab where you’re endlessly polishing the damn thing. Shipping is a feature. A really important feature. Your product must have it.
Who’s he arguing against here? There simply isn’t anyone anywhere who will continue talking about code past the point when it’s supposed to have shipped - not in industry anyway. Or, if there are such people, they’re obvious candidates for firing. Done! No one wants those people on their team. It’s as if someone had written an interview advice book that said “the secret to a successful job interview is remembering to offer the job to the people who will succeed at it and passing on those who won’t.” Well, sure. Sure we want coders who write code that gets shipped and people use. What we need you for, Mr. Spolsky, is to tell us how to spot those people.
But the advice here is unhelpful too.
One principle duct tape programmers understand well is that any kind of coding technique that’s even slightly complicated is going to doom your project.
Is that true? I don’t know - because I don’t know what is meant by “complicated.” “Complicated” here seems to mean “any technology the developers don’t already know very well.” But that doesn’t square well with this:
Duct tape programmers tend to avoid C++, templates, multiple inheritance, multithreading, COM, CORBA, and a host of other technologies that are all totally reasonable, when you think long and hard about them, but are, honestly, just a little bit too hard for the human brain.
Do they avoid these things? I don’t think they do. I think people who are brilliant at C++ because they’ve been writing multithreaded code in it for years are going to do just fine writing multithreaded code in C++, and you want those people on your team. There can be such a thing as a C++ “duct tape programmer” if that guy is someone for whom C++ is the tool of choice, the language he writes everything in without blinking. It isn’t really the complexity of a technology that’s at issue, if I understand this correctly, but rather the coder’s familiarity with it. It’s all just a fancy way of saying “don’t get distracted by shiny things when it’s time to sit down and work.”
Or maybe it’s really “don’t spend more time thinking about what you’re going to do than you do actually doing it.” Or, honestly, it seems to be a little of both. But whichever one - or both - of these it really is, it’s the kind of advice that makes itself. It doesn’t help us much to point out that these issues are there since everyone is well aware of them - and not just in programming, but any field, really. There’re aphorisms for both sides that predate the computer by quite a bit: “a stitch in time saves nine” vs. “if it ain’t broke, don’t fix it.” Sometimes it’s good advice to plan ahead carefully, and sometimes it’s good advice to just get down to work and stick with what you know. How to know which is which? That would be a subject for an essay. But this one seems to say “don’t plan too much if planning too much would be a bad thing.” Uh-huh.
It’s manufactured controversy. It’s an essay that says something that seems controversial without actually saying much of anything at all. I don’t know whether there’s such a thing as “jumping the shark” for bloggers - but if there is, it might be something exactly like this. Someone who had useful and insightful things to say for most of his career finds himself stirring up non-controversies so that people can argue with him about something you can’t prove he said.
But then again, “jumping the shark” for bloggers might be more along the lines of what happened to the Arc Language Blog, which used to be about the Arc Programming Language but has since become a repository for - admittedly cool! - stories about the neat things you can do with an Arduino. Arduino’s great, but even if everything he shows is implemented in Arc, the blog has strayed from its purpose.
Well, maybe jumping the shark for bloggers is either of those things, and I’m doing what Joel’s doing by saying “hey, we all know it when we see it, so let’s call it out!”
So fair enough - I do indeed know what is meant by a “duct tape programmer” just from the clever name, even if Joel doesn’t do the best job outlining exactly what it is (or, probably more importantly, what the evil alternative is) for the rest of the screenspace. And I guess this is a term that will now get adopted for common use in the hacking blogosphere. And if that happens, then I guess it’s not fair to say that Joel has jumped the shark, since any blog that is creating useful jargon is ipso facto still relevant. And certainly Joel still says insightful and useful things on the Stack Overflow Podcast. In fact, the latest one I heard was the one that was a collection of clips from DevDays, and I definitely think Joel was on the right side of that brief argument with Scott Hanselman about Wasabi and type inferencing. The larger point that I took away from that, in fact, was that Joel was hinting that a lot of “new” technologies - such as compile-time type inferencing - aren’t really new at all, they’re just “recently popular.” A lot of what counts as progress these days goes back to new programmers not really knowing their field as well as they should - which was actually the subject of one of his better essays from back in the day. It’s like that Asimov short story about the guy who’s considered a genius because he rediscovers long division in a society where all math is done by machines. There really is a cost associated with innovation on the educational level, even if innovation makes you more productive overall.
And actually, I think that would have been a better way to express what a “duct tape programmer” is. It isn’t someone who eschews planning for practice, since both planning and practice are important. Rather, it’s someone who, by virtue of being really good at one thing, is in fact good at all things, because the time he saves not learning every new tool that comes along allows him to think about more general techniques. So it’s the difference between the person who spends his time learning general strategies for Magic: the Gathering rather than buying endless expansion packs hoping to get the ultimate trump card. Or the kid who builds what he needs out of basic Lego sets rather than assembling a different special kit for each highly specific thing he wants to build.
If THAT’s Joel’s advice, then I completely agree. But then I wouldn’t call it “duct tape programming,” since duct tape, in the end, isn’t a production-level tool, but just a stopgap for the time being. Python is that for me - the language I can get things done in quickly that I then go back and port to C++ later. The better advice might be to just get really good at C++, so that I can skip the initial Python step altogether. Which is to say that I think this “duct tape” thing is a red herring. In the absence of real skill and practice (and I am a Linguist first, so programming is a secondary thing - though I admit I find myself wishing more and more that programming was my fulltime job instead), duct tape is the way to go: it keeps your plumbing working until you can read up on water pressure. But duct tape is never better than the real fix, and if you’re a professional, you should start with the real fix. So if the advice Joel is giving is “don’t let shiny new technologies distract you from getting things done,” then some good advice about how to actually accomplish that is “pick one thing and get really good at that thing - learn it exhaustively, in fact, and practice at it daily - and then you won’t be distracted by the shiny new technologies in the first place because you won’t need them so much.” But that’s the kind of advice Donald Knuth would give, and not Jamie Zawinski. Of course, Jamie Zawinski was the first chapter in the book that inspired Joel to write this essay, and Knuth, as luck would have it, is the last. Maybe Joel just hasn’t finished the book yet.
November 23, 2009
This post reminds me why I read Will Wilkinson. It is wonderfully concise, has a good point to make, and presents an angle on a common debate topic that neither side will have really considered. I am in general suspicious of Wilkinson for some of the same reasons that Todd Seavey seems to be (to quote: “rightly or wrongly — you have to admit that his shtick is arguing that libertarians ought to accept elements of the welfare state”). But today is one of the days that I do believe he’s on “our team.” For all that is really required to be on “our team” is that one be appropriately skeptical of government intervention. And by that I don’t mean signal skepticism of govenrnment intervention (in the Robin Hanson sense) - which is cheap and easy. I mean actually stepping back and thinking about whether the government program du jour really is necessary and/or more likely to be efficient/effective than the private sector alternative. Since in the vast majority of cases the answer will be “no,” and since in the vast majority of cases the government program du jour will have as a side effect the increasing of opportunities for mismanagement and corruption, then the default position should be to oppose any new proposals for government intervention. This isn’t an insurmountable barrier for the socialists, it’s just a way of keeping the burden of proof on those who want to expand the role of government. As I’ve made clear on this blog, I’m not knee-jerk opposed to an increased government role in the healthcare sector, for example. But I AM very much knee-jerk opposed to the timetable on which the Obama crowd seems to want to get it done. They’ve skpped straight past making the case for government intervention, and then straight past taking the time to reasonably compare alternative models of government intervention, right over to “pass some plan, ANY plan, yesterday.” This is NOT a good idea.
I wonder whether Matt Yglesias - or anyone else, for that matter - will get around to answering Wilkinson’s excellent question about TARP?
November 19, 2009
There was a neat article in Wired recently about math shortcuts - you know, tricks to solve math problems quickly. I enjoy that stuff because it’s all about how you organize the numbers. Unfortunately, the article doesn’t make many of the tricks available, but there’s a list of user-contributed ones in the comments - and anyway, it’s not like the sourcecode is compiled. All you have to do to come up with these things, really, is play around with digits and variables.
Anyway, there was one posted in the comments that hadn’t occurred to me before. If you want to square a number that ends in five, the following works:
(1) separate the number into 5 and the prefix: i.e. 25 ⇒ 2, 5
(2) multiply the prefix by its successor: (2)(2 + 1) ⇒ 6
(3) slap 25 on the end: 6, 25 ⇒ 625
Neat, eh? This one caught my attention because it’s not immediately obvious why it works. OK, it’s pretty obvious where the 25 comes from, but not necessarily why the other part of the trick works. Fortunately, I can look at the assembly code.
For 25 it must go something like this:
(20 + 5)(20 + 5)
In general form, that’s
(x + y)(x + y) = x^2 + 2xy + y^2
25 is the y-squared, so the question is how you get
(prefix)(prefix + 1)
out of
x^2 + 2xy
Well, if you look twice there are three xs - and we know that x in this case is 20. So that implies we’re getting
(20*20) + 20(2*5)
from somewhere. And in the microsecond it takes you to realize that 2 times 5 is ten, the answer comes clear. The reason why this is a special trick that works with 5 is because we have a 10-based number system. It takes 10 of something to get you to shift a column, in other words. And 5 is half of what it takes to cause you to shift. So when you’re adding two of them together, what you’re really doing is just shifting one more value onto the prefix, which is why, rather than just squaring it, you multiply it by itself plus one more. Think of those trailing zeros in 20 and 10 not as values, rather, but just position markers.
(20*20) + 20(2*5) = (20*20) + 20(10)
(2-shift*2-shift) + 2-shift(1-shift)
2(2) + 2(1)
2(2 + 1)
In other words, whatever the prefix times whatever the prefix is plus one. Neat!
There’s no reason it can’t work for other numbers, of course. There’s just more record-keeping to do. If you wanted to do the trick for, say, 3, you’d have to keep in mind that you’re 4 off of shift.
(x + y)(x + y) = x^2 + 2xy + y^2
= 20(20) + 2(20)(5-2) + (5-2)(5-2)
= 20(20 + 2(5-2)) + 9
= 20(20 + 10 - 4) + 9
= 20(20 + 10) - 80 + 9
Which by the previous algorithm means just that you have to subtract out 80 from 600 and add 9 to it. In more general terms, it means you have to account for the distance from five, double that (since there are two factors of five), multiply it by the prefix (since there are that many members of the prefix missing), and then subtract that ammount shifted one column to the right (since this is the deficit that would enable us to shift if only the end number had been 5). For end numbers greater than five, obviously, you add.
So try it with a more complex example like 236.
We’re one up from five - so we’re going to have to add twice our prefix (shifted to the right) on to our result. The prefix is 23. We already know that 23 squared is 529 (or, if we don’t, we can apply the algorithm again). We need one more 23 (remember, it’s “prefix times prefix plus one - aka 24 23s in this case), so we’re at 552. We’ve got twice our prefix (46) to add back on - but shifted to the right, so 5520 + 46 = 5566. And then we add 36 (shifted to the right) to that to get 55696. Voila!
Yeah, so it’s not so magic when you’re off 5. But with practice it still saves time! The shortcut is: multiply however much “off shift” you are (which is double the distance from five) by the prefix, subtract (add if your trailing digit is greater than 5) that from 10 times the result of multiplying the prefix times its successor, add a zero, and then add the trailing digit squared.
November 18, 2009
IBM has apparently developed cat brain software. Don’t rush out to buy it, though. You need 147,456 processors to run it - not something that you can fire up the Python interpreter on your average machine and expect a return value from. I think the point is just that this is really motherfucking impressive. And heck, I’m impressed.
My comments.
First - the obligatory political observation about how it didn’t take the NSF to bring us this apparently useless and profit-less science project. Private companies can and in fact frequently do fund research for the sake of research on huge scales like this one. So the left can stop with that “there’ll be no pure research AT ALL without the government!” straw man any time.
Second - in response to all the snide comments on the web about how IBM is running a cat’s brain because cats aren’t actually all that smart compared with dogs, I think you’re all still missing the point of this pet raising thing. Pets are companions, not calculators. Even if it’s true that dogs are smarter than cats, I’m not sure how that bears on my decision about what kind of an animal to feed and spend time with. Isaac Newton, by all accounts, was a really smart guy and a first-class whiny asshole who had no friends. It turns out you can be smart and not all that much fun to be around. Which is what dogs are. They’re useful as tools for things like sniffing out bombs and criminals and participating in rescue missons, but spending time with something that slavishly devoted to you is just not interesting. Which is a polite way of saying that dogs may be more intelligent than cats as animals go, but people who like dogs aren’t as smart and don’t have as much character as people who like cats, and that’s the real issue, kids. So try another line, will ya? Or take up the courage of your convictions and raise pigs instead, since they’re definitely smarter than dogs. I hang out with cats because they’re fun to hang out with, and that’s really all that’s involved.
Third - cut the crap about how this is scary. It’s not. It’s not even a whole cat brain - just some subset of a cat brain. It’s certainly not a human brain, and even as a cat’s brain it runs 100 times slower than the real deal. You can’t stuff it in a robot aibyou (note the ‘y’ - that’s “pet cat” in Japanese, rather than pet dog) and have it chase string! And as for the people who say that if Moore’s Law holds the same number of processors will be able to handle a human brain by 2019, well, you’re making a lot of assumptions. First, you’re assuming that there’s any evidence at all that this giant simulation of a cat’s brain is really behaving like an actual cat, and I haven’t seen any provided. Second, you’re assuming that Moore’s Law will continue to hold, which, since it doesn’t even hold now, seems unlikely for the future. Third, you’re assuming that there’s anything at all threatening about a human brain living inside a giant computer complex, which there isn’t. Fourth, you’re assuming that machine intelligence must be functionally equivalent to human intelligence to count as intelligence, which is just silly. I forget who said it, but there’s a money quote from someone saying “The question of whether machines can think is about as interesting as whether submarines can swim.” Which is to say, it’s all a matter of semantics. Machines already do think in non-trivial ways, and what it is exactly that you’re (irrationally) afraid of will be here long before we’ve made a convincing machine implementation of a human. You COULD, but you WOULDN’T, build a computer out of hydraulics, just like you COULD, but you WOULDN’T, implement machine intelligence by simply rebuilding a human brain, only this time with silicon! There are much more efficient ways to achieve machine thinking.
Well, the future is here it seems. But then, it always was, wasn’t it?
Things like this demonstrate why it’s ultimately futile for the government to enforce a currency monopoly - and they also demonstrate another quirk of human nature, a maladaption similar, in a way, to our apparently inability to think of organizations and individuals as separate categories.
The story is about a company that’s lighting some fire under the credit card companies by issuing one-off debit cards that act like credit cards. You prepay them, and they only charge the merchant 0.5% at point of sale - compared with about 2% for regular credit cards. American Express has just acquired the company for a huge sum as a way of expanding their business.
Now - this is interesting for two reasons. First the boring one: it’s a nice demonstration of just how unnecessary government intervention in the credit markets actually is. I hear a lot of talk these days about the need to regulate the credit card companies to keep interest rates down. Sounds to me like the market it getting around to doing just that faster than the government, and more effectively.
Second - it’s interesting to me that this doesn’t show up on the government’s radar as an “illegal private currency.” It’s every bit as much of a currency as the much-prosecuted Liberty Dollars, right? I mean, just like with Liberty Dollars, you buy some of these from the merchant at a markup, and take them to participating stores where you can exchange them for goods and/or services. And yet in the case of Liberty Dollars the government shits its wad coughing up all kinds of specious arguments (no pun intended, really) to sic the dogs on them, but when it’s an electronic card that doesn’t call itself a “dollar” or come on printed currency-like paper, everything’s peachy. Which just demonstrates another unfortunate human tendency, actually - the undue focus on trappings rather than substance. Apparently you can issue alternate currency so long as you don’t make it look like that’s what you’re doing. Which doesn’t say much for the so-called “experts” at the Secret Service, actually, but no matter. Private currencies are an unambiguous good, so if turning up the heat slowly rather than quickly lets us boil this frog, let’s do it!
Never send a computer to do a man’s job; never send a man to do a computer’s job. You wouldn’t hire your analyst to add millions of columns of small digits any more than you would ask your computer to talk you through your marriage problems. 20 years after home computers became ubiquitous, most people seem to get this right almost all of the time.
Which is why it’s so puzzling to me that after well over 500 years of dealing with the modern corporation people aren’t similarly able to separate out things that companies are good at from things that individuals are good at.
I think about this a lot, actually, and what got me thinking about it again today was this blog entry of Cody Brocious’ about some truly abysmal customer service he was on the receiving end of recently. Short version: he ordered something online only to find out that the distributor was pretty much just down the street, so he emailed and asked if they could skip the shipping middleman and him just come pick it up in person? Their response went something like “No, douchebag, we deliver; if you want pickup call Papa John’s.” OK, so they didn’t say “douchebag,” but the rest of it is pretty much as it happened.
Shitty, right? I mean, there’s just no excuse. And it’s all the worse for being over email. Sometimes in realtime your emotions get the better of you and you say shit you don’t really mean, but over EMAIL? Surely there’s enough distance there that even the world’s most childish person can take a step back and write something appropriate.
But here’s where it goes wrong. Mr. Brocious wants to conclude from this that the company is simply incompetent or even malicious. He closes with “If you don’t want to do the job, don’t do it; don’t act like the customer is doing you a disservice by giving you money.”
Well, sure. I mean, it’s the kind of thing that you hesitate to call “good advice” because it’s so obvious that it’s basically impossible to imagine a company that doesn’t already know it. Sort of on par with “try the door before you cut a hole in the wall” or “don’t drink gasoline” or “don’t drive through South Carolina with an out-of-state license plate.” Common sense. Can you imagine a company anywhere that makes a conscious policy out of insulting its customers? Well, OK, clever netizens, I’m sure there are some somewhere that do it as a schitck, but in the general case, it just doesn’t happen.
Now, that’s not to say that the company is off the hook. It’s just that there are different standards of judging organizations than there are of judging individuals, and before we go concluding that the organization in question is bad, we have to first make sure that we’re accusing it of failing at something that organizations are expected to be good at. One thing that organizations are really bad at is human relations consistency. They can’t empathize, they can’t be your friend, and they can’t make special exceptions for you. All of these are things that only individual people can do. So if a company makes a special exception for you, or treats you nicely, or demonstrates real affection for you, then only because some individual who represents that company is doing these things. The company itself can only put you in touch with that individual and run a system such that that individual is empowered to cut you whatever slack you need cut.
To the extent that a customer service problem is the fault of the organization and not the individual sending the email, then it’s because the organization is set up in such a way that there’s a big disconnect between the people sending the email and the people who make the policies. Verizon and Comcast stand out in my mind as companies that can be reasonably said to be bad - as companies - at customer service, and the reason is because they don’t give their customer service representatives the training, the authority or the incentive to do anything to help you. The nicest person in the world would be useless working for Comcast just because the way Comcast is structured gives them no outlet for their niceness. But as to the example at hand, well, I’d need more information to know if this was a company failing or just some random dick being randomly dickish on company time. No organization in the world has the time or resources to watch every one of its members all hours of the day - just ask the Feds how the War on Drugs is going, for example. To be certain that this was a company failing, we’d need to file a customer service complaint and see how they handle it. THAT would tell us something about the corporate structure and corporate commitment to customer satisfaction.
And there are tons of related things. For example, people just can’t help themselves blowing up at customer service reps that they know good and well aren’t personally responsible for their companies’ shitty policies. It may be how we are, but it’s also deeply unfair. When I’m dealing with a low-level customer service rep, I try to keep that in mind. It doesn’t mean you have to cut them slack, necessarily - they don’t care about you any more than you care about them, after all - but it does mean that if you want to rant you really need to make sure you’re ranting at someone who gets paid to listen and/or can do something about it. Ranting at the minimum wage phone operator is just mean. For another example - if I get some bad service and complain about it and the company does something worthwhile to fix it, I make a point of continuing to shop with that company. Most people’s instinct in that situation is to jump ship and take their business elsewhere, and they see the fix as a kind of entitlement. And so it is - but it’s something more than that too: it’s evidence that the company in quesiton can be relied upon as an organization to provide good service. Mistakes happen, systems break down - even the best systems. But if they then fix the problem and it doesn’t happen again? I consider that a win. Why take my business to some other company that will inevitably screw up someday but I don’t know how they’ll handle it when I’m already doing business with one that’s demonstrated real commitment to fixing problems? This came up recently with TeaGschwender, actually. They completely screwed up my order over the summer, sent me someone else’s instead, and then sent me a second helping of that person’s order and tried to charge me twice. So something really broke down - and I sent them a fairly angry email. But the response from them was very polite, they immediately admitted the problem and shipped me my twice my original order to make up for it, and let me keep the other person’s order, all free of charge. I admit, my first human instinct was to find another tea company. But once I calmed down I realized this was stupid. Every organization will screw up eventually, and this one had just demonstrated that the mechanisms were in place to fix their screwups. Why stop shopping at a store like that?
I guess it’s the fact that there is a human voice behind the counter that short circuits our brains about these things. When it’s a computer, it’s easier to remember that it’s a thing, not a person, even if it sometimes has quirks that make it seem almost human. But somehow we just never learn that lesson about organizations. I wish we would. I wish we would because I think a lot of annoying and harmful bullshit in the world comes of expecting organizations to be your friends. And I think this is true all the way up and down the scale. It goes all the way from increasing wait times at grocery stores, where some confused and lonely people abuse the cashiers for attention, up to expecting the govenrment to care about us and project the right “national image,” whatever that is. People are people and organizations are organizations, and if it’s hard to keep the two separate, then maybe it’s something we should remind ourselves of more often.
November 17, 2009
The ongoing saga of trying out .NET on Mac OS X via Mono. Remember that libiconv thing, where installing Mono briefly and mysteriously broke Mutt? Well, it turns out it breaks MonoDevelop too! More proof that the Mono Development Team isn’t exactly Mac-friendly. No - that’s NOT an accusation of sneakiness! The Mono Team does great work, and I’m grateful that Mono exists at all. That it runs as well as it does is a testament to their skill and dedication. No, I’m just taking this as more evidence that Mono doesn’t get tested as thoroughly on the Mac platform as it does on Linux and Windows - owing, I speculate, to the preferences of the development team. Fair enough.
In any case, the issue is that you (meaning some subset of us Mac users MAY) have to update libiconv to get Mono to work in the first place. Interestingly, though, the official beta release of MonoDevelop seems to depend on the same outdated version of libiconv that crashed Mono for me in the first place (at least, that’s what the error message I got implied…). Then, in a final and somewhat bizarre twist, it turns out that just grabbing MonoDevelop from a link on Miguel de Icaza’s blog directly (download link here: looks like it’s an early one that M J Hutchinson put up and never took back down) resolves the whole issue. Which is strange, because it makes it look like MonoDevelop for the Mac first used the new improved libiconv, then switched back to the old one inexplicably. Maybe in response to bug reports? But then, why does Mono itself continue to rely on the new version?
Clearly I’m missing something here, but I’m not complaining. I’m happy to have both Mono and MonoDevelop working and am looking forward to trying out the ASP.NET MVC here on the Mac. Thanks again to the Mono team for bringing .NET to the Mac platform - it’s much appreciated!
Just for kicks, here’s a bit of gratuitous internet boneheadedness courtesy of “A Tiny Revolution.” The title of the blog entry is “Once Again Adam Smith Betrays the Principles of Adam Smith.” And it links this New York Times column from some financial analysts who claim that American workers are overpaid. Then, apropos of absolutely nothing, it quotes Adam Smith way back in 1776 saying that businessmen are often hypocritical in complaining about worker wages being too high while saying nothing about being overcompensated themselves. And then comes the money quote:
Once [sic] of the strangest things about the American overclass is the way they cite Adam Smith and The Wealth of Nations all the time.
Now, click the link to the column they cite and do an Apple-F for “Smith” and watch it turn up nothing. Why? Because there isn’t a single mention of Adam Smith in this column that they cite in the context of complaining about how the American “overclass” (whoever they are) cites Adam Smith and the Wealth of Nations “all the time.” Yeah, I couldn’t believe it either, so I did actually take the time to read the whole column to confirm. And … nope … not one mention of Adam Smith. And of course don’t take MY word for it - the column is right there on the internet completely devoid of any Adam Smith reference for any- and everyone to (not) read.
So if the “American overclass” cites Adam Smith and the Wealth of Nations “all the time,” then why not just pick one of the columns where they actually, you know, cite Adam Smith to include in your blog entry about selective citation of Adam Smith? That’s the question, innit Ladies and Gents? Picking a column where they (you know, anyone writing a financial column is ipso facto a memeber of the “overclass” - THAT “they”) don’t mention Adam Smith AT ALL and using it as evidence that the “overclass” often quotes Adam Smith selectively is a bit like holding up Quantum Leap as evidence that all science fiction shows erroneously have sound effects in space. I mean, OK, fine, Quantum Leap doesn’t involve any ACTUAL space travel per se, much less space laser cannons making space laser cannon sounds in a vacuum, but it’s a science fiction show isn’t it, and you know what THEY’RE like. They’re all written in the same room at Paramount by the same rugby-shirted basement-dwellers, for one thing.
Nope, sorry mate. FAIL. Maybe there are people out there in the world who quote Adam Smith selectively. You can’t even quote THEM selectively. Move along.
Everything that’s wrong with internet commentary is right there. Pass it on.
November 13, 2009
As mentioned, I’ve been thinking seriously about porting Boltun (I really should add some more content to that link soon, eh?) to .NET. As a consequence, I’ve been delving into C# recently - reading both Andrew Troelsen’s excellent book Pro C# with .NET 3.0 and the Annotated Standard. So far, I’m really liking the language. Here are some initial thoughts.
Well, actually only one initial thought, and that’s that C# is to C++ what Objective-C was to C, and not what Java was to C++ or C++ was to C.
Alright, my analogy is a little bit contrived since C# really is Java-like in being explicitly targeted to a platform; it doesn’t make the same claim to universality that C++ did. But all things considered, it really does feel like an incremental improvement to C++ in a way that Java just wasn’t.
We all know the story: back in the dark days of malloc Bjarne Stroustroup endeavored to bring an object-oriented layer to what was then the “high-level” language of C. C was and is the logical favorite of systems programmers because it’s just enough abstraction over Assembler that you don’t have to use too much machine-level boilerplate code, but it’s not so far abstracted that you can’t interact with the machine directly. It mimics machine code really well, and as such is, as Kent Dybvig put it in class once, “kind of a beautiful thing.” Dybvig said that in the context of contrasting it with C++, which he and most others think of as an inconsistent, haphazard mess. And so it is. What started out (literally) as C with Classes ended up as a different language entirely, though it does support a mostly-comprehensive subset of C. But in a real sense, C++ was a kind of lie: it wasn’t an incremental improvement to C as the name implied; it was in fact its own thing.
So it’s not too radical to say Objective-C has the better claim to being “C++.” For one thing, it really is C with and object-oriented capabilities bolted on. For another thing, the object-oriented capabilities look and act like Smalltalk, the prototypical OOP language at the time, so even the object layer wasn’t that much of a leap. But Stroustroup called his language “C++” first, and so there you go.
Something similar happened with Java with regard to C++ in the mid-90s. Java was a language born largely out of frustration with C++. It wasn’t just a convenience tool for C++ programmers tired of writing their own string classes and garbage collectors, it was a calculated attempt to replace C++, so that people wouldn’t have to make the case to their employers for migrating away from C-world. The argument was that memory capacity and processor speed improve so quickly that there is no longer a need to optimize at these levels; technology improvements deliver the optimizations faster and less expensively than programmers can. For that reason, you should optimize your programmer resources by letting them work in an environment that abstracts away from the machine entirely, so that code is easier to update and maintain. If you find you need a performance boost, just upgrade your hardware. And they meant that seriously: the mantra was “write once, run anywhere:” and Java really was the first “language” that solved the cross-platform problem. By compiling to an intermediate language of instructions to a virtual machine, it ran on any computer running the virtual machine. It was neither interpreted nor compiled - actually it was a little bit of both.
I put “language” in shock quotes because I happen to agree with Paul Graham that Java isn’t a language that runs on a platform, Java is a platform. Paul Graham is a well-known Java-hater, so of course in context that was a snarky comment, but it needn’t be (a non-prejudiced explanation of the same concept here), and in any case it’s true. Java doesn’t compile down to anything that runs on your machine, it compiles down to something that runs on something that runs on your machine. Whether or not this was a good idea (probably it’s safe to say, with hindsight, that it was, though Paul Graham and others will have some not-unintelligent objections), Java was also a kind of lie. It was advertised largely as a cleaning up of C++, but in fact it was something quite different - just the way that C++ had been advertised as an incremental improvement to C when it was, in fact, a completely different language that just happened to look enough like C++ to lure that crowd into a false sense of security.
.NET, of course, is the same idea, but not wedded to any particular language. In that sense, it’s a kind of Java++: it specifies a virtual machine code that languages should target, and languages that target that bytecode can run on it. It’s “write once, run anywhere” for a fleet of languages rather than one. And the flagship of this fleet is C#.
I guess it would be fair to say that C# is Java whose time has actually come. When Java came out, it was deceptive to tell the C++ programmers that it was meant to make their lives simpler becuase it was in fact a whole new programming paradigm. It freed them from memory management, yes, and it came with a standard library that was actually useful, yes, but it also pulled out from under them all the things that they liked about C++: its expressiveness, its ability to manage machine-level things directly. Any surface syntactic resemblance to C++ was an illusion.
C#, by contrast, can make an actual claim to being an incremental improvement to C++. It won’t have replaced it exactly. C++ still gives a closer coupling to the machine in that C# doesn’t allow stack-allocated objects. All objects in C# are reference types, and so are allocated, at run-time, on the heap. But this is really just C# learning the obvious lesson from C++. The truth is that most C++ programmers who are worried about efficiency steer clear of objects anyway, prefering to use structs. structs are retained in C#, and they’re value types, allocated on the stack, so they’re just as efficient (in theory) as they were in C++. (Reality, of course, is that you’re still running in the .NET environment, so even the stack isn’t exactly machine code. There’s an inevitable performance hit, though unlikely to be noticeable in 99.9% of cases.) C# also gives the same reference semantics that C++ does - you can decorate argument parameters to a function with ref (& in C++), which gives the callee full access to the variable in the calling environment. C# retains C++’s obsession with annotating everything. They even add their own pointless annotations - for example there’s an out decorator for function parameters that are reference types specifically intended to collect return values. Why not just use ref, you ask? Why not indeed. out simply enforces that the variables be uninitialized before function call. No careful programmer actually needs this, but it’s very much in the spirit of C++’s “let the compiler do your debugging for you” philosophy.
It’s probably not really off the mark to say that C++ was two languages in one. There was the mouldy old systems language for the REAL men, and then there was this completely different object-oriented language for the boys, and the nice thing about C++ was that the systems programmers could do object-oriented programming on those rare occasions they felt the need, and the object-oriented people could write efficient code on those rare occasions they needed to. C# is also two languages in one. On the one hand, it retains the C++ dual systems/OOP language, but with much more emphasis on the abstracted half. On the other hand, it’s evolving toward allowing you to do static and dynamic programming all at the same time. The upcomming version will even include a dynamic keyword that allows you to mix late-bound code in with compile-time-bound code. A very basic example of this here: a method that returns a string if its input is an odd numer, an int if even - and it can be called from within a static context. It’s sort of the obvious step, and allows closer interoperability with the increasingly-popular dynamic languages on .NET. Point being it makes C# a kind of hybrid beast along the current programing paradigm faultline (dynamic vs. static) in the way that C++ was a hybrid beast along the faultline of its day.
C# is the new C++. It has been for years, of course, and I’m just majorly late to the table, but I’m really enjoying learning it and I think I’ll end up really liking it. Of course, the day after I start seriously diving into C#, I read that Google has released a language called Go that’s described on TechCrunch as “Python Meets C++.” Just the kind of largely-similar thing I needed to distract me from the task at hand.
November 11, 2009
Well, wouldn’t you know it. My two big log pages for “how-to-install-Mac-unfriendly-shit-on-Leopard” turn out to be incompatible! I KNEW that installing Mono would break SOMETHING, and that something turns out to be Mutt.
The problem is that the library that Mutt calls to do its unicode conversions is libiconv.2.dylib, which was of course one of those things that had to be upgraded to get Mono to work. Identifying libiconv as the problem wasn’t the hard part; what had me gussing was that trying to reinstall Mutt via MacPorts mysteriously didn’t work.
It’s not a black mark against MacPorts. It turns out that I have been using a devel version of Mutt, which means I should be prepared for things to break while they iron out the kinks. So recompiling it from source with the new version solves everything since the new version doesn’t choke on libiconv.
OK, that’s not quite true. The Mutt team seems to have removed a bunch of features, so I had to comment out a lot in my config file to get it to load without a spew of pointless error messages. And it does this weird thing now where it doesn’t play all the headers back to me as I’m composing an email. Somehow the signals haven’t quite been reconnected in some parts. I don’t know if that’s my configuration or some stuff that’s still “under construction.” I’m guessing it’s my configuration somehow, but I’m sort of unwilling to start from scratch on that with an official config file. Maybe this weekend.
Anyway, it’s good to have the world’s best email client back up and running. I’m pleased to have Mono, but life is seriously hard for me without Mutt!