Tuesday, August 22, 2006

Tricky instanceof operator

Let's start with a little puzzle.

Object obj = ...
System.out.println(obj instanceof Object);

How do you initialize the obj in order to print "false"?

Well, aren't all possible Java objects instances of Object? To answer this question one must understand how instanceof operator works. The answer is that it would print "true" for any Object. The only way to make it false is not to give it an object, give it a null reference.

The tricky bit about instanceof operator can be that if object on the left side is null, the condition evaluates to false. Therefore there is no need for null check after a class cast as in the following example.

public boolean equals(Object o) {
if (o instanceof MyClass) {
MyClass mc = (MyClass) o;
if (mc == null) // never null
return false;
else
return ... // compare members of mc
}
return false;
}

This can be simplified as shown in the following code snippet

public boolean equals(Object o) {
if (o instanceof MyClass) {
MyClass mc = (MyClass) o;
return ... // compare members of mc
}
return false;
}

So the moral if this excercise is that instanceof operator works as you would expect with objects, and returns false when given a null.

And remember that equals() method is probably the only reasonable place for instanceof operator. If you do it elsewhere and use it to create an alternative flow (e.g. if-else, switch) it is a bad smell and should be replaced with polymorphism. Read more about Swich Statement code smell and Polymorphism

BTW the previous example was not a very nice example of how to implement equals method, so do not copy it ;-) Usually we would do something like this

public boolean equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (!(o instanceof MyClass)) return false;
MyClass mc = (MyClass) o;
return ... // compare members of mc
}

Saturday, August 19, 2006

Swich Statement code smell and Polymorphism

One of the symptoms of object-oriented programming is the lack of switch or case statements. Imagine that we have some client class that calculates the area and perimeter of particular geometrical shapes.

public class Client {
private double a;
private double b;
private double r;
...
public double calculateArea(int shape) {
double area = 0;
switch(shape) {
case SQUARE:
area = a * a;
break;
case RECTANGLE:
area = a * b;
break;
case CIRCLE:
area = Math.PI * r * r;
break;
}
return area;
}

public double calculatePerimeter(int shape) {
double perimeter = 0;
switch(shape) {
case SQUARE:
perimeter = 4 * a;
break;
case RECTANGLE:
perimeter = 2 * (a + b);
break;
case CIRCLE:
perimeter = 2 * Math.PI * r;
break;
}
return perimeter;
}
...
}

The previous code is clearly a poor design that limits the current client to only work with three types of shapes. The problem with switch statements is the duplication and that is a code smell. There are usually several places in the code where the behaviour slightly deviates and these switch statements are present (e.g. in calculateArea and calculatePerimeter methods). Even worse case is if we work with objects where the switch is replaced by multiple instanceof conditions.


public class Client {
...
public double calculateArea(Object shape) {
double area = 0;
if (shape instanceof Square) {
Square square = (Square) shape;
area = square.getA() * square.getA();
}
else if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
area = rectangle.getA() * rectangle.getB();
}
else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
area = Math.PI * cirle.getR() * cirle.getR();
}
return area;
}

public double calculatePerimeter(Object shape) {
double perimeter = 0;
if (shape instanceof Square) {
Square square = (Square) shape;
perimeter = 4 * square.getA();
}
else if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
perimeter = 2 * (rectangle.getA() + rectangle.getB());
}
else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
perimeter = 2 * Math.PI * cirle.getR();
}
return perimeter;
}
}

To improve the desing we make Square, Rectangle and Circle have a commont root. By that I mean that they either extend the same class, such as AbstractShape or that they implement a common interface, such as Shape or ideally both.

Then we can eliminate the switch statement code smell very easily. We replace it with polymorphism.

Shape.java file
public interface Shape {
public double getArea();
public double getPerimeter();
}

Square.java file
public class Square implements Shape {
private double a;
...
public double getArea() {
return a * a;
}
public double getPerimeter() {
return 4 * a;
}
}

Rectangle.java file
public class Rectangle implements Shape {
private double a;
private double b;
...
public double getArea() {
return a * b;
}
public double getPerimeter() {
return 2 * (a + b);
}
}

Circle.java file
public class Circle implements Shape {
private double r;
...
public double getArea() {
return Math.PI * r * r;
}
public double getPerimeter() {
return 2 * Math.PI * r;
}
}

And such refactoring simplifies the Client code. It also allows for easy extensibility by implementations of other shapes without changing a single line of Client code.

public class Client {
private Shape shape;
...
public double calculateArea() {
return shape.getArea();
}
public double calculatePerimeter() {
return shape.getPerimeter();
}
}

Another way of looking at it is from the responsibility point of view. Why should the client be responsible for calculating the area or the perimeter; or have a knowledge about shape's internals (e.g. number of sides, radius, etc.) It is the responsibility of each shape and all that the client needs to know is that a shape has a perimeter and area.

To sum this all up:

Wednesday, August 16, 2006

