Pull to refresh

Comments 24

Я даже больше скажу.

Изначально, когда прога ещё не существует, она состоит из бага на 100%: в ней всё не так, потому что её ещё и вовсе нет.

Потом бага в ней всё меньше и меньше. Асимптотически — до нуля, а в мелких проектах реально бывает ноль багов, когда ошибка округления этой асимптоты до ближайшего целого бага даёт ноль.

Поэтому нет никакого программирования, есть только дебаг. Если бы можно было точно измерить процент бага адекватными метриками, это был бы идеальный показатель прогресса.

Но, увы, метрики все крайне приближённые и нелинейные, где-то бага стало меньше, а число выловленных метриками только выросло…

Интересные мысли !)

Обычно наоборот:

Для непонятливых, краткая история. Проект Wine был основан в 1993 году. Он представлял собой проект размером 0 байт. И был идеален по архитектуре и составу. Потом в него начали добавлять баги. Проект разрастался, к проекту стали подключаться новые разработчики, которые добавляли ещё больше багов. И поэтому при каждом новом релизе принято спрашивать "Чо опять сломали?!".

Не бывает безбаговых программ, бывают недотестированные.

это и есть Test Driven Development

А как насчет "дебага тестами"? Лично я при наличии возможности стараюсь прибегать именно к нему.

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

Когда тест падает — разбираться и фиксить.

Вот внутри "разбираться и фиксить" и находится собственно дебаг. Тест показывает, что в коде есть ошибка, а дебаг - процесс поиска и устранения этой ошибки.

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

Тест чем хорош, что это автоматизированный минимально воспроизводимый (в идеале) пример бага.

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

Валидная идея)

Для прояснения - "нельзя просто так взять и начать программировать/тестировать/отлаживать программу". К отладке надо готовиться заранее.

Одна из распространённых проблем при логировании - очень неконкретные описания, например, как в вашем примере выше написано (в вашем же компоненте):

Компонент не объясняет что именно ему не понравилось "Declares multiple JSON fields..." очень расплывчатое "объяснение". Особенно с учётом того, что не указаны какие вообще данные подверглись обработке и что именно в этих данных задублировалось (не указано имя поля, которое считается дубликатом. Будет очень неприятно выяснить, что условие сработало всё-таки ложно). А самое неприятное в таких логах - абсолютная оторванность от исходного кода, когда один и тот же текст ошибки неожиданно может использоваться в нескольких местах. Если в разных функциях, то ещё может выручить stacktrace, а вот если в одной функции то всё очень плохо - контекст ошибки почти потерян. Из своей практики - я пишу уникальные коды ошибок в каждом сообщении. Найти ошибку по уникальному коду быстрее, чем с помощью stacktrace. (но это чисто субъективный подход, дело не в скорости поиска, а в точности поиска места ошибки)

Согласен, корректное описание в логах - это очень важная история)

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

Такой подход тоже вполне валиден)
Главное, чтобы в этих логах не проскакивали sensitive данные на релизных сборках)

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

спасибо вам за фидбэк !)
буду улучшаться

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

Часто помогает, например, с RecyclerView: если странно себя ведёт, сначала убираешь ItemAnimator, потом меняешь LayoutManager на дефолтный (если использовался кастомный), затем "отключаешь" часть элементов (не передаёшь их в адаптер). Когда доходит до этого, уже всё должно проясниться.

Без локализации бага можно долго тыкаться не в те места.

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

P.S:

Давай прибегнем к LayoutManager, посмотрим, что он нам скажет:

Опечатка, должен быть Layout Inspector

Полностью с вами согласен, навык убирать все лишнее также максимально важен)
Спасибо за корректировку, там дейсвительно имелся в виду Layout Inspector

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

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

как и автор, не соглашусь

у каждой проблемы есть причина, решить проблему для инженера - это сначала найти причину этой проблемы

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

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

у меня прям подгорало, когда ко мне приходили с вопросами "что могло сломать? давай предположим..."
Надысь вот приходили с проблемой: на дев-стенде в миникубе перестал работать деплой... место почистили - не помогло, перезагрузили машину - не помогло, пришли ко мне с вышеозвученным вопросом.
Оскорбились, когда я озвучил свой подход про "проблемы и причин", мол, "ты пришёл нас учить, как дебажить проблемы?" (сами меня позвали)...
а надо было всего лишь системно подойти к вопросу:
деплоймент (запрос в API) проходит, но поды не появляются, значит, нарушено взаимодействие между компонентами куба
глянул поды куба, глянул в логи, увидел инфу о том, что серты не подходят... оказалось серты протухли (надо ли говорить, что обновление сертов исправило проблему?) ...
Заняло это минут 15 с момента работы над проблемой... и да, я - разработчик, приходили девопсы ) (просто миникуб на дев-стенде поднимал я, а не они... но что от этого меняется в методах отладки?)

Согласен с вами, системный подход при нахождении причины проблемы максимально важен

а я бы дополнил ещё про смежную тему: поиск причин возникновения ошибки путём поиска места её внесения в коде через git bisect:
может пригодиться в малоизвестном проекте да ещё на непрофильном языке, но для которого достоверно известно, что баги не было в такой-то версии, и она точно есть в такой-то (к слову, валидно и наоборот: так можно найти как именно исправили проблему, но это не совсем тема дебага)
иногда это быстрее, чем пытаться дебажить

Интересная техника, спасибо, что подсветили !)

Sign up to leave a comment.