2015-12-19 1 views
0

Весь мой слой базы данных в настоящее время возвращает Future [Option [Model]] для всех моих моделей.Зачем вам возвращать параметр [Модель] при извлечении по идентификатору?

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

Я не совсем уверен, почему я пошел с опцией [Model], но что считается лучшей практикой?

Я знаю, что в RubyonRails, когда вы выбираете Id i.e. Model.find (123), он генерирует исключение, если оно не найдено.

ответ

3

В этой ситуации я бы точно пошел с Future[Model]. Даже если приложение не должно «в основном сбой», Future может потерпеть неудачу, и это можно легко обработать. Используйте Future[Option[...]], где имеет смысл преуспеть без результата (например, где у вас есть ассоциация с нулевым значением в базе данных).

1

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

Это означает, что вместо написания вложенных операторов if/else, которые проверяют значение null, а затем извлекают значения .... вы можете обрабатывать результат как коллекцию и обрабатывать ее.

Это приводит к коду, который является плоским, а не традиционным вложенным способом if/else.

Вы можете прочитать о преимуществах использования вариантов здесь

http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html

0

Я думаю, что вы должны придерживаться Future[Option[Model]] именно по причине не бросать и не ловить исключения. Если тип возврата метода равен Option[Model], вы не можете пропустить обработку случая отсутствия модели. Подпись типа подсказки может быть ничего невозможен. Вызывающий должен явно указывать map или fold за Option, чтобы избавиться от него и обработать внутреннее устройство Model.

Поскольку все исключения не отмечены (и проверенные исключения - это просто крушение поезда), компилятор не может намекнуть на то, чтобы вы обрабатывали исключение, поэтому вы можете получить сюрприз во время выполнения. Scala - это скомпилированный и статически типизированный язык, и использование типов для описания возвращаемых данных - довольно чертовски хорошая идея, поскольку компилятор поможет вам все исправить. Это похоже на Ruby! Вы должны понимать преимущества статической типизации и обработки ошибок компиляции.

То же самое относится и к обработке не удалось Future S: если Future всегда успешно и не Future s указует только некоторые неожиданные ошибки, никогда не регулярные вещи, как «модель не найдены», вы можете просто map над ними без явных проверок, если они» неудачно или нет.

В вашем случае Future[Option[Model] дает вам лучшую обработку ошибок и управление потоком программ. Если ваш DAO просто выдает исключения, вы получите разбитое приложение с некоторой уродливой трассировкой стека в случае ошибки.Но если ваш DAO возвращает Future[Option[Model]], код вызывающего абонента может выглядеть л так:

DAO.findById(id).map { maybeModel: Option[Model] ⇒ 
    maybeModel match { 
    case Some(model) ⇒ processModel(model) 
    case None  ⇒ exitWithError(s"Could not find model with id = $id") 
    } 
} 

(код настолько многословен для целей удобочитаемости)

Приведенный выше код дает вам больший контроль над точками выхода в ваше приложение, которое может быть очень полезно, если ваши требования меняются, и вы не должны разбивать приложение, если модель не найдена. Например, вы можете найти все вызовы exitWithError и заменить их на logError или showErrorMessage вид логики. Это почти невозможно, если вы идете с исключениями.

Другой пример: предположим, что у вас есть 2 метода DAO: findById(id: Long): Future[Option[Model]] и countById(id: Long): Future[Int]. Их подписи типов предполагают, что findById может иметь ничего, чтобы вернуть обратно вызывающему, что указано Option. countById всегда должен будет вернуть что-то, которое предлагается просто Int. При кодировании с помощью этого API вызывающий абонент понимает семантику обоих методов. При вызове findById они должны думать о двух явных случаях: когда модель найдена, а когда нет. При вызове countById просто используйте любое возвращаемое значение, всегда Int.

Надеюсь, что это станет более ясным :) Не стесняйтесь задавать больше вопросов.

+0

Проблема также в том, что обработка Будущего [Option [Mode]] очень сложная, мне нужно написать столько кода, используя карту, а затем совпадение. Я так много делаю в своем приложении, что очень сложно писать простой код. У меня так много для понимания, и для начала каждого из них у меня есть вызов findById. – Blankman

+0

Ну, я мог бы помочь вам, если бы вы поделились некоторыми с вашим кодом. Ваше описание очень расплывчато. Если вы используете '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Вы можете использовать 'fold', чтобы избежать' match' в 'Option'. –

Смежные вопросы