[ Content | Sidebar ]

etrian odyssey

August 24th, 2007

I’ve talked about Etrian Odyssey before. It’s a dungeon crawler, which isn’t my favorite genre, but it also has the gimmick that, as you play, you have to draw the map of the dungeon on the bottom screen of your DS with your stylus. And I love (and miss) drawing maps while playing games, so I figured I had to pick it up and give it a try.

And the mapping was a lot of fun! No big surprise there, and I’m sure there are lots of people who would give it a try and wonder how anybody could possibly consider doing that sort of basic mapping to be entertaining; those people are not me.

What was more of a surprise was that I enjoyed the dungeon crawling as well. The difficulty progression was well done, the levels were acceptably varied, there were some at least somewhat interesting choices to be made in the character classes that you use and how you level them up. Each time you level up you get to either unlock a new skill – a spell or a new attack or something – or improve an existing skill. (Which may, in turn, make more new skills available for unlocking.) So you have a good amount of choice in how you develop your characters, instead of being forced along a single path by the choice of character classes.

Often, when playing games like this, I actually get frustrated at the number of choices, because I want to explore them all; here, though, I was okay with only focusing on four of the classes, and with exploring one way of developing each of those. (Except for Alchemists: I had two of them, which I initially leveled up along different lines.) And, actually, I enjoyed the dungeon wandering enough to keep a second party around, representing the classes that weren’t in my primary party.

As to difficulty: the monsters normally get gradually harder but not in any threatening way. There’s a big boss at the end of every fifth level that’s quite a bit harder as well. And occasionally there’s a tough boss elsewhere, most notably at the start of level three. Which worked out well: I was rarely bored during my normal progression through the game, I was rarely frustrated when I got to the tough bosses, and on those few tough bosses that I couldn’t beat on the first couple of tries (levels 3 and 12 – hmm, I guess the really toughest bosses aren’t on the multiple of five levels, are they?), I didn’t have to do too much wandering around and leveling up (combined with intelligent upgrade selection) to get to beat them.

So all was fine and dandy through the first ten or fifteen levels. At that point, though, problems developed. For one thing, two character classes aren’t unlocked at the start, leaving hope for interesting new opportunities going forward. The first one, Ronin, was okay; after suitable leveling up, I swapped out my previous fighter type for one, and was happy enough with that choice. But I didn’t feel that I got anything great from the new class, either: I’m fairly sure I would have been just as happy with my previous class.

The second new class, though, was an active disappointment. As mentioned above, I’d been with a party of two Alchemists, the stock magic user type. (The rest of my party was a Landsknecht (= generic fighter), later to be swapped with a Ronin; a Medic; and a Dark Hunter, a rather fun fighter type who also has paralyzing whip attacks that are extremely useful against boss monsters.) The last class to unlock is a Hexer; I’d been hoping that would be an interesting twist on an Alchemist, allowing me to vary my party a little more. In fact, though, a Hexer wasn’t very much like an Alchemist; the result was that I kept my party the same (I like my elemental spells!), and was unhappy.

Also, at about this time, the plot took a turn for the worse. All along, the plot was, to put it gently, threadbare. Which is okay: that’s really not what this sort of game is about. At around level 15 or level 16, though, they introduce what seems to be an interesting turn of events. I expected here that I’d be able to choose between a good way of proceeding and an evil way of proceeding. Which has been done a zillion times recently, so it’s no great shakes, but would at least have been a sign that they were taking some small amount of care of the plot.

In fact, however, there was only one way to proceed, and that one way involved proceeding in a banally evil fashion. This left me with a bad taste in my mouth for two reasons. One is that it drove home the lack of quality in the plot. And the other is that I don’t particularly enjoy slaughtering people, even random cardboard enemies, just to proceed through a game, if I’ve been given active reason to believe that they have more right to be in that part of the game world than I do.

And then I reached level 20. The level started off as an interesting twist: there were no random encounters, but instead the level was full of mini-bosses. Which I couldn’t all kill, so I assumed the level was about mapping it out properly and picking my way through them to find a stairs somewhere. Eventually I had the whole level mapped, though, with no stairs; on to theory B, that the boss in the center was special, and once I beat him I would find some stairs.

And indeed the boss in the center was different from the other monsters in several ways, but beating him didn’t turn up anything. After a bit of scratching my head, I looked on gamefaqs: it turns out that you have to beat all of the mini bosses plus the central boss in the level without dying.

Which, for me, crossed the line from a pleasantly tough challenge to actively disrespectful. I could have done it after a bit more leveling up, I’m fairly sure. But each attempt would have involved an hour or two of battles, with no guarantee at the end that I’d succeed, and with monsters respawning if I left in the middle to save. I probably would have soldiered through it if I’d had a more favorable impression of the game by then, but my two recent disappointments had already left me with a bad taste in my mouth; at that point, the game had spent too much of my goodwill towards it to leave me willing to invest further potentially unproductive hours to make it past that barrier.

So I stopped. Lest I end this on a depressing note, however, I want to emphasize that this was a quite pleasant game through the first 15 levels or so. I’m glad I played it, and it did a lovely job of helping me through the summer game doldrums.

But I’m also confident that I stopped at the right time. For one thing, there were a few other games that I wanted to give a try in the second half of the summer. And, right now, all hell is about to break loose: as far as I can tell, if I want to spend all of the next nine months playing video games that are better than this one, I will be able to do so. Metroid drops next week, the DS Zelda and Zack and Wiki in October, Mario in November, Professor Layton (for single-player fun) and Smash Brothers (for multi-player fun; Miranda has recently discovered the Gamecube version and quite enjoys it) in December. And hopefully by the time I’m done with those I’ll be confident enough about the quality of Xbox 360’s that I’ll be able to buy one of those, at which point Bioshock, Eternal Odyssey, Rock Band, and Mass Effect will keep me quite busy. The rest of this year looks like it will be the best four months of games that I can remember; maybe I should just burn my vacation time and hole up in front of the TV for a few weeks…

post length

August 20th, 2007

Maybe I’d have more free time if I were capable of writing blog posts that are less than three pages long?

game development

August 20th, 2007

For the last several months, Miranda has been repeatedly talking about ideas that she has for a computer game. I idly encouraged her without thinking too much about it; recently, however, she’s been actually filling up notebooks with designs for the game, so it looked like time to start getting serious.

She doesn’t show any particular interest in actual game programming, so we’ve decided that I’ll do the programming while she’ll do the art and game design. Which raises two technical questions:

  • What’s the best environment for programming in?
  • What’s the best way for her to generate sprites?

Both of which seem like pretty obvious questions, which you’d think would be easily answered; not so, it turns out. (Thought I’m still quite open to the possibility that I’m dense or clueless.)

For the first, there are various C++ libraries and Java libraries out there. But I don’t particularly feel like starting a new side project in either of those languages right now: if there were some dominant library in either language that everybody agreed was wonderful, than great, but otherwise I’d rather try something else. I’ve heard a few mentions of pygame; I may actually end up using that.

The frustrating thing is that there is, actually, one obvious language to use: Flash. There are zillions of existence proofs that it’s both a suitable language for novice game developers and a platform that can be used to develop quite professional games. I’d certainly rather use an open source platform, but there’s something to be said for the democratic effect of a language that allows you to easily publish your game and make it accessible to billions of people.

The problem is that it costs seven hundred freaking dollars. This is rather more than I’m used to paying for software. (I was going to say about seven hundred dollars more, but I’m happy to spend fifty bucks on a video game.) If it were fifty bucks, I’d feel guilty about it’s non-freeness, but I’d buy it. If it were a hundred, I’d think about it but do more research. But seven hundred dollars? Well, maybe, if Miranda and I are still into this in a couple of years, but no way I’m spending that right now.

I have to think that Adobe is missing some sort of market segmentation opportunity here. There are many people for whom the value of the product is (much more than) seven hundred dollars. And then there are people like me for whom the value is rather less than that. The marginal cost of the product to them is low; if they could find a way to produce, say, an introductory version that I’d be happy with, it would be, to some extent, free money for them. And once I got hooked, they could get me to upgrade to a better version.

Eventually, I stumbled across rubygame. Which looked pretty primitive but possibly functional enough to be worth a try. So I downloaded it yesterday; the C extentions compiled with no hassle, and the demo “game” they provided, while not much of a game, ran just fine.

So I had a lot of fun the last two evenings combining that with the aptly named “Miraculously Flexible Game Prototyping Tiles” from Lost Garden. Yesterday, I assembled some tiles into an environment; today, I added a character that can move around the environment. Extremely bare bones, but it all works fine, and I can see how I should be able to develop it into a game that expresses many of Miranda’s goals.

I’m still not sure if I’ll stick with rubygame, but I’m sure that much of what I’m learning will transfer to other environments. And it really is neat to see pictures pop up on screen.

So now I have to replace those pictures with sprites that Miranda has designed! One advantage of having somebody else’s tiles to start with is that they give me some design parameters: so I need to generate tiles that are 100 pixels wide, 170 pixels high, a certain proportion of which is boundaries. (I’m also willing to consider entire room backgrounds that she might draw, but never mind that for now.)

How should she generate the tiles, though? For now, I’m telling her to draw things on paper. My brother gave us a combo printer/scanner/copier last year; we haven’t used the scanner yet, but we should be able to scan in images using that. Then we’ll need to shrink them to an appropriate size, and touch them up.

But what are the best tools for that? Everybody talks about GIMP, but I’m not at all convinced that it would be a good fit: it’s complicated enough that Miranda gets scared by it (and, actually, I find it to be more than a bit much), and all its its complication is pretty much irrelevant for us. Honestly, I just want a simple drawing program that can generate PNGs and that makes it easy to get pixel-level control when necessary; that’s about it. There are probably features that we’ll want in the future (e.g. the ability to handle layers), but that’s the core that I want it to be focused on.

And I’m having a hard time finding the right solution. (Admittedly, I’ve only put in a couple of hours of search, so I could be missing something.) Googling turns up lots of possible choices, but nothing that everybody says “this is great”. Pixen looked good, but it crashed a few times when I tried it.

And, actually, maybe I shouldn’t be focusing on editing pixels – maybe I should be looking for vector-based solutions instead? This is all new to me…

For that matter, maybe I shouldn’t be focusing on software at all. The last couple of years have certainly taught me something about the importance of input devices; maybe I should buy Miranda a graphics tablet? I’d been assuming those were too expensive to contemplate, but actually the low-end Wacom models don’t look that bad, and they come with some software that might do the trick. Hmm, that’s a real possibility; I’m not going to buy one now, but if she sticks with the game project for a while, maybe I will get her one.

dealing with annoying drivers

August 19th, 2007

Jordan responded to my earlier post by adding:

If you would like to be driving 5 mph faster than you are, but someone is preventing you, stop and think about how much difference the extra 5 mph makes to your overall life goals. If the answer is “not very much,” then try to keep from getting angry. Angry people are bad drivers.

To which I say: absolutely. Getting angry at other people does zero good. It does zero good to your psyche, it does zero good to your and others’ safety, it does zero good toward accomplishing your goals. You should try to do as good a job as you can driving in the context of the drivers you’re actually surrounded by, instead of pretending/wishing that you’re surrounded by clones of yourself and getting frustrated when you’re reminded that that isn’t the case.

So don’t tailgate. Don’t pass the car ahead of you if, in order to do that, you have to force your way into adjacent lanes. Don’t erratically alter your speed.

Things you can do in this situation:

  • Marvel at the wondrous variety of your fellow drivers, try to develop a mental model of their behavior, and think about how you can detect various varieties of inferior drivers earlier. This is not only more fun, this increases the chance that you’ll be able to respond effectively to them, e.g. by changing lanes when there was a hole in the left lane 30 seconds ago instead of waiting until you’re right behind them and boxed in on both sides.
  • Think about whether or not you ever exhibit the behavior of the driver that you’re currently annoyed at. Does this suggest ways in which you should alter your behavior in the future? In which you should alter your behavior right now? Can you think of reasons why the driver in front of you might, in fact, be behaving completely reasonably right now?
  • Compose your next blog post in your head. (As long as doing so isn’t excessively distracting.)

Having said that, if I am stuck behind a car that I wish were either going faster or would get out of my way, and if I believe that car can actually do something about the situation, I drive a little closer to the car than I normally would. (Don’t get me wrong, I still leave more than enough room for safety, just not the ridiculous margin I might otherwise leave.) I justify this in terms of my fifth suggestion from before: for all I know, other drivers would be perfectly happy to get out of my way if they knew they were hindering me; and the primary means of communication I have in this situation is my following distance. Certainly I’m more likely to move a lane to my right if the car behind me is driving in a way that makes me think they’d rather be going faster than if they’re 15 car lengths behind me and matching my speed.

ide assumptions

August 18th, 2007

On the XP mailing list, somebody recently pointed out that never changing IDEs is a sign that you’re in a rut. Which is true; I love Emacs, but I love it less with more recent languages, so why not learn a bit more about what’s out there? Tim Bray recently posted about how well the NetBeans Ruby support works; I thought I’d download it and give it a try.

I’m typing on my Mac right now, and the NetBeans Ruby community seems to be somewhat Mac-centric, so I figured I’d start there. So, after a bit of reading wiki pages, I found something to install, and fired it up.

First thing that made me say hmm: it seems to think that your source code and unit tests should be in parallel directories; in my current project, the tests are in a subdirectory. Will that bother NetBeans? Not clear; I’ll just point it at the right place, and see what happens.

But my local sources are out of date. Part of the point of an IDE, however, is that it knows about version control systems; sure enough, there’s the “Update” menu item. Which doesn’t work: apparently NetBeans got a complaint from ssh about “Connection unexpectedly terminated”, or something like that.

Some background: I use svn+ssh to read the files from my server. I require a password: I’ve decided not to put any ssh private keys on the laptop for security reasons. To double check that things are still working, I go to a shell and do ‘svn update’ in my local checkout: no problem there.

Next step: see if this works with NetBeans without using the existing local copy that I’ve checked out. So I create a project from scratch, and try to add files by telling NetBeans to check them out from the svn repository. Based on the menus, it does know about svn+ssh; the usage examples that it gives, however, require having a private key available.

See, this is the problem with IDEs. It’s okay that it doesn’t let me use a password: I don’t expect it to be able to handle every wart of my setup, as long as it doesn’t mind if I handle that wart a different way. And with Emacs, I know I can do my svn updates outside of Emacs, because I know what’s going on within Emacs: at the core, Emacs edits files. It can do lots of other things for me, but I know that, if I go to a shell, and type ‘svn update’, Emacs won’t get confused. I’ll have to revisit buffers that are looking at changed files, sure, but that’s to be expected, and Emacs will let me know if I’m trying to edit an out-of-date buffer. Whereas with NetBeans, who knows what I can do manually! Does it depend only on the file system the way Emacs does, does it keep a separate index elsewhere, or what? I don’t want to start depending on its fancy “find usages” stuff only to discover that it’s missed usages because it didn’t learn about files that came in through an svn update that I did in an external shell.

