2

I have a very fat pojo java class with over 1000 fields / getters & setters. Some of those fields are no longer being used and I'd like to clean-up that class. I don't know much about reflection but I would like to be able to programatically identify fields that are no longer being referenced in another class.

The way to identify if a field needs to be cleaned up is to see if the field's setter method is being invoked in another, if not, its a candidate for clean-up.

I got as far as figuring out how to extract methods and field names using reflection, but I don't know where to begin identifying those fields whos setters are not referenced in another class's execution.

public class GetterSetterReflec {

    public static void main(String args[]){
        printGettersSetters(SearchEngineClientModel.class);
    }

    public static void printGettersSetters(Class<?> aClass)
    {
          Method[] methods = aClass.getMethods();

          Field[] fields = aClass.getDeclaredFields();
          for(Field field : fields){
              System.out.println(field);
          }

          for(Method method : methods){
            if(isGetter(method)) System.out.println("getter: " + method);
            if(isSetter(method)) System.out.println("setter: " + method);
          }
    }

        public static boolean isGetter(Method method){
          if(!method.getName().startsWith("get"))      return false;
          if(method.getParameterTypes().length != 0)   return false;  
          if(void.class.equals(method.getReturnType()))
                  return false;
          return true;
        }

        public static boolean isSetter(Method method){
          if(!method.getName().startsWith("set")) return false;
          if(method.getParameterTypes().length != 1) return false;
          return true;
        }
}

I'd be grateful for any help you can provide. Thank you in advance!

Balder
  • 8,623
  • 4
  • 39
  • 61
Horse Voice
  • 8,138
  • 15
  • 69
  • 120
  • 1
    Can't your IDE tell you which fields and methods are redundant? – Paul Boddington Jan 06 '15 at 20:23
  • That would take about 3 weeks of manual work. Unfortunately, this is a very very large class. Over 1000 fields – Horse Voice Jan 06 '15 at 20:39
  • You are using frameworks like JSF?, you have a high test coverage? – Arturo Volpe Jan 06 '15 at 20:47
  • Indeed. Technical debt can become rather expensive. – hoipolloi Jan 06 '15 at 20:49
  • I'm thinking of reading the file which uses the setter methods storing that in a string variable and using contains() method to see if the setter method is being used or not to highlight the deletable fields – Horse Voice Jan 06 '15 at 20:55
  • You could use JDT to search for references to your method. For inspiration see [here](http://www.programcreek.com/2011/07/find-all-callers-of-a-method/) and [here](http://stackoverflow.com/questions/14493613/how-to-get-all-the-references-of-static-field-with-jdt). – Balder Jan 07 '15 at 06:49

1 Answers1

0

I don't think this is possible with reflection. You can use your IDE (or other static analysis tools) to discover call hierarchies. This approach works 99% of the time but fails for any calls executed via reflection (for example, by a framework) at runtime.

If you want to catch runtime calls, you could advise methods with AOP. A simpler approach might be to introduce log statements (or throw an exception) from methods you suspect to be unused and then run your tests. If your tests have poor coverage, you can introduce log statements to suspect methods and then allow your application to run for some time in production (with the marker statements) until you are confident enough to remove the suspect methods.


Dynamic method invocation example

Consider the following Spring bean:

public class Foo implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext ctx) 
             throws BeansException {
        // you won't find any reference to this setter; 
        // ...it is invoked at runtime by the Spring framework

    }

}
hoipolloi
  • 7,984
  • 2
  • 27
  • 28
  • I'm thinking of reading the file which uses the setter methods of the fat class and using contains() method to see if the field can be deleted or not. – Horse Voice Jan 06 '15 at 20:54
  • @Horse - that's basically what static analysis tools will do for you. Beware runtime invocation though. The methods may be built dynamically so your 'contains()' strategy won't pick up those use cases. – hoipolloi Jan 06 '15 at 20:59
  • Hmm.. Not sure I understand what you mean. Basically, if the fat pojos field has a setter method appearance in the other classes string variable, that field is not a deletable field. Am I missing something crucial here? – Horse Voice Jan 06 '15 at 21:02
  • I guess I dont know what u mean by methods being built dynamically. – Horse Voice Jan 06 '15 at 21:04
  • The approach you're describing is reasonably solid. Most IDEs have this functionality built in. For example, IntelliJ shows a warning 'Method xxx() is never used'. However, some frameworks use reflection to call your methods at runtime. Consequently you won't 'find' any reference to your methods at compile time. – hoipolloi Jan 06 '15 at 21:14