Является ли объект Java, содержащий нулевые переменные, анти-шаблоном? Если да, то какой? [закрытый]


Если я запрашиваю объект, скажем, для животного, и возвращаемый объект не является нулевым, но содержит нулевые переменные, это неправильно? Например, я могу вызвать animal.getDeathDate(); и поскольку он еще не мертв, он возвращает null. Для черепахи getFlightSpeed() вернет null, так как она не может летать, пока не будет добавлен пакет ракеты черепахи. И так далее, и тому подобное.

Я подумал, что это плохой способ сделать вещи, так как это часто вызывает необходимость в большом количестве нулевых проверок при вызове методов объекта, чтобы проверить, что они содержат ненулевые значения. Есть ли какие-либо ссылки на информацию об этом, которые могли бы информировать меня и моих коллег дальше?

9 5

9 ответов:

null часто бывает двусмысленным. Было ли поле еще неинициализировано или оно просто не имеет значения?

Часто лучше иметь некоторую предопределенную константу для неинициализированных / нерелевантных полей.

Еще лучше, чтобы у одного класса была только одна ответственность. Методы, подобные getFlightSpeed(), не должны наследоваться, а скорее исходить из реализации интерфейса (методы, подобные getDeathDate(), однако, должны иметь предопределенную константу, возвращаемую, когда Animal все еще жив).

Как принесло google-гуава docs :

Дуг ли (автор пакета java.util.concurrent) сказал, что Null s**ks.

Также сэр С. А. Р. Хоэр, изобретатель ссылки null сказал: I call it my billion-dollar mistake.

Это какое-то широкое плечо, на которое можно опереться.

Возвращение null для даты смерти живого животного вполне разумно, но в таких случаях я считаю, что лучше предложить булеву проверку смерти:

public boolean isDead() {
    return deathDate != null;
}

Это предлагает разумный способ проверки смерти экземпляра без неуклюжей нулевой проверки атрибута:

// this is ugly and exposes the choice of the value of the field when alive
if (animal.getDeathDate() != null) {
    // the animal is dead
}

С помощью метода isDead() вы будете в пределах своих прав, чтобы сделать это:

public Date getDeathDate() {
    if (deathDate == null)
        throw new IllegalStateException("Death has not occurred");
    return deathDate;
}

Что касается скорости полета черепахи, вы можете применить тот же подход, хотя я я бы сказал, что в вашем дизайне класса есть проблема-не все животные летают, поэтому класс Animal не должен иметь метода getFlyingSpeed().

Вместо этого используйте что-то вроде этого:

interface Flyer {
    Integer getFlightSpeed();
}

class Animal {}

class Turtle extends Animal {}

class Eagle extends Animal implements Flyer {
    public Integer getFlightSpeed() {
         //
    }
}

Null иногда может быть вполне разумным способом представления того, что у объекта отсутствует определенное свойство.

Тем не менее, полезно разрешить одиночную проверку.

Для массива или списка часто лучше иметь переменную, которая всегда ненулевая, но может указывать на пустой список. В противном случае становится необходимым проверить, что переменная не является нулевой и что в списке есть члены.

Главное правило проверки null, которое у меня есть, - никогда не помещать null вместо списка или массива.

Пустые списки и массивы гораздо лучше выражают то, чем они являются на самом деле.

Я не думаю, что это неправильно. В качестве аналогии рассмотрим семантику NULL в SQL :

Хороший способ запомнить, что означает NULL, - это запомнить, что в терминах информация, "отсутствие ценности" - это не то же самое, что "ценность ноль"; точно так же "отсутствие ответа" - это не то же самое, что "Ан ответ "нет".

Вполне допустимо применять ту же логику в Java.

Для того, чтобы сделать примитивные типы, допускающие значение null, проверьте , допускающий значение null типы В C#. Она должна быть простой в реализации, допускающий значение null в Java универсальные.

Это только мое мнение, но ваш пример действительно звучит как анти-шаблон (как вырожденный нулевой объект), так как вам нужно было бы сделать нулевые проверки того, что возвращают методы на "нулевом объекте". Если вы вообще не вызываете эти геттеры, то ваш пример будет правильным.

Идея с null-объектами заключается в том, что вам вообще не нужно выполнять проверки null, поэтому это может сработать, если ваши геттеры возвращают другие null-объекты, или методы используют подход tell-don't-ask (и просто возвращают пустота).

Null-это прекрасно, но вы должны стараться избегать их, используя значения по умолчанию как можно больше

Например пустой список должен быть возвращен вместо null перечисление типов данных должно содержать неизвестные

Вышеуказанное предположение делает жизнь потребителя API легкой

В вашем примере я бы вернул null из animal.getDeathDate, как я не могу думать о любом подходящем значении по умолчанию.

Я обеспечу удобство метода animal.isDead возвращает true / false

Для getFlightSpeed () я бы вернул 0 для вашего случая

Шаблон нулевого объекта действительно может быть использован в случае нулевых переменных. На случай черепахи.getFlightSpeed (), вы можете абстрагироваться от концепции скорости (может быть интерфейс или абстрактный класс), и иметь один нулевой объект, реализующий сценарий "невозможно летать". Это поможет присвоить классам черепахи поведение по умолчанию. Возвращает null в случае животного.getDeathDate () кажется прекрасным

Я думаю, что для животного.getDeathDate() возвращает значение NULL, если животное живое-это правильный способ делать вещи. Вам всегда будет нужен специальный код для обработки 2 случаев: животное живое и животное мертвое, и нет никакой полезной даты, которую вы можете вернуть, если животное живо.

Для getFlightSpeed() все может быть по-другому. Я не знаю точно, что он возвращает, но давайте просто для примера представим, что он просто возвращает скорость как m/s

В этом случае возвращается 0(или объект с тот же эффект) будет иметь идеальный смысл, потому что он действительно описывает скорость полета.