(On the “find usages” note – that’s great, but I hope they get to “extract method” soon. Which they probably will: they seem to be developing actively, it’s flagged on their wiki page as something they should do, and I have to think it’s a lot easier to implement than “find usages”.)

To be sure, my IDE complaint above is quite unfair: when I say “who knows what I can do manually”, I mean “I, a complete NetBeans novice, do not know what I can do manually”. Somebody knows, it may well be documented somewhere (I haven’t tried to look at all), and for all I know everything will just work. Having said that, I’ll stand by my basic point that, the more a development environment depends only on the public contents of the directory system (as opposed to special stuff that only the IDE controls), the better: that makes it clear that tools can interoperate, and reduces the barriers to entry and exit.

I’ll give it a try on the Linux box next, I guess: that’s where I do most of my home programming, anyways, and there I don’t have to worry about the ssh issue. And, given my last paragraph, I suppose I’ll drag NetBeans out of the trash: maybe it does the right thing, in which case I was premature in deleting it.

Hmm, getting back to the first sentence of this post, maybe this is a great example of how my development environment usage is a sign of being in a rut. If I freak out at the first (or maybe the second) sign of problems and run back to the environment that I’ve been using for the last two decades (have I really been using Emacs for 20 years? Wow. If not, I must be close – maybe I didn’t start using it until 1988? Looking at the relevant bits of the release history, I can’t tell; my first version may well have been an 18.4x one, but I don’t know which), then obviously I need to get out more.

clueless drivers

August 18th, 2007

Warning: boring whining about other drivers follows. And no, I don’t claim to be a perfect driver myself.

One of my coworkers has been known to say something like “east coast drivers are assholes, west coast drivers are clueless”. Having driven on both coasts recently, I’m inclined to agree. And, while I’ll take the clueless driver over the asshole, I do wish people around here would think a bit more.

I actually hadn’t been bothered by the clueless behavior much in the past. Most of my driving is during rush hour; during those times, I understand why people make the decisions they make, and while I disagree with some of them, it’s quite possible that I’m the one making bad choices instead of them. But I’ve been doing some driving recently during off-peak times, and been astounded more than once (much more than once) by how drivers around here manage to create congestion in a four-lane highway that is way below capacity.

Suggestion 1: You do not have a god-given right to stay in one lane in perpetuity.

Traffic conditions change: just because you were behaving reasonably by driving at a given speed in the third lane two minutes ago does not mean that you are behaving reasonably by driving at that speed in that lane now.

Suggestion 2: If you are at the front of a wave of traffic, think about why that might be.

A dozen or so times recently, I’ve been driving along a four-lane highway at good speed (around 68mph, I’m not a big speeder these days), run into a clot of cars, and had to slow down to 60-65. And, when making it through the clot, I’ve discovered that the cause is because four drivers have decided that it’s a smart thing to drive next to each other at the same speed, making it impossible for anybody to pass.

Those four people are blocking potentially hundreds of people; I don’t blame the one in the right lane, but if any of the other three were the slightest bit awake, they’d notice that there is open road in front of them, dozens or hundreds of cars behind them, and they’d accelerate slightly to move ahead of the car to their right and then change lanes to their right. And then the clot would disappear. But no, they apparently all think they have the right to stay in their lane no matter what.

Suggestion 3: If the amount of open space ahead of you is more than the following distance you need to feel comfortable, think about why that might be.

By all means, keep a generous buffer between yourself and the car in front of you: I’m towards the extreme end of that spectrum myself. But if the amount of space in front of you is more than you need, look in your rear view mirror. Is there a car, perhaps even several cars behind you who would prefer to pass you? Are you not in the right lane? Then move over! Do it even if you have to, heaven forbid, speed up two miles an hour to pass the car to your right to find a space, or, heaven doubly forbid, slow down a mile an hour to match the rightward lane’s speed so that you can let some cars pass.

This is, of course, a generalization of suggestion 2, this symptom’s most perverse form. And I do realize that, at times, the lane to your right is too clogged for you to be able to get into it. Which leads to:

Suggestion 4: If you’re not going at least three or four miles per hour faster than the lane to your right, and you can take action to correct that, do so.

Lanes are there for a reason; they don’t work well if the right lane is going 65mph, the second lane 66mph, the third 67mph, and the left lane 68mph. I appreciate that your favorite speed in the entire world may be 67mph, and that the lane to your right may be going a pathetic 66mph. (Honestly, I really do appreciate that: it’s really annoying to be stuck behind somebody going just a bit too slow.) But sometimes you have to balance your desires between those of, say, the twenty drivers behind you. If that means speeding up a bit and staying in your lane while being less of a hindrance, or slowing down a bit to move to the right, do so.

Suggestion 5: Look at the drivers around you; try to figure out what they’d like to be doing and, if you can make it easier for them to do that, consider doing so.

Honestly, it’s a lot more fun to pay attention than to drive zombie-like down the road, obvlivious to your surroundings.

detailing carpets

August 16th, 2007

I’ve been on a bit of a Christopher Alexander kick for the last couple of years. At first, I started reading his most famous books, but those were good enough to leave me curious about what else he’d written. Not all of which is great, but enough is to keep me going.

Still, it’s taken me a while to get around to his book on carpets. For one thing, it’s out of print, and it took me a while to find a copy at a price that I’m willing to pay. For another thing, I don’t particularly care about carpets! But I finally found a copy, which I started reading earlier this week.

And I was completely blown away right from the start. Mainly because of the pictures: I was completely unprepared for the colors that are used in the carpets that he gives as early examples. But he also starts right off with a point that is really resonating with me right now:

What is often called the “detail” of the building—its fine structure—is not some kind of icing on the cake, but … the essence of what it is, and how it makes its impact upon us. (pp. 7–8)

The small stuff matters just as much as the big stuff; the power of the big stuff comes in large part out of the small stuff.

Translated into programming terms: keep your code clean, make every line as expressive as it can be. Which is something that I really enjoy doing, and I’m quite sure that I have a lot more to learn in that area. In particular, I’m fairly sure that there’s a lot more power to the notion that unexpected structure can arise somewhat spontaneously by determined refactoring than I’ve experienced so far. I don’t really believe that determined refactoring is all you need for good structure, but there too I have a lot to learn: where do you need more design, and what sort of extra design do you need?

(Side note: if I’m remembering correctly, Lisa Crawford told me once that Gustav Leonhardt spent a lot of time working with his students on how to best play short musical phrases. This sort of ability worked great for him, but apparently left some of his students able to play pieces in ways that sounded good at the small scale but didn’t work out so well in the large.)

But I’m not getting nearly enough practice at this. In my pet project at home, I’m trying to keep the code expressive and free from duplication, but there’s only so much you can learn from a thousand lines of code. I’ve had some interesting experiences at work, but there’s a lot of legacy code there, and I can’t responsibly spend large amounts of time cleaning it up.

Having the team as a whole spend small amounts of time cleaning it up is something that would be responsible for me to push on; I haven’t been very successful in balancing that against other activities with more immediate payoff so far, but I want to keep on trying. Even if that is successful, though, what I’ll get out of it will be different: I’ll learn a lot about balancing competing short-term and long-term demands, which is great, but I won’t have the experiences of uncovering structure myself.

