Java


Les getters/setters, dans la plupart des cas, ne sont pas nécessaires et ils pollutent notre code, rendent le code plus long, les classes plus ouvertes (sans la vrai nécessité) donc plus vulnérables face au changement et la maintenance plus difficile.
Examinons le code suivant:

	private int height; 
	
	public void setHeight(int height) {
		this.height = height;
	}
	public int getHeight() {
		return height;
	}


D’abord, on déclare la propriété “height” en privé, biensûr, pour cacher l’information – comme on a tout appris dans les principes de la programmation orienté-objet. Mais juste après, on a les fameux getters/setters: getHeight et setHeight qui donnent l’accès totale à notre propriété ???
C’est encore plus dangereux si height est un pointeur (de type List, Set, …) parce que dans ce cas le getter seul suffit pour exposer la propriété au public (si on n’utilise pas le “defensive copy”, et c’est souvent le cas avec la génération automatique de getters/setters)
Pire encore, cette pratique est aussi un signe de mauvais design car elle transgresse les principes de la programmation orienté-objet (encapsulation) et rend le programme plus procédural que objet.
Avec 2 ans dans l’environnement professionnel, j’ai vu plein de code comme au-dessus. Qui a écrit “bêtement” les getters/setters comme ça ? Personne! Avec les IDEs modernes, les gens apprennent vite l’habitude de générer les getters/setters et comme c’est trop facile à faire, on trouve partout les getters/setters qui ne sont jamais vraiment utilisés. Ils sont juste là, comme une bombe à retardement, ne font rien mais attendent le jour où on doit faire des changements au code pour exploser.
Pour savoir pourquoi les getters/setters sont mauvais:
Why getter and setter methods are evil
Un excellent article sur les getters et le design de Martin Fowler:
GetterEradicator

La question a l’air simple mais la réponse (ou plutôt les réponses) demande quand même des détails précises.

Supposons que j’ai 2 nombres: n et m, avec m = 0 et dans mon programme je fais: result = n / m;
Qu’est-ce que je vais obtenir comme résultat ? une exception ? un nombre ? ou quelque chose qui n’est pas un nombre ?
La réponse est : les 3 et ça dépend du n et m
Concret:

  • si m ou n ou les deux sont float ou double, on a 3 cas
    1. si n > 0, le résultat est +Infinity (le constant POSITIVE_INFINITY de la classe Float ou Double)
    2. si n = 0, le résultat est NaN (Not a Number – le constant NaN de la classe Float ou Double)
    3. si n < 0, le résultat est -Infinity (le constant NEGATIVE_INFINITY de la classe Float ou Double)
  • si m et n sont int ou long, on a une exception (java.lang.ArithmeticException)

Donc il faut faire attention quand on divise par zéro dans le programme. Dans la plupart des cas, un try…catch ne suffit pas.

Plus de détails: le livre “The Java Language Specification, Third Edition – page 26”

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.

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

Next Page »