Null Safe, разыменование в Java, как? в Groovy используя монаду Maybe - PullRequest
2 голосов
/ 25 мая 2010

Я работаю над базой кода, портированной с Objective C на Java. Существует несколько способов использования метода без проверки нуля

dog.collar().tag().name()

Я искал что-то похожее на оператор безопасной разыменования ?. в Groovy вместо нулевых проверок

dog.collar?.tag?.name

Это привело к Возможно, монада имела представление о Ничто, а не о Нуле. Но все реализации Nothing, с которыми я сталкивался, генерируют исключение при доступе к значению, которое все еще не решает проблему цепочки. Я заставил Nothing вернуть макет, который ведет себя как шаблон NullObject. Но это решает проблему цепочки.

Что-то не так с этой реализацией Nothing?

public class Nothing<T> implements Maybe<T> {

    private Class<T> klass;

    public Nothing(Class<T> klass) {
        this.klass = klass;
    }

    @Override
    public T value() {
        return mock(klass, Mockito.RETURNS_DEEP_STUBS); 
    }
}

Насколько я вижу

  1. Странно использовать библиотеку насмешек в коде
  2. Это не останавливается на первом нуле.
  3. Как отличить нулевой результат, потому что нулевая ссылка или имя фактически равны нулю? Чем он отличается в коде Groovy?

Ответы [ 4 ]

7 голосов
/ 25 мая 2010

Я бы не советовал просто проверять наличие нулей. На самом деле, я рекомендую даже не возвращать ноль, а вместо этого бросать исключения.

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

4 голосов
/ 25 мая 2010

Мне также нравится этот оператор, но он не доступен на Java - плюс это патч-пробел для небрежного кода: если у dog.collar нет тега, он, вероятно, должен переходить по-другому, и если у тега нет имени - это, вероятно, ошибка и должно выдать исключение.

Нельзя сказать, что когда вы наследуете код, который вы не написали, все решает, что лучше сказать «код лучше».

Я предлагаю сначала провести рефакторинг своего кода - если подобный код происходит повсеместно, возможно, его все равно нужно перенести в централизованную функцию. Если dog.getName () делегирует dog.collar (), чтобы получить его тег и, наконец, имя тега, то вам нужно исправить эту ошибку только в одном месте (у собаки должно быть имя, даже если оно не на ошейнике, поэтому dog.getName должен иметь возможность пройти любой путь, чтобы решить вашу проблему - теперь сделайте это снова для СЛЕДУЮЩЕГО пятна дрянного кода.

Всякий раз, когда вы видите, что исправляете один и тот же код в двух местах, возникает проблема факторинга. Если это происходит только один раз для каждой группы атрибутов (если она уже полностью разложена и является ОО), то это не может быть серьезной проблемой, просто пара патчей.

Черт возьми, разве такой код даже не нарушает несколько правил знакомства?

1 голос
/ 24 декабря 2010

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

Я натолкнулся на это в то же время, что и на ваш вопрос.
http://groovyconsole.appspot.com/script/205001

? безопасная разыменование является, очевидно, синтетически более чистым в groovy для проверки на ноль, цепочку можно завершить с помощью?: для возврата значения Nothing вместо null, такого как "" в этом контексте.

Если вы хотите понять монады, я бы порекомендовал изучать Haskell, и тогда вы, естественно, начинаете понимать, как эти понятия могут и используются в других языках. Языки, которые допускают изменчивость, даже если функциональные (такие как Scala) часто демонстрируют «нечистые» решения, а не чисто функциональные.

0 голосов
/ 09 сентября 2012

В Java нет оператора "безопасной разыменования".

Я думаю, что это хорошо, поскольку «безопасная разыменование» часто является маскировкой. У вас есть две возможности:

  • Значение не должно быть нулевым . В этом случае нулевое значение указывает на серьезную ошибку в ваших предположениях, и вы должны генерировать исключение NullPointerException, если нулевое значение каким-либо образом появляется (это принцип отказоустойчивости )
  • Значение может быть нулевым . В этом случае вы, как правило, должны выполнять некоторую явную обработку нуля, которая является более сложной, чем просто «не вызывать этот метод». Вы должны подумать: что означает ноль в этой ситуации?

Лично я обычно рассматриваю длинные цепочки методов как подсказку, чтобы преобразовать ваш код в меньшие, с четко названными методами (которые могут обернуть правильную обработку нуля внутри при необходимости). Это, вероятно, более разумно, чем введение монад в большинстве случаев.

...