Комментарии 53
«В редакторе настоящего программиста должна отсутствовать функция копирования блоков [текста]» © Чарльз Мур (?) :)
Да, как люди только ни страдают лишь бы не использовать лисп^Wмакросы и ФП.
Не, серьезно, пора делать постинг ачивок в соцсетях: «30 дней без ошибок в последней строке», «Проект похвалили ребята из PVS-Studio».
Главное, что это не обидно будет, ачивка-то будет об отсутствии косяков, а не об их наличии!
А если серьезно, то крупным проектам прямо хорошим тоном было бы заказывать у вас проверку их трудов — может, вы и не 100% косяков выявите, но сторонним взглядом посмотрите, а то и других статьей научите, все же профит!
Главное, что это не обидно будет, ачивка-то будет об отсутствии косяков, а не об их наличии!
А если серьезно, то крупным проектам прямо хорошим тоном было бы заказывать у вас проверку их трудов — может, вы и не 100% косяков выявите, но сторонним взглядом посмотрите, а то и других статьей научите, все же профит!
Лучше бы, конечно, «ХХ дней без копипасты» :)
Риск получить нештатную ситуацию всегда выше в крайних точках, когда начинаешь и когда заканчиваешь. Я стараюсь про это не забывать в любом деле.
OpenSSL… Длина строки «BITLIST» не 3, а 7 символов...
Меня это настораживает — там уже где то был баг где длина буфера неправильная была :)
Меньше — не больше… Да и операция сравнения несколько безопаснее операции чтения блока памяти.
Эээ… А чем сравнение не чтение?
Ага, особенно прикольно сравнить меньше символов где-нибудь в checksum :-)
И понизить криптостойкость на несколько порядков.
И понизить криптостойкость на несколько порядков.
Глупый вопрос: как вообще это всё работает? Вы уже немало статей написали с явными ошибками. Не синтаксическими, а логическими. Если их ещё не исправили, значит они не заметны и программа вроде как работает. Почему? Ведь надёжность сложной системы, составленной из блоков, меньше, чем сумма надёжностей этих блоков?
Едет ли машина у которой не горят фары?
Весьма краткий и точный ответ. :)
Самое отвратительное даже не то, что она едет, а что если ездить только днём то даже не узнаешь, что с ней что-то не так.
В нормальных машинах есть индикаторы, которые оповещают водителя о проблемах, в том числе о перегоревших (не горящих) фарах. Такой же эффект принесут юнит-тесты в разрабатываемом приложении.
Наличие тестов тоже не гарантия: Как статический анализ дополняет TDD :).
А некоторые вещи вообще юнит-тестами поймать практически невозможно: V596, V597.
А некоторые вещи вообще юнит-тестами поймать практически невозможно: V596, V597.
Вот 596й не совсем правильный пример — хорошие тесты должны покрывать и «плохие» случаи тоже. Отсутствие искдючения -> тест провален.
А вот 597й да, плохо. При сборке тестов если проверять на чистоту на выходе — оптимизатор не выкинет memset; а в релизе может и выкинуть.
А вот 597й да, плохо. При сборке тестов если проверять на чистоту на выходе — оптимизатор не выкинет memset; а в релизе может и выкинуть.
На практике 596 покрыть крайне сложно и никто это не делает. Что-бы в нужный момент new кинул исключение, нужна целая система.
А как же «ни коммита без 100% покрытия»?
Это в параллельной вселенной. На практике, даже в те, кто стараются, обычно покрывают только 80%.
Кроме того, при желании не сложно обеспечить формально 100% (или близко к этому) покрытия тестами, которые по сути не особо полезны — то, что строчка кода выполнилась в процессе работы теста не даёт гарантии, что вся функциональность и все возможные случаи действительно были протестированы. Так что «покрытие» полезно только тем, что показывает какой код точно не тестируется, но ничего полезного не говорит про качество тестирования покрытого кода.
Что значит «в нормальных»? Где эта норма? Я повидал с десяток машин разной стоимости — от 300 тысяч до более миллиона. И только в одной есть датчик неработающих фар.
Веет дао :-)
По себе могу сказать — иногда просто везет. Например, по милости компилятора (или согласно своей-же крюкописи где-то в другом месте в коде) переменная, которой сам забыл присвоить значение (как, например, здесь: pattern->patternRepeatY = false;), уже содержит нужное значение. Ошибку-то ты потом сам находишь, но только по коду, а в работе программы она не проявляется. Вот так и живем. ))
А есть статистика, сколько ошибок происходит из-за копипасты по сравнению с прочими, в процентах от общего кол-ва? Хотя бы примерно.
Хорошо, что анализатора во времена Quake не было, иначе бы ни распрыжки, ни овербаунсов…
Это баги, а не заложенная особенность физики? Про это где-то можно почитать?
Вроде бы сначала это были особенности реализации (непреднамеренные), а в последующих версиях такие вещи стали закладывать как фичу, потому что киберспортсмены и любители триксов (распрыжки и тд) привыкли.
Впервые распрыжка появилась в quake 2 как баг, но из-за того, что он сильно вошел в моду, в 3й части его сделали фичей. Другой баг — двойной прыжок (double jump) был «исправлен», однако появился новый — overbounce, ситуация, когда при столкновении с поверхностью вектор скорости отражался либо в противоположную сторону, либо в другую плоскость. Распрыжка была переполнением, в 2000х был блог у разработчиков промода, они там это описывали. Сейчас только гуглить остается.
Ну здрасте! Распрыжка появилась ещё в Quake I, а с физикой QuakeWorld получила всеобщее распространение. Самая круть была в Quake TF ворваться на базу врага разогнанным heavy guy с 300 красной броней на скорости в 1000 единиц и пролететь сквозь взрывающиеся поля и гранаты, забрать флаг и унестись к себе на базу =)
Я где-то слышал, что часто альпинисты срываются на последних десятках метрах подъема. Не потому, что они устали. Просто они радуются, что осталось совсем немного. Они предвкушают сладкий вкус победы над вершиной. В результате они ослабляют внимание и допускают роковую ошибку.
Я в Super Hexagon так играю. Проигрываю часто на плюс-минус 00:59.50 (там одна минута — «победа»).
ContainerEndLine != ContaineeEndLineЗа такие названия переменных нужно бить по рукам. Различие в одну букву в середине слова совершенно не видно при беглом чтении кода. Да что там, чтобы это заметить даже при внимательном чтении, мне пришлось сравнивать названия переменных побуквенно!
НЛО прилетело и опубликовало эту надпись здесь
Я сразу заметил разницу. Мне они даже не показались похожими.
P.S. Я много читаю и привык глотать слова целиком, всегда замечаю отличие даже в одну букву
P.S. Я много читаю и привык глотать слова целиком, всегда замечаю отличие даже в одну букву
Видимо, это код писал человек, подобный вам )
P.S. Я много читаю и привык глотать слова целиком, не замечая ошибок в одной букве…
P.S. Я много читаю и привык глотать слова целиком, не замечая ошибок в одной букве…
Ну значит нужно ещё и словарный запас подтянуть. *er vs *ee — это довольно частая фишка в английском. Contrainer vs Containee, Employer vs Employee и т.д. и т.п. Путать их ни в коем случае нельзя. Да и какая тут «середина слова» к бесу? Это ж последняя буква! Тут скорее камешек в огород CamelCaseIdentifiers…
Словарный запас тут ни при чём, я знаю об *er и *ee. Мы сейчас работаем над поддержкой WebRTC в нашем приложении, и было бы логично назвать звонящего Caller, а отвечающего — Callee. Но не всё то, что логично, ещё и удобно. На слух слова указанными выше окончаниями чётко различимы, тогда как при чтении ошибиться очень легко, а при написании — и подавно: латинские буквы E и R расположены на клавиатуре рядом. В результате мы вообще не стали использовать слово Callee, и, т.к. в коде нужно только знать, кто инициировал звонок, назвали звонящего initiator. Всё-таки, мы заботимся, по возможности, о читающих наш код коллегах.
Про середину слова вы заметили верно, но, по сути, просто придрались к словам (нечаянный каламбур), т.к. буквы различаются в середине идентификатора. Великая разница.
И CamelCase тут не виноват. Вот это
Про середину слова вы заметили верно, но, по сути, просто придрались к словам (нечаянный каламбур), т.к. буквы различаются в середине идентификатора. Великая разница.
И CamelCase тут не виноват. Вот это
container_end_line != containee_end_line
не очень сильно улучшает читабельность кода. Я искренне рад за вас, раз вы обладаете способностью мгновенно обнаруживать подобные отличия в одну букву, но увы, я и множество (не в математическом смысле) других людей обделены этим даром. Выбирать чётко различимые названия переменных — одно из правил хорошего тона в разработке ПО.Будучи перфекционистом, давно, еще в ВУЗе заметил, что очень часто ошибаюсь при копи-пастинге.
Очень скоро стало жалко тратить время на отладку и поиск «детских» ошибок и была выработана методика по «недопущению» таких ошибок.
Поделюсь, может кому-нибудь сбережет немного времени и нервов.
Звучит сложно, на по факту, все делается быстро и почти на автомате.
Для наглядности рассмотрим пример. Есть код (из примеров выше):
Я бы писал так:
Получаем исходный акроним (восьмая колонка): xyz.
Получаем остальные акронимы: xyy, xyz.
Опечатка более-менее видна.
В указанной методике важны все 4 пункта. Они дополняют друг-друга.
Отсутствие любого из пунктов или сводит на нет эффективность, или приводит к неврозу «все ли копи-пасты проверены».
Очень скоро стало жалко тратить время на отладку и поиск «детских» ошибок и была выработана методика по «недопущению» таких ошибок.
Поделюсь, может кому-нибудь сбережет немного времени и нервов.
— Как только нажали Ctrl+C, выставляем (в уме или лучше в комментах) флаг «копи-паста»: //CP->
— Пишем копи-пасту НАРУШАЯ ВСЕ правила форматирования кода — главное чтоб отличающиеся места были в одной колонке.
— Закончив редактирование копи-пасты, составляем и сверяем акронимы отличающихся колонок слева и справа (если несколько, то все).
— Только после того как убедились, что все верно, снимаем флаг копи-пасты. Но в коде, в комментах, оставляем метку копипасты: //CP
Звучит сложно, на по факту, все делается быстро и почти на автомате.
Для наглядности рассмотрим пример. Есть код (из примеров выше):
intens.x=OrSIMD(AndSIMD(BackgroundColor.x,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.x));
intens.y=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.y));
intens.z=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.z));
Я бы писал так:
intens.x = OrSIMD(AndSIMD(BackgroundColor.x, no_hit_mask), AndNotSIMD(no_hit_mask, intens.x));
intens.y = OrSIMD(AndSIMD(BackgroundColor.y, no_hit_mask), AndNotSIMD(no_hit_mask, intens.y));
intens.z = OrSIMD(AndSIMD(BackgroundColor.y, no_hit_mask), AndNotSIMD(no_hit_mask, intens.z));
Получаем исходный акроним (восьмая колонка): xyz.
Получаем остальные акронимы: xyy, xyz.
Опечатка более-менее видна.
В указанной методике важны все 4 пункта. Они дополняют друг-друга.
Отсутствие любого из пунктов или сводит на нет эффективность, или приводит к неврозу «все ли копи-пасты проверены».
Good. Я про аналогичное писал здесь "Последствия использования технологии Copy-Paste при программировании на Си++ и как с этим быть".
У меня какая то другая тенденция, при копипасте скорее во втором пункте ошибусь, чем в последнем)
Эклипс подсказывает, а не копипастная ли ошибка.
Моё новое интересное исследование: Зло живёт в функциях сравнения.
Данная статья относится к серии «ужасы для программистов». Продолжаю эту тематику и предлагаю почитать: Ноль, один, два, Фредди заберёт тебя.
Бывало подобное. По сему тщательно просматриваю код после подобного рода манипуляций.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Эффект последней строки