[ Content | Sidebar ]

google reader

November 28th, 2005

I started playing around with Google Reader over the weekend, and I think I’m going to stick with it as my RSS reader. I don’t have any reason to believe that it’s better than other web sites for that purpose, but it’s good enough for me, and is a significantly better RSS reader than Gnus, which is what really counts for me. In particular:

  • It understands Atom. There are a couple of blogs out there that I like that only provide Atom feeds; sensible people are convinced it’s the way to go, so who am I to argue?
  • Gnus has a per-feed cost: different feeds show up as different groups but without the number of messages shown, so I have to enter each one to see if it has any new messages. This discourages me from subscribing to blogs that only get added to, say, once a month, which is bad.
  • Gnus has to download the feeds each time I use it, which takes a while; Google operates out of cache.
  • In Gnus, I have to click on a link to see the entry in a web browser; the entries frequently look just fine the way Google displays them, and if they don’t, I can bring up the original just by typing a key, with no mouse usage required.

Having said that, Google reader needs some polishing. (No surprise; they don’t claim otherwise.) Some examples:

  • When I went through my initial orgy of subscribing, Google sometimes wasn’t able to carry out my requests. It told me to try again in 30 seconds, which didn’t work; trying again in a few hours did.
  • Its search functionality is surprisingly bad: for several of the blogs that I’d already subscribed to, I ended up having to type in the feed address by hand instead of finding it through the search engine. (Though the flip side is that it did know about feeds for some blogs whose feeds aren’t listed on the blogs’ main pages…)
  • I don’t like the way it presents new articles. For one thing, if you go to it when there’s one new article to read, then the left column makes it look like you’ve read all the articles. So it would be nice if it only cleared the “article read” mark after you had moved off the article in question, instead of when you select the article. For another thing, if there are a bunch of unread articles, it starts you off at the newest instead of the oldest.
  • It claims that a couple of the blogs I read have no articles in them. I was going to say that I’ll be curious if new items from those blogs show up, but I just checked: one new item has been posted to one of those blogs, and it didn’t show up. Oops. For all I know, the RSS feeds may be malformed, though.

At first, I wasn’t sure I liked the way it handled starred items – they easily get buried in the list on the left – but now I’m fine with having to click on the “Starred” link.

One question: do I ultimately want my feed reader to be built into my browser or a separate web site? The former has the advantage of being able to read feeds that aren’t on the global internet; the latter has the advantages of fast startup and accessibility from multiple computers. (The latter of which I used over the weekend, since I spent some amount of time in (gulp) Windows XP, downloading podcasts via iTunes.) For now, the question is academic: I would prefer to stick with Galeon, which doesn’t have a feed reader. I will try to avoid giving in to the temptation of using Google Reader at work…

book index

November 28th, 2005

I added a book index. Pretty straightforward cutting and pasting, followed by some refactoring.

The refactoring was a little different from normal. For one thing, it was my first experiment with writing generic classes in Java. (I’d written a generic function before, but not a generic class.) I learned a little more about what you can and can’t do; it turns out that you can’t construct objects of a type given by a generic parameter (not surprising – you don’t even know what arguments the constructor will take, if any) or check if a type is an instanceof a generic parameter (doesn’t work because of type erasure – they need to provide a single implementation, basically, and the implementation wouldn’t work if you replaced the parameter by Object). Too bad, though, since my code would have been a little shorter if I’d been able to use those features.

For another thing, I made more mistakes than normal. I’ve avoided learning to use a Java debugger so far; with TDD it’s rarely necessary. But I did make one mistake that took me a while to figure out; I ended up undoing some refactorings, redoing them, and using printfs, but it would have been a lot faster if I’d gone into a debugger. So next time this happens, I really should learn how to use one. (My problem was that I was doing something complicated in a constructor before the object was fully initialized; I should know better than that. It’s always hard to find the right balance when writing a class that basically exists to calculate a single value, though: what goes in the constructor, what goes in the other member function?) And then I ran into a bug that my acceptance tests caught that had slipped through my unit tests, and of course I wasn’t sure when I’d last run the acceptance tests, so I didn’t know when I’d introduced the bug. Fortunately, I found the bug after thinking about it for just a couple of minutes, but I was starting to regret that I wasn’t regularly saving the output of svn diff on my source tree, like I do at work.

And getting the balance of the classes just right, and figuring out which should be nested classes and which wouldn’t, took a while. I like what I ended up with, though; in fact, it was a strange refactoring in that it didn’t save me many, if any, lines of code, but it did clarify the code nicely. So the next time I implement an index, it will only be three or five lines shorter than it would have otherwise been, but I’ll know exactly what I need to type.

I also used the new code to help me generate the list of books by an author. It turns out (I’d realized this a week ago) that that code had a bug in it: if I had two books with the same name by the same author, they would have only shown up once. Which would sound a bit far-fetched, except that books in the database largely represent physical objects; so if I wanted to enter both of my copies of Delany’s The Mad Man in the database, they wouldn’t have both shown up everywhere. But now they will! The same bug still exists in a couple of other ways: multiple series with the same title, mutiple volumes in a series with the same number. There, it’s not so clear to me how to come up with realistic examples, so I’m not worrying about it for now. It’ll probably all get naturally fixed when I move to an SQL representation of the database, anyways.

esteban loiza

November 28th, 2005

Esteban Freaking Loaiza? A 33-year-old pitcher for three years at more than 7 million dollars a year? Was he as good as any member of the A’s starting rotation last year? Sigh…

more html explorations

November 26th, 2005

I recently lamented the design that I came up with for outputting HTML: I was combining a class accumulating HTML together with static methods that spit it out as text, leading to an unhappy marriage that I thought I knew how to deal with in C++ but couldn’t in Java.

As I said at the end of that post, though, I thought that I could come up with a reasonably elegant solution using functor classes. And thinking about it more before going to sleep earlier this week convinced me that that should work. So I tried it.

I got halfway through implementing it, though, and it just didn’t seem like it was going well. So I svn reverted, and am leaving things as is for the time being. (Nice to have a source control system that makes it easy to discard abortive experiments.) I did learn something from the experiment, though: I realized that the functor classes that I was building up was really an ungainly representation of the HTML tree. So the new solution was, in a weird way, actually moving away from the accumulating parameter solution: I wasn’t spitting out any HTML until I’d created a big, fat parse tree. It was, ultimately, a lot more like the static string solution: a bit more structure, perhaps, but the structure wasn’t easy to get at.

Which suggests yet another solution: I should separate the presentation of the HTML from its structure. So (given that there’s no performance reason that I need to spit out a textual representation of the HTML as we go), I should have static functions that, instead of returning a string representation of the HTML, return an abstract tree representation. And then I should have a Visitor that turns it into text, doing whatever prettifying it wants (indenting, turning relative links to absolute ones, etc.) at the same time. And there could be other Visitors for the parse structure – e.g. I generate a header and a title that look the same, except that the title can’t have HTML in it, so I could have a remove-elements Visitor that traverses the header to produce the title.

But that’s all a long ways off, and I may never end up doing it; I think I understand the situation well enough that it’s not bothering me any more, so until a story comes along that provides an external motivation for this split, I’ll leave well enough alone.

health

November 26th, 2005

I just got back from jogging, for the first time in about three months. Quite a three months it has been; I can’t remember whether the first cold or the massive lice invasion came first, but both started with Miranda and were passed to Liesl and me in short order. Then Miranda came down with what we thought was another cold; when Liesl got it, it seemed more serious, keeping her home from work for much of a week (and putting a dent in our lice removal activities); when I got it, it was clearly a full-blown flu. (Doubtless it was clear to Liesl earlier that she had the flu; it’s easier to tell from the inside.)

Fortunately, the lice was in remission, because I was in no shape to help with its removal (or, for that matter, to have my hair combed: staying vertical for showers didn’t sound too smart). Then I got better, then I got dramatically worse, then it turned out I had pneumonia. I missed three weeks of work, and wasn’t up to near full strength for another four weeks. During this time, we also discovered that we hadn’t gotten rid of all the lice, so we went through another couple weeks of treatments (trying different chemicals this time).

But now I feel decent – I can imagine feeling a little better, but I don’t need much imagination to know that I could be a lot worse. There’s a strange wheeze at the end of my cough that wasn’t there before; if it doesn’t go away soon, I might go back to the doctor, but I’m not too worried for the time being. I think we’ve gotten rid of all the lice; we looked over Miranda’s hair the other day and found four eggs, but our optimistic theory is that they all contain dead lice. We shall see.

The extended family has a ways to go: I really hope the doctors can find something that will help my brother, because he’s not having much fun right now.

we love katamari

November 25th, 2005

We ♥ Katamari is a sequel to the excellent Katamari Damacy. (I have finally given up and started spelling the second word the same way as its US publisher.) And it is everything that you’d expect from a sequel: quite good, several minor improvements, slightly worse in many ways (largely but not entirely because of the lack of novelty).

