|Ned Batchelder : Blog | Code | Text | Site|
» Home : Blog
A few days ago I moaned about the difficulty of getting a new machine set up. Since then, I've been working through the process, trying to document it fully. At this point I have a usable laptop, in fact, I'm producing this blog post with it. Here's what I did (so far):
After all that, I'm able to do real work on it. I haven't migrated my email yet, but I think everything else is on there.
BTW: Naturally, I was going to make all of those software and package names above links to the home pages, but screw it, that's a lot of links to paste in. You know where Google is, use it!
I took my autistic son Nat to the dentist today, and then we were going to the bank. The dentist went fine, but he was kind of agitated at the bank. This happens quite a bit these days, and I can usually calm him down by reminding him of the schedule, and where we're going next, and when we'll get home. We left the bank without incident, and were driving home. I was flipping around the radio stations, looking for something to listen to, a habit that gets on Nat's nerves.
When we got to The Pretenders' Brass In Pocket, he really didn't want me to change the station again, which he indicated by suddenly singing loudly along with the song, something he doesn't usually do. So there's Nat belting out,
Coming from Nat's mouth, the words took on a completely different but fitting meaning.
There are a lot of add-ons for Windows that offer window management, or shell extensions, or task launching. Many of these look great in the screenshots, but then I try them, and am disappointed. They end up being flaky or slow or just awkward. TaskSwitchXP is not one of these. It is a replacement for the Alt-Tab behavior in Windows for switching among running programs. It provides thumbnails of the applications, and a nicer UI for the icons, and lets me just click on the icon I want when I see it. It does just what I want, in a competent unobtrusive way.
I've been developing on Windows for a long time. I've figured out the thing about Windows I dislike the most, and it is not one of the things that most people bitch about (monopoly, security holes, UI, whatever). The thing that gets me as a developer is the Windows mindset of there being only one of anything. This is exemplified by the registry. THE registry. Sure, you can build software so that it has multiple instances, and knows how to find them all in the registry, and pick the proper one, but generally, no one does that.
The latest problem along these lines is installing Python. There are two sources for Windows installers for Python: python.org and ActiveState ActivePython. Both provide MSI files, which make it super-easy to install Python on your Windows machine. The problem is that MSI installations are based on the notion that a product is only installed once per machine. That's a good model for most people, but as a developer, I'd like to manage a number of Python installations simultaneously. It lets me test software against multiple versions, and it lets me keep complex product installations separate.
If you've installed Python once from an MSI, the next install offers only the options to change, repair, or remove the installation. The MSI instructions mention a TARGETDIR option, but setting it doesn't help: the "one installation per product" mindset pervades the installer.
ActivePython has .zip files available too, on their raw downloads page. These provide a .bat file for installation, and let you specify the install directory, which does create side-by-side installations. But the script doesn't write the registry settings that let 3rd party packages find the Python installation.
I used to manage a number of installations. Have the installers changed? Am I losing my mojo? What's the best way to keep a number of Pythons caged on Windows simultaneously?
Update: I found this page about how Python uses the registry (someone might want to look into what's going on with that background image in Firefox!), and this script to register a Python installation in the registry. Perhaps this is the way to go? Manually re-register Python installations as needed to get modules to install in the proper places?
I don't use emacs any more, and I don't think I will, but I'd like to see Artist in action. It's a line drawing mode. Drag out lines, rectangles, whatever, and it draws them with ASCII characters. What won't they think of next?
As a result of changing jobs, I am also changing laptops. I've used an IBM Thinkpad for a number of years. I like it physically, but something about it has always been flaky. I've just got a new Toshiba Tecra M3. I chose it because it has a fast large disk, but now that I have it in my hands it seems so foreign to me. The keyboard layout is strange. The backquote key is next to the space bar, the enter key is not the right-most in the layout, and the insert/delete/home/end/up/down pad is split up and the keys thrown all over the place. I hope I can get used to the new layout.
And of course, I have to configure the whole thing, which means getting rid of all the junk that comes pre-installed (Napster?), re-establishing settings I've long forgotten I had changed on my current laptop, re-installing all sorts of software, files, bookmarks, and so on. It's all very overwhelming.
Every year about this time, we get around to sending out holiday cards, and every year, I wonder the same thing: How come I don't have a good solution to keeping all these addresses on file so I can just print up a bunch of labels? Every year I scrounge around for people's addresses, and wonder who I sent cards to last year, and poke around at various possibilities for personal databases of mailing addresses. Surely this is a solved problem? It seems like I've got to have something right at my fingertips that's perfect for this. I just don't know what it is...
sIFR is a technique for displaying headlines online, whereby plain heading tags are included in the HTML, but are replaced dynamically with nicer-looking Flash headlines. It provides the benefit of simple and accessible HTML with the beautiful cosmetics of Flash.
What caught my eye, though, were the clever type jokes in the sIFR sample page. I especially liked "Helvetica, Arial in Grotesque Accident". Akzidenz-Grotesk is a typeface similar to both Helvetica and Arial. The name is from the German Akzidenzschrift, meaning display face or jobbing type; and Grotesk, the German spelling of grotesque, which was a current term for sans-serif in the 1890's when Akzidenz-Grotesk was designed.
There are people in this world who think differently than most. Some have trains of thought so foreign, that even when you take into it into account ahead of time, even then, when they open their mouths you are baffled anew as to how a rational person could possibly form opinions like theirs.
One such person is Karl Pilkington, the third member of the Ricky Gervais podcast. The first two are Ricky Gervais and Stephen Merchant, the writers and directors of the wildly successful British comedy series The Office.
The podcasts consist of Ricky and Stephen engaging Karl on various topics, Karl explaining how he sees the world, and then Ricky and Stephen gamely trying to cope with Karl's bizarre thoughts. Well, actually, they often savage him. If it sounds confrontational, it can be ("You are a f*@#ing lunatic!!!"), but it is also hilarious. And every episode includes Monkey News, actual headlines involving monkeys. I have never laughed so hard on my way to work.
Kodak Assvertising, in which a major multinational corporation puts their logo on women's asses, and pays them to drop things and pick them up all day at a photo trade show. And we wonder why engineers have poor opinions of marketing...
At lunch today, the topic of bogus reviews at Amazon came up, and I mentioned a classic involving The Story About Ping, the children's book about a duck on the Yangtze river. A review appeared that confused it with a manual about the ping networking utility.
The review, of course, was written intentionally as a gag. It seems to have started as a review on Slashdot, and then migrated to Amazon. It is no longer among the 46 reviews at Amazon, but there are plenty of others to choose from, including a few that mention the operating system angle. It's a real mixed bag, including raves, rants against corporal punishment, historical readings for and against Fascism, and political allegories for our current administration. It's a kid's book, for goodness sake!
BTW: If you want to know more about the networking utility, there's also The Story of the PING Program, which really is about the utility. It also includes a discussion of the Amazon review.
A debate about asserts flared up in the fall, and I only just now caught up with it. Len Holgate started it with Asserts are Evil. His complaints center mostly around how asserts are traditionally implemented (only in debug builds, and they exit the program if failed).
B (?) mostly agreed: Assertions are still evil. It's in the comments on that thread that the defining phrase was coined: Len Holgate described asserts as "exploding comments".
Noel Llopis came to assert's defense with Asserting Oneself.
I've written about asserts before, and I'm all for them. Programmers need every tool they can get to help nail down the often slippery semantics of the complex beasts they are building. Even if they are only exploding comments, isn't that better than just plain-old comments?
The biggest misconception about asserts (and I think the heart of Len's complaints about them) is the confusion of the caller's semantics with the implementation details. The main thing I learned while writing my Asserts essay was the detailed semantic of an ASSERT statement:
That last word is the most important: if the expression is false, what happens is undefined. Note that nothing is said about debug vs. release builds. Nothing is said about exiting the process. So when Len complains,
how does he know the failed assert will end the program? Who said? He's assuming a detail about the implementation of the assert. It sounds like he's living with too-simple an implementation.
In the assert framework I built at work, a failed assert could do one of a number of things:
The decision about what to do is mostly controlled by defaults based on product (clients display a dialog, servers throw an exception), but could be affected by registry settings, or by the user's choice if a dialog comes up.
The anti-assert people assert (!) that unit testing is a much better way to guarantee the correctness of an implementation. I'm all for unit tests, but have found it very difficult to build them for complex systems being built on tight deadlines. But unit tests depend on asserts, so I'm not even sure it's an either/or situation. In many unit test frameworks, it is specifically failed asserts that signal the test failure to the test runner, which continues on to the next test.
I say asserts are good. I've found them very useful for building self-diagnosing code that can raise the alarm when it hasn't adapted to changing requirements fast enough.
Yesterday a federal judge ruled that intelligent design cannot be taught in public schools. Many are cheering this decision as a victory for the forces of science over religion. I'm not so sure.
I think the three or four paragraphs of disclaimer the ID folks wanted read was not such a big deal, and would have been a great jumping off point for a discussion about what science is and is not. An entire class (or more) could be given over to the topic. It wouldn't be teaching intelligent design, it would be teaching the philosophy of science with the current ID debate as a backdrop.
Part of the difficulty in this debate is the two sides are arguing about different things. The intelligent design people are trying to talk about how the world came to be. The scientists are mostly arguing about what science is. Putting the discussion into the hands of science teachers would let them frame the debate.
The most interesting piece I've read on intelligent design was this piece in the New Yorker: Devolution: Why intelligent design isn’t.. It wasn't about right vs. left, or blue states and red states. It was about science. It lays out the arguments of the intelligent design proponents, and then discusses the scientific merits of their case. Reading it, I learned about biology and the philosophy of science.
Embracing the ID debate in this way is the best defense against it. All they want is a mention in science class. Give them that, then give them both barrels with a real examination of their stance. Get the debate out into the open. Refusing your opponent a chance to speak is rarely a way to defeat them.
Tim Bray, who is one of the editors of the XML standard, and creator of the awesome Annotated XML Specification, writes about the absurd wart of <!DOCTYPE>: Drop the <!DOCTYPE>. I've long thought that of all the things that are ugly about XML, <!DOCTYPE> is the worst: it could easily have been separated out into another standard, giving competing validation techniques an equal chance, and saving us from carrying it around forever in the spec.
It turns out Tim and Norman Walsh (another XML luminary) have each written speculative follow-on XML specs: Norman's XML 2.0, and Tim's XML-SW, both of which omit <!DOCTYPE>. Neither of these is being worked on as an actual standard, but it's interesting to see where people think XML can go. (I know: "Hey buddy! I'll tell you where XML can go!", ba-dum bum!)
Tim's a smart guy, though. He observes (correctly):
Standards evolve to a point where they are good enough, and they get a large enough adoption, then they stop, because it isn't worth the marginal improvement to leave all the earlier adopters behind. It happened with HTML, and it's happened with XML.
One of the trickier aspects of building applications on relational databases is upgrading the database schema. As features get added to the application, columns and tables get added to the database. At some point, you want to install the new code onto an existing installation. How do you change the database schema to add the columns and tables without losing the existing data?
In my last two startups, I was put in charge of figuring this out. The two designs I came up with had some differences, because there were different requirements and constraints, but they had these aspects in common:
We'll have this same problem in my next job, though this time it will be on top of the Django framework. The Django dudes understand the issues (the first three comments on the Model Reference documentation page are about automatically upgrading databases), but may not tackle it for 1.0.
What I found doing this in the past in real applications was that database upgrades are too complicated to be done automatically. The simple cases (adding a nullable column, dropping a column) can be made very simple. For example, the developer writes an upgrade clause that includes a call to a DropColumn function. But the complicated cases are always going to be beyond the reach of automatic generation. Real upgrades include things like taking an existing text column and splitting it into rows in a new foreign-keyed table, or adding a non-nullable column with existing values being computed from other tables. Upgrades also include stuff like realizing your application had been writing invalid data for a while, and running update statements to fix the bad rows.
The real world is messy. There's just no way to leave the developer out of the solution.
The online map applications continue to leapfrog each other. Microsoft now has Windows Live Local. In addition to the map and satellite views that Google Maps offers, Live has what they call a "bird's eye" view. It's aerial imagery, but taken from helicopter height rather than satellite height, and at an angle rather than straight down. The result is that you get a very good view of what a neighborhood looks like. And you can choose to view from any of the four compass directions, ensuring that you can get the view angle that will actually help you understand what you are looking at.
I used it recently to find the unfamiliar address of a birthday party, and after poking around the bird's eye views, I felt like I was an old hand in the neighborhood.
The first time I looked at my house, I saw my car in the driveway, and I knew the picture was taken on a Thursday because the trash cans were out on the sidewalk! The next day, I showed Max, and it seemed to be the same picture from the same angle, but the car and trash cans were not there. Somehow, they've got multiple photos for the same location, who know how they choose among them?
As cool as the bird's eye photos are, there are a few problems: First, they are only available for a few densely populated areas. Even then, the coverage is spotty. The unfamiliar place I have to go today is one tile off the bird's eye coverage. So close! And the photos don't tile and scroll the way maps and satellite images do. Maybe that's coming, or maybe the capture process can't stitch them together accurately enough to make it a satisfying experience?
This morning my seven-year-old asked if Wikipedia had entries for made-up planets (he has his own lovingly imagined world populated with many characters). I guessed that they might have ones for Star Wars planets like Naboo, and indeed they do. In fact, they have lots of Star Wars planets. As much Star Wars content as there is on Wikipedia, the fan demand has overflowed even its generous borders, into the wonderfully-named Wookieepedia. I love the web.
One of the interesting things about running a geek blog like this is seeing non-geek's reactions to it. My college friend Ray is not a geek, but he's cool in his own ways. I'm extremely jealous of his piano abilities, for example, and he works at the National Cathedral.
Ray recently sent me an email saying:
Since I am leaving Kubi Software, they are looking to hire another developer. If you've ever read this blog and thought, "I could do what he does," now is your chance to prove it! If you are at all interested, drop me a line.
Jonathan Payne has a couple of handy Visual Studio plugins on his Visual Studio Stuff page:
When I was at Digital, I did a little bit of maintenance work in a language called Bliss. Like C, Bliss was a low-level high level language. It was designed for systems programming (for example, implementing parts of VAX/VMS). It had a strange macro facility which I don't remember anything about, and was typeless: you dealt with memory layout similarly to how you would in assembler. The defining characteristic, though, was its use of variable names.
In most languages, what a variable name means depends on where it is used, but in a subtle way that programmers typically don't even realize. For example, in this C statement:
a = b;
The "a" means the address of the variable a, and the "b" means the value of the variable b. The statement means: take the value of b, and store it in a.
Bliss didn't make this distinction. For uniformity, variable names meant the same thing everywhere. And since the left-hand side of the assignment operator needed the address of a variable, that's what variable names meant everywhere. To get the value at an address, you used the dot operator, which is the equivalent of C's * operator. So in Bliss, the above statement would be written:
a = .b;
The most common error in Bliss was forgetting a dot. "a = b" meant store the address of b in a. Dealing with pointer variables meant double dots:
val = ..pVal;
What a headache. If you are really curious, the Bliss Reference Manual is online.
After four-plus years at Kubi Software, I will soon be leaving for a new job. Antonio Rodriguez got in touch with me, and convinced me that his startup would be really interesting. I'll be joining his small team building consumer-oriented online applications, which is very different from my current work building installable enterprise software. As I told him,
Seriously though, I'm very excited to be moving into a new technical area, working in Python, and using Django. We're going to build cool things. I can't wait to get started.
The latest post at The Daily WTF is about a database design with one table for every order! Mixed in with the usual snarky comments about incompetence and unjust promotion was a link to a scholarly paper, Unskilled and Unaware of It: How Difficulties in Recognizing One's Own Incompetence Lead to Inflated Self-Assessment.
I haven't read the whole thing, but it's a fascinating vindication of what many people have suspected for a long time: that dumb people don't know they are dumb. The abstract sums it up:
Here's a video of a guy doing sleight-of-hand magic. The first trick seems like a standard coin manipulation, but the second trick? He pulls a large salt shaker through a glass tabletop! What the?
For the second time in two weeks, I happened upon Marshall Cline's C++ FAQ Lite. I'm not sure why it's called "Lite", because it is a huge list of hard questions, expertly answered. I thought I had shone a flashlight into every dark corner C++ had to offer, but I learned a few things poking around.
For example, in the answer to What does throw; mean? Where would I use it?, I learned that you can use throw even when not lexically nested in a catch:
(We can argue over whether this is a good idea: my point is I didn't even know it was possible in the language.) And in What should be done with macros that contain if? (and the three questions that follow it), Cline explores all of the fiddly details that you need to consider when writing macros of any interesting complexity.
The whole FAQ is amazing like this: chock-full of top-notch technical detail.
Lately I've been getting periodic storms of spam being returned to me as undeliverable. I don't know if the spammers intend me to open these messages, or if they're just using my domain as a From address on spam intended for someone else. Either way, it's a pain when 40 non-delivery reports a day flow into my inbox. Unlike regular spam, these messages come and go. There'll be a week where they arrive all the time, then three weeks with none, then they'll be back.
I'd like to not have to look at each one to see if it is a genuine delivery failure, but I'd also like to know if I really did have an email bounce. I figured I'd use Outlooks rules to deal with this. Surprisingly, I couldn't find a way in the rule to target non-delivery reports specifically, but the subject lines are fairly repetitive:
Apply this rule after a message arrives
This works great, especially the last part. Since the spam bounces use bogus addresses at my domain as the From address, they go into the Spam Bounces folder. If I really do screw up an email address, its non-delivery report will stay in my Inbox since my name is in the To field. For an extra feeling of safety, I added the To column into the view of the Spam Bounces folder, so I can see at a glance the bogus addresses that got me the messages in the first place.
Last week's New Yorker magazine had a good story on Matthew Carter, a renowned type designer. They got all the details right, but one factoid they mentioned stood out like a sore thumb. They said, "Dickens preferred vowels, Thackeray used more consonants". How could that be? They were both writing in English in the same time period. How much personal preference for one letter over another could you express?
So I did an experiment. I downloaded plain text versions of David Copperfield and Vanity Fair from Project Gutenberg. A quick histogram of the letters in each reveals this distribution of frequency of use (for letters more than 1%):
The most significant difference I can see is the i: 7.24% for Dickens and 6.41% for Thackeray. And Thackeray's s, h, and r are more common than Dickens'. But Thackeray used more e's and fewer t's. It's all a wash as far as I can see. Maybe there's a slight truth to it, but enough to make a difference to a type designer? I don't see it.
BTW: every time I have to make a data table on this site, I struggle with it. Some day I'll learn the CSS to do it right.
I've updated coverage.py with a number of (mostly user-contributed) changes:
What is it about December that spurs work on coverage.py? Looking at the changes made over the years, they have all taken place between December 4th and January 7th across three separate years! Perhaps the coming cold of winter causes us to turn to the warmth and safety of a tool that increases our confidence in our tests...
Tim Tom is a clever animated short. It depicts the efforts of Tim and Tom to get together, regardless of their creator's attempts to keep them apart. It plays wittily with all of the conventions and technologies of animation along the way.
I added a link to Jester, a mutation testing tool. It makes changes to your source code, then runs your test suite on the result. If all the tests pass, you missed a test case. Jester works on Java code, but a sidecar tool called Pester provides the same service for Python. It's a fascinating idea, but I've never had the fortitude to try it out (it needs Java and Python, and modified versions of unit test frameworks in both languages).
BTW, my adding that link to that wiki page proves that I don't always have to control the data.
Here are two UI blogs I recently discovered:
About once a year, someone at work decides that we need to tweak the icons on the Windows client. This usually involves getting an outside graphic designer to send us images which are unusable because they don't know what we need for a .ico file. Then a developer munges the images to get the proper transparency, resolutions, and so on, and builds an ico file (@icon sushi is my favorite tool for this).
Then comes the fun of trying yet again to second-guess how Windows is going to choose among the multiple images in the icon. Microsoft technotes notwithstanding, it is not obvious what is going on. In particular, the icon chosen for the notification tray (commonly referred to as the system tray) always looks smudged.
To figure this out, I built a diagnostic icon (rgb.ico). It has three images, 16×16, 32×32, and 48×48. But the three images are designed to look different: they are solid red, solid green, and solid blue respectively. If you look at this file in Windows Explorer, you'll see a red square in the list view, a green square in the icon view, and a blue square in the tiles view:
In the client C# code, I tried setting rgb.ico as the notification icon. Ideally, the red square would display, since it is the 16×16 image. Nope, the green square appears, a perfect 16×16 green square, clearly produced by taking the 32×32 image and scaling it down. No wonder my icons look gross.
I don't know if this is something about the system tray, or about the .NET NotifyIcon class, or what. But it bugs me. To get the pixels I want I'll have to create a special 16-only icon for the notification area?
Russ Freeman has a few handy tools available: Winspector is a window inspector, like Spy++, but slicker. I don't need to inspect Windows windows much these days, but I can see how well implemented this tool is. And Zoom+ is a windows magnifier that just gets the details right.