if ( document.comments_form.url ) { document.comments_form.url.value = getCookie("mtcmthome"); } Otaku, Cedric's weblog: October 2004 Archives

October 29, 2004

Today is Googleween

Big Halloween party later today at Google, and this morning, I rode the shuttle with a Nascar driver, a bee, a mechanic, various angels and kitties and Frankenstein.

Happy Halloween everyone!

 

Posted by cedric at 09:18 AM | Comments (3)

October 27, 2004

Far Cry, Myst and other geeky pleasures

A quick overview of the games I have played recently...

Far Cry

Pure bliss.  This game is absolutely gorgeous in 1600x1200 with all details turned on and it offers a tremendous amount of variety.  It is also surprisingly long and I thought I had finished it a couple of times until I realized that the plot was unfolding further.  I also liked the scenario, which starts with a simple plot and slowly turns into a full-scale Doom-like adventure.  But what keeps you going and going is just the constant hunger to discover where the next level will take you... Dune buggy?  Glider?  Patrol boat?  Jeep?  Carrier?  Helicopter?

Interestingly, the show "Lost" that is currently airing reminds me a lot of Far Cry...

Doom 3

Undoubtedly a fantastic technical achievement but after Far Cry, Doom 3 bored me pretty quickly.  I gave Doom 3 a fair chance to get me hooked and I played about one third of it until I simply got tired of wandering in dark corridors, waiting for the next alien to jump me from behind a closet.  I didn't install the "duct tape" mod, which allows you to have your flashlight on at all times, since I wanted to play the game the way it was designed, and I honestly didn't find it to be as frustrating as some other players have.  Having said that, while the constant darkness is guaranteed to make you jump on your seat on more than one occasion, the sad truth is that it probably hides most of the game's technical brilliance.

Experts will probably argue that Doom 3 is one generation ahead of Far Cry (which is at least chronologically true) but I'll take fun and variety over technical brilliance any day.  Especially since I think Far Cry certainly holds its grounds visually.

Exit Doom 3 then...

More recently, I have had a renewed craving for a good old Real Time Strategy (RTS) game that would match Rise of Nations, so I looked in the direction of Rome: Total War (RTW) and Warhammer 40,000: Dawn of War (DOW).

Rome:  Total War

I spent a few hours on RTW, playing a battle and trying to get a feel for the campaign map but I can't say the game took me in.  Maybe I need to spend more time on it but my initial impression is that mixing battlefield and campaign doesn't work very well, especially since you can automatically resolve the battlefield campaign.  I am curious to hear from veterans RTW players:  do you still play the battlefields at all after many hours?

I also had a hard time getting a good grasp of how certain key concepts of the games are connected and how they play out together.  Maybe I am missing out and I should spend more time on it, but I distinctly remember feeling very much connected to Civilization right away, and its manual weighed a hefty 120 pages...

So I switched my focus to Dawn of War.

Warhammer 40,000:  Dawn of War

It's pretty easy to be seduced by the sheer beauty of the game.  It's fun.  Pure, unedited, mindless, childish fun.  A lot of colored units, great voice-overs, detailed animations that even now I find myself zooming into (especially when a mech eviscerates a whole platoon).  And the combat scenes...  oh my.  Lasers, missiles, grenades, and this is just in the very beginning, I bet more sophisticated units will be coming up for even more eye candy.

But is it the real-time strategy game I am looking for?

Certainly not.

First of all, the missions are very directed.  It's not an all-out battle with one team in each corner of the map and letting them duke it out.  There is a story line and the levels follow it.  A frustrating aspect of this is that some technology that is available at a certain level might be grayed out at the next level.  This goes against my intuition, and against simple common sense.  The best RTS games will not only provide you a gentle tutorial but the missions themselves will slowly bring you up to speed with the units you can use, and this progressive learning is the only way you can truly master even an RTS game as complex as Civilization or Rise of Nations.

