Tuesday, October 21, 2008

A comedy of BBQ errors

As planned, I cooked a roast on the BBQ last night, and used the side burner. It wasn’t exactly smooth sailing, but it did work.

First of all, here’s how I cooked the roast: It’s called the “indirect method” of cooking on a BBQ. You turn on one side of the BBQ, but not the other, and you put the meat on the side that’s not on. In other words, it’s not the heat from the flames that is cooking the meat, it is the indirect heat inside the BBQ. So you do the following:

  1. Season the grill. (It’s a good idea to do this every time you cook—although I don’t always do it. I didn’t last night.)
  2. Get a drip tray, and put it under the BBQ racks, on the side that will not be on.
  3. Turn on the other side of the BBQ, on medium heat.
  4. For best results, you should be using a meat thermometre, which will tell you when the meat is done. I have a nice one, from President’s Choice, that I just tell I’m cooking beef, and I want it cooked “medium” (vs. well done, or whatever), and it knows what internal temperature the meat has to reach. It’s got an end that you stick into the meat, and an electronic part that sits outside the BBQ (connected by a wire which must be burn-resistant). If you’re using one too, you should stick it in the meat.
  5. When it’s up to temperature, put the meat in the BBQ, on the side that isn’t on (above the drip tray).
  6. Wait for the meat thermometre to tell you that the meat is done.
If you follow these steps, you’ll end up with a great roast. Also, you should resist the temptation to keep opening the BBQ, to look at the meat, because every time you do, heat escapes. Just let the thermometre do its job.

But here’s what happened to me:

First of all, I turned on the BBQ, and then, just for fun, I decided to try the side burner. I wasn’t ready to cook the potatoes, yet, but I figured I’d give it a shot. And to my great chagrin, it didn’t work. (Didn’t I just write that yesterday? Every time I want to test it, it will work, but every time I want to use it, it won’t.) Luckily, though, I grabbed a lighter, and was pleased to find out that I can start it manually; it’s just the lighter button on the BBQ that doesn’t work. (Even though I can clearly see the spark, whenever I press the button.)

So I put in the meat, and went inside to… I don’t remember what I did. Watch TV or check my email or something. Maybe I was peeling the potatoes. And a little while later, I went out to check the meat, and saw that it was lightly raining. I figured I’d better cover the electronic thermometre, so I went inside and got a little plastic bag, which was the perfect size to put on top of the thermometre like a little tent.

Now, my back door doesn’t open directly onto the back yard, it’s too high. So there is a set of wooden stairs that goes down to the lawn. On my way back into the house, the bottom stair—which has been getting ready to give way for a long time—finally broke. So now, any time I use the stairs, I have to bypass that step.

A little while later, I went out to check on the food again, to find that the little plastic bag tent had blown off the thermometre. So I went back in the house and got something to rest on top of the bag, to hold it down in the wind. (There wasn’t a lot of wind, but a bit.)

A little while later, I went out to find out that the bag had blown off again—but this time, it blew onto the BBQ, and melted against the side! I pulled off what I could, and then ran inside to find something to try and scrape off the rest. Unfortunately, I wasn’t able to get it off. (Plus, since it was raining out, I tracked water and mud all over the kitchen.) The bag was red, so I now have a big red rectangle on the BBQ. I hope it’s not going to smell every time I turn it on.

I went in and got another plastic bag—although I wasn’t able to find one small enough, like the last one had been—and got more (and heavier) weights to hold it down.

By the time I was ready to put on the potatoes, there was no more drama to be had for the night. I started the side burner (with the lighter), and put them on to boil. They actually boiled and cooked quicker than they would have on the stove, even with the rain. (I put the cover on the pot, so that the rain wouldn’t get into the potatoes too much.) And I did a pretty good job of timing it, too, because I got the potatoes to finish just as the meat was finishing. When I took the pot off and brought it inside I realized that it was covered with black soot, but that came off easily in the sink.

And as for the roast? It came out beautifully.

Monday, October 20, 2008

The BBQ again. I hope this isn’t going to become a saga…

I wrote that the side burner on our BBQ wasn’t working. On Saturday, Andrea and I finally got around to borrowing her dad’s van, so that we could bring it back to the store, and either get it fixed, or get a refund. (Or rather, she finally made me get my butt in gear to do it.)

But before we did, I decided to try it one last time. We’d look pretty dumb if we got there and it worked, eh? Well, fortunately or unfortunately, it worked fine. So either:

  1. It was too windy the first time I tried to use it
  2. God just doesn’t want me to use the side burner on our BBQ, and it’s going to work every time I test it, but not when I actually want to use it
So we’re planning on cooking as many meals as possible on the BBQ for the next week or two, to keep trying it out. (If it works, but only intermittently, we can still take it back.) Tonight we’re going to try doing roast beef, and I’ll cook potatoes on the side burner. (I hope it’s not windy tonight.) (I also hope it’s not cold tonight.)

Tuesday, October 14, 2008

Google Talk

I regularly praise Google products on this blog, but that doesn’t mean that they’re perfect. I’ve been trying for a few days now to get Google Talk working, but it just… won’t. (I have a friend who has got a new job where he can’t use MSN Messenger anymore, but can use Google Talk. I thought I’d give it a shot, so we could keep in touch. Well, other than email, I mean.)

My problem is that I already have a Google account, but not a Gmail account. I use my regular email account as a sign-in name, and use that for the Google services I use (Blogger and Google Docs, mostly). So can you use Google Talk if you don’t have a Gmail account? Google says yes; according to this page:

If you’d like to sign up for Google Talk for an existing Google Account:

  1. Sign in with your Google Account email address and password at https://www.google.com/accounts/Login?service=talk.
  2. Enter your desired Talk username and click check availability! If your chosen name isn’t available, you can select from the suggested alternatives, or enter another username and try again.
  3. Optionally, enter your first and/or last name in the appropriate fields. If you enter a name, it will show up on your friends’ Talk contact lists instead of your username.
  4. Click Continue.
Sounds good—except that it doesn’t work. When I click the link, I don’t get prompted to enter a username, and I don’t get an option to enter a first name or last name. I just get… well, not much of anything, really. I get a page called “My Account” where I can’t really do anything.

So if I’m going to keep in touch with my friend, I guess he’ll have to try and configure MSN Messenger to work through his proxy. (Eric, have you tried using Pidgin? It can connect to MSN Messenger—even through HTTP—and Google Talk, and probably any other chat services you use.)

Friday, October 10, 2008

Joke

I know, I haven’t posted in a long time. At least, not here. (I have been posting to the Bible Blog—although a bit less than usual—and to the Book Blog.)

And I still don’t have anything to say. (It’s my SOP to only say something when I feel I have something to say. Which isn’t a good way of doing things when you’re a blogger—isn’t it a blogger’s duty to fill up the internet with incessant garbage?) So I’ll try to make up for my silence by posting a joke that I heard recently.

There are two older gentlemen, let’s call them Roy and Bob. Roy is telling Bob about a great restaurant that he was at the night before.

“It sounds great,” says Bob. “I’d love to try it out. What was the name of the place?”

“Hmm… the name, what was the name?” Roy says to himself. “Red flower… red flower…”

“Carnation?” replies Bob.

“No, red flower with thorns…”

“Oh, you mean rose.”

Roy’s eyes light up. “Yes, rose, that’s it!” He turns to the woman beside him. “Rose, what was the name of the restaurant we went to last night?”

Monday, October 06, 2008

Nuit Blanche

We went to Nuit Blanche on Saturday night. It was… disappointing. If this is the state of Toronto’s art scene, I don’t expect us to be leading the world when it comes to art. (Not that I consider myself an expert, of course, so don’t just take my word for it.)

However, we managed to have a good time anyway, even without the art. For that matter, since I’m not a big patron of the arts, it might not even have made a difference if the art had been magnificent.

Tuesday, September 30, 2008

Flickr

A colleague of mine was having trouble sharing her photos in Flickr, and, since we weren’t too busy this week, we spent quite a bit of time working on it together. (I believe she’s got it all set up properly now, in case you were worried.) She made me a “contact”, and I’ve spent hours watching her pictures. (I say “watching” because when I’m in a conference call where I don’t have to do much, I go to one of her picture sets, and just turn on the slideshow, and let it go by while I listen to my call.)

So now that I’ve been watching all of her photos, I’m starting to think that I need to go on vacation again soon, so that I’ll have more photos to put up in my Flickr account—which, these days, is mostly consisting of book covers from the serna Book Blog. Not that I expect that to happen any time soon; no vacations planned for a while. Maybe I should finally go and scan in my wedding photos, and share those…

BBQ redux

I finally got a chance to use the side burner on my BBQ last night—or so I thought. We decided to make curry, the very thing I’d wanted a side burner for. I got everything prepared, and went into the back yard to start up the BBQ, only to find… that I couldn’t get the side burner to start. The main burners started fine, but the side burner wouldn’t. (I did test it, when I first put the thing together, and it worked at the time.)

