The Source for Java Technology Collaboration
User: Password:



Evan Summers's Blog

September 2006 Archives


A Case Against Uppercase

Posted by evanx on September 28, 2006 at 07:13 AM | Permalink | Comments (19)

Consider the following code.

public class Car {
   private static final int SPEED_LIMIT = 120; 
   private int speed;
   ...
   public boolean isLegal() {
       if (speed > SPEED_LIMIT) return false;
       return true; 
   }
}

OK, in C our constants were #define macros, and we put them in uppercase. Because macros are quite distinctive animals, compared to domesticated code.

In Java by convention we put them in uppercase as well. They are distinguished from other class attributes by being static and final. Since other attributes might also be static, and others might also be final, semantically this distinction is weak.

Let's say we decide to make the above class more customisable where the SPEED_LIMIT is configuable, eg. for different countries. So we make it not final.

public class Car {
   private static int SPEED_LIMIT = 120; 
   private int speed;
   ...
   public static void setSpeedLimit(int newSpeedLimit) {
      SPEED_LIMIT = newSpeedLimit;
   }
}

Of course as soon as we take away the final modifier, we should rename it speedLimit.

The argument i'm trying to illustrate is that we should drop this legacy hangover of uppercase and underscores for "constants." Because they aren't macros anymore. They are class attributes with a final modifier, and in my book that's not enough for any special treatment, such as breaking the clean Java camel-cap naming convention.

To summarise, LOUD UPPERCASE WORDS AND _UNDERSCORES_ SHOULD BE BANISHED, as relics of a bygone era, don't you think!?

Five Steps to Freedom, Almighty Administrator

Posted by evanx on September 08, 2006 at 06:16 AM | Permalink | Comments (1)

med2_250.jpg

That would be freedom from support hassles, which is the most important freedom in IT, innit. It's all about taking control away from your users and installing yourself as the Almighty Administrator. "If anyone is gonna break this system, it goddamn better be me!"

Step 1: Firefox. This is an easy sell, cos of the tabs and niceties. And as we IT guys know, anyone who hasn't switched to Firefox has got rocks in their head, and malware in their hard drive.

Step 2: Thunderbird. Once your users are loving Firefox, explain that Firefox has a brother called Thunderbird, and like Firefox, it's got more shiny marbles than other warez. Remember, we're fighting a war here, and subversion is an effective weapon.

Hey, a mailer is a mailer. So if you don't use Outlook Shared Calendaring, then migrating to Thunderbird is fairly painless. Except you might lose all the remembered email addresses that you use but don't bother adding to your address book. So get your users to spend some time getting their address books in order, ready for importing to Thunderbird.

Step 3: OpenOffice. Mmmm, PDF export. Mmmm, big cost savings. If your dumb users are failing to see the benefits of OpenOffice, tell them a rumour that the BSA is coming next week to check if they are using any pirated software. Works everytime.

Step 4: Linux Desktop. Once your users are using Firefox, Thunderbird and OpenOffice, and are just starting to get comfortable and happy, that is the time to pull the rug from under their cosy feet again.

HP_thin_client_100.jpg Subversion might be required. For example, "I have some terrible news for you. Your computer has been infected with the worse type of virus that there is, and it's only gonna get worse. (User responds with alarm and concern for their documents.) We will have to reinstall with Linux to protect your documents and emails from hackers. (User talks, while we ignore their pointless utterances.) You have 24 hours to backup your documents, do you understand?"

Step 5. Linux Thin Clients. The problem with desktop computers is (a) they are literally in the hands of users. We cannot allow this. Users need dumb clients, giving them access to a server under our control. And (b) they have moving parts, which are liable to stop moving at some point, which then becomes our problem. No, we can't have that. So we order some thin clients for the users, and some big iron with quad cores and quad gigs for ourselves. Mission Accomplished.

Generic PropertyDescriptor puzzler

Posted by evanx on September 08, 2006 at 01:34 AM | Permalink | Comments (0)

Consider the implementation of a validator, to do a range check.

Since I have a sneaky suspicion we gonna need to communicate with the user when the validation fails, lets prepare those messages in a resource-injectible bundle of bytes as follows. The problem with IT is all these darn users! They keep getting in the way of real progress, wanting silly features, finding silly bugs...

class ValidatorResource {

    @ResourceAnnotation()
    String property = "The property '%s'";

    @ResourceAnnotation()
    String isNull = "is null";        
    
