Комментарии 119
-del
Я конечно не работал в этих ваших микрософтах с гуглами, но мне кажется самое ужасное в последнем примере это boolean originAtCenter
.
ИМХО, надо либо не делать origin point вообще (как она и сделала), либо делать уже кастомным значением. Для полного ублажения пользователей можно сделать процентным :)
А так — ни то, ни сё и если кому-нибудь понадобится делать взаимодействие шарика с origin в центре и кубика с origin не в центре — он убьется.
Пока писал, вспомнил что моей самой позорной ошибкой было сделать неверный расчет цены на определенные штуки в некой билетной системе на день (из-за чего потом базу откатывали), так что может она и права, а мне ей советы давать не пристало, хз хз
И зачем убиваться — играешь чисто с шарами все ориджины в центре. Играешь с шарами и кубиками, при этом тебе достаточно представлять их описывающими прямоугольники — у всех ориджины в углу. Играешь с шарами и кубиками и при этом нужно обрабатывать углы у кубиков — все равно убиваться. Убивайся по вкусу, хоть через разные ориджины, хоть через ориджин в центре и у кубика тоже.
И там ошибки в синтаксисе. Похоже, автора это ничему не научило.
Вот эта история:
https://habr.com/ru/post/417435/
А можно подробности? Ни разу не видел подобного эффекта.
Специально сейчас ради такого дела задал вопрос на стриме профессионального геройщика и получил ответ, что да, было такое дело в ранних версиях то ли Возраждения Эрафии, то ли Клинка Армагеддона.
Баг касался только битв без участия игрока, поэтому прожил достаточно долго
Я рассчитывал, что в выводах она хотя бы упомянет, что не стоит называть переменные i, j, особенно, если речь в коде не про математику.
for (int i = 0; i < user->interests->length(); i++) {
for (int j = 0; j < user->interests(i)->keywords.length(); j++) {
keywords->add(user->interests(i)->keywords(i)) {
}
}
И там ошибки в синтаксисе
Где? Если ты про скобочки, то там может быть перегружен оператор круглых скобочек.
for (int interest = 0; interest < user->interests->length(); interest++) {
for (int keyword = 0; keyword < user->interests(interest)->keywords.length(); keyword++) {
keywords->add(user->interests(interest)->keywords(interest)) {
}
}
Думаю, понятно, почему?
Такая схема именования всех запутает. interest должен быть элементом коллекции interests, а не индексом в ней.
Кстати, этих ошибок легко избежать, если пользоваться хорошим двухпанельным менеджером с GUI. Правда, его сначала надо написать.
Но это у меня опыт с версией года 13-14 был, так что уже не актуально, скорее всего.
Не выношу консольную имитацию GUI. Консоль хороша для ввода команд и скриптов, а пытаться имитировать GUI сеткой из одинаковых символов — не лучшая идея. Настоящий GUI выглядит лучше, позволяет использовать шрифты разных размеров, лучше управляется мышью, поддерживает Ctrl + C/Ctrl +V, итд.
Плюс, в mc какие-то сочетания клавиш из каменного века и не работает нормально кнопка Esc.
Так и консольная имитация GUI поддерживает.
Именно из-за таких случайностей переучиваю себя работать под обычным юзером с беспарольным sudo (на ввод пароля, все-таки много конуентрации уходит). Как минимум пару раз выручало.
А вообще из подобных косяков, хотел поменять права для скрытых файлов, начинающихся с точки командой типа: cd /var/myfolder; chown -R usr:usr .*
Команда быстренько пробежалась по всем папкам, включая "..".
Хорошо что это была чистая ОС и сервер только готовился к использованию — сервис не пострадал, но вот ssh вырубился намертво, и пришлось подрывать инженеров в ДЦ ехать (у самого пропуска не было). На следующий день задарил им по ананасу в качестве извинения.
rm -f все делают пару раз в жизни. А локальные файлы и без судо можно удалить без проблем.
SSH отрубился, и пришлось физически восстанавливать доступ, а сервер был где-то в Азии… короче не знаю как админ это решал.
Но приложение (веб-сервис) крутилось с недельку само по себе, без возможности вносить изменения.
А, самое эпичное было то, что это была ночь перед моей свадьбой, и сидели с шефом примерно до 2 ночи, пытаясь что-то сделать (у меня была незавершенная сессия в WinSCP), но в итоге ничего не добились.
В итоге юзера root не стало и sudo перестало работать. На сервер под user заходить мог, но никаких изменений вносить, естественно, не получалось. И в ближайшие сутки все обещало обрушиться.
Но в этом случае сервер был виртуальный, и удалось удаленно через гипервизор загрузиться с live cd, замаунтить раздел и вернуть root:root. Это был мой лучший урок «чем виртуальные машины отличаются от железных».
переучиваю себя работать под обычным юзером с беспарольным sudo
Эм, а где вы научились работать под рутом? Сколько я помню Linux (с года этак 2006-го), открывать root-сессию без жёсткой на то необходимости, всегда считалось чем-то от чего в мире умирает один котёнок. Как, впрочем, и беcпарольный sudo.
rm -rf /
Я когда с каким-то ембедедом работал, хотел снести с SD карты xloader с u-boot (чтобы залить свежепересобранный) и вместо sudo rm -rf ./boot (что было бы папкой /mount/boot) написал sudo -rf /boot
Потом полдня продолбал на то, чтобы все вернуть… так чтобы еще и пакетный менеджер не афигевал.
у меня на клавиатуре не всегда пропечатывалась точка
несложно догадаться, что в один раз вместо
rm -rf ./
в консоли оказалось rm -rf /
Это традиционная описка, проверку на которую должны делать все ide
А шрифты — это как раз хороший тест, если можно перепутать, шрифт не подходит для записи кода.
Чем там гордиться? Тем, что такую специализированную оптимизацию поддерживать — запредельное зло?
Это надо самому поработать с таким кодом, доставшимся в наследство. Вместо ясной-понятной логики с обработкой крайних случаев, одна сплошная мешанина, где на каждый чих — уникальное решение.
Смотришь на такое и понимаешь: "работает — не трожь". Слишком долго и дорого это менять
Тю.
Ни выливания новой версии софта с крешем на старте и поломанным обновлением.
Ни забытого where в delete на проде
Ни "ой, я удалил settings.php на проде, никто доступ к базе не помнит?"
Ни "а давайте закомментим эти 50 тестов, потому что все совсем поменялось, а времени их править нет"
Какие-то ошибки в стране единорогов, блюющих радугой.
Тю
— Надули Фердыщенка! Вот так надули! Нет, вот это уж так надули! — вскричал плачевным голосом Фердыщенко, понимая, что можно и должно вставить словцо.
— А вам кто велел дела не понимать? Вот и учитесь у умных людей! — отрезала ему чуть не торжествующая Дарья Алексеевна (старинная и верная приятельница и сообщница Тоцкого).
А ваши примеры — ни о чем, ну может кроме первой. Да и первая ни о чем.
Как говорится, если тебе не стыдно за свой старый код, значит, ты не растешь как программист — и я согласна с таким мнением.Как же так, вы прожили жизни в написании кода и получается что теперь вам за него стыдно? Мне кажется «стыдно» тут не правильное слово. Или вы на работе дурака валяли, поэтому за такой код вам стыдно? Мне НЕ стыдно за свой старый код, поскольку я знаю сколько труда в него вложено. Даже если я сейчас знаю как сделать лучше — это еще одна возможность приложить свои усилия к работе. А вот стыдно пускай будет (должно быть) тем кто на govnokod.ru выкладывает чужой код и стебется над ним.
Были случаи когда туда «заготовку с листочка» выкладывали.
Ну и по идее можно было бы запатчить просто создав новый тип УстаревшийКруг и присвоить в него все уже созданные круги, и новый создать нормальным.
Вообще странный баг, если софтом пользуется большое количество пользователей, то первая линия была-бы завалена feature request'ами, а тут только через 10 лет фикс...
Странно что ошибку в апи не поправили сразу же, когда по идее юзеры должны были бы начать жаловаться неудобное управление кругом.
В отличие от моих прошлых ошибок, от этой пострадали не только мои коллеги, но и миллионы пользователей App Inventor. Многие из них были детьми или совсем новичками в программировании.
Новички, обычно, даже если видят, что что-то можно сделать лучше, стесняются об этом сказать, т.к. будут думать, что покажутся дураками, «АПИ же всё-таки делали серьёзные программисты из майкрософт, куда мне до них» может думать новичок.
С этими шариками и квадратиками (было ещё в какой-то программе crop от центра, не помню), постоянная проблема, т.к. люди разрабатывающие ПО и пользующиеся им часто живут в сильно разных мирах.
Т.е. по сути feedback не дошёл...
for (int i = 0; i < user->interests->length(); i++) {
for (int j = 0; j < user->interests(i)->keywords.length(); j++) {
Давно отказался от i/j/k для счетчиков, и тем более, всяких s/l/n для переменных. Только осмысленные названия, вроде interestCount и interestIndex.
Всё-таки не на бумаге пишем, и мониторы давно не 40 и даже не 80 колоночные. Читаемость важна, и если не делать 150 уровней вложенности и 20 операторов в строке, места для человекочитаемых названий хватает. А после компиляции или минификации вообще все равно, какая длина имени была.
Кстати, насчет вложенности. На самой заре программерской жизни, написал как-то вложенные циклы — for i, for j, for k, а потом, когда начало верхнего цикла уже было тремя экранами выше, снова for i. Вот это было веселье для новичка отлаживать! Поведение совершенно дикое получилось. На всю жизнь запомнил, что так глубоко циклы вкладывать не стоит.
P.S. Хотя, это же упрощенный пример, вполне возможно, в коде автор совсем по-другому называла переменные.
for(i..)
for(ii..)
for(iii..)
От опечаток, конечно, не спасёт, но сразу видеть глубину цикла удобно.
А после iii
идет iiii
или iv
?
но сразу видеть глубину цикла удобно
man табуляция
Тоже соглашусь насчет осмысленных названий для счетчиков, сам так поступаю в подобных случаях.
В таких случаях главное в стек не упереться ;)
И в зависимости от языка может быть медленно. Всякие там паковки и пр.
Особенно если надеяться на умный компилятор:
ideone.com/ilKvzM
Именованные переменные это конечно хорошо, но что насчет
for (auto interest: user->interests) {
for (auto keyword: interest->keywords) {
keywords->add(keyword);
}
}
?
Ну а в идеале декларативно конечно:
keywords.extend(
user.interests
.into_iter()
.flat_map(|x| x.keywords),
);
Как на cpp это выражается сходу не скажу.
UPD: Выше уже написали. Был невнимателен. Но очищать коммент не буду. Всякие «del» и «удалено» меня смущают больше, чем дублирующая информация.
Простите.
Я «всего» лет десять программирую, но ошибок, подобных второй делал уже, наверное, просто тысячи. Когда код сложный с парой уровней абстракции, очень много ресурсов мозга тратится просто на то, чтобы все эти абстракции между собой верно взаимодействовали. Опечатки или глупые ошибки встречаются постоянно, но если ты нормальный программист, ты всегда запускаешь свою программу и стараешься проверить максимально возможное число случаев (а во втором примере очевидно, что это не работало бы вовсе скорее всего), поэтому чаще всего вылезают непредвиденные ошибки самого алгоритма на «граничных случаях», которые, понятно, не всегда можно учесть сходу.
Что касается кода который я писал несколько лет назад… Ну да, бывает такое, что благодаря опыту сейчас некоторые вещи выглядят диковато, но также полно мест, на которые я смотрю сейчас и думаю «Вау, нихрена себе, это я написал?». Походу мы с автором как-то очень по разному мыслим.
Чем проще код, тем его проще поддерживать
Простой код не оптимален, а значит требует больше ресурсов
Отсюда вывод — чем больше ресурсов потребляет код, тем более он поддерживаемый
Исключение из правил — MS Windows
Меня больше удивляет, что такой код (никем не тестированный и написанной сырой программисткой) попадает в прод. А мы потом ругаемся на качество ОС Windows или студию. Так все же закономерно: просто разработчик сэкономил на тестерах и на кошечках, т.е. на нас, пользователях, проверяют новую версию...
На самом деле нужно было указать x- и y-координаты центра круга, как этому учит любой учебник математики и любой другой источник, упоминающий круги.
Но надо оперировать не только шариками, но и звездочками, линиями, и вообще произвольными растровыми изображениями. Специальный паттерн описания круга — разрушает целостность подхода к управлению спрайта! Почему было не сделать маску (тень) объекта — которая определяла бы где объект спрайта, а где уже нет? Причем, эту маску можно было бы вычислять автоматически (если пользователь ее не задал) или использовать преопределенную пользователем! Мне кажется, что как раз выпуск патча, описывающий круг как специальный объект, — ошибка. А действительно полезный патч, был бы добавление маски к спрайту. Причем он бы не ломал совместимости со старыми приложениями, ведь если маски нет — ее создают автоматически.
Не совершает ошибок тот, кто ничего не делает.
Есть ошибки на которых многие не учаться.
Правописание "*т(ь), *т(ь)ся", кстати, тоже к ним относятся.
если с "ь" и без текст работает одинаково, то ничего менять не нужно ))
была интересная история про то, как в большой компании выбирали между Linux и Windows для постройки инфраструктуры с нуля. Выбрали Windows, потому что в тестах Oracle на ней стартовала на 30 секунд быстрее. А через пару лет админ залез в скрипт запуска базы на Linux и нашел строчку sleep 30.
Это все равно что на вопрос «назовите свои худшие качества» ответить — я трудоголик и перфекционист! (вместо лентяй и рукожоп)
Нет чтоб написать — неправильно поделила 4 на 2 и это из-за меня взорвался «Челленджер».
ЗЫ Меня в микрософт работать не взяли, поэтому ошибки поэпичнее: неправильно проинициализировал выходные регистры в регуляторе тока — в результате сгорели все огни ВПП на аэродроме. Потом через несколько лет из-за косяка стерлись все видео у какого-то телеканала )
Одной из позорнейших моих ошибок было изменение кода поля ввода пароля в приложении ВК для iOS. Тогда началась мода на то, чтобы можно было показывать пароль в закрытых полях (понять, что ты ввёл вообще), и я решил «ну а что бы нет», хотя это делать было вообще не нужно («работает, не трожь», да да) и задачи тоже не стояло.
Я запилил красивый глазик рядом с полем пароля, протестил и всё было ок. Влил код в dev ветку, затем он ушёл на прод. И началось… Приложение крашилось тысячами раз. Куча людей просто не могли зайти в вк из-за меня. Трейс краша, однако, был совсем ничем не намекающий на проблему.
На моем девайсе, конечно же, работало, как и на девайсах людей вокруг. Думали, что iOS как-то в этом замешана, людям помогал сброс настроек телефона.
Когда мы нашли девайс, на котором воспроизводится, я обнаружил, что ошибка была невероятно тупейшей. Дело в том, что Objective-C код использует подсчёт ссылок. Он может быть ручной или автоматический. Тогла приложение ВК ещё использовало ручной, тк проект уже было довольно большой, мигрировать все было немного опасно и проблематично.
Так вот, когда я добавлял функциональность, в одном месте мне нужно было вернуть значение поля пароля, строку (я слегка хачил и наследовался от класса поля ввода, нужно было переопределить некоторые методы). Код был примерно такой
-(NSString*) text { return _textValue; }
Короче, из-за ручного подсчета ссылок ось ожидала получить «дополнительно retained объект», и делала этой строке release (счётчик -1). Дальше строка высвобождалась и всё становилось плохо, sigsev все дела.
Решение было простое, использовать [_textValue copy], чтобы вернуть «новую строку» (на самом деле, возвращается та же строка, просто счётчик +1).
Было очень обидно, потому что сначала я искал проблему в другом месте, и мы даже выпустили промежуточную версию с «теоретическим» исправлением бага, который ничего не исправлял :(
Самые позорные ошибки в моей карьере программиста (на текущий момент)