What to do? One possibility is to try to work on a bigger project myself at home. I don’t feel like I have any big ideas bursting out right now, though. (Do any of my readers? I’m open to collaboration…) Another possibility would be to spend some time on evenings and weekends cleaning up the work code base. That sounds more reasonable; it still raises issues as to whether or not I’d be acting responsibly in doing so (since I’d be doing so for my own benefit, and I wouldn’t want that to hurt my team, e.g. by setting a bad example or depriving them of pleasure/learning opportunities), but in the balance I think that would be okay.

Or I could find a medium-sized open source project with an interesting code base to get involved in. That’s also an intriguing idea, and one that could have other benefits (and, to be sure, down sides); I have a few ideas in the back of my mind, but nothing concrete yet. I’m certainly open to suggestions on this front.

I’ll think it over for a few months: balancing the demands of existing programming projects, learning Japanese, reading blogs, blogging, playing video games, and of course reading books is quite a challenge as is. So, realistically, something has to give, which probably means that I have to wait until I’m done with my current personal programming project, and I already have another couple ones sketched out after it. But maybe in three or six months I’ll have managed to carve out a bit more time.

Back to the book. I’m not as in love with the rest of the first part of the book as I was with the beginning. He’s spending a lot of time talking about centers; I’d already seen those ideas in more refined form in The Phenomenon of Life. Still, it’s interesting enough, and I’m now pretty curious about the catalog of carpets that makes up most of the book.

I now have all of his earlier books except for The Linz Cafe: that one I have been unable to find at a price that I’m willing to pay. I just put in an interlibrary loan request for it, though. Once I’m done with it, I guess I’ll reread The Phenomenon of Life, and then move on to the rest of The Nature of Order.

learning japanese: a month and a half in

August 15th, 2007

I’m on the fourth chapter of my Japanese textbook now, enough for a new set of difficulties to surface. All of which ring vague bells from a decade ago; I’m trying to do things right this time, which means that I need better strategies for facing these difficulties than I had last time.

One problem: when I claim I know a vocabulary word, when I move it from the “review regularly” stack of flash cards to the “mastered” stack of flash cards, I want that to mean that I really do know the word! But, for an uncomfortable number of flash cards, what is really going on is that I can reliably, upon seeing the front of the flash card, recite what is on the back of the card. Which isn’t the same thing.

Some aspects of that problem show up no matter what language you’re learning. For example, I usually only do my cards in one direction, so I regularly drill going from megane to “glasses” but not in the other direction. Also, their are grammatical issues: to really know a verb, you should be able to conjugate it at will, and recognize it in any of its forms.

Those particular problems aren’t that big a deal for me yet. I haven’t learned too much grammar, and I’m doing a pretty good job so far in being able to go from English to Japanese even though I’m drilling Japanese to English.

What is a big deal is the presence of kanji. This increases complexity in a few different ways. For one thing, I have to go between three forms of the word (kanji, pronunciation, and English) instead of just two forms (Japanese and English). And, of course, a single kanji character can have multiple pronunciations, which may or may not have multiple readings, and which may or may not be signalled by adding some kana at the end. (After some experimentation, I’ve decided to exile all the extra kana to the back of the card, instead of leaving it on front.)

That’s the obvious problem, but there’s also a more subtle one. When I see a vocabulary card, I see something I wrote by hand, taken from a limited number of other vocabulary cards that I’ve written. So when I see, say, the kanji for bijutsukan, what I really see is a card with three kanji characters on the front, where in this case I happen to have written the kanji characters a little smaller than would be ideal, and a little bit off center. And, honestly, that enough is almost enough to allow me to uniquely identify the vocabulary card from among my current set, especially if one of the radicals in one of the kanji seems familiar for some reason.

But, of course, that doesn’t mean that I know the word at all: if I saw those same three characters in a Japanese book, I would have almost zero chance of recognizing them as bijutsukan, and for that matter I’d be equally likely to mistakenly think that some other sequence of three characters might represent bijutsukan. I now appreciate what kids learning to read and write English are going through when they see a sequence of letters and guess that it’s some other word that happens to start with the same letter or two and is more or less the same length: they don’t have any deeper grasp of the phonetics of written English than I do of the radicals that make up a kanji character, and in both cases we quickly get overwhelmed by the task of really understanding how a word is written.

So what do I do about this? Part of my solution is to simplify the problem. I can adopt a classic agile planning technique: recognize that there isn’t a strong correlation between the difficulty of a task and its business value, and that, when chosing between two equally tasks of equal business value, you’ll get the quickest bang for the buck by doing the easier one first. What that translates to in this case is that, all things being equal, I should try to memorize words made up of as few kanji characters as possible. So one is best, two might be okay, especially if I’ve seen one of them before, three is unlikely to be a good idea. And not all kanji characters are created equal: given a choice, I should choose characters made up of as few radicals as possible, to increase the chance that I’ll be able to really know the whole character. (As opposed to, say, having the left side of the character trigger a memory in me.)

That alone isn’t good enough, though: it doesn’t leave me with a strategy for dealing with important but more complicated characters/words, and doesn’t directly address the complexity of what it means to learn a character. To really learn a character, I should be able to write it out myself, and be able to reliably tell it apart from similar-looking characters, characters with, say, the same radical on the left and on the upper-right but a different one on the lower right.

The answer to both of these aspects of knowledge is, for me, the same: I need to learn to love radicals. Once I really know the radicals, I won’t have to, say, recognize and reproduce the thirteen strokes making up a complicated character, I’ll just have to recognize and reproduce the three radicals making it up. That’s not a simple problem, given that there are about 200 radicals to grapple with, but it’s at least a tractable problem. Especially since the radicals in a character aren’t chosen arbitrarily: radicals have meanings on their own, so you can frequently build up the meaning of a larger characters out of the meanings of its radicals, and radicals can at times lend their pronunciation to the pronunciation of the entire character. So there’s real structure to work with here; as I buff up my radical credentials, it should become easier and easier for me to learn more and more complex characters.

And, fortunately, I’ve recently acquired an excellent book on the subject. It does a great job of showing how the characters evolved (and is historically accurate, as far as I can tell), and of gradually introducing radicals and showing how they add meaning in more and more contexts. So I’m gradually adding characters from that book into my stack of cards to memorize, even if I haven’t run into those characters in my textbook, and trying to remember the evolution of those characters in the bargain. Should make learning characters more fun, and easier.

That’s the main problem; there are a couple of other problems that I’m running into as well, though. One is that there are too many new words in each chapter for me to be able to memorize. I was worried about this three weeks ago: it seemed like my stack of unmemorized cards was getting longer and longer. Since then, I’ve been doing a pretty good job of moving cards into the memorized stack, but I don’t want to ignore the problem. (Especially since I’m now adding vocabulary cards from a source other than my textbook!)

Part of the solution is to simply not memorize every new word in each chapter. Each chapter introduces maybe 80-100 new words; I’m pretty sure that I can get away with only learning 40 or 50 of them right then. So I’m picking the ones that seem particularly likely to be important, or particularly likely to be easy to learn, and I don’t sweat the other ones for now. And if, in subsequent chapters, I keep on encountering a word that I didn’t memorize when it first showed up, then I can always learn the word later. It’s not completely clear that this is a scalable strategy – maybe, once I get to chapter 15, I’ll have to memorize 5 new words from each of the previous 15 chapters along with an extra 50 words from that chapter, which would suck – but I think it’s worth giving a try.

The second part of the solution is basic queue management: the problem here is an unbounded queue. And if you don’t want to have an unbounded queue, then put a cap on it! So I could adopt a rule that I can never have more than, say, an inch of unmemorize vocab cards in the box. Once I reach an inch, I have to do something else until the stack goes down: some combination of memorizing a smaller proportion of words in each chapter, taking longer to go through each chapter, and learning to be more effective at memorizing words. I don’t have an exam schedule or anything that I’m working towards: I want to do this right, and to do this right I need to balance my capacities, my time, and the number of words that I’m attempting, instead of letting artificial pressures skew my attempts at the cost of a loss of effectiveness.

