Я написал структуру, которая представляет координаты широты / долготы. Их значения варьируются от -180 до 180 для долгот и от 90 до -90 для широт.
Если пользователь этой структуры дает мне значение вне этого диапазона, у меня есть 2 варианта:
- Бросить исключение (arg вне диапазона)
- Преобразовать значение в ограничение
Поскольку координата -185 имеет значение (ее очень легко преобразовать в +175, поскольку это полярные координаты), я мог бы принять ее и преобразовать.
Лучше ли генерировать исключение, чтобы сообщить пользователю, что его код дал мне значение, которого не должно быть?
Редактировать: Также я знаю разницу между широтой и долготой и координатами, но я хотел упростить это для облегчения обсуждения - это была не самая яркая идея
c#
exceptions
validation
К. Гкинис
источник
источник
Ответы:
Если суть вашего вопроса заключается в следующем ...
... тогда мой общий ответ будет "отклонить", потому что это поможет привлечь внимание к потенциальным ошибкам в клиентском коде, которые фактически приводят к тому, что недопустимое значение появляется в программе и достигает вашего конструктора. Привлечение внимания к ошибкам, как правило, является желаемым свойством в большинстве систем, по крайней мере, во время разработки (если только это не является желательным свойством вашей системы, которое нужно перепутать в случае ошибок).
Вопрос в том, сталкиваешься ли ты с этим делом .
Если ваша структура данных предназначена для моделирования полярных координат в целом, то примите это значение, потому что углы вне диапазона -180 и +180 на самом деле не являются недопустимыми. Они совершенно верны, и у них просто всегда есть эквивалент в диапазоне от -180 до +180 (и если вы хотите преобразовать их в целевой диапазон, не стесняйтесь - клиентскому коду обычно не нужно заботиться) ,
Если ваша структура данных явно моделирует координаты Web Mercator (в соответствии с вопросом в его первоначальном виде), то лучше следовать всем положениям, упомянутым в спецификации (которые я не знаю, поэтому я не буду ничего говорить об этом) , Если спецификация моделируемой вещи говорит, что некоторые значения недопустимы, отклоните их. Если это говорит о том, что они могут быть интерпретированы как нечто разумное (и, следовательно, они действительно действительны), примите их.
Механизм используется для сигнала , было ли принято значение или нет , зависит от особенностей вашего языка, его общей философии и требований к производительности. Таким образом, вы можете генерировать исключение (в конструкторе) или возвращать обнуляемую версию вашей структуры (через статический метод, который вызывает закрытый конструктор) или возвращать логическое значение и передавать вашу структуру вызывающей стороне в качестве
out
параметра (снова через статический метод, который вызывает приватный конструктор) и так далее.источник
Это зависит от многих. Но вы должны решить что-то сделать и задокументировать .
Единственная определенно неправильная вещь для вашего кода - забыть учесть, что пользовательский ввод может быть вне ожидаемого диапазона, и написать код, который случайно имеет некоторое поведение. Потому что тогда некоторые люди сделают неверное предположение о том, как ваш код ведет себя, и это вызовет ошибки, в то время как другие в конечном итоге будут зависеть от поведения, которое ваш код имеет случайно (даже если это поведение совершенно ненормально), и поэтому вы будете вызывать больше ошибок когда вы позже решите проблему.
В этом случае я могу видеть аргументы в любом случае. Если кто-то путешествует +10 градусов от 175 градусов, он должен в конечном итоге на -175. Если вы всегда нормализуете пользовательский ввод и, таким образом, рассматриваете 185 как эквивалентное -175, тогда клиентский код не может поступить неправильно, когда он добавляет 10 градусов; это всегда имеет правильный эффект. Если вы воспринимаете 185 как ошибку, вы заставляете каждый случай, когда клиентский код добавляет относительные градусы, вставлять в логику нормализации (или, по крайней мере, не забывать вызывать процедуру нормализации), вы на самом деле вызываетеошибки (хотя, надеюсь, легко поймать те, которые будут быстро устранены). Но если значение долготы вводится пользователем, записывается буквально в программе или вычисляется с помощью какой-либо процедуры, которая всегда должна быть в [-180, 180), то значение вне этого диапазона, скорее всего, будет указывать на ошибку, поэтому «с любовью» «Преобразование это может скрыть проблемы.
Мой идеал в этом случае, вероятно, будет определять тип, который представляет правильный домен. Используйте абстрактный тип (не позволяйте клиентскому коду просто обращаться к необработанным числам внутри него) и предоставьте как нормализующую, так и проверочную фабрику (чтобы клиент мог сделать компромисс). Но независимо от значения этого типа, значение 185 должно быть неотличимо от -175 при просмотре через ваш общедоступный API (не имеет значения, преобразованы ли они в конструкцию или вы предоставляете равенство, методы доступа и другие операции, которые каким-то образом игнорируют разницу) ,
источник
Если вам не важно выбрать одно решение, вы можете просто позволить пользователю принять решение.
Учитывая, что ваша структура является объектом значения только для чтения и создана методом / конструктором, вы можете предоставить две перегрузки, основанные на опциях, которые есть у пользователя:
Также никогда не позволяйте пользователю иметь недопустимую структуру для передачи другим вашим методам, сделайте это прямо при создании.
Редактировать: основываясь на комментариях, я предполагаю, что вы используете c #.
источник
catch
ваши исключения. Как уже говорили другие, это позволяет клиенту ограничивать себя, если он этого хочет. Вы на самом деле ничего не обходите.Это зависит от того, вводится ли пользователь напрямую через какой-либо пользовательский интерфейс или из системы.
Ввод через пользовательский интерфейс
Это вопрос пользовательского опыта, как обращаться с неверным вводом. Я не знаю о вашем конкретном случае, но в целом есть несколько вариантов:
Выбор зависит от ожиданий ваших пользователей и того, насколько важны данные. Например, Google автоматически исправляет орфографию в запросах, но это низкий риск, потому что бесполезные изменения не являются проблемой и их легко исправить (и даже на странице результатов ясно, что запрос был изменен). С другой стороны, если вы вводите координаты для ядерной ракеты, вам может потребоваться более жесткая проверка ввода и отсутствие скрытых исправлений неверных данных. Так что универсального ответа нет.
Самое главное, вы должны рассмотреть, если исправление ввода даже приносит пользу пользователю. Зачем пользователю вводить неверные данные? Легко увидеть, как кто-то может сделать орфографическую ошибку, но зачем кому-то вводить долготу -185? Если бы пользователь действительно имел в виду +175, он, вероятно, набрал бы +175. Я думаю, что, скорее всего , неверная долгота просто является ошибкой при наборе, а пользователь имел в виду -85 или что-то еще. В этом случае тихое преобразование плохо и бесполезно . Наиболее удобный подход для вашего приложения, вероятно, состоит в том, чтобы предупредить пользователя о недопустимом значении и заставить пользователя исправить его самостоятельно.
Ввод через API
Если входные данные поступают из другой системы или подсистемы, никаких вопросов не возникает. Вы должны бросить исключение. Никогда не следует молчаливо преобразовывать неверные данные из другой системы, поскольку они могут маскировать ошибки в других местах системы. Если ввод «исправлен», это должно происходить на уровне пользовательского интерфейса, а не вглубь системы.
источник
Вы должны бросить исключение.
В приведенном вами примере, отправив 185 и преобразовав его в -175, в некоторых случаях это может быть полезно для обеспечения этой функциональности. Но что, если звонящий отправит 1 миллион? Они действительно хотят преобразовать это? Кажется более вероятным, что это ошибка. Поэтому, если вам нужно сгенерировать исключение для 1 000 000, а не для 185, вам нужно принять решение о произвольном пороговом значении для исключения. Этот порог может сбить вас с толку, так как некоторые вызывающие приложения отправляют значения около порога.
Лучше выбросить исключение для значений вне диапазона.
источник
Наиболее удобный вариант для разработчика - поддержка ошибок времени компиляции в платформе для значений вне диапазона. В этом случае диапазон также должен быть частью сигнатуры метода, как и тип параметров. Точно так же, как ваш пользователь API не может передать строку, если ваша сигнатура метода определена как целочисленная , пользователь не должен был бы передавать значение без проверки, находится ли значение в диапазоне, указанном в сигнатуре метода. Если не проверено, он должен получить ошибку времени компиляции и, таким образом, можно избежать ошибки времени выполнения.
Но в настоящее время очень немногие компиляторы / платформы поддерживают этот тип проверки времени компиляции. Так что это головная боль разработчиков. Но в идеале ваш метод должен просто генерировать значимое исключение для неподдерживаемых значений и четко документировать его.
Кстати, мне очень нравится модель ошибки, предложенная здесь Джо Даффи .
источник
По умолчанию должно быть выброшено исключение. Вы также можете разрешить такую опцию, как
strict=false
и делать принуждение на основе флага, где, конечно,strict=true
по умолчанию. Это довольно распространено:DateFormat
поддерживает снисходительный .источник
strict=false
?Для меня лучшая практика - никогда не менять пользовательский ввод. Подход, который я обычно использую, заключается в том, чтобы отделить валидацию от исполнения.
источник