Programmable Web and GoogleMaps Fligh Simulator

Today I came across an iteresting website: ProgrammableWeb - because the world's is your programmable oyster. In their words:

ProgrammableWeb is where you can keep-up with the latest mashups, what's new and interesting with Web 2.0 APIs, and the Web as Platform in general. The core of the site is the blog and the 3 dashboards: Home, Mashups and APIs. All dashboards are updated daily.

It's worthwhile having a look at API part. And this is how I found

Quite nice app, good fun exploring the world without being scared of terrorism! And as you can see I had a few successful flights over the Sydney Opera House. But be careful! Do not fly too low, you can crash!

Sunday, August 13, 2006

Improved Map Iteration

When some one new to Java comes to play, first thing they do, they re-invent the wheel. Such wheel can be a class that is already implemented in java.util package. Yes! Collections and Maps! Later, as you become a senior Java developer you alredy know the narrow places in the "Utils" valley. And yet we can make mistakes.

Such mistake can be the following implementation of the method that calculates the size of the collection.

private Collection myStuff = ...

public int calculateSize() {
int count = 0;
for (Iterator it = myStuff.iterator(); it.hasNext(); it.next()) {
count++;
}
return count;
}

This can be easily fixed by

public int calculateSize() {
return myStuff.size();
}

Another, more frequent example of bad performance is a condition where one wants to know if there are any objects in the collection, but does not really care how many there are.

if (myStuff.size() == 0) {
// do something
}

Remember size() method may possibly calculate the size and therefore generally is slower than a call to isEmpty() method. Therefore the fix is obvious.

if (myStuff.isEmpty()) {
// do something
}

Could you imagine that I once worked for a company where the senior developers did not know about Iterators? So instead of

for (Iterator it = myStuff.iterator(); it.hasNext();) {
Object item = it.next();
// do something with the item
}

they had

for (int i = 0; i < myStuff.size(); i++) {
Object item = myStuff.get(i);
// do something with the item
}

and on top of that myStuff was a Vector, which is synchronized. Very sloooow code!

Nevertheless my point is: Know your collections!

Now back to the topic of improving the Map iteration. Well, it really depends what we need to do at each step of our iteration.

If you need to iterate over the keys of the Map do this

for (Iterator it = myMap.keySet().iterator(); it.hasNext();) {
Object key = it.next();
// do something with the key
}

And if you need to iterate over the values of the Map do this

for (Iterator it = myMap.values().iterator(); it.hasNext();) {
Object value = it.next();
// do something with the value
}

But what if we need both the key and the value? The usual approach and very bad approach is to get the set of keys, iterate over them and get the value for each key.

for (Iterator it = myMap.keySet().iterator(); it.hasNext();) {
Object key = it.next();
Object value = myMap.get(key);
// do something with the key and the value
}

What is wrong about this? Nothing! You can do it this way and it's perfectly fine. It is just very inefficient as at each iteration a map needs to look up the value for a given key. It is better to iterate over map entries. There is a special interface Map.Entry that can be used to retrieve the key and the value of each entry in the map. So the previous example can be transformed into

for (Iterator it = myMap.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
// do something with the key and the value
}

Don't forget to change myMap.get(key) to entry.getValue(), otherwise you are not gaining anything from this modification. I did this recently, I omitted to change it, even worse - I changed it to myMap.get(entry.getValue()). As a result the map was not finding anything... Luckily, we had tests around the class I modified and my stupid mistake was caught early.

Have the tests ready before making changes! Even experienced people make mistakes.

Server Polling - Reverse AJAX

I am starting to feel a bit old or old-school. I know the concepts of AJAX but never had enough time (or project) to get my hands dirty doing AJAX. So I decided to make time and learn AJAX by doing.

I joined the 10-Week Free AJAX Programming (with Passion!) online course organized by Sang Shin from Sun Microsystems. This course is in its second week now and the homework was:

"... to write one or two paragraphs describing an "interesting" AJAX related technology/feature you find while you are playing with the online demos or while reading AJAX articles on the net"

I though that it would be good to share my point of view with you. So, here I go.

Title: Server Polling - Reverse Ajax)
URL: http://ajaxian.com/archives/reverse-ajax-with-dwr

Keeping the displayed information up-to-date was always difficult in web world. Before AJAX, one had to use JavaScript or META Refresh tag to get the page refreshed. This was quite annoying from the user experience point of view. However it was not as annoying as something that I experienced few days ago on one of the banks website (a bank in Australia). I was filling out the form and there were couple of select boxes on the page. I selected an option in the select box and moved onto next field just to realize that as I was typing, the page has been reloaded and all data entered past that select-box was gone and had to be re-typed again. Very, very annoying - and it's AJAX age already!

Server polling, in my humble opinion, is a great feature of AJAX. There is no need to refresh the whole page to obtain the required information. With AJAX, it is possible to:

  • update the forms with information as the user moves through the form (e.g. country - state - city)
  • get the feedback about a long server-side or transport process (e.g. progress bar showing the percentage of the uploading file)
  • fake the push of the updated data from the server (think stock prices, weather, traffic info)

