Рубрики
Без рубрики

Руководство разработчика программного обеспечения по эффективной отладке

Есть некоторые вещи в жизни, от которых невозможно убежать, например, смерть и налоги. А также для нас, технарей, там”… С пометкой first post, debug, java.

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

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

Существует множество разработчиков, которые могут просматривать новые функции, писать код и внедрять бизнес-требования, как будто их обучал сам великий Деннис Ричи, но задумывались ли вы когда-нибудь, кто устраняет колоссальное количество ошибок, которые они оставляют после себя?

Одно дело знать, как писать красивый элегантный код. Другое дело знать, как отлаживать самый неприятный код, который вы когда-либо видели в своей жизни, который был написан тем ранее упомянутым мифическим человеком, которому в одиночку удалось собрать все приложение за 48 часов.

Как назло, отладке – как и любому другому навыку – можно научиться. Если вы применяете правильные методы и практики, вы можете стать великим в этом. Кто знает? Возможно, вам это даже понравится.

Настоящий секрет отладки

Секретный ингредиент отладки заключается в следующем: поймите, что все дело в мышлении. Речь идет о том, чтобы использовать логическую линию атаки, чтобы противостоять проблеме — не торопясь, не пытаясь найти решение и, конечно же, не предполагая, что вы можете просто определить проблему. Большинство разработчиков придерживаются подхода: сначала стреляйте, стреляйте еще немного, а затем, когда все умрут, умудряйтесь задать вопрос или два. Отладка должна заключаться в том, чтобы оставаться спокойной и собранной и подходить к проблеме с рациональной, аналитической точки зрения, а не с драматической.

Прежде чем мы углубимся в это, давайте попытаемся понять, “что именно такое отладка? “Это звучит довольно очевидно, верно? Вы открываете перспективу отладчика и исправляете сбои, которые обнаруживаете в своем коде. Вот тут-то вы бы однозначно ошиблись. Отладка не имеет абсолютно никакого отношения к отладчику.

Отладка имеет непосредственное отношение к:

  1. Поиск причины проблемы в базе кода
  2. Признавая возможные причины этого
  3. Проверяя гипотезы, пока возможная первопричина обнаружена
  4. Затем, в должное время, устраните эту причину и гарантируйте, что это никогда не повторится.

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

Теперь давайте пройдемся по типичному процессу отладки программиста, и вы точно поймете, что я имею в виду.

Теперь давайте пройдемся по типичному процессу отладки программиста, и вы точно поймете, что я имею в виду.

Итак, вы приходите в офис, и ваш менеджер проекта говорит, что у него есть несколько ошибок, которые вы должны исправить. Вы, программист, решаете сесть за свой рабочий стол с мыслью: “Я использую всю мощь своего интеллектуального мастерства в этом

Вы, программист, решаете сесть за свой рабочий стол с мыслью: “Я использую всю мощь своего интеллектуального мастерства в этом Вы осторожно проходите через код. Время, кажется, расплывается, минуты превращаются в часы, часы – в недели. Постепенно вы становитесь прежним парнем, сидящим за клавиатурой, неподвижным в неизменном сеансе отладки, но в некотором роде вы “ближе”. Все ваши дети выросли. Возможно, ваша жена бросила вас. Единственное, что остается, это… жук.

То, что делает абсурдное количество программистов, когда они хотят отладить проблему в коде, – это запустить отладчик и начать осматриваться с одного места на другое. Никогда не делай этого. Отладчик должен быть вашей конечной альтернативой. Когда вы сразу запускаете отладчик, вы говорите: “У меня нет никаких знаний о корне проблемы, я просто просмотрю все и попытаюсь понять, что происходит”.

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

Точно такой же принцип применяется и при отладке. Вам нужно знать, что вы ищете. Не поймите меня неправильно – отладчик – замечательный и мощный инструмент. При правильном использовании отладчик может помочь вам расшифровать все категории сбоев и увидеть, что происходит во время выполнения вашего кода. Тем не менее, отладчик – это не место для запуска. Многочисленные ошибки можно устранить, даже не прикасаясь к отладчику.

Единственное, что вы обязательно ДОЛЖНЫ сделать во время отладки

Итак, что вы делаете, если вы не должны запускать отладчик, когда начинаете отлаживать проблему? Первое, что должен сделать любой хорошо сбалансированный, рациональный инженер-программист, – это воспроизвести ошибку. Почему? Чтобы быть уверенным, что проблема действительно является ошибкой и что вы сможете ее отладить.

Сто процентов сбоев, которые не могут быть воспроизведены, не могут быть отлажены. Так что, если вы не можете точно воспроизвести проблему, нет смысла в Так что, если вы не можете точно воспроизвести проблему, нет смысла в Тем не менее, даже если бы вы это исправили, как бы вы проверили, что это было исправлено утвержденным способом?

Четыре шага к эффективной отладке

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

  2. Сядь и подумай – Сразу после того, как вы воспроизведете свой сбой, следующий этап является наиболее важным, которого разработчики программного обеспечения избегают по той же причине, по которой они так спешат расшифровать сбой. Ваш следующий шаг – сесть и подумать. Да, это верно. Подумайте о глюке и о том, каковы его возможные корни. Рассмотрите, как работает система, и возможные объяснения странного поведения, которое вы наблюдаете. Вы будете в спешке прыгать в код и в отладчик и начинать “смотреть на вещи”, но прежде чем вы начнете это делать, жизненно важно понять, что вы ищете и на что именно смотреть. Скорее всего, вы сгенерируете несколько концепций или гипотез о том, что, возможно, может быть причиной сбоя. У вас должно быть как минимум два или три, с которыми вы можете поэкспериментировать, прежде чем двигаться дальше.

  3. Проверьте свои концепции – в большинстве случаев ваши гипотезы не сработают. Это просто жизнь. Если это так, то следующее лучшее, что вы можете сделать, – это проверить свои предположения о том, как все работает. Мы, естественно, предполагаем, что код работает определенным образом или что какой-то ввод или вывод должен иметь какое-то значение. Снова и снова мы думаем: “Этого не может быть!” и часто оказывается, что мы ошибаемся. Это случается с лучшими из нас. Лучшее, что вы можете сделать с этими предположениями, – это проверить их. Вы делаете это, написав примеры модульных тестов. Напишите несколько модульных тестов, которые проверяют очевидные вещи, которые должны работать в рамках рабочего процесса проблемы, которую вы пытаетесь отладить. Большинство из этих тестов должны быть легко пройдены, но время от времени вы будете писать модульный тест, чтобы проверить какое-то очевидное предположение, и результаты будут просто шокирующими. Всегда помните, что если бы ответ на ваш сбой был очевиден, это вообще не было бы сбоем.

  4. Понять, как вы это исправили – Если вы устраняете проблему, поймите, что вы сделали, чтобы ее устранить. Если вы не знаете, устранило ли то, что вы сделали, проблему, вы еще не закончили. Насколько вам известно, возможно, вы непреднамеренно вызвали другую проблему или, скорее всего, не устранили свою первоначальную проблему. Проблемы никогда не исчезают сами по себе. Когда вы исправите сбой, не останавливайтесь на достигнутом. Изучите немного дальше и убедитесь, что вы точно понимаете, что происходило, что вызвало проблему в первую очередь, и как ваше решение устранило ее. Когда разработчики программного обеспечения устраняют сбой, возясь с кодом, и он, по-видимому, начинает работать, они предполагают, что он исправлен, даже не зная почему. Это опасная привычка по многим причинам. Как указывалось выше, когда вы бессистемно настраиваете механизмы в системе и изменяете фрагменты кода здесь и там, вы можете вызывать всевозможные другие сбои, не осознавая этого. Что еще более важно, вы тренируете себя, чтобы быть ужасным отладчиком! Время от времени вам может повезти, но у вас не будет повторяемой процедуры или надежного набора навыков для отладки.

Эффективная отладка на практике

Некоторое время назад я исправил неприятную ошибку для клиента. Это было связано с тем, что соединения Secure Socket Layer (SSL) с системой стороннего клиента были выпущены случайным образом. Сторонний клиент использовал древнее программное обеспечение, и у моего клиента был пользовательский код, который подключался к системе стороннего клиента по протоколу SSL.

Было предпринято множество попыток устранить этот сбой, которые были основаны не более чем на слепых выводах. Один из этих выводов (который, казалось, работал в течение некоторого времени) состоял в том, чтобы поместить всю информацию в буфер и в это время выполнить один вызов функции write() для функции OutputStream SSLSocket, с ожиданием, что все это будет передано как один SSL-пакет. Какое-то время создавалось впечатление, что это работает, но ошибка иногда появлялась снова после этого так называемого “исправления”.

Наконец сторонний клиент обратился к поставщику своего программного обеспечения эпохи Юрского периода, который в свое время точно выяснил, почему их программное обеспечение периодически отключало соединение. Сообщения, которые мы отправляли, начинались с поля длиной 4 байта. Они заметили, что наши данные были фрагментированы на две записи SSL, первая запись состояла только из самого первого байта сообщения, а вторая состояла из остальной части сообщения. Их программное обеспечение не было приспособлено для обработки этого – оно предполагало, что первая запись SSL будет содержать поле длиной не менее 4 байт.

Теперь загадкой было то, почему наш код передавал первый байт в отдельной записи SSL. Чтобы выяснить, почему это произошло, я запустил код в режиме отладки и вошел в исходный код JDK. Через некоторое время я наткнулся на класс sun.security.ssl. SSLSocketImpl. Функция getOutputStream() этого класса возвращает sun.security.ssl. AppOutputStream. Класс AppOutputStream реализует функцию write(). Благоразумно понаблюдав за этим, я увидел кое-что, что выглядело немного подозрительно. Было несколько строк, чтобы решить, сколько байтов данных поместить в запись SSL:

При определенных обстоятельствах, если isFirst Запись Полезной Нагрузки и c.need To Split Payload() имеет значение true, он выбирает не более 1 байта в запись SSL. Это именно то, что видел клиент и что было причиной проблемы. Но оказалось, что это было сделано намеренно и не было ошибкой в JDK. Но почему? И что в методе нужно для разделения полезной нагрузки()? Это метод в классе SSLSocketImpl. Прочитав об этом подробно, я понял, что это оказалось обходным решением проблемы безопасности с TLSv1.0 и старше. К сожалению, исходный код стороннего клиента не смог справиться с этим обходным путем.

К счастью, сотрудники Sun (теперь называемой Oracle) предвидели, что обходной путь может вызвать проблемы с совместимостью, поэтому они предоставили способ отключить его, установив системной переменной jsse.enableCBCProtection значение false. У нас был выбор между отключением обходного пути, установив системному свойству jsse.enableCBCProtection значение false, что сделало бы программное обеспечение уязвимым для уязвимости безопасности, или убедившись, что мы используем TLSv1.1 или новее, что в конце концов решило сделать руководство.

Отладка– как и разработка программного обеспечения, является одновременно наукой и искусством. Вы можете преуспеть в отладке только благодаря постоянной практике, которую вы наверняка получите на протяжении всей своей карьеры. В конце концов, неизбежность жизни – это смерть, налоги и программисты, создающие ошибки.

Оригинал: “https://dev.to/vineeth/a-software-developer-s-guide-to-effective-debugging-27jn”