Archive for July, 2007

Copying the contents of one directory into another: not as easy at it looks!

Tuesday, July 24th, 2007

Task: You want to copy the contents of one directory into another existing directory. On Linux.

I.e. if the source directory is “x” and the destination directory is the already-existing directory “y”, if there are files “x/1″ and “x/2″ then files “y/1″ and “y/2″ should be created. If “x” is an empty directory then no files in “y” should be created.

Now, this is not as easy as it sounds.

cp -r x y

This command copies “x” into “y” meaning that the resulting files end up being “y/x/1″ etc.

cp -r x/* y

This copies files like “x/1″ into files “y/1″ correctly, but if “x” is an empty directory, an error is presented, that the file “x/*” cannot be found.

Surely this should be easy! I even considered firstly deleting the directory y, and then copying x as y.

rm -rf y
cp -r x y

This is rather inelegant as you have to set the permissions on “y” again if they’re non-standard, and it doesn’t work if “y” isn’t empty.

I came up with the following solution.

cd x
cp -r –parents . ../y

This copes the “current directory” and all children (i.e. all files) into “y”, but the “–parents” option tries to create any hierarchy leading to the source into the destination. So if you copy “a/b/c” into “d” then it creates “d/a/b/c” as opposed to just “d/c” which it would normally create.

In my case the “hierarchy” is just “.” so it copies e.g. “./1″ into “y/./1″ i.e. “y/1″.

Concorde Fallacy

Friday, July 13th, 2007

This is a good term for a commonplace management error.

http://www.answers.com/topic/concorde-fallacy

Java: List<X> or X[] ?

Thursday, July 12th, 2007

Since the creation of Java 1.5, one’s been able to parametrize classes using generics, with a syntax similar to C++ templates.

Before Java 1.5, I would always return simple list data structures as arrays. This was

  • Type-safe (e.g. User[] as opposed to List; the former one knows what’s in the collection, in the latter one doesn’t)
  • One could find out the length of the collection with array.length (in contrast to C arrays)

But since Java 1.5, one has a choice. One could use the Java collections framework, now supporting generics, or still use arrays.

Perhaps it’s because I don’t like change, but I would still advocate using arrays as opposed to Lists:

  • The generic information is thrown away at compile-time, so a List<X> and List<Y> look the same at run-time, whereas X[] and Y[] do not. Introspection, and getting exceptions at the time of a wrong array cast, and not later, are the benefits here.
  • You can easily create an array declaratively. int[] x = new int[] { 1, 2 }; You can’t do the same with the collections frameworks.
  • I’m sure arrays are faster
  • Arrays are also simpler. I think one should, given two solutions to the same problem, nearly always take the simpler unless there’s a clear benefit of the more complex solution (which I don’t see in this case)

Maybe the point about faster and simpler aren’t really relevant points these days. But collections are still the sort of things which one accesses in inner loops. Consider the ways in which X[] is faster than List<X>:

  • To iterate over the collection, with List<X> you need to create an Iterator. This also happens if you use the “foreach” construct.
  • To get a particular element, or to get the length, you have to call methods, like aList.get(3).

It has been said that using Iterators is preferable to using a for loop over array indexes, for software design reasons. This may be the case in some special situations, but I really don’t think it’s an advantage in common usage.

  • One can iterate over an array or collection with the Java 1.5 “foreach” keyword: so in this case the source code looks the same.
  • The code “for (i=0; i<array.length; i++)”, i.e. non-iterator code, is not really difficult to write or difficult to read.

Sony Vaio Support (Day 12)

Wednesday, July 11th, 2007

Sony rang on Friday. They wanted to know the guarantee number (the number that I don't have, which should have been on the invoice; the invoice which originated from them, and I've sent them back twice already).

I took the opportunity to ask how the repair was going (as their website where you can track the repairs doesn't work). They told me the battery was broken and they had to send off for a new one, which hadn't arrived yet. There are two things wrong with that:

  1. They are a Sony repair shop. They are Europe's Sony repair shop (as far as I know). Why don't they have any batteries available in stock? Maybe this is the first time ever that a notebook has needed a new battery, but I doubt it.
  2. The laptop didn't work without the battery (i.e. with just the power cable connected). So I doubt it's the battery which is broken.

I am writing this on Wednesday (day 17) and still no news.

Hibernate / Boolean Fields / MySQL 5.0

Wednesday, July 4th, 2007

There’s a problem persisting boolean fields using Hibernate 3.2.2 to MySQL 5.0, if you allow Hibernate to generate your schema, and you leave Hibernate to generate the schema in the default way. It works fine on MySQL 4.1 and it doesn’t matter if you use boolean (primitive) or Boolean (object) types for the fields.

with a class such as:

public class MyObject {
   protected boolean myField;
   public boolean getMyField() { return myField; }
   public void setMyField(boolean x) { myField = x; }
}

and a Hibernate mapping such as:

<property name="myField" column="my_field" not-null="true" />

and allow Hibernate to generate the schema on startup, e.g. by writing the following in the “hibernate.cfg.xml” file:

<property name="hbm2ddl.auto">create</property>

Against MySQL 4.1 this all works, and the column has the data type tinyint(1). But in MySQL 5.0 the data type is bit(1) (which seems logical enough) but Hibernate then throws the following unhelpful exception upon every insert:

could not insert: [com.company.MyObject]
org.hibernate.exception.DataException: could not insert: [com.company.MyObject]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
....
Caused by: java.sql.SQLException: Data too long for column 'my_field' at row 1
at ....

The solution is to change the Hibernate mapping for the field to this:

<property name="myField" not-null="true" >
   <column sql-type="BOOLEAN" not-null="true" name="my_field" />
</property>

Then the field is generated as tinyint(1) and then it all works fine again.

Generate Javadoc HTML only for public members

Monday, July 2nd, 2007

In Java there are four protection levels which members (fields and methods) can have:

  1. Private
  2. Protected
  3. Package-level
  4. Public

Any member can have Javadoc (including private members).

But when one generates the Javadoc, which protected levels should be included?

Generated Javadoc is used by humans. These humans are probably not you. And thus are probably clients of your classes, either within or outside of your organization. It’s possible, although unlikely, that they may be able to access package-level members. It’s possible they may need to subclass your class, although in (nearly) all cases I can conceive of, they won’t do that without looking at your source code.

Javadoc should be simple to understand. There’s simply a lot of potentially documentable stuff going on in a class, which is capable of reducing simplicity. Setters which only Hibernate needs to see (private), or which only your factories in your package need to see (package-level).

Javadoc should therefore only be generated only for public attributes. That’s what Sun’s JDK docs do as well (for example you don’t see any protected or private stuff here). And there’s an additional benefit of simplicity is that if this is the only level for which the Javadoc is being generated, it doesn’t even state the protection level in the summary, so you see “int getX()” in the method list as opposed to “public int getX()”.

This can be achieved with the “-public” option to the Javadoc generation program. In Netbeans 5.5, right-click on the project in the “projects” tab, select the menu item “properties”, go to the “documentation” entry under the “build” entry, and enter “-public” in the “additional javadoc options” field.