Re[16]: обработка ошибок
От: Ночной Смотрящий Россия  
Дата: 20.04.22 08:36
Оценка: +1
Здравствуйте, yenik, Вы писали:

Y>Остаётся вопрос, можем ли мы обобщить это так, что любые ошибки приложения (кроме отказов инфраструктуры) должны возвращать 4хх?


Нет. Я же приводил цитату из стандарта:

The 4xx class of status code is intended for cases in which the client seems to have erred.

... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[17]: обработка ошибок
От: yenik  
Дата: 21.04.22 06:59
Оценка:
Y>>Остаётся вопрос, можем ли мы обобщить это так, что любые ошибки приложения (кроме отказов инфраструктуры) должны возвращать 4хх?

НС>Нет. Я же приводил цитату из стандарта:

НС>

НС>The 4xx class of status code is intended for cases in which the client seems to have erred.


Помню. Но здесь
Автор: Sinclair
Дата: 07.04.22
говорится следующее:

400 означает, что неверны не вообще любые аргументы чего угодно, а конкретно аргументы, переданные клиентом.
То есть хэндлер рест-апи должен проверить аргументы, и только если они в порядке, ехать дальше.
Исключения за пределами первичной валидации — это уже 500.


В самом начале речь шла об ArgumentException. Такое исключение может прийти и из глубин бизнес-логики, много позже первичной валидации, и оно может быть связано с ошибкой клиента.
Ну и описанная выше ситуация с отсутствием денег на счету не отлавливается первичной валидацией. Однако мы установили, что она должна порождать код 400, а не 500.
Re[18]: обработка ошибок
От: Ночной Смотрящий Россия  
Дата: 21.04.22 07:08
Оценка:
Здравствуйте, yenik, Вы писали:

Y>Помню. Но здесь
Автор: Sinclair
Дата: 07.04.22
говорится следующее:


Я цитату из стандарта привел. Она первична.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[18]: обработка ошибок
От: MadHuman Россия  
Дата: 21.04.22 08:46
Оценка:
Здравствуйте, yenik, Вы писали:


Y>Ну и описанная выше ситуация с отсутствием денег на счету не отлавливается первичной валидацией. Однако мы установили, что она должна порождать код 400, а не 500.

отсутствие денег на счету это не 400. с самим реквестом в данном случае всё ок, счет указан верно, ошибок в данных реквеста нет.
это 403 — операция запрещена. она классифицируется как ошибка клиента — т.к. при таких данных реквеста (они валидны), операция не может быть выполнена, по штатным причинам. повторять клиенту реквест смысла нет.

500 — это когда — мало памяти/веб-сервер перегружен и пока не может/ошибка при связи с сервером БД/сервер БД перегружен/ещё какая-та "неведомая херня", в итоге — сервер по техническим причинам не может обработать реквест.
Re[18]: обработка ошибок
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.04.22 09:54
Оценка:
Здравствуйте, yenik, Вы писали:

Y>Помню. Но здесь
Автор: Sinclair
Дата: 07.04.22
говорится следующее:

Y>

Y>400 означает, что неверны не вообще любые аргументы чего угодно, а конкретно аргументы, переданные клиентом.
Y>То есть хэндлер рест-апи должен проверить аргументы, и только если они в порядке, ехать дальше.
Y>Исключения за пределами первичной валидации — это уже 500.

Там речь идёт именно об ArgumentException.

Y>В самом начале речь шла об ArgumentException. Такое исключение может прийти и из глубин бизнес-логики, много позже первичной валидации, и оно может быть связано с ошибкой клиента.

А может быть и не связано. Всё, что мы знаем, поймав ArgumentException — то, что какому-то методу не понравился аргумент. Например, у нас поломалась конфигурация, и куда-то вместо сертификата приехал null, вызвавший ArgumentNullException.

Вот для того, чтобы не гадать, что за аргумент и кем был забракован, и нужно выделять проверку аргументов метода контроллера в отдельную фазу.
Либо сразу же обучать те методы, которые будут бросать исключения на более поздних фазах, выбрасывать не ArgumentException, а подходящий потомок HttpException.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: обработка ошибок
От: -n1l-  
Дата: 29.04.22 21:57
Оценка:
Здравствуйте, MadHuman,
если вы боитесь, что внутри вашей функции какие-то другие функции выкинут какой-то ArgumentException,
который не будет значить, что пользовательские данные некорректны, а будет иметь отношение к реализации тела вашей функции, то тогда хорошим способом будет
написать внутренний блок try-catch для вашей функции GetThing и полученный эксепшн обернуть во что-то другое.

типа

public object GetThing(UserInput input) {
    input = input ?? throw new ArgumentNullException("UserInput can not be empty.");
    try {
        return GetThingInternal(input.SubscriptionId, input.PromoCode, input.Card);
    }
    catch(Exception ex) {
        throw new InvalidOperationException("Subscription can not be renewed.", ex);
    }

}


Если этот путь не подходит, можно создать валидатор для данных и использовать этот валидатор перед тем как
отправлять ваши обьекты в модель. Сам валидатор прикрутить через middleware, так как речь идет о веб приложении.
Для таких валидаторов есть библиотечки типа fluentvalidation и куча примеров как их использовать.
Отредактировано 02.05.2022 14:15 -n1l- . Предыдущая версия .
Re[2]: обработка ошибок
От: vaa  
Дата: 30.04.22 01:41
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Здравствуйте, MadHuman,

N>если вы боитесь, что внутри вашей функции какие-то другие функции выкинут какой-то ArgumentException,
N>который не будет значить, что пользовательские данные некорректны, а будет иметь отношение к реализации тела вашей функции, то тогда хорошим способом будет
N>написать внутренний блок try-catch для вашей функции GetThing и полученный эксепшн обернуть во что-то другое.

N>типа


N>
N>public object GetThing(UserInput input) {
N>    input = input ?? throw new ArgumentNullException("UserInput can not be empty.");
N>    try {
N>        return GetThingInternal(input.SubscriptionId, input.PromoCode, input.Card);
N>    }
N>    catch(Exception ex) {
N>        throw new InvalidOperationException("Sabscription can not be renewed.", ex);
N>    }

N>}
N>


N>Если этот путь не подходит, можно создать валидатор для данных и использовать этот валидатор перед тем как

N>отправлять ваши обьекты в модель. Сам валидатор прикрутить через middleware, так как речь идет о веб приложении.
N>Для таких валидаторов есть библиотечки типа fluentvalidation и куча примеров как их использовать.

А почему бы UserInput не валидировать данные в конструкторе?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: обработка ошибок
От: -n1l-  
Дата: 30.04.22 09:28
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>А почему бы UserInput не валидировать данные в конструкторе?


Я предполагаю что конструктор там так просто не напишешь, так как данные приходят ввиде какого-то json документа,
который десериализуется System.Text.Json или Json.net и уже по факту создания класса записывает данные.

Ну и такая валидация может различаться в зависимости от конкретной функциональности системы, это некая бизнес валидация, а не просто валидация параметров,
так что я бы использовал fluent validator или делал для этого отдельный класс как минимум.
Re[3]: обработка ошибок
От: Ночной Смотрящий Россия  
Дата: 02.05.22 12:27
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>А почему бы UserInput не валидировать данные в конструкторе?


В конструкторе имеет смысл валидировать только вещи, не зависящие от внешнего контекста.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: обработка ошибок
От: MadHuman Россия  
Дата: 02.05.22 13:56
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>типа


N>
N>public object GetThing(UserInput input) {
N>    input = input ?? throw new ArgumentNullException("UserInput can not be empty.");
N>    try {
N>        return GetThingInternal(input.SubscriptionId, input.PromoCode, input.Card);
N>    }
N>    catch(Exception ex) {
N>        throw new InvalidOperationException("Sabscription can not be renewed.", ex);
N>    }

N>}
N>


хороший вариант. спасибо за идею!
Re[12]: обработка ошибок
От: Mystic Artifact  
Дата: 06.05.22 19:39
Оценка: +1 :)
Здравствуйте, Ночной Смотрящий, Вы писали:

Ничего подобного, за годы тема подробнейшим образом изучена но по прежнему дисскуссионнная.

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

Во всех остальных случаях это — осознанное снижение качества кода, а неосознанное использование исключений (например как весь System.IO из .net 1) ведет к тяжелым проблемам сопровождения или дизайна (проблемы не в том смысле, что оно плохо, а в смысле — что это всегда компромисс, который лежит на ваших плечах). Есть области, на подобии как тут обсуждается (веб-сервер, процессинг) где такая модель во благо, но плюньте в сторону и это уже совсем не так.

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

В добавок, вы упускаете из вида, что правильная программа всегда делает валидные вызовы (в идеальном мире ессно — в реальном мире для этого надо очень постараться), вне зависимости от поданных значений на её вход. Т.е. в рамках дисскуссии — номер счета который совсем не похож на него, — это часть БЛ. Это штатная ситуация и места исключениям в подобных вопросах в общем случае нет.

Но, я не хочу быть не правильно понятым: исключения — отличная концепция, в добавок присутствует почти во всех языках, хоть компилируемых, хоть скриптовых. Просто их нужно крайне аккуратно использовать и быть готовым мириться с гетерогенной природой некоторых исключений. У меня искаженное их восприятие, потому, что, я регулярно вижу отвратительные способы их использования (не тут), и в основной массе работаю с кодом без исключений (C++). Но по моим наблюдениям, средний код ничего не потеряет если не будет их использовать даже на C#. Ну а с точки зрения перфоманса, то т.н. "zero-cost exceptions" — они зеро только по отношению к setjmp, а так, они всегда хуже кода на кодах ошибок. Протаскивание кодов на верх — это такой миф. Ну и конечно же просто рекорды от души пороть в C# (не струкуры) — это хуже чем исключения, надо бить по рукам ногами за такое.

PS: Мне можно не отвечать. Это просто мое мнение. Я отвечать не буду. Я даже читать не буду. Я за 2 месяца зашел сюда впервые.
Отредактировано 06.05.2022 19:40 Mystic Artifact . Предыдущая версия .
Re[3]: обработка ошибок
От: yenik  
Дата: 08.05.22 08:21
Оценка:
N>> input = input ?? throw new ArgumentNullException("UserInput can not be empty.");
N>> throw new InvalidOperationException("Sabscription can not be renewed.", ex);

Не могу пройти мимо и не протянуть руку пoмoщи!
И да будет милостив модератор.

can not cannot
Sabscription Subscription
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.