Null pointers are everywhere because data is suddenly sparse

Someone has developed code based on complete data; XML has always had every element. The data source now sends sparse XML; if he was empty before that, he went missing. So, it's time to refactor when fixing bugs.

There are over 100 lines of code:

functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A"). getChild("oo").getContent()); 

Except now, getChild ("A") can return null. Or any of the getChild (xxx) methods could.

As another turn, instead of getChild (), there are actually four separate methods that can only be executed in specific orders. Someone suggested calling varargs, which is a good idea, but will not work as we would like.

What is the fastest way to clear this? Best? A β€œtry / catch” around each line was suggested, but the person, this one is ugly. By destroying the third argument to the aforementioned method, it can work its own function ... but it will entail more than 100 new methods that seem ugly, albeit less.

The number of calls to getChild (xxx) is six to ten per line without a fixed depth. There is also no way to get the correct DTD for this; things will be added later without previous headings, and where I would prefer a warning in the logs when this happens, additional lines in XML should be handled gracefully.

Ideas?

getChild () is a convenience method, in fact. The cleanest way that I mean is for convenience methods to return a valid Child object, but having this "empty" Child getContent () always returns "".

+4
source share
6 answers

What you described (returning a special child) is a form of the NullObject template, which is probably the best solution here.

+8
source

Please consider using XPATH instead of this mess.

+9
source

The solution is to use a DTD file for XML. It validates your XML file, so getChild("A") will not return null when A is required.

+2
source

What about:

 private Content getChildContent(Node root, String... path) { Node target = root; for ( String pathElement : path ) { Node child = target.getChild(pathElement); if ( child == null ) return null; // or whatever you should do target = child; } return target.getContent(); } 

to be used as

 functionDoSomething(foo, bar, getChildContent(root, "1", "A", "oo")); 
+2
source

Your problem may be a design problem: The Law of Demeter .

If you cannot use something like a Parameter Type that changes the return type of getChild to Option <Node>:

 for(Node r : getRoot()) for(Node c1 : r.getChild("1")) for(Node c2: c1.getChild("A")) return c2.getChild("oo") 

This works because Option implements Iterable, it will abort if the return value is undefined. This corresponds to Scala, where it can be expressed in a single for expression.

Another advantage is that you can define interfaces that will never return a null value . Using the Option type, you can specify in the interface definition that the return value can be undefined, and the client can decide how to handle it.


+2
source

If it always drills to about the same level, you can probably reorganize the code using Eclipse and it will automatically change every line that looks the same.

This way you can modify the method to be smarter and not change each line separately

0
source

All Articles