So far, all the problems I’ve talked about have been about memorizing words, but it’s also starting to get a little harder to put everything in the chapter together. In the fourth chapter, for the first time, I had a bit of trouble doing all the exercises in the chapter the first time through, because of a combination of not having all the grammatical details, the usage details, and the words at my fingertips. I think that, for now, the best approach is to acknowledge that this is a potential issue, and be alert for warning signs. So I’m planning to go through the exercises in this chapter until I can do them all easily; if that means it takes three weeks to get through the chapter instead of two, that’s fine.

I imagine that further non-vocabulary issues will crop up as I go along: needing to memorize conjugations, for example. It’s been a while (almost 15 years! Ouch) since I’ve had to deal with that sort of thing, but I was once adequate at memorizing grammar, so I assume I’ll be able to do it again, and I don’t think Japanese holds any particular horrors in that area. And further holistic issues will appear: getting practice in reading actual books (and finding a suitable gradual series of books to practice that), practicing spoken Japanese. I imagine that, once those become urgent problems, outside guidance will be essential; fortunately, outside guidance shouldn’t be hard to find around here.

Fun stuff.

i guess that’s why they’re there

August 14th, 2007

A few months ago, I lost the foam covers on my earphones (standard iPod earbuds). I didn’t worry about it too much at the time; they sound fine without them.

A month ago, the left ear in one set of earphones died. I didn’t notice exactly when it happened; I chalked it up to kinking the wires, or something, and didn’t worry too much: I had extras.

While I was jogging today, the left ear in another set died; I don’t think I was doing anything in particular at the time, other than sweating.

So is the point of those foam covers to absorb sweat, so it doesn’t get into the earphones proper and screw things up? Or is my recent experience just a coincidence, and there’s another reason?

joshua bell in a subway station

August 12th, 2007

Several months ago, the Washington post wrote an article about Joshua Bell performing in a D.C. subway station. Almost nobody noticed him; he made some money (probably a good amount for a subway musician), but certainly didn’t attract any crowds or anything.

My first reaction was: I hope that I would recognize the quality of the performance, and even stop and listen for a while. And I’m enough of a snob that I still hope that I would recognize the quality of the performance! And on the surface of it, it does seem odd that people are willing to pay a hundred bucks to hear him perform in a concert hall, but walk right past him in a subway station. The more I think about it, though, the less sure I am that I wouldn’t walk past him, too.

The first answer to why some people walked past him while others paid lots of money to listen to him is, of course, that it’s not the same people making those choices. (And, in fact, they catch one person on camera who did see him perform in a concert hall recently, and who did stop to listen in the subway station.) There’s certainly something to that.

But I’m not happy with that answer. Yes, people don’t always notice beauty even if it’s sitting right in front of them. But if we take Joshua Bell as the exemplar of beauty, well, recordings of a wide range of his performance are a short Amazon search away; just how different is not buying one of those CDs from walking past him in a subway station?

Sure, it’s a few clicks and 15 bucks different, but I can scrape up 15 bucks without too much trouble these days and I’ve already done the clicks. They’re recorded performances instead of live ones; live performances are special, no question, but a recording studio has certain acoustic advantages over a subway station.

Which leads to this answer: access to beauty is, in general, not something in short supply in my life. What is in short supply is time, and a way to choose between the staggering amounts of beauty that are available to me. As ways to choose, stopping to pay attention to beauty that you walk past in a subway station isn’t a bad one. But back when I was a regular denizen of subway stations, my life wasn’t a soulless void that needed to be filled by famous performers: I was talking to friends or reading books in those subway stations, and the only reason I wasn’t listening to music was that I didn’t have as good portable audio options at the time. (Well, that plus I really like reading books.)

Saying that those are bad choices and that I should be listening to Joshua Bell instead is just being an elitist asshole. (To be clear, I’m not accusing the author of the article or Joshua Bell of being an elitist asshole: I have no reason to believe they are espousing that point of view. Though the author’s comment that “I bet Yo Yo Ma himself, if he were in disguise, couldn’t get through to these deadheads” makes me wonder, for a couple of reasons.) And, frankly, while I’m sure he’s a fine performer, I’d far rather have my current collection of CDs than an all-Joshua Bell collection of recordings.

By all means, pay attention when unexpected beauty enters your life, and go out of your way to fill your life with beauty. But beauty comes in countless forms; keep an open mind as to where you might find it, as to where others might find it.

And there’s something to be said for getting to your appointments on time, too…

more shuffle, please

August 12th, 2007

Last weekend, we were driving back from the Exploratorium, and were listening to the iPod in shuffle mode most of the time. As expected, it gave us a delightful selection to listen to: Stan Freberg (“There’ll Never Be Another War”, the Civil War version as opposed to the WWI reprise); a 10-second snippet of Katamari music; the title song from Rhinoceros Tap; two different Jewlia Eisenberg songs (one in her Charming Hostess incarnation, another as Red Pocket); some Herbert Grönemeyer (whom Miranda has turned into a fan of recently); Bernstein’s “The President Jefferson Sunday Luncheon Party March”; a portion of Mathis der Maler; some Andrews Sisters; a bit from Striking 12 that we skipped over since we’d listened to it on the drive up; and a few more pieces that I’ve forgotten. Hard to imagine a better way to spend a car ride.

And then, on Thursday, I was taking Miranda to daycare; what should the iPod decide to give me but “There’ll Never Be Another War”? Hmm, that’s a bit of a coincidence – which version of the song is it? Ah, “brother won’t fight brother”, Civil War again. Still, coincidences happen. After that same snippet of Katamari music, though, I was rather more suspicious, and “Rhinoceros Tap” sealed the deal. Though I did, after dropping Miranda off, fast-forward through fourteen songs and verify that we’d listened to all of them on our recent drive.

There are about 1200 songs in the iPod right now; clearly this is not a coincidence. I’d suspected problems like this in the past, but this was the first time that I’d gathered such compelling evidence. I guess they don’t bother to use a decent algorithm for picking new seeds for their random number generator? Which kind of boggles the mind – the device has a clock in it, so they can just use the current time as a seed! Not necessarily the only thing you’d want to use as a seed – I can imagine the clock dying, in which case you wouldn’t want shuffle to always return the same thing – but whatever they’re doing now sure isn’t good enough.

Maybe they keep a persistent seed which gets reset to zero when you reset the iPod? (Hopefully not when you just sync it, that would be too stupid for words.) And then gets bumped up each time you do some specific action (enter shuffle mode, maybe)? Because I do have to reset my iPod a few times a week; given that I only add or remove (non-podcast) songs once or twice a month, that could be a reason why I’m running into this particular problem.

Sigh.

mechanical assistance

August 6th, 2007

An interesting analysis of the beneficial effects of Bonds’ armor on his swing. Sounds plausible to me, if not 75-100 home runs plausible; I’d be curious to read further studies on the topic.

And, if it’s true, what’s the proper way to deal with the situation? I guess I’d lean towards allowing body armor for everybody, with some amount of mechanical/weight restrictions.

car models

August 4th, 2007

