Best practices for nested objects

What is the best practice for linking nested objects?

Say I have the following:

class Outer { private InnerA innerA; //getters and setters } class InnerA { private InnerB innerB; //getters and setters } class InnerB { private String someString; //getters and setters } 

and in my controller or service class I need to check the someString String variable of the InnerB class to make sure it is not null or not empty, so I do this:

 if (getOuter().getInnerA().getInnerB().getSomeString() != null && !getOuter().getInnerA().getInnerB().getSomeString().equalsIgnoreCase("") { //do something } 

For me, this looks dirty and can have problems if the nested objects themselves are zero.

Am I creating getters ans seters in parent objects for child objects checking null? Just wondering what was the best practice, if any, and / or what some of you do in your code?

+6
java object reference nested
source share
9 answers

If any of these objects can be null, then you need to check the null value before calling the getter on that object, of course.

But this type of chain is a bad smell of lack of encapsulation (anemic objects that have only data and no behavior). You are breaking the law of Demeter: do not talk with strangers.

+7
source share

You can use Apache Commons BeanUtils to navigate your nested properties as follows:

Add the getSomeString() method to your Outer class and write something like

PropertyUtils.getNestedProperty(this, "innerA.innerB.someString");

I cannot remember if the PropertyUtils class checks for null properties, but I would look at the Apache Commons BeanUtils site .

Hope this helps!

+7
source share

You have two options:

+4
source share

I would recommend reading the Law of Demeter .

+4
source share

I do not think that Outer users should have knowledge of Outer.InnerA.InnerB.SomeString - he is buried deeply. You cannot change the implementation of InnerB without touching the clients of the Outer 3 departments - so what's the point even with inner classes? Situations like the description are ugly and should not arise.

I would recommend that you first consider whether SomeString belongs to InnerB or InnerA or Outer.

Now suppose your hierarchy is correct, but SomeString has this unique property of requiring Outer clients (if SomeString is not unique in this case, the hierarchy is definitely incorrect). In this case, Outer.getSomeString () or even better Outer.isSomeStringNullOrEmpty (), so at least Outer clients should not know about InnerA and InnerB

PS. someString.equalsIgnoreCase ("") is expensive, do not use this. Much cheaper someString.length () == 0

+1
source share

It's messy, but if you only needed to do this in one place, I could live with it. Otherwise, I would use Outer.getSomeString() , which hides the internal path, since your Outer class is the one you show as your interface.

It also allows you to deal with the case when one of the intermediate inner classes is null, without having to perform a series of consecutive checks every time you try to access someString .

+1
source share

I am convinced that you should not expose the โ€œinner-innerโ€ members using the methods of the outer class unless you add some kind of functionality or other behavior or meaning โ€œessentialโ€ to use the outer class, However, this is also a matter of judgment and may vary depending on the use and architecture of your code.

On the side of the note, if you want the code for the long line of invocations to be โ€œless ugly,โ€ I suggest voting to add the Elvis Operator for the project coin in the next version of Java (I would like it to turn into 7: - ().

+1
source share

This is a limitation of java. You should implement helper methods in the parent "OuterObject" if this helps you reduce code duplication.

These helper methods are useful for an object that aggregates another object, and you only need to check if a nested value exists.

the code:

 getOuter().hasInnerB(); 

Which will do all zero checks.

This problem often occurs with objects generated from * .xsd. In a complex xml structure, there are often many nested additional nodes. And what is usually interesting is the last node. Then it is better to write helper methods that will answer questions if node exists for reuse.

If it matches your cod pattern, I usually write something like this

 if (hasSomeString(getOuter())) { //do something } 
+1
source share

I wrote a Java 8 method:

 public class Helper { public static <IN, OUT> OUT returnNullOrCallFunction(IN o, Function<IN, OUT> f) { return o == null ? null : f.apply(o); } } 

Now you can call:

 Helper.returnNullOrCallFunction( myObject.getSomeOtherObject(), SomeOtherObject::toString ); 

If myObject.getSomeOtherObject() is null , the method will return null , otherwise it will call myObject.getSomeOtherObject().toString() .

This is very useful if you just need to go one level deeper.

For multi-level, it gets ugly:

 Helper.returnNullOrCallFunction( Helper.returnNullOrCallFunction( myObject.getSomeOtherObject(), SomeOtherObject::getAnotherObject ), AnotherObject::toString ); 
0
source share

All Articles