But overall, I just find that a simple way of winning at DOW is to rush.  Plain and simple rush.  If it doesn't work the first time, fall back, regroup, reconstitute your army and try again.  Watch over your resources and your energy, and you will inch your way into the computer's field, who doesn't seem to be smart enough to reconstruct while you are rebuilding your army of minions.  That's disappointing.  Or maybe I should play at a more difficult level.

Until then, I find myself going back to DOW once in a while because it's mindless, doesn't need to much thinking or too much context and you can dive right back into a game that you left several days ago. 

If you liked Warcraft 3, you will love Dawn of War.  If you are more the Rise of Nations type, the title of best RTS to date is still up for grabs.

Myst 4 : Revelation

And finally, I have found myself being suckered into Myst for the fourth time (well, a bit more than that if you count Uru and its extension packs).

Myst 4:  Revelation is a pure gem.  It's by far the Myst episode that strikes the best balance between jaw-dropping sceneries, mesmerizing ambiance and reasonably hard puzzles.

Contrary to Uru (which would deserve an entry of its own), Myst 4 is not in full 3D.  It uses the same navigation technique as the previous three episodes (discrete moves) but each location can be fully viewed in 360 degrees and above you (in other words, you can look around).  While I was quite disappointed by this apparently step back from Uru, I got used to it pretty quickly and since the familiar Zip locations are present, it's fairly easy to move around (with a notable exception, see below).

As I said above, what I like most about Myst 4 is this impression that the puzzles are actually solvable by a non-lateral human thinker (that is: me).  Uru was disappointing in this, as I found that I could never have solved some puzzles in my lifetime other than by reading the walkthrough. 

Myst 4 is the opposite, and the very first puzzle you will face (restoring the power of your base of operations) will give you a good idea of what lies ahead.

But you need to have a very good eye for details.  And in doubt, not hesitate to take a picture, because most of the time, it will come in handy later.

Myst 4 takes you through several ages, each more beautiful than the previous one (I am almost done with the third one right now) and while the size of each world is daunting at first, it's only a matter of time before you get familiar with the various areas you can explore and you figure out how they relate to each other.

Unfortunately, this also happens to be the only bad thing about Myst 4:  it's easy to get lost.

And I don't mean losing yourself, I mean:  overlooking certain locations because finding your way is everything but easy.  If there is one thing missing from this otherwise-perfect adventure game, it's a way to tell what the possible paths are every time you reach a new location.

Barring this, the puzzles are quite enthralling and always logical.  If you didn't miss any location, an idea of how each age level will slowly form in your mind as you discover new pieces of the puzzle and nothing is more thrilling than when you can finally put your theory to the test and see it work (I even found myself writing down a finite-state automaton once, although obviously, you can certainly solve this problem differently and the only thing you really need is simple common sense).

Overall, Myst 4: Revelation is one of the most immersive games I have played in a long time, and I recommend it to not only Myst lovers but you anyone curious to try something new.

Posted by cedric at 10:37 AM | Comments (13)

October 26, 2004

Debuggers should be used even on new code

In this TheServerSide thread, Amin Mansuri has this to say about debuggers:

I dunno.. maybe I'm a bit old school, but I'm influenced by Steve McConnell author of Writing Solid Code and Debugging the Software Development process who suggests that you should step through all your code in the debugger before checking it in.

Yes!

I actually got this habit from reading "Writing Solid Code" myself.  Single-stepping through all your new code might be a bit overkill, though, but I am a firm believer in the idea that debuggers should be used on new code, and I find myself doing that very often as the result of reading this book more than ten years ago.

Frankly, I don't understand the argument "unit tests are good enough, I don't need a debugger" put forth by so many anti-debugger people.

First of all, even unit tests break and have bugs, so you have to debug at some point.

But more importantly, unit tests only give you a superficial view of the quality of your code.  Okay, the bar is green, but are you really sure your code is behaving the way you designed it, and not by accident?  Or that two bugs are not canceling each other out, yielding a good result by accident?

What better way is there to really make sure of this than by putting a breakpoint in your fresh new code, single-stepping through it and verifying that all the variables are what you expect?

Posted by cedric at 10:46 AM | Comments (11)

October 22, 2004

Testing a testing framework

The best way to test a testing framework is, of course, to use it on itself.  There are plenty of benefits to this approach:

  • I like to "drink my own champagne" (I prefer this analogy to "eating my own dog food", being French and all).  If I don't use my own code in-house, I am missing an opportunity to receive important feedback.
     
  • It's a great way to refine the listening API and make sure it covers all possible cases (this is the API that allows clients to be informed of when a test is being called, is succeeding, failing, etc...).
     
  • It also allows me to make sure that TestNG is reentrant, since it is basically calling itself.  This is important since TestNG supports parallel execution of tests, so no deadlocks are permitted.

With this in mind, the requirements for testing TestNG are as follows:

  • I need to be able to specify testng.xml programatically.  I don't want to create sub XML files for each test.  Instead, I want to set up my testing environment completely in Java.
     
  • When I run the tests, I want to make sure that the right methods are called and that their status (pass, fail, skip) matches what I expect.

The design I have achieved so far allows me to write tests like this:

@Test
public void partialGroupsClass() {
  addClass("test.sample.PartialGroupTest");
  addIncludedGroup("classGroup");
  run();
  String[] passed = {
    "testMethodGroup", "testClassGroup" 
  };
  String[] failed = {
  };
  verifyTests("Passed", passed, getPassedTests());
  verifyTests("Failed", failed, getFailedTests());
}

In this test, I specify the test class to be invoked and the group to be included for this run.  Then I run the tests and compare the methods actually run against the ones I expect to be run.

As you can expect, the class PartialGroupTest contains several methods, of which only testMethodGroup() and testClassGroup() belong to the group "classGroup", so I only expect these methods to be invoked and to pass.

Now, how does this work exactly?  It's quite simple:  the inner TestNG instance is configured in a "beforeTestMethod" method, so that it gets invoked before each test method.  This way, I am guaranteed to start with a clean inner TestNG instance for each test method:

@Configuration(beforeTestMethod = true)
public void methodSetUp() {
  setPassedTests(new HashMap());
  setFailedTests(new HashMap());
  setSkippedTests(new HashMap());

  // ...
}

This method is defined in a base class that all my tests inherit, so I don't need to worry about this when I write my tests.  It is also responsible for setting itself as a listener to the inner TestNG instance so that it gets notified each time a test passes, fails or skips.  Later, the method verifyTests() can be invoked by each test method to compare the methods run against the ones they expect.

This infrastructure makes it trivial for me to add new tests and new functionalities and be test-happy.  For example, as I was writing this entry, I realized I could also test failures of partial groups, so I added a couple of methods that belong to the same group, made them fail with an "assert false", verified that the test failed, then I added the names of these two methods in the failed array and the test passed.

I cannot over-emphasize how important it is to have a testing framework that is flexible and yet, easy to use.  No matter how you look at it, if you don't understand how your tests work and you are not clear on how to add tests yourself, your work as a developer is sub-optimal and you are probably not as productive and not as aggressive as you could be.

This applies to "real life" as well, where you are working with an entire QA department that came up with its own testing framework and is responsible for writing most of the tests.  If this testing framework is too complex for you and your developers, you need to get together with your QA department and come up with a way that both units can exchange tests easily.

 

Posted by cedric at 10:31 AM | Comments (2)

October 21, 2004

Debugger tips

Debuggers are back in the spotlight with a recent post from Kasia.  She likes debuggers, so do I.

I have already expressed my views here and here on the importance of debuggers and my philosophy is quite simple:

No matter how productive you are with your current tools, I guarantee you will be more productive with an IDE and with a debugger.

I am pretty good with emacs and vi, with pinpointing potential bug areas by just reading code or quickly reading reams of output on a console, but at the end of the day, I just get things done faster if I add my IDE and a debugger to my arsenal of tools.  Ignoring this simple common sense is like being a caveman saying that he's okay without fire.

The point of this entry is not to revive this debate (let's leave cavemen into their caves) but to ponder the following question:  why is there almost no information on how to use a debugger wisely?  I don't mean the user manual telling you how to set a breakpoint and how to single-step through code.  I mean a "good practice" guide.

As far as I know, this is not taught in school and hardly broached in books and I wonder why.  Is it because debuggers vary widely in scope and functionalities?

 I don't believe this statement is true any more:  these days, debuggers have converged toward a very similar set of functionalities and except for a few innovations such as back-in-time debugging, you can reasonably expect your debugger to offer the same functions, regardless of the language or the operating system you are debugging in.

I would love to see a central place where all debugger tips and practices can be found, I'm sure there is a wealth of information waiting to be uncovered out there.

I'll start with a few tips of my own.

Run method till it exits

Sometimes, you accidentally step into a method you didn't mean to investigate, typically a library method.  You want to "get out" of this method so you can resume the debugging of the method you are really interested in.  You do this in Eclipse with the Step return button:

Press it and the current method will be run until it exits and the current frame is popped, taking you back to where the call was made.

Using conditional breakpoints.

I cannot overstate how important conditional breakpoints are.  Unless you are working on a very simple piece of code, the bug you are trying to find or the code you are trying to test will probably not be exercised right away, or it will be run several times without the parameters you are expecting.  The only way to get there faster is to type in entire expressions in your conditional breakpoint text box.

Using break conditions for println

As I stated in the link above, I'm not a big fan of "println debugging", which is antiquated and actually quite dangerous at times.  That being said, a bug sometimes happens after a certain number of iterations which cannot be easily captured by a conditional breakpoint (see below).  Or maybe, you just want to have some information about the state of the program displayed on stdout so that when you hit your breakpoint, the console contains some context information.

How could you do this without inserting println's in your code?

Simple :  use a breakpoint expression that will do this println for you.

For example, the expression above could simple be replaced with "System.out.println(methodName)".  Since this expression will never return true, the program will never stop, but it will display the value of methodName throughout the entire execution.

Now, that's what I call an efficient use of println and since the logic is contained in the debugger and not your code, no risk of shipping with it.

Of course, you don't have to limit this to just println, you could just as easily modify existing variables or do some other crazy stuff...

How about you?  Any hot tips to share about your relationship with your debugger?

Posted by cedric at 11:07 AM | Comments (44)

October 19, 2004

Type-ahead find in FireFox

I wondered for a while why FireFox's "type-ahead find link" feature was not working for me (type ' and then the link you are looking for).  I finally figured out why:  this functionality looks for the text of the link, not the href.

Which is a bummer because looking for an href without having to open the source window would be quite convenient.

Does such a feature exist in FireFox?

 

Posted by cedric at 02:42 PM | Comments (5)

October 14, 2004

Testing JMS and asynchronous code

I recently added a couple of features to TestNG that make testing asynchronous code (such as JMS) very easy:  parallelism and time-outs.

Parallelism instructs TestNG to run your test methods in different threads.  The trick here is that some of these test methods depend on each other, so these methods will obviously be invoked sequentially in the same thread.  But all the other test methods that do not depend on anything else will be run in a separate thread, picked from a pool (which size is configurable).  Here is an example configuration:

<suite name="Main Suite" parallel="true" thread-count="10">
  <test name="First Test">
    <classes>
      <class name="test.Test1" />
      <class name="test.Test2" />
    </classes>
  </test>
</suite>

After the run, you can use the chronological view to see which methods were invoked and in what threads they ran.

Another interesting feature is time-outs, where you can indicate that a specific test method is expected to return within a certain number of milliseconds.  If it fails to do so, it will be interrupted and marked as a FAIL with a TimeOutException.

With that in mind, testing JMS (or asynchronous code) becomes trivial.  For example, imagine that our application posts a message on a JMS topic whenever an error condition arises.  Here is how you could test it:

public class ErrorMessageTest implements MessageListener {
  // Used to block
  private Object m_done = new Object();

  @Test(timeout = 5000 /* 5 seconds */)
  public verifyErrorMessageGetsPosted() {
    // register this class as a listener on the error topic
    // create the error condition
    // wait for completion
    m_done.wait();
  }
  
