company_banner

Самые позорные ошибки в моей карьере программиста (на текущий момент)

Автор оригинала: Ellen Spertus
  • Перевод

Как говорится, если тебе не стыдно за свой старый код, значит, ты не растешь как программист — и я согласна с таким мнением. Я начала программировать для развлечения более 40 лет назад, а 30 лет назад и профессионально, так что ошибок у меня набралось очень много. Будучи профессором информатики, я учу своих студентов извлекать уроки из ошибок — своих, моих, чужих. Думаю, пришло время рассказать о моих ошибках, чтобы не растерять скромность. Надеюсь, кому-то они окажутся полезны.

Третье место — компилятор C от Microsoft


Мой школьный учитель считал, что «Ромео и Джульетту» нельзя считать трагедией, потому что у героев не было трагической вины — просто они вели себя глупо, как и положено подросткам. Тогда я с ним не согласилась, но сейчас вижу в его мнении рациональное зерно — особенно в связи с программированием.

К моменту окончания второго курса MIT я была молода и неопытна, как в жизни, так и в программировании. Летом я проходила практику в Microsoft, в команде компилятора C. Поначалу я занималась рутиной вроде поддержки профилирования, а потом мне доверили работу над самой веселой (как я считала) частью компилятора — оптимизацией бэкенда. В частности, я должна была улучшить код x86 для операторов ветвления.

Настроенная написать оптимальный машинный код для каждого возможного случая, я бросилась в омут с головой. Если плотность распределения значений была высока, я вносила их в таблицу переходов. Если у них имелся общий делитель, я использовала его, чтобы сделать таблицу плотнее (но только если деление можно было выполнить при помощи битового сдвига). Когда все значения представляли собой степени двойки, я проводила еще одну оптимизацию. Если множество значений не удовлетворяло моим условиям, я разбивала его на несколько оптимизируемых случаев и использовала уже оптимизированный код.

Это был кошмар. Через много лет мне рассказывали, что унаследовавший мой код программист меня ненавидел.


Вынесенный урок


Как пишут Дэвид Паттерсон и Джон Хеннесси в книге «Архитектура компьютера и проектирование компьютерных систем», один из главных принципов архитектуры и разработки в том, чтобы в общих случаях все работало как можно быстрее.

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

В свою защиту могу сказать, что я пыталась разобраться, как выглядели операторы ветвления на практике (например, сколько существовало веток и как были распределены константы), но в 1988 году эта информация была недоступна. Тем не менее, мне не стоило добавлять специальные случаи всякий раз, когда действующий компилятор не мог сгенерировать оптимальный код для придуманного мной искусственного примера.

Мне нужно было позвать опытного разработчика и вместе с ним подумать, какие были общие случаи, и разобраться конкретно с ними. Я написала бы меньше кода, но это даже хорошо. Как писал основатель Stack Overflow Джефф Этвуд, злейший враг программиста — сам программист:

Я знаю, что у вас самые добрые намерения, как и у всех нас. Мы создаем программы и любим писать код. Так уж мы устроены. Мы думаем, что любую проблему можно решить при помощи изоленты, самодельного костыля и щепотки кода. Как бы ни было больно кодерам признавать это, но лучший код — тот код, которого нет. Каждая новая строчка нуждается в отладке и поддержке, ее нужно понимать. Добавляя новый код, вы должны делать это с неохотой и отвращением, потому что все другие варианты оказались исчерпаны. Многие программисты пишут слишком много кода, делая его нашим врагом.

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


Второе место: реклама в соцсетях


Когда я работала в Google над рекламой для соцсетей (помните Myspace?), я написала на C++ что-то вроде этого:

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)) {
  }
}

Программисты, возможно, сразу увидят ошибку: последним аргументом должен быть j, а не i. Модульное тестирование не выявило ошибку, не заметил ее и мой проверяющий. Был проведен запуск, и как-то ночью мой код отправился на сервер и обвалил все компьютеры в дата-центре.

Ничего страшного не произошло. Ни у кого ничего не сломалось, потому что перед глобальным запуском код тестировался в пределах одного дата-центра. Разве что SRE-инженеры ненадолго бросили играть в бильярд и сделали небольшой откат. Наутро я получила email с аварийным дампом, исправила код и добавила модульных тестов, которые выявили бы ошибку. Поскольку я следовала протоколу — иначе мой код бы просто не прошел запуск — других проблем не возникло.


Вынесенный урок


Многие уверены, что подобная крупная ошибка обязательно стоит виновнику увольнения, но это не так: во-первых, все программисты ошибаются, во-вторых, они редко совершают одну ошибку дважды.

На самом деле, у меня есть знакомый программист — блестящий инженер, которого уволили за одну-единственную ошибку. После этого его взяли на работу в Google (и вскоре повысили) — он честно рассказал о допущенной ошибке на интервью, и ее не сочли фатальной.

Вот что рассказывают о Томасе Уотсоне, легендарном главе IBM:

Был объявлен госзаказ на сумму около миллиона долларов. Корпорация IBM — а точнее, лично Томас Уотсон-старший — очень хотел его получить. К сожалению, торговый представитель не смог этого сделать, и IBM проиграла тендер. На следующий день этот сотрудник пришел в кабинет к мистеру Уотсону и положил ему на стол конверт. Мистер Уотсон даже не стал в него заглядывать — он ждал сотрудника и знал, что это заявление об уходе.

Уотсон спросил, что пошло не так.

