Wednesday, August 13, 2008

Beautiful Code: What Is Beautiful Code?

This post is part of the Beautiful Code series.

No complex programming concepts in this post. Just a question: What is beautiful code? What makes code ugly? (And isn’t that a matter of opinion? Pshaw…) Most of the posts so far have been about beautiful ideas encapsulated in the programs, but what about the code itself?

This post is all over the place, so brace yourself for it.

Reusability

To start with, some thoughts from Adam Kolawa.

…. Code reuse significantly reduces the effort required for code development, testing, and maintenance. In fact, it is one of the best ways to increase developers’ productivity and reduce their stress. The problem is that reuse is typically difficult. Very often, code is so complicated and difficult to read that developers find it easier to rewrite code from scratch than to reuse somebody else’s code. Good design and clear, concise code are vital to promoting code reuse.

Unfortunately, much of the code written today falls short in this respect. Nowadays, most of the code written has an inheritance structure, which is encouraged in the hope that it will bring clarity to the code. However, I must admit that I’ve spent hours on end staring at a few lines of code…and still could not decipher what it was supposed to do. This is not beautiful code; it is bad code with a convoluted design. If you cannot tell what the code does by glancing at the naming conventions and several code lines, then the code is too complicated.

Beautiful code should be easy to understand. I hate reading code that was written to show off the developer’s knowledge of the language, and I shouldn’t need to go through 25 files before I can really understand what a piece of it is really doing. The code does not necessarily need to be commented, but its purpose should be explicit, and there should be no ambiguity in each operation. The problem with the new code being written today—especially in the C++ language—is that developers use so much inheritance and overloading that it’s almost impossible to tell what the code is really doing, why it’s doing it, and whether it’s correct. To figure this out, you need to understand all of the hierarchy of inheritance and overloading. If the operation is some kind of complicated overloaded operation, this code is not beautiful to me.

This is an interesting quote—one with which I both agree and disagree. I definitely agree that code which is difficult to understand is not beautiful; Kolawa uses reusability as a criterion for beauty, which I think is a good criterion to use. I also agree that if it takes a few hours to understand what a piece of code is doing, that code is not beautiful, and not reusable.

And I also agree that code written to show off the developer’s knowledge of the language is not beautiful. You might have a very good reason why you had to take advantage of some obscure feature of the language, but if your program is going to be at all maintainable, you’re going to have to comment it so well that you might have been better off finding another way to do it, that other programmers would understand more easily. Either that or you don’t actually care about maintainability; you might feel that people should have to spend hours going through the language reference guides, trying to decipher your code—which is arrogant—or you might just be worried about job security, for which I have no respect.

However, at the same time, this quote also seems to be a diatribe against object-oriented programming. It almost sounds curmudgeonly; “In my day, we didn’t have no object-oriented programmin’. We had miles and miles of procedural code, and that’s the way we liked it!” I agree with Kolawa’s main points, but I disagree that object-oriented programming in general, or C++ in specific, are to blame for bad code (if that’s what he’s saying). You can write clear, concise, object-oriented code, and you can write really terrible object-oriented code. Just as you can with procedural code. It’s true that you have to get your mind around object-oriented programming before object-oriented code is going to make sense to you, but that doesn’t make object-oriented programming bad, or even necessarily more difficult; it’s just a different way of thinking about code. (I can’t believe I’m typing this in 2008.)

On the next page, Kolawa had another quote that I also found interesting:

My next criterion for beautiful code is that you can tell that a lot of thought went into how the code will be running on the computer. What I’m trying to say is that beautiful code never forgets that it will be running on a computer, and that a computer has limitations. As I said earlier in this chapter, computers have limited speed, sometimes operate better on floating-point numbers or integer numbers, and have finite amounts of memory. Beautiful code must consider these limitations of reality. Quite often, people writing code assume that memory is infinite, computer speed is infinite, and so on. This is not beautiful code; it’s arrogant code. Beautiful code is frugal about things like memory use and reuses memory whenever possible.

I have mixed feelings about this quote, too. I find myself wanting to agree, and I do agree under certain conditions, but I also disagree under other conditions. There are cases where a developer should not worry about memory, should not try to optimize for particular CPU architectures, should not worry about the low-level details of a computer. (After all, computer science has been trying to abstract these concepts away almost since its inception.) Writing code in C++ that will run on a Windows desktop is much different from writing code in Java that will run on a J2EE application server.

But, to Kolawa’s point, using memory as an example, even if Java is supposed to abstract away details about memory cleanup, that doesn’t mean that Java code running on a J2EE server can use up as much memory as it wants. Just because some of the details are no longer important, you still have to put some thought into how much memory you’re allocating. Maybe loading up 10MB worth of data into a user’s session every time the user logs in to your web site is a really bad idea. The fact that Java will automatically garbage collect objects when they’re no longer used isn’t going to help you in this case, you’re just wastefully using up too much memory.

The Actual Source Code—The Seven Pillars

This is all well and good, but it’s still a bit too conceptual; what about the code itself? The semi-colons and the tabs and spaces and newlines? What makes that beautiful? Chapter 32 talked about that, based on an article by Christopher Seiwald called Seven Pillars of Pretty Code. I won’t bother to list all of the “pillars”, you can read the article if you wish, but some examples they gave are making code “bookish”, making alike look alike, and overcoming indentation.

“Bookish” Code

When they say making code bookish, they’re talking about a couple of things, which can be summed up by laying out your code the way that text is laid out in books or magazines; “columns” of code shouldn’t be too wide, and it should be broken up into chunks, not put in continuous blocks. The writers commented on this:

Research also seems to show that, when it comes to line lengths of text, there’s a difference between reading speed and reading comprehension. Longer lines can be read faster, but shorter lines are easier to comprehend.

Chunked text is also easier to comprehend than a continuous column of text. That’s why columns in books and magazines are divided into paragraphs. Paragraphs, verses, lists, sidebars, and footnotes are the “transition markers” of text, saying to our brains, “Have you grokked everything so far? Good, please go on.”

As a side note, as of this writing, I still haven’t got around to fixing the width of the text in my blog. My apologies to anyone who’s reading this on a really wide widescreen display. (As another side note, see the definition of “grok” from the Jargon File, if you’re not familiar with the term.)

Making Alike Look Alike

For making alike look alike, they’re just saying that when code blocks that are similar in nature look similar to each other, it’s much easier for the brain to comprehend what’s going on at a glance. They give an example, that looks like this:

while( d.diffs == DD_CONF && ( bf->end != bf->lines() ||
lf1->end != lf1->lines() ||
lf2->end != lf2->lines() ) )
Even if you know nothing about this code—as I don’t—you can easily see how the conditions within that while loop are all similar to each other. The fact that each test looks the same (compare the end member to the result of the lines() method—and not the other way around—indent them all to the same place) makes it easier to comprehend this code.

Overcoming Indentation

And finally—or at least, finally for the points that I’m going to mention here—they mention overcoming indentation. By which they are not saying that you shouldn’t indent code! What they’re saying is that you should avoid nested code as much as possible. (Which, in so doing, will reduce indentation. Which also does help, by the way, since it helps with keeping your columns of text narrow, although the main point here is that we’re trying to avoid nested logic as much as possible.) If you can, try and avoid having nested conditionals in your code; they’ve got a bunch of statistics showing how much harder it is to maintain deeply nested code than code that isn’t nested.

For example, suppose I want to write a function to calculate a tip, based on a bill. But I only want to calculate the tip if it hasn’t already been included on the bill; if it has, the tip is 0. If I had some kind of DTO object, with details about the bill, I might write a method like this:

float calculateTip(Bill bill) {
if (!bill.includesTip) {
for (int i = 0; i < bill.lineItems.length; i++) {
float subTotal += bill.lineItems[i].cost;
}

return subTotal * 0.15;
}

else {
return 0.0;
}
}
This does exactly what I’d said above, and calculates the tip only if it hasn’t already been included on the bill. Unfortunately, it means that the bulk of the code for this method has to be included within that if statement. And that means that the code is inherently a little bit harder to understand. Although the logic isn’t too complex, in this case, when you’re reading that for loop, you do have to keep in mind that this is within the if statement, meaning that it only happens when the tip is not included on the bill.

But there’s another way of looking at this logic; if the bill includes the tip, we can return 0 and exit the method right away:

float calculateTip(Bill bill) {
if (bill.includesTip) {
return 0.0;
}

for (int i = 0; i < bill.lineItems.length; i++) {
float subTotal += bill.lineItems[i].cost;
}

return subTotal * 0.15;
}
Although it logically does the same thing as the version above, the fact that it’s got less nested logic makes it inherently a bit easier to read and comprehend. We took care of the logic of determining if the bill already includes the tip, and once that is done, we can carry on with the rest of the code, and not worry about it again.

