Monday, August 27, 2007

Java Puzzlers, Episode 6

I am a big fan of Java Puzzlers.

Another part of the Java Puzzler series appeared on Google Video couple days ago. This is one named Advanced Topics in Programming Languages: Java Puzzlers, Episode VI and is a repeat of a talk given at Google in May and at JavaOne 2007.

Josh Bloch and special guest star Bill Pugh present yet another installment in the continuing saga of Java Puzzlers, consisting of eight more programming puzzles for your entertainment and enlightenment.

I really enjoyed watching it and also learnt a thing or two.

Funny thing was when Bill Pugh said in the conclusion:

Use FindBugs: it finds all 8 bugs in this talk!

I use FindBugs everyday and I have to tell you, our codebase (JIRA) is quite clean and FindBugs helps us to keep it that way.

Alright! Enough said. Go on! Watch it!

Related posts: Java Puzzlers

Sunday, August 26, 2007

Contract of the interfaces

As I mentioned in my previous post titled Don't test everything, unit testing is very valuable in the software development process, but on some occasions the test expects more that it should. In some cases those expectation work fine, in other they fail.

What the hell am I talking about? If you follow the good practice of coding against interfaces, you know that the interface defines the contract all implementation classes must adhere to. If you write an implementation of an interface your unit tests should test possibly everything that this contract specifies and nothing more.

Take a Set from Java Collections Framework for example. This interface is defined as:

A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.

At some point I had a unit test that had some input values and my test was assuming the correct results in the set that was returned. I knew that my implementation wa returning a HashSet and I also knew what was in that set. The asserts were quite simple (the code is simplified):

String[] addresses = new String[] {"address1", "address2", "address3"};
Set set = new HashSet(Arrays.asList(addresses));
Iterator i = set.iterator();
assertEquals("address1", i.next());
assertEquals("address2", i.next());
assertEquals("address3", i.next());

It's a good test, you may think. Well, it isn't! This test runs or fails depending on which JDK you use. The problem with this test is that it assumes the order of the elements in the returning set. Set interface does not guarantee the order of its elements. We should not test that.

Let's have a look at the following unit test

import junit.framework.TestCase;

import java.util.Set;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;

public class TestJdkDiff extends TestCase
{
    public void testOrder()
    {
        String javaVersion = System.getProperty("java.version");
        String javaVendor = System.getProperty("java.vendor");
        System.out.println("Running " + javaVendor + " " + javaVersion);

        String[] addresses = new String[] {"address1", "address2", "address3"};
        final Set set = new HashSet(Arrays.asList(addresses));
        for (Iterator i = set.iterator(); i.hasNext();)
        {
            System.out.println(i.next());
        }
    }
}

Execution of the previous test on Java 6 produces the following output

Running Sun Microsystems Inc. 1.6.0_02
address1
address2
address3

The same test executed on Sun's JVM 1.4 prints out

Running Sun Microsystems Inc. 1.4.2_12
address2
address3
address1

Oops! Now I know why my test failed. Even, in JDK the implementation of some classes can change from time to time. As long as the contact is kept all should be fine.

So to fix my initial test one should write

String[] addresses = new String[] {"address1", "address2", "address3"};
Set set = new HashSet(Arrays.asList(addresses));
assertEquals(3, set.size());
assertTrue(set.contains("address1"));
assertTrue(set.contains("address2"));
assertTrue(set.contains("address3"));

Happy coding!

Thursday, August 16, 2007

Keep it simple

Recently I saw pieces of code that could be simplified. I see such code often, however, recently I came across code that seemed to follow the same pattern

The patern was as in the following example:


private boolean someFlag;

...

public boolean isSomeFlagSet() {
if (someFlag) {
return true;
}
else {
return false;
}
}

Why not simply write:


public boolean isSomeFlagSet() {
return someFlag;
}

It is so much simpler!

Similarly to boolean flags, there where occurencies of other object types being used and methods invoked on them in the following manner:


