Wednesday, December 25, 2013

Left-over mashed potato croquettes

I've got a weakness for salty, savoury, starchy foods. This makes mashed potatoes and gravy one of my favourite holiday indulgences. But what of the leftovers? Let's face it: mashed potatoes don't take well to reheating. This once-delightfully fluffy mass of salty starch is now a stubbornly rubbery brick that refuses to yield to the reapplication of heat.

What do we do with such an intransigent leftover? The same thing we do with any nonconformist: tar it and feather it! Or at least the culinary equivalent: batter it and fry it!

Part of this woefully incomplete breakfast!

Left-over mashed potato croquettes

Any amountMashed potatoes, refrigerated overnight
1/2 cup + 1/4 cup Rice flour
1/4 cup Finely ground flax seeds (about 3tbsp before grinding)
1/2 cup Water
1 tsp Salt
1/2 cup Corn meal
1/2 cup Nutritional (flaked) yeast
1/4 cup Sesame seeds
4 cups Sunflower oil for deep frying

Equipment:

You will need 3 medium bowls and a wax paper or parchment-lined sheet pan for the battering process, a thermometer and wok or large saucepan for deep frying, and a wire rack with paper towels for drying.

Method:

Put the first 1/2 cup of rice flour in the first bowl.

In the second bowl, whisk together the ground flax seeds with the water. Let it sit for a couple minutes and it will take on an eggy consistency. Now whisk in the other 1/2 cup of rice flour and the salt. Add water if necessary to achieve a runny library paste consistency (see photo).

In the third bowl, combine the corn meal, nutritional yeast, and sesame seeds.

Now roll a golf-ball sized ball of mashed potatoes in your hands and drop it into the rice flour. Roll it around in the bowl to coat it evenly. Move the dusted potato ball into the flax seed paste and roll it around to completely coat it in the paste. Finally, transfer the glue-covered ball into the corn meal, yeast, and sesame seed bowl and roll it around to coat. Move the finished ball to the paper-lined sheet pan.

Repeat the above until all the mashed potatoes are used up. Don't start heating the oil until all the potato balls are battered and lined up on the sheet pan, or you'll be sorry!

Okay, now heat the oil to 180°C (350°F). Deep fry the balls 4 at a time. Monitor the temperature of the oil, and adjust the heat to keep it locked in at 180. Cook to an internal temperature of 55°C (130°F), which should take 3 or 4 minutes. Now they're croquettes: golden brown and delicious! Move them to the paper towel-lined rack for cooling.

We served these croquettes on Christmas morning with a Sriracha sauce aioli. Yum!

Saturday, October 20, 2012

"Daddy is a Robot" on Ada Lovelace Day

Tuesday this week was Ada Lovelace Day, an annual celebration of the women in science, math, technology, and engineering who have inspired us to become who we are today.

Ada Lovelace Day is doubly important to me: in Grade 3—when I was 8 or 9—the person who introduced me to computer programming was a smart, supportive, and encouraging woman named Lise; now I have a six-year-old daughter named Ada who is smart as a whip, kind and thoughtful, and full of creativity. Lise engendered in me a lifelong joy of programming by teaching me Logo and BASIC on an Apple ][; naturally, I've been eager to give Ada the same chance by teaching her Logo.

But not on an Apple ][. Not on an electronic computer at all. Not just yet. Instead, we've been playing the "Daddy is a Robot Game."


The setup is simple: I used index cards, some sticky labels, a pen, and a pencil. I cut up the labels into small rectangles and wrote the basic Logo commands on them in pen, like this:


Note the blank space to the right of the commands. That's where the programmer writes in the parameter. I gave Ada a pencil with an eraser for this, which helped a lot when it came time to fine-tune and debug the program.

To get things started, I put a few simple commands (FD 2 RT 90 FD 2) on a card. I gave this card to Ada. I explained that when I was a robot, I would follow the instructions on any card that someone hands me. So I became a robot, Ada handed me the card, and I followed the instructions. I ended up running into a wall. Ada was hooked immediately!

Coming up with inspiration for a program turned out not to be a problem. On her own, Ada quickly decided to try and get me to go upstairs.

We designated a place on the floor as "home," and Ada made a card that had just the HOME command on it. At first, she would hand it to me before each run through her program. Then, to make things efficient, she wrote HOME on the back of her program card, then she invented the TURN command, which told me to flip the card over and run the program on the other side. How quickly programmers want to become language designers!


Giving the arguments to LT and RT in degrees was not a problem. Ada is in first grade now, and although she's not completely comfortable with "big" numbers, it was a comfortable stretch for her. She had no trouble remembering 90 degrees is a right angle and 180 degrees reverses course.

But from my point of view, the most amazing part was to watch Ada debug the program. It came naturally to Ada to sit at the table and visualize herself moving through the program as me. She would locate the instruction that caused me to overshoot or undershoot a turn—or run into something—and then erase the number and write in a different one.


Taking this exercise to the computer will be a small step: we're already using real Logo syntax, and we're working with the concept of starting over with a blank slate in the home position (in Logo, you do this with the DRAW command).

I have no idea what Ada will want to do when she grows up. Veterinarian, Astronaut, and Drummer are all on the list. I wouldn't be surprised if she adds Computer Programmer after we take this game onto the computer. Whatever she chooses to do, I think that it can only help that she's making the neural connections now that will give her an intuitive understanding of what it means to program a computer.

If you're a mom or a dad, a teacher, or an uncle or an aunt, why not try this with the 5- and 6-year-olds (or older) in your life? It uses simple supplies you probably have in a desk drawer already, it takes minutes to get started, and it just might lead to a lifetime of fun.

Wednesday, October 10, 2012

JavaOne 2012 Retrospective

I think I can best summarize my experience at this year's JavaOne in just two words: It's Back!

After some well documented missteps which I witnessed first-hand in 2010, I can confidently say that that JavaOne conference has completely recovered from the change of venue and it once again feels like a first-class conference. The organization was spot-on, and the content selection was superb. A big thank-you to the organizers who worked tirelessly, listened to our feedback, and made JavaOne 2012 the year to beat!

My highlights this year started with the Java Community sessions on Sunday. This is a tradition that started in 2009 with the Sun Community Days conference, a free conference for community projects that took place at Moscone on the Sunday before JavaOne. It was nice to share information on the different techniques for getting people engaged in the Adopt a JSR and Adopt OpenJDK initiatives. This is something we are trying to get more involved in at the Toronto JUG. The outcome for me is that we plan to hold a hack night in Toronto where we will focus on getting a preview implementation for one JSR up and running on everyone's machine, then we'll try coding something against it so we can provide feedback to the expert group. Of particular interest are the JSON processing API and the new Date & Time API. If there is a JUG in your area, you should do this too! Now that JSRs are developed in the open, you are partly responsible for the APIs. There's no excuse to stay uninvolved!

After the community events came the Sunday evening keynotes. For me, the standout was the Java Technical keynote.

Rather than a boring list of features and roadmaps, the technical keynote was structured as a conversation between Brian Goetz and Mark Reinhold that arose from a code example from the previous segment (which was on JavaFX). Brian bemoaned the "beef to bun ratio" in the example and used it as a vehicle to demonstrate the language and library changes that are coming in Java 8 as part of Project Lambda. It was entertaining and informative: the most fun I've had at a technical keynote in quite some time!

Another highlight at the technical keynote was seeing OpenJDK and JavaFX running on ARM. We saw OpenJDK running on two different ARM systems, one of which was (of course) a Raspberry Pi. Cool stuff: in terms of development tools and deployment stack, embedded computing is now virtually indistinguishable from desktop computing. Or server-side computing, as several people showed earlier this year.

In Monday's sessions, I learned an interesting tidbit: did you know that the Jackson Java-JSON marshalling system not only outperforms the other established JSON marshallers within the JVM, but it actually gives Protobuf/Protostuff and Thrift a run for their money. I wonder how it stacks up against the generated JSON marshallers we use with Errai (the project I work on at JBoss). There's something new for my to-do list!

Monday afternoon (in fact, every afternoon), we had the opportunity to sit outside in the beautiful Taylor Street Café and enjoy some free beer and coffee from the "Buzz House" bar.



This was the best way I found to meet new people and have a chat. One of my most memorable chance encounters was with someone from the team that builds the app that science teams use to apply for time on the Hubble Space Telescope. His team also maintains the software that actually executes the repositioning commands and moves the telescope up in orbit. His team is really excited about the James Webb Space Telescope, a much larger instrument that will launch in 2018, achieving an even clearer view by orbiting near the Earth-Sun L2 Lagrange Point (between the orbital paths of Earth and Mars). One of its design goals is to get a good look at planetary systems other than our own. Exciting times ahead!

Monday night, we were off to the official unofficial Java Posse hangout at Kate O'Brien's. We had a nice chat with the Posse and the other listeners who showed up.

On Tuesday, I teamed up with Christian Sadilek to co-present at the JBoss booth in the exhibition hall. First, we did a live-coding presentation where we had some fun with Errai, hooking up accelerometers to CDI events using the HTML5 device orientation API, then visualizing the data with CSS3 perspective transforms. In our demo, we even streamed these events to the server and rebroadcast them back to clients for a social "tilt party" effect. [will edit with a link to the video once it's available.]


Tuesday evening, I attended the BOF that's a perennial favourite of mine: "Java Champions and JUG Leaders meet the SunOracle Executives."


In this evening session, top executives from Sun (and now Oracle) submit themselves to some tough questions from JUG leaders and Java Champions. I really appreciate these guys putting themselves in the hot seat and not just defending past missteps but listening to us and putting forward suggestions on how to make things better. This year's execs were Henrik Stahl and Georges Saab. They did a good job maintaining the honesty and earnestness I've come to expect from this session. Henrik even closed by asking for this to be a 2-hour session next year. Right on!


On Wednesday, Christian and I were back in the JBoss booth with more live coding, this time showing Errai's typesafe JAX-RS client and our browser-based JPA implementation that persists and retrieves JPA entities in HTML5's localStorage. [again, a link to the video is coming.]

Incidentally, on Wednesday I had the opportunity to tell Linda DiMichiel, JPA spec lead, about my efforts implementing JPA2 in the browser. She literally laughed out loud. I'm choosing to take that as a compliment. :-)

On Thursday, Christian and I presented our technical session. In that session, which we lovingly called Taming the Spaghetti: Rich Web Applications in Errai, we discussed the motivations for designing web apps to run large portions of their code in the browser; we talked about why it's a big help when the browser-side code and the server-side code are written in the same language, and we made our case for doing that in Java with the help of the GWT compiler. Then we showed how the Errai framework makes everything better by reducing boilerplate, promoting a declarative code style, and allowing maximum sharing of code between client and server. Then we dove into the specific features and demoed them with some live coding.

In my not-so-humble opinion, our talk hit the right balance between well-paced, informative, and funny. And thanks to the JavaOne team, that talk is already available online for everyone to stream for free. Check it out now! (The link for streaming is under Media on the right-hand side.)

All in all, it was a great JavaOne: I met new people, chatted with those I met in previous years, and got lots of time with my out-of-town JBoss colleagues. Plus the presentations I was involved in went really well. Thanks to all who attended!

Monday, November 14, 2011

Devoxx 2011 Day One


This is the 10th anniversary of Devoxx, and my first time attending. I've attended JavaOne three times, most recently as a speaker: I shared the stage with Dan Fraser and we presented on a fun project we helped out with back in 2008.

This year Dan and I thought it was time to give Devoxx a try. So far, we have not been disappointed!

Sessions

With one exception, the sessions have been great. Today was divided into two three-hour "university" sessions followed by a series of 30-minute quick talks about open source software tools.

As a Java expert and Scala neophyte, I found Mario Fusco's introduction to the Scala language this morning to be well-balanced and informative. Mario's material was challenging enough to keep me engaged for the full 90 minutes, but not so ambitious that it left me behind. After the break, Kevin Wright took the podium to talk about Scala as an Agile Enabler. Although Kevin is clearly well-versed in the professional use of Scala, I don't feel his talk was particularly focused on Scala as an Agile Enabler, or on any particular topic. Kevin's enthusiasm for Scala was clear, but unfortunately the talk was a bit too undirected. The redeeming feature was the Q&A session at the end, where Kevin related some of his real-world stories of Scala in daily use on a multi-person team.

After lunch, we were treated to a fascinating talk on Continuous Delivery by David Farley of LMAX. David presented in great detail on both the theory and practice of Continuous Delivery, which he pointed out is often overlooked by agile teams even though it's the first item of the Agile Manifesto. Part of what kept this talk so engaging were all the references to the actual process in place today at LMAX. This kept the talk grounded in reality, and I think attendees left with the feeling that through a process of gradual improvement, we can all eventually achieve a similar state of Release Nirvana.

Following the Continuous Deployment session, the pace picked up as the rapid-fire 30-minute sessions came up.

Aslak Knutsen and Dan Allen presented a lively talk jam-packed with Arquillian. From a cold start assuming no prior knowledge, Aslak and Dan introduced Arquillian, illustrated a dozen use cases with live working demos, then dug into the plugin API and demonstrated how to use and create(!) Arquillian extensions. Yes, this was a 30-minute talk and somehow they managed to finish on time. :)

Next up, Ben Evans stood in for Kirk Pepperdine and presented "Are your GC Logs Speaking to You?" Ben did a great job illustrating the ins and outs of HotSpot's generational garbage collectors, how to read and understand their log output, and covered a few need-to-know basics on the tuning parameters you can use to change the size of the different heap areas.

Finally, Marian Muller presented on an exciting set of features that SERLI is contributing to Glassfish: versioning and rolling upgrades. The versioning feature allows the server administrator to deploy new webapps into the container while retaining the previous version of the app in a deployed-but-disabled state. Rollbacks are then simple: you just ask Glassfish to re-activate the older deployment. During this switchover, there is still a period of downtime where the app is unavailable. This brings us to the companion feature: rolling updates. Although this is still a work in progress, Marian demonstrated several different policies for "no downtime" switchover between one active-and-deployed context and an inactive-and-deployed version.

And that was just day one. There are so many interesting speakers, I've already had to make lots of difficult choices. Good thing I'll have the chance to see what I missed on Parleys.

Surprises

It's cold here! From what I heard, I was expecting more moderate temperatures. Maybe 10-15ºC. So far, the tempature has been hovering around the 4ºC mark. Good thing I packed some layers.

The "hall track," which tends to be what I remember most about the conferences I attend, hasn't been working for me so far. At JavaOne, there were many opportunities to break the ice and start fascinating conversations with strangers: sharing tables at lunch, while queueing for a popular session, or in one of the many lounge areas set up throughout the venue. Here at Devoxx–this year, at least–breakfast and lunch are eaten at small standup tables, there is no need to queue for sessions, and I haven't spotted any designated lounging areas. Tomorrow I will just have to start picking people at random and saying "hi."

In Conclusion

I'm happy we chose to come to Devoxx this year. Antwerp is a beautiful city, Belgium is full of great beer, and I'm happy to support a truly independent community-run conference. I look forward to the next four days with eager anticipation.

Sunday, August 8, 2010

Making Pickles

One of the great things about living in Toronto is the abundance of corner stores with fresh, cheap produce. There's at least one within walking distance of most inner city houses and apartments. Stores like these are made possible by the Ontario Food Terminal, a wholesale market where producers lease stalls and buyers can enter for a small fee. From the mom & pop operation down the street to the multinational megamarkets, all kinds of buyers show up early every morning.

The selection at the corner store tends to be smaller, fresher, and cheaper than the megamarts. Beyond the traditional Western staples of carrots, onions, potatoes, and so on which are always available, I imagine the selection is based mostly on what was cheapest or best presented last time the owners visited the food terminal.

For the past 4-6 weeks, our local store has kept a big box of small cucumbers filled. The sign says they're "Dill Cucumbers." I'm not sure if there really is such a thing (maybe that's what they're really called!), but turning them into dill pickles sounded like a fun project. So I bought some.

I don't have any canning experience or equipment, so I started by looking up recipes for refrigerator dill pickles. There are many to choose from, and my survey of 10-15 of them tells me the essence of the dill pickle brine is vinegar, water, kosher salt, and dill weed or seed. I combined the following in a saucepan and brought it to a boil:

1 part pickling or kosher salt (by dry volume)
4 parts vinegar
12 parts water
1 tbsp dill seeds
1 tsp pickling spice




Once the salt dissolves into the brine, it doesn't add much volume. You can ignore it in your calculation. So, you can make 1 litre of brine using 75cL water, 25cL vinegar, and 62.5mL salt.

Some recipes call for boiling the brine where others say to just work with room-temperature ingredients. I decided to boil the brine mostly because I believed it would extract more flavour from the spices, and perhaps speed up the initial stage of the pickling process. Maybe next time I'll try it at room temperature to see if it makes any difference.

Of the recipes that did call for boiling the brine, a few of them said to chill the cucumbers in an ice water bath before pouring the brine over them. The claimed advantage is that the pickles will come out crunchier if you chill them first. I did this. It makes sense--cold pickles should be less likely to get cooked by near-boiling brine, but of course the cold probably cancels out the possibility that the hot brine will kick-start the pickling process.



After their ice bath, I packed the following into three jars (I later discovered we had a large jar big enough to hold everything. I'll use that next time!)

1 bunch of fresh dill
1kg of pickling cucumbers, chilled in ice water
4 cloves of garlic, sliced
1/2 white onion, thinly sliced



Then I poured the boiled brine over the ingredients in the jars, lidded them, and waited for them to reach room temperature (several hours).



How long did they take to become pickled? I tried one after a few days, and it was mildly pickled. I was actually worried that there was too much water and not enough salt and vinegar in the brine. But after a full seven days in the fridge, the cucumbers were pickled all the way through and had a pleasant abundance of sourness and saltiness.

I was surprised that the dill flavour was less prominent than expected. Dill is a distinctive flavour, but quite mild. I assumed a whole batch of dill weed plus some seeds would have provided sufficient flavour. Perhaps with more time in the fridge, the dill flavour would have become more pronounced. Which brings me to my next point…

These pickles were quite popular, both with us and our guests! They were completely gone within three weeks of my making them, which effectively means we ate them all in the two weeks after they "matured." A store-bought jar of pickles typically lasts several months in our house.

In conclusion, making refrigerator dill pickles was fun and easy. Not only would I do it again, but I already have. The second batch is ready for consumption. I think I'll go have a pickle now.

Wednesday, July 7, 2010

I've started contributing to the Android Cookbook, a brand new project of O'Reilly which is being run by my friend, Ian Darwin. Since you retain ownership of the material that you submit and simply license it to O'Reilly under the Creative Commons cc-by license, you have every reason to contribute something you may have already written–and no excuse not to!

Here is the first recipe I submitted:

Problem

Android's embedded SQLite3 database supports date and time data directly, including some useful date and time arithmetic. However, getting these dates out of the database is troublesome: there is no Cursor.getDate() in the Android API.

Solution

Use SQLite's strftime() function to convert between SQLite timestamp format and the Java API's "milliseconds since the epoch" representation.

Discussion

This recipe demonstrates the advantages of using SQLite timestamps over storing raw milliseconds values in your database, and shows how to retrieve those timestamps from your database as java.util.Date objects.

Background

The usual representation for an absolute timestamp in Unix is time_t, which historically was just an alias for a 32-bit integer. This integer represented the date as the number of seconds elapsed since UTC 00:00 on January 1, 1970 (the Unix time epoch.) On systems where time_t is still a 32-bit integer, the clock will roll over partway through the year 2038.

Java adopted a similar convention, but with a few twists. The epoch remains the same, but the count is always stored in a 64-bit signed integer (the native Java long type) and the units are milliseconds rather than seconds. This method of timekeeping will not roll over for another 292 million years.

Android example code that deals with persisting dates and times tends to simply store and retrieve the raw milliseconds since the epoch values in the database. However, by doing this, it misses out on some useful features built in to SQLite.

The Advantages

There are several advantages to storing proper SQLite timestamps in your data: you can default timestamp columns to the current time using no Java code at all; you can perform calendar-sensitive arithmetic such as selecting the first day of a week or month, or adding a week to the value stored in the database; and you can extract just the date or time components and return those from your data provider.

All of these code-saving advantages come with two added bonuses: first, your data provider's API can stick to the Android convention of passing timestamps around as long values; second, all of this date manipulation is done in the natively-compiled SQLite code, so the manipulations don't incur the garbage collection overhead of creating multiple java.util.Date or java.util.Calendar objects.

The Code

Without further ado, here's how to do it.

First, create a table that defines a column of type timestamp.
CREATE TABLE current_list (
item_id INTEGER NOT NULL,
added_on TIMESTAMP NOT NULL DEFAULT current_timestamp,
added_by VARCHAR(50) NOT NULL,
quantity INTEGER NOT NULL,
units VARCHAR(50) NOT NULL,
CONSTRAINT current_list_pk PRIMARY KEY (item_id)
);
Note the default value for the added_on column. Whenever you insert a row into this table, SQLite will automatically fill in the current time (accurate to the second) for the new record.
sqlite> insert into current_list (item_id, added_by, quantity, units)
...> values (1, 'fuerth', 1, 'EA');
sqlite> select * from current_list where item_id = 1;
1|2010-05-14 23:10:26|fuerth|1|EA
sqlite>
See how the current date was inserted automatically? This is one of the advantages you get from working with SQLite timestamps.

How about the other advantages?

Select just the date part, forcing the time back to midnight:
sqlite> select item_id, date(added_on,'start of day')
...> from current_list where item_id = 1;
1|2010-05-14
sqlite>
Or adjust the date to the Monday of the following week:
sqlite> select item_id, date(added_on,'weekday 1')
...> from current_list where item_id = 1;
1|2010-05-17
sqlite>
Or the Monday before:
sqlite> select item_id, date(added_on,'weekday 1','-7 days')
...> from current_list where item_id = 1;
1|2010-05-10
sqlite>
These examples are just the tip of the iceberg. You can do a lot of useful things with your timestamps once SQLite recognizes them as such.

Last, but not least, you must be wondering how to get these dates back into your Java code. The trick is to press another of SQLite's date functions into service—this time strftime(). Here is a Java method that fetches a row from the current_list table we've been working with:
 Cursor cursor = database.rawQuery(
"SELECT item_id AS _id," +
" (strftime('%s', added_on) * 1000) AS added_on," +
" added_by, quantity, units" +
" FROM current_list", new String[0]);
long millis = cursor.getLong(cursor.getColumnIndexOrThrow("added_on"));
Date addedOn = new Date(millis);
That's it: using strftime's %s format, you can select timestamps directly into your Cursor as Java milliseconds since the epoch values. Client code will be none the wiser, except that your content provider will be able to do date manipulations for free that would take significant amounts of Java code and extra object allocations.

See Also

SQLite's documentation for its date and time functions
This recipe in the Android Cookbook

Sunday, February 28, 2010

Guaranteed Definite Assignment, Bugs, and You

Here is a great technique to adopt when you must initialize a variable to one of two or more values. It's a simple technique that's easy to apply even when you're feeling lazy, but I'm surprised at how few people are aware of the advantages.

The scenario is simple enough: while revisiting a little parser I wrote a few months ago which turns strings such as "2010-02.1m" into corresponding typesafe immutable objects with a start date and end date, a small addition I made to it had the fortunate side effect of revealing a boneheaded bug I had baked into the original version.

Quick–can you spot the bug in this code, which compiles with no warnings and no errors?

Calendar start = (Calendar) end.clone();
if (periodType.equals("d")) {
start.add(Calendar.DAY_OF_MONTH, 1 - periodScalar);

} else if (periodType.equals("m")) {
start.set(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.MONTH, 1 - periodScalar);

} else if (periodType.equals("y")) {
start.add(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.YEAR, -periodScalar);
}

return new FilingPeriod(
code,
start.getTime(),
end.getTime());

It's missing the else part that throws an exception for unknown period types. Did you see it, or were you too distracted by the calendar manipulation to notice the obvious problem?

This code fragment comes from an accounting-related application, and sooner or later someone is going to have to add "q" for Quarter. If you gave the above code a periodType of "q," it would happily return an incorrect result rather than throw an exception. Besides, we're essentially building a parser for a little language here. It ought to throw an informative exception when you give it invalid input.

It was easy to justify the need for the catch-all else clause here, but truthfully, it's simply part of the idiom, and it's a waste of time to contemplate whether the catch-all is likely to actually do anything in practice. You should just get in the habit of always including it, and consider its omission in existing code to be an error. Unfortunately, even though it's such an important thing to remember, the compiler didn't issue any warnings or errors about its absence.

The good news is, your Java compiler can enforce the need for an else block that throws an exception (or returns normally, but your muscle memory for this idiom should have you typing "throw new …" before you've even thought about it.)

By the way, even if you did "immediately" spot the missing else, I bet it still took you more than .0001 seconds. It would have been more efficient, and safer, to let your Java compiler pick it up.


Let the compiler help you

So how do you enlist javac's help? Here's the change I made that gave javac the chance to throw my previous mistake in my face (sure, it sounds irritating, but it's actually a very very good thing:)

Calendar start = (Calendar) end.clone();
int monthsCovered;
if (periodType.equals("d")) {
start.add(Calendar.DAY_OF_MONTH, 1 - periodScalar);
monthsCovered = periodScalar / 30; // approximate

} else if (periodType.equals("m")) {
start.set(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.MONTH, 1 - periodScalar);
monthsCovered = periodScalar;

} else if (periodType.equals("y")) {
start.add(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.YEAR, -periodScalar);
monthsCovered = periodScalar * 12;
}

return new FilingPeriod(
code,
start.getTime(),
end.getTime(),
monthsCovered);

Now, the code won't compile: referencing monthsCovered is now an error because it might not be initialized. If I had initialized monthsCovered to 0 (or any other value) then the compiler would not have found the missing else for me. This is the key of what I'm saying: don't initialize your local variables to some garbage value. Leave them blank, and the compiler will help you to write better code.


But you can do even better

In most cases such as this, you can gain even more safety by marking the uninitialized variable final. This causes the compiler to guarantee that the variable has been assigned exactly once before it is first referenced.

Marking your uninitialized local variables final makes it virtually impossible for a future maintainer[1] to accidentally introduce subtle bugs into your multi-path initialization code–and this is the code where bugs experience long incubation periods before they rear their ugly heads[2].

Calendar start = (Calendar) end.clone();
final int monthsCovered;
if (periodType.equals("d")) {
start.add(Calendar.DAY_OF_MONTH, 1 - periodScalar);
monthsCovered = periodScalar / 30; // XXX approximate

} else if (periodType.equals("m")) {
start.set(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.MONTH, 1 - periodScalar);
monthsCovered = periodScalar;

} else if (periodType.equals("y")) {
start.add(Calendar.DAY_OF_MONTH, 1);
start.add(Calendar.YEAR, -periodScalar);
monthsCovered = periodScalar * 12;

} else {
throw new ParseException(
"Unrecognized period type in period " +
"specifier: " + code);
}

return new FilingPeriod(
code,
start.getTime(),
end.getTime(),
monthsCovered);

This third revision is robust code that's relatively safe in the hands of future maintainers. In terms of word count, it's a small change from the first example, but it's code I'd be far more comfortable having inside any system I'm responsible for.


The next step

Is it possible to make this type of code even more robust in the face of future modification? Yes! The typesafe enum pattern, introduced by Josh Bloch, is undoubtedly safer than what I've recommended above. It has even become a language feature in Java 5, which eliminates much of the boilerplate in simple applications of the pattern. However, unlike leaving your variables uninitialized and marking them final, applying the typesafe enum pattern to this type of problem is a big tradeoff in terms of lines of code you will write to solve the same problem. Is the tradeoff worthwhile? In many cases, I think it is.

My next post will go through the process of applying a typesafe enum to this same problem, and I will give you my insights on when I would go the extra mile versus sticking with the more succinct solution you see above. Ultimately, though, it's up to you to decide for yourself on a case-by-case basis.

[1] And let's be honest–this hypothetical future maintainer will be you, six weeks from now.
[2] This will happen either in production, or, more likely, during a demo.