October 2007


Java: A Retrospective

A wonderful article! I love Java and Open Source.

Java tools for small to medium websites

I have used commons-fileupload, it is really very easy to use. For the database communication, I have used Hibernate (2.x) but not Torque. For other things, I just want to give a try with my (small) personnal projects. But not immediately, I hope I could start in one month. I’ll post the result later.

Today, while playing with Java code and Eclipse, I falled to the following code:

package test;

/**
 * @author Hong Nam NGUYEN -- Created: 18 oct. 07 - 15:23:41
 */
public class Recursion
{
	private int x;
	private Recursion obj;
	
	public void init(int x)
	{
		this.x = x - 1;
		System.out.println("x = " + this.x);
		
		while (this.x > 7)
		{
			obj = new Recursion();
			obj.init(this.x);
		}
	}
	
	public static void main(String[] args)
	{
		Recursion obj = new Recursion();
		obj.init(10);
		System.out.println("Finish");
	}
}


I thought that the program will print out
x = 9
x = 8
x = 7
Finish
and stop!
But not, the real result is
x = 9
x = 8
x = 7
x = 7
x = 7
x = 7
….
and infinite loop ??

By reinspecting the code, I found that I have made an error. The variable x is an instance variable, so it belongs to each instance of the class Recursion, but not to the class at a whole. When a new instance is created (Recursion obj = new Recursion();) and the init method called, the following instruction is executed: this.x = x – 1;, but not the same x each time. In fact, the x of the very first instance has the value 9 (= 10 – 1), and then, it never change any more ! That’s why I get the infinite loop.
To correct this problem, there are (at least) two solutions:
– make x a static variable (static private int x;)
– or add code that changes x in the while loop

		while (this.x > 7)
		{
			obj = new Recursion();
			obj.init(this.x);
			this.x--;
		}


!!! The results of the two solutions are not the same, but the loop finite.

Recently, I worked on a problem which can be resumed as following:

I have a function that take an input, do some calcul and give me a output value. Now I have a output value and I want to know the input that produce the output.

Example: y = x*x + sqrt(x) – 7/x + (15/(2*x) – 4.5*x)*(sqrt(6*x) – x*sqrt(x/2));
If I have x, I can calculate y.
Now I have y and I want calculate x.

Of course, my function is a thousand of time more complex than in the example. The calculation formula is about a dozen of pages long.

I had tried to inverse the formula to obtain something like x = func(y) so I could calculate x when I know y, but I had failed because it was really difficult for me. Fortunately, a friend tell me about the dichotomy algorithm.

Dichotomy algorithm:
The idea is
I have y = func(x), I know y and want to calculate x, so
I take a value x, calculate func(x), compare the result with y,
    if result == y, so x is what I need,
    if not, I take another x, and recalculate func(x), recompare the result with y, …
repeat it until I find x.

Does it sound stupid ? Yes, if I don’t have a computer, but I have a power computer who does the calculation for me, so this is a wonderful idea.

However, I was skeptical at first, because I don’t know how many loops I have to repeat to obtain the result and the simplest way to implement this algorithm is to use recursion. But when I started to implement the algorithm, I recognize that with some simple optimizations and some heuristic knowledge, the number of loops (and so the performance) is really acceptable. (about 50 to 100 loops to get the result).

Here is the first code I used:

package test;

/**
 * @author Hong Nam NGUYEN -- Created: 15 oct. 07 - 16:26:27
 */
public class Dichotomie
{
	public static void main(String[] args)
	{
		double x = 2.55;
		double y = func(x);
		System.out.println("x = " + x);
		System.out.println("y = func(x) = " + y);

		System.out.println("=========================");

		double result = 5105.4;
		double variable = getX(result);
		System.out.println("result = " + result);
		System.out.println("variable = " + variable);
	}

	private static double func(double x)
	{
		return 2000000 * x + 7 - Math.sqrt(x);
	}

	public static double getX(double y)
	{
		double x = y * 2000000;

		double max = 0;
		double min = 0;

		double tmp = func(x);
		double diff = tmp - y;

		// TODO: On peut améliorer les méthodes getMin/Max
		if (diff > 0.0)
		{
			max = x;
			min = getMin(x / 2, y);
		}
		else if (diff < 0.0)
		{
			min = x;
			max = getMax(x * 2, y);
		}
		else
		{
			return x;
		}

		return dichotomie(min, max, y);
	}

	private static double dichotomie(double min, double max, double y)
	{
		double x = (min + max) / 2;
		double tmp = func(x);
		double diff = tmp - y;
		if (diff > 0)
		{
			return dichotomie(min, x, y);
		}
		else if (diff < 0)
		{
			return dichotomie(x, max, y);
		}
		else
		{
			return x;
		}
	}