The thing is, though, that I don’t know if it’s defective, or if I just didn’t hook it up properly. Either one, in my mind, is very possible. It’s a cheap BBQ, but I was never really sure from the beginning if I’d hooked up the side burner properly. (It seems like the venturi tube might not be connected correctly—there’s a big gap which may or may not be necessary, although I can’t see any other way to hook it up—but I can’t find any instructions/diagrams on the net to help me figure out if it’s connected properly or not.)

I tried using the main burners, but the pot was too far away from the flame, so the oil wasn’t getting hot enough. I had to resort to bringing it back inside, and doing it on the stove.

Friday, September 19, 2008

A shindig, and getting my writing analyzed

Andrea had a “thing” to go to last night, and I went along too. It was for some organization that works with non-profit organizations in Toronto; if they want a space to do a fundraising event, this group can provide a space for free, and hook you up with deals for food and drink. Seemed like a good deal, at first glance, although I’m not posting the name of the organization, in case it turns out that it’s a rip off.

The space itself was excellent. Top floor of a downtown building, with an amazing outdoor patio that goes all around the building. (Actually, now that I think about it, I think it was only three sides of the building. But still, it was really well done.) It was weird being there, though, because it was supposed to be for non-profit organizations, and everyone there looked… well… rich. They obviously weren’t grassroots organizations; they were the big organizations, that everyone has heard of. (The ones that have so much money they don’t need this type of service.) Just watching them all interact, and seeing how they were dressed, it seemed a lot more like a bunch of CEOs getting together than people working for non-profit organizations. So of course I was uncomfortable, because I’m never comfortable around rich people.

But one of the things they had set up was a woman who will analyze your handwriting, so Andrea and I gave it a shot. Of course, everything that she told me is what I’d expect to be told; I’m intelligent, I’m independent, I’m a leader not a follower, etc. I’m pretty sure she’d say the same stuff to everyone. (You’ll never hear her reading someone’s handwriting, and say, “Oh! You’re not very bright, are you?”) And, since she did both Andrea and I together, it turns out we’re perfect for each other. (Again, although I’d find it hilarious, I doubt she’s ever talked to a couple and said, “wow, you guys might as well just break up right now.”)

She did tell me one negative thing, though: The paper asked me to write my favourite saying or philosophy of life, and I put “Nothing is ever easy.” (If you know me in real life, you’ve probably heard me say that. Many times.) She thought that was too pessimistic, so she crossed it out, and wrote, “everything is always easy”—which is just silly. We all know that everything isn’t always easy.

Anyway, I hope that the organization turns out to be good for small organizations, and that Andrea ends up hosting some events there, because I wouldn’t mind going back.

Wednesday, September 17, 2008

The BBC Lost Land of the Jaguar series

Because Andrea and her family are Guyanese, every once in a while I get sent a link to some Guyanese-related site, or show, or whatever. We recently got sent a link to a BBC series, called Lost Land of the Jaguar, which someone has helpfully put up on YouTube. (The preceding link is to the BBC’s website, not YouTube.) It is absolutely fascinating, having to do with the Guyanese rainforest—perhaps the only above-ground place left in the world where nature is still untouched by modern-man. (If not the only, one of the only.)

Andrea and I watched the first two episodes last night, and will probably watch the third episode soon (schedule permitting). Unfortunately, YouTube limits you to about ten minutes per video (unless you sign up for a paid account), so the episodes are in ten minute segments; however, I’ve created a couple of playlists, which should make it easier to watch them in one contiguous group:

I haven’t yet created a playlist for Episode 3, because I’m not sure if it’s fully uploaded yet. When we’ve watched it, and confirmed how many pieces there are to that episode, I’ll create a playlist for that one, too. (I guess you can watch out at my YouTube profile page, for the next playlist to show up.) The first episode was seven videos, and the second one was six, so I’m not sure how long the third one will be.

I would have preferred to simply link to the BBC iPlayer—so that I could be sure that the videos wouldn’t get taken down, as they might on YouTube—but they don’t seem to have this show available online.

Wednesday, September 10, 2008

Quantum of Solace redux

There is another trailer online for QoS:


Unfortunately, based on the two trailers I’ve seen so far, it seems like a great action movie, but it doesn’t feel like a Bond movie. Hopefully I’m wrong—after all, I’m only basing these feelings on a couple of trailers.

Tuesday, September 09, 2008

Separating Programming Sheep from Non-Programming Goats

I found this blog entry to be very interesting. It’s about a paper that has been written on distinguishing those who can program from those who can’t. (The blog entry contains a link to the paper itself, too, which is here.)

I should say that the intent of the paper is not elitist. “We can program, and you can’t, so don’t even bother to try.” But programming is something that people seem to have either a natural ability for, or… well… don’t. As the authors of the paper say:

Learning to program is notoriously difficult. A substantial minority of students fails in every introductory programming course in every UK university. Despite heroic academic effort, the proportion has increased rather than decreased over the years. Despite a great deal of research into teaching methods and student responses, we have no idea of the cause.

It has long been suspected that some people have a natural aptitude for programming, but until now there has been no psychological test which could detect it. Programming ability is not known to be correlated with age, with sex, or with educational attainment; nor has it been found to be correlated with any of the aptitudes measured in conventional ‘intelligence’ or ‘problem-solving-ability’ tests.

That quote is followed closely by this sentence, which I rather enjoyed:

We point out that programming teaching is useless for those who are bound to fail and pointless for those who are certain to succeed.

The authors talk about three significant hurdles that students encounter, when learning to program: assignment and sequence; recursion/iteration; concurrency. They then go on to say this, which I found very interesting:

…. Assignment and sequence … hardly look as if they should be hurdles at all: storage of / remembering information and doing one thing after another are part of everyday patterns of life and thought, and you might have expected (as at first do most teachers) that students’ experience could be analogised into some kind of programming expertise. Not so: it is a real hurdle, and it comes at the very beginning of most programming courses.

I’m sure, when I was first learning to program, that I became frustrated with fellow students, when they couldn’t figure out how assignment works. I guess this paper explains both sides of the coin: why my fellow students couldn’t get it, and why it seemed so obvious to me.

But enough preamble. Let’s talk about the test itself. It consisted of questions such as the following (click to see a bigger version):
sheep and goats sample question
And the authors found these results:

We could hardly expect that students would choose the Java model of assignment … but it rapidly became clear that despite their various choices of model, in the first administration they divided into three distinct groups with no overlap at all:

  • 44% used the same model for all, or almost all, of the questions. We call this the consistent group.
  • 39% used different models for different questions. We call this the the inconsistent group.
  • The remaining 8% refused to answer all or almost all of the questions. We call this the blank group.

We did not interview our subjects to determine anything about their group membership, so we do not know whether students chose consciously or unconsciously to follow one strategy or another, nor how conscious choices (if any) were motivated, nor what any particular choice meant to a subject who made it. We have no information about how group membership correlates with earlier education, employment experience, age, sex, marital status or indeed anything else.

The great thing about the study is that the test was administered twice: Once before the students had had any computer programming studies, and once after they had completed their first course. (The authors aren’t really sure whether it was planned to give the test prior to instruction, or if it was a happy accident.) They found that the results were fairly consistent: People who fell into one of the three groups before taking the course tended to fall into the same group after taking the course.

Interestingly, the authors then talked about using these groups to predict who would be good programmers, and who wouldn’t. I would have expected that the “consistent” group would be the most successful programmers, but I would have been in the minority:

Speculation is part of science, though, and those to whom we have recounted this tale have usually been ready to try it. Told that there were three groups and how they were distinguished, but not told their relative sizes, we have found that computer scientists and other programmers have almost all predicted that the blank group would be more successful in the course exam than the others: “they had the sense to refuse to answer questions which they couldn’t understand” is a typical explanation. Non-programming social scientists, mathematicians and historians, given the same information, almost all pick the inconsistent group: “they show intelligence by picking methods to suit the problem” is the sort of thing they say. Very few, so far, have predicted that the consistent group would be the most successful. Remarkably, it is the consistent group, and almost exclusively the consistent group, that is successful. We speculate on the reasons in section 7.

And what do they feel are the results of this study? First of all, they feel that they have a predictive test, as to who will be a good programmer, and who will not.

[One of their graphs] suggests that it is extremely difficult to teach programming to the inconsistent and blank groups. It might be possible to teach them, if we concentrated on trying to persuade them to see a programming language as a system of rules (though the evidence in section 6 below seems to suggest otherwise).

The consistent group seem to be much easier to teach. We speculate that they divide into two groups: the very successful ones find programming easy and may perhaps be those who ought to follow a conventional computer-science education, with lots of formal content; the moderately successful perhaps are the software engineers, those who can program but can’t imagine that they will ever enjoy it, and are content to submit to management discipline and to be drowned in UML (ugh!).

As a side-note, why does everyone hate UML?

I don’t know how scientifically accurate this study will turn out to be, or if the authors will attempt to try it in a larger experiment with more subjects, but I found it interesting nonetheless.

Sunday, September 07, 2008

Quantum of Solace

The new James Bond movie, Quantum of Solace, is coming out in November. I don’t know a whole lot about it, but the trailer is up on YouTube. (It was actually put up way back last June, but as always, I’m behind the times.)


It doesn’t grab my attention the way the previews for Casino Royale grabbed my attention, but I’m looking forward to it.

Thursday, September 04, 2008

Finding Parking in Toronto

Every once in a while I have to drive downtown, and my biggest hassle is usually “where can I park?” Unfortunately, my first impulse is to go to the Green P Parking website, but it turns out that their site is lousy. I’ve never satisfactorily been able to use it to find a parking lot near where I’m going. (It’s been a pet peeve for a while, and I finally sent them a long-winded email with suggestions to improve their site.)

However, just as my blood was getting its hottest, I found a great site: StopFinder. It’s a mashup that uses Google Maps; type in your destination, and even what time you’re going and how long you’ll be staying, and it will give you:

  • All of the parking lots in the area—something that the Green P web site cannot do, I can’t stress that enough—with the closest lot highlighted for you
  • Prices and hours of service for each of the parking lots
  • Colour-coded rankings of the lots’ prices
  • Bus and subway stops in the area, with links to the TTC schedule, so that you can figure out when the bus will arrive
It looks like this:
StopFinder
Of course, now that I’ve put up a specific destination in that screenshot, knowing my luck they’ll tear down the club that’s currently there, and build some kind of sex club or something, that will last for twenty years. And anyone who comes to this post will be wondering, “why did serna put up a link to a sex club?!?”

So there you have it. If you’re going somewhere in Toronto, and want to know where to park or how to take the TTC there, try StopFinder.

Wednesday, September 03, 2008

Grilled Asparagus

Wow, this is my third post of the day. I’m on a roll!

I’ve already posted a recipe for some great burgers. Now it’s time to post a link to a recipe for grilling asparagus on the BBQ.

Actually, there’s nothing revolutionary about it. I’m finding that when it comes to grilling vegetables on the BBQ, the steps are usually the same:

  • drizzle the veggies in olive oil, usually combined with lemon juice
  • grill them on medium heat, usually about two minutes per side
And this asparagus recipe is the same. (No lemon juice, in this case.) The only thing I did differently from the recipe was that I didn’t use as much salt as the recipe’s author had suggested—even though s/he said to “trust” him/her that it wouldn’t be too much.

Some day, I’ll post my instructions for grilling the perfect steak. Unfortunately, I tried it again last night, and, although it came out great, it still wasn’t perfect.

Chrome

Since I’m always behind the curve when it comes to writing about new stuff, I guess I should mention—a day or two after everyone else has—that Google has introduced a new open-source web browser, which they call Chrome.

Now, you might ask yourself: Why has Google built its own web browser? Isn’t there already an open-source web browser, called Firefox, which by most accounts is pretty darned good? And if you want to do something interesting with the browser, couldn’t you do it by creating a Firefox plugin? (e.g. Ubiquity.) And Google expected that response, and put up a page saying why they did it.

But the thing is… I still don’t get it. I mean, I read the page, but it didn’t really answer the question, in my mind: Why did Google feel that they need their own browser? Why couldn’t they build on something like Firefox? I went through the little demo videos on their features page, and although it seems like a great browser, it also seems like it’s just a series of incremental improvements over Firefox or Internet Explorer 7. Not something revolutionary.

Now, don’t get me wrong. I’m definitely not saying that I think this is a dumb idea. Most of the folks over at Google are a lot smarter than I am, and I’m betting they had a good reason for doing this. And I’m also thinking back to when Firefox first introduced tabbed browsing, and how I didn’t think it was such a big deal, because that was only an “incremental improvement” over having multiple browser windows open. (“You’re just trading multiple buttons in your Taskbar for multiple tabs in your browser,” I thought, “What’s the big deal?”) But now I can’t imagine not having tabs in a browser.

In any event, I’m downloading Chrome, and will give it a try. (I’ve written too many love letters on this blog to other Google products not to give it a try!) I’m prepared to be blown away, but expecting to find “just another browser”, maybe slightly better than Firefox. Time will tell.

Coincidences

I’d thought I’d posted about this before, but apparently I haven’t. So I’ll do so now.

I get a lot of coincidences in my life. (e.g. see this previous post, for a perfect example; I’m often thinking of a particular Simpsons episode, only to turn on the TV the next day and find it playing.) I’ve sometimes thought of creating a “serna Coincidence Blog”, to document all of the many coincidences I encounter.

Knowing me, the following will probably happen:

  • I will hesitate for a long time—mostly because I won’t be able to settle on a blog template to use.
  • I will finally do it, because for some bizarre reason I love creating blogs, and I just won’t be able to help myself.
So… yeah. Stay tuned for that.

Saturday, August 30, 2008

The BBQ: working great

Well, it’s been over a week. And how’s the BBQ doing? As a matter of fact, it’s doing quite well. Unfortunately, the very first thing I tried was steak, and it didn’t come out well. (A bit more well done than I like, even though I followed instructions which should have made it medium. It wasn’t bad—I still enjoyed it—it was just too well done.) We’ve also done lamb burgers from President’s Choice, which were great, lamb skewers (also President’s Choice, also great), zucchini and eggplant, chicken with BBQ sauce, salmon steaks and salmon kebobs, and finally, burgers. Everything has been great.

Speaking of which, if you want a really good recipe for making burgers, see this recipe. You won’t regret it.

What I haven’t yet done, but hopefully will soon, is try making curry on the side burner. As it is, I’m too busy enjoying the flavour of the BBQ on my other foods, but using the side burner for curry was one of the selling points of this BBQ for me, so I owe it to myself to give it a try.

Wednesday, August 20, 2008

BBQ

We finally—finally!—bought a barbeque. We’ve been living in our townhouse for over three years, and all that time I’ve wanted a BBQ, and now we finally have one.

One of the main things holding us up was that Andrea’s dad had a used one, that he had volunteered to give us, but we never got around to digging it out of his garage. So we finally went and picked it up on Sunday. (Actually, we went on Saturday afternoon and wiped and hosed it down, to get rid of the dust, and then picked it up on Sunday, after it had dried off.) Unfortunately, it turned out that it didn’t work. The burner wasn’t connected properly to the hose from the propane tank, and I couldn’t figure out how to connect it properly. Plus, it was pretty rusty in there. So we decided to go and get a new one, because I didn’t want to mess around with propane connections. Which, in retrospect, I’m happy about, because we also wanted a side burner, which the free one didn’t have.

I had been thinking about getting a Weber. That seems to be the cream of the crop, when it comes to BBQs. However, although Weber BBQs last forever, they are also very expensive. So, after much soul-searching, I decided that it wasn’t worth the money; even if a cheaper BBQ didn’t last forever, it would probably still be cheaper in the long run.

Once I’d made up my mind to get something cheaper, I actually thought about getting a President’s Choice BBQ, from Fortinos. For about half the price of a Weber, I could get a BBQ with a side burner. There was a good chance that it would be a piece of crap, but, on the other hand, President’s Choice is pretty good, so there was also a chance that it would be a good, lasting unit. But we finally gave up, and got a Sterling, which is even cheaper. Who knows how long it will actually last; I’m hoping it’s not a disposable BBQ! (Obviously, if we have to buy a new one every year, we would have been better off getting a Weber…)

Anyway, you probably don’t care about all of that. I got it put together on Monday night, which wasn’t as bad as I’d been led to believe. It took an hour or two, but very little cursing. (I did end up with one extra nut and bolt, which I couldn’t attach; the holes in two pieces of metal that it was supposed to connect together wouldn’t quite line up. But there were three other sets of nuts and bolts keeping them together, so I don’t think it will cause any problems.) I also couldn’t get the lighter button to work, but wasn’t overly worried about it, since we have a lighter.

I had been hoping to fire it up on Tuesday, and cook something. (I’d been further hoping that the “something” I cooked would be a nice, juicy steak.) Unfortunately, we had leftovers in the fridge that we had to eat out. And, since I’m an adult now, and I have to make mature decisions, we decided to eat the leftovers first, and maybe cook something on the BBQ on Wednesday. I did take the opportunity to season the grill, though, and I also figured out why the lighter button hadn’t worked. (I’d missed connecting a wire. And it’s a good thing I figured it out, because the wire was within the BBQ—or very close to it, anyway—and probably would have caught on fire or something.)

I’m crossing my fingers, hoping to be able to cook something tonight. (I’m also crossing my fingers that I’ll be able to cook it well—it will seem like a terrible waste of money to have bought a BBQ, if it turns out I have no BBQing skills.)

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.