public String getCity() {
if (address == null) {
return null;
}
else {
return address.getCity();
}
}

This can be also simplified (applying "change if-else to ?:" refactoring) to:


public String getCity() {
return address == null ? null : address.getCity();
}

Please strive for simplicity in your code (K.I.S.S. principle). Verbosity clutters the code and can hide the meaning or intention of it.

Sunday, August 12, 2007

ArithmeticException vs. NaN

Recently I worked on a small UI widget that renders bars that represent percentage. The percentage could be calculated by a simple formula such as the following:

percentage = value / total * 100%

Imagine a utility method that calculates the percentage and looks like the following:

public static int calcPercentage(int value, int total) {
return 100 * value / total;
}

You could say that this is a fairly simple method and would not be that hard to unit test it. Assuming that the given parameters will never be negative numbers one could whip up a sample test values very quickly.

public void testCalPercentage() {
assertEquals(0, calcPercentage(0, 2));
assertEquals(33, calcPercentage(1, 2));
assertEquals(50, calcPercentage(2, 2));
}

Take a bunch of positive numbers or zeros... Wait! Zeros?! But there could be a possible division by zero! That's right! There is our edge case. Let's test it! Aha! We now get an ArithmeticException.

public void testCalPercentageDivisionByZero() {
try {
assertEquals(0, calcPercentage(0, 0));
fail();
}
catch (ArithmeticException ex) {
// expected
}
}

That's understandable. So we need to work around this and the bar should not be rendered if not values (zeros) were entered.

And here comes the twist! Change the type of spent and remaining variables from primitive int to primitive float.

public static int calcPercentage(float value, float total) {
return (int) (100 * value / total);
}

No exception is thrown anymore. What happened? Why such a different behavior?

It all boils down to how Java and other programming languages handle float point arithmetic. I hope that the following quote sums it all.

Floating-point numbers in the JVM use a radix of two. Floating-point numbers in the JVM, therefore, have the following form:

sign * mantissa * 2 exponent

The mantissa of a floating-point number in the JVM is expressed as a binary number. A normalized mantissa has its binary point (the base-two equivalent of a decimal point) just to the left of the most significant non-zero digit. Because the binary number system has just two digits -- zero and one -- the most significant digit of a normalized mantissa is always a one.

The most significant bit of a float or double is its sign bit. The mantissa occupies the 23 least significant bits of a float and the 52 least significant bits of a double. The exponent, 8 bits in a float and 11 bits in a double, sits between the sign and mantissa. The format of a float is shown below. The sign bit is shown as an "s," the exponent bits are shown as "e," and the mantissa bits are shown as "m":

Bit layout of Java float
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

The exponent field is interpreted in one of three ways. An exponent of all ones indicates the floating-point number has one of the special values of plus or minus infinity, or "not a number" (NaN). NaN is the result of certain operations, such as the division of zero by zero. An exponent of all zeros indicates a denormalized floating-point number. Any other exponent indicates a normalized floating-point number.

The JVM throws no exceptions as a result of any floating-point operations. Special values, such as positive and negative infinity or NaN, are returned as the result of suspicious operations such as division by zero. An exponent of all ones indicates a special floating-point value. An exponent of all ones with a mantissa whose bits are all zero indicates an infinity. The sign of the infinity is indicated by the sign bit. An exponent of all ones with any other mantissa is interpreted to mean "not a number" (NaN). The JVM always produces the same mantissa for NaN, which is all zeros except for the most significant mantissa bit that appears in the number. These values are shown for a float below:

Special float values
ValueFloat bits (sign exponent mantissa)
+Infinity0 11111111 00000000000000000000000
-Infinity1 11111111 00000000000000000000000
NaN1 11111111 10000000000000000000000


Things like these we learn when we learn computer programming and tend to forget over time. And then... a simple percentage calculation will remind us.

Happy coding!


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