Sign up to receive your copy of the JavaRanch Journal.

productivity award
JavaRanch Newsletter Articles in this issue :
The SCJP Tip Line - hashCodes UncoveredCorey McGlone
Printable Version
LegoTM meets JavaTM: RoboJDE vs. LeJOSJessica Sant
Printable Version
Whizlabs SCMAD Exam Simulator (CX-310-110) ReviewValentin Crettaz
Printable Version
The Coffee House - An Agile ExcursionSolveig Haugland
Printable Version
Meet the Author - Solveig HauglandDirk Schreckmann
Printable Version
Saloon Question and Answer of the Month - Use OOP to design database tables schema?Dirk Schreckmann
Printable Version
Book Review of the Month - Software by NumbersMatthew Phillips and Lasse Koskela
Printable Version
Book Promotions coming in July and August Dirk Schreckmann Printable Version

SCJP Tip Line - hashCodes Uncovered
The SCJP Tip Line
hashCodes Uncovered
by Corey McGlone

In this edition of the JavaRanch Journal SCJP Tipline, author Corey McGlone investigates hashCodes, expanding on an April blog entry.

What is a hashCode?

First of all, what the heck are hashcodes for? Well, oddly enough, they're used heavily in Hashtables. Hashtables, along with the other classes that extend the Map interface, are discussed in this Journal article For the purposes of this article, I'm going to assume you know what a Hashtable is and how useful it can be. Needless to say, Hashtables can help you keep a large number of objects organized and allow you to access them very quickly. Of course, to do so, a Hashtable relies on the power of the hashCode method.

In essence, when you invoke the get(Object o) method of a Hashtable, the Hashtable will use the hashCode method of the object you passed to it in order to access an object (or list of objects). As long as the hashCode method is working properly, everything works just fine. If it doesn't, however, you can have some rather serious problems.

So, what makes a valid hashCode? Well, here's what is said about hashCodes in the API Specification for Object:

The general contract of hashCode is:
  1. Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  2. If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  3. It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

Study: A Proper hashCode

Let's start by looking at a good program. In this case, we've defined a new object, MyObject, which defines its own equals and hashCode methods. In general, it is good practice to define your own hashCode method any time you override equals (more about this later). Here it is:

import java.util.Hashtable;
import java.util.Date;

public class MyObject
{
    int a;
    
    public MyObject(int val)
    {
        a = val;
    }
    
    public boolean equals(Object o)
    {
        boolean isEqual = false;
        
        if ( o instanceof MyObject )
        {
            if ( ((MyObject)o).a == a )
            {
                isEqual = true;
            }
        }
        
        return isEqual;
    }
    
    public int hashCode()
    {
        return a;
    }
    
    public static void main(String[] args)
    {
        Hashtable h = new Hashtable();
        
        MyObject[] keys = 
        {
            new MyObject(11),
            new MyObject(12),
            new MyObject(13),
            new MyObject(14),
            new MyObject(15),
            new MyObject(16),
            new MyObject(17),
            new MyObject(18),
            new MyObject(19),
            new MyObject(110)
        };
        
        for ( int i = 0; i < 10; i++ )
        {
        	h.put(keys[i], Integer.toString(i+1));
        }
        
        long startTime = new Date().getTime();
        
        for ( int i = 0; i < 10; i++ )
        {
        	System.out.println(h.get(keys[i]));
        }
   
        long endTime = new Date().getTime();
        
        System.out.println("Elapsed Time: " + (endTime - startTime) + " ms");
    }
}

Executing the above code leaves you with this output:

1
2
3
4
5
6
7
8
9
10
Elapsed Time: 0 ms

As you can see, we easily retrieved the objects we had originally put into the Hashtable and it took practically no time at all. How does our hashCode method do? Does it pass all 3 of the criteria laid out earlier? Let's look at each of the criteria one at a a time.

1. Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

Does our hashCode meet that criteria? Does our hashCode continually return the same value (assuming that our variable, a, hasn't changed)? Certainly, it does - it returns the value of a. Okay, next criteria.

2. If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

How about this one? Does our hashCode method still work here? Sure, it does. If two object have the same value for a, they will be equal (by the equals method). In such a situation, they would also return the same hashCode value. Our hashCode method works here. Okay, on to the final criteria.

3. It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

Well, this isn't really a requirement at all - it's more of a suggestion, if anything. It is best if the hashCodes for unequal objects are different, but it's not required. We'll look at this a little more in a few minutes.

So, there you have it - we've successfully overridden the hashCode method. So, how do you know when you should do such a thing? Well, in general, it's considered good practice to override hashCode any time you override equals. The reason for this is due to the default behavior of the equals and hashCode methods.

When Should you Override hashCode()?

In Java, the default equals method (as defined in Object) compares the two objects to see if they are, in fact, the same object. That implementation does not take into account any data that might be contained by the object. For example, had we not overridden the equals method in our class, MyObject, we'd see that the following code:

MyObject obj1 = new MyObject(1);
MyObject obj2 = new MyObject(1);
System.out.println(obj1.equals(obj2));

...would produce the output "false." The reason for this is that, even though the two objects contain the same data, they are different objects - two separate objects on the heap. Fortunately, we overrode the equals method and, given the MyObject class as defined originally, we'd get the output "true" from this example. However, what about the hashCode?

Well, the default hashCode method works in a similar fashion to the default equals method. It converts the internal address of the object into an int and uses that as the hashCode. Well, that won't work so well here. We just defined a way in which two distinct objects (which will, necessarily, have distinct memory addresses) to be considered "equal." The default hashCode implementation, however, will return different hashCodes for the two objects. That violates the second rule defined above - any objects that are considered equal (by their equals method) must generate the same hashCode value. Therefore, whenever you override the equals method, you should also override the hashCode method.

Study: Faulty hashCodes

What happens if we override the hashCode method poorly? Let's violate one of the rules, shall we? Let's change our hashCode method to look like this:

public int hashCode()
{
    return (int)(Math.random() * 5);
}

This one actually violates a couple rules. Not only does it not guarantee that two objects that are equal have the same hashCode, it doesn't even guarantee that the same object will keep the same hashCode from one invocation to the next. Any idea what havoc this might wreak on a poor, unsuspecting Hashtable? If I execute the main method again, as I did before, I get this output:

null
2
null
4
null
6
null
null
null
null
Elapsed Time: 0 ms

Eek! Look at all of the objects I'm missing! Without a properly functioning hashCode function, our Hashtable can't do its job. Objects are being put into the Hashtable but we can't properly get at them because our hashCode is random. This is certainly not the way to go. If you were to run this, you might even get different output than I got!

Even if the hashCode that is returned is always the same for a given object, we must ensure that the hashCodes that are returned for two objects that are equal are identical (Rule #2). Let's modify our MyObject class so that we hold true to Rule #1 but not to Rule #2. Below is the modified parts of our class:

public class MyObject
{
    int a;
    int b;
    
    public MyObject(int val1, int val2)
    {
        a = val1;
        b = val2;
    }
    
    ...
    
    public int hashCode()
    {
        return a - b;
    }
    
    ...
    
    public static void main(String[] args)
    {
        ....
        MyObject[] keys = 
        {
            new MyObject(11, 0),
            new MyObject(11, 1),
            new MyObject(11, 2),
            new MyObject(11, 3),
            new MyObject(11, 5),
            new MyObject(11, 5),
            new MyObject(11, 6),
            new MyObject(11, 7),
            new MyObject(11, 8),
            new MyObject(11, 9)
        };
        ...
    }
}

Executing this code gives us some more disturbing results, although they may not appear that way at first. Here's my output:

1
2
3
4
5
6
7
8
9
10
Elapsed Time: 0 ms

So what's wrong with that, you ask? Well, what should the put method do? If you first put an object into a Hashtable using a specific key and then put a new value into the Hashtable using a key that is equal to that one, the original value should be replaced with this new one. That's not what's happening here. Instead, our Hashtable is treating our keys as if they're all unequal. Eek! This is the same result you could expect if you were to override equals without overriding hashCode. Here's the output we should get, assuming we have a good hashCode method:

10
10
10
10
10
10
10
10
10
10
Elapsed Time: 0 ms

Inefficient hashCodes

Okay, one more thing to go over. What happens if we have a valid hashCode, but the values aren't very distinct. In this case, I'm going to hold to requirements 1 and 2, but I'm going to ignore requirement 3 entirely. Let's modify MyObject.hashCode() and our main method to look like this:

public int hashCode()
{
    return 0;
}

public static void main(String[] args)
{
    Hashtable h = new Hashtable();
    
    MyObject[] keys = new MyObject[10000];
    for ( int i = 0; i < 10000; i++ )
    {
        keys[i] = new MyObject(i);
    }
    
    for ( int i = 0; i < 10000; i++ )
    {
    	h.put(keys[i], Integer.toString(i+1));
    }
    
    long startTime = new Date().getTime();
    
    for ( int i = 0; i < 10000; i++ )
    {
    	h.get(keys[i]);
    }

    long endTime = new Date().getTime();
    
    System.out.println("Elapsed Time: " + (endTime - startTime) + " ms");   
}

Note that this is a valid hashCode method. It always returns the same value for a given object, assuming that nothing used in the equals method changes (not that it cares anything about that). It also returns the same value for two objects that are "equal." What it doesn't do is return a different value for objects that are not equal. It always returns the same value. This is a valid hashCode but, as this example will show, an inefficient one. Executing this 5 times using this new hashCode method, I get this output:

Elapsed Time: 7016
Elapsed Time: 7125
Elapsed Time: 7297
Elapsed Time: 7047
Elapsed Time: 7218

That gives me an average time of 7140.6 - roughly 7 seconds. By executing my original hashCode method and execute the same main method, I got this output:

Elapsed Time: 16
Elapsed Time: 16
Elapsed Time: 16
Elapsed Time: 15
Elapsed Time: 16

That's an average of about 16 millseconds - a far cry from the 7 seconds we saw earlier! We're seeing a dramatic increase in the amount of time required to retrieve objects from our Hashtable using the poor hashCode method. The reason for this is that, with every key object having the same hashCode, our Hashtable has no choice but to index every value under the same hashCode. In such a case, we've got everything in one long list and our Hashtable does us no good at all - we might as well have stored the objects in an ArrayList.

Summary

Hopefully you see the importance of creating a valid hashCode for any objects you're using. Whenever creating your own hashCode method, it's important to remember the 3 rules. I've listed them here in a summarized format; refer to the API Spec for full details.

  1. The hashCode method must always return the same value (assuming the object has not changed) from one invocation to the next.
  2. The hashCode for multiple "equal" objects must be identical.
  3. The hashCodes for multiple "unequal" objects should be different, but it is not required.

With that knowledge, you should have a firm grasp on how to override hashCodes and make the most out of the Hashtable (and other Map classes) in Java. Remember to tune in to The SCJP Tipline for more updates.


Discuss this article in The Big Moose Saloon!


Return to Top

LegoTM meets JavaTM : RoboJDE vs. LeJOS

by Jessica Sant

Introduction

I recently took a Robot Building Lab as part of my Master's degree program. The class was a mix of graduate and undergraduate Computer Science students. The majority of the course was taught using the HandyBoard controller programmed with a C derivative called IC4. Being the Java geek that I am, I was thrilled when my professor mentioned there was a Java product out there that you could use to program the HandyBoard. Enter RoboJDE. All the graduate students had an additional requirement to program an RCX robot using leJOS. This article is based on my experience of the two platforms. This is by no means a definitive comparison of the two platforms.

Every language has its purpose, and this may have not been the ideal application of Java due to the extremely limited memory on the platforms (~12k for the JVM, program, and the execution space), but trying to code java small was a very interesting (albeit sometimes frustrating) exercise. Plus, I always get a kick out of writing a program that "does something cool". And getting a robot to do stuff like following a flash light, avoiding obstacles it encounters, and determining where it is along a wall based on what it sees with its sonar definitely qualify as "cool".

Highlights

RoboJDE and leJOS both have strong aspects to their platform. Some highlights include: leJOS's built in RotationNavigator that performs both forward and inverse kinematics (basically knowing where it is on a 1' x 1' grid and the ability to go to a particular point on that grid); and RoboJDE's sensor interaction that better encapsulates the behavior of different sensors. Because both platforms are Java-based it is possible to create stand-alone programs in order to test the needed functionality off-line and without the use of the actual robot. Each of these aspects proved quite helpful in the respective labs.

Each platform has their issues... the main problem that sticks out for leJOS is its lack of Garbage Collection. The extremely limited memory is hard enough to deal with, and not having the ability to free the memory after its been allocated makes the situation more challenging for significant programs. RoboJDE has a very efficient built-in garbage collector. The main issue with RoboJDE is that its only available on the Windows platform, leJOS is available on both Windows and Linux.

Hardware comparison

The RCX—brain of the Robotics Invention System
The RCX controller. Source: O'ReillyNet.com The HandyBoard controller. Source: HandyBoard.com


I/O ports
The Lego Mindstorm RCX board has a limited number of input and output ports (three each). However the ability to overlap sensors allows the programmer to use more sensors than there are ports available. Overlapping sensors has the side effect that the readings from the sensors can be received but it is often impossible to differentiate between which overlapped sensor is sending the signal.

The HandyBoard had seven analog input ports, seven digital input ports and two digital input / output ports. The limited number of digital I/O ports became a problem during the 2nd half of the course because we needed to use two encoders (used with kinematics to determine where the robot is) and a sonar sensor. Each of these sensors required the use of an individual digital input/output port. The HandyBoard does not have the ability to overlap sensors, and so we were forced to use only one encoder along with the sonar sensor.
*Note: as a work around we could have written native code to allow one of the encoders to run on a pure input port, but this proved too difficult given the time constraints and my pathetic understanding of the Motorola M68HC11 assembly language.

LCD
The RCX board has a severely limited display. It allows only a total of 5 characters to be shown on the board whereas the HandyBoard can display a total of 32 characters (2 lines, 16 characters in length). The ability for the HandyBoard to display a more significant output significantly aids in the process of debugging.

Robot Interface
The Handyboard interfaces with the PC through the serial port, which connects to a standard phone line, which connects to the robot. So, if you'd like to get debug information sent back to the PC during the robot's run, it must remain "tethered" via the phone cord.

The RCX on the other hand uses a USB tower to send signals via IR (I believe the tower can also be connected to the PC via a serial port, but we didn't have the appropriate hardware in our kits). Whether it was due to the IR speed or the RCX loading software's speed, the RCX took a significantly longer amount of time to download programs to the robot than the HandyBoard software. The nice advantage about the built-in IR capabilities of the RCX robots is that it doesn't need to be tethered in order to send debug information back to the PC.

Software comparison

The Tools
RoboJDE is a commercial product that compiles code for the Handyboard. It has a more elegant user interface and cleaner out-of-the-box experience than the UI used with leJOS. RoboJDE runs only on windows, but the installation is much cleaner, requiring only the execution of a simple setup executable. The UI itself produces a significant amount of statistics about the user's program during compilation (program size, number of static variables, number of classes used, etc) and execution (free bytes available, free blocks available, % CPU used, % memory used). This information proved quite useful while coding and debugging the HandyBoard.

leJOS is an open-source product and thus has several available interfaces that can be used to compile and download programs. Bricxcc required several products to be installed as well as multiple environment variables to be set, and I was unable to configure it successfully. Instead, I used RCXDownload, which requires only that the JDK and the USB Tower driver be installed. It provides none of the helpful statistics provided by RoboJDE; it is simply a way to compile and download the leJOS programs.

The API
Both RoboJDE and leJOS are Java-based platforms, but they differ in the amount of the standard Java API they implement and how they interact with the Robot.

RoboJDE API:      http://www.ridgesoft.com/robojde/1.2/docs/apidoc/index.html
leJOS API:      http://lejos.sourceforge.net/apidocs/index.html
  • java.lang
    leJOS implements more of the java.lang package than implemented by RoboJDE. However the only significant piece of functionality I found missing from RoboJDE was java.lang.Math.random(), a simple random number generator. In order to simulate a random number generator in RoboJDE when we needed to randomly choose from three different actions (turn left, turn right, go straight) we performed a modulus operation on the current system time. This method worked for our purposes, but one should note that it is only effective if the call itself is made at random intervals.
  • java.util
    One significant piece of the standard Java API that is implemented by leJOS and is missing from RoboJDE is the java.util package. The Collection classes are the most useful parts of the java.util package for the purposes of programming a robot. These data types are quite useful when developing significant programs such as trying to find the optimal path through a set of obstacles based on the sonar input. Because RoboJDE does not implement any of these data types, simple arrays must be used to hold the necessary data.

Robot Interaction
One of the significant comparisons that need to be made between RoboJDE and leJOS is how easily the two interact with and control the robot.

RoboJDE provides specialized classes to handle a select set of sensors. These classes encapsulate all the functionality of the particular sensor. For example, the conversion of a sonar reading into a distance (see Figure 1) is handled by the RangeFinder class. If necessary, this class can also be extended to support different brands of Range Finders other than the DevantechSRF04.

Instead of providing specialized classes that handle different sensors, leJOS provides a generic Sensor class which, when initialized with different "Type and Modes", will behave differently. These types can range anywhere from TOUCH to TEMP or LIGHT.

I find that RoboJDE's method of interacting with sensors is more intuitive and easier to implement than the one used by leJOS.

Figure 1: Example of leJOS and RoboJDE code to interact with sonar
leJOS
//initialize the sonar      
   Sensor.S2.setTypeAndMode (3, 0x80);       
   Sensor.S2.activate();
//read the raw value of the sonar      
   float value = Sensor.S2.readValue();
//manually convert sonar reading to distance in centimeters      
   float distance = (float)(12f+.53*a*2.54);
 
RoboJDE
//initialize the sonar     
   RangeFinder sonar = new DevantechSRF04(...);     
   float distance = 0.0f;
//send out a ping and read the value within 100 milliseconds     
   sonar.ping();    
   long timeout = System.currentTimeMillis() + 100;   
   do {
//RoboJDE automatically converts sensor reading to distance   
      result = sonar.getDistanceCentimeters();  
   } while ((result < 0.0f) && (System.currentTimeMillis() < timeout));

Both RoboJDE and leJOS have a similar method of interacting with the Motors (see Figure 2). With both API's, you set the power levels of the motors their directions.

Two very useful features that leJOS possesses that are lacking in RoboJDE are the methods Motor.X.isMoving() and Motor.X.flt(). These methods tell the program if the motor is currently being moved, and tells the motor to stop applying power to the motor, respectively. The .flt() command is different than stop in that it removes power, rather than bringing the motor to an abrupt stop.

Figure 2: Example of controlling motors in RoboJDE vs leJOS
leJOS
//Performs a left turn by moving the left motor (A) slowly     
    Motor.A.setPower(1);
    Motor.A.forward();  
//moving the right motor (C) quickly     
    Motor.C.setPower(7);
    Motor.C.forward();
//pausing     
    Thread.sleep (1000);
//stopping both motors     
    Motor.A.stop();     
    Motor.C.stop();	
 
RoboJDE
//initializes the motors     
    Motor leftMotor = HandyBoard.getMotor(0);    
    Motor rightMotor = HandyBoard.getMotor(1);
//performs the turn by moving the left motor slowly 
    leftMotor.setPower( Motor.FORWARD );
//moving the right motor quickly    
    rightMotor.setPower( Motor.FORWARD/10 );
//pausing    
    Thread.sleep(1000);
//stopping both motors     
    leftMotor.setPower( Motor.STOP );  
    rightMotor.setPower( Motor.STOP );


Kinematics
LeJOS makes kinematics almost a trivial task. LeJOS provides a class called RotationNavigator that uses two encoders to calculate the distance the robot has traveled, and in what direction. The RotationNavigator performs the desired move by using commands such as RotationNavigator.gotoPoint() (inverse kinematics). It also can calculate where the robot is currently located by using commands such as RotationNavigator.getX() and .getY() (hence forward kinematics).

When using RoboJDE, all of the functionality provided by a class such as RotationNavigator needed to be designed and coded. Granted, having to code this myself gave me a renewed appreciation for high school geometry as well as a better understanding of how the kinematics calculations were actually performed.

Bump detection
Due to the limited number of input ports available on the RCX, the two bump sensors were stacked on a single input port and it was not possible to determine if the bump occurred on the left or right side of the robot. So, when avoiding a bump the robot always attempted to avoid the obstacle by turning to the right. This caused a problem sometimes because the robot would take several tries to completely avoid an obstacle, which would in turn cause the robot to hit the obstacle more, and possibly collect more error in the calculation of its position.

Figure 3: RoboJDE vs leJOS in detecting a bump.
leJOS
Sensor.S2.setTypeAndMode (SensorConstants.SENSOR_TYPE_TOUCH,
    SensorConstants.SENSOR_MODE_BOOL);
if( Sensor.S2.readBooleanValue() ) {   
    // avoids obstacle
}
 
RoboJDE
DigitalInput leftBumper = HandyBoard.getDigitalInput(15);
DigitalInput leftBumper = HandyBoard.getDigitalInput(13);
if( leftBumper.isSet() && rightBumper.isSet() ) {
    //center hit avoid obstacle
} 
else if( leftBumper.isSet() && !rightBumper.isSet() ) {   
    // left hit avoid obstacle
} 
else if( !leftBumper.isSet() && rightBumper.isSet() ) {   
    // right hit, avoid obstacle
}


Debugging
Debugging the robot's program for logical errors is a much easier task in the HandyBoard due in large part to the RoboJDE UI as well as the large LCD on the HandyBoard. Error messages, variable values and other helpful debugging statements can easily be sent to the host machine (and simultaneously displayed on the LCD) by simply calling System.out.println(). As mentioned before, the RoboJDE interface that tracks the amount of memory and CPU used as well as program size etc is incredibly helpful when debugging.

This type of helpful debugging is much more involved with the Mindstorm. There is no simple way to print to the host, and the limited size of the LCD prevents much useful information from being displayed. We found that "debugging" is often reduced to adding different sounds to be played at various points in the program and trying to interpret these sounds to mean that the program has successfully reached a particular area in the code. *In all fairness to the RCX and leJOS, because it has an IR connection to the PC, you can send message through the IR in order to debug problems -- but I didn't realize this at the time I was programming it.

Garbage Collection
One significant advantage that RoboJDE has over leJOS is its automatic Garbage Collection. When an object or variable is no longer used it is removed and the memory is freed in order to be used by other variables. In leJOS the programmer must be diligent and not produce more objects than necessary because there is no way to reclaim memory once it is used. The lack of a Garbage Collector is a huge detriment due to the extremely small amount of memory on the RCX.

RoboJDE is also very efficient when it compiles your program. Any methods or classes not used will not be compiled and built into byte code for the HandyBoard. This also aids in significantly reducing the size of your program.

Other Stuff
One significant advantage that leJOS has over RoboJDE is that it has a Persistent memory area that can be used to store calibration values from one program execution to the next. This functionality would have proven useful during the first half of the course when we were constantly calibrating and recalibrating the light and reflection sensors. If we could have calibrated the robot once and stored these values in a Persistent memory area, we could have saved time from one run to the next.

Simulating the Robot
Due to Java's object oriented nature, it was easy to encapsulate much of the functionality of the labs as individual classes that were not dependent on the Robot code itself. This quality became very useful when writing and testing some of the major pieces of the labs.

For example, in one of the final labs a map of the world needed to be built and stored on the HandyBoard based on the Sensor inputs. We were able to hard-code a simulated set of sonar readings into a main class. These values were then manipulated and stored so that they could later be used to find an optimal path to the goal. The ability to do all of this off-line with the use of real debugging utilities such as those built into IntelliJ IDEA significantly reduced the number of logical errors present in the program once it was actually used by the Handyboard.

What I think

In the end, I found that using and debugging RoboJDE was easier than leJOS. The UI provided by RoboJDE made it easier to identify memory problems as well as logical errors, and as I mentioned before, I found the API a bit more intuitive to use as well.

All that being said, for the average robot geek (and particularly for the recreational robot geek), money is almost always an issue. LeJOS is a free open source product, and the Mindstorm itself costs about $200. The HandyBoard costs about $300, and RoboJDE is about $100 (there is a free Lite version available as well). So, for the casual geek, RoboJDE may not be the most cost-efficient path, but I believe for the academic arena, its certainly a strong choice.

Links


Discuss this article in The Big Moose Saloon!


Return to Top

Whizlabs SCMAD Exam Simulator (CX-310-110) Review

by Valentin Crettaz

When some big corporation's educational services announces the release of a new certification exam, you can be certain that the Whizlabs team won't be that far away. After many successful simulator releases in 2003 and before (SCBCD, SCJP 1.4, etc), Whizlabs now wants to make you MAD (that is, a Mobile Application Developer ) by complementing their product suite with another exam simulator for Sun's new certification exam targeted at the Micro Edition of the Java 2 Platform (J2ME). Whizlabs' simulators essentially pursue the following goals:

  1. to provide a huge question bank in order to best train the exam taker, and
  2. to closely mimic real exam conditions.

Basically, the user interface hasn't change much compared to what I have experienced with other simulators from Whizlabs' product line. While some display bugs have been eliminated, a few ones are still on the edge eargerly waiting to be terminated. Furthermore, when looking back at Lasse Koskela's review of their SCJP 1.4 simulator last December, it appears that Whizlabs has done much of its homework:

  • I haven't experienced any problems during the installation process, and
  • the code is well indented (even though monospace font is still not used for displaying code snippets.)

Moreover, I have to admit that I have specially liked the way Drag-n-Drop questions have been implemented. They are even better than in the real exam since after you have answered a question you can reopen the Drag-n-Drop box without having to answer the question again. This is, in my opinion, one of the big limitations in Sun's certification exam software. Actually, as most of you, every time I take a Sun certification exam, I have to write down my answer to a Drag-n-Drop question before closing the dialog box, which is a little annoying.

Regarding the content itself, you will find a total of 490 questions evenly distributed across 5 mock exams (68 questions each) and 1 quiz (150 questions). You can even create your own mock exams with the built-in test customizer that allows you to select any questions in the bank to help you focus on a specific area of your choice. Besides, all questions come with very exhaustive explanations and links to sections of the relevant specifications. Once you finish an exam you are offered the opportunity to review some answers you were unsure about or to directly go to the exam report and see if you have passed or failed. On the reports you will find a good deal of very comprehensive information. For each question, you will be able to see the objective to which the question relates, the level of difficulty, the type of the question (i.e., multiple choice, DnD, fill-in, etc) and whether you answered it correctly or not. Wait, that's not all!! The help menu will direct you to a complete user guide and some help content on how to use the tool itself. As always, Whizlabs has also bundled a Tips'N'Trick cheat sheet and quick revision notes for you to read just before taking the exam. On the downside, it's just unfortunate that you can't print out these helpful notes from the tool and take them with you to the test center to do some last minute brush up... Maybe, they'll consider adding that to future versions of their tools. Who knows...

A cool new feature has been added to the simulator: If you ever have a doubt about a question or an explanation or if you want to report some problem you experienced, you can do it by clicking on the "Discuss it" button and you will be forwarded to a dedicated SCMAD forum on Whizlabs website. Once you have logged in, you will just have to write your message. Of course, a live Internet connection is required in order to take advantage of this feature.

SCMAD User Interface Practice Test Test Customizer
Exam Report Help Content Answers and Explanations
Discuss It!!

Finally, I think that this new exam simulator is well worth the money spent ($79.95 for new customers and $63.95 for existing ones) for the reasons enumerated below:

  • The simulator is very efficient and is of great support for exam takers
  • You get free upgrades for 6 months
  • You get free technical support from the authors
  • There are very few SCMAD mock exams out there yet (check out this link)
  • And... (drum rolls) You'll get your money back if you don't pass the exam anyway

Don't hesitate to download the free trial edition to get a feeling of the exam simulator before buying it. I definitely recommend this outstanding resource to any respectful J2ME developer willing to tackle the SCMAD exam.

Resources
Whizlabs homepage
Whizlabs SCMAD exam simulator
SCMAD Certification Primer


Discuss this article in The Big Moose Saloon!


Return to Top

The Coffee House

coffee house

An Agile Excursion

by Solveig Haugland

Looking back, nobody could agree what really made the project go bad. But everyone agreed that Sid had gone nuts.

The JavaRanchers, in their hurry to get their code ready for the fall release date, had gotten a little over-organized. It all seemed so innocent at first. They made lists. Then spreadsheets. Then project plans, and then multiple levels of organizational hierarchy, and four-dimensional schedules. Then of course when the staff senior project manager told the senior staff project manager and the lead senior project manager that it looked like the September 1st release wasn't going to happen, the senior lead project manager went out and hired 42 more contract JavaRanchers to help move the project along. Which is when the project, oddly enough, actually ground to a halt.

Sid and Zeke, who were lead senior staff developers on a couple of the project modules, slunk into the Coffee House around 2 to avoid their daily 3-hour status meeting.

"Give me a latte with a triple shot of strychnine, Brenda," Zeke groaned as he bellied up to the bar. "I don't want to be in a world that has this project in it."

"And a d-d-d-dodeca-espresso for me, Lacey," stammered Sid, jumping up and down at approximately 120 reps per minute. "I got to keep alert! The Incan Monkey God is going to come to me at midnight to tell me how to get this project back on track! Yes, he is! Hey, isn't that Tony Randall? Pretty pretty flowers!"

Lacey grinned. Brenda looked as if she wanted to look sympathetic but also wanted to bust out laughing. "Ummm...so you guys are still on the stagnant death march project from hell., eh?" Brenda asked as she poured out the latte, sans strychnine. "Any new info today, Zeke; any progress?"

"Well, we got the users to tell us that the requirements they gave us last month bear absolutely no resemblance to the software they want, but that's OK since none of the developers actually knew those requirements existed. Apparently two thirds of them have been working on a really cool offshoot of wiki and the other third have been playing Quake. So now we have to re-gather the requirements, and analyze them, and that usually takes about a year in itself but we have a day and a half."

"Oh is that all!" Brenda started laughing but Zeke was too far gone to hear her.

"Well, no. Sid here has gone into infinite loop caffeine intake and whenever you ask him for a project update, he just keeps talkin' about how the Pope and him have joined the Swiss luge team and they need to go luge shopping."

Lacey, who was as amused as Brenda but didn't relish human suffering quite as much, said. "You know, Zeke, I think there's something that just might help y'all, over the hill in that big ol' Salt Lake City. Did you know the Agile Development conference is takin' place right there?"

"Agile! I've got an agile badger in my pants! Whoopeee!" That of course was Sid, who by now had stripped naked (thus belying the pants remark) and was doing some pretty remarkable cartwheels up the side of the Coffee House.

"Agile Development....isn't that a bunch of religious folks who worship a guy named Kent Beck and have this heretical notion that ya don't need the traditional 1500-page specification? I tell you, I think them folks is a big tetched."

"Well, OK, that's not entirely wrong, but you know what else they do? They tend to release software."

You could tell that Zeke was struggling. He was a Traditionalist and hated the idea of taking on some pansy ass new fangled touchy feely methodology. On the other hand, his bonus should he bring this project in on time was a brand new John Deere combine with a titanium Mac 17-incher mounted on the cupholder. He struggled. He shifted in his chair. He swatted Sid as Sid came twirling down the near wall, and yelled for somebody to put some clothes on that man. He looked close to a decision.

"Can a man get a decent whiskey in that town? In Salt Lake City?"

Lacey nodded. "Yes, but not on election day or in a month ending in an R."

Zeke said "I'll do it!" and that weird guy in the back of the coffee house played the theme from The Magnificent Seven as Zeke threw Sid over his shoulder and strode out the coffee house's swinging doors.

Zeke rode hard all the way to Salt Lake, with Sid strapped to the horse's rump, inhaling some pretty nasty fumes which it turned out are a great antidote to overcaffeination. They arrived just in time for the conference ice breaker, where they strode around the room, eyeing the pretty ice-breaking belly dancers.

"Who is that guy in the weird hat with the wild look in his eyes?" asked Sid, newly adjusted to the real world and just a little afraid of it.

"I imagine he's just the entertainment," Zeke assured him.

They looked around at the small but talkative developers around them. One table was listening intently to a guy with a radio announcer's voice discussing gap-toothed women. A tall man in frightening cowboy boots was describing the pot-smoking rules in Amsterdam. Several men with really cute accents who looked to be thoughtful workers were discussing soccer in a depressed sort of way. "We're supposed to learn how to release software from these folks ??? " Sid was skeptical. Zeke had a nasty feeling in the pit of his stomach, but four drink tickets and their corresponding contents helped ease the discomfort. They went to sleep that night in an uneasy state of mind.

The next four days, however, changed their minds, lives, and attitude toward supposedly silly touchy feely development methodologies. Zeke learned much to his chagrin that just because you write something down, well, that don't make it true. Sid learned that extreme programming does not in fact mean just staying up til it's done. They both learned that there are two kinds of customers, liars and damned liars, and you have to watch them to find out what their requirements are, not actually believe them when they say they need shoulder-mounted faxes and milkshake machines for their field people. They learned not to giggle and elbow each other when somebody said SCRUM master, and to not confuse process with actually knowing what they were doing.

And they bought a bunch of technical books, as all people of honor do, and stuffed them in their leather saddle bags along with some incredibly tasty brownies from the afternoon snacks. They stuffed themselves at the end-of-conference banquet, laughed uproariously at the truly amazingly exceptionally hilarious top ten lists, donned their novelty sunglasses, stuffed the novelty plastic clappers in their pants, and danced up a storm, especially to "YMCA".

The next day, flushed with new ideas, new books, and while they wouldn't even admit it under torture, empowerment, Sid and Zeke made the return trip to the JavaRanch, humming snatches of their Agile Development Song. They met with the senior staff senior project manager, discussed the user requirements, did some non-paralyzing analysis, threw a pile of dead fish out the window of the meeting room, and in the end figured out that an application meeting the customers' needs already existed and could be purchased at WalMart for $49.99. Sid and Zeke exchanged high fives and went home, at last, for a well-deserved whiskey.


This month's Coffee House Adventures were inspired by a trip to the 2nd Annual Agile Development Conference in Salt Lake City, www.agiledevelopmentconference.com. The conference was not only chock full of great information and run by a conference team that knows the importance of chocolate, but was just plain lots of fun. And as if that weren't enough, these agile development guys can dance up a storm.
Solveig Haugland is an independent trainer and author near Boulder, Colorado. Her businesses include GetOpenOffice.org for those switching from Microsoft Office to OpenOffice.org  (www.getopenoffice.org); Techwriter Stuff: The Single Source, tshirts and posters for tech writers and those who love them; and of course Dating Design Patterns, the original reusable solutions to recurring problems.

Discuss this article in The Big Moose Saloon!


Return to Top
Meet the Authors - Kathy Sierra and Bert Bates
Meet the Author
Solveig Haugland
by Dirk Schreckmann

Not yet posted. Check back soon.

Discuss this article in The Big Moose Saloon!


Return to Top
The Big Moose Saloon Question and Answer of the Month

Mosey on in and pull up a stool. The JavaRanch Big Moose Saloon is the place to get your Java questions answered. Our bartenders keep the peace, and folks are pretty friendly anyways, so don't be shy!

Question: Use OOP to design database tables schema?

Over in the OO, Patterns, UML and Refactoring forum, Edward Chen opened a bottle of worms with this thread starter:

This question has haunted a while.

Usually, we firstly check the porject requirements and set up tables, and then do 1/2/3-NF normaliztion.

I don't like this way, because it is not Object-oriented way. So any body could share exprience how we use OOP to design complicate table schema/relationship?

Now, mosey on o'er, see what folks are saying and chime in with some thoughts of your own.



Join this discussion in The Big Moose Saloon!


Return to Top
Book Review of the Month

Software by Numbers
Mark Denne, Jane Cleland-Huang
Finally, a book that applies a solid financial methodology to iterative software development. The basis of this book is the Incremental Funding Methodology. IFM is not a new software development methodology. It is a funding methodology that can be applied to your chosen development methodology to maximize ROI through the release of minimum marketable features.

This book starts with the assumption that you are using a methodology such as RUP or XP and builds a case for incremental funding. It moves on to teach you the tools to maximize the ROI on your project. Methods for moving up the self-funding date are also in this book. The book ends with 3 application chapters. The first is on how to apply IFM to RUP. The 2nd is on applying IFM to an agile software methodology. The final chapter is a case study on using IFM. The glossary is excellent and there is a quick reference guide to IFM as well.

Before reading this book, I was never completely convince that an agile methodology was the way to go. This is the book I was looking for to complement agile development.

(Matthew Phillips - Bartender, January 2004)

"Software by Numbers" is yet another book I would like any manager involved in my working life to read and re-read.

The authors describe an Incremental Funding Method (IFM) for scheduling incremental development of software which optimizes the Return on Investment (ROI) by having the requirements engineered into Minimum Marketable Features (MMF) with concrete, monetary value.

The book is very light (less than 200 pages) but packed with interesting material. I read most of the book during a flight from Finland to Germany and finished the book on my way home. Despite the minimal page count, the authors manage to explain why their method is desperately needed and how it fits to existing software processes such as RUP and XP. They also describe the business case for incremental architecture and different strategies for sequencing MMFs and Architectural Elements (AE) for maximum ROI over the project's lifetime.

The only reason for not giving a full 10 for this book is that I would've needed some more baby-steps support for the actual calculations (sequence-adjusted net present values etc.). I'm sure others will be hoping to see some more real world examples of feature deconstruction and sequencing as well. On the other hand, I really appreciate the fact that the authors made the effort of putting up a spreadsheet online for supporting their method.

Overall, an excellent book. Highly recommended.

(Lasse Koskela - Bartender, June 2004)
More info at Amazon.com || More info at Amazon.co.uk


Other books reviewed in June :

Professional Portal Development with Open Source Tools by W. Clay Richardson , Donald Avondolio, Joe Vitale, Peter Len, Kevin T. Smith
Eclipse 3 Live by Bill Dudney


Discuss this book review in The Big Moose Saloon!


Return to Top

Following are the scheduled book promotions coming in July and August. Be sure to check our book promotions page often for changes and new promotions.

July 13 XSLT 2.0 Web Development Dmitry Kirsanov Prentice Hall PTR XML and Related Technologies
July 20 J2EE 1.4: The Big Picture Solveig Haugland, Mark Cade, Anthony Orapallo Prentice Hall PTR EJB and Other J2EE Technologies
July 27 Pro Jakarta Struts, Second Edition John Carnell Apress Web Application Frameworks
August 3 Whizlabs SCMAD Certification Exam Simulator Sathyanarayanan Srinivasan and Sivasundaram Umapathy Whizlabs Mobile Application Certification (SCMAD)
August 10 JavaServer Faces in Action Kito D. Mann Manning Web Application Frameworks
August 10 JUnit Recipes: Practical Methods for Programmer Testing J. B. Rainsberger Manning Testing
August 17 Whizlabs SCDJWS Certification Exam Simulator   Whizlabs Web Services Certification (SCDJWS)
August 24 Java 2 v1.5 (Tiger) New Features Herbert Schildt McGraw-Hill Osborne Media Java in General (intermediate)
August 31 Hibernate in Action Christian Bauer, Gavin King Manning Object Relational Mapping
August 31 Explorer's Guide to the Semantic Web Thomas B. Passin Manning General Computing



Return to Top
Managing Editor: Dirk Schreckmann

Comments or suggestions for JavaRanch's Journal can be sent to the Journal Staff.

For advertising opportunities contact the Journal Advertising Staff.