Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
> Собственно задание заключается в написании функции, которая заменяет содержимое указанной строки этой же строкой, но с обратным порядком следования символов. Почему строка не переворачивается?
Бабушка Карлсона говорила: "Переодень носки, Карлсончик, переодень носки..."
Ну он и переодел: носок с левой ноги надел на правую, а с правой – на левую
(и обратно, если я верно прочитал код)
Собственно данная постановка задачи формулируется следующим образом: задание заключается в написании функции, то есть процедуры, возвращающей значение, на ЯП С++, которая модифицирует путем замены содержимое указанной пользователем компьютерной программы строки, то есть последовательности символов, заканчивающейся нулем, этой же самой, то есть исходной, строкой, но с обратным порядком следования однобайтовых символов типа char в строке. Почему строка не переворачивается?
Какие-нибудь временные файлы не удалятся. В большинстве прог похер, конечно.
Да, на топлевле удобно иметь кетч. Дождаться деструкторов, нормально залогировать ошибку и тогда уже сдохнуть. Без него просто выведет what() из экцепшена в stderr и terminate().
>В нормальном коде - никогда.
В нормальном коде вообще исключений быть не должно, во всяком случае в нормальном языке, лол. Исключение же это всегда бага
Совершенно нет. Возвращение результата заставляет программиста проверять, что ошибки нет, либо явно отказыватьсяот проверки (как чекд исключения), но при этом не засирает код.
псведоко
val fileRes = openFile()
when fileRes
is File -> fileRes.write('a')
is Error -> log.err(fileRes.errorMessage)
Клиенту вернулся эксепшн, который на его уровне не обрабатывается, он должен его прокинуть выше, в итоге у меня весь код обвешан Result'ами, не, ну его нахуй
Для этого есть сахар, позволяющий сделать проверку и вернуть наверх ошибку, завернув ее если нужно в соответствущий резулт
Зацени
fun askUserAndReadFileGood(): Result<Data, TopLevelException> {
val file = askUser()
return readDataFromFile(file).mapIfError { TopLevelException((it)) }
}
fun askUserAndReadFileDirty(): Data {
val file = askUser()
return readDataFromFile(file).successOr("This error will be thrown, app will die")
}
fun readDataFromFile(file: File): Result<Data, FileNotFoundException> {
}
Ну ты должен как-то сообщить компилятору, что ты можешь вернуть ошибку, так что сигнатура будет всегда страдать.
Или ты тоже считаешь, что компилятор ничего проверять не должен, и пускай умненький программист сам не забудет почитать доку, и поймать нужные исключения?
>в Йаже исключения говно, потому они везде говно
Бизнес логика на исключениях практически везде говно, но про свифт я вот почитаю чуть попожжа, и скажу)
> Ну короч, мы уже по третьему кругу пошли.
Подтверждаю, такова специфика срачей про исключения на ГК. Возникают рагулярно, имеют зацикленный характер.
>- у тебя то же самое будет, если метод бросает несколько не связанных между собой типов исключений
Верно.
>А ты кроме котлина и жабы что-то знаешь ещё?
во всех остальных кроме жабы известных мне языках исколючения не чекд. Сегодня я узнал, что в свифте они в некотором роде чекд)
В языках со статической типизацией строить логику на не чекд исключения плохо по причинам, которые я уже несколько раз описал: не существует способа статически проверить, что ты осмысленно отказался от проверки исключения или обработал его.
В C# вместо исключений иногда используют out параметры (в джаве и котлине так нельзя).
Так себе способ:
int number;
if (Int32.TryParse(value, out number))
{
// У нас число
} else //ну ты понел
В скриптушне логику строят иногда на исключениях (в джанге например) но там это пофиг: один хуй cpython ничего не проверяет "статически".
Давай я перефразирую свое утверждение:
В языках со статической типизацией, где компилятор проверяет код, и где нет чекд исключений (то есть это НЕ свифт и не джава) исключения не должны использоваться для нормального програм флоу, а должны только для ошибок в программах и оборудовании.
При выборе между резалтом с матчингом и чекд исключениям я отдаю предпочтение первому, потому что я вижу там больше сахара и больше гибкости, однако по уровню надежности решение свифта и решение с резалтом примерно одинаковы.
Если бы я писал на свифте, я бы конечно использовал его исключения с throws
Что плохого то? Крестовые исключения - это ж не SEH и не сигналы. Это вполне детерминированная хуйня, которая возникает только её явно вбросили в коде.
К примеру, кривого клиента можно просто дропнуть, поймав исключение от парсера пакетов. Всю прогу было бы глупо убивать из-за такой мелочи. А обрабатывать эту исключительную ситуацию по-сишному на каждом уровне - нафиг надо.
Если я вижу функцию "GetSomething()", то я обычно сразу проверяю, что она вернет. А вот догадаться, что какая-то функция вдруг может кинуть исключение -- сложно.
Проблему можно решить чекдами, но ты же и сам прекрасно знаешь почему это плохо
Возьми Свифт. Если функция бросает исключение, то её надо пометить как throws. Если ты её зовёшь внутри функции, которая сама НЕ бросает исключения, то такой вызов нужно обработать явно (у тебя три варианта на выбор, два хороших один харам).
Да, ты не указываешь список возможных исключений, но для этого есть дока, зато без обработки ты никуда не уйдёшь
1) обернуть вызов в do try catch
2) позвать с try?, где в случае исключения вернётся nil
3) (в большинстве случаев хуёвый вариант) сделать try!, который подавит необходимость проверять ошибку, линтер по умолчанию такое не пропускает
Ты просто сказал, что в «нормальном языке исключений быть не должно», на мой взгляд, это утверждение безосновательно.
Резалт есть и в Свифте, но это ж теорема Эскобара, да и нужен он имхо только для того, чтобы в замыканиях использовать, потому что замыкания это
Это похоже на то, что я предлагаю с резултом (у нас в котлине есть такой самописный резулт)
Функция возвращает тебе Result, у которого ты можешь:
1) проверить, что он success, и тогда взять результат
3) явно потребовать результат (если он не sucess, то всё упадет, ты сам дурак)
Варианта "2" (вернуть null если не success) у нас нет, но может стоит добавить)
Такой вариант кажется мне более удобным, чем исключения.
Впрочем, выбора у нас нет: в котлине нельзя никого заставить ничего ловить
Любая функция, не помеченная как noexcept, может кинуть исключение. Как минимум bad_alloc какой-нибудь.
Если среди них есть какие-то интересные, которые может захотеться обработать, то они обычно в доке перечислены. Если вернуться к сишке, то ты ведь не все варианты errno в каждой функции обрабатываешь. Ты обычно смотришь в доку и выбираешь пару-тройку. Либо тупо пробрасываешь всё подряд наверх, с чем исключения автоматически справляются.
>Любая функция, не помеченная как noexcept, может кинуть исключение.
Ты всем свом функциям пишешь noexcept, или явно перечисляешь все возможные исключения?
В сишке с интами тоже сделано не айс, но там я точно отличаю ошибку от не ошибки
Но лучше всего резулт и матчинг, как я выше написал
Компилятор не заставляет меня ничего ловить, я могу тупо проигнорить ошибку по причине распиздяйства, и всё упадет.
А в случае с матчинтгом я должен сделать это явно
Нахуя перечислять все возможные исключения? Перечисляю интересные, которые может захотеться обработать.
Ты ведь не делаешь в своём result отдельный enum под каждую функцию? Который содержит только те коды, которые она может вернуть. А скорее всего юзаешь один на всех.
Да. Но таких исключений очень мало. Большинство - это как runtime error в джаве, на содержание которых всем насрать кроме каких-то catch all обработчиков.
Перефразирую на результ коды - ты всем функциям перечисляешь все возможные варианты кодов, которые может захотеть обработать юзер?
Ну вот смотри: ты явно каждой функции пишешь noexcept, а пользователь вынужден это проверять. Если он забудет сделать catch функции без noexcept, то всё скомпилируется.
Это багор.
> ты всем функциям перечисляешь все возможные варианты кодов
В сишечке? нет, но я явно пишу какой код SUCCESS.
Забыть проверить результат тоже можно, но это реже случается, чем забыть проверить исключения.
Но я не защищаю сишечку, я пожалуй даже соглашусь что С++ исключения лучше сишных результов (во всяком случае у меня нет четкого мнения).
Я сообщаю вам, что лучше всех результ и матчинг. Там ты обязан проверить факт ошибки или явно от этого отказаться
Не бросил исключения - success. Бросил исключение - не success. Всё просто.
Никто никуда особо не смотрит. noexcept'ы это в основном намёк на то, что эту функцию можно безопасно юзать в деструкторах, при перемещении и ещё в нескольких местах. Остальной код всегда готов к пролёту исключения.
А твой матчинг засирает код проверками, не относящимися к логике. Это тот же самый чекед, только покороче. При этом, в отличие от чекеда, ты даже не знаешь какие там ошибки могут быть то. Иначе придётся ваять отдельный енум с ошибками на каждую функцию, а это боль.
>Ты же даже в своих примерах не посмотрел, какую ошибку ты ловишь.
Я знаю, что я получил ошибку, и могу дальше от этого отталкиваться. Могу посмотреть, какая ошибка. Могу не смотреть.
Важно, что прилетела ошибка, которую функция явно вернула.
На выбор я могу
1. сказать "мне плевать на ошибку, ее никогда не будет, а если будет то падай"
2. сказать "если ошибка, то сделай то-то"
3. сказать "если ошибка такая-то то.."
Причем выбрать я должен явно. А не бегать потом "ох блядь, оказывается эта функция могла ошибку кинуть, интересно как, я этого не ждал"
Вот всяко же тупо на рефлексах добавляете эти mapIfError и successOr не читая. Как то же явное подтверждение удаления файла в фаре, которое все на рефлексах энтером скипают.
Ну вот и с исключениями точно так же. Если я задумался о какой-то ошибке, которую полезно было бы обработать для удобства юзера, я пойду и почитаю что мне там могут вбросить. Если мне похуй - я не буду читать, catch all поймает, RAII всё лишнее закроет.
>Признайся, как часто ты смотришь.
Если это является частью логики, то смотрю.
Например, если мне пользователь передал имя файла, то я могу сообшить ему почему нет доступа к файлу
А если это имя файла зашито в програме, и файл там должен быть (потому что часть дистрибутива) то я делаю successOr
>Если я задумался о какой-то ошибке
Проблема в том, что компилятор не заставляет тебя задумываться "а может ли тут быть ошибка".
Есть функция "GetPetuh()", и ты сможешь узнать о том, что она вообще может кинуть исключение только если
* ты об этом задумался
* ты почитал доку
* автор не мудак, и написал доку
В случае же с резалтом у тебя тупо ничего не скомпилируется, пока ты явно не выберешь стратегию обработки ошибок.
Эффект примерно как и от чекд, но с гораздо меньшим количеством говна.
Компилятор должен пинать программиста, иначе программист что-нить забудет
Если в задаче не требуется что-то особым образом обрабатывать (тот самый файл из дистриба), то ты на рефлексах не читая воткнёшь политику по-умолчанию. Тебе похуй какую ошибку там возвращают и возвращают ли вообще.
> может кинуть исключение
Прими на веру, что любая функция в крестах может что-то кинуть. Любая. Кроме редких исключительных случаев, которые помечены как noexcept. Но они для особых ситуаций так помечены, а не для твоей логики.
Поэтому, если задача требует подавить или завернуть что-то от группы функций - лови всё, не ошибёшься.
Если нужно конкретное исключение - ну тут да, надо надеяться на доку. Но и с результами тебе могут generic хуйню вернуть по которой ничего не понятно.
>Вот! Не компилятор тебя пинает, а условие задачи!
И ты сообщаешь комплиятору "дорогой комилятор, я явно забиваю на исключение". Посредством двух символов.
Это позволяет тебе не пропустить ошибку там, где ты не имел ввиду ее забивать.
>Прими на веру, что любая функция в крестах может что-то кинуть. Любая.
Тогда я не понимаю как мне узнать кидает она что-то, что нужно ловить, или что не нужно.
Вот есть функция "Pay()" в классе "Bill". Откуда я знаю что она кидает или не кидает исключение? Только из доки?
И где гарантия, что она не начнет кидать что-то завтра?
Вчера она молча ничего не делала, если денег нет, а сегодня стала кидать "шорт оф фундс".
Вчера я вообще про это не думал.
А сегодня перекомпилировал, и всё работает. А семантика изменилась.
Поменять возвращаемое значение она не может (упадет компиляция) а вдруг начать кидать чот-то может.
Ну что значит не кидала? Сигнализировала об ошибке другим способом (возвращала пустую строку или нулл), а потом вдруг перестала это делать и перешла на исключения? Ну так и имя вместо фамилии можно вернуть и твоя система это не поймает.
Бери да бросай. Те, кто хотел обрабатывать ошибки, следовали принципу "любая функция бросает исключения" и обработали её. Те, кому было похуй - не обработали и у них она просто зафорвардится дальше по стеку.
>ледовали принципу "любая функция бросает исключения"
и каждую функицю заворачивали в try catch чтоли?
Сравним со свифтом (в пизду джаву, ее никто не любит)
Там я бы добавил throws, иу них бы не скомпилировались
Им пришлос бы или явно заткнуть ошибку, или обработать ее
Разве это не лучше?
--------
Если что-то можно выразить статически, то лучше выразить это статически. Чтобы это мог проверить компилятор. Чтобы код можно было статически валидировать. Если это добавляет бойлерплейт, то значит нужно такой сахар сделать, чтобы его было по минимуму.
Например auto позволяет уменьшить бойлерплейт но сохарнить стат типизацию.
Мои резулты позволяют уменьшить бойлерплейт (на мой вкус) но сохранить валидацию обработки ошибок
Статическую валидацию
Если они хотели обрабатывать ошибки от конкретных функций - да, заворачивали их в трай. Если им было похуй и хотелось просто зафорвардить ошибку выше - вообще ничего не делали.
> Если что-то можно выразить статически, то лучше выразить это статически.
Так можно и до кока с агдой докатиться. Нужен какой-то разумный баланс, чтобы статические проверки ловили реальные проблемы, которые в коде встречаются часто и имеют хуёвые последствия.
От пропущенной проверки на нулл или еррор код в сишном коде ты получишь UB. Это происходит часто и заканчивается очень плохо. Поэтому исключения или твой матчинг приносят очень много пользы по сравнению с их отсутствием.
От непойманного исключения юзер в большинстве случаев просто увидит "неизвестную ошибку" вместо более полезного сообщения. Поэтому матчинг приносит не так много пользы по сравнению с исключениями.
>реальные проблемы, которые в коде встречаются часто и имеют хуёвые последствия.
У меня были реальные проблемы. Мы резулт свой запилили не на пустом месте, а именно потому, что хотели заставить клиента API что-то внятное сделать с ошибкой.
Может быть у нас с тобой разные юзкейсы просто.
У тебя быавала большая рыхлая плохо документированная кодовая база, где куча питухов чото понаписала?
У меня вот была, и от нее хочется наручников и плёт максимально строгого компилятора.
Если бы мы не сделали резулт, то питухи кидали бы рантайм исключения и не документировали бы их (потому что никто нкиогда не пишет доки!) или вообще возвращали бы null (а ошибка бы терялась)
>От непойманного исключения юзер в большинстве случаев просто увидит "неизвестную ошибку
Ну лучше же узнать об ошибке во время компиляции, чем от пользователя, верно?
Чувак обновил себе ось на телефоне, ему от вендора прилетела новая версия некого фреймворка, теперь пока я не перекомпилирую приложение, то предыдущая версия должна просто крашиться?
Это немножко не так работает
Хорошо, когда язык позволяет хендлить такие ситуации. А, если нет, то у тебя такая же жопа, как с новыми исключениями. Компилятор не волшебник, будь добр, почитай доку и адаптируй
> то предыдущая версия должна просто крашиться
Нет конечно. Должна остаться и старая, и новая версия библиотеки.
В старой версии библиотеки метод принимал два параметра, а в новой три. Нужно две версии библиотеки, иначе нихуя не взлетит. Или два метода: старый и новый, ну и два класса тоже соответственно
>А, если нет, то у тебя такая же жопа, как с новыми исключениями.
почему недопустимая? Методы депрекейтяд, удаляют итд.
С енумом тоже самое: если ты добавил новое значение, которое человек не умеет обрабатывать, то у него просто не выберется ветка, и всё упадет. Так пусть лучше сразу упадет с криком "не верный енум", чем упадет потом потому что кодфлоу нарушен
Добавление тоже очень часто breaking change. Вот добавлю я метод в интерфейс, для которого ты делал реализацию.
Добавление в енум тоже очень часто пидорасит логику, поэтому это почти всегда breaking change. Я сам на это много раз налетал. Даже буквально на днях, лол.
Программа стала работать НЕВЕРНО: она стала врать, что письмо отправлено. А оно не отправлено. И это пиздец.
Как же быть?
1. Заставить пользователя всегда делать else. Но тогда вы же сами меня с говном съедите за засирание кода ненужным else. Особенно смешно, если я рядом определил enum, и тут же вынужден писать else для того, чего никогда не будет.
2. Заставлять енум всегда быть экзастив или иметь else.
Тогда код без Каруши не скомпилируется.
Или перечисляй явно всех, или пиши else
И так, у нас есть два вида енума:
* Frozen. Мы гарантируем, что в него никогда не будет добавлен новый элемент.
* Open. Мы НЕ гарантируем такого.
Для frozen программист обязан(!!) либо проверить ВСЕ варианты либо ЯВНО сделать default. Если он этого не сделает -- будет ошибка компиляции (ну пока ворнинг, но в будущем будет ошибка).
Для unknown программист обязан(!!) обработать случай неизвестного ему значения.
Для этого он обязан добавить defaullt.
Причем default бывает двух видов:
* обычный default значит "я готов нормально обработать все не описанные значения, как новые, так и те, которые я просто не указал"
* unknown default значит "я хочу обработать все значения, но если добавятся новые значения, то я не хочу падать, но хочу ворнинг при компиляции"
При добавлении нового значения я получу ворнинг если будет unknown, и после перекомпиляции увижу проблему, и добавлю значение, но до этой поры я все еще буду работать.
Звучит логично. Свифтовцы вообще молодцы, хочу такое в котлине.
Since the proposal was accepted months after it was written, the rollout plan turned out to be a little too aggressive. Therefore, in Swift 5 the diagnostic for omitting @unknown default: or @unknown case _: will only be a warning
Но старые бинари с новыми всё равно мешать нельзя, даже если проверка в конпеляторе. Тут только версию бампать и говорить, что обратной совместимости больше нет.
Ну почему. Вот есть у меня SDK 1.0 и SDK 1.1, в котором какие-то новые интерфейсы или методы добавили. Прога, которую я собирал под 1.0 вполне будет работать под 1.1.
тоесть мало того, что бойлерплейт и вынос строчки (!) в отдельную функцию (и эти люди смеются над вербозностью резулта!), так еще и в случае добавления Каркушки программа будет просто молча ничего не делать?
Збс
>Откуда возьмется каркуша,
Видимо ты забыл, с чего начался тред.
Программу скомпилировали без каркуши. А запускают ее с новой версией либы, где каркуша уже есть.
Программа работает неверно. Потому что добавление каркуши в енум это брекинг чендж.
Я пытался это показать.
Это такой же брекинг чендж, как семантику метода поменять.
пользователю от этого ни горячо, ни холодно. Он запустил программу, и она молча ничего не сделала. Она не работает. С таким же успехом она могла упасть.
во-первых мы сейчас не про продуктовые требования. ты прыгаешь на другой уровень.
во-вторых вопрос появления каркуши по-прежнему неясен. если он запускает конечную программу, то её там по-прежнему нет, потому что как она попадет в программу, которая не знала о символе компайл-тайм?
если это промежуточная библиотека, то тут вопрос, почему конечный продукт использует нерабочие зависимости
>ты прыгаешь на другой уровень.
Я на том же самом уровне: в общем случае невозможно обеспечить корректную работу программы при добавлении записи в enum. Добавление записи в енум это брейкинг чендж в общем случае
>во-вторых вопрос появления каркуши по-прежнему неясен.
Программа скомпилирована с версией 1.0, где ее не было.
А запускается с версией 2.0, где она есть.
Откуда взялось значение?
На выбор:
* ввел пользователь (при вводе значения, отсутствующего в enum, выдается ошибка: SpokNochi.fromString(string))
* пришла по сети
* пользователь выбрал из выпадаюещго меню, которое предлагает библиотека
> Я на том же самом уровне: в общем случае невозможно обеспечить корректную работу программы при добавлении записи в enum.
Да ну хорош увиливать уже. Мы про техническую корректность, а не про продуктовый уровень. Продуктовый уровень вообще не знает про библиотеки-хуеки.
> * ввел пользователь (при вводе значения, отсутствующего в enum, выдается ошибка: SpokNochi.fromString(string))
Пользователь пытается вызвать несуществующий функционал программы
> * пришла по сети
Аналогично
> пользователь выбрал из выпадаюещго меню, которое предлагает библиотека
Вообще да, но я ни разу не видел, чтобы библиотека моделей строила за меня выпадающее меню.
> техническую корректность, а не про продуктовый уровень.
Мне неизвестны такие понятия. Программа либо работает в соответствии с ТЗ, либо нет.
Если она нарушает ТЗ (не важно -- падает или молча ничего не делает) то значит она сломана.
В инструкции к программе сказано: "Пользователь вводит имя персонажа. Если пользователь вводит неверные данные, то он должен получить сообщение об ошибке". В примере с enum он его не получает.
Программа ведет себя неверно. Она сломана.
Если бы она упала в рантайме, то было бы даже лучше, чем просто ничего не сделала
Это вполне допустимая ситуация. Инкрементишь мажорную версию либы, ломаешь всё что можно сломать и оставляешь старую копию сайд-бай-сайд для старого софта.
ну ты можешь в тупл засунуть 2 переменных разного типа (кресты давно умеют)
только ничего не выиграешь, т.к. тебе надо tmp менять на каждой итерации, ты ошибочно предположил, что только при инициализации цикла
а раз надо на каждой итерации, то что экономить собрался? строки кода? значит, в другом месте их проиграешь
и да, int хуевый тип для хранения "размера"
а схема tmp = a; a = b; b = tmp; не для каждого типа Т адекватна (оптимальна или вообще компилируема)
именно поэтому алгоритмы в стл используют using std::swap; swap(a, b);
в надежде, что ты перегрузишь, компилятор найдет в твоем неймспейсе, или не найдет, тогда в std:: найдет
Рыба моя, уже в которй раз ты постишь топики на сях, самодовольно заканчивая их с постскриптумом 'какой багор)))'. Не приходило ли тебе в головочку, что не все знают сях? Ты бы хоть на паскаль перевёл, сделал одолжение, уважил народ.
Лично для меня твой пост выглядит как бред психбольного. ничего личного.
MAKAKA # 0
Ну он и переодел: носок с левой ноги надел на правую, а с правой – на левую
(и обратно, если я верно прочитал код)
AHCKujlbHblu_netyx # 0 ⇈
oaoaoammm # 0
bormand # 0 ⇈
З.Ы. Учись юзать отладчик или логи писать.
oaoaoammm # 0 ⇈
defecate-plusplus # 0 ⇈
bormand # 0 ⇈
А что там кроме bad_alloc в конструкторе может быть?
MAKAKA # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
алсо, я верно понимаю, что любой код с конструктором всегда надо оборачивать на топлевеле в кетч?
bormand # 0 ⇈
Да, на топлевле удобно иметь кетч. Дождаться деструкторов, нормально залогировать ошибку и тогда уже сдохнуть. Без него просто выведет what() из экцепшена в stderr и terminate().
defecate-plusplus # 0 ⇈
bormand # 0 ⇈
Майки, кстати, этим страдают в комовских обёртках. Хотя ошибку освобождения памяти надо ещё умудриться вызвать.
AHCKujlbHblu_netyx # 0 ⇈
HoBorogHuu_nemyx # 0 ⇈
bormand # 0 ⇈
AHCKujlbHblu_netyx # 0 ⇈
MAPTbIwKA # 0 ⇈
В нормальном коде вообще исключений быть не должно, во всяком случае в нормальном языке, лол. Исключение же это всегда бага
Desktop # 0 ⇈
Если у тебя в языке легковесные исключения, то в чём проблема их использования?
Да даже если и не легковесные
MAPTbIwKA # 0 ⇈
Тогда их надо делать checked, а это довольно неудобно, джависты вон страдают.
А не чекд эксепшен для логики это пиздец, потому что не понятно что откуда и когда вылетет.
Самое нормальное это возвращать резулт (наверное это называется "монада") и потом его паттеринг матчить
Desktop # 0 ⇈
- сорта говна
MAPTbIwKA # 0 ⇈
псведоко
Предложи более красивый вариант решения
Desktop # 0 ⇈
?
Я ебал такое
MAPTbIwKA # 0 ⇈
клиент может потом сам матчить нужный ему эррор
Desktop # 0 ⇈
Клиенту вернулся эксепшн, который на его уровне не обрабатывается, он должен его прокинуть выше, в итоге у меня весь код обвешан Result'ами, не, ну его нахуй
MAPTbIwKA # 0 ⇈
Зацени
Desktop # 0 ⇈
И что поменялось?
MAPTbIwKA # 0 ⇈
Вот проблему "обвешан трай кетчем" я понимаю.
Вместо
я вынужден писать
Причем даже если я не хочу ее обрабатывать, я все равно обязан ее ловить.
Такой вариант как askUserAndReadFileDirty с чекд исключениями не сделать
Desktop # 0 ⇈
А у тебя вообще получается типа такого: в Йаже исключения говно, потому они везде говно
А это не так
guest # 0 ⇈
Или ты тоже считаешь, что компилятор ничего проверять не должен, и пускай умненький программист сам не забудет почитать доку, и поймать нужные исключения?
>в Йаже исключения говно, потому они везде говно
Бизнес логика на исключениях практически везде говно, но про свифт я вот почитаю чуть попожжа, и скажу)
Desktop # 0 ⇈
> умненький программист не забудет поймать нужные исключения
- ты ж сам написал, что в котлине никто не может заставить тебя ничего ловить, так котлин всё же говно или?
MAPTbIwKA # 0 ⇈
На самом деле это значит
Result<PizdecType, Exception>
А потом клиент класса должен сидеть, и разбирать что именно пришло (или не разбиратьь, если не интересно).
В нашем варианте ты всегда должен указывать ошибку (кстати, это может быть и не исключение вовсе)
Было бы удобно иметь упрощенный синтаксис типа Result<PizdecType> где второй параметр это неявно Exception
>ты ж сам написал, что в котлине никто не может заставить тебя ничего лови
В котлине нет чекд ичключений: слово throws там нет (есть только для интеропа с жабой).
Так что использовать исключения для логики там вообще никак нельзя. Никто не заставляет тебя их ловить.
Ты сделал
var = vend()
А потом в продакшене у тебя упало "no enough funds".
и ты такой: "ой, а вот еще оказывается как могло быть, а я не подумал"
Desktop # 0 ⇈
- у тебя то же самое будет, если метод бросает несколько не связанных между собой типов исключений
Ну короч, мы уже по третьему кругу пошли. А ты кроме котлина и жабы что-то знаешь ещё?
gost # 0 ⇈
Подтверждаю, такова специфика срачей про исключения на ГК. Возникают рагулярно, имеют зацикленный характер.
Добрый вечер.
Desktop # 0 ⇈
guest # 0 ⇈
ты за исключения, за резулт с матчингом или за что?
gost # 0 ⇈
guest # 0 ⇈
MAPTbIwKA # 0 ⇈
Верно.
>А ты кроме котлина и жабы что-то знаешь ещё?
во всех остальных кроме жабы известных мне языках исколючения не чекд. Сегодня я узнал, что в свифте они в некотором роде чекд)
В языках со статической типизацией строить логику на не чекд исключения плохо по причинам, которые я уже несколько раз описал: не существует способа статически проверить, что ты осмысленно отказался от проверки исключения или обработал его.
В C# вместо исключений иногда используют out параметры (в джаве и котлине так нельзя).
Так себе способ:
В скриптушне логику строят иногда на исключениях (в джанге например) но там это пофиг: один хуй cpython ничего не проверяет "статически".
Давай я перефразирую свое утверждение:
В языках со статической типизацией, где компилятор проверяет код, и где нет чекд исключений (то есть это НЕ свифт и не джава) исключения не должны использоваться для нормального програм флоу, а должны только для ошибок в программах и оборудовании.
При выборе между резалтом с матчингом и чекд исключениям я отдаю предпочтение первому, потому что я вижу там больше сахара и больше гибкости, однако по уровню надежности решение свифта и решение с резалтом примерно одинаковы.
Если бы я писал на свифте, я бы конечно использовал его исключения с throws
bormand # 0 ⇈
MAPTbIwKA # 0 ⇈
ну в общем я к тому, что если к тебе прилетел исключень, то всё ОЧЕ плохо, и сдохнуть тут записав корку вполне допустимо.
Другой вопрос, что если ты демон, то тебе надо куда-то лог писнуть
bormand # 0 ⇈
К примеру, кривого клиента можно просто дропнуть, поймав исключение от парсера пакетов. Всю прогу было бы глупо убивать из-за такой мелочи. А обрабатывать эту исключительную ситуацию по-сишному на каждом уровне - нафиг надо.
MAPTbIwKA # 0 ⇈
Лучше тогда возвращать код ошибки или указатель на структуру с данными, который может быть NULL если там ошибка.
Да и код выглядит симпатичнее и не создает ненужных скобочек, если проверять код ошибки.
bormand # 0 ⇈
Исключения нельзя забыть поймать, в худшем случае прога в терминейт уйдёт. А вот код возврата или нулл забыть обработать вполне возможно.
MAPTbIwKA # 0 ⇈
Проблему можно решить чекдами, но ты же и сам прекрасно знаешь почему это плохо
Desktop # 0 ⇈
MAPTbIwKA # 0 ⇈
Кстати, где они есть крмое джавы?
Desktop # 0 ⇈
Какие в сраку чекды.
Возьми Свифт. Если функция бросает исключение, то её надо пометить как throws. Если ты её зовёшь внутри функции, которая сама НЕ бросает исключения, то такой вызов нужно обработать явно (у тебя три варианта на выбор, два хороших один харам).
Да, ты не указываешь список возможных исключений, но для этого есть дока, зато без обработки ты никуда не уйдёшь
MAPTbIwKA # 0 ⇈
"помечать функции, которые throws" это чекд эксепшены в джаве
Расскажи подробнее как в свифте, кстати
Desktop # 0 ⇈
Я ж написал, как в свифте 🙂
Конкретизируй
MAPTbIwKA # 0 ⇈
>(у тебя три варианта на выбор, два хороших один харам
Алсо, заметь: тебя заставляют все таки как-то реагировать на исключения, да?
А в С++ нет. Обычно лучше когда компилятор следит за корректностью кода все таки
Desktop # 0 ⇈
2) позвать с try?, где в случае исключения вернётся nil
3) (в большинстве случаев хуёвый вариант) сделать try!, который подавит необходимость проверять ошибку, линтер по умолчанию такое не пропускает
Ты просто сказал, что в «нормальном языке исключений быть не должно», на мой взгляд, это утверждение безосновательно.
Резалт есть и в Свифте, но это ж теорема Эскобара, да и нужен он имхо только для того, чтобы в замыканиях использовать, потому что замыкания это
не будем о грустном
MAPTbIwKA # 0 ⇈
Функция возвращает тебе Result, у которого ты можешь:
1) проверить, что он success, и тогда взять результат
3) явно потребовать результат (если он не sucess, то всё упадет, ты сам дурак)
Варианта "2" (вернуть null если не success) у нас нет, но может стоит добавить)
Такой вариант кажется мне более удобным, чем исключения.
Впрочем, выбора у нас нет: в котлине нельзя никого заставить ничего ловить
bormand # 0 ⇈
Если среди них есть какие-то интересные, которые может захотеться обработать, то они обычно в доке перечислены. Если вернуться к сишке, то ты ведь не все варианты errno в каждой функции обрабатываешь. Ты обычно смотришь в доку и выбираешь пару-тройку. Либо тупо пробрасываешь всё подряд наверх, с чем исключения автоматически справляются.
MAPTbIwKA # 0 ⇈
Ты всем свом функциям пишешь noexcept, или явно перечисляешь все возможные исключения?
В сишке с интами тоже сделано не айс, но там я точно отличаю ошибку от не ошибки
Но лучше всего резулт и матчинг, как я выше написал
Компилятор не заставляет меня ничего ловить, я могу тупо проигнорить ошибку по причине распиздяйства, и всё упадет.
А в случае с матчинтгом я должен сделать это явно
bormand # 0 ⇈
Ты ведь не делаешь в своём result отдельный enum под каждую функцию? Который содержит только те коды, которые она может вернуть. А скорее всего юзаешь один на всех.
MAPTbIwKA # 0 ⇈
Ты всем свом функциям явно пишешь noexcept, или явно перечисляешь все возможные исключения, которые в теории может захотеть поймать пользователь?
bormand # 0 ⇈
Перефразирую на результ коды - ты всем функциям перечисляешь все возможные варианты кодов, которые может захотеть обработать юзер?
MAPTbIwKA # 0 ⇈
Это багор.
> ты всем функциям перечисляешь все возможные варианты кодов
В сишечке? нет, но я явно пишу какой код SUCCESS.
Забыть проверить результат тоже можно, но это реже случается, чем забыть проверить исключения.
Но я не защищаю сишечку, я пожалуй даже соглашусь что С++ исключения лучше сишных результов (во всяком случае у меня нет четкого мнения).
Я сообщаю вам, что лучше всех результ и матчинг. Там ты обязан проверить факт ошибки или явно от этого отказаться
bormand # 0 ⇈
Не бросил исключения - success. Бросил исключение - не success. Всё просто.
Никто никуда особо не смотрит. noexcept'ы это в основном намёк на то, что эту функцию можно безопасно юзать в деструкторах, при перемещении и ещё в нескольких местах. Остальной код всегда готов к пролёту исключения.
А твой матчинг засирает код проверками, не относящимися к логике. Это тот же самый чекед, только покороче. При этом, в отличие от чекеда, ты даже не знаешь какие там ошибки могут быть то. Иначе придётся ваять отдельный енум с ошибками на каждую функцию, а это боль.
guest # 0 ⇈
Тогда как они узнают какие ошибки ловить?
>А твой матчинг засирает код проверками
нет, если у тебя достаточно сахара
https://govnokod.xyz/_26918/#comment-555907
Никто не зставляет тебя ничего проверять, ты можешь отказаться от проверки, но ты должен сделать это явно.
Тут ты явно говориш: "мне результат, а иначе пускай всё упадет"
bormand # 0 ⇈
Именно это я и называю засиранием кода. Это абсолютно те же самые чекед экцепшены, только подсахаренные немножко чтобы скобок и траев поменьше писать.
MAPTbIwKA # 0 ⇈
>Именно это я и называю засиранием кода.
>. Это абсолютно те же самые чекед
Это примерно как сказать "слово auto это абсолютно тоже самое, что и явное указание типа и засирает код, толь дело питон".
Я уже привел пример того, что явный отказ можно сделать с помощью .success.
Можно сократить это до одной буквы, и будет еще проще
bormand # 0 ⇈
А зачем? Ты же даже в своих примерах не посмотрел, какую ошибку ты ловишь. Что-то там поймал, завернул и выбросил дальше.
MAPTbIwKA # 0 ⇈
Я знаю, что я получил ошибку, и могу дальше от этого отталкиваться. Могу посмотреть, какая ошибка. Могу не смотреть.
Важно, что прилетела ошибка, которую функция явно вернула.
На выбор я могу
1. сказать "мне плевать на ошибку, ее никогда не будет, а если будет то падай"
2. сказать "если ошибка, то сделай то-то"
3. сказать "если ошибка такая-то то.."
Причем выбрать я должен явно. А не бегать потом "ох блядь, оказывается эта функция могла ошибку кинуть, интересно как, я этого не ждал"
bormand # 0 ⇈
Признайся, как часто ты смотришь.
Вот всяко же тупо на рефлексах добавляете эти mapIfError и successOr не читая. Как то же явное подтверждение удаления файла в фаре, которое все на рефлексах энтером скипают.
Ну вот и с исключениями точно так же. Если я задумался о какой-то ошибке, которую полезно было бы обработать для удобства юзера, я пойду и почитаю что мне там могут вбросить. Если мне похуй - я не буду читать, catch all поймает, RAII всё лишнее закроет.
MAPTbIwKA # 0 ⇈
Если это является частью логики, то смотрю.
Например, если мне пользователь передал имя файла, то я могу сообшить ему почему нет доступа к файлу
А если это имя файла зашито в програме, и файл там должен быть (потому что часть дистрибутива) то я делаю successOr
>Если я задумался о какой-то ошибке
Проблема в том, что компилятор не заставляет тебя задумываться "а может ли тут быть ошибка".
Есть функция "GetPetuh()", и ты сможешь узнать о том, что она вообще может кинуть исключение только если
* ты об этом задумался
* ты почитал доку
* автор не мудак, и написал доку
В случае же с резалтом у тебя тупо ничего не скомпилируется, пока ты явно не выберешь стратегию обработки ошибок.
Эффект примерно как и от чекд, но с гораздо меньшим количеством говна.
Компилятор должен пинать программиста, иначе программист что-нить забудет
bormand # 0 ⇈
Вот! Не компилятор тебя пинает, а условие задачи!
Если в задаче не требуется что-то особым образом обрабатывать (тот самый файл из дистриба), то ты на рефлексах не читая воткнёшь политику по-умолчанию. Тебе похуй какую ошибку там возвращают и возвращают ли вообще.
> может кинуть исключение
Прими на веру, что любая функция в крестах может что-то кинуть. Любая. Кроме редких исключительных случаев, которые помечены как noexcept. Но они для особых ситуаций так помечены, а не для твоей логики.
Поэтому, если задача требует подавить или завернуть что-то от группы функций - лови всё, не ошибёшься.
Если нужно конкретное исключение - ну тут да, надо надеяться на доку. Но и с результами тебе могут generic хуйню вернуть по которой ничего не понятно.
guest # 0 ⇈
И ты сообщаешь комплиятору "дорогой комилятор, я явно забиваю на исключение". Посредством двух символов.
Это позволяет тебе не пропустить ошибку там, где ты не имел ввиду ее забивать.
>Прими на веру, что любая функция в крестах может что-то кинуть. Любая.
Тогда я не понимаю как мне узнать кидает она что-то, что нужно ловить, или что не нужно.
Вот есть функция "Pay()" в классе "Bill". Откуда я знаю что она кидает или не кидает исключение? Только из доки?
И где гарантия, что она не начнет кидать что-то завтра?
Вчера она молча ничего не делала, если денег нет, а сегодня стала кидать "шорт оф фундс".
Вчера я вообще про это не думал.
А сегодня перекомпилировал, и всё работает. А семантика изменилась.
Поменять возвращаемое значение она не может (упадет компиляция) а вдруг начать кидать чот-то может.
Какая-то прямо скриптушня по уровню безопасности.
bormand # 0 ⇈
Да, кидает. Если тебе нужно какие-то конкретные ошибки по-особому обработать - ну тут только на список в доке надежда.
MAPTbIwKA # 0 ⇈
Откуда знаешь?
А printf кидает?
А GetLength()?
А
?
А что будет, если вчера не кидала, а сегодня кидает? Я перекомпилируюсь, и ничего не замечу
bormand # 0 ⇈
guest # 0 ⇈
Я -- автор функции. Что мне делать?
bormand # 0 ⇈
guest # 0 ⇈
и каждую функицю заворачивали в try catch чтоли?
Сравним со свифтом (в пизду джаву, ее никто не любит)
Там я бы добавил throws, иу них бы не скомпилировались
Им пришлос бы или явно заткнуть ошибку, или обработать ее
Разве это не лучше?
--------
Если что-то можно выразить статически, то лучше выразить это статически. Чтобы это мог проверить компилятор. Чтобы код можно было статически валидировать. Если это добавляет бойлерплейт, то значит нужно такой сахар сделать, чтобы его было по минимуму.
Например auto позволяет уменьшить бойлерплейт но сохарнить стат типизацию.
Мои резулты позволяют уменьшить бойлерплейт (на мой вкус) но сохранить валидацию обработки ошибок
Статическую валидацию
bormand # 0 ⇈
bormand # 0 ⇈
Так можно и до кока с агдой докатиться. Нужен какой-то разумный баланс, чтобы статические проверки ловили реальные проблемы, которые в коде встречаются часто и имеют хуёвые последствия.
От пропущенной проверки на нулл или еррор код в сишном коде ты получишь UB. Это происходит часто и заканчивается очень плохо. Поэтому исключения или твой матчинг приносят очень много пользы по сравнению с их отсутствием.
От непойманного исключения юзер в большинстве случаев просто увидит "неизвестную ошибку" вместо более полезного сообщения. Поэтому матчинг приносит не так много пользы по сравнению с исключениями.
guest # 0 ⇈
У меня были реальные проблемы. Мы резулт свой запилили не на пустом месте, а именно потому, что хотели заставить клиента API что-то внятное сделать с ошибкой.
Может быть у нас с тобой разные юзкейсы просто.
У тебя быавала большая рыхлая плохо документированная кодовая база, где куча питухов чото понаписала?
У меня вот была, и от нее хочется наручников и плёт максимально строгого компилятора.
Если бы мы не сделали резулт, то питухи кидали бы рантайм исключения и не документировали бы их (потому что никто нкиогда не пишет доки!) или вообще возвращали бы null (а ошибка бы терялась)
>От непойманного исключения юзер в большинстве случаев просто увидит "неизвестную ошибку
Ну лучше же узнать об ошибке во время компиляции, чем от пользователя, верно?
bormand # 0 ⇈
Зависит от статистики на самом деле. Если это один багрепорт в год, а затыкать конпелятор придётся на каждом вызове функции, то я бы выбрал багрепорт.
Ну ок, если механизм решает реальную проблему - я не против.
Desktop # 0 ⇈
(в одном языке, который я не буду называть, это обошли на уровне собственно языка)
guest # 0 ⇈
Кстати, в котлине в IDE есть инспекция для тго, что бы ты или все проверил, или сделал else (defualt).
В хорошем матчинге тебя компилятор заставил бы проверить все значения
Fike # 0 ⇈
Desktop # 0 ⇈
А что бы мне дал компилятор, если у меня обновятся системные зависимости?
guest # 0 ⇈
Если ты скомпилировался с одним енумом, а работаешь с другим, то это пиздец всегда и везде.
С таким же успехмо в рантайме вообще может этого енума не оказаться.
Кстати, вот товарищ тоже этого хочет для sealed classes:
https://youtrack.jetbrains.com/issue/KT-12380
Было бы охуенно
Desktop # 0 ⇈
Чувак обновил себе ось на телефоне, ему от вендора прилетела новая версия некого фреймворка, теперь пока я не перекомпилирую приложение, то предыдущая версия должна просто крашиться?
Это немножко не так работает
Хорошо, когда язык позволяет хендлить такие ситуации. А, если нет, то у тебя такая же жопа, как с новыми исключениями. Компилятор не волшебник, будь добр, почитай доку и адаптируй
guest # 0 ⇈
Нет конечно. Должна остаться и старая, и новая версия библиотеки.
В старой версии библиотеки метод принимал два параметра, а в новой три. Нужно две версии библиотеки, иначе нихуя не взлетит. Или два метода: старый и новый, ну и два класса тоже соответственно
>А, если нет, то у тебя такая же жопа, как с новыми исключениями.
Совершенно верно. И это грустно.
Fike # 0 ⇈
это недопустимая ситуация со стороны мейнтейнеров библиотеки.
можно добавлять только новые фичи, и если появился новый енум, его значение должно обозначать то, чего раньше в принципе не было.
guest # 0 ⇈
С енумом тоже самое: если ты добавил новое значение, которое человек не умеет обрабатывать, то у него просто не выберется ветка, и всё упадет. Так пусть лучше сразу упадет с криком "не верный енум", чем упадет потом потому что кодфлоу нарушен
Desktop # 0 ⇈
Добавление - не всегда breaking change
А тебе надо реагировать и на то, и на то
bormand # 0 ⇈
Добавление в енум тоже очень часто пидорасит логику, поэтому это почти всегда breaking change. Я сам на это много раз налетал. Даже буквально на днях, лол.
guest # 0 ⇈
и-мен-но!
Это ровно то, что я показал в своем примере
MAPTbIwKA # 0 ⇈
gost # 0 ⇈
Desktop # 0 ⇈
guest # 0 ⇈
Смотри:
И тут внезапно завезли Каркушу.
Программа стала работать НЕВЕРНО: она стала врать, что письмо отправлено. А оно не отправлено. И это пиздец.
Как же быть?
1. Заставить пользователя всегда делать else. Но тогда вы же сами меня с говном съедите за засирание кода ненужным else. Особенно смешно, если я рядом определил enum, и тут же вынужден писать else для того, чего никогда не будет.
2. Заставлять енум всегда быть экзастив или иметь else.
Тогда код без Каруши не скомпилируется.
Или перечисляй явно всех, или пиши else
Desktop # 0 ⇈
guest # 0 ⇈
Мысленно поменяй в моем комменте слово "else" на "default"
Desktop # 0 ⇈
MAKAKA # 0 ⇈
И так, у нас есть два вида енума:
* Frozen. Мы гарантируем, что в него никогда не будет добавлен новый элемент.
* Open. Мы НЕ гарантируем такого.
Для frozen программист обязан(!!) либо проверить ВСЕ варианты либо ЯВНО сделать default. Если он этого не сделает -- будет ошибка компиляции (ну пока ворнинг, но в будущем будет ошибка).
Для unknown программист обязан(!!) обработать случай неизвестного ему значения.
Для этого он обязан добавить defaullt.
Причем default бывает двух видов:
* обычный default значит "я готов нормально обработать все не описанные значения, как новые, так и те, которые я просто не указал"
* unknown default значит "я хочу обработать все значения, но если добавятся новые значения, то я не хочу падать, но хочу ворнинг при компиляции"
При добавлении нового значения я получу ворнинг если будет unknown, и после перекомпиляции увижу проблему, и добавлю значение, но до этой поры я все еще буду работать.
Звучит логично. Свифтовцы вообще молодцы, хочу такое в котлине.
Desktop # 0 ⇈
- а где ты прочитал про ворнинг?
Вроде в Свифте switch must be exhaustive это всегда ошибка компиляции
MAKAKA # 0 ⇈
Since the proposal was accepted months after it was written, the rollout plan turned out to be a little too aggressive. Therefore, in Swift 5 the diagnostic for omitting @unknown default: or @unknown case _: will only be a warning
У фрозен буде ошибка?
Desktop # 0 ⇈
Но и свитч по обычному энаму без всяких модификаторов не взлетит, если все варианты не рассмотрены или нет default
error: switch must be exhaustive
note: add missing case: '.three'
guest # 0 ⇈
В общем это хорошо
Desktop # 0 ⇈
Но некоторые стайл-гайды рекомендуют явно указывать все варианты энама и дефолт в данном случае не использовать
bormand # 0 ⇈
Но старые бинари с новыми всё равно мешать нельзя, даже если проверка в конпеляторе. Тут только версию бампать и говорить, что обратной совместимости больше нет.
guest # 0 ⇈
Я не имею права скомпилитваться с SDK 1.0 и ожидать, что я буду работать с Runtime 3.0, если там явно не сделана обратная совместимость
В моем примере каркушу нужно добавлять в SpokNochi2, либо требовать от всех перекомпиляции с новой SDK, как модули ядра у прыщей
bormand # 0 ⇈
Ну почему. Вот есть у меня SDK 1.0 и SDK 1.1, в котором какие-то новые интерфейсы или методы добавили. Прога, которую я собирал под 1.0 вполне будет работать под 1.1.
guest # 0 ⇈
А если добавили каркушу, то ее порушили.
Это тоже самое, что сломать ABI. Считайте значения енума частью ABI
Fike # 0 ⇈
Но если представить, что она работает верно, то ее функционал не изменился: она как слала письма этим двоим, так и шлет. Её функционал не изменился.
guest # 0 ⇈
Fike # 0 ⇈
SpokNochi.HRUSHA -> sendToHrusha(); pacifyUser(),
SpokNochi.STEPASHKA -> sendToStepashka(); pacifyUser()
}
guest # 0 ⇈
Збс
Fike # 0 ⇈
Насчет вербозности - у меня бы там был либо враппер, либо отдельная система нотификаций по ивентам, но не писать же ее тут всю блэт
guest # 0 ⇈
Видимо ты забыл, с чего начался тред.
Программу скомпилировали без каркуши. А запускают ее с новой версией либы, где каркуша уже есть.
Программа работает неверно. Потому что добавление каркуши в енум это брекинг чендж.
Я пытался это показать.
Это такой же брекинг чендж, как семантику метода поменять.
Fike # 0 ⇈
guest # 0 ⇈
Fike # 0 ⇈
guest # 0 ⇈
Fike # 0 ⇈
во-вторых вопрос появления каркуши по-прежнему неясен. если он запускает конечную программу, то её там по-прежнему нет, потому что как она попадет в программу, которая не знала о символе компайл-тайм?
если это промежуточная библиотека, то тут вопрос, почему конечный продукт использует нерабочие зависимости
guest # 0 ⇈
Я на том же самом уровне: в общем случае невозможно обеспечить корректную работу программы при добавлении записи в enum. Добавление записи в енум это брейкинг чендж в общем случае
>во-вторых вопрос появления каркуши по-прежнему неясен.
Программа скомпилирована с версией 1.0, где ее не было.
А запускается с версией 2.0, где она есть.
Откуда взялось значение?
На выбор:
* ввел пользователь (при вводе значения, отсутствующего в enum, выдается ошибка: SpokNochi.fromString(string))
* пришла по сети
* пользователь выбрал из выпадаюещго меню, которое предлагает библиотека
Fike # 0 ⇈
Да ну хорош увиливать уже. Мы про техническую корректность, а не про продуктовый уровень. Продуктовый уровень вообще не знает про библиотеки-хуеки.
> * ввел пользователь (при вводе значения, отсутствующего в enum, выдается ошибка: SpokNochi.fromString(string))
Пользователь пытается вызвать несуществующий функционал программы
> * пришла по сети
Аналогично
> пользователь выбрал из выпадаюещго меню, которое предлагает библиотека
Вообще да, но я ни разу не видел, чтобы библиотека моделей строила за меня выпадающее меню.
guest # 0 ⇈
Мне неизвестны такие понятия. Программа либо работает в соответствии с ТЗ, либо нет.
Если она нарушает ТЗ (не важно -- падает или молча ничего не делает) то значит она сломана.
В инструкции к программе сказано: "Пользователь вводит имя персонажа. Если пользователь вводит неверные данные, то он должен получить сообщение об ошибке". В примере с enum он его не получает.
Программа ведет себя неверно. Она сломана.
Если бы она упала в рантайме, то было бы даже лучше, чем просто ничего не сделала
Fike # 0 ⇈
guest # 0 ⇈
Еще раз повторю эту часть
Если пользователь вводит неверные данные, то он должен получить сообщение об ошибке.
Fike # 0 ⇈
Fike # 0 ⇈
удалять депрекейт ты можешь только на смене мажорной версии как раз по причине этого
guest # 0 ⇈
Fike # 0 ⇈
Если обработка каждого поля обязательна - да.
Если добавляется идентификатор новой операции, которую может выполнять сервер - нет.
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
Desktop # 0 ⇈
Для информации
MAPTbIwKA # 0 ⇈
bormand # 0 ⇈
MAPTbIwKA # 0 ⇈
result.successOrDie
Fike # 0 ⇈
3_dar # 0 ⇈
AHCKujlbHblu_netyx # 0 ⇈
P.S: Мне всегда было занятно, как ты, Ильяс, дуришь людей, ведЯ диалоги С САМИМ СОБОЙ.
MAPTbIwKA # 0 ⇈
Я не вижу тут временных файлов
> В большинстве прог похер, конечно.
отож
Чем отличается "нормально залогировать" от "what() из экцепшена в stderr"?
Если ты демон, то я понимаю. А если ты комманд лайн, то не понимаю.
Кстати, это же заморочки вашего кресторантайма? Я думал, будет просто падение програмы в кору/доктор вацон
bormand # 0 ⇈
guest # 0 ⇈
Fike # 0 ⇈
MAPTbIwKA # 0
3_dar # 0 ⇈
AHCKujlbHblu_netyx # 0 ⇈
Кстати, с возвращением. Сегодня четвертое сентября две тысячи двадцатого года, пятница. Температура воздуха - +25, солнечно.
Desktop # 0
bormand # 0 ⇈
3_dar # 0 ⇈
defecatinho # 0 ⇈
admin # 0 ⇈
defecatinho # 0 ⇈
defecatinho # 0 ⇈
gost # 0 ⇈
admin # 0 ⇈
defecatinho # 0 ⇈
gost # 0 ⇈
defecatinho # 0 ⇈
admin # 0 ⇈
Sers # 0 ⇈
defecate-plusplus # 0 ⇈
только ничего не выиграешь, т.к. тебе надо tmp менять на каждой итерации, ты ошибочно предположил, что только при инициализации цикла
а раз надо на каждой итерации, то что экономить собрался? строки кода? значит, в другом месте их проиграешь
и да, int хуевый тип для хранения "размера"
а схема tmp = a; a = b; b = tmp; не для каждого типа Т адекватна (оптимальна или вообще компилируема)
именно поэтому алгоритмы в стл используют using std::swap; swap(a, b);
в надежде, что ты перегрузишь, компилятор найдет в твоем неймспейсе, или не найдет, тогда в std:: найдет
Desktop # 0 ⇈
а это выглядит как хуета
> int хуевый тип для хранения "размера"
- это к ОПу
cecilie # 0
Лично для меня твой пост выглядит как бред психбольного. ничего личного.