Я столкнулся с этой проблемой в проекте: существует цепочка вложенных объектов, например: класс A содержит переменную экземпляра класса B, которая в свою очередь имеет переменную экземпляра класса C,..., пока мы не получим node в дереве класса Z.
----- ----- ----- ----- -----
| A | ---> | B | ---> | C | ---> | D | ---> ... ---> | Z |
----- ----- ----- ----- -----
Каждый класс предоставляет получателям и сеттерам своих членов. Родительский экземпляр создается парсером XML, и для любого объекта в цепочке законно быть нулевым.
Теперь представьте, что в какой-то момент приложения мы имеем ссылку на экземпляр A, и только если он содержит объект Z, мы должны вызвать на нем метод. Используя регулярные проверки, мы получаем этот код:
A parentObject;
if(parentObject.getB() != null &&
parentObject.getB().getC() != null &&
parentObject.getB().getC().getD() != null &&
parentObject.getB().getC().getD().getE() != null &&
...
parentObject.getB().getC().getD().getE().get...getZ() != null){
parentObject.getB().getC().getD().getE().get...getZ().doSomething();
}
Я знаю, что исключения не должны использоваться для обычного потока управления, но вместо предыдущего кода я видел, как некоторые программисты это делали:
try {
parentObject.getB().getC().getD().getE().get...getZ().doSomething();
} catch (NullPointerException e){}
Проблема с этим кодом заключается в том, что при его поддержании может быть запутанно, поскольку он не показывает, какие объекты могут быть пустыми. Но, с другой стороны, гораздо более кратким и менее "телескопическим".
Это приемлемо для экономии времени разработки? Как можно перепроектировать API, чтобы избежать этой проблемы?
Единственное, о чем я могу думать, чтобы избежать длинной проверки на нуль, - это предоставить void экземпляры вложенных объектов и предоставить методы isValid
для каждого из них, но не создаст ли это много необычных объектов в памяти
(Я использовал код Java, но тот же вопрос может применяться к свойствам С#)
Спасибо.