Archive for September, 2007

Macau until 2nd December

Monday, September 17th, 2007

I am going to London on Friday 21st September and will be working from there until Wednesday 26th September whereafter I shall be in Macau, working, until Sunday 2nd December when I'm back in Vienna.

EU Countries, ISO 3166-1 Alpha-3

Tuesday, September 11th, 2007

For various reasons I needed a list of 3-letter country codes for all the EU countries. (These are "ISO 3166-1 Alpha-3 codes"). It would have been much better if this software had used 2-letter country codes like everyone else.

And because I couldn't find this list on the Internet anywhere I had to make it myself from some huge list of 3-letter country codes for all countries in the world.

In case anyone else ever needs this (including but not limited to me), here it is.

EU Countries, ISO 3166-1 Alpha-3

Unit testing and configuration files

Sunday, September 9th, 2007

I used to think of a function as something which would convert some input value into some output value (potentially with some side-effects). And thus unit testing a function would involve passing particular inputs into the function and checking that the results were as expected (potentially setting up some database rows or something to test that the side-effects were executed properly).

But sometimes a function relies on a particular piece of global configuration. That’s an input to the function too. For example the tax rate.

public int calculateVat(int cents) {
    double vat = config.getDouble("vatRate");
    return (int) Math.round(cents * vat);
}

Initially I would just test the function with the current settings of the config file.

// VAT is currently 20% in Austria
assertEquals(20, obj.calculateVat(100));

However that’s obviously not a great solution as that will break when the config file changes. And after all, configuration files are there to extract the things that likely will change from the otherwise often very long but hopefully reasonably static domain logic.

So the solution I use now is to extend such configuration accessing classes with methods such as “setValueForTesting”. The “forTesting” part of the name indicates clearly its purpose is for test programs only.

config.setDoubleForTesting("vatRate", 0.2);
assertEquals(20, obj.calculateVat(100));

That code feels much better. There are actually two advantages:

  1. Obviously the test code will not break if the config file changes.
  2. But also there is more locality. Everything you need to understand about that test is there in the test program’s source file, in two easy-to-read lines.

But this approach feels somewhat unorthodox. How do other people do it?

Java 5 enums can be compared with ==

Thursday, September 6th, 2007

Java Enum instances are singletons. This seems to be not clearly documented by Sun (at least I found it difficult to find). But it’s the case.

What this means is that it’s possible to compare enumerated types by identity, which is cool for readability. (And it means that the switch statement works.)

You don’t have to write this:

if (PurchaseState.complete.equals(anItem.getPurchaseState()) { ...

You can write:

if (anItem.getPurchaseState() == PurchaseState.complete) { ...

This is documented here in the “discussion” section.

Interesting Oracle/MySQL locking difference

Wednesday, September 5th, 2007

I know the rules for Oracle row locking well. A row can be locked for write if one updates it, or if one “select for update”s it.

  1. create table a (x number); (and equivalent in MySQL for InnoDB)
  2. Session A: insert into a values (9);
  3. Session A: commit;
  4. Session A: start transaction (in mysql)
  5. Session A: select * from a where x=9 for update;
  6. Session B: start transaction (in mysql)
  7. Session B: select * from a where x=9 for update;
  8. Session B hangs, waiting for row-level lock to be release from the row by Session A
  9. Session A: update a set x=4;
  10. Session A: commit;
  11. At this point, Session B returns no rows. Lock has been released, and row no longer confirms to where, so is not returned.
  12. Session A: update a set x=5;

This is where the difference occurs:

  • Oracle returns the row to session A. The command “for update” in session B did not return any rows, and thus no rows were locked, and thus session A has nothing to wait on.
  • MySQL (version 4.1.18) blocks session A waiting on the transaction in session B to be ended. That means A requires a lock owned by B. But what is this lock? Is it a row-level lock on the row which was not selected? Some other type of lock?

The reason I tested this was it just occurred to me that in a “select for update” the where clause is applied twice:

  1. Firstly to determine which rows to return. A lock is requested for those rows, which can involve waiting until the lock is released if it is owned by some other transaction.
  2. After the lock has been acquired, the rows is checked again to see if it still confirms to the where clause. If not, it is not returned (although the session blocked waiting for it)

I suspect that both databases simply do step 1 involving waiting and acquiring the lock on the rows which initially conform to the where clause. And both apply the where in step 2, as in both cases no rows were actually returned dispite the wait. But Oracle, upon noticing the row will not be returned, actually releases the lock as the command implies only rows returned will be locked. But MySQL just leaves the lock form step 1 hanging around, which is wrong.

3-dimensional photo organization

Monday, September 3rd, 2007

I have just viewed some photos on Facebook. They were of a friend's trip to Malaysia.

  1. Facebook has a limit of 60 photos per album; meaning you have to split photos up into albums with names like "Malaysia 1", "Malaysia 2" etc if you want to upload more than 60 photos in total.
  2. Each album, as is current practice in web design, is divided into pages with "page next" buttons to get to the next page.
  3. Each page of each album, as was introduced with windowing systems, has a scroll bar (vertical only, unless one makes the window really small)

OK now fundamentally a set of photos from a holiday are one-dimensional. I can think of many ways to lay out photos but I'm sure these three dimensions would not be the dimensions I would choose.

The scroll bar is quite a good device. It was well thought through. It was specifically developed to solve the problem of "you have more data than can fit on the screen". You can move slowly up or down using the arrows at the end which are deliberately easy to understand even for novices unfamiliar with windowing systems. You can see how far down the available data you are. You can drag the bar with your hand/mouse to move either fast or slow in a natural motion.

I have heard that some web novices find "next page" easier to use than using the scroll bar. But this wouldn't be the case if there were no "next page" links. And knowing how to use scroll bars is non-optional, if you want to use any other system other than photo browsing websites. For example when using the compose interface of an email website, there is no "next page" button once you've typed text equal in length to the size of the window the user interface designers assume you are using.

Scroll bars are so much better than "next page" links, and even if they weren't, displaying 1-dimensional data using 1 data navigation tool is better than displaying 1-dimensional data using 3 different navigation tools.