Yes Virginia, more WTFs are real



  • You've heard of the global date table WTF. It's not as ludicrous as you might think. My company uses a concept not entirely dissimilar: a global record status table, where records in various tables can have a status column that refer to it. The columns are commonly named STATUS_ID. It is not quite as bad because a status id does not need to refer to an entry in the status table and they're really constants. Status table records cannot be edited by any UI screen but that's OK because the records aren't used anyway, even for presentation layer text.

    For the education of junior programmers, an example of the pain this causes is when maintaining legacy code. Here are the first 10 status values (out of 1522) listed in a constants file. Guess which statuses apply for documents processed for a bespoke, mobile app. And no peeking at documentation because there isn't any.

    public static final Integer ACTIVE = new Integer(1);<BR/>
    public static final Integer HIDDEN = new Integer(2);<BR/>
    public static final Integer DELETED = new Integer(3);<BR/>
    public static final Integer INACTIVE = new Integer(4);<BR/>
    public static final Integer OK = new Integer(5);<BR/>
    public static final Integer ERROR = new Integer(6);<BR/>
    public static final Integer PENDING = new Integer(7);<BR/>
    public static final Integer DOWNLOADED = new Integer(8);<BR/>
    public static final Integer DLOADING = new Integer(9);<BR/>
    public static final Integer NEW = new Integer(10);<BR/>
    

    Yes, you correctly guessed it. It is, in fact...

    public static final Integer PP_DRAFT = new Integer(100);
    public static final Integer PP_DELETED = new Integer(101);
    public static final Integer PP_PENDING = new Integer(102);
    public static final Integer PP_REJECTED = new Integer(103);
    public static final Integer PP_PUBLISHED = new Integer(104);
    public static final Integer PP_BEING_PUBLISHED = new Integer(105);

    Experienced Java programmers will find it odd that these constants are Integer objects, not int primitive types, and suspect bugs when comparing Integer objects with the == operator as that is reference comparison. As all STATUS_ID columns do not allow null, they'd conclude it's not a problem because primitive/object comparisons compare values, not references. They'd be incorrect because STATUS_ID of any record is loaded into Integer objects, not int primitive types, even though a null status of any record is not allowed.

    Just to add frustration to bugs, these constants cannot be used in case statements because they're not actually constants.

    To finish off with the absurd, all these 'constants' are defined in a dedicated Status class, which is Serializable. Because instances of Status that are never created, and would contain no data if they were, must be transportable.

    Weep for me.



  • Java is the new VB!



  • @warmachine said:

    ...

    Experienced Java programmers will find it odd that these constants are Integer objects, not int primitive types, and suspect bugs when comparing Integer objects with the == operator as that is reference comparison.

    ...

     

    But at least they created these Integer types with constructors rather than autoboxing, so at least they all will react the same.

     People might find the output of this little code snippet interesting:

     for(int i = 125; i < 130; ++i) {
           Integer a = i;
           Integer b = i;
           Integer c = new Integer(i);
           Integer d = new Integer(i);
           System.out.println("" + a +": a==b,"+ (a == b));
           System.out.println("" + a +": c==d,"+ (c == d));
    }

     

     



  • @Rick said:

    People might find the output of this little code snippet interesting:

    ... please post the output for non-Java-devs?



  • @Rick said:

    @warmachine said:

    ...

    Experienced Java programmers will find it odd that these constants are Integer objects, not int primitive types, and suspect bugs when comparing Integer objects with the == operator as that is reference comparison.

    ...

     

    But at least they created these Integer types with constructors rather than autoboxing, so at least they all will react the same.

     People might find the output of this little code snippet interesting:

     for(int i = 125; i < 130; ++i) {
           Integer a = i;
           Integer b = i;
           Integer c = new Integer(i);
           Integer d = new Integer(i);
           System.out.println("" + a +": a==b,"+ (a == b));
           System.out.println("" + a +": c==d,"+ (c == d));
    }

    Why does Java punish the people who work with it?



  •  @derula said:

    @Rick said:
    People might find the output of this little code snippet interesting:

    ... please post the output for non-Java-devs?

    125: a==b,true
    125: c==d,false
    126: a==b,true
    126: c==d,false
    127: a==b,true
    127: c==d,false
    128: a==b,false
    128: c==d,false
    129: a==b,false
    129: c==d,false



  • @Rick said:

     @derula said:

    @Rick said:
    People might find the output of this little code snippet interesting:

    ... please post the output for non-Java-devs?

    125: a==b,true
    125: c==d,false
    126: a==b,true
    126: c==d,false
    127: a==b,true
    127: c==d,false
    128: a==b,false
    128: c==d,false
    129: a==b,false
    129: c==d,false

    Does that mean it autoboxes a and b there and has "cached boxes" while i < 128, so a and b will be the same integer object which it retrieved from this cache?



  • @derula said:

    Does that mean it autoboxes a and b there and has "cached boxes" while i

    Yes, Java autoboxes and has a store of cached Integer objects wrapping int values of small absolute value (-128 <= i <= 127 by default, iirc, and I think you can change the size if you need more).

    Thus when you assign an int i to an Integer, it checks whether i is in the cached range, if so assigns from the store, else creates a new object. If you use a lot of Integers of small modulus, that can give a good boost.

     


Log in to reply