They kept the same basic gameplay, of course. And, like the original, there are core levels where you’re trying to get large enough within a time limit, as well as other levels where you have some special rules (the most common of which is that what counts is the number of items of a specific kind).

This time, they’ve added a few new special rules, some of which are kind of fun as a lark (e.g. the one where you’re on a race track and never stop moving) and some of which are annoying (the one where you’re on fire and, if you don’t pick up anything for a certain length of time, you lose). Almost all of the levels come in an easier and harder version, which is good; the main levels also come with a “double your size in a short amount of time” variant, which is bad (see below). They increased the number of places to roll in, which is good; there are only five core levels instead of the fifteen in the original, which is bad. And there’s no way to unlock an unlimited-time variant of the levels, which is bad.

Basically, they broadened the range of options, at the expense of underemphasizing the core gameplay. And, ultimately, I like rolling around well-designed levels, getting really big, and while I don’t mind a reasonable time limit, that’s not the most important thing to me. So what I want the most is the old core gameplay, where you get used to certain environments, being gradually allowed to explore larger and larger areas for longer and longer times, and where you ultimately get to unlike an unlimited time variant. So I’d trade all of the extra variants in the sequel for more and better core levels.

The cut scenes are perhaps even more pleasantly bizarre.

And then there’s the music. The original had an incredibly catchy theme, reused in many ways, with some other quite nice pieces thrown into the mix. Hard to top; it remains the only video game CD that I’ve bought. And of course it’s impossible for the sequel to live up to that, simply because it will keep the same theme instead of trying (and almost inevitably failing) to come up with a new, incredibly catchy theme. Having said that, the music is solid, and Liesl and I are big, big fans of Everlasting Love. Which might be better than any song from the original, and might (I’m not sure yet) be enough to get me to buy the CD for the sequel, too.

All in all, still a quite good game, and I’ll be happy to go another round of sequel. But I hope they emphasize the core gameplay more next time.

conservative bloggers

November 25th, 2005

I hear about these conservative bloggers, but I almost never run across them. The one exception is Uncle Bob, who posts on the Object Mentor blog; I read that for the software development insights (and Uncle Bob knows much more about that than I do, believe me), but Uncle Bob also posts on politics there. (Which are easy to avoid from the URLs, should you so desire.)

Interesting to dip into occasionally, though I wouldn’t want to do so very often. The most recent post to catch my eye: Lies, Damn Lies, and Democrats. “The notion that the President purposely misled congress by manipulating intelligence is ridiculous and specious.” Hmm; can’t say that I agree with you there. “Congress had access to the same information that the President did.” Well, no: Congress doesn’t have the same access to intelligence agencies that the President does, and it certainly doesn’t have the same ability to influence intelligence agencies to spin their results. And it’s not like the President enthusiastically shares information: he puts out only that information that suits his purpose. Having said that, it’s hard to argue with “Congress voted for the war, and enthusiastically agreed with the mission.” Despite the president’s best efforts, Congress had enough information at the time to strongly suspect that going to war was a bad idea. Democrats still have a lot to apologize for on that front. (And many others, but that’s a separate blog post.)

One of his earlier posts, Are Agile Methods Leftist, complains against a facile linking of software development methods with politics, and rightly so. Having said that, some aspects of agile methodologies could be used in other fields, should you choose to do so. I don’t know enough about planning for the Iraq conquest to be able to divide it up into a sequence of timeboxed iterations/releases, with specific goals linked to acceptance tests. I guess the first iteration would have been to conquer Iraq, the acceptance test being that Saddam Hussein is overthrown. And we did that, and did it faster than I thought we would.

Now we’re in the middle of a sequence of iterations; the acceptance test there is for Iraq to be a self-governing democracy. I’ll admit up front that I think the notion of imposing democracy at the point of a gun barrel is self-contradictory; having said that, my understanding is that we basically did just that in a few countries after WWII, quite successfully, and I certainly applaud the goal of a democratic Iraq.

But: agile methods tell us to timebox our iterations; and if it looks like getting the desired results is unexpectedly difficult, then the customer should take that new information into account, and may change the plans if desired. So when I see the government constantly saying things like “we’ve turned the corner”, making claims that we’ve achieved milestones that, in retrospect, seem hollow, forcing semblances of democratic events to happen without substance behind them, and overriding the judgment of military and intelligence professionals, it doesn’t sound to me like a way to run a project of any sort. If that were a software project, it would be one of the ones that was “95% done” for years on end, with the programmers driven at the lash to meet unrealistic deadlines, and ultimately cancelled with nothing to show for it. (Other than its potentially ruinous cost, even in the software case; the costs in the war case are, of course, much higher.)

And his last paragraph:

We can not back down. We can not cut and run. We can not tell the enemy when we are leaving. And we can not play politics with this war.

The first two sentences sound to me like a customer shielding himself off from honest progress reports in a project. To the third sentence, I’ll just say that he has a different notion of “the enemy” than I do; while we are now the enemy of the Iraqi people, they shouldn’t be considered as our enemy, and if he thinks that we’re hurting Al Qaeda by staying in Iraq, he’s reading different news sources than I am. (Which is clearly the case.) And, as far as “play politics with this war” goes, the entire blog post is playing politics with the war, casting substantive disagreements solely in political terms! But apparently people with the wrong point of view are the only ones playing politics; people with the right point of view would never dream of such a thing, even as they directly politically attack their opponents…

rorty and latour, part two

November 25th, 2005

Something else Rorty and Latour have in common: they both answer their e-mail quite quickly. I got a short note from Rorty saying, among other things, that he particularly liked We Have Never Been Modern, and a longer note from Latour gently chiding me for completely misreading him. (“ah readers, readers…”)

Latour’s point (unless I’m misreading him again) is that he’s interested in objects, while Rorty is interested in people. He calls himself “a hard core realist”; as realists go, I’m not sure his view is entirely mainstream, but never mind that. And he really didn’t like my uses of “belief” and “conversation”, saying that Iconoclash is against belief, and “this one [Politics of Nature?] entirely against conversation”.

So I think that my view of Latour must have been tainted by my recent reading of Rorty. Having said that, I’m still having a hard time seeing them as quite as different as that – both of them argue against Platonic notions of idealism, and I’m not sure that Rorty’s conversations leading to constantly-changing webs of beliefs are so different from Latour’s networks of (among other things) propositions whose value gets revisited over and over again. I should clearly go back and take another look at Latour’s collectives (including both human and nonhuman members), though. If nothing else, I still can’t remember how Politics of Nature could be seen as “entirely against conversation”.

what i’m reading: the css spec

November 22nd, 2005

If you look at my recently read page, you’ll now see what I’m in the middle of. Which took about 5 minutes to implement.

My internet explorer problems are an IE bug: the fifth item in the list of rules in the CSS spec on float positioning says that “The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.” Which IE is violating.

I’m tentatively leaning towards giving up on using a definition list, replacing it with an unordered list that I tell the browser not to style with bullet points, and enclosing the fields in a span which I style with boldface. We’ll see. I should really get my tests in shape to not require huge amount of typing if I do HTML changes like that. (Well, a fair amount of typing, aided by Emacs keyboard macros.)

rorty and latour

November 22nd, 2005

I’ve been reading Rorty’s Objectivity, Relativism, and Truth, and he reminds me a lot of Bruno Latour, especially his We Have Never Been Modern and Politics of Nature. Both of them, as far as I can tell, see statements about science having a special direct relationship with reality as, at best, not adding anything to arguments, and, at worst, unhelpfully polemical. In contrast, both of them very much appreciate claims that we should pay attention to scientists because of the predictive value of their statements and because of the new products that they enable us to make. Also, both of them like to emphasize the role of conversations and changing webs of thoughts when discussing truth.

I haven’t seen either of them discuss the other, though. It’s not so strange that I haven’t seen Rorty discuss Latour, since the papers I’ve been reading were written just when Latour was first publishing, but the lack of the references in the other direction seems to me to be a bit odd. They’re both alive; maybe I should e-mail them to see what they think of each other.

They’re also both quite pleasant to read, as far as philosophers go; I was already pretty convinced by Latour, and Rorty has added to those convictions. I’m wondering what other philosophers I should be reading, and what other themes; I’m kind of tired of bouncing off of recent French philosophers, and I don’t feel compelled to follow epistemology any further. Any recommendations in, say, moral or political philosophy?

internet explorer css problems

November 21st, 2005

I did some more cross-browser testing; it turns out that my pages look like crap under Internet Explorer, and probably have for a while. Specifically, on the book card section of the page, the headers (Title:, Author:, etc.) look fine, but all the values are lined up horizontally in a row. I suspect it’s also interpreting some of the CSS I added yesterday differently as well, but the problems there are less severe.

Safari agrees with Firefox/Galeon, so it’s probably a bug in IE’s CSS. Which, apparently, isn’t uncommon, though all browsers have CSS bugs; it’s certainly conceivable that my CSS is wrong and that I’ve gotten lucky. I’ll have to look at the spec some more. Or maybe there’s something else – e.g. maybe IE has a default stylesheet that is being correctly interpreted (together with mine) to lead to the behavior I’m seeing, so perhaps I’d get the behavior I want if I can figure out what to override.

If anybody has any insights, here’s the relevant bits:

dl {
  float: left;
  width: 100%;
}
dt {
  float: left;
  clear: left;
  width: 100px;
  font-weight: bold;
}
dd {
  float: left;
  margin-left: 0;
  margin-bottom: 2px;
}

So the dt bits are being lined up vertically as expected, but IE thinks that the dd entries can all be placed on one line. And it’s not clear to me that that’s crazy: there’s no clear attribute there, after all.

It’s not clear what the next course of action is. It’s certainly unfortunate; on the other hand, realistically I’m the main person who looks at those pages, and I suspect that you, my beloved audience, are heavily Firefox-weighted as well. So I’m not sure that doing something about this is urgent. If I decided it’s worth changing, I can presumably generate and style CSS that doesn’t suffer this problem, but I’ve grown attached to my dl usage.

I will mull it over.

sidebar

November 20th, 2005

My pages now have sidebars. And are a bit more colorful. Yay.

It didn’t turn out the way I envisioned. At first, I was planning for there to be a darker color (grey, which turned into pink) across the top and left, and for there to be white not just in the data area but to its right and below it. I couldn’t figure out how to get that to work without using a background image, though, which I didn’t want to do. And I actually think the design that I ended up with is just as good as that would have been; as is, it’s sort of reminiscent of a card in a card catalog, which is a nice memory for people my age or older.

I also haven’t managed to control the positioning and spacing as well as I’d like. If you make your window narrower, you’ll notice that the links on the left get pushed down even while there’s still a fair amount of white space which could be compressed instead. And in my browser, the ‘dbcdb’ at the top and the links on the left have their left sides lined up, but that’s more or less by accident and fiddling with numbers; I doubt that will be true for other browsers.

So clearly I have more to learn about CSS, let alone about web design in general. Still, it’s an improvement over the extremely austere former design. Next, to start populating the list of links on the left…

2004 miranda pictures

November 19th, 2005

Most of you probably don’t care, but we’ve finally gotten around to putting up some 2004 pictures of Miranda. We don’t seem to have any 2003 pictures in digital form; some 2005 ones are coming eventually.

i miss destructors

November 19th, 2005

As threatened, I’ve extracted an HtmlWriter class. And certainly the code is an improvement, though there’s one thing about it I don’t like.

The class has a couple of core responsibilities: it knows how to close the currently open tag, and it knows how to indent. (One could argue that it’s a bit pointless to indent output intended for machines, of course.) So you can do something like this:

writer.open("body");
writer.open("p");
// Stick in more output.
writer.close();
writer.close();

and you’ll get output that looks like this:

<body>
  <p>
    // More output.
  </p>
</body>

Not rocket science, and it doesn’t even save you typing. But it does save you from counting spaces, and it clearly expresses what you’re doing.

This is fine for tags that live on a single line. But sometimes I don’t want to do that: e.g. I might want to create a line like this:

    <h1>Header</h1>

My first attempt at the corresponding code was as follows:

writer.indent();
writer.openInline("h1");
writer.print("Header");
writer.close();
writer.newline();

Which expresses what’s going on, I suppose, but it’s a lot of typing. And the first and last pairs of lines show up every time you wanted to generate output like this.

This might suggest creating a method on HtmlWriter as follows:

void printInlineElement(String element, String text) {
  indent();
  openInline(element);
  print(text);
  close();
  newline();
}

That works for the example above, but what if the text itself contains tags, as in this example:

    <h1><cite>Title</cite></h1>

We’d like all HTML tags to be generated by HtmlWriter, so we don’t want to pass in the literal string <cite>Title</cite> to printInline. But what are our other options?

One is to replace the second argument to printInline by some sort of class which has a method that to generate the text. (And that method can take the HtmlWriter as an argument.) Which is a pretty natural solution; in this instance, though, it’s really clunky to create a class on the fly when all you want to do is insert a relatively small amount of text. (Java’s anonymous classes help a bit, but not enough.) In a language with lambda, I might go this way, but not in Java.

What I ended up doing is leave printInline like above, but in addition to add static members to HtmlWriter to generate text with inline tags surrounding it. I picked this option because it was probably the simplest choice given the existing uses of HtmlWriter, but it sucks: in some places, HtmlWriter exists to accumulate HTML that you’re generating, while in other places it’s just some static functions to spit out HTML. One or the other is acceptable (though the former is preferable); both at the same time is wrong. (Not just aesthetically: it limits future possibilities, making it impossible to, say, have HtmlWriter automatically turn relative links into absolute ones, or do line wrapping, or anything else requiring state.)

If I were programming in C++, though, there would be a third, quite attractive solution. The methods open and close, or openInline and close, or indent and newline, are always designed to be called in pairs. So our C++ reflexes say: create classes whose constructor calls the first member of the pair, and whose destructor calls the second member of the pair. Which would leave us with code like this:

Line(writer);
InlineElement(writer, "h1");
// Code to generate whatever HTML we want; that code can generate text directly
// or call further methods on writer.

That’s much nicer; three lines of code instead of five, no loss of expressiveness, and it’s as flexible as you’d want. (I would probably further refactor those first two lines into a single line, but never mind that.)

But I am programming in Java instead of C++. Too bad. I do think that proponents of general garbage collection sometimes underestimate what they’re giving up (phrasing the discussion solely in terms of performance issues). If we accept that a language should provide (possibly optional) reference-counted garbage collection, then the question is whether it’s more useful to augment that with general garbage collection, or with destructors. Much of the time, I prefer the latter. And I look forward to future programming languages where I don’t have to make that choice.

(I was going to end the post there, but then I had more thoughts while walking the dogs. We already have a bigger picture available: it’s all about the ease of constructing function-like objects in various circumstances. You can even analyze the C++ case that way: the function-like object in question is the rest of the current block. So maybe you can do destructor-style programming pretty easily in languages without destructors but with lambda; and maybe in this situation, I should let people pass an appropriate function class to various methods, and also (for ease of use, so people aren’t creating anonymous classes all the time) provide some concrete classes for people to use, classes that do things like insert a bit of text or create an entity surrounding the output of a further functor class. Hmm. I guess I’ll try that and see how it works; should be fun, at least. But I should probably not let myself do that until I’ve implemented more functionality, to prevent myself from spending too much time refactoring.)

recently read books

November 13th, 2005

If you gaze upon the right side of this blog, you will now see a link to my list of recently read books.

This was a pretty interesting story to implement. XP encourages you to always do the simplest thing that will cause all your tests to pass; one of their key phrases in support of this is You Aren’t Going to Need It, abbreviated as YAGNI. The feeling is that, as long as you’re conscientious about refactoring constantly, you’ll be able to maintain a clean, extensible design at all times even without long-term planning.

One example of this is that, when I added the “Read” field, I represented the date as a string, since that was the simplest thing that could possibly work. I didn’t seriously think that YAGNI applied in that case – I was pretty sure I was going to want to eventually generate a list of recently read books, at which point I’d need to be able to sort by date – but I didn’t need it for that particular story.

But now I’ve had to write my Date class (I didn’t see any built-in classes that provided quite the functionality I needed). And doing it now instead of earlier has clearly turned out to be the right choice – while I haven’t saved any time overall (if I’d guessed at the Date interface back then, I probably would have gotten it right), it meant that I got to add the “Read” field faster than I would otherwise have been able to, which is good.

The story did, however, point out a more insteresting refactoring that it’s now time to do. When I started generating HTML pages, I thought about writing some sort of HtmlWriter class, to handle things like opening and closing elements, adding attributes to elements, indentation, etc. But I decided that it was overkill to do so at the time: all the HTML pages were for what I’m calling ‘entities’ (items in the database, such as authors, books, or series), so the structure all looked the same. And if I stuck the HTML generating code in my Entity class, I could use virtual functions to good effect to generate the HTML in a straightforward matter.

Now, however, I’m generating an HTML page that doesn’t correspond to an entity, namely the list of recently read books. Which results in a bit of code duplication; it’s not too serious yet, but it bothers me a little bit. I’m honestly not sure whether XP would have me pull out a full-fledged HtmlWriter now: the only other non-entity pages on the radar screen are other indices of various sorts (lists of authors sorted by name, books sorted by title, etc.), so maybe the simplest design would be to have an Index base class that knows how to generate HTML for indices, just like Entity knows how to generate HTML for entities, and leave it at that. But I think the current Entity class already has a mixture of responsibilities (both storing entity-related data and writing out HTML); having two classes like that, with one of their responsibilities shared, wouldn’t leave a good taste in my mouth. And XP likes your classes to have a single responsibility, and to clearly express that responsibility. So I think now is the time to pull out an HtmlWriter class.

Here, unlike the date example, YAGNI does apply: the HtmlWriter that I’m going to pull out is going to be the simplest such class to let me generate the pages in question, and won’t have all of the features that I’d earlier envisioned. And having two concrete, distinct places where I’m going to use it will help clarify its class interface enormously.

Also, having this HtmlWriter class will have other benefits. For example, I’d been thinking that it would be a good idea for my internal links to be absolute instead of relative; I’ll have to do that eventually if I decide to provide multiple ways to access single page from different locations within a directory hierarchy. (E.g. the Walter Benjamin page might be accessible both via dbcdb/1 and via dbcdb/author/walter-benjamin.) And implementing that will take five minutes once I’ve refactored out HtmlWriter: I’ll add a link prefix to the constructor and tell its openLink method (or whatever it will be called) to stick that prefix at the start of the href. (And at the start of the stylesheet link, too.) Simple.

A couple more potential refactorings made themselves known during this story, too. I have a Collection class that keep tracks of entities; it also currently knows how to write out the HTML files corresponding to the entites in the database. Which was fine when doing so was a simple loop over all entities, constructing a file name for each one and telling it to write itself to that file.

But now there’s an extra step, generating the page of recently read books. At this point, I have two methods that are more presentational, and they could both be written using Collection’s public interface. So it’s time to split out that functionality to a different class, CollectionWriter. And that class will be even more useful in the future, both when I add more indices and when I change the database storage method to use a SQL database instead of a Java file. (The latter change will probably require further refactorings, but never mind that.) I’ll probably do that refactoring now – after all, CollectionWriter will need to know about HtmlWriter while Collection won’t, so the split goes with my HtmlWriter refactoring. (Plus, it will take something like two minutes – I just have to move a handful methods to a new class and their tests to a new test class.)

And, having written the code to generate the a sorted list of recently read books (which took more steps than I expected to get right), I can see how that code will get generalized to handle other fields. Basically, I want to go through all entities of a certain type (Book, Author, whatever), and sort them by some field on that type (date, title, name). And I should be able to write some generic code to do that. Which I will do. But some other day; that can wait until I generate another index, at which point I’ll have two examples to work from and refactor out the common code.

It’s a joy to work like this; on the one hand (men), the code is clean enough to be easy and pleasant to work with, while on the other hand (de), it’s pregnant with possibilities, with refactorings lurking under the surface that I know I can carry out if I need to. I think Michael Feathers said something along the lines that you shouldn’t try to have your code always express absolutely everything it could, you should just try to make sure that it’s one refactoring away from expressing anything latent in the code. Which is how I feel about this code, and is a good rule of thumb: YAGNI suggests that too much refactoring might be a waste, but if a story appears for which the refactoring is important, you want to be able to carry it out ASAP.

And now I have an excuse to delve into web design again: there are enough dbcdb-related links that I think I could begin to populate a sidebar on my generated pages. Which I would have to style appropriately. Fun!

ant aargh

November 12th, 2005

Okay, now I’m mad at ant: I just changed a method from public to private, a method which was called by other classes, and ant didn’t recompile all the affected files: I had to wait until I got an error at runtime. So either ant doesn’t do what it should, or something’s seriously wrong with my understanding of Java.

(Admittedly, the latter is a serious possibility.)

homework

November 12th, 2005

Last year, Miranda had a couple of pieces of homework each weekend: the red bookbag, where we were supposed to read some books to her and she was supposed to draw and write about them, and the yellow folder, where she was supposed to read to us. This year, the red bookbag continued, but the yellow folder turned blue and comes home most weekdays.

On the surface of it, this is reasonable enough – who could complain about having Miranda practice reading and writing at home? But the second night of the blue folder, we already ran into problems: the book was a little harder than her reading level, so while she could struggle through it with help, it took quite a while, and wasn’t something we’d want to go through every night. Fortunately, the next day was my classroom day (I got to meet the kindergartners in her class; fun), so I asked the teacher about it. The teacher said that she didn’t want it to be a big time sink – Miranda should either read the book three times or for 10-15 minutes, whichever comes first.

And 10 minutes an evening sounds pretty reasonable; who could complain about that? It turns out, though, that the answer is “I could”; here’s why.

We wake up around 6:45am. From 6:45 to 8am, we’re trying to get ourselves fed, dressed, showered, lunches packed, etc. Then we bring Miranda to school; she’s at school and daycare all day. We get home a little after 6; we have to walk the dogs, examine the mail, check answering machine messages, take tupperwares out of backpacks, etc., so assume it’s 6:15 by the time we’re done with all that.

Miranda starts getting ready to go to bed at 8:15. So, in a weekday, I have at most 2 hours of unrestricted free time to spend with my daughter. But it’s actually a lot less than that; for one thing, cooking and eating dinner take about an hour of that time. For another thing, I usually want to spend a little bit of time relaxing right when I get home, instead of playing with Miranda. And, for that matter, Miranda frequently wants to spend a little bit of time doing something, too. So 30 minutes a day is a more realistic estimate. (For weekdays; weekends are much better.)

And all of a sudden, taking 10 to 15 minutes a weekday to do homework looks flat out insane: who, in their right mind, given 30 minutes a day to spend just hanging out with their 6-year-old daughter, would give up half of that to homework? I for one am not willing to do so.

I’m sure that her teacher hasn’t worked through these numbers (she’s fresh out of school, for one thing). We have a parent teacher conference coming up, so I’ll talk to her about it, and it will doubtless be fine. And, even if it isn’t, this is a situation where we can simply say “no”. But it really scares me: for one thing, I doubt situations like this are at all uncommon, especially with the ratcheting up of “standards” that is infesting our country, and I can’t imagine that the results are good. And, for another thing, 30 minutes already sucks; I hadn’t realized the problem was so bad.

And school can already take some amount of blame for the latter. Of course, there’s only so much that can be done: Liesl and I are going to spend most of the day at work, so even if she didn’t go to school at all, she wouldn’t be hanging out with us. But if Miranda didn’t have to be at school right at 8:10 every day, then mornings could be a little more relaxed, bed time could be pushed back a bit, and bed time could be more flexible if we wanted to do something later in the evening some day.

Given the situation, I’m not even sure what the next step should be from a tactical point of view. At first I was considering asking that the blue folders be moved to weekends instead of weekdays, like last year, but, thinking about it, I think just working through the red bookbags is probably a bit more time than I’d ideally prefer to spend on homework even on weekends, though I’m willing to do so. So I’m leaning towards explaining that we simply won’t be doing the blue folders (at least regularly; Miranda may want to do them sometimes), and leaving it at that. Liesl and I will have to think about that before the conference.

ant and junit

November 12th, 2005

After getting ant to do my compiling, I decided to get it to run my unit tests. Which it can now do acceptably, though the path was a bit rockier than I would have liked. Some steps:

  • Copy down an example from a book, mutatis mutandem.
  • Hmm: ant says it doesn’t know about the junit task. Looks like it’s an optional task, so maybe it’s in a separate rpm? After not too much searching, yum install ant-junit does the trick. A bit annoying, except that I do approve of modular architectures and packaging that takes advantage of that.
  • But ant is using GCJ while my code needs Sun’s Java 1.5. I dealt with this for the compile step; let’s see if I can deal with this for the test step? Yes, not hard to do. But it can’t find the code – is ant not passing my CLASSPATH setting to it? I guess so; how do I fix it? Not directly obvious from any of the documentation that I was looking at, but not too hard to figure out.
  • But even if the tests fail, the task still passes. The book tells me what to do about that, and how to fix it. (And agrees that’s a design flaw.) Great; now everything seems to work.
  • Except that half an hour or so later, I notice that only two-thirds of my tests are being run. I thought I verified earlier that they were all being run? There is a failing test currently – could the haltonfailure attribute really cause the test run to stop after the first failure, not after all of them? That sure sounds like a design flaw to me – if a change causes multiple tests to fail, that’s useful information. There seems to be no attribute to use that gives the behavior I want; sigh. The book, however, in its explanation of why you normally don’t want a test failure to halt the junit task (because you might want a subsequent task to format the results attractively, and then fail) shows a trick that I can use: I’ll set a property instead of halting the task when a test fails, and then the next task will fail if that property is set. Which works great.

So now everything is working fine. I’m still not overwhelmingly impressed by ant, though I imagine most tools would present similar stumbling blocks when you first learn to use them. I’m happy with the results; if I were planning to stick with Java for the long haul, I’d change things still further (in particular I’d run the acceptance tests and installation from within ant), but as is I’ll stick with what I’ve got.

benefits of white shirts

November 12th, 2005

Miranda says: it’s good to wear a white shirt on Arts Focus days, because that way if it gets dirty and the stain won’t come out in the wash, it’s like a tie-dye shirt.

One way of looking at things, certainly.

rhyming

November 12th, 2005

The rhyming bit near the start of The Princess Bride is a nice throwaway touch.