cloudstack-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Hugo Trippaers <h...@trippaers.nl>
Subject Anti-patterns
Date Tue, 25 Feb 2014 13:41:14 GMT
Anti-pattern:
An anti-pattern (or antipattern) is a common response to a recurring problem that is usually
ineffective and risks being highly counterproductive. The term, coined in 1995 by Andrew Koenig,
was inspired by a book, Design Patterns, in which the authors highlighted a number of design
patterns in software development that they considered to be highly reliable and effective.
— source http://en.wikipedia.org/wiki/Anti-pattern


Here at Schuberg we spend quite some time going through bugs reports from automated scanners,
you have probably seen the mails coming by on the ML. As part of our work we have encountered
a number of problems that keep on popping up in the code base. So here is my first attempt
to clarify why a certain pattern is wrong and hopefully help developers to avoid this.

So first up is the equality operator, ==.  This operator is commonly used in many languages
to compare if two items are equal. The trick with this operator in java is to know exactly
what you are comparing, because it matters.

Consider this piece of code:

public class App
{
    public static void main(String[] args)
    {
        int a = 1;
        int b = 1;

        if (a == b) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}

The expected outcome is “Equal!” and indeed it prints just that. Now consider the following
code:

public class App
{
    public static void main(String[] args)
    {
        Integer a = new Integer(1);
        Integer b = new Integer(1);

        if (a == b) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}

The result of running this bit of code is “Different!”. With == you are telling the java
compiler to compare the two variables. The variable are references to Objects, so it will
do exactly what you tell it to do, compare the two object references. As you give it two different
objects, the result willl be “Different!”. The correct way of comparing the contents of
two objects is to use the equals method. Consider the following piece of code:

public class App
{
    public static void main(String[] args)
    {
        Integer a = new Integer(1);
        Integer b = new Integer(1);

        if (a.equals(b)) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}


This will again be “Equals!”.

Why is this often a problem? There are a lot or reasons why these bugs came to exist in CloudStack
(or any other project). For example somebody might cause this bug by changing the return type
of a function from long to Long. The first one is a primitive which can be compared with ==
and the second one is an Object which might result in another comparison than you intended.
Findbugs will catch these types of comparisons and warn you for them. See commit d1efdca50622a0b67ae1a286aad3297b1c748e9e
for an example.



Oh and what does this print?

public class App
{
    public static void main(String[] args)
    {
        Integer a = 1;
        Integer b = 1;

        if (a.equals(b)) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}


Surprise!, it prints “Equals!”.  This is a boxed integer and java keeps a pool of these
so internally the object is cached and both a and b get the same objects assigned to them
by the internal boxing logic. Just never rely on this! It only works in specific cases and
is implementation specific per JVM vendor and JVM version. 

Cheers,

Hugo


P.S. If you have another anti pattern feel free to post em in this thread.


Mime
View raw message