Self-Documenting Code

Interestingly, I was surprised at an aspect of code that wasn’t mentioned in the book, but since I’m talking about pretty code, I’ll mention it here. In Martin Fowler’s excellent book Refactoring: Improving the Design of Existing Code—a book I highly recommend—he introduced me to the concept of “self-documenting code”. Let me give a silly example, using Java-like pseudocode:

/* note that I've hard-coded the amounts for tax and tip,
but this isn't real code, it's just illustrating a point,
and in real life I would never do that, blah blah blah */

Bill calculateBill(BillLineItem[] lineItems) {
Bill bill = new Bill();

bill.lineItems = lineItems;

//calculate and set bill subtotal
for(int i = 0; i < lineItems.length; i++) {
float total += lineItem[i].cost;
}
bill.subTotal = total;

//calculate and set tax (PST and GST)
bill.provincialTax = bill.subTotal * 0.06;
bill.federalTax = bill.subTotal * 0.05;

//calculate and set tip
bill.tip = bill.subTotal * 0.15;

return bill;
}
To make the code self-documenting, you might refactor it to make it more like this:

Bill calculateBill(BillLineItem[] lineItems) {
Bill bill = new Bill();

bill.lineItems = lineItems;

calculateAndSetBillSubtotal(bill);

calculateAndSetTax(bill);

calculateAndSetTip(bill);

return bill;
}

void calculateAndSetBillSubtotal(Bill bill) {
for(int i = 0; i < bill.lineItems.length; i++) {
float total += bill.lineItems[i].cost;
}

bill.subTotal = total;
}

void calculateAndSetTax(Bill bill) {
bill.provincialTax = bill.subTotal * 0.06;
bill.federalTax = bill.subTotal * 0.05;
}

void calculateAndSetTip(Bill bill) {
bill.tip = bill.subTotal * 0.15;
}
In other words, where possible, when you have a comment in front of a block of code, you can break it out into its own function instead, and name the function such that it replaces the comment. In general, this simplifies the calling function, and promotes reuse, since the smaller chunk of code is more likely to be usable somewhere else. (Not guaranteed to be reusable, obviously, but there’s more possibility of reusing a smaller piece of code than a larger piece, in general. The larger a block of code is, the more chance that it will have a specialized side effect that you don’t want, when you’re trying to reuse it.)

Now I know—I know!—that I’m going to get a bunch of comments on this example, talking about execution speed and optimization. Especially since the method in question was so simple in the first place. “Why would you take the performance hit of making that a function call… blah blah blah…” Yes, yes, stay with me folks, there are always multiple tradeoffs to consider. But we’re talking about making the code understandable, and if you can make the code self-documenting, instead of putting in explanatory comments, it’s easier to read, and therefore, easier to maintain. (I don’t have statistics to back that up. If you disagree and would like to comment on the fact, feel free—I’m getting good at separating the wheat from the chaff in my comments.)

If you look at the new calculateBill() method, you can see the high-level logic much easier than you could with the previous version. It’s true that you can’t see the details of everything that it’s doing all at once—and that’s the point. You don’t need to know every detail of everything this method is doing all at once. If you’re reading the code to get an idea of what it’s doing, you can look at the calculateBill() method, and not get sidetracked with details about how the tip is calculated; conversely, if you’re tasked with fixing a bug in how the code calculates a tip, you can glance at the calculateBill() method, see that you should be looking at the calculateAndSetTip() method, and concentrate your energies there. And, again, not be bogged down with details on how tax is calculated.

Code Should Be Concise

Another aspect of beautiful code, which was mentioned numerous times by numerous authors in the book, is that it should be concise. I was reminded of this by another quote from Diomidis Spinellis (who was mentioned in the Computer-Generated Code post):

I always feel elated if, after committing a refactoring change, the lines I add are less than the lines I remove.

And I have to say that I have the same feelings. When I’m modifying some code, I get a great feeling of satisfaction when I can make the code smaller, rather than larger. But it should be noted that conciseness is something you have to work at. Typically, you will write code that is longer, and only with some extra thought can you make it more concise.

Along these lines, my email sig includes a bastardization of a quote from Blaise Pascal; it says:

Sorry this email was so long—I didn’t have time to make it shorter.

Tuesday, August 12, 2008

Calzones

If you like calzones, Andrea found a great recipe on AllRecipes.com for Broccoli, Pepperoni and Three Cheese Calzones. We tried it on Sunday, and they were excellent.

Fortunately or unfortunately, the bread is completely hand-made. This is unfortunate because it means that you have to spend hours making the darned things, but fortunate because the bread is really good. I’m sure I’ll make them again, but only if there is a special occasion, that would warrant the work. For example, if the Queen of England were visiting. To ask me to marry her daughter. And she’d specifically mentioned ahead of time that she liked calzones.

Tuesday, August 05, 2008

Blood

I had previously attempted to give blood—and I had previously failed. But it was time to try again on Friday, and this time I was determined to give my blood, come hell or high water.

I was worried that I’d get nauseous again, as I did last time. I did my best to eat properly on Friday—I didn’t even have any coffee that day—and I also had a game plan: If I did get nauseous, I wouldn’t tell them. (It’s a brilliant plan! Foolproof!) Only if it got really bad would I let on that I was nauseous.

