Simple, common interests, code-based parsers, Java questions

OK, after looking at some code with PMD and FindBugs , I was able to make some wonderful changes to the code I just covered. However, there are some things that I don't know how to fix. I'll repeat them below, and (for better reference) I'll give each question a number. Feel free to answer all / all of them. Thank you for your patience.

1. Even harshly I removed some of the rules, the corresponding warnings still exist after re-evaluating the code. Any idea why?


2. Look at the ads:

    private Combo comboAdress;

    private ProgressBar pBar;

      

and object references using getters and setters:

    private final Combo getComboAdress() {
  return this.comboAdress;
 }

 private final void setComboAdress(final Combo comboAdress) {
  this.comboAdress = comboAdress;
 }

 private final ProgressBar getpBar() {
  return this.pBar;
 }

 private final void setpBar(final ProgressBar pBar) {
   this.pBar = pBar;
 }

      

Now I'm wondering why the first ad doesn't give me a PMD warning, while the second one gives me the following warning:

Found non-transient, non-static member. Please mark as transient or provide accessors.

      

Read more about this warning here .


3. Here's another warning, also given by PMD:

    A method should have only one exit point, and that should be the last statement in the method

      

Read more about this warning here .

Now I agree with this, but what if I write something like this:

public void actionPerformedOnModifyComboLocations() {
    if (getMainTree().isFocusControl()) {
        return;
    }
    ....//do stuffs, based on the initial test
}

      

I tend to agree with this rule, but if the performance of the code involves multiple exit points, what should I do?


4. PMD gives me this:

Found 'DD'-anomaly for variable 'start_page' (lines '319'-'322').

      

when i declare something like:

String start_page = null;

      

I get rid of this information (the warning level is information) if I remove the null assignment, but .. I got an error from the IDE stating that the variable might be uninitialized, at some point later in the code. So, I'm kind of stuck with this. Overcoming the warning is the best thing you can do?


5. PMD warning:

Assigning an Object to null is a code smell.  Consider refactoring.

      

This is a case of single user use of GUI components or a case of a method that returns complex objects. Assigning the result to null in the catch () section is justified to avoid returning an incomplete / inconsistent object. Yes, NullObject should be used, but there are times when I don't want to. Should I suppress this warning?


6. FindBugs warning # 1:

Write to static field MyClass.instance from instance method MyClass.handleEvent(Event)

      

in method

@Override
public void handleEvent(Event e) {
    switch (e.type) {
        case SWT.Dispose: {
            if (e.widget == getComposite()) {
                MyClass.instance = null;
            }
       break;
         }
    }
}

      

static variable

private static MyClass instance = null;

      

The variable allows me to check if the form has already been created and is visible or not, and in some cases I need to forcefully re-create the form. I see no other choice here. Any ideas? (MyClass implements Listener, hence the override method in handleEvent () method).


7. FindBugs warning # 2:

Class MyClass2 has a circular dependency with other classes

      

This warning is displayed based on simple imports of other classes. Do I need to refactor this import to make this warning go away? Or is the problem related to MyClass2?

Okay enough said that for now ... expect an update based on additional findings and / or your answers. Thank.

+2


source to share


3 answers


Here are my answers to some of your questions:


Question number 2 :

I think you are using properties incorrectly. These methods should be named getPBar and setPBar.

String pBar;

void setPBar(String str) {...}
String getPBar() { return pBar};

      

The JavaBeans specification states that:

For readable properties, a getter method will be available to read the property value. The writable properties will have a setter method that will update the property value. [...] Creates a PropertyDescriptor for a property following standard Java convention using the getFoo and setFoo methods. Thus, if the argument name is "fred", the read method is assumed to be "getFred" and the write method is "setFred". Note that the property name must begin with a lowercase character, which will be capitalized in method names.


Question number 3 :

I agree with the offer of the software you are using. For readability, only one exit point is better. For efficiency use 'return;' could be better. I assume the compiler is smart enough to always choose an efficient alternative, and I bet the bytecode is the same in both cases.

FURTHER EMPIRICAL INFORMATION

I did some tests and found out that the java compiler I am using (javac 1.5.0_19 on Mac OS X 10.4) does not apply the expected optimizations.

I've tested the following class:

public abstract class Test{

  public int singleReturn(){   
     int ret = 0;
     if (cond1())
         ret = 1;
     else if (cond2())
         ret = 2;
     else if (cond3())
         ret = 3;

    return ret;
  }

  public int multReturn(){
    if (cond1()) return 1;
    else if (cond2()) return 2;
    else if (cond3()) return 3;
    else return 0;
  }

  protected abstract boolean cond1();
  protected abstract boolean cond2();
  protected abstract boolean cond3();
}

      

Then I analyzed the bytecode and found that there are multiple rotation operators for multReturn (), and there is only one for singleReturn (). Moreover, the singleReturn () bytecode also includes several gotos in the return statement.



I have tested both methods with very simple cond1, cond2 and cond3 implementations. I have verified that there are three conditions that are equally provable. I found a consistent time difference of 3% to 6% in favor of multReturn () . In this case, since the operations are very simple, the impact of multiple returns is quite noticeable.

I then tested both methods using a more complex implementation of cond1, cond2, and cond3 to make the impact of different returns less obvious. I was shocked by the result! Now multReturn () is consistently slower than singleReturn () (2% to 3%). I don't know what is causing this difference, because the rest of the code should be the same.

I think these unexpected results are caused by the JVM JIT compiler.

Anyway, I agree with my initial intuition: the compiler (or JIT) can optimize things like this, and this frees up the developer to focus on writing code that is easy to read and maintain.


Question number 6 :

You can call a class method from your instance method and leave that static method by changing the class variable.

Then your code looks something like this:

public static void clearInstance() {
    instance = null;
}

@Override
public void handleEvent(Event e) {
    switch (e.type) {
        case SWT.Dispose: {
            if (e.widget == getComposite()) {
                MyClass.clearInstance();
            }
       break;
         }
    }
}

      

This will lead to the warning you described in 5, but there must be some compromise, in which case it is just a smell and not a bug.


Question number 7 :

It's just the smell of a potential problem. This is not necessarily bad or wrong, and you cannot be sure just using this tool.

If you have a real problem like constructor dependencies, testing should show that.

Another but related issue is circular dependencies between jars: while classes with circular dependencies can be compiled, circular dependencies between jars cannot be handled in the JVM because of the way class loaders work.

+2


source


  • I have no idea. It seems likely that whatever you did was not what you were trying to do!

  • Perhaps the declarations appear in the class Serializable

    , but the type (for example, is ComboProgress

    not serializable). If it's UI code, then it seems very likely. I would just comment out the class indicating that it shouldn't be serialized.

  • This is a valid warning. You can refactor your code like this:

    public void actionPerformedOnModifyComboLocations() {
        if (!getMainTree().isFocusControl()) {
            ....//do stuffs, based on the initial test
        }
    }
    
          

  • This is why I cannot stand on static analysis tools. The appointment null

    obviously leaves you open for NullPointerException

    later. However, there are many places where this is simply unavoidable (for example, using try catch finally

    to clean up resources with Closeable

    )

  • This also looks like a valid warning, and your use of access static

    is likely to be considered a code smell by most developers. Consider refactoring with dependency injection to inject a resource tracker into the classes where you are currently using the static one.

  • If your class does not use imports, it should be removed. This may cause the warnings to disappear. On the other hand, if imports are needed, you might have a genuine circular dependency that looks something like this:

    class A {
        private B b;
    }
    class B {
        private A a;
    }
    
          

This is usually a confusing state of affairs and leaves you open to initialization problems. For example, you might accidentally add code to initialization A

that requires an instance of it to B

be initialized. If you add similar code to B

, then a circular dependency would mean that your code was indeed broken (i.e. you couldn't build A

either B

.



Again, an illustration of why I really don't like static analysis tools - they usually just give you a bunch of false positives. Looping code can work great and be very well documented.

+2


source


For point 3, probably most developers these days would say that the one-return rule is simply wrong, and results in worse code on average. Others see that this is a written rule with historical credentials, some code that breaks it is difficult to read and therefore not following it is simply wrong.

You seem to agree with the first camp, but not sure if the tool should disable this rule.

The thing to remember is a simple rule of thumb to code in any validation tool and some people want it. Thus, they are almost always implemented by them.

While few (if any) employ more subjective "guards"; body; return calculation; which usually produces the simplest and most understandable code.

So, if you're looking for good code and not just avoiding the worst code, this is one rule you probably want to disable.

+1


source







All Articles