	private static double getMax(double x, double y)
	{
		double tmp = func(x);
		double diff = tmp - y;
		if (diff > 0)
		{
			return x;
		}
		return getMax(x * 2, y);
	}

	private static double getMin(double x, double y)
	{
		double tmp = func(x);
		double diff = tmp - y;
		if (diff < 0)
		{
			return x;
		}
		return getMin(x / 2, y);
	}
}

This code works well, but the functions getMin and getMax could be done better, so here is the second version. The difference between the two versions of code is showed when I have made a really bad choice for the first try – heuristic plays its role in this choice (here is double x = y * 2000000;)

package test;

/**
 * @author Hong Nam NGUYEN -- Created: 15 oct. 07 - 16:26:27
 */
public class Dichotomie2
{
	static int	loopFunc		= 0;

	public static void main(String[] args)
	{
		double x = 2.55;
		double y = func(x);
		System.out.println("x = " + x);
		System.out.println("y = func(x) = " + y);

		System.out.println("=========================");

		double result = 5105.4;
		double variable = getX(result);
		System.out.println("result = " + result);
		System.out.println("variable = " + variable);
	}

	private static double func(double x)
	{
		System.out.println("func: " + (++loopFunc));
		return 2000000 * x + 7 - Math.sqrt(x);
	}

	public static double getX(double y)
	{
		double x = y * 2000000;

		double max = 0;
		double min = 0;
		double[] minmax = new double[2];

		double tmp = func(x);
		double diff = tmp - y;

		if (diff > 0.0)
		{
			max = x;
			minmax = getMin(x / 2, x, y);
		}
		else if (diff < 0.0)
		{
			min = x;
			minmax = getMax(x, x * 2, y);
		}
		else
		{
			return x;
		}
		min = minmax[0];
		max = minmax[1];

		return dichotomie(min, max, y);
	}

	private static double dichotomie(double min, double max, double y)
	{
		double x = (min + max) / 2;
		double tmp = func(x);
		double diff = tmp - y;
		if (diff > 0)
		{
			return dichotomie(min, x, y);
		}
		else if (diff < 0)
		{
			return dichotomie(x, max, y);
		}
		else
		{
			return x;
		}
	}

	private static double[] getMax(double min, double x, double y)
	{
		double tmp = func(x);
		double diff = tmp - y;
		if (diff > 0)
		{
			return new double[] {min, x};
		}
		return getMax(x, x * 2, y);
	}

	private static double[] getMin(double x, double max, double y)
	{
		double tmp = func(x);
		double diff = tmp - y;
		if (diff < 0)
		{
			return new double[] {x, max};
		}
		return getMin(x / 2, x, y);
	}
}

The strength of this algorithm is that I even don’t need to know the detail of func(x), I can treat it like a black-box.
enjoy;

Trop fort le mec. J’espère que je peux avoir une moitié de sa connaissance. I hope I could have 1/2 of his knowledge.
Very interesting reading. For anyone who love Java.
Writing Better Code: A Conversation With Sun Microsystems Technology Evangelist Brian Goetz

Wrong Intuitions About Performance Problems
We’re intimately familiar with the code that we write. The external services that we depend on, whether libraries or external agents, such as databases and web services, are out of sight and out of mind. So when we see a performance problem, we tend to think about places in our code that we can imagine being performance problems. But often, that’s not the source of the performance problem — it’s somewhere else in the application’s architecture.

“Write Dumb Code”
Often, the way to write fast code in Java applications is to write dumb code — code that is straightforward, clean, and follows the most obvious object-oriented principles. This has to do with the nature of dynamic compilers, which are big pattern-matching engines. Because compilers are written by humans who have schedules and time budgets, the compiler developers focus their efforts on the most common code patterns, because that’s where they get the most leverage. So if you write code using straightforward object-oriented principles, you’ll get better compiler optimization than if you write gnarly, hacked-up, bit-banging code that looks really clever but that the compiler can’t optimize effectively.

Moving From C to Java Programming
The Java language is not just a syntax: There’s a design philosophy that goes with managed languages. To get the benefit of Java programming, you have to understand that you are not just programming in C with a different syntax.

Advice for Beginners: Learn the Class Libraries
because they can make you more productive and make your programs smaller, more reliable, and easier to read and maintain.

Java SE 6 – JSR 223: Scripting Integration
You can call back and forth between JavaScript and Java applications and use the Java class libraries in JavaScript. JSR 223 offers a very nice integration between the Java environments and PHP, Ruby, JavaScript, or whatever your favorite scripting language is.