We went through all of the same procedures, but this time, there was a lot of waiting involved. There was a big line of people there ahead of me, also giving blood. (Lesson for the day: If you’re going to donate blood, don’t do it at Woodbine, where there are lots of people donating blood. Do it at Sherway Gardens, where there aren’t any lines.

Finally, I got on the table, and they put the needle in. And right away, I felt a bit nauseous. (Andrea still feels that this is psychological.) However, I wasn’t that nauseous; just a bit. So I stuck to my plan, and didn’t tell anyone. (“Are you okay?” “Yep, everything’s fine.”) And it quickly passed, so my plan was a good one. There was a moment of panic, when the woman had to adjust the needle, and pull it a bit further out of the vein; I guess the blood wasn’t flowing as well as she would have liked.

As an aside, there was another woman there, just ahead of me, who was also donating blood. She was the type of person who laughs constantly when she talks, so I was hearing her laughter the whole time I was there. When I was on the table, she was behind me, where I couldn’t see her, but I was constantly hearing her laughter. And then at one point it occurred to me: “Wait a second. She got on the table well before I did, but I still hear her laughter! How long has she been there?!? It’s been at least fifteen minutes—does that mean I have another ten minutes here?” As it turns out, she’d left her table long before, and was sitting at the recovery area; it’s just that, because I couldn’t see her, and could only hear her laughter, I assumed she was still being drained.

In any event, whatever the nurse did with my needle worked, because I was finished much sooner than I’d thought I would be. (Especially given my panic over the woman on the table behind me.)

And then she took the needle out, and I got hit with a real strong wave of nausea. For a moment, I thought I was going to throw up. (Again, people were asking me if I was okay, and I was telling them yes.) Luckily it passed after a few moments. They brought be over to the recovery area, and gave me some juice and cookies, and by the time I finished, I felt completely normal.

Tuesday, July 29, 2008

Stinking Paper Towel Dispensers

I wrote quite a while ago about the fact that they’d replaced the paper towel dispensers at my office with automated ones. At the time, I wasn’t happy about the fact.

Now that I’ve been living with them for a while, I’m even less happy. For some reason, they tend to run out of paper towels a lot more often than the manual ones used to. (Is it because they dispense more paper towel than is necessary? I don’t know.) So, many times I’ll go into the washroom, wash my hands—and maybe even splash some water on my face, which I do from time to time—only to find that I have nothing with which to dry myself.

This is a very petty complaint, I realize that. I’m not expecting pity.

Exercise—I’m still doing it!

I posted a while ago that I’d started exercising—crunches and push-ups—and I wondered how long I’d keep it up. It turns out I’ve kept it up for the last couple of months, which is better than I thought I’d do.

But I’ve now added something new to my regimen: The escalators are out of commission for the next twelve weeks, in the office where I work, and my desk is on the fifth floor. So I’ve decided, since the elevators are so slow, that I’m going to start taking the stairs. It turns out that I’m very much out of shape, but I’m hoping that after a week or two of taking the stairs, I won’t be so winded after the climb anymore…

Cuil

A new search engine has been launched, named Cuil (pronounced “cool”), which is touting itself as a Google killer. Am I one of the first to write about it? Naw, I doubt it. Maybe one of the first ten thousand. Anyway, they claim to have a bigger index, and, therefore, a better ability to find search results.

I first read about it on Wired, in an article that seemed very positive, but Wired isn’t always that prescient. I thought I’d try it out; I’ve been having trouble writing a plugin for gedit, in Python, that I just can’t quite get working. (I don’t know if it’s because I don’t know Python—which I don’t—or if it’s because I don’t know the gedit/gtk programming model, which is really poorly documented.) I’ve done lots of searches in Google to try and find help on how to debug a plugin, and I’m seeing lots of example plugins and other stuff, but nothing that is helping with my troubleshooting. So I pulled up Cuil, and started searching for things like “help writing a Python plugin for gedit” and similar phrases. Also, for fun, I also searched for “David Hunter”.

What I got was a lot of error messages, and very few search results. In fact, in my gedit-plugin-related searches, I never got any results. In my “David Hunter” searches, I did get a page of results, although I never found myself, and the page seemed to indicate that it was still loading, but never actually finished.

Now, I wasn’t worried about the error messages. It’ll take them a while to get their infrastructure firmed up, and get the kinks worked out. (One might have hoped that they’d have done that before launching, but hey, I’m a forgiving guy.) The thing is, even if the search results were great, even if I’d managed to find everything I was looking for—especially the gedit plugin stuff, since I wasn’t able to find a lot of help through Google—they’d still have an uphill battle trying to unseat Google. Google is more than search. I would go on about it further, but this post from another blog did a better job.

The fact is, Google is pretty darned good, and even if Cuil is better, it is probably only marginally better. If I couldn’t find what I was looking for, regarding my gedit plugin, it’s probably because what I’m looking for doesn’t exist.

Sunday, July 20, 2008

Beautiful Code: False Optimization Redux

This post is part of the Beautiful Code series.

Here we’re going to look at the concept that you should know your usage patterns, before you try to optimize for them. (This is pretty much just an addendum to the False Optimizations post.)

Andrew Kuchling wrote a chapter about Python’s dictionary implementation. Why is Python’s dictionary implementation beautiful? One reason is the way that it determines its size: the dictionary always keeps a number of spots open, for new insertions, and any time the dictionary gets too full (that is, too few empty spots), it quadruples in size, to make more room. And what happens when you remove an item from the dictionary? Well… nothing. A Python dictionary expands when necessary, but never bothers to contract.

Any why is this? Because of the way that Python dictionaries are used:

This means that dictionaries are never resized on deletion. If you build a large dictionary and then delete many keys from it, the dictionary’s hash table may be larger than if you’d constructed the smaller dictionary directly. This usage pattern is quite infrequent, though. Keys are almost never deleted from the many small dictionaries used for objects and for passing function arguments. Many Python programs will build a dictionary, work with it for a while, and then discard the whole dictionary. Therefore, very few Python programs will encounter high memory usage because of the no-resize-on-deletion policy.

Honestly, I would have put this in the False Optimizations post, except that I’d already posted it by the time I started writing about this chapter. But the concept is the same: It seems that the right thing to do is to have the dictionary expand and contract as necessary. But since most Python programs don’t spend a lot of time removing items from dictionaries, it’s not worth the effort to build that functionality into the Python dictionary implementation. For a tradeoff of taking up a bit more memory, the Python dictionary implementation means that deleting from a dictionary is quicker (since no shrinking of the dictionary needs to happen), and that the Python dictionary itself is easier to maintain for the people who build Python itself, because less code means easier to maintain code.

Saturday, July 19, 2008

Beautiful Code: Runtime Type Checking

This post is part of the Beautiful Code series.

I have to admit, the title of this post might be misleading. Scratch that: It is misleading. This post is actually about a lack of runtime type checking. This quote is from Greg Kroah-Hartman, on a chapter about the Linux kernel driver model. He has explained some concepts, and given some code samples, and then he says this:

If you notice, there is no runtime type checking to ensure that the pointer that was originally passed as a struct device really was of the struct usb_interface type. Traditionally, most systems that do this kind of pointer manipulation also have a field in the base structure that defines the type of the pointer being manipulated, to catch sloppy programming errors. It also allows for code to be written to dynamically determine the type of the pointer and do different things with it based on its type.

The Linux kernel developers made the decision to do none of this checking or type definition. These types of checks can catch basic programming errors at the initial time of development, but allow programmers to create hacks that can have much more subtle problems later on that can’t easily be caught.

Whoa. In the Linux kernel driver model, in this instance, they don’t do runtime type checking. But what if a developer passes the wrong kind of struct? Well, if I may paraphrase Kroan-Hartman—perhaps incorrectly—if people are passing the wrong kind of struct, then they have bigger problems. Frankly, if the code did do runtime type checking, developers would probably simply set the appropriate value in the struct, until they found a value that worked. They’d still have the problem, they’d just mask it, but now it would be hard to track down and find. So why waste the kernel’s time doing this runtime type checking, when it’s not really going to buy anything anyway?

Is this a lesson that we can apply in other areas? Maybe, although you’d have to be very careful about it. We’re not all writing Linux, folks. And, to be clear, the parts of the Linux kernel being discussed in this chapter aren’t really worked on by thousands, hundreds, or even dozens of people. There are only a limited subset of people who are working on the Linux kernel driver model. That makes a difference too.

Beautiful Code: Computer-Generated Code

This post is part of the Beautiful Code series.

I saw two really wonderful examples of computer-generated code in Beautiful Code. First was a chapter by Charles Petzold—yes, that Charles Petzold—who was discussing image processing. Petzold’s example is fairly complex, so I’ll try to give a simpler example, to illustrate the general concept.

Suppose you have an array of integers, and for each integer, you want to add 1 to the number if it’s less than 10. A ridiculously contrived example, but it is simple enough to explain the concept. Now suppose your array includes 5 items, with the following values:

{1,16,72,2,4}
If you knew that ahead of time, then you could write code like this:
function someRidiculousFunction() {
int anArray[10] = {1,16,72,2,4};

anArray[0]++;
anArray[3]++;
anArray[4]++;
}
We know that the first, fourth, and fifth elements in the array are less than 10, so they need to be incremented.

In real life, however, chances are our code wouldn’t know which elements are less than 10, and which aren’t. The code might not even know how many elements are in the array. So the code is more likely to look more like this:
function moreRealisticFunction() {
int anArray[] = generateArray();

for(int i = 0; i < anArray.length; i++) {
if(anArray[i] < 10)
anArray[i]++;
}
}
We need a loop, to cycle through the elements of the array, and we need an if statement, to determine if each element in the array is less than 10, before incrementing it. The first code sample just isn’t realistic; there are very few instances in real life when you’d be able to write code like that. Not only that, but for an array of any size, the second function will be much more readable and maintainable by future programmers. Having a function with a hundred lines after each other, like in the first example (if the array were bigger) would numb the mind.

But the thing is, someRidiculousFunction() would be more efficient than the moreRealisticFunction() would! If only we did know ahead of time, when we were writing the program, how many elements there would be in the array, and which (if any) needed to be incremented, then we wouldn’t need the loop, or the if statements.

Petzold presents a much more complex situation, having to do with processing images. Because an image (such as a JPG or GIF file) will potentially have millions of bytes, representing many, many pixels, processing each pixel to do things like adding blur effects can be a time consuming process. Anything that can be done to streamline the process would present an amazing time savings to the program—but the issue is that you need all of those if statements and loops, to go through the image.

His solution is to use .NET’s ability to generate code on the fly. When you’re writing your program for manipulating images, you can’t necessarily write code like you could for someRidiculousFunction(), but you can have your program generate code that works that way, in which case you can avoid the tedious if statements and looping, and just generate mountains and mountains of procedural code. Since it is being generated at runtime, there is no worry about maintaining the code afterward, so you don’t need to worry about how pretty or understandable (or beautiful) that code is; you only need to worry about maintaining the code that generates that code. (Too meta for you? Read through it again. Or, better yet, buy the book, and read Petzold’s chapter.)

That’s at runtime, but what about at compile time? Most programmers are familiar with the C preprocessor, and the ability to create macros that will expand within the code at compile time, but most programmers are also aware of the limitations of the C preprocessor’s abilities. But that doesn’t mean that generating code at (or near) compile time is a bad idea. In a chapter by Diomidis Spinellis I came across a novel idea: use awk (or a similar text processing language) as your code preprocessor! (Note: Spinellis kept italicizing “awk,” so I am too. I don’t know if it really has to be italicized.)

Suppose you have highly repetitive pieces of code, repeating throughout your program. Instead of typing it out over and over again, you can include a simple notation instead, which can be processed by a language like awk, and expanded into real code, which would then be compiled. That is: write your source code, potentially involving a special notation; save your source code files; run those files through a program written in awk, which would process the special notations within your source code and generate more source code; save the new code into a new file; run the new file through the compiler, to create the program.

Doing this in awk instead of the C preprocessor has two advantages that I can think of:
  1. Using the C preprocessor limits you to the syntax available; it’s its own little language. However, with awk, or similar languages, you have the power of regular expressions at your fingertips, and can do some very complex text manipulation, if necessary.
  2. The C preprocessor is available to you if you’re writing code in C, or C++, and there are some similar things being added to later versions of Java for performing certain tasks, but using something like awk would work for any programming language you choose.
Let’s look at an example from Spinellis.

The handling of locking assertions deserves more explanation. For each argument, the code lists the state of its lock for three instances: when the function is entered, when the function exits successfully, and when the function exits with an error—an elegantly clear separation of concerns. …. The following code excerpt indicates that the rename call arguments fdvp and fvp are always unlocked, but the argument tdvp has a process-exclusive lock when the routine is called. All arguments should be unlocked when the function terminates.

#
#% rename fdvp U U U
#% rename fvp U U U
#% rename tdvp E U U
#

The locking specification is used to instrument the C code with assertions at the function’s entry, the function’s normal exit, and the function’s error exit. For example, the code at the entry point of the rename function contains the following assertions:

ASSERT_VOP_UNLOCKED(a->a_fdvp, "VOP_RENAME");
ASSERT_VOP_UNLOCKED(a->a_fvp, "VOP_RENAME");
ASSERT_VOP_ELOCKED(a->a_tdvp, "VOP_RENAME");
Now, the code starting with # characters isn’t actually C code. In fact, the C compiler would throw errors at those lines. But that doesn’t matter because awk is going to replace those lines with real C code, which the compiler will like. In fact, for each line of #-prefixed code above, 3 lines of code would be inserted into the code—tedious, error-prone code, which has nothing to do with the actual logic the programmer was trying to accomplish. According to Spinellis, “In the FreeBSD version 6.1 implementation of the vnode call interface, all in all, 588 lines of domain-specific code expand into 4,339 lines of C code and declarations.”

If your code has a lot of repetitious, error-prone code in it, and if you have the ability to insert awk or a similar tool into your compilation process, this technique can save you not only time, but debugging effort, too. Then again, with modern IDEs—especially ones that compile your code as you work, but even ones that just warn you about syntax errors—you’ll also need to contend with code that your IDE keeps warning you about. One solution might be to include your special notations in comments, that the IDE will ignore, and have awk process that. For example, instead of
#
#% rename fdvp U U U
#% rename fvp U U U
#% rename tdvp E U U
#
you might do something like this, instead:
//#
//#% rename fdvp U U U
//#% rename fvp U U U
//#% rename tdvp E U U
//#
You just need to alter the regex’s in your awk script to use //# instead of # when looking for lines to process.

Beautiful Code: False Optimizations

This post is from the Beautiful Code series.

One of the first concepts that jumped out at me from Beautiful Code concerned false optimizations—that is, something added to the code which should have been an optimization, but as it turns out, actually causes the code to run slower.

As an example, we’ll look at some code that implements a binary search, from a chapter written by Tim Bray:

package Binary;

public class Finder {
public static int find(String[] keys, String target) {
int high = keys.length;
int low = -1;
while (high - low > 1) {
int probe = (low + high) >>> 1;
if (keys[probe].compareTo(target) > 0)
high = probe;
else
low = probe;
}
if (low == -1 || keys[low].compareTo(target) != 0)
return -1;
else
return low;
}
}
As mentioned, this function simply searches through some strings, using the binary search algorithm, and sees if there is a match. I just quickly read through the code, and didn’t realize—until Bray pointed it out—that there is no explicit check within the loop to see if the match has been made. One would expect him to add that in, as an optimization, so that when the target is found, the loop could exit, and not bother continuing with its checks. But as it turns out, that would be a false optimization; mathematically, the match is likely to be found late enough in the loop that the extra if statements during every execution of the loop would be more of a performance hit than simply letting the loop execute a few more times. Or, as Tim puts it:

Some look at my binary-search algorithm and ask why the loop always runs to the end without checking whether it’s found the target. In fact, this is the correct behavior; the math is beyond the scope of this chapter, but with a little work, you should be able to get an intuitive feeling for it—and this is the kind of intuition I’ve observed in some of the great programmers I’ve worked with.

Let’s think about the progress of the loop. Suppose you have n elements in the array, where n is some really large number. The chance of finding the target the first time through is 1/n, a really small number. The next iteration (after you divide the search set in half) is 1/(n/2)—still small—and so on. In fact, the chance of hitting the target becomes significant only when you’re down to 10 or 20 elements, which is to say maybe the last four times through the loop. And in the case where the search fails (which is common in many applications), those extra tests are pure overhead.

You could do the math to figure out when the probability of hitting the target approaches 50 percent, but qualitatively, ask yourself: does it make sense to add extra complexity to each step of an 0(log2 N) algorithm when the chances are it will only save a small number of steps at the end?

The take-away lesson is that binary search, done properly, is a two-step process. First, write an efficient loop that positions your low and high bounds properly, then add a simple check to see whether you hit or missed.

Let’s look at another example. This is a snippet of code from Elliotte Rusty Harold, from XOM, used in verifying XML documents. After verifying an XML namespace (which is a URI), it is cached; when a namespace is encountered, the parser can look in the cache, to see if it has already been verified, and, if so, not bother verifying it again. This class is the cache Elliotte uses.
private final static class URICache {

private final static int LOAD = 6;
private String[] cache = new String[LOAD];
private int position = 0;

synchronized boolean contains(String s) {

for (int i = 0; i < LOAD; i++) {
// Here I'm assuming the namespace URIs are interned.
// This is commonly but not always true. This won't
// break if they haven't been. Using equals() instead
// of == is faster when the namespace URIs haven't been
// interned but slower if they have.
if (s == cache[i]) {
return true;
}
}
return false;
}

synchronized void put(String s) {
cache[position] = s;
position++;
if (position == LOAD) position = 0;
}
}
This code is fairly simple. It’s a helper class used to maintain a list of namespace URIs that have been captured, and a method which will tell you if a URI is in the list or not. The surprising thing is that the helper class uses a static array, with exactly six items, and if you try to add a seventh, it simply overwrites the first one (and so on). Why not use a hash map, or a table? Something dynamic, which could grow as large as necessary? Why a statically-sized array?

Again, the answer is simple performance, because Elliotte Rusty Harold has seen enough XML documents to know that rarely will any document have more than six namespaces defined in it. So by using a statically-sized array, instead of something more dynamic, he gets a boost in performance in the majority of cases. In the case where a document does have more than six namespace URIs, validation will simply take a little longer for that document, because some namespace URIs may have to be verified twice. (If the parser comes across a URI which has already been verified, but has been overwritten in the cache, then it would have to be re-verified. Of course, if the URI hasn’t been overwritten, it still won’t have to be re-verified.)

This was counter-intuitive for me, at first; it seems like the “Right Thing” would be to always make the size of your list dynamic, to deal with as many elements as are necessary. In fact, at first glance, it almost seems like a rookie developer’s mistake, to use a statically-sized list. But in this case, it was done on purpose, and for very good reason.

So again, he’s not doing something that he doesn’t have to do, even though, at first glance, it would seem like an optimization. Without thinking about it, I’d have made the size of the array dynamic, so that I’d never have to verify a URI that had already been verified, but Elliotte thought more deeply about it, and realized that making the code more complex in that manner would not have been an improvement. And he’s right; that array will be accessed much more often than it’s added to, so he was able to optimize for the majority of cases, with a small potential performance hit in the minority of cases.

Beautiful Code

As mentioned on the serna Book Blog, I recently read Beautiful Code, written by… well, written by a whole bunch of programmers who are smarter than I am. (Or better programmers, anyway.)

So I have devoted a series of posts to some of the concepts in the book that I found the most interesting. Here are the posts I included in this “series”:

And I’ll finish off with a quote from Brian Hayes, that I found especially poignant—and described my reaction to many of the concepts I read in this book:

In cartoons, the moment of discovery is depicted as a light bulb turning on in a thought bubble. In my experience, that sudden flash of understanding feels more like being thumped in the back of the head with a two-by-four. When you wake up afterwards, you’ve learned something, but by then your new insight is so blindingly obvious that you can’t quite believe you didn’t know it all along. After a few days more, you begin to suspect that maybe you did know it; you must have known it; you just needed reminding. And when you pass the discovery along to the next person, you’ll begin, “As everyone knows….”

Monday, July 14, 2008

Camping

Hmm, how long has it been since I posted? Really? That long? Ouch. I’ve been remiss. Me me.

I went “camping” this past weekend. There’s not much to say about it, but here are the highlights:

  • I’ve probably lost weight, because of the amount of blood removed from my body by mosquitos.
  • I got to know my god daughter Alexis a bit better. Which was nice, because I don’t get to see her that often.
  • I sat on a bag of chips.
And that’s about it. I had a very nice, pleasant weekend, but Andrea should be glad she didn’t come; it wasn’t real camping, but it still would have been torture for her.

Friday, July 04, 2008

Karma?

I was glancing at my Ubuntu wiki this morning, and noticed a little icon next to my Wikidot “avatar” (which is part of my profile) that looks like some kind of rating. I clicked it, and found out that my “karma” is very high for some reason.

karma

So I wanted to know what this “karma” thing is. It turns out that Wikidot has started calculating this karma thing based on your activity on the site. According to their explanation page, ways you can raise your karma are:
  • Creating (and editing) a wiki, which I have done
  • Participating in forums, which I have not done
  • Participating in “community portals” (whatever they are), which I have not done
  • Being a wiki admin, which I have done—but it’s part and parcel of having created a wiki
  • Inviting others to join Wikidot, which I have not done
  • Having contacts and friends on Wikidot, which I have not done
  • Using AdSense on a wiki, which I have not done (although I did briefly toy with the idea)
So, of all of the ways one can raise one’s karma, all I’ve done is create and maintain a wiki, and yet they say my karma is very high. So one of three things is happening:
  1. I’ve done a lot of work on my wiki—so much so that my karma has gone through the roof
  2. There are few active wikis on Wikidot, meaning that my wiki seems more active by comparison. And keep in mind that I don’t maintain my wiki on a regular basis, so the other wikis would have to be very dormant.
  3. Wikidot calculates karma incorrectly, and is giving me more karma than I actually deserve

Wednesday, July 02, 2008

Back from vacation

As the title of this post mentions, I’m back from my vacation. It wasn’t too exciting, but it was a rest from work, which was sorely needed. Here are some highlights—actually, not even “some” highlights, this is pretty much everything that happened:

I started off with a quick trip back home, to go out to lunch with my mom (to celebrate her birthday), and then to go to my god-daughter’s 2nd birthday party. Unfortunately, Andrea wasn’t able to make it with me, because she got roped into doing a bit of work, at the beginning of her vacation.

Later on we went to Niagra Falls for a night, but our timing was bad, so we left Toronto during rush hour traffic, and came back to Toronto in rush hour traffic, too. (Luckily, we were against the traffic for our return trip, so it wasn’t as bad.) We went to see the band A is A, who were playing at Fallsview Casino, but also to spend a night in Niagra Falls. Unfortunately, we forgot to bring the camera, so I wasn’t able to get any real good pictures of the falls. Just these two from my cell phone (which are almost identical, and were taken from a window in my hotel):

IMAGE_023

IMAGE_024

However, I also managed to get this picture, which blows the lid off the whole waterfall racket:

IMAGE_025

See? The waterfall is a scam! If you go to Niagra Falls, don’t bother wasting your film taking pictures. It’s all just special effects or something.

Our next trip was to the States, to visit Andrea’s relatives. This involved more driving—ten hours’ worth, including a bunch of driving during Toronto’s rush hour—but I don’t really mind driving, and it was beautiful scenery, so that wasn’t bad. And of course Andrea’s relatives are great cooks, so that makes for a great trip, too. Unfortunately, we forgot to bring the camera again, so I have no pictures.

After this, Andrea went to Montreal for the Jazz Festival, and I stayed home in Toronto. Unfortunately, I don’t sleep very well anymore, when Andrea’s not with me, so I didn’t catch up on my sleep, as I’d been hoping to.

Finally, when she got back from Montreal, we took another trip, to go back to my parents’ place again.

And that’s it. It wasn’t really a restful vacation, per se, but I enjoyed all of the individual things we did.

Saturday, June 28, 2008

Movie Review: Balls of Fury

So far this weekend, I’d seen the new Indiana Jones movie, and Wanted. And then I got up Saturday morning, and wanted to kill some time doing something mindless, so I popped on TMN, and watched Balls of Fury.

Now, there is a big difference between Wanted and Balls of Fury. Sure, both are terrible, silly, bad movies. But Wanted is a terrible, silly, bad movie that people liked (according to its average rating on Google Movies). It’s bad, but bad in a way that you can watch it and really enjoy yourself. Balls of Fury, on the other hand, is just a terrible movie.

However, I have to admit—and I am ashamed of myself for this, believe me—that I was laughing all the way through Balls of Fury (which I will abbreviate to BoF for the remainder of this post). Why? Well, to start, it’s got Christopher Walken; that right there is enough to make any movie worth watching. Every time he spoke, I was rolling on the floor. It also had Maggie Q, and she was great too; I’ve only seen her in two movies so far (this and Live Free or Die Hard), but I loved her in both.

But it wasn’t just the actors/acting that had me laughing in BoF. It was the writing. There was something about it that just struck a chord with my particular sense of humour. I mean, sure, a lot of the jokes were pretty silly, but I don’t mind silly humour.

So I don’t recommend BoF. And I’m not planning to get it on DVD. And I’ll never, ever watch it with Andrea. But on this particular day, it made me laugh.

Movie Review: Wanted

I mentioned that Andrea’s out of town, and I had decided to take advantage of the situation by going to the movies, since she doesn’t really like going. But then I thought to myself: Why didn’t I take advantage of the situation fully? I mean, I went to the movies, sure, but I saw a movie that she’d probably like. I should have seen one that she’d never want to see.

So I did. I went back to the theatre, and saw Wanted, a movie that I knew she’d never want to see. Not that I would blame her; it’s pretty ridiculous. But I saw James McAvoy on The Daily Show this week, and Jon Stewart had said that the movie seems ridiculous, from the trailers, but that when he actually saw it, it was great, what with the action and all. So I figured what the heck, I’d give it a shot.

And I have to admit, it wasn’t bad. If—and that’s a big if—if you’re able to lose yourself into it, you’ll find yourself laughing at the action, chuckling at the poor choices in music, rolling your eyes at the plot, and just generally enjoying the movie altogether. Not that I’m recommending the movie, mind you; I’m just saying that I enjoyed it. It’s the type of movie that I’d see in the theatre, enjoy, decide to buy the DVD, wait for the DVD to come out, buy the DVD, realize on second viewing that I don’t enjoy it as much as I thought I did, and let it sit on the shelf for years, gathering dust. (And then, years later, Andrea, out of boredom with the movies we’ve seen, would decide that she wants to see it, even though I’d try and convince her that she’d hate it, but we’d watch it anyway, and she’d make fun of me for years about my poor taste in movies. Justifiably.)

On a side note, I’ve never really found Angelina Jolie all that attractive, but I thought she looked quite beautiful in this movie.

Friday, June 27, 2008

Movie Review: Indiana Jones and the Kingdom of the Crystal Skull

Yeah, yeah, I know. I never review movies when they first come out, when my reviews might actually help someone. I review them when it’s too late, and everyone’s already seen them. Oh well. It’s who I am. No sense trying to change now. Since Andrea was out of the city for the weekend, I took the opportunity to go to the movies (something she doesn’t normally like to do). I went to see Indiana Jones and the Kingdom of the Crystal Skull.

I wasn’t sure what to expect, what with Harrison Ford being so old and all, but it was quite good. I would say on par with The Last Crusade, but I’m sure there are many who would disagree with me. It seems old fashioned to say this, but the movie is just good, clean, family fun. Lots of action and adventure, no over-the-top violence, no sex. (But it’s not boring, as that description might seem to make it out to be.)

And that’s all I have to say about that.

Friday, June 13, 2008

Vacation

I haven’t mentioned it yet, but I’m going on vacation for a couple of weeks. Which probably doesn’t mean anything for my blog readers; a couple of weeks without posting won’t be anything strange. (Assuming that I don’t post, of course. Who knows? We might take some interesting trips that I can write about.)

Thursday, June 12, 2008

Should I avoid Google, to be smart?

That’s a stupid title. I was just trying to come up with one that’s different from the title of the article I’m linking to.

I read an article today, Is Google Making Us Stupid? (by Nicholas Carr), which talks about the fact that our thought processes might be changing, because of the way that we use the internet. One of the things I took away from it is that I should keep making my blog posts long-winded and verbose, because it will help you battle the effects of the internet. (I doubt that would have been Carr’s intended outcome of the article…)

It’s definitely something to think about. We already know that people don’t read blog entries that are longer than a couple of paragraphs long; I’ve gotten that feedback—although it hasn’t changed my writing style at all—and other people have gotten similar feedback on their blogs, as well. I don’t think I’ve suffered the full effects of the internet-alization of the brain, though, because I can still sit down and read a lengthy book. Or even—gasp!—a lengthy blog entry.

But that doesn’t mean I disagree with Mr. Carr. In fact, I should warn you that if you click the link to his article, it’s a long read. Try and make yourself go through the whole thing. It can be your self-improvement exercise for the day.

Wednesday, June 11, 2008

Why Service Oriented Architecture Won’t Work in the Corporate Environment (redux)

I sent a colleague a link to a previous post, Why Service Oriented Architecture Won’t Work in the Corporate Environment.


E.S. says (11:45 AM):
i love your blog on SOA

E.S. says (11:45 AM):
Why Service Oriented Architecture Won't Work in the Corporate Environment

sernaferna says (11:45 AM):
hehe Did you read it, or do you just like the title?



E.S. says (11:45 AM):
i read it

E.S. says (11:45 AM):
not in full details but i read it

sernaferna says (11:45 AM):
LOL

sernaferna says (11:46 AM):
Yes, I get kind of long-winded sometimes.

E.S. says (11:46 AM):
its all an issue about having an "Enterprise" architecture

E.S. says (11:46 AM):
Orgs. are having a hard time about buuilding a real enterprise architecture

sernaferna says (11:46 AM):
Which most organizations DON'T have, even if they like to pretend that they do.

E.S. says (11:47 AM):
LLOL exactly

E.S. says (11:47 AM):
i snet your blog to a VP here

sernaferna says (11:47 AM):


sernaferna says (11:47 AM):
My blog will become a meme! lol

E.S. says (11:47 AM):
the vp in charge of Business solutions and SOA

E.S. says (11:48 AM):
i like your references to call centers and customer profiles

E.S. says (11:48 AM):
LOL

E.S. says (11:48 AM):


sernaferna says (11:48 AM):
lol Well, if I get an from him, telling me to mind my own business and stop badmouthing SOA, I'll know why.



E.S. says (11:48 AM):
LOL

sernaferna says (11:50 AM):
Do you mind if I post this conversation to my blog?

Monkey work

Further to my earlier post, I may not be able to find things to read during my few minutes of “down time” throughout the day, but I can use the internet to do mindless, repetitive tasks—a.k.a. “monkey work”—while on the phone.

I was able to modify all of my blogs to use the new blogroll feature while I was on a conference call today.

Blogroll

Not that it really matters, but I’ve changed the way that I list my other blogs, in my sidebar. Google has introduced a specific gadget for creating a blogroll. (Most people will use this to list other blogs that they link to, instead of narcissistically linking to their own, but hey, I’m not most people.)

Tuesday, June 10, 2008

Google Reader and the internet

I’ve mentioned before [probably] that if you want to follow my blog(s), you should probably get yourself some type of RSS “reader”, so that you can be notified when a new post appears. There’s little point coming back here every day to see what’s new when there’s a 90% chance that there won’t be anything. (There’s a 100% chance that even if there is, it won’t be worth your time, but technology can’t help with that problem. That’s just a matter of making poor choices in the blogs you follow.)

Lately, I’ve been using yet another Google product, as my RSS reader: Google Reader. And it’s pretty cool. When I log in, I get a list of all of the blogs (or other sites that have RSS feeds) that I’m watching, and can see at a glance which ones have new posts/items. I can read the posts right in Reader, or I can click the link to go to the blog’s site itself. If I want to, I can “star” an item, so that I can easily find it later, and I can even “share” items—with or without personal comments—and they’ll show up on a special public page, where people can see the posts that I’ve shared. (Which, itself, has an RSS feed, so people could in turn watch my “shared items” in their RSS reader.) I haven’t actually started using the “sharing” feature, though—except for one post from this blog, just to see what it looks like—so at the time of writing, there isn’t much to see at my shared items page. But still, I can definitely see the potential for that to be very cool. If I used it more often, I’d probably even put an RSS feed to my shared items in the sidebar at the side of this blog.

But here’s the issue, which is partially the reason I don’t use the sharing feature: There aren’t that many blogs that I follow. Most of the time when I go into Google Reader, I have the same experience as anyone who follows my blog: Nothing is there. So you’d think that I’d probably just go in once a day, first thing in the morning, and then leave it until the next day. But that’s not how I operate. Any time I have a couple of free minutes, I’m there, seeing the “no unread items” message.

I read a blog post today by someone who was mentioning the fact that the internet has the ability to waste a lot of his time, but I have the opposite problem: When I get a few free minutes at work, my first impulse is to go to the internet and read something, but when I go, there’s nothing to read! I get off a conference call, and have a few minutes to kill before my next one, so I whip out Google Reader, and find… nothing. (There’s even a handy Trends tool, that gives some cool statistics on the blogs I’m following, but that doesn’t do me much good either, when I’m not reading anything.)

So I foresee a future in which I spent a lot of time looking for blogs that I can put in my Google Reader list. Eventually, when I’ve got dozens and dozens, it will become more likely that there will be something to read any time I go into Google Reader. But that will cause other problems: I’ve noticed that I tend to get new items showing up in Reader in clusters; I may not find posts throughout the day, but if I look first thing in the morning, I’ll find a bunch. (Apparently most blog writers do their writing/posting at night, not throughout the day.) So when I get dozens and dozens of blogs added to Google Reader, I’ll also find dozens and dozens of posts showing up every morning—and probably still nothing (or very little) throughout the day!

Thursday, June 05, 2008

Virus

I haven’t written in a while, and I had some very good reasons. Reasons that I won’t write about here because I haven’t made them up yet.

We got a virus on our computer at home, and it was a particularly nasty one. I was doing a deployment on Tuesday night, and Andrea called me around 9:00PM to tell me that we had it. When I got home at 12:30, she was still trying to get it off the computer; AVG wasn’t having any success. We were up until 1:30 trying to get it off, with no luck.

I was reading about it on the Internet. It’s some company that produces anti-virus software, and created this virus to drive people to them, to have it cleaned off. Every couple of minutes it would launch a browser, going to the company’s site; it changed Andrea’s desktop to some horrible red page, saying that our computer is infected, and to clean it we should “click here”; it created little icons in the taskbar, emulating Windows Security Centre, saying that our computer was infected with malware. Very intrusive. And all of the instructions I read didn’t work: I was told to remove a particular directory, but the directory didn’t exist; I was told to go to Task Manager, to shut down the process, but the virus disabled Task Manager; I was told to remove certain registry entries, but the virus disabled the registry editor(s).

We shut off the computer and went to bed, and then on Wednesday I got an email (and a phone call) from our ISP, telling us that one of our computers had been sending out a bunch of spam emails, meaning that we probably had a virus, and if we didn’t get the virus cleaned off within forty-eight hours, they’d shut down our service.

Finally I had to do the following:

  1. Reboot the computer in Safe Mode (without networking)
  2. Run AVG again. This time it was able to clean the virus, because in Safe Mode, the virus wasn’t active
  3. Do a System Restore, to fix the Windows DLLs that the virus had modified
That seems to have done the trick.

Luckily, I talked to the people at our ISP’s Tech Support, and they indicated that the emails our computer was trying to send didn’t actually get anywhere; the ISP caught them and stopped them. So it’s not like all the people in our address books got these emails. That would have been embarrassing.

My faith in AVG was starting to wane, when it couldn’t initially clean the virus off, but it was restored when AVG was able to do it in Safe Mode.

Friday, May 23, 2008

Exercise

I’ve started exercising again. Not real exercising, just push-ups and “crunches” in the morning, before I shower. I figure I’ll wait until I get into a little better shape, and then increase to something more substantial.

However, I’m finding that even the little tiny bit that I’m doing is already making me sore. I’ve done it two days in a row now, and my arms and my stomach muscles are… I wouldn’t say “hurting”, but I constantly feel them. (So I’ve really fallen out of shape from what I used to be able to do.)

We’ll see how long I keep it up, before I decide that an extra five minutes of sleep is more important than exercise, and I give it up.

Plain Ruffles

I was on the subway yesterday, on my way downtown, and I saw this sticker stuck to the seat in front of me:

ruffles
If you can’t read that (since my camera phone sucks), it says:

Mom bought plain Ruffles
I never understood that
So many flavours

Beginning XML on the shelf

It’s a great feeling to walk into a bookstore, and see your own book staring out at you from the shelf. Not just the spine, but the front cover—which means that my publisher has made a deal with the bookstore to display it that way.

the book on a shelf

Wednesday, May 21, 2008

Indiana Jones

When I was younger, I really wanted a fedora, like the one that Indiana Jones wears. In fact, it was a great disappointment to me, when my family went to Disneyworld—specifically, Hollywood Studios—that I didn’t get a chance to look around for one I could buy. There is also a good chance that I decided to buy my leather jacket—which is brown—because of Indiana Jones.

It turns out that I’m not the only one who wants to dress like Indy.

Tuesday, May 20, 2008

Tired. So tired.

May has been a terrible month, at work. (And the remainder of the month will continue to be terrible.) I was talking with one of Andrea’s cousins the other day about the fact that both she and I are so tired, these days, that we have trouble falling asleep. Which explains why I haven’t been posting here; if I’m too tired to sleep, then I’m definitely too tired to blog. (And/or too busy.)

Uh… except for this post, of course.

Friday, May 09, 2008

Yeah, yeah, I’m not posting very often. Too bad. You can just read some other blogs, for a while.

So here we are, over a week since my last post. And nothing much has happened in between. Well, except for my birthday; that happened this week. But that wasn’t really a big deal, either; I didn’t go out or celebrate or anything. (I’m 34 now, and 34 isn’t really a magic number, for me. Maybe when I turn 40 I’ll celebrate more.)

But, in honour of my birthday, I thought I’d look back through my blog, and see what’s happened since my last birthday. Here are some of the highlights, of the last year:

And that’s about it. Other than the new car, nothing too big really happened this past year. We’ll have to see if my 34th year is more exciting than my 33rd year was…

Thursday, May 01, 2008

Roll up the Rim 2008

I forgot to write about it, but I guess it’s pretty safe to say that Roll up the Rim season is over for the year. I finished the year with seven winning cups, out of sixty-eight altogether. Five coffees, two donuts, and zero GPS systems. But wait—why am I writing that, when I can just link to the spreadsheet on Google Docs, and you can see for yourself?

I love technology…

Thursday, April 24, 2008

Obama, Ferraro, Wright: ‘Postracial’ Meets Racism

I read a very good article in The Nation this week, and I thought I’d link to it here. (This is a bit late, but I’m always a few weeks or months behind, behind when reading The Nation.)

My favourite quote, in reference to the Rev. Wright “scandal”:

For while Wright’s sermons clearly shocked many whites, to many blacks his sentiments were as banal an addition to the dinner table as hot sauce.
Andrea’s favourite quote: “White is the new black.”

Tuesday, April 22, 2008

Nothing. Everything.

The good weather has arrived, and serna has been driving with his windows open. That’s good.

Roll up the Rim season seems to be over, or ending. That’s bad. If it is over, and I won’t have any more rims to roll up, then I ended the season at 10.29%. (I’ll post a summary post when I’m sure that it’s over.)

People are starting to ask me if I’m going to be doing anything for vacation this summer. That’s good.

I have no plans, and work is going to suck this summer. That’s bad.

Maybe Andrea and I will take some more light weekend trips. That’s… that’s neither good or bad. It’s sort of “meh”. I’d prefer to have a longer vacation, to allow myself to come down from too much work.

Monday, April 21, 2008

Anniversary—Part 2

As mentioned our anniversary—or rather, one of our anniversaries—was on Saturday. So how did we spend this momentous occasion? Well… not very gloriously.

  1. We slept in, a little bit, and then spent some time reading.
  2. We went out and distributed Bibles with our church in the early afternoon.
  3. We borrowed Andrea’s dad’s van, and brought some of Jehovah Shalom’s musical equipment to another church, since we’d be playing there on Sunday.
  4. We stopped at Home Depot to buy yard waste bags, and I got very distracted by the BBQs. I really want to get one, but will probably wait until the end of the season, so that I can get one more cheaply.
  5. We went home and spent a couple of hours filling up all of those yard waste bags, as well as a number of garbage bags, cleaning up all of the crap that tends to accumulate in our yard. (We live at the end of the street, and the wind tends to blow everyone else’s garbage into our yard.) We also removed a number of plants, because every time we clean the yard, we remove more and more. This would be the worst—and least anniversary-like—thing that we did to “celebrate” our anniversary.
  6. We decided that we would go out for dinner, even though we were tired from doing yard work. I asked Andrea if she wanted to go somewhere fancy or “regular”, and she said fancy. Which, I now realize, was a test, because Andrea never wants to go anywhere that’s expensive, so she didn’t really mean fancy. But luckily for me, I’m not a complete idiot, so I skipped the really expensive places. (I did some research on toronto.com and Toronto Life, and they both gave an approximate price range, so I skipped over the restaurants that indicated that you’d be spending $150–200 for two people.)
  7. We went to a place that I won’t name—because we didn’t like it—and had a terrible dinner. Mine was worse than hers; she got a club sandwich, which you can’t really screw up, but I got a greasy, over-cooked steak.
And that was that. Now that the weather is nice, maybe we’ll go out for dinner again sometime soon, and have a better time.

Friday, April 18, 2008

Anniversary

It’s my anniversary tomorrow. Andrea and I are celebrating ten years together; on April 19th, 1998, we began the relationship. I was talking to a colleague, and she said that she doesn’t even celebrate her “real” anniversary (i.e. her wedding anniversary), whereas I celebrate our wedding anniversary, the day the relationship began, and even the day that Andrea proposed.

Now, I realize that I’m not like other guys; I’m smarter and better looking. Ha! No, I kid. I’m not like other guys because I keep track of three anniversaries, whereas the cliché is that most guys can’t keep track of one. But there’s a good reason for that: When Andrea and I began our relationship—and then when we got married—I got into a relationship with a woman who’s better than me in every way. In the normal course of things, I could never get into a relationship with someone who’s so far above my league, and yet somehow I did. And we love each other, and have a good relationship.

So of course, I celebrate our anniversaries. I’ve spent a decade with someone I don’t deserve, and, if things continue as they have, I look forward to the next decade. (And if things don’t work out… I’m screwed. Being with Andrea has set the bar too high—how could I settle for any other woman?)

Excuse the grumbling. (Or just skip this post.)

Yeah, yeah, I know. (Insert standard boilerplate text here, about the fact that I haven’t written anything in a while.) It’s been a lousy couple of weeks. Or has it been a lousy month? At any rate, it’s been lousy. I’ve been drinking too much coffee, eating too little food, getting too little sleep, putting up with too much garbage at work, and just generally getting very run-down. (And it’ll probably get worse before it gets better.)

I just started blogging at the serna Bible Blog again, after an absence, and hopefully I’ll keep that up. I haven’t written anything on the Book Blog in a while, because I haven’t finished reading a book in a while. (I’m currently reading two—one fiction and one non-fiction—and they’re both pretty terrible, which might be why it’s taking me so long to finish them.)

Some updates, about things I have written lately:

  • As it turns out, I have to bring back my new shirt, so, even though I didn’t like it, it all worked out in the end. When I got home from work and took it off, one of the buttons popped off. Now, I’m not the type of person who would return a shirt just because it lost a button, but when it comes off the very first time you wear it, it doesn’t bode well for the quality of the construction.
  • I’ve started using the Stuff White People Like site to calculate how white I am. It’s the most un-scientific use of number and statistics that I’ve ever undertaken, so I’m pretty proud of myself. (Also, it’s giving me a chance to use Google Docs some more.)

Wednesday, April 09, 2008

New Shirt

I bought some new clothes for work, recently, including a bunch of dress shirts. I had to get a black one, because for me, that’s standard, but instead of a plain one, I got one with pinstripes. I wasn’t sure if I liked pinstripes or not, but I thought I’d try something new. Then, when I got home, I realized that it also has French cuffs.

Today is the first day I’m actually wearing it, and I’m definitely having second thoughts. The combination of the pinstripes and the French cuffs makes me feel like a British gangster. If only the collar and cuffs were white, it would complete the picture.

Stuff White People Like

I don’t normally link to sites that I like—especially because I tend to tire of them so quickly—but I’ll make an exception, and give a shout out to Stuff White People Like. If I had a “blogroll” of some kind, I would add this site to it.

Of course, the site is only devoted to a certain type of white person—I would say the urban professional white person—but if you know anyone who fits that category, then you’ll get endless hours of amusement from this site. And, if you are that type of white person, then you’ll probably have endless hours of entertainment in addition to the occasional uncomfortableness, when something hits a little too close to home. (For example, #82 Hating Corporations.)

Actually, I shouldn’t be so quick to assume that you’ll love the site. There are plenty of negative comments throughout, from people who don’t, so that probably indicates that there are people who don’t and won’t find this nearly as funny as I do.

Dealing With Stress

Suppose you’re having a lousy week. (Oh, let’s be honest: a couple of lousy weeks.) You’d like to put it all behind you, and spend an enjoyable evening. How do you do that? I have the solution! Follow the simple steps below, and you’ll be fine.

  1. Control the weather. These steps will only work if it’s a nice warm evening.
  2. Make plans to meet with Andrea after work, for dinner. (For best effect, it really has to be Andrea that you’re meeting with. Results not guaranteed if you’re meeting someone else.)
  3. On the way to the meeting, have your car windows open (see point 1 above), and have DJ Shadow playing on the CD player.
  4. Meet Andrea in the Yonge and Eglinton area of Toronto.
  5. Wander up and down Yonge St. for a bit, trying to decide where to eat. (See point 1 above.)
  6. Choose a Thai/Vietnamese restaurant, and go in.
    • Note: If you’re following these steps carefully, it doesn’t matter if there are two loud, obnoxious, über-yuppie women sitting behind you, having a conversation so high in volume that you can hardly have your own. It won’t have any negative effects on the evening.
  7. Order the mango chicken, and a Sleeman Cream Ale. (Alternatively, you can order some kind of pho—I think it was the dumpling pho—which Andrea has indicated is also very good. However, you may need to choose a different beverage, as the Sleeman Cream Ale wasn’t tested against the pho.)
  8. Since the Yonge and Eglinton area is pretty yuppy-ish, spend much of your meal watching yuppies walk by, out the window.
And that’s all you have to do. You will have a wonderful evening, forget your stresses and aggravations, and enjoy yourself.

Of course, you’ll have to go back to work the next day, and it will all hit you again. This is only a temporary reprieve for your problems, not a cure.

Monday, April 07, 2008

How serna Saved 3¢ On His Coffee

  • How serna Saved 3¢ On His Coffee
  • By sernaferna
  • Starring:
  • sernaferna
  • The Woman Who Runs the Till at Tim Horton’s
  • INT: Tim Horton’s. serna has purchased a medium double-double, and is poised to pay for it.
  • The Woman Who Runs the Till
  • $1.23, please.
  • serna
  • Oh, wasn’t the price supposed to go up today?
  • The Woman Who Runs the Till
  • Yeah, but I haven’t updated the cash register yet.
  • serna
  • Cool.
  • The End. Roll Credits.
Unfortunately, I had to pay full price this afternoon. A medium coffee is now $1.28. (I’m not complaining or anything—I can afford it.)

I wish I had things to write. But I don’t.

Once again, my blog has gone dormant. As have all of the blogs around me.

I loved Christopher Walken on Saturday Night Live. I always do. Something about his delivery makes for great, quirky comedy—and makes me wonder how he became an actor in the first place.

I had a dream last night that I rolled up my rim, and won a year’s supply of coffee, which equated to something ridiculous like 239,452 coffees. (Yes, it actually said that on the rim. I don’t remember the actual number, but it was huge, and it was precise.) I’m a nerd for two reasons:

  1. I had a dream about rolling up a Tim Horton’s coffee rim, and winning. (Simpsons paraphrase: “Which is odd because I usually dream about naked… Andrea.”)
  2. I spent a good portion of the dream trying to figure out how they came out to such a precise number. (And there’s no good answer. It’s just a dream. Assuming that I drink ten coffees a week—which is what I drink, on average—239,452 coffees would last me over four hundred and sixty years. Whatever the real number was, in the dream, would have still lasted me a long, long time.)
Work is lousy these days, but I won’t say any more than that. In fact, I’ve already said too much. In fact, I should probably delete this paragraph… but I don’t have the energy. Well, I should at least stop typing it, and making it longer.

Today is the anniversary of the day that Andrea proposed marriage. (In your face, everybody who’s not married to Andrea!) We may or may not celebrate. We don’t really care to celebrate things like that, usually, and yet, for some reason, I feel like celebrating. We’ll see what happens.

This post is feeling more and more disjointed with every word that I type.

I’ve still been playing with Ubuntu. I’ve got it installed on my laptop, and use it almost exclusively when I’m at home, instead of Windows. (And yet I still haven’t installed it on the home computer; just my work laptop.) Saturday I discovered a great tool called recordmydesktop, which allows you to take videos of your desktop session. I had played with this before, to try and do a quick video of what Beryl was like, but it was so complicated that I eventually gave up. So I was amazed at how simple recordmydesktop worked. I’ll probably revisit my idea, and do a quick video of Compiz Fusion in action.

More [probably disjointed] thoughts to come, as I feel like posting them.

Saturday, April 05, 2008

Bridget Grey’s Letter to Hip Hop

Andrea sent this to me, and I enjoyed it. Hopefully you will too.

Monday, March 31, 2008

Post Pourri

Many thanks to an anonymous commenter for the suggestion of using the term “post pourri”. Although… anyone who comments anonymously must be a coward. So I take it back—no thanks to you, whoever you are! I plan to claim the idea as my own.

I know that I haven’t been posting lately. I’ve been very busy, and not with things that are worth writing about. I haven’t even posted to the Bible Blog in a while, which is unusual for me—for the most part I’ve been managing to post there regularly, even if I haven’t been posting here.

My bladder problems are still ongoing, from the last time I wrote about it. I’ve stopped taking the “pee pills” that the doctor prescribed, because of a side effect which has begun to happen. He told me that it’s not a big deal if I stop taking them—it’s just a “lifestyle drug”—so I didn’t feel bad for stopping. Hopefully the side effect will go away, soon.

I’ve decided that I’m not a good cook. I’d had some good results, for some things that I made, but I think those were exceptions, rather than the rule, because everything I’ve cooked lately has turned out terribly, in one way or another. (e.g. the stew that I tried to cook recently.) We bought some lamb kebobs the other day, and I tried cooking those, but the problem is that you have to broil them, and I’ve never used the broiler feature on my oven. So they burned. (Not terribly, but a bit. They were harder than they should have been, although they still tasted okay.) I’m making waffles on a regular basis these days, and they’re turning out okay, although still not perfect. (I think I have an issue because I’m using 2% milk, instead of skim milk, which the recipe calls for; I had better results when I used skim milk.) So, because my cooking skills are somewhat lacking, I get nervous every time we have chicken because, hey, when you’re not a good cook, chicken isn’t something you want to mess around with…

I’m thinking about changing my blog template, slightly. The issue is that I have it set to take up the whole screen, in terms of width, but that’s not a good idea for people who are reading this on a widescreen monitor. (It’s hard to read text that stretches too far horizontally—which is why so many blog templates have such narrow bands of text.) So I might make it narrower, when I find the time. Unfortunately, I don’t think CSS will let me be as precise as saying “the width of the screen or X pixels wide, whichever is smaller”. So I’ll be stuck doing what every other blog template does: have a lot of wasted space.

And that’s it. The next time I think of something to write—and actually have the time to do it—I’ll do so. Until then… um… don’t do anything I wouldn’t do.

Tuesday, March 25, 2008

Google Docs. Yes, again.

I found some articles on Google Docs, that you might find interesting.

Sunday, March 23, 2008

A is A

A friend dragged me out to the bar Friday night, to see a band that she likes. Actually, I’m just kidding, she didn’t have to drag me. She just caught me on a good night. But the band she brought me to see is called A is A. (I’m no expert on the band, but I think the photo currently showing on that web site is out of date. I don’t think all of the people shown are still in the band.)

I don’t really have anything to say about it, though. I had a good time, and really enjoyed seeing the band. They’re pretty durned talented, and I enjoyed myself thoroughly. (If I knew how to dance, I probably would have enjoyed myself even more, but frankly, that’s why I learned to play guitar—so I wouldn’t have to dance, at such occasions. Except that my plan only works when I’m playing; when I’m watching someone else play, it doesn’t work so well. Let’s face it folks: Musicians aren’t the smartest people in the world.)

And that’s all I have to say about that. If anyone from A is A ever reads this, I hope that you’re suitably touched: A mediocre, amateur musician is impressed by your talents. What higher praise could there be?

Wednesday, March 19, 2008

Google Docs in use

I’ve written numerous posts lately in which I’ve raved about Google Docs, but have I ever actually used the service? I mean, is there any point, when I already have Word and Excel and PowerPoint installed on my machine? Why yes. Yes I have. Let me give you a perfect example of where the service shines:

The other day, a number of us were all working on something at the same time. We had a list of accounts that we had to populate with data, and we were working off of an Excel spreadsheet. “You work on accounts 1–12, and you do 13–24, and I’ll do 24–36…” etc. To make things more difficult, not all of the accounts we were working on needed work to be done, so one person might finish his/her list early, and then we’d have to re-shuffle the remaining accounts. But then I had a brainstorm: Isn’t this exactly where Google Docs would be perfect? We could create a spreadsheet online, and all edit it at the same time! All we had to do was list all of the accounts that hadn’t been done yet, and which ones had. Something like this:

Not Done YetFinished  
 123serna is currently working on:124
  person b is currently working on:125
  person c is currently working on:130
126   
 127  
128   
129   
    
131   
132   
133   

But the key—the really cool part about all of this—is that we were all editing it at the same time. If someone wanted to start working on item 128, they could cut and paste from that cell to another cell, and at the same time it would disappear from all of our screens, and re-appear somewhere else. No need for anyone to save the spreadsheet, and for the rest of us to refresh our screens—it all happened in real-time! There’s no need to be shouting out, “Hey, I’m going to work on number 128, nobody else work on that!” If I want to start working on one of the accounts, any of the ones in the “Not Done Yet” column were fine to work on, because if someone else had done it, I’d see it in the “Finished” column on my screen. (Or, if they were currently working on it, I’d see it to the right of the screen, beside their name.)

It’s a very simple use of the technology, and yet it saved us a lot of time and aggravation.