Отладка. Утверждайте по сравнению с исключениями

Краткий ответ: Актуальность в Elasticsearch не простая тема :) Подробности ниже.

Я пытался воспроизвести ваше дело ...

Сначала я поместил два документа:

POST /megacorp/employee/1
{
  "first_name": "John",
  "last_name": "Smith",
  "age": 25,
  "about": "I love to go rock climbing",
  "interests": [
    "sports",
    "music"
  ]
}

POST /megacorp/employee/2
{
  "first_name": "Jane",
  "last_name": "Smith",
  "age": 32,
  "about": "I like to collect rock albums",
  "interests": [
    "music"
  ]
}

, а позже я использовал ваш запрос:

GET /megacorp/employee/_search
{
  "query": {
    "match": {
      "about": "rock climbing"
    }
  }
}

Мои результаты были совершенно другими:

{
  "took": 89,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "1",
        "_score": 0.5753642,
        "_source": {
          "first_name": "John",
          "last_name": "Smith",
          "age": 25,
          "about": "I love to go rock climbing",
          "interests": [
            "sports",
            "music"
          ]
        }
      },
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 0.2876821,
        "_source": {
          "first_name": "Jane",
          "last_name": "Smith",
          "age": 32,
          "about": "I like to collect rock albums",
          "interests": [
            "music"
          ]
        }
      }
    ]
  }
}

[ 1115] Как видите, результаты в «ожидаемом» порядке. Обратите внимание, что значения _score полностью отличаются от вас.

1116 Вопрос: почему? Что произошло?

Подробный ответ для этой ситуации был описан в Практическом BM25 - Часть 1: Как Осколки влияют на оценку релевантности в статье Elasticsearch .

Коротко: как вы, вероятно, могли заметить, Elasticsearch хранит документы, разделенные между осколками. Чтобы быть быстрее, по умолчанию используется стратегия query_then_fetch . Это означает, что Elasticsearch сначала запрашивает результаты для каждого сегмента, а затем извлекает результаты и представляет их пользователю. Конечно, то же самое происходит с подсчетом очков.

Как вы можете видеть, в наших результатах 5 осколков, где были запрошены. Elasticsearch использует 5 шардов по умолчанию, если они не указаны при создании индекса (можно указать с помощью параметра number_of_shards). Вот почему наши оценки разные. Более того, если вы попытаетесь сделать это самостоятельно, есть большая вероятность, что вы снова получите другие результаты. Все зависит от того, как документ распределяется между осколками. Если вы установите number_of_shards в 1 для этого индекса, вы будете получать одинаковые оценки каждый раз.

Еще одна вещь, также упоминаемая в статье :

Люди начинают загружать в свой индекс всего несколько документов и спрашивают: «Почему у документа A выше / более низкий балл, чем у документа B », и иногда ответ заключается в том, что пользователь имеет относительно высокое отношение сегментов к документам, поэтому оценки пересекаются между различными фрагментами.

blockquote>

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

Надеюсь, мой ответ объяснит ваши сомнения.

17
задан Community 23 May 2017 в 11:44
поделиться

8 ответов

Я соглашаюсь с большинством людей здесь и следую за Дизайном Контракта. Необходимо попытаться дифференцироваться очень ясно между требованиями в развернутом коде (Контракты) и выяснение ожидаемого состояния во время дизайна (Отладка Утверждений).

необходимо ВСЕГДА бросать утверждения контракта как исключения (поскольку они должны всегда быть исключительными). Существуют механизмы, встроенные к большинству платформ для ловли утверждений отладки. Но во времени выполнения необходимо всегда выдавать исключение.

я пользуюсь пользовательской библиотекой для помощи с этим (в C#/VB.NET). Я недавно поднял его на Codeplex ( http://www.contractdriven.com/ ), если Вы интересуетесь тем, как это работает на практике.

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

Так вопрос в Вашем исходном сообщении... "Что я достигаю, вот то, что пользователь MyClass оставил его в недопустимом состоянии. Таким образом, что мы должны сделать?"... никогда не должен возникать.

Вы никогда, возможно, не должны отлаживать что-либо снова! ;-)

5
ответ дан 30 November 2019 в 13:34
поделиться

Во-первых, причем MyClass допустим, должен быть, конечно, выражен MyClass инвариант .

119-секундный, Вы говорите, что "Мы ожидаем, что MyMode будет обновлен внешними пользователями этого класса" - конечно, метод set этого режима должен иметь типичную форму дизайна контракта (как любая государственная функция):

  void Setter(mode m)
  {
    // INVARIANT ASSERT (1)
    // PRECONDITION ASSERTS (uses "m") (2)

    // BODY (3)

    // POSTCONDITION ASSERTS (if any) (4)
    // INVARIANT ASSERT (5)
  }

В (5) Вы перестали бы работать с кричащим нарушением утверждения, которое не содержит инвариант. , Но в (2) Вы перестали бы работать, ранее, потому что режим m передал, недопустимо. Это отправило бы сообщение открытым текстом пользователю и таким образом решает Вашу проблему.

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

Редактирование: Об утверждениях и режиме выпуска, см. также:

5
ответ дан 30 November 2019 в 13:34
поделиться

Я в основном соглашаюсь с заключением Вашего собственного вопроса: если А код вшей обнаруживает ошибку А сделанные вши, это - случай для А ssert (и на утверждениях нужно оставить в производственном коде, если производительность не диктует иначе). Если код Alice обнаруживает ошибку в код Eve's, это - случай для Exceptions, предполагая, что Alice и Eve находятся на противоположные стороны Вашего программного обеспечения отслеживания ошибок .

Теперь это - общее эмпирическое правило. Утверждения, в немного измененной форме, могут также использоваться в качестве "предостережение, разработчик!" механизм (и затем их нельзя назвать, "УТВЕРЖДАЕТ" только "HEADS_UP" или что-то подобное). Что, если Ваша компания разрабатывает клиент-серверный продукт, и сервер отправляет недопустимые данные клиенту? Если Вы - клиентский программист, Вы испытываете желание рассматривать его как внешние данные (это - данные Eve, которые являются уничтоженными), и Вы хотите выдать исключение. Но "более мягкое" утверждение, которое заставляет отладчик Visual Studio остановиться тут же, может быть очень хорошим способом обнаружить те проблемы действительно рано и сообщить об этом команде сервера. В реальной установке это могла очень хорошо быть Mallory, умеряющая с данными между Eve и Alice, но большую часть времени это - действительно ошибка одним из Ваших коллег, и Вы хотите видеть его, когда это происходит - вот почему я называю их "настороженными" утверждениями: они не заменяют исключения, но они дают Вам предупреждение и шанс осмотреть проблему.

5
ответ дан 30 November 2019 в 13:34
поделиться

Часто оба: Утверждайте, затем бросьте.

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

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

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

4
ответ дан 30 November 2019 в 13:34
поделиться

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

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

2
ответ дан 30 November 2019 в 13:34
поделиться

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

0
ответ дан 30 November 2019 в 13:34
поделиться

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

0
ответ дан 30 November 2019 в 13:34
поделиться

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

Иногда вы не знаете, пришли ли данные из внешнего источника или нет. Если безопасность важна и есть вероятность того, что вы имеете дело с внешними данными, правильность которых не была проверена, используйте исключение. Если безопасность не важна, я бы использовал производительность как средство разрешения конфликтов: может ли этот код выполняться в замкнутом цикле? В таком случае рассмотрите возможность использования assert, поскольку вы получите лучшую производительность в сборке Release. В противном случае используйте исключение.

1
ответ дан 30 November 2019 в 13:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: