Friday, August 20, 2010

UI Code Don'ts..!!!

It's important to keep code quality in check constantly in UI classes probably more than others as it typically seems to get out of hand more quickly.  Here are some observations, they hopefully do not fall into the micro-optimisation category but I definitely feel they are bad to have around.

  • Images or other memory hungry objects/resources marked with static.  These objects will never be garbage collected even if they are never used.  A shared object should store these images short term or SoftReferences should be used to store the images for a greater time without the danger of memory leaks.
  • Style information spread out across the whole program.  Especially Font objects, this seems to be the first thing to change and if it is spread out across the whole project then its going to be a mess.
  • Creating new Color objects in setters.  This causes a couple of problems, you're creating new Color objects all over the place which is only a minor problem but still pointless.  The other problem is understandability, it's hard to see what that colour is from the RGB constructor.
  • Magic numbers.  Not much need to explain why this is bad, please name them.  If there are too many then create a separate class to house them, you can even use a static import to keep code readable.
  • Too many anonymous classes.  Anonymous classes are useful buf too many look ugly (I don't like the syntax noise) and can cause memory leaks as the reference isn't explicit.
  • SwingTimer.  Please no!  Even if you know the memory leak pitfall, it's still too easy to fall into it.  Just avoid.

This is just a short list off the top of my head, I'll update it if I think of anymore.

Thursday, August 12, 2010

Builder Pattern

I've gotten round to improving some of the more complicated domain objects today by making them a) immutable b) use builders and c) use default serialisation techniques which has been an overall success.

Making the objects has become quite necessary since objects are serialised throughout our distributed system and the instance you're holding might be stale and any of the fields changed on this may overwrite the latest data, so really you want to request a change and some time later receive the updated object and typically display it until all that happens again.

The best way of doing this that I've found is the builder pattern from the Effective Java (2nd edition) book, while also trumping some of the other builder patterns I've seen. Basically the domain object has an inner Builder class with mutable data, and a build method which returns the domain object with it's data passed to the objects constructor. I'm not going to give a code sample since no one is reading and you should check out the book, go to Waterstones :P

Other problems have been finding the true identity of an object for equals and hashCode, is it really a combination of all of the fields or is it a select few containing the true ID of the object? Its far better to keep this data in it's own class or else the clutter will consume the intent of your code.

Serialisation was hit and miss, the end result was turning a class that serialised into 35 bytes into one that took 208. More investigation is needed because there is far more to it than I originally thought. I'm not really impressed by all of the magic methods like readObject, readResolve etc. Shouldn't this have been wrapped up in an interface, if only to provide some code completion?

Friday, August 6, 2010

Starting Listeners in the Correct State

A problem that I'm having with event listeners at the moment is making the listening object begin at a point in time in the correct state when it is really designed to build its state from the the events that are received while assuming a state to begin with.

For example, say you add a listener to an observable containing the state for a light switch, the listener should really know the state straight away but the event could be fired in 8 hours, or never. There are two ways I can see to fix this.

When adding the listener the listener gets the current state from the observable and updates itself.  This is fine but it does mean that the listener needs to know about the observable which adds a dependency so that the listening object is less reusable.  The Java property change framework is weakly typed, treating sources and values as objects anyway so you shouldn't really be expected to add this dependency.  Plus it makes the listener more difficult to test.

The observable holds a copy of the last event object it fired and when a listener is added fires all events to that listener.  This can give us even more problems.  Imagine firing an event with a complex or resource hungry value.  The complex object could have references to many other objects that would get garbage collected except that this stored event keeps them in memory.  An image is probably the best example of an object that you wouldn't like to keep in memory longer than necessary.  This really means that only primitive values, enums and other small immutables should be the values in change events.

These problems are really compounded for state machines where to get begin at the correct state the machine has to analyse system state in much the same way a conventional solution would need to.

Friday, July 30, 2010

Sunday, 11 January 2009 Setting a custom cursor which doesn't get resized

When setting a custom cursor in Swing you shouldn't really rely on the createCustomCursor method to use your images in any respectful way. The behaviour of this method is to resize the image into the dimensions returned by the getBestCursorSize method, which on Windows XP always seems to return 32x32 pixels.

To me this seems pretty crap because the image is going to get resized at some point depending on the platform your app is being run on which will most likely make the cursor image look terrible, perhaps to the user, unusable. IMO the behaviour should be to create a new image of the dimensions of getBestCursorSize and draw the supplied image at point 0,0. This does cause a problem if your image is larger than the dimension but your would be screwed the default way anyway.

Implementation is below...
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

public class SizedCursor
{
  public static Image getPreferredSizedCursor(
      Image image)
  {
    Dimension bestDimension = Toolkit
        .getDefaultToolkit()
        .getBestCursorSize(
          image
              .getWidth(null),
          image
              .getHeight(null));
    
    if (bestDimensionsEqualsImageSize(
      image,
      bestDimension))
    {
      return image;
    }
    else
    {
      BufferedImage resizedImage = new BufferedImage(
          bestDimension.width,
          bestDimension.height,
          BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = (Graphics2D) resizedImage
          .getGraphics();
      
      g.drawImage(
        image, 0,
        0, null);
      
      return resizedImage;
    }
  }
  
  private static boolean bestDimensionsEqualsImageSize(
      Image image,
      Dimension bestDimension)
  {
    return bestDimension
        .getWidth() == image
        .getWidth(null)
        && bestDimension
            .getHeight() == image
            .getHeight(null);
  }
}

Wednesday, July 14, 2010

Java Memory Debug Command Line Settings

Analysing memory usage and checking for memory leaks is an integral part of any Java application developmkent. This is especially true for swing apps, where swing design lends itself to creating leaks (lots of listeners with different lifespans, some of them static, SWING TIMER!).

Here's my typical command line arguments when I'm running in debug mode, enjoy.

set MEMORY_DEBUG_ARGS=-agentlib:hprof=file=myheapdump.hprof,format=b -verbose:gc -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpOnCtrlBreak

set LOW_MEMORY_HEAP=-ms128m -mx128m

Friday, July 9, 2010

Referencing Enclosing Instance of an Inner Class

When using an inner class how do you reference the enclosing class? The answer is Object.this where Object is the class type of the enclosing class. Sweet :)

Tuesday, July 6, 2010

Guice in a Java Swing App

Recently I have been working on a project that as normal uses Swing but decided to use Guice to avoid some of the problems that I’ve encountered in previous projects.

The problem is that if you have components that rely on service type interfaces that are nested several layers deep (not that unlikely in a complex UI) then to pass the service to the component all the other components above it need to have methods/constructors that pass the service down the hierarchy. This culminates in a simple change to a component that needs a reference to a new service requiring changes to 4/5 classes that also now have references to something they didn’t need to know about. This means extra coupling and more pain when you’re trying to refactor.

So now there are panels which have references to components that are themselves injected, which have injected services and everything works. It just works. In fact I barely think about it anymore, components with dependencies are just injected and there are no problems, no extra dependencies and no extra work. If the injected components also need service dependant components then they are injected as well and have no impact up the hierarchy.

Many classes in the project now have no code depending on the way they are created, which is a real joy. I haven’t heard this benefit touted by IoC propaganda but it really should be. If you ever wondered if adding dependency injection was overkill for you project, note down what you would inject. If there is more than two (my own measurement) injectable classes then the gains will be more than the cost of complexity in setting up the IoC infrastructure with modules and injectors etc.

Thursday, July 1, 2010

Use of UML !?

I was reading this article about the supposed best use of UML diagrams during the course of a project, in particular, generating code from UML is useless.  I have to agree that it seems pointless, once the generated code is modified the UML diagram is no longer useful and can no longer be used to generate the source.  Maybe this has just be used in the wrong way.  UML could be used in the same way as a unit test.  Perhaps initially it could generate code but also assert that code sticks to the design, if not then this test would fail and the architects would be notified.  This would help keep the architects up to date on what the codebase looked like without constant peer reviews, keep the documentation up to date and give warning when the design needed to change.  I have a feeling this is already done by someone.