    @ResourceAnnotation()
    String lessThanMinimum = "is less than %s" ;
    
    @ResourceAnnotation()
    String equalsMinimum = "is equal to, not greater than %s";
    
    @ResourceAnnotation()
    String greaterThanMaximum = "is greater than %s";
    
    @ResourceAnnotation()
    String equalsMaximum = "is equal to, not less than %s";

    public ValidatorResource() {
        configurator.configure(this);
    }
}

Now because we got so many types of numbers and dates and what-not, let's implement a generic range validator as follows, where our value type is Comparable.

abstract class ComparableRangeValidator<Value extends Comparable> {
    public static final ValidatorResource resource = new ValidatorResource();
    
    Value minimum;
    Value maximum;
    boolean nullable;
    boolean exclusive;
    
    public ComparableRangeValidator() {
    }
    
    private String format(NBeanProperty property, String format, Object ... args) {
        return formatter.format(resource.property, property.getPropertyLabel()) +
                formatter.format(format, args);
    }
    
    public String validate(NBeanProperty property, Value value) {
        if (value == null) {
            if (!nullable) {
                return format(property, resource.isNull);
            }
            return null;
        }
        if (value.compareTo(minimum) < 0) {
            return format(property, resource.lessThanMinimum, minimum);
        }
        if (value.compareTo(minimum) == 0 && exclusive) {
            return format(property, resource.equalsMinimum, minimum);
        }
        if (value.compareTo(maximum) > 0) {
            return format(property, resource.greaterThanMaximum, maximum);
        }
        if (value.compareTo(maximum) == 0 && exclusive) {
            return format(property, resource.equalsMaximum, maximum);
        }
        return null;
    }
    
    public void setExclusive(boolean exclusive) {
        this.exclusive = exclusive;
    }
    
    public boolean isExclusive() {
        return exclusive;
    }
    
    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }
    
    public boolean isNullable() {
        return nullable;
    }
    
    public void setMinimum(Value minimum) {
        this.minimum = minimum;
    }
    
    public Value getMinimum() {
        return minimum;
    }
    
    public void setMaximum(Value maximum) {
        this.maximum = maximum;
    }
    
    public Value getMaximum() {
        return maximum;
    }    
}

Now we can very easily create validators for specific types, which are effectively type aliases, as follows.

class IntegerRangeValidator extends ComparableRangeValidator<Integer> {    
}

Supoib!

Now let's check the PropertyDescriptor's of our minty IntegerRangeValidator.

public class IntegerRangeValidatorInsanityCheck {
    public static void main(String[] args) throws Exception {
        BeanInfo beanInfo = Introspector.getBeanInfo(IntegerRangeValidator.class);
        for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
            logger.info(property.getName(), property.getPropertyType());
        }
    }
}
INFO:logger:IntegerRangeValidator:main:123: (String) class :: (Class) Class
INFO:logger:IntegerRangeValidator:main:123: (String) exclusive :: (Class) boolean
INFO:logger:IntegerRangeValidator:main:123: (String) maximum :: (Class) Comparable
INFO:logger:IntegerRangeValidator:main:123: (String) minimum :: (Class) Comparable
INFO:logger:IntegerRangeValidator:main:123: (String) nullable :: (Class) boolean

Darn, the type of minimum and maximum is Comparable, as in the generic ComparableRangeValidator superclass. Houston, why can't it just be Integer like i want?! Cos i wanna coerce (integer) values in there from string resources, so i'm stumped!

Plumber's Hack 2: Blog o' warez

Posted by evanx on September 06, 2006 at 02:42 AM | Permalink | Comments (6)

(*)

So i wrote this warez to parse my articles in "poor text format" and generate my desired output, eg. HTML for my weblog, with syntax highlighting. Another feature is switching between online image URLs, and local offline image files.

There's a GUI interface, for previewing the HTML. This could be used as a tool for syntax highlighting and escaping Java and XML snippets, to cut and paste into your blog entries.

Read the full article on java.net CVS.

Ssh ssh, Show me the warez

Here is the Web Starter...

(*) (Quitewriter, Java5, 450k, unsandboxed)

Which looks like this...

(*)

The code for the above demo in the quitewriter package on vellum.dev.java.net, but moving to quitewriter.dev.java.net. The main class to run the GUI is quitewriter.gui.QuitewriterGui.

Other Reading Material

Last week, in Swing and Roundabouts 1M: Emission DTs, we implemented a publish/subscribe message bus, for dialogs and such.



Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds