Почти в любой системе количество входных данных таково, что полный перебор всех возможных вариантов никогда не закончится. И рандомизация (особенно, если она с учётом граничных значений, coverage guided, и так далее) может тестировать новые и новые данные с каждым запуском. Всех случаев не проверишь но 1-5 минут рандома на каждый pull request и рано или поздно ошибка найдётся.
В Java language specification отдельно описано, что if (false) это годный код, и компилятор не должен ругаться на его недостижимость: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21
Думаю, ни там ни там не надо. Разумеется, "правильного ответа" тут нет, и как партия решит, так пусть и будет. Но я всё равно думаю, что подкрашивать условие if(false) это странно. Вполне нормально взять и написать while(false), if(false) и т.п. для отладки. Если оно более блеклым цветом отметит "никогда не выполняющиеся ветки кода", то это другой разговор. А подкрашивать "if(false) is always false" -- ну, зачем?
Не, объявить val debug=false и бранчеваться -- самая тема. Поэтому, да, соглашусь, что ругаться на if (debug) не стоит. Поэтому же и считаю, что ругаться на if (false) не должно. Тут же по-человечески написано false. Зачем лишний раз сообщать, что "condition is always false"? :)
Тема статьи какая? "Вот нормальный код, анализатор пытался его обругать, но не надо было". А тут смотришь -- и между строк написано "тут должно было быть isNullOrEmpty".
Я другое спрошу (213.4631.20, 6 October). Почему на if (false) ругается, что "condition is always false", а на val x = false; if (x) уже нет? Бага получается? Я бы на if (false) и if (true) не ругался.
Ну представь, что там исключение кидается. Лучше будет?
Исключение прекрасно кинется в when else ветке. Ну, тут я полностью соглашусь, что корень проблемы не в "expression is always true", а в том, что тут возникло дублирование логики, и, вполне возможно, это дублирование следует убрать, чтобы перечни статусов не разошлись (ну, вдруг добавят ветку в when, а if забудут поправить?). Но, если бы у меня в том when "low" возникло предупреждение "condition is always true", то я бы порадовался и сказал: "а, действительно, как так получилось, что always true" и пошёл бы и убрал if или что там.
А смысл? Предупреждения должны нести смысл. Если над каждым придётся думать, то смысла в них никакого не будет. Так-то в каждой строке можно предупреждение придумать: "вы точно уверены, что тут переменная x, а не y?"
Возможно, что 99.42% всех таких примеров сведутся к тому, что незачем там return внутри let использовать, и оно должно ругаться словами "убирайте return" или "убирайте let"
Например, перед when могло быть общее действие, которое надо сделать для всех трёх вариантов. Давай что-нибудь добавлю
По-моему, всё равно if лишний. Убрать бы его. Получается, кто-то там может слать недопустимые значения, а мы их игнорируем. Конечно, так и до enum недалеко додуматься, но вопросы остаются.
Если уже 25 вызовов с одним значением ignoreCase, то пора extract method делать.
Разумеется, я поддерживаю, что ругаться должна инспекция "вы тут зря переменную завели, воспользуйтесь лучше именованными параметрами", а не "expression is always true", просто исходно код выглядит стрёмно, и зачастую ожидаемо, что анализатор будет что-то там бурчать, особенно, когда код стрёмный.
Пример про isOption, конечно, нужно вообще без return записывать. Там ни return ни let не нужно: `isOption(s: String?) : Boolean = s?.startsWith("--") ?: false`. Ну или на String.isOption переделать (но это уже от проекта зависит)
А зачем в updatePriority примере нужен был if? Если его убрать, то станет проще читаться и будет проще поддерживать (не придётся дублировать литералы). Правильно оно ругалось на код, по делу.
command.startsWith("--data", ignoreCase) -- тоже по делу ругалось. Если хочется пояснить ignoreCase, то почему бы не использовать для этого именованные параметры? Зачем переменную объявлять? Вот так хорошо: command.startsWith("--data", ignoreCase = true)
Например, в Oracle DB курсоры без проблем переживают операцию commit и продолжают возвращать согласованные данные. Можно открыть курсор, сделать commit (или несколько) и без проблем продолжать выборку из курсора. Разумеется, у долгих курсоров есть шанс наткнуться на ORA-01555 snapshot too old, но это другая история.
Разработчики PostgreSQL почему-то посчитали, что, если транзакцию закрываем, то и курсоры нужно обязательно закрыть. При этом, фиксация транзакций в параллельных потоках никак не влияет.
Типичный подход в Oracle мире для batch обработки: открываем курсор, выбираем 10'000 записей. Обрабатываем, меняем данные, выполняем commit. Выбираем следующие 10'000 (операцией fetch bulk collect into… limit 10000) и так далее. Это позволяет не выполнять выборку каждый раз с нуля, и «выбирающий» курсор не протухает. В PostgreSQL такой подход не работает.
"6. Рандомизация в тестах". Вам там property-based testing https://en.m.wikipedia.org/wiki/Software_testing#Property_testing и фаззинг https://ru.m.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B7%D0%B7%D0%B8%D0%BD%D0%B3 показывают, а вы отнекиваетесь, что "не надо писать рандомизированные тесты". Надо. Надо их писать. Вот пример с недавнего Гейзенбага: https://youtu.be/fbhuzSpyUJc.
Почти в любой системе количество входных данных таково, что полный перебор всех возможных вариантов никогда не закончится. И рандомизация (особенно, если она с учётом граничных значений, coverage guided, и так далее) может тестировать новые и новые данные с каждым запуском. Всех случаев не проверишь но 1-5 минут рандома на каждый pull request и рано или поздно ошибка найдётся.
Если Котлин, то при чём тут Си?
На самом деле, статья и начинается со слов, что в Java анализатор уже написан и отлажен, поэтому с Java сравнивать логично.
Если код закомментировать, то он может перестать компилироваться, поэтому if false зачастую лучше, чем комментирование кода
В Java language specification отдельно описано, что if (false) это годный код, и компилятор не должен ругаться на его недостижимость: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21
Думаю, ни там ни там не надо. Разумеется, "правильного ответа" тут нет, и как партия решит, так пусть и будет. Но я всё равно думаю, что подкрашивать условие if(false) это странно. Вполне нормально взять и написать while(false), if(false) и т.п. для отладки. Если оно более блеклым цветом отметит "никогда не выполняющиеся ветки кода", то это другой разговор. А подкрашивать "if(false) is always false" -- ну, зачем?
Не, объявить val debug=false и бранчеваться -- самая тема. Поэтому, да, соглашусь, что ругаться на if (debug) не стоит. Поэтому же и считаю, что ругаться на if (false) не должно. Тут же по-человечески написано false. Зачем лишний раз сообщать, что "condition is always false"? :)
"condition is always false". И quick-fix там -- "delete expression"
Хотя посмотрел на Java -- там if (false) ругается (почему бы?). Наверное, если уж делать, то однообразно.
Тема статьи какая? "Вот нормальный код, анализатор пытался его обругать, но не надо было". А тут смотришь -- и между строк написано "тут должно было быть isNullOrEmpty".
Я другое спрошу (213.4631.20, 6 October). Почему на if (false) ругается, что "condition is always false", а на val x = false; if (x) уже нет? Бага получается? Я бы на if (false) и if (true) не ругался.
Ты меня раскусил
Исключение прекрасно кинется в when else ветке. Ну, тут я полностью соглашусь, что корень проблемы не в "expression is always true", а в том, что тут возникло дублирование логики, и, вполне возможно, это дублирование следует убрать, чтобы перечни статусов не разошлись (ну, вдруг добавят ветку в when, а if забудут поправить?). Но, если бы у меня в том when "low" возникло предупреждение "condition is always true", то я бы порадовался и сказал: "а, действительно, как так получилось, что always true" и пошёл бы и убрал if или что там.
А смысл? Предупреждения должны нести смысл. Если над каждым придётся думать, то смысла в них никакого не будет. Так-то в каждой строке можно предупреждение придумать: "вы точно уверены, что тут переменная x, а не y?"
Возможно, что 99.42% всех таких примеров сведутся к тому, что незачем там return внутри let использовать, и оно должно ругаться словами "убирайте return" или "убирайте let"
val empty = str?.isEmpty() ?: true if (!empty && str != null) { // 'str != null' is always true
Что только люди не напишут, лишь бы не делать по-простому (штатный механизм в stdlib): if (str.isNullOrEmpty()) { ... }
По-моему, всё равно if лишний. Убрать бы его. Получается, кто-то там может слать недопустимые значения, а мы их игнорируем. Конечно, так и до enum недалеко додуматься, но вопросы остаются.
Если уже 25 вызовов с одним значением ignoreCase, то пора extract method делать.
Разумеется, я поддерживаю, что ругаться должна инспекция "вы тут зря переменную завели, воспользуйтесь лучше именованными параметрами", а не "expression is always true", просто исходно код выглядит стрёмно, и зачастую ожидаемо, что анализатор будет что-то там бурчать, особенно, когда код стрёмный.
Пример про isOption, конечно, нужно вообще без return записывать. Там ни return ни let не нужно: `isOption(s: String?) : Boolean = s?.startsWith("--") ?: false`. Ну или на String.isOption переделать (но это уже от проекта зависит)
А зачем в updatePriority примере нужен был if? Если его убрать, то станет проще читаться и будет проще поддерживать (не придётся дублировать литералы). Правильно оно ругалось на код, по делу.
command.startsWith("--data", ignoreCase) -- тоже по делу ругалось. Если хочется пояснить ignoreCase, то почему бы не использовать для этого именованные параметры? Зачем переменную объявлять? Вот так хорошо: command.startsWith("--data", ignoreCase = true)
В Java 8+ лучше использовать
java.lang.Integer#remainderUnsigned
. И биты не теряем, и проблем с отрицательными значениями нет.папка / новая папка / новая папка (2)
?Например, в Oracle DB курсоры без проблем переживают операцию commit и продолжают возвращать согласованные данные. Можно открыть курсор, сделать commit (или несколько) и без проблем продолжать выборку из курсора. Разумеется, у долгих курсоров есть шанс наткнуться на ORA-01555 snapshot too old, но это другая история.
Разработчики PostgreSQL почему-то посчитали, что, если транзакцию закрываем, то и курсоры нужно обязательно закрыть. При этом, фиксация транзакций в параллельных потоках никак не влияет.
Типичный подход в Oracle мире для batch обработки: открываем курсор, выбираем 10'000 записей. Обрабатываем, меняем данные, выполняем commit. Выбираем следующие 10'000 (операцией fetch bulk collect into… limit 10000) и так далее. Это позволяет не выполнять выборку каждый раз с нуля, и «выбирающий» курсор не протухает. В PostgreSQL такой подход не работает.
Я почему-то считал, что это всё портировано и в 8
Это связанные события или нет?
Shenandoah разлива JDK 8/11 не хватает? Или в JDK13 есть что-то дополнительное?