Торговый представитель подробно рассказал о ходе тендера. Он назвал допущенные ошибки, которых можно было избежать. Наконец, он сказал: «Мистер Уотсон, спасибо вам за то, что дали мне объясниться. Я знаю, насколько мы нуждались в этом заказе. Я знаю, как он был важен», — и собрался уходить.

Уотсон подошел к нему у двери, посмотрел ему в глаза и вернул конверт со словами: «Как я могу дать тебе уйти? Я ведь только что вложил миллион долларов в твое образование.

У меня есть футболка, на которой написано: «Если на ошибках и правда учатся, то я уже магистр». На самом деле по части ошибок я доктор наук.

Первое место: App Inventor API


По-настоящему страшные ошибки затрагивают огромное количество пользователей, становятся достоянием общественности, долго исправляются и допускаются теми, кто мог бы их не допускать. Моя крупнейшая ошибка удовлетворяет всем этим критериям.

Чем хуже, тем лучше


Я читала эссе Ричарда Гэбриела об этом подходе в девяностые, будучи аспирантом, и оно мне так нравится, что я задаю его своим студентам. Если вы плохо его помните, освежите память, оно небольшое. В этом эссе желание «сделать как надо» и подход «чем хуже, тем лучше» противопоставляются по многим параметрам, включая простоту.

Как надо: дизайн должен быть простым в реализации и интерфейсе. Простота интерфейса важнее простоты реализации.

Чем хуже, тем лучше: дизайн должен быть простым в реализации и интерфейсе. Простота реализации важнее простоты интерфейса.

Забудем об этом на минутку. К сожалению, я забыла об этом на долгие годы.

App Inventor


Работая в Google, я входила в команду App Inventor, онлайновой среды разработки с поддержкой перетаскивания объектов для начинающих Android-разработчиков. Шел 2009 год, и мы спешили вовремя выпустить альфа-версию, чтобы летом провести мастер-классы для учителей, которые могли бы пользоваться средой при обучении уже осенью. Я вызвалась реализовать спрайты, ностальгируя по тому, как в свое время я писала игры на TI-99/4. Для тех, кто не в курсе: спрайт — это двумерный графический объект, который может перемещаться и взаимодействовать с другими программными элементами. Примеры спрайтов — космические корабли, астероиды, шарики и ракетки.

Мы реализовали объектно-ориентированный App Inventor в Java, так что там просто куча объектов. Поскольку шарики и спрайты ведут себя очень похоже, я создала абстрактный sprite-класс со свойствами (полями) X, Y, Speed (скорость) и Heading (направление). Они обладали одними и теми же методами выявления столкновений, отскока от границы экрана и т.д.

Главное отличие между шариком и спрайтом в том, что именно нарисовано — заполненный круг или растр. Поскольку сначала я реализовала спрайты, логично было указать x- и y-координаты верхнего левого угла места, где располагалось изображение.


Когда спрайты заработали, я решила, что можно реализовать объекты-шарики очень небольшим количеством кода. Проблема была лишь в том, что я пошла самым простым путем (с точки зрения реализатора), указав x- и y-координаты верхнего левого угла контура, обрамляющего шар.


На самом деле нужно было указать x- и y-координаты центра круга, как этому учит любой учебник математики и любой другой источник, упоминающий круги.


В отличие от моих прошлых ошибок, от этой пострадали не только мои коллеги, но и миллионы пользователей App Inventor. Многие из них были детьми или совсем новичками в программировании. Им приходилось выполнять много лишних действий при работе над каждым приложением, в котором присутствовал шар. Если остальные свои ошибки я вспоминаю со смехом, то эта бросает меня в пот и сегодня.

Я наконец-то запатчила эту ошибку лишь недавно, десять лет спустя. «Запатчила», а не «исправила», ведь как говорит Джошуа Блох, API вечны. Не имея возможности внести изменения, которые повлияли бы на существующие программы, мы добавили свойство OriginAtCenter со значением false в старых программах и true во всех будущих. Пользователи могут задать закономерный вопрос, кому вообще пришло в голову расположить точку отсчета где-то, кроме центра. Кому? Одному программисту, который десять лет назад поленился создать нормальный API.

Вынесенные уроки


Работая над API (что иногда приходится делать почти каждому программисту), вам стоит следовать лучшим советам, изложенным в видео Джошуа Блоха «Как создать хороший API и почему он так важен» или в этом кратком списке:

  • API может принести вам как огромную пользу, так и огромный вред. Хороший API создает постоянных клиентов. Плохой становится вашим вечным кошмаром.
  • Общедоступные API, как и бриллианты, вечны. Выложитесь на все сто: другого шанса сделать все, как надо, больше не представится.
  • Наметки для API должны быть краткими — одна страница с сигнатурами классов и методов и описаниями, занимающими не больше строчки. Это позволит вам легко реструктуризировать API, если с первого раза он выйдет не идеальным.
  • Распишите сценарии использования, прежде чем реализовывать API и даже работать над его спецификацией. Таким образом вы избежите реализации и спецификации полностью нефункционального API.

Если бы я написала хотя бы небольшой конспект с искусственным сценарием, скорее всего, я бы выявила ошибку и исправила бы ее. Если и нет, то это точно бы сделал кто-то из моих коллег. Любое решение, которое имеет далеко идущие последствия, необходимо обдумывать хотя бы день (это касается не только программирования).

Название эссе Ричарда Гэбриела «Чем хуже, тем лучше» указывает на преимущество, которое получает тот, кто первым вышел на рынок — пусть даже с несовершенным продуктом — пока кто-то другой целую вечность гонится за идеалом. Размышляя над кодом спрайтов, я понимаю, что мне даже необязательно было писать больше кода, чтобы сделать все, как надо. Как ни крути, я грубо ошиблась.

