Поймать универсальное исключение в реализации toString - плохая практика? - PullRequest
8 голосов
/ 21 июня 2019

У меня есть класс модели домена, у которого есть реализация toString, которая выглядит следующим образом:

public String toString() {
     try {
        return getX() + "\n"
             getY() + "\n"
             getZ(); //etc.
     } catch(Exception e) {
        throw new RuntimeException(e);
     }
}

Методы getX(), getY() и getZ() не являются простыми геттерами, они могут выполнять поиск в фоновом режиме, как правило, поиск статической карты предопределенных пар ключ-значение. У некоторых из них в подписи было throws SomeCheckedException.

У меня сложилось впечатление, что это плохая практика и "кодовый запах". Тот факт, что toString() даже нуждается в этой проверке, является для меня признаком плохого дизайна. Но коллега спросил меня, что именно не так с перехватом общего Exception в toString(), так как перехваченный Exception распространяется дальше.

Я полагаю, что это нарушает, по крайней мере, принцип KISS, поскольку простой метод, такой как toString(), здесь обозначен как требующий специальной обработки исключений.

Итак, пахнет ли код, чтобы иметь универсальный блок в toString ()?

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

Ответы [ 4 ]

4 голосов
/ 21 июня 2019

Да, это плохая практика.

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

На самом деле, я бы посчитал не автогенерацию этих методов вонючей, но предполагая, что вам неудобно или вы не можете использоватьIDE, которая создаст их для вас, я бы порекомендовал включить ссылку на все поля объекта и имя класса объекта, как это делается методом intellij toString

3 голосов
/ 21 июня 2019

Для метода toString(), перехват Exception не обязательно является плохой практикой. Однако, перебрасывание является проблемной частью.

Контракт для toString () :

... Как правило, метод toString возвращает строку, которая «представляет собой текст» этого объекта. Результатом должно быть краткое, но информативное представление, которое легко читается человеком ...

В Effective Java 3rd Edition (статья 12) Блох настаивает:

Когда это практически возможно, метод toString должен возвращать всю интересную информацию, содержащуюся в объекте.

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

Однако: поднял отмеченные исключения, предоставляющие информацию о состоянии объекта. В соответствии с целью toString, было бы неплохо включить исключительное условие в сообщение, возвращаемое toString.

Что касается того, почему плохая идея бросать исключения из toString, , этот пост дает отличный ответ.

Рекомендация: Поймайте отмеченные исключения, используя их конкретный тип исключения, и включите этот факт в сообщение toString() вместо его распространения.

3 голосов
/ 21 июня 2019

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

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

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

0 голосов
/ 21 июня 2019

Должен ли "нормальный поток" прерываться ошибочным методом toString ()?Если ответ отрицательный, вы должны заставить метод toString () работать.Поймать исключение и отразить это в результате - одна возможность или простой вывод журнала.

...