Another thing I learned on the trip: I can see why Ford retired the Taurus. (Though I guess they’re bringing it back.) I didn’t like ours from the moment I sat down in it, mainly because I felt like my head was banging against the ceiling. I realize that I like to sit farther forward than most people do in cars – otherwise, my arms start feeling like they’re getting RSI twinges – but if my Saturn Ion can give me plenty of headroom, why can’t a larger car? And I far prefer the acceleration and braking in the Ion, though admittedly I thought the Ion’s brakes were overly sensitive when I first started driving the car. Fortunately, I got used to the amount of braking required by the time we started to run into Boston drivers doing stupid stunts. (Otherwise, we would have run into them literally instead of just metaphorically.)

Liesl, however, is getting thoroughly sick of our older Saturn, with good reason: it’s required way too much maintenance. And, even when it works, I don’t enjoy driving it as much as the Ion. So we’ll be buying a new car this year, and one from a manufacturer whose quality we trust, which means Toyota or Honda. Not clear yet which model, though.

One question: do we want a slightly wider car, for those few times when we have five people in the car? Another question: how much do we care about mileage? A third question: is it posisble to find a Toyota dealer who isn’t a complete asshole? I think a Corolla would be too small, but a Prius, a Camry, a Civic, or an Accord would all be plausible choices.

Any recommendations?

belches

August 4th, 2007

Miranda is currently under the impression that the name of The Blue Danube Waltz is “the burping song”. She practiced some on vacation; she’s not nearly as good yet at burping melodically on demand as Wakko, but she’s definitely improving.

(Trivia: that’s not actually the regular Wakko voice doing the burps: they are stunt burps provided by Maurice LaMarche, the voice of The Brain.)

boston trip notes

July 29th, 2007

Some random notes from our recent trip to Boston and its environs:

  • T tokens are no more. Which made me a little sad, but I was very happy that, when arriving Tuesday evening for a trip where we’d be leaving the next Tuesday morning and would spend three days outside of Boston, there was a week pass available that was a good value. And I now know that kids under 12 can ride for free, but didn’t know that when buying the passes…
  • I was surprised that we got a good rate at the Park Plaza for a couple of days – is it normally affordable, or did we get lucky with a Tuesday/Wednesday request? Good location (though it took us a little while to find it, because we were confused by the construction at the Arlington T stop), and I could live without free internet access for two days. And an Amino set-top box on the TV – just like being at work!
  • Hampton Inn has decent internet access at no extra charge. Though I was pretty annoyed at the fake nameserver at the Norwood one that sticks in an ad page if an address doesn’t resolve. Especially the one evening when, for whatever reason, a fair number of lookups were timing out, poisoning any future requests to those domains for the next 15 minutes or so. Not good if you’re reading blogs and can’t get to feedburner.com any more…
  • I was impressed how we could get from downtown Boston to a turnpike entrance three short blocks away to out of town almost immediately. Especially since it doesn’t feel like there’s a turnpike cutting through downtown Boston, though I realize that I have walked on bridges over it several times.
  • Sturbridge Village turned out to be a really good choice for a place to spend much of a day. Enough stuff to keep us interested, very low key, we got to see 1820’s welding technology in practice, Miranda liked it too.
  • The suburbs that aren’t in the inner ring seem to kind of suck, at least near the arteries. I was not pleased with being stuck traveling at 5 miles an hour on 128 at 5pm, and route 1 in Norwood was not a place where I’d want to spend much time, if largely for aesthetic reasons.
  • Got to see a couple more retirement communities. I’m glad these things are around. (Though I’m sure there are bad ones out there, too.)
  • Didn’t get to see almost any friends or old haunts: we were too busy doing other stuff. Which is fine, actually: almost all of my Boston-area friends have moved away. I wish I’d had another day to just putter around places, but I can live with that.
  • The MGA is still active. Unfortunately, I couldn’t make it on a Tuesday or a Friday, so I didn’t get to see any of my old friends from the club, but you can get together a few people to play go on a Sunday at the Diesel Cafe. Which apparently opened about a year after I left the area; it’s a long narrow space (running all the way through the building from one street to the next), with good food and pleasant decor.
  • That day, about 75 percent of the people in the cafe were using laptops, and about 20 percent of the people were reading the latest Harry Potter. (Which had come out the day before.)
  • I enjoyed meeting blog reader Chris Ball in person (and other MGA members and Chris’s wife Madeleine), and we had a couple of exciting games – we turn out to be quite close in strength, conveniently! And I got to see the OLPC laptop in person, too.
  • Harvard Square is doing okay; a few stores I like closed, one out-of-place building has appeared, but no wholesale destruction. Wordsworth’s has closed (though their children’s book store still exists, didn’t go in to see what it’s like these days); Harvard Book Store is still open. (I also didn’t go into the Coop to see what it’s like these days.) I’d be willing to believe that the square is declining, but I’d also be willing to believe that it’s at a steady state.
  • And Schoenhof’s is still open. I broke my rule and bought several books that I don’t plan to read immediately, that indeed it’s not completely clear that I’ll ever read. But I was just so happy that the store is there! One book on learning kanji that I actually have started, a general Japanese grammar, and small individual books on verbs, particles, and connections (“Making your Japanese Flow”.)
  • Grammar and verbs are pretty basic concepts, but I like the ideas of books on particles and connections. I was going to say that those seemed like “only for Japanese” sorts of things, but of course there’s The Greek Particles.
  • We went to a couple of old favorite restaurants. The food at Chez Henri is still good, but the waitress we had drove me crazy. When I go out to eat, I do so for exactly two reasons: the food and the company of people I’m eating with. The waitress apparently thought that I had several other goals for the evening, prioritizing (among other things) her comedy routine above, say, getting us dessert menus. I am pleased to say, however, that the Elephant Walk still has both excellent food and excellent service. (Though it’s not that much better the food we make at home from their cookbook.)

Not sure when we’ll visit again, but I’m glad that we’ve managed to make it back every four years or so.

random links: july 28, 2007

July 28th, 2007

xml, html output

July 21st, 2007

My HTML output class is now at what I expect to be a reasonably stable state. It’s not by any means a perfect solution for the world’s HTML needs, but it can generate the output that I want without much excess typing, which is all that matters.

Actually, it divided into two classes this morning. First, XmlOutput:

  class XmlOutput
    def initialize(io)
      @io = io
      @indentation = 0
      @elements = []
    end

    def element(*element_and_attributes)
      if (block_given?)
        open_element(element_and_attributes)
        yield(self)
        close_element
      else
        write_indented_element(element_and_attributes)
      end
    end

    def inline_element(*element_and_attributes)
      "<#{element_and_attributes.join(" ")}>" +
        yield +
        "</#{element_and_attributes[0]}>"
    end

    def line
      if (block_given?)
        indent
        @io.write(yield)
      end

      @io.write("\n")
    end

    # FIXME (2007-07-21, carlton): Can I use define_method to
    # construct a method taking a block?
    def self.define_element(element, *attributes)
      module_eval element_def("element", element, attributes)
    end

    def self.define_inline_element(element, *attributes)
      module_eval element_def("inline_element", element, attributes)
    end

    def self.element_def(method, element, attributes)
      %Q{def #{element}(#{attr_args(attributes)} &block)
           #{method}("#{element}", #{attr_vals(attributes)} &block)
         end}
    end

    def self.attr_args(attributes)
      attributes.map { |attribute| attribute.to_s + "_arg, " }
    end

    def self.attr_vals(attributes)
      attributes.map do |attribute|
        '"' + attribute.to_s + '=\\"#{' + attribute.to_s + '_arg}\\"", '
      end
    end

    def write_indented_element(element_and_attributes)
      line { "<#{element_and_attributes.join(" ")} />" }
    end

    def open_element(element_and_attributes)
      line { "<#{element_and_attributes.join(" ")}>" }
      @indentation += 2
      @elements.push(element_and_attributes[0])
    end

    def close_element
      element = @elements.pop
      @indentation -= 2
      line { "</#{element}>" }
    end

    def indent
      @io.write(" " * @indentation)
    end
  end

I’ve given up on the whole public/protected/private distinction, for now: I don’t see much point in it for programming that I’m doing by myself. But I suppose it does have uses when explaining code to others: if you were to use the class directly, then you’d use element, inline_element, and line. The former is for an XML element that you deem important enough to put the opening and closing tags on their own lines (perhaps head and body for HTML); inline_element is for XML elements that you want to stick in the middle of lines (perhaps cite and a for HTML). And line is for text that you’re inserting, either passed as a string or generated via inline_element. They all take blocks, to either fill in the middle of the elements or the lines; two of them do something useful if not given a block, and the third could easily enough if I need that functionality. Oh, and the element functions have a crappy way of specifying attributes.

Which works well enough, but still requires more typing (in my case, manifesting itself as > 80 column lines) than would be ideal. Which is where the class functions define_element and define_inline_element goes in. Here’s HtmlOutput:

  class HtmlOutput < XmlOutput
    define_inline_element :a, :href

    define_inline_element :span, :class

    define_inline_element :li
    alias_method :inline_li, :li

    define_inline_element :title

    define_inline_element :h1
    define_inline_element :h2

    define_element :head
    define_element :body

    define_element :div, :id

    define_element :ul, :class
    alias_method :ul_class, :ul
    define_element :ul

    define_element :li

    define_element :link, :rel, :type, :href

    def html(&block)
      line { "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" }
      line { "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" }
      element("html", "xmlns=\"http://www.w3.org/1999/xhtml\"",
              "xml:lang=\"en\"", "lang=\"en\"", &block)
    end
  end