Because of the tight integration, developers are no longer forced into an either-or choice. They don’t have to choose between writing in the Java language or in, say, Python. By making it so easy to call back and forth between Java code and scripting code, you get the best of both worlds. You can develop most of an application in Java code and develop pieces in Python, which may enhance productivity because you can use the right tool at the right point.

It also opens the door to a new generation of extensible applications that allow us to ship applications that have extension points that call out to scripts. So instead of customizing applications by configuring some horrible XML configuration file, which is often underdocumented and hard to do, we’ll configure and customize applications by running scripts when needed. We’ll insert behavior into these applications as opposed to controlling whatever options the environment gives us.

Applications will be more extensible, easier to customize, and easier for developers to deliver, because we won’t have to anticipate everything that every customer might want to do with an application. We can simply provide them with an extension mechanism.

I read this article this morning : Becoming a Better Programmer: A Conversation With Java Champion Heinz Kabutz.
It’s good to see others points of view. It helps open my mind.
Here’s some points that I find interesting:

When I asked Sun’s Brian Goetz the key to writing fast Java code, he said developers should write “dumb code,” by which he meant straightforward, clean code that follows the most obvious object-oriented principles in order to get the best compiler optimization. Compilers are big pattern-matching engines, written by humans who have schedules and time budgets, so they focus their efforts on the most common code patterns, in order to get the most leverage. Goetz argues that clever, hacked-up, bit-banging code will get poorer results.

JSC: What are some of the big mistakes that even experienced Java developers make?

Kabutz: Not unit testing.

To really learn, you need to choose the technology that you want to experiment in and take the time to study and read, which will require sacrificing your personal time. If you follow this advice, you’ll grow more valuable over time and won’t become a computer dinosaur.

If you are currently a Java programmer, you owe it to yourself to experiment in other technologies. Try out Squeak, JRuby, and other languages. Install and use a different IDE. Never stop learning. The moment you stop, you can lose the wave, and it will require a lot of paddling to catch up with it again.

Recently, I work with the Calendar and GregorianCalendar classes of Java (JDK 1.4.2). I used the Calendar.add(int field, int amount) method. But I found that there is an incoherent between the Javadoc and the behavior of the method.

Here is the extract of Javadoc for the Calendar class:

Usage model. To motivate the behavior of add() and roll(), consider a user interface component with increment and decrement buttons for the month, day, and year, and an underlying GregorianCalendar. If the interface reads January 31, 1999 and the user presses the month increment button, what should it read? If the underlying implementation uses set(), it might read March 3, 1999. A better result would be February 28, 1999. Furthermore, if the user presses the month increment button again, it should read March 31, 1999, not March 28, 1999. By saving the original date and using either add() or roll(), depending on whether larger fields should be affected, the user interface can behave as most users will intuitively expect.

I interpreted this as following:
If I have the date “31 January 2007” and I use add(Calendar.MONTH, 1), I should obtain the date “28 February 2007”. — This is exactly what the method did. OK
If I have the date “28 February 2007” and I use add(Calendar.MONTH, 1), I should obtain the date “31 March 2007”. — This is unfortunately NOT what the method did. I obtained “28 March 2007”

Here is the code I used:

package test;

import java.util.Calendar;
import java.util.GregorianCalendar;

import junit.framework.TestCase;

/**
 * @author Hong Nam NGUYEN -- Created: 4 oct. 07 - 10:38:28
 */
public class CalendarTest extends TestCase
{
    final int MONTH = Calendar.MONTH;
    final int DAY_OF_MONTH = Calendar.DAY_OF_MONTH;
    static Calendar calendar = new GregorianCalendar();
    static {
	calendar.clear();
	calendar.set(2007, Calendar.JANUARY, 31);
    }
	
    public void testAdd1()
    {
	calendar.roll(MONTH, 1);
	assertEquals(
            "Should be February", Calendar.FEBRUARY, calendar.get(MONTH));
	assertEquals("Should be 28", 28, calendar.get(DAY_OF_MONTH));
    }
	
    public void testAdd2()
    {
	calendar.roll(MONTH, 1);
	assertEquals(
            "Should be March", Calendar.MARCH, calendar.get(MONTH));
	assertEquals("Should be 31", 31, calendar.get(DAY_OF_MONTH));
    }
}

the second test is down.

I have reported this bug to Sun, so wait for the response.

[Add 10-oct-2007] I had the response from Sun, so this is really a bug. Sun had added this bug to their internal bug tracking system under Bug Id: 6615044.
We can see the bug on the Java Bug Database at:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6615044