Возврат нуля против исключения против контракта

Что можно было бы считать приемлемым способом работы с возвратом записи из БД со следующими тремя потенциальными результатами:

  1. Соединение с базой данных работает, находит пользователя и возвращает заполненный объект пользователя
  2. Соединение с БД работает, пользователя не находит, возвращает новый объект пользователя
  3. Ошибка подключения / запроса к базе данных ...

Я по большей части стремлюсь к проектированию по контракту:

class Scratch {
        public User getUser(int id) {
            try {
                // Prepare SQL Query
                PreparedStatement s = this.connection.prepareStatement(
                        "select * from get_user(?)"
                );

                // Provide SQL Parameters
                s.setInt(1, id);

                // Run our SQL
                ResultSet rs = s.executeQuery();
                rs.next();

                // Extract data into Entity
                User user = User.createFromDatabase(rs);
                rs.close();

                return user;

            } catch(Exception e) {
                e.printStackTrace();
            }

            return new User();
        }
}

В ситуации, когда соединение или запрос к БД не удается, менее очевидно, что мне делать, у меня есть несколько вариантов:

  • Вернуть новый объект пользователя, потому что наш метод согласился вернуть пользователя
    • Плюс: это касается проектирования по контрактам.
    • Против: из-за этого создается впечатление, что пользователя не существует.
  • Возврат ноль, поскольку он фактически не получил пользователя.
    • Плюс: Совершенно очевидно, что пользователь не найден.
    • Минус: требуется проверка нуля
  • Выбросить исключение дальше по цепочке.
    • Pro: ясно дает понять, что операция не выполнена.
    • Против: не пытается исправить проблемы там, где они возникают.

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

Однако я хотел бы знать, есть ли какие-либо очевидные подводные камни или это знакомая ситуация с хорошо установленным шаблоном для ее решения.

getUser должен делать только одно - привлечь пользователя. Если он не может, он должен вызвать исключение. Для меня возврат null создает впечатление, что пользователя не существует. Связанный: stackoverflow.com/questions/77127/when-to-throw-an-exception
Ivar 25.10.2018 10:32

@Ivar спасибо Я обновил это сейчас, я открыл новый рабочий файл в IntelliJ и вставил некоторый код.

Royal Wares 25.10.2018 10:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

Мой выбор - выбросить исключение

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

Royal Wares 25.10.2018 10:40

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

  • Необязательно (Пользователь), если пользователь найден в базе данных
  • Пусто, если пользователь не найден
  • В случае ошибки у вас есть два варианта:
    • Уведомите клиента, чтобы он мог получить обратную связь и отреагировать на этот сбой. В этом случае вызовите исключение и обработайте его на соответствующем уровне. Это должно быть поведением по умолчанию для большинства приложений.
    • Скрывайте это от клиента, это менее распространено, но иногда клиенту все равно, или вы не хотите публиковать свои ошибки. В этом случае просто верните пустой.

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

Ivar 25.10.2018 10:41

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

Royal Wares 25.10.2018 10:47

Я полагаю, что заслуживаю отрицательной оценки, не знаю, о чем я думал -_- !. Кстати, я действительно рекомендую вам использовать Optional, чтобы избежать возврата null при пустом запросе результатов.

RoberMP 25.10.2018 13:53

Другие вопросы по теме