Заключение


Программисты совершают ошибки каждый день — будь то написание кода с багами или нежелание попробовать что-то, что повысит их мастерство и продуктивность. Конечно, можно быть программистом и не допуская столь серьезных промахов, какие делала я. Но стать хорошим программистом, не осознавая своих ошибок и не извлекая из них уроков, невозможно.

Мне постоянно встречаются студенты, которым кажется, что они допускают слишком много ошибок и потому не созданы для программирования. Я знаю, насколько распространен в IT синдром самозванца. Надеюсь, вы усвоите перечисленные мной уроки — но помните главный из них: каждый из нас допускает ошибки — стыдные, смешные, страшные. Я буду удивлена и расстроена, если в будущем у меня не наберется материала на продолжение статьи.
Mail.ru Group
1 137,62
Строим Интернет
Поделиться публикацией

Похожие публикации

Комментарии 120

    0

    -del

      +11

      Я конечно не работал в этих ваших микрософтах с гуглами, но мне кажется самое ужасное в последнем примере это boolean originAtCenter.


      ИМХО, надо либо не делать origin point вообще (как она и сделала), либо делать уже кастомным значением. Для полного ублажения пользователей можно сделать процентным :)


      А так — ни то, ни сё и если кому-нибудь понадобится делать взаимодействие шарика с origin в центре и кубика с origin не в центре — он убьется.




      Пока писал, вспомнил что моей самой позорной ошибкой было сделать неверный расчет цены на определенные штуки в некой билетной системе на день (из-за чего потом базу откатывали), так что может она и права, а мне ей советы давать не пристало, хз хз

        –2
        Как можно «не делать ориджин вообще» мы же указываем координаты объекта в любом случае. Это и есть ориджин. Но он либо в центре, либо в верхнем левом углу
        И зачем убиваться — играешь чисто с шарами все ориджины в центре. Играешь с шарами и кубиками, при этом тебе достаточно представлять их описывающими прямоугольники — у всех ориджины в углу. Играешь с шарами и кубиками и при этом нужно обрабатывать углы у кубиков — все равно убиваться. Убивайся по вкусу, хоть через разные ориджины, хоть через ориджин в центре и у кубика тоже.
          +1
          В iOS (macOS) есть свойство anchor (CALayer class). anchor(0.5, 0.5) — это центр, соответственно anchor(0, 0) и anchor(1.0, 1.0) — это углы. Математика — простейшая. И кстати все координаты это float(double) а не int.
            0
            С триггером меньше считать. Могу предположить вариант автора оптимизирован.
            +9
            Второе — банальная опечатка. Странно, что попало в топ ошибок. Такое случается со всеми и потом может жить в проде годами незамеченным, не то, что пройти ревью и тесты.

            И там ошибки в синтаксисе. Похоже, автора это ничему не научило.
              +5
              Вспомнил случай, когда в конфигурационных фалах игры про Чужих была допущена опечатка, которую никто не заметил, и из-за этого ИИ ботов работал не правильно (слабо), что сильно испортило репутацию игры.
                +5

                Вот эта история:
                https://habr.com/ru/post/417435/

                  0
                  Или досадная ошибка кода рассчета битв между AI в третьих героях, из-за которых компьютерные стрелки никогда не стреляли. Исправление этого бага в современных модификациях серьезно повысило сложность игры пртив ботов.
                    +1

                    А можно подробности? Ни разу не видел подобного эффекта.

                      0
                      Странно, никаких письменных свидетельств не удается найти.
                      Специально сейчас ради такого дела задал вопрос на стриме профессионального геройщика и получил ответ, что да, было такое дело в ранних версиях то ли Возраждения Эрафии, то ли Клинка Армагеддона.
                      Баг касался только битв без участия игрока, поэтому прожил достаточно долго
                  0

                  Я рассчитывал, что в выводах она хотя бы упомянет, что не стоит называть переменные i, j, особенно, если речь в коде не про математику.

                    0
                    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)) {
                      }
                    }
                    


                    И там ошибки в синтаксисе


                    Где? Если ты про скобочки, то там может быть перегружен оператор круглых скобочек.
                      0
                      Когда пишешь реальный код для реального применения, то нужно зарубить на носу и всегда, повторяю, ВСЕГДА, писать так:
                      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)) {
                        }
                      }


                      Думаю, понятно, почему?
                        0
                        так я не топлю за i, j, k, я спрашивал, где синтаксические ошибки. Тогда уж лучше range based for, читабельнее и, в зависимости от реализации interests(), может быть быстрее
                          0
                          Надо полагать что в те времена range based for в С++ не было и в помине. Ведь она пишет еще про MySpace…
                          +1

                          Такая схема именования всех запутает. interest должен быть элементом коллекции interests, а не индексом в ней.

                            0
                            +1. А индекс я обычно называю interestCounter
                      +5
                      У меня самая страшная ошибка это когда я 2 ночь подряд писал API на сервак и дошло дело до файлов. Так как время поджимало перешел на продакшн, что делать конечно нельзя. И перешел в папку с помощью cd где остались от тестирования папки, которые хотел удалить и прописал rm -rf / Более я на продакшн не ходил.
                        0

                        На прошлой работе коллега также сделал. Там ещё не было патча против удаления корня. Тоже совершенно случайно.

                          +5

                          Кстати, этих ошибок легко избежать, если пользоваться хорошим двухпанельным менеджером с GUI. Правда, его сначала надо написать.

                            0
                            Консольный mc или WinSCP. С WinSCP плохо, что можно случайно нажать удаление (вроде в настройках правится)
                              0
                              У WinSCP были проблемы с производительностью, если в директории много файлов. При этом тот же Far с NetBox справлялся на ура. Ну и вообще там полно косяков было, когда в одной из сессий проблема с подключением (например, хост не отрезолвился) — блокировалась работа приложения полностью, и кнопка отмены не работала. Рекурсивная раздача прав/смена овнера чудесным образом пропускала часть файлов.
                              Но это у меня опыт с версией года 13-14 был, так что уже не актуально, скорее всего.
                                –2

                                Не выношу консольную имитацию GUI. Консоль хороша для ввода команд и скриптов, а пытаться имитировать GUI сеткой из одинаковых символов — не лучшая идея. Настоящий GUI выглядит лучше, позволяет использовать шрифты разных размеров, лучше управляется мышью, поддерживает Ctrl + C/Ctrl +V, итд.


                                Плюс, в mc какие-то сочетания клавиш из каменного века и не работает нормально кнопка Esc.

                                  +1
                                  За что минусы? Не труЪ линуксоид?
                                    0
                                    > поддерживает Ctrl + C/Ctrl +V

                                    Так и консольная имитация GUI поддерживает.
                                      0
                                      Если вспомнить историю, то всё было ровно наоборот. Сначала появилась эта самая «консольная имитация GUI» — операторам первых ЭВМ были доступны физические кнопки и сетка из однотипных индикаторов сгруппированных по назначению.
                                0

                                Именно из-за таких случайностей переучиваю себя работать под обычным юзером с беспарольным sudo (на ввод пароля, все-таки много конуентрации уходит). Как минимум пару раз выручало.


                                А вообще из подобных косяков, хотел поменять права для скрытых файлов, начинающихся с точки командой типа: cd /var/myfolder; chown -R usr:usr .*
                                Команда быстренько пробежалась по всем папкам, включая "..".
                                Хорошо что это была чистая ОС и сервер только готовился к использованию — сервис не пострадал, но вот ssh вырубился намертво, и пришлось подрывать инженеров в ДЦ ехать (у самого пропуска не было). На следующий день задарил им по ананасу в качестве извинения.

                                  0
                                  Не вижу чем вам это поможет.
                                  rm -f все делают пару раз в жизни. А локальные файлы и без судо можно удалить без проблем.
                                    0
                                    Это поможет тем, что потерять локальные файлы и потерять удаленный доступ к удаленному серверу, с его одновременным падением — немного другой уровень проблемы.
                                    И да, если для вас является проблемой потерять локальные файлы, то задумайтесь о бэкапах, если это в вашем ведении.
                                    0
                                    У меня такая же хрень была — сделал chown root:root / на проде.

                                    SSH отрубился, и пришлось физически восстанавливать доступ, а сервер был где-то в Азии… короче не знаю как админ это решал.
                                    Но приложение (веб-сервис) крутилось с недельку само по себе, без возможности вносить изменения.

                                    А, самое эпичное было то, что это была ночь перед моей свадьбой, и сидели с шефом примерно до 2 ночи, пытаясь что-то сделать (у меня была незавершенная сессия в WinSCP), но в итоге ничего не добились.
                                      0
                                      Прочитав ваш коммент, вспомнил еще одну историю, когда редактировал вручную /etc/passwd и в начале первой строки «root:root:...» поставил нечаянно какой-то символ.
                                      В итоге юзера root не стало и sudo перестало работать. На сервер под user заходить мог, но никаких изменений вносить, естественно, не получалось. И в ближайшие сутки все обещало обрушиться.
                                      Но в этом случае сервер был виртуальный, и удалось удаленно через гипервизор загрузиться с live cd, замаунтить раздел и вернуть root:root. Это был мой лучший урок «чем виртуальные машины отличаются от железных».
                                        0

                                        А для железных тоже есть аналогичные решения. Если только их безопасники не запретили...

                                      0
                                      переучиваю себя работать под обычным юзером с беспарольным sudo

                                      Эм, а где вы научились работать под рутом? Сколько я помню Linux (с года этак 2006-го), открывать root-сессию без жёсткой на то необходимости, всегда считалось чем-то от чего в мире умирает один котёнок. Как, впрочем, и беcпарольный sudo.

                                        0
                                        Парольный sudo не очень сочетается с аутентификацией по ключам в ssh.
                                      0
                                      rm -rf /


                                      Я когда с каким-то ембедедом работал, хотел снести с SD карты xloader с u-boot (чтобы залить свежепересобранный) и вместо sudo rm -rf ./boot (что было бы папкой /mount/boot) написал sudo -rf /boot

                                      Потом полдня продолбал на то, чтобы все вернуть… так чтобы еще и пакетный менеджер не афигевал.
                                        0
                                        пол дня разве это время?
                                          0
                                          Я мог бы потратить это время на что-то полезное, ну или хотя бы на видео с котиками. А вместо этого занимался бесполезной работой. Уж не говоря о том, что то, что было бы готово через 30 минут было в итоге готово только в конце дня.
                                        0
                                        hahaha, classic

                                        у меня на клавиатуре не всегда пропечатывалась точка
                                        несложно догадаться, что в один раз вместо
                                        rm -rf ./
                                        в консоли оказалось
                                        rm -rf /
                                          +1
                                          Можно было писать
                                          rm -rf .
                                          , тогда ничего страшного не случилось бы
                                            0
                                            Привет яндекс.диск
                                          0
                                          интересно было почитать, особенно понравилось второе место, с этой ошибкой столько проблем было при изучении с++, эх времена
                                            0

                                            Это традиционная описка, проверку на которую должны делать все ide

                                              0
                                              Кстати, почему принято для счётчиков использовать i и j? Их же во многих шрифтах легко перепутать и не заметить.
                                                0
                                                Из математики еще пошло.
                                                А шрифты — это как раз хороший тест, если можно перепутать, шрифт не подходит для записи кода.
                                                  0
                                                  Может всё-таки не подходят однобуквенные переменные, которые легко перепутать?)
                                                    0
                                                    Одно другому не мешает же.
                                                      +1
                                                      Дело не в количестве букв, какой-нибудь оhfcjlocmpqw ситуацию не улучшит. Правильнее будет рекомендовать использовать термины предметной области, а там как раз зачастую те самые i да j и использованы.
                                                        0
                                                        Правильнее использовать логичные названия, типа keywordIndex, а не i или j
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                  +7

                                                  Чем там гордиться? Тем, что такую специализированную оптимизацию поддерживать — запредельное зло?


                                                  Это надо самому поработать с таким кодом, доставшимся в наследство. Вместо ясной-понятной логики с обработкой крайних случаев, одна сплошная мешанина, где на каждый чих — уникальное решение.


                                                  Смотришь на такое и понимаешь: "работает — не трожь". Слишком долго и дорого это менять

                                                  +25

                                                  Тю.


                                                  Ни выливания новой версии софта с крешем на старте и поломанным обновлением.


                                                  Ни забытого where в delete на проде


                                                  Ни "ой, я удалил settings.php на проде, никто доступ к базе не помнит?"


                                                  Ни "а давайте закомментим эти 50 тестов, потому что все совсем поменялось, а времени их править нет"


                                                  Какие-то ошибки в стране единорогов, блюющих радугой.


                                                  Тю

                                                    +53
                                                    Просто она — старый опытный сотрудник, сменивший множество организаций с очень высокой конкуренцией (профессор — это тоже пример такой должности). Она прекрасно понимает, что и рассказ о собственных ошибках должен быть таким, чтобы её не в чем было упрекнуть. Одна овероптимизация в юности, один непродуманный интерфейс (зато похвасталась тем, что в итоге этим интерфейсом пользовались миллионы) и одна дурацкая опечатка, какие мы делаем чуть ли не каждый день. Учитесь правильной самокритике у успешных профессионалов.
                                                      +1
                                                      Да Федор Михайлович еще когда…

                                                      — Надули Фердыщенка! Вот так надули! Нет, вот это уж так надули! — вскричал плачевным голосом Фердыщенко, понимая, что можно и должно вставить словцо.
                                                      — А вам кто велел дела не понимать? Вот и учитесь у умных людей! — отрезала ему чуть не торжествующая Дарья Алексеевна (старинная и верная приятельница и сообщница Тоцкого).
                                                        +2
                                                        Напоминает анекдот о сотруднике, который в анкете в графе «недостатки» написал «очень много работаю и слишком доверяю начальству».
                                                          0
                                                          Хмм, анекдот. Примерно так в реальности и отвечают на вопрос «какие у вас недостатки» на англоязычных интервью. Другой вариант ответ «на должность старшего разработчика — фальшивю, когда пою в душе»
                                                        0
                                                        Только вот описанные ошибки могли помешать или даже помешали миллионам людей.
                                                        А ваши примеры — ни о чем, ну может кроме первой. Да и первая ни о чем.
                                                        +11
                                                        Как говорится, если тебе не стыдно за свой старый код, значит, ты не растешь как программист — и я согласна с таким мнением.
                                                        Как же так, вы прожили жизни в написании кода и получается что теперь вам за него стыдно? Мне кажется «стыдно» тут не правильное слово. Или вы на работе дурака валяли, поэтому за такой код вам стыдно? Мне НЕ стыдно за свой старый код, поскольку я знаю сколько труда в него вложено. Даже если я сейчас знаю как сделать лучше — это еще одна возможность приложить свои усилия к работе. А вот стыдно пускай будет (должно быть) тем кто на govnokod.ru выкладывает чужой код и стебется над ним.
                                                          0
                                                          А вот стыдно пускай будет (должно быть) тем кто на govnokod.ru выкладывает чужой код и стебется над ним.
                                                          Серьёзно? Идея говнокода вовсе не в том, чтобы просто стебаться.
                                                          PS: О, его отмодерировали
                                                            0
                                                            Претензии не к идеи govnokod.ru, а к тому как его используют. И по статье разница между, «у тебя стиль кода невыдержан» или «глаза кровоточат глядя на это» все таки существенная. Тем кого устраивает такой нравственный облик, сложно что либо объяснять.
                                                            Были случаи когда туда «заготовку с листочка» выкладывали.
                                                          +2
                                                          Странно что ошибку в апи не поправили сразу же, когда по идее юзеры должны были бы начать жаловаться неудобное управление кругом.
                                                          Ну и по идее можно было бы запатчить просто создав новый тип УстаревшийКруг и присвоить в него все уже созданные круги, и новый создать нормальным.
                                                            0

                                                            Вообще странный баг, если софтом пользуется большое количество пользователей, то первая линия была-бы завалена feature request'ами, а тут только через 10 лет фикс...

                                                              0
                                                              Странно что ошибку в апи не поправили сразу же, когда по идее юзеры должны были бы начать жаловаться неудобное управление кругом.


                                                              В отличие от моих прошлых ошибок, от этой пострадали не только мои коллеги, но и миллионы пользователей App Inventor. Многие из них были детьми или совсем новичками в программировании.


                                                              Новички, обычно, даже если видят, что что-то можно сделать лучше, стесняются об этом сказать, т.к. будут думать, что покажутся дураками, «АПИ же всё-таки делали серьёзные программисты из майкрософт, куда мне до них» может думать новичок.
                                                                0

                                                                С этими шариками и квадратиками (было ещё в какой-то программе crop от центра, не помню), постоянная проблема, т.к. люди разрабатывающие ПО и пользующиеся им часто живут в сильно разных мирах.
                                                                Т.е. по сути feedback не дошёл...

                                                                +9
                                                                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. Хотя, это же упрощенный пример, вполне возможно, в коде автор совсем по-другому называла переменные.
                                                                  +2
                                                                  Как-то раз попалась такая рекомендация (которй сейчас и пользуюсь при необходимости)
                                                                  for(i..)
                                                                     for(ii..)
                                                                        for(iii..)
                                                                  

                                                                  От опечаток, конечно, не спасёт, но сразу видеть глубину цикла удобно.
                                                                    +22

                                                                    А после iii идет iiii или iv?

                                                                      0
                                                                      Дело вкуса. Если нет слишком большой глубины, то по мне — проще iiii. Или сразу i0..i3. Но больше 3 — это уже обычно очень хитрые случаи. Даже 3 попадалось только для работы с 3D-текстурами. Для разных задач проще разделить. Например i..iii для итерации по масиву и j..jjj для вычислений по конкретной ячейке. При большой разнице в грубине перепутать становится сложнее.
                                                                        +1
                                                                        Например i..iii для итерации по масиву и j..jjj для вычислений по конкретной ячейке.

                                                                        Да уж. Это настолько толсто, что даже кажется тонким xD

                                                                        0
                                                                        ix4
                                                                        0
                                                                        Ну фиг его знает, я вижу тут массу способов отстрелить себе что-нибудь простой опечаткой. Стоит случайно вместо iii написать ii, как жизнь заиграет новыми красками.
                                                                          0
                                                                          Их в любом случае хватает. Доводилось по запаре путать даже длинные и совершенно разные названия. Тут же разница заметна даже просто по длинне, что достаточно неплохо бросается в глаза.
                                                                            +3
                                                                            Тут же разница заметна даже просто по длинне, что достаточно неплохо бросается в глаза.

                                                                            Вот вы лишнюю букву в слове «длина» напечатали, и ничего, в глаза на бросилось :).
                                                                          0
                                                                          но сразу видеть глубину цикла удобно

                                                                          man табуляция
                                                                            0
                                                                            И как она поможет различить переменные из разных уровней?
                                                                              +1
                                                                              Называй переменными логичными именами и будет понятно, какая откуда и для чего.
                                                                            0
                                                                            хы, так тоже делал, но не от рекомендации, а сам пришел. Но это не лучшее.
                                                                              0
                                                                              Само собой. Это скорее «дёшево и сердито». Правильные имена — это хорошо, но не всегда удобно.
                                                                            +3
                                                                            Для себя я еще вынес полезный совет из книги «Чистый код» Роберта Мартина — чтобы не делать много вложенности (не только в циклах, но и в конструкциях if), можно тело цикла оборачивать в функцию (а внутри этой функции будет второй цикл). Это повышает читаемость и уменьшает шанс на подобные ошибки.
                                                                            Тоже соглашусь насчет осмысленных названий для счетчиков, сам так поступаю в подобных случаях.
                                                                              –1

                                                                              В таких случаях главное в стек не упереться ;)
                                                                              И в зависимости от языка может быть медленно. Всякие там паковки и пр.

                                                                                +2
                                                                                Добро пожаловать в 2019, компиляторы уже давно умеют оптимизировать код
                                                                                  –2
                                                                                  Такое «удобство» неминуемо стрельнёт себе в ногу.
                                                                                  Особенно если надеяться на умный компилятор:
                                                                                  ideone.com/ilKvzM
                                                                                  0
                                                                                  Use «inline», Luk.
                                                                                    0

                                                                                    Выше написал пример, где возможны всякие неприятные казусы.

                                                                                +1

                                                                                Именованные переменные это конечно хорошо, но что насчет


                                                                                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 это выражается сходу не скажу.

                                                                                  +1
                                                                                  Имхо, если пишешь вложенные циклы, стоит задуматься, чтобы вынести код вложенного цикла в отдельный метод/функцию. Это и от подобных ошибок поможет, и читается код проще, и отлаживать удобнее.

                                                                                  UPD: Выше уже написали. Был невнимателен. Но очищать коммент не буду. Всякие «del» и «удалено» меня смущают больше, чем дублирующая информация.
                                                                                    0
                                                                                    Я думал это только я такой странный, что не люблю короткие имена даже для счётчиков. А насчёт конкретно i и j вообще ужасный выбор, т.к. их легко перепутать на многих шрифтах, не понимаю, как так исторически сложилось, что используют их.
                                                                                    0
                                                                                    Как же я люблю эту картинку!
                                                                                    Простите.
                                                                                      +3
                                                                                      Нууу нее знаааюю…

                                                                                      Я «всего» лет десять программирую, но ошибок, подобных второй делал уже, наверное, просто тысячи. Когда код сложный с парой уровней абстракции, очень много ресурсов мозга тратится просто на то, чтобы все эти абстракции между собой верно взаимодействовали. Опечатки или глупые ошибки встречаются постоянно, но если ты нормальный программист, ты всегда запускаешь свою программу и стараешься проверить максимально возможное число случаев (а во втором примере очевидно, что это не работало бы вовсе скорее всего), поэтому чаще всего вылезают непредвиденные ошибки самого алгоритма на «граничных случаях», которые, понятно, не всегда можно учесть сходу.

                                                                                      Что касается кода который я писал несколько лет назад… Ну да, бывает такое, что благодаря опыту сейчас некоторые вещи выглядят диковато, но также полно мест, на которые я смотрю сейчас и думаю «Вау, нихрена себе, это я написал?». Походу мы с автором как-то очень по разному мыслим.
                                                                                        –1
                                                                                        Да уж, позорно
                                                                                          +1
                                                                                          Предлагаю под этим комментарием поделится своими «успехами» в денежном эквиваленте, мой суммарный урон который нанесен работодателю за 10 лет: 1200$
                                                                                            0
                                                                                            что-то мало. Как рассчитывался урон? Он включает в себя только стоимость исправления ошибки? Или есть еще репутационные издержки, недополученная прибыль из-за плохой репутации?
                                                                                              0
                                                                                              Урон рассчитан по себестоимости использованных материалов + временные затраты + утилизация ненужного изделия. Репутация работодателя не пострадала. Исправлялась ошибка с горящим стулом, бесплатно )
                                                                                              +3
                                                                                              Буквально уронил сервер?)
                                                                                                0
                                                                                                Вы серьзно? У вас завышено чувство вины. Не смешите копейками. Такими суммами можно смело гордится. Кривая морда и дурной характер могут куда больший урон нанести, если на нее клиент натыкается.
                                                                                                +1
                                                                                                Чем оптимальнее код, тем сложнее его поддерживать
                                                                                                Чем проще код, тем его проще поддерживать
                                                                                                Простой код не оптимален, а значит требует больше ресурсов
                                                                                                Отсюда вывод — чем больше ресурсов потребляет код, тем более он поддерживаемый
                                                                                                Исключение из правил — MS Windows
                                                                                                  +2
                                                                                                  С прискорбием вынужден не согласиться. Нередко код потребляет много ресурсов не потому, что он простой, а потому, что он одновременно сложный и неоптимальный.
                                                                                                  0

                                                                                                  Меня больше удивляет, что такой код (никем не тестированный и написанной сырой программисткой) попадает в прод. А мы потом ругаемся на качество ОС Windows или студию. Так все же закономерно: просто разработчик сэкономил на тестерах и на кошечках, т.е. на нас, пользователях, проверяют новую версию...

                                                                                                    +2
                                                                                                    На самом деле нужно было указать x- и y-координаты центра круга, как этому учит любой учебник математики и любой другой источник, упоминающий круги.

                                                                                                    Но надо оперировать не только шариками, но и звездочками, линиями, и вообще произвольными растровыми изображениями. Специальный паттерн описания круга — разрушает целостность подхода к управлению спрайта! Почему было не сделать маску (тень) объекта — которая определяла бы где объект спрайта, а где уже нет? Причем, эту маску можно было бы вычислять автоматически (если пользователь ее не задал) или использовать преопределенную пользователем! Мне кажется, что как раз выпуск патча, описывающий круг как специальный объект, — ошибка. А действительно полезный патч, был бы добавление маски к спрайту. Причем он бы не ломал совместимости со старыми приложениями, ведь если маски нет — ее создают автоматически.
                                                                                                      +1

                                                                                                      Не совершает ошибок тот, кто ничего не делает.

                                                                                                        +2
                                                                                                        А используй они PVS Studio, на одну ошибку было бы меньше…
                                                                                                          –1
                                                                                                          Есть ошибки на которых многие не учаться. Например не использование TDD ошибка, но это мало кого заставляет изменяться пока что-то в проде не отвалиться. Тогда возможно программисту станет ясно, что если бы он меньше думал как оно будет работать, а больше о том как проверить результат работы, то ошибку бы не пропустил уже на уровне написания кода.
                                                                                                            +1
                                                                                                            Есть ошибки на которых многие не учаться.

                                                                                                            Правописание "*т(ь), *т(ь)ся", кстати, тоже к ним относятся.
                                                                                                              –3

                                                                                                              если с "ь" и без текст работает одинаково, то ничего менять не нужно ))

                                                                                                                0
                                                                                                                По-разному работает. Сразу не доверяешь мнению человека, который школьные правила освоить не в силах.
                                                                                                                  –4
                                                                                                                  Kак вам повезло что тут ресурс для программистов и кроме знаний русского и немного программирования больше ничего не нужно показывать, но в школьном курсе есть другие предметы и вот тут не факт что вы выучили больше чем я :P
                                                                                                            +1
                                                                                                            В метрополитене лет 15 назад, когда вводили бесконтактные билеты заметил, что если приложить билет одновременно: я к одному турникету, другой пассажир в другой турникет, то проходит только один, у второго ошибка возникала и нужно было либо еще раз приложить, либо подождать 7 минут, если билет безлимитный. Наверное, программист чувствовал в тот момент, когда обнаружили ошибку: анти-Робин Гудом, можно сказать все пассажиры вложились в его обучение.
                                                                                                              +5

                                                                                                              была интересная история про то, как в большой компании выбирали между Linux и Windows для постройки инфраструктуры с нуля. Выбрали Windows, потому что в тестах Oracle на ней стартовала на 30 секунд быстрее. А через пару лет админ залез в скрипт запуска базы на Linux и нашел строчку sleep 30.

                                                                                                                +1
                                                                                                                Самая моя большая ошибка, это просидеть 3 года в компании, занимаясь реализацией скриптов для сборки проектов и их тестирования. 3 года моей жизни просто в никуда.
                                                                                                                  0
                                                                                                                  devops, 3 года опыта. Звучит неплохо на первый взгляд.
                                                                                                                  0
                                                                                                                  У меня самая ацкая ошибка была в 2006м. Я для одной конторы, которая занималась гэмблингом, писал пакет игр типа рулетка.
                                                                                                                  И для отладки выигрышей забил вместо ГСЧ жесткую последовательность из 10 шаров после которой шли случайные.
                                                                                                                  И естественно, по закону подлости, это все в прод утекло — админ поторопился выложить. Хотел похвастаться перед заказчиком как мы быстро все делаем. В продакшене около часа оно провисело. Было очень «весело» потом.
                                                                                                                  Как ни странно финансовых убытков не было. Те кто выиграл за час потом все и спустили.
                                                                                                                    +3

                                                                                                                    Блин, а ведь это не баг а фича, чуваки расслабились и втянулись, а потом закономерно все слили.

                                                                                                                    +1
                                                                                                                    та ладно. мне как-то пришлось откатывать банковскую бд на бэкап четырехчасовой свежести и около сотни сотрудников переделывало свою работу второй раз.
                                                                                                                      –1
                                                                                                                      Хорошая статья, я полагаю, что самой большой ошибкой программиста было бы прекращение процесса самообучения, как самого студента-программиста, один важный совет, который я хотел бы дать всем новым программистам / разработчикам программного обеспечения, состоит в том, чтобы сделать это привычкой следуя официальным блогам лучших в мире фирм по разработке программного обеспечения, таких как DCS, GoodCore Software и т. д., поскольку такие источники блогов регулярно предлагают самые последние обновления из области разработки программного обеспечения, также такие блоги действительно помогли мне понять последние процессы разработки программного обеспечения. Надеюсь, это тоже поможет. еще раз спасибо
                                                                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                          +1
                                                                                                                          От статьи ощущение, что автор про эти свои «ошибки» HR'у рассказывает при приеме на работу.

                                                                                                                          Это все равно что на вопрос «назовите свои худшие качества» ответить — я трудоголик и перфекционист! (вместо лентяй и рукожоп)
                                                                                                                          Нет чтоб написать — неправильно поделила 4 на 2 и это из-за меня взорвался «Челленджер».

                                                                                                                          ЗЫ Меня в микрософт работать не взяли, поэтому ошибки поэпичнее: неправильно проинициализировал выходные регистры в регуляторе тока — в результате сгорели все огни ВПП на аэродроме. Потом через несколько лет из-за косяка стерлись все видео у какого-то телеканала )
                                                                                                                            0
                                                                                                                            Насчет координат круга в левом верхнем углу описанного квадрата — это боль. Боль, которую знает каждый, кто хоть раз рисовал круги в mspaint. Видимо, в MS тоже есть такой злодей, но он своих ошибок не признает, очевидно. Потому что столько лет прошло, а воз и ныне там.
                                                                                                                              +2

                                                                                                                              Одной из позорнейших моих ошибок было изменение кода поля ввода пароля в приложении ВК для iOS. Тогда началась мода на то, чтобы можно было показывать пароль в закрытых полях (понять, что ты ввёл вообще), и я решил «ну а что бы нет», хотя это делать было вообще не нужно («работает, не трожь», да да) и задачи тоже не стояло.
                                                                                                                              Я запилил красивый глазик рядом с полем пароля, протестил и всё было ок. Влил код в dev ветку, затем он ушёл на прод. И началось… Приложение крашилось тысячами раз. Куча людей просто не могли зайти в вк из-за меня. Трейс краша, однако, был совсем ничем не намекающий на проблему.
                                                                                                                              На моем девайсе, конечно же, работало, как и на девайсах людей вокруг. Думали, что iOS как-то в этом замешана, людям помогал сброс настроек телефона.
                                                                                                                              Когда мы нашли девайс, на котором воспроизводится, я обнаружил, что ошибка была невероятно тупейшей. Дело в том, что Objective-C код использует подсчёт ссылок. Он может быть ручной или автоматический. Тогла приложение ВК ещё использовало ручной, тк проект уже было довольно большой, мигрировать все было немного опасно и проблематично.
                                                                                                                              Так вот, когда я добавлял функциональность, в одном месте мне нужно было вернуть значение поля пароля, строку (я слегка хачил и наследовался от класса поля ввода, нужно было переопределить некоторые методы). Код был примерно такой
                                                                                                                              -(NSString*) text { return _textValue; }
                                                                                                                              Короче, из-за ручного подсчета ссылок ось ожидала получить «дополнительно retained объект», и делала этой строке release (счётчик -1). Дальше строка высвобождалась и всё становилось плохо, sigsev все дела.
                                                                                                                              Решение было простое, использовать [_textValue copy], чтобы вернуть «новую строку» (на самом деле, возвращается та же строка, просто счётчик +1).
                                                                                                                              Было очень обидно, потому что сначала я искал проблему в другом месте, и мы даже выпустили промежуточную версию с «теоретическим» исправлением бага, который ничего не исправлял :(

                                                                                                                              0
                                                                                                                              Самая глупая ошибка: функция вида bool IsBusy {return IsBusy}. Это был промышленный сервер Oracle. Он продержался 15 минут и упал. Никто ничего так и не понял. Мне стало стыдно, а я ничего никому не сказал, молча исправил. Перепутал имя функции и переменной (должно было быть что-то вроде return vIsBusy)

                                                                                                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                                                              Самое читаемое