I am sure that I will come across more coolness when I start writing more and more Ajax code!

Thursday, August 10, 2006

Empty String

How many times have you coded a check for String being null or empty? Countless times, right? I have. We use some ready-to-use classes from open source frameworks or we write our own StringUtils class. More or less they all implement the same thing and it always looks similar to the following code snippet:

String s = ...
if (s == null || s.equals(""))...

or similar to the following, which trims leading and ending whitespaces

String s = ...
if (s == null || s.trim().equals(""))...

Of course you could also do this:

"".equals(s)

which is a case when you do not care if String s is null and you don't have to worry about NPE as if won't happen ("" is never null, whereas s could be). But that's another story.

I have had "extra" warnings turned on in my IDE for couple of days. But today my IDE suprised me when it highlighted

[1] s.equals("")

and suggested that I could optimize it by making it to

[2] s.length() == 0

And guess what?! The IDE was right! I looked at the suggested code briefly, gave it a bit of thought and agreed that it would probably be faster. Method [1] creates a new instance of the String (an empty String, yes I know that all instances of "" would be caught during compilation and optimized and that they all would refer to the same instance). Just to be on the safe side I looked at the source of the String class.

And here is what I found. The length() method returns and integer primitive, which is not calculated with each method call to length(). It is rather a member variable (or constant, as Strings are invariants) of String class that is calculated when new String instance is created. So this method would be super fast.

536   public int length()
537 {
538 return count;
539 }

On the other side, there is the equals() method, which is fast as well, but not as fast as length method. It has to do a check for class, class casting and comparison of count members (that's what length method returns).

684   public boolean equals(Object anObject)
685 {
686 if (! (anObject instanceof String))
687 return false;
688 String str2 = (String) anObject;
689 if (count != str2.count)
690 return false;
691 if (value == str2.value && offset == str2.offset)
692 return true;
693 int i = count;
694 int x = offset;
695 int y = str2.offset;
696 while (--i >= 0)
697 if (value[x++] != str2.value[y++])
698 return false;
699 return true;
700 }

And remember the few important points when it comes to Strings:

  • Do not compare Strings with == operator. Unless you want to compare the object references. Use equals() method.

  • Do not construct new instances like new String("abc"). Simple "abc" will do, unless you really mean that you need a new instance of String with same value. Read more about How useful is String(String) constructor

  • Do not concatenate Strings in loops using + operator. It's faster to use StringBuffer (or StringBuilder, which is in Tiger and is not synchronized) append() and then toString() methods instead. The plus (+) operator constructs new String object each time.

Saturday, August 05, 2006

Comments in Java Code

We all use comments to describe the Java code. There are three types if comments in Java as demonstrated in this Java tutorial by SUN:

// text

where the compiler ignores everything from // to the end of the line

/* text */

where the compiler ignores everything from /* to */ and

/** documentation */

which is ignored by the compiler the same way as the previous comment type. This one is a special comment as this indicates a documentation comment. The JDK javadoc tool uses doc comments when preparing automatically generated documentation.

I am not going to tell you how to use them. There are many articles and documentation written about that. We all know how to use them and most of us use them on a daily basis. Over time we can develop a stereotype. Mine looks like this:


/** first name */
private String firstName;

/** last name */
private String lastName;

/**
* Constructs and returns the full name
* @return full name
*/

public String getFullName() {
if (firstName == null) {
if (lastName == null) {
// user does not have a name specified
return "[no name]";
}
else {
return lastName;
}
}
else {
if (lastName == null) {
return firstName;
}
else {
// construct full name from first and last name
return firstName + " " + lastName;
}
}
}

As you can see, I use doc comments to describe the meaning and function of my class members. I also like to use line comments, rather than block comments. Even if my comment spans multiple lines I prefer to use // comments. It's due to my IDE settings. When I press Ctrl+/ it un-/comments the selected lines. It's very neat feature and I use it a lot.

Recently, I was doing some code modifications and I wanted to re-visit some code later. I decide to break the code by putting a comment in the middle if it, so it would not compile and I would be forced to come back to it.

I did somethig like this:


myObject.getAnother()/* change to ID */.getName();

To my surprise the code did not break. Even when I changed it to


myObject.getAnother()./* change to ID */getName();

Obviously, when I did this


myObject.getAnother().ge/* change to ID */tName();

the code broke. At the end I made it to break in a nice way, anyway


myObject.getAnother()./* change to ID */.getName();

(notice an extra dot)

All this made me thinking. Where are all the valid spots for the comments. After I read the definition for Java comments I understood why it worked, but I simply find it puzzling. Of course, we do not put comments in places like this, but the language allows us to.

I am not sure if there is any value in this lesson learnt. It would certainly make a good exam question though. I can see it now: "Will the following code compile?" ...


Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.