This lets me create methods corresponding to the elements that I care about. If those elements take attributes (as in <a href=...>, I pass them as extra arguments (define_inline_element :a, :href), and the generated methods take arguments that are the values for the attributes. So, if I want to generate the following:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
      <title>The Title</title>
      <link rel="stylesheet" type="text/css" href="styles.css" />
    </head>

    <body>
      <h1>Main Header</h1>
      <ul>
        <li><a href="http://site/page/">link text</a></li>
      </ul>
    </body>
  </html>

  o.html do
    o.head do
      o.line { o.title { "The Title" } }
      o.link("stylesheet", "text/css", "styles.css")
    end

    o.line

    o.body do
      o.line { o.h1 { "Main Header" } }
      o.ul do
        o.line do
          o.inline_li do
            o.a("http://site/page/") { "link text" }
          end
        end
      end
    end
  end

Admittedly, this isn’t the eighth wonder of the world or anything, but I do think the interface will work pretty well for the specific uses that I have in mind. Or maybe not – I read the relevant chapter in the Pickaxe book this morning; they describe a library with an interface basically identical to what I ended up with, but then comment that people almost never use it, typically preferring to use some sort of HTML template with embedded Ruby instead. And maybe I’ll switch to a solution like that as I get more used to the area.

However that turns out, there are two bits that I want to talk about. One is what I discussed in my previous post, that it was a lot of fun starting with a complex bit of output and refactoring my way into a class that generated it. I won’t yet propose that as the way to go in all situations, and I’m not even sure it actively helped me here: if I’d started out wanting to build up a solution from scratch instead of decompose one out of a monolithic print statement, I don’t see any reason to believe it would have turned out differently or gone any slower. But it was a very pleasant way to develop code, I’m confident it didn’t slow me down at all, and I only spent about 10 minutes of development time wondering what was the best thing to do next. If nothing else, it will give me further motivation to write my acceptance tests early: currently, I have them in mind from the start of a task, but I don’t usually actually write them until the code that they’re testing is finished. That delay isn’t usually for any good reason, it’s simply because I don’t yet like writing acceptance tests as much as I like doing other things, but if I can start to see real effects out of writing the acceptance tests earlier, I’d probably switch to doing so. (It would help if I started using Fit, too; for now, though, I’m not convinced I’m working in areas where that is an obvious win.)

The second bit I want to emphasize is that I love the way the definition of HtmlOutput looks. This is the second time in this project that I’ve done something like that: there’s a base class that implements class functions designed to let you provide functionality in a subclass without writing explicit method definitions in that subclass! Much more fun than sticking in protected hooks here and there, and when it works the subclass definitions are dramatically shorter (and freer of boilerplate repetition) than they would be if I were, say, programming in Java. As the FIXME comment shows, I’m not entirely comfortable with the implementation in this particular case, and now that I think about it, I’m not entirely comfortable with my implementation in the other case as well, but the fact that I can do it at all pleases me greatly.

So: I can generate one particular piece of HTML. Now I just have to have that HTML vary based on the contents of a database. Shouldn’t be too hard; I hope I’ll find a few more ways in which the implementation improves upon its Java counterpart.

generating html output

July 20th, 2007

One decision that I had to make when doing the HTML output part of my book database: should I roll my own HTML generator, or use somebody else’s? I ended up going the ‘roll my own’ route, partly because it sounded like more fun, and partly because it would be easier to get the acceptance tests working.

As written, the acceptance tests do a strict textual comparison, and it seemed unlikely that it would be easy to find another library that would generate code indented exactly the way I want. Admittedly, that’s a sign that the acceptance tests are overly strict, so the right thing to do would be to find a way to relax that validation, and in fact I think I already have code for that around. (I use it when validating that my output is legal XHTML.) But that combined with laziness and a desire for fun was enough to sway me.

And it has been fun! I started out with one unit test that checks for the output of a page for an author who hasn’t written any books. The easiest way to get that to work was to hardcode the expected output. So, at this point, my implementation was a function that spit out a really long string.

And then it was time to start refactoring. A single long string is hard to work with, so I broke it up into separate functions for the different parts of the page. Which, actually, I haven’t done much with; it will help me in the future, though. But next came a series of more immediately useful refactorings:

  • I had the output function generate an array of lines instead of a single multiline string.
  • I noticed that the lines in the arrays almost all started with whitespace, so I added another argument which is an amount of whitespace to add to all the lines in the array.
  • The indentation changes in predictable ways: so, rather than pass in “indent 6” here and “indent 8” later on, I had the HtmlOutput class have a member variable with the current indentation, and provided open and close member functions which added or subctracted 2 from the indentation level.
  • The adding and subtracting happen in conjunction with text, so let’s pass that text in as an argument to open and close
  • The opening and closing text consists of opening and closing tags: so let’s keep a stack of the elements that are in the current scope, and have close generate the closing tag automatically. (And provide a way to pass in attributes to the opening tag.)
  • Having to explicitly type open/close pairs violates my RIAA instincts; in Ruby land, that means that we should just have an element functions which generates the tags itself, and which takes a block as an argument to fill in the middle.
  • But what about element with no body, where the opening tag is the closing tag? No problem: I just won’t pass in a block there, and element can alter its behavior based on block_given?.

That’s where I am now. The next step is to handle elements that I put in the middle of a line (<cite>, <a>, etc.); I think I have a scheme that will work for that, but we’ll see where the refactorings lead me.

I’ve never programmed this way before, refactoring a class into existence based solely on a complicated chunk of expected output. I highly recommend the experience; it’s lots of fun, and has a rather unusual flavor. I’m being good and adding unit tests for all the methods I create; the thing is, though, that each method seems to last for about half an hour before it and its unit test get refactored out of existence, replaced by the next refactoring! For the longest, time, the HtmlOutput tests consisted of two tests, one of which was the result of the previous step of my refactoring and the other of which was the next step in my refactoring, which I was in the process of converting the existing AuthorPrinter object (the user of HtmlOutput) into using. Recently, though, more tests have been coming into existence, which I hope is a sign that I’m settling into a more useable and powerful interface.

My only regret was that I did most of this refactoring without an internet connection, so I couldn’t check all of the intermediate steps into my Subversion repository, and get a good view of the differences between steps. All well; maybe I’ll switch over to a more distributed version control system for my next project.

jason kendall

July 16th, 2007

I see we managed to foist Jason Kendall off on the Cubs. About time: not only is he blocking an actual prospect (Kurt Suzuki), his OPS is currently the worst in the majors by a full 40 points. He may have hit twice as many home runs this year as the last two years combined, but when that brings his total of Oakland home runs to 3, it’s not saying much.

I applauded the trade where we acquired him. I was wrong.

ipod, car, shuffle

July 15th, 2007

I’ve been using a radio adapter to play my iPod in my car for the last year. Which works well enough, and is unbelievably better than having to rely on the radio or CDs to listen to music, but has its downsides. There aren’t a lot of holes in the radio spectrum around here; I’ve found one or two that work acceptably on the commute to work, but even so I get more static than I’d like. And if I venture up to, say, San Francisco, the radio holes change, so I have to either give up or try to find a different place in the spectrum to broadcast.

By now, the value of this experiment has clearly proven itself, so I figured that I’d see if I could get my radio modified to have some sort of direct connection. Which turned out to be really easy in this case: the radio is designed to accept an external CD changer, and the mechanism that that uses turns out to be fairly general, so you can plug iPod adapters in there, too. Cost about 60 bucks, which is fine; a lot cheaper than buying a whole new radio just to get an extra jack.

It took two tries to get it right. The first time, they installed a unit that had the iPod controlled through the radio itself; maybe this would have been fine if I’d had a more flexible radio with a better screen, but it would have made the device almost completely useless in my scenario: I’m not sure there was even a way to switch from an episode of one podcast to an episode of a different podcast. Fortunately, I realized the problem before I left the lot; they were very good about straightening things out and installing what I really wanted once we realized we’d miscommunicated.

Actually, I’m not entirely sure if it’s what I really wanted: I still have a proprietary iPod connection coming out of my radio, and I feel a bit guilty about not sticking with open standards. The thing is, though, I’d need a proprietary dock connector somewhere, or else accept an inferior signal out of the earphone jack. And it turns out that what they installed is a two-part system, where there’s something connecting the radio to a pair of standard RCA jacks (or its moral equivalent) and a second gizmo that goes from the RCA jacks to my iPod (plus a power line to charge the iPod, which is nice but no big deal). So the non-proprietary part turns out to be nicely modularized: you can’t tell that from the outside, but there’s a nice standards-compliant bit hidden inside.

While I am talking about iPods: I don’t believe I’ve blogged about the virtue of shuffle play. I hadn’t gotten around to giving that a try for a while: I didn’t think I’d particularly like it more than any other way of listening to the iPod, and I was a bit worried about how it would interact with podcasts and with classical music. But when my Mac went in for repairs earlier this year, I had no way to update my podcasts; the repairs took longer than expected, so I ran out of saved episodes, and decided to give shuffle mode a try instead of listening to albums again. And it’s great!

My fears turned out to be unfounded. Podcasts don’t get thrown into the mix, which is clearly the right thing to do. A nice bit of design: it would have been easy to treat podcasts like any other music, just with a special tag (i.e. something could be “rock”, “classical”, “podcast”, etc.), but in fact they treat podcasts differently. This is one example; syncing rules are another; the “listened to” mark is a third.

And, as far as classical music goes, when I started doing this, the only classical music I had on the podcast was some Schumann lieder, both Glenn Gould recordings of the Goldbergs, and the Glenn Gould recordings of both WTC volumes. And all of that shuffled just as well as pop songs – I kind of wish that a prelude and its corresponding fugue got played together, but it’s not that big a deal. And I’ve even learned something: to my embarrassment, I couldn’t reliably tell whether a piece was a Goldberg variation or one of the preludes, but I’ve gotten much better now at distinguishing the two. I’ve since put more classical music on the iPod; it works fine.

Having said that, I doubt that, say, symphonies would work very well. Certainly the choice of track markers makes a difference: I have a CD of Peter Maxwell Davies’s Eight Songs for a Mad King and Miss Donnithorne’s Maggot, which puts that on two thirty-minute tracks. (As opposed to, say, splitting the first work into eight tracks.) When we ran into one of those on shuffle mode, it rather put a damper on the trip; we ended up hitting the next button to skip to the next piece in the shuffle, and I took them off the iPod when I got home. No big deal, really; if I’d really wanted to have those on my iPod, occasionally hitting ‘next’ wouldn’t have been a serious sacrifice.

On a similar “track placement” note, there are a few talking + singing CDs I own (Flanders and Swann, Arlo Guthrie and Pete Seeger) where each track is “song + subsequent talking” instead of “talking + subsequent song”, even though the talking always relates to the song after it instead of the song before it. Fortunately, I’ve listened to those CDs a zillion times so I know what they’re talking about anyways, and they’re entertaining enough speakers that I don’t mind hearing talking that isn’t connected to a song I’m about to hear.

So my concerns turned out not to be a problem in practice. And the benefits were real:

  • It got me listening to some of my old friends again.

Before this, if I wanted to listen to a piece of music from my library, I had to actively decide to do so, which usually meant actively deciding that I wanted to take the time to listen to a whole album. No problem for long drives; not something that I was finding time to do on my relatively short commute.

  • It’s something that everybody can agree with.

The rest of the family doesn’t want to listen to my podcasts; and if I ask Miranda what she feels like listening to, she’ll normally pick one of a handful of albums, most of which I don’t mind (in fact, Philadelphia Chickens is stunning) but which I also don’t want a steady diet of. But she’s happy to listen to most of my music, even though she doesn’t ask for it herself (perhaps because she doesn’t know what all is on there). Because of shuffle mode, she’s even turned into a bit of a Charlotte Martin fan, and our running into a couple of songs from Striking 12 in close succession got her asking to hear all of that album, which is now sitting in the CD player in her room.

  • It fits into gaps in my commute.

Occasionally, for example, I’ll be finishing up a podcast episode as I get off of the highway. I still have six or seven minutes until I get home, which probably isn’t enough for me to want to start another podcast. But shuffle play fits the gap nicely: I can go to shuffle mode and listen to a couple of songs over the course of the rest of my drive.

  • It’s a non-inventory buffer against variance.

I occasionally run out of podcast episodes to listen to. (Well, other than JapanesePod101 episodes, but I don’t want to overdose on that.) If I were to increase the number of podcasts that I listen to in order to minimize the chance of that happening, however, my queue of unlistened-to episodes would quickly grow out of control. But I couldn’t possibly consider driving or jogging without something to listen to; listening to the radio or manually selecting albums are both possibilities, but shuffle mode works a lot better.

Don’t get me wrong: I still mainly listen to podcasts, and I’m certainly not about to buy a shuffle-only iPod. And I’m not going to wax rhapsodic about insights from unexpected juxtapositions: it’s all music that I like to listen to individually, and am happy enough to listen to in any order, but there’s nothing deeper than that. But shuffle mode is great; if you have an iPod, find yourself in situations where you have 5-30 minutes to listen to it, and haven’t given shuffle mode a try, then I encourage you to do so.