  // implements MessageListener
  public void onMessage(Message msg) {
    if ( /* msg contains what we expect */) {
      m_done.notify();
    }
    // else, do nothing, wait for another message
    // or for the time-out to kick-in
  }
}
This code is fairly self-explanatory and it leaves the dirty part (handling the time-out and multi-threading issues to the testing framework).

 

Posted by cedric at 07:21 PM | Comments (4)

Google Desktop Search

I apologize for the plug but I wouldn't mention it if I didn't find this tool incredibly cool...

Google Desktop Search radically changed the way I search on my computer.  Check it out!

Posted by cedric at 09:36 AM | Comments (9)

October 07, 2004

Guantanamo? Excuse me?!?

It was so obvious to me that Guantanamo (this name is very poor taste, by the way) was a joke that I found the entire idea amusing, but now, I'm not so sure.  Aslak seems to be awfully serious about it, but seriously... 

A tool that deletes lines of code that are not tested?  Surely, even the most hardcore XP proponent wouldn't be that radical and would just read the reports of a coverage tool and use his judgment to decide whether the untested code should be tested or not...

If anything is missing from Clover and other coverage tools, it's a way to tell "I know this part is not tested and/or exercised, but it's okay".  But a tool that will delete my code?

Come on...

Posted by cedric at 07:22 PM | Comments (15)

October 06, 2004

The secret to writing books

Bruce Snyder is feeling some distress about Word:

Unfortunately I am required to use Microsoft Word to write this book. Anyone who knows me knows that my choice would be VIM but I haven't figured out how to author XML documents that make use of DocBook and keep some type of styles intact upon conversion to Word.

Bruce, here is the secret: don't mix the task of writing with the tax of formatting.

First, write the text. Word, emacs, vi, notepad, it doesn't matter. Just write the text, the code, the remarks, maybe you can use a few newlines to help you visually, but perform *no* formatting whatsoever. I call that "Typing kilometer text" (yeah, I am still a metric system person).

Then when you're done with a decent chunk (I usually do that after a chapter), proofread yourself and start using the mouse to format your text.

I wrote my PhD dissertation and a book using this technique and the amount of productivity I gained was just astounding. Plus, it allowed me to leverage the strengths of all the tools (emacs and Word) while not being hampered by their weaknesses.  It's also a great way to "stay in the zone" when you are on a good writing roll, and you don't get distracted by stupid formatting issues.

And as a matter of fact, I just noticed I use this very technique for my weblog entries as well...  You learn something every day.

Posted by cedric at 06:31 AM | Comments (6)

October 05, 2004

Cool Eclipse plug-in: GotoFile

GotoFile is an Eclipse plug-in that lets you find a file in your workspace based on fuzzy naming.  This is different from Ctrl-Shift-R ("Find resource", which is useful when you are trying to find a file that is not a Java source).  The key here is that the file search only needs to have the letters you type appear in the same order you type them.

For example, TestNG contains dozens of files starting with Test:  TestException, TestClass, TestMethod, Test1, etc...  Even the super-fast Ctrl-E shortcut sometimes requires a few extra keys to reach the correct buffer.  With this plug-in, I can just type "tc" and TestClass is automatically selected.

Interestingly, emacs used to have a similar package to locate Emacs-Lisp files, so it's good to see that good ideas never really die.

At any rate, congratulations to Max Muermann for his idea!

 

Posted by cedric at 11:47 AM | Comments (10)

October 03, 2004

Game of the week

And the game of the week is...  Lemmings!

Written 100% in DHTML, nothing less!  Quite impressive (although it doesn't seem to run well on Firefox, so I recommend IE).

If there is one video game that is very likely to hook your significant other even though she/he is not into games, it's the adorable little lemmings.  And they are now available directly from your browser.  Imagine that.

Who knows, maybe in five years from now, we'll be able to play Doom 3 from our phones.

 

Posted by cedric at 07:13 AM | Comments (5)