Pull to refresh

Comments 135

Сам так делал, но обычно, когда по-быстрому проблему не удалось обнаружить.
Согласен. Сам к этому пришел со-временем. А раньше думал, что эта мысль — мое изобретение =)
Самый ценный совет дала мне как-то преподаватель математики: «Если что-то не получается — отвлекитесь, заварите чай, и попробуйте снова». Конечно она говорила про математику, но это не важно.
Я иду покурить в таких случаях :)
Думаю она просто не курит :-)
Гораздо лучше — это легкая пробежка или не сложные физические упражнения.
На своем опыте такого рода отвлечение гораздо эффективнее.
Сложные физические (которые на предел собственных возможностей) тоже хорошо работают =)
Работают, в моем случае только потом руки трясуться и по клавишам не попадают :)
Обычно встаю из-за ноутбука и начинаю на автомате ходить по комнате, иногда ложусь на кровать или хожу по ней. И надо сказать, очень помогает для разбора ошибок или продумывания архитектуры.
Не могу вспомнить и нагуглить автора:

«Поставьте на рабочий стол бутылку с водой и периодически отпивайте из неё: организм сам подскажет, когда сделать перерыв»

ps: подскажите автора, не успокоюсь, пока не узнаю :-)
UFO landed and left these words here
Только вот коллеги сначала недоумевали, когда я внезапно вставал от компьютера и начинал отжиматься…
И я уходил курить… и именно когда курил у меня пред глазами все проплывало и появлялись решения или идеи.
После того как бросил, производительность ощутимо снизилась и как-то уже почти на нет сходит все.
Вон, выше замечательный совет: физические упражнения. На работе я их делать не пробовал, но самые замечательные и далеко идущие идеи касательно разработки складывались в моей голове дома, во время тренировки. С курением сравнить не могу, ибо никогда не курил, но факт. Кофе/чай, по моему опыту, помогают не уснуть, но прозрений не вызывают.
Самый вредный совет: «Если что-то не получается — перенесите это на следующий день!».
Если не получается вечером, то может не такой уж и плохой. Иногда устаешь за день и банальных вещей не видишь, не получается сделать что нужно. А бывает получается, но утром по пути на работу понимаешь, что нужно было сделать и переписываешь.
Не откладывай на завтра то, что можно сделать послезавтра.
ага, если хочется работать, ляг поспи и все пройдет :)
Еще один неплохой способ отвлечся для фрилансеров, например, это приготовление еды :)
По личному наблюдению скажу, многие порой непонимают необходимость отвлечся и сделать перерыв.
это аргументы в спор «отладчик» против «debug out»
сам как то привые к debug out, и замечал за сабой, что попав в IDE с отладчиком, трачу КУЧУ времени в отладчике, ибо это вроде бы проще
у меня получалось наоборот

имхо в контексте поста, debug out заставляет задуматься о тот где и почему грабля
отладчик же предлагает поставить бряк и посмотреть

а по большому счету — кто к чему привык
Я дебаглю так, пишу сразу весь код, пускаю, убираю синтаксические ошибки, а логику проверяю тестированием.
А потом, конечно же, автоматические тесты ну совершенно лень, не так ли? Ведь все работает!
Будь прокляты эти автотесты.
Да грешен, не тестирую авто, тестирую руконеграми.
Я лично вообще не понимаю, как можно тестить автоматически. Особенно части, где требуется до хрена других частей для работы — куча объектов, созданных в других этапах там…
Внешние к тестируемому коду части системы заменяются фейковыми версиями. В динамических языках это очень просто; в какой-нибудь джаве при нормальной архитектура вполне доступно.
Так в том-то и прикол что фейковые данные отражают лишь один вариант развития событий. Писать по десять-двадцать-сто вариантов?
Именно. Рассматривайте тесты как документацию к коду, формализованную запись ТЗ. Если у вас десять-двадцать-сто вариантов исполнения, они же должны всё равно должны быть документированы. Кстати, это не означает, что нужно писать сто тестов — создаём массив входных значений, массив ожидаемых выходных и прогоняем его в цикле.
Добивайтесь хорошего покрытия и тестируйте граничные случаи (второе в принципе входит в первое).
Я почему не сдержался… У меня тут масса коллег в принципе тестирование одобряет, но сути не понимает: тесты пишутся ДО кода. Даже и особенно продуманного кода.

После всегда бывает лень.
Это только в TDD. TDD — не аксиома.
Аксиомы — удел математиков, оставим поэзию.

Я сведу мысль к следующему:

1. Тесты при адекватном использовании и некоторой дисциплине тупо облегчают вам и окружающим работу. Особенно в крупных проектах!

2. Тесты после написания кода делать либо лень, либо они пишутся только в самом банальном случае.

Как вариант тесты можно писать и после создания кода, но до внесения в него изменений. Обнаружили баг (неожидаемое поведение) — пишем тест, который проваливается и исправляем баг, чтобы тест прошёл. Изменились требования — аналогично. Захотели сделать рефакторинг — наоборот, пишем тест, который проходит (фиксируем поведение) и исправляем код чтобы тест всё ещё проходил. Эффективность ниже чем при «тру» TDD (не всегда можно, даже глядя на код и зная изменения, адекватно покрыть тестами все эффекты изменений), но намного лучше чем ничего.
и тогда как быть, если запуск и прогон всего кода вообще очень тяжел? Скажем, в софтине сотни тысяч строк, и работать она должна на 196-гигабайтном сервере? Да руконегры отвалятся тестировать подсистемы!

А в тестиках можно и новую подсистемку отдельно на локальной машине отладить; и после рефакторинга видеть, что нифига не посыпалось на чужом участке…
А как UI тестить? Вот у меня простой код:
circle.slideTo( 100, 200 )


Круг должен за 1 секунду переехать в другую точку. Какие юнит тесты писать?
А то обычно в примерах юнит-тестов ставится всякая фигня, типа тестинг «return 2+2».
Блин, у меня редко бывают ошибки в примитивной логике.
У меня ошибки в неправильном затирании при быстром движении объекта, ошибки сихронизации и баги из-за разных оптимизаций.
Вот как это всё проюниттестить?
Подменить таймер, сделать его синхронным или просто очень быстрым.

timer.fake();
circle.slideTo(x,y);
timer.jumpTo(1); // sec
assert
И как это поможет проверить, что оно плавно переместилось из точки А в точку Б? Если цель проверить, находится ли оно в конце через секунду, то можно ассерт просто через секунду кинуть:

circle.slideTo(x,y);
timer.after( 1000, (
  if (circle.at(x,y)) assert;
));

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

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

Это уже по необходимости скорее делают, нежели на регулярной основе.
Тестируйте каждые 10 мс. Один раз. Вернее все основные сценарии использования и особые случаи по одному разу отдельно от остальных систем. А при использование функции в UI тестируйте не как она работает, а что она в принципе вызывается (создавайте мок) с нужными параметрами или если текущий тест проверяет что-то другое, то просто пустой вызов, возможно возвращающий значение (стаб) — её работа у вас уже оттестирована должна быть к тому моменту.
> ассерт просто через секунду

Ну, я, как параноик, исходил из того, что исходный пример примитивен и служит вектором.
А если это запрос к базе? Или hanging get какой нетривиальный? Или хотя бы просто анимация с неизвестным временем/расстоянием?

Или, что более реалистично — таких ассертов через секунду на проект набирается на полчаса? Чем быстрее тесты выполняются, тем чаще их запускают.

> плавно
Ну, товарищ, у вас и запросы. Не «живо», не «рывками», а именно «плавно». И еще если там easing какой хитрый, его также желаете протестировать? А если еще эта анимация кореллирует с другими?

Режьте реальность там, где вам удобно. И достаточно. И — имхо — помельче и попроще.
Если хватит протестированного перемещения от и до за нужное время — нужен подменяемый в тестах таймер.
Нужна «плавность» — подменяйте к тому же установку координат, проверяйте с заранее рассчитанными «плавными» контрольными точками.
По опыту:

1. Ошибки синхронизации. У вас хитрая многопоточная система? Скорее всего — нет. Сейчас, насколько мне известно, почти все сводится к довольно простым паттернам, имитировать которые в тестах особой проблемы не составляет.

2. Ошибки визуализации. Какая-та часть кода визуализации всегда остается непокрытой тестами и с этим можно и нужно смириться.

3. Баги из-за оптимизаций. Если вы все же покрыли тестами хотя бы 80% системы, то ошибки после рефакторинг или мелкие фиксы ловятся на ура.

Мне довелось работать в месте, где требовали 100% покрытие тестами. И, как ни странно, оно было, и все проблемы на ура решались. И система как часики работала. Особенно кайфово было разворачивать проект в неизвестной среде: можно было просто запустить тесты, чтобы увидеть, что и где еще не настроено.
вообще одно другому не мешает, это не соперники.
здесь говорится не про «debug out», а про то КАК эта ошибка могла возникнуть.
То есть Вы уже примерно знаете, на каком этапе она произошла.
именно, с дебаг аутом сначала нужно понять что тут должно быть, а потом уже вывести.
Я напомнию, что здесь говорится о том, чтобы думать о баге не смотря в код, а если в код не смотреть, то и дебаг не добавишь.
Здесь говорится о том, чтобы подумать, как могла возникнуть ошибка, и уже можно согласно мыслям, добавить дебаг аут в нужное место или начать отлаживать с нужного места.
«Роб Пайк» разумеется. Простите, Йода попутал.
У них программы были ма-а-а-а-аленькие. Держать в голове ментальную модель даже ста тысяч строк кода уже не получится. Сейчас для решения этой задачи используют другие методики — defensive development, юнит тесты, code coverage и прочие страшные слова.
Всё зависит от способностей…
… и существующей архитектуры приложения
и даже в этом случае от способностей. Все люди разные.
Да нет таких способностей, которые позволят запихать в голову реально большие системы. Нетуть. У всех есть пределы.
Рекомендую посмотреть «Человек дождя».
А из жизненного опыта — человек который помнил полностью всю карту Москвы с маршрутами общественного транспорта (троллейбусы, автобусы, маршрутки, трамваи, метро). Так себе системка конечно.
Личный же опыт говорит о том что сложность системы конечно же усложняет степень «погружения» в неё, но всё возможно. У вас в голове система ещё более сложная.
А в Лондоне вообще все таксисты должны знать город наизусть. Ну и что? Наши программные системы еще и меняются с быстрой скоростью; плюс в принципе параметров и свойств имеют чуть больше, чем можно найти на карте Москвы или Лондона.

Статичные или медленно меняющиеся системы — для обезьян. А вот держать в голове большой поток изменений — челендж.
Ну и как классно человек дождя применял свои навыки в реальной жизни?
Такие люди опасны в большом проекте
В чём проблема держать в голове модель каждого отдельного «куска» + общую глобальную модель без подробностей?
Проблема в том что многие не могут спроектировать архитектуру приложения так, чтобы локальный кусок кода был действительно локальным куском кода.
Большие программы состоят из множества маленьких моделей. Как правило, достаточно держать в голове ту самую маленькую модель, над которой работаешь.
Большие программы состоят из множества маленьких моделей


В идеальном мире — да. В реальном мире можно скачать исходники, к примеру… хммм… ну пусть будет Firefox — и посмотреть какой «маленький кусок кода» отвечает за загрузку настроек. Чтобы, например, дописать загрузку настроек из Dropbox. Код вас приятно удивит :).
Я сужу по своему опыту. =) Разумеется, всегда найдется место говно-коду, но надо стараться его избегать. Его и дебаггером замучаешься дебажить.
Просто большинство людей не думают при программировании. В этом проблема. Пытаются нажимать на кнопки до того как проблема решена в голове.

В итоге имеем код который компилируется но работает неправильно. Человек просто не может рассказать что и как он делает. Но зато может продебажить и проверить состояние при неких входных данных (и считает что так код в его власти)
UFO landed and left these words here
Это примерно как «нужно писать хороший код и не писать плохой». Или «нужно снимать хорошие фильмы и не снимать плохие» :). Да, нужно — кто же спорит. Но в реальной жизни не получается ©.
Есть не мало примеров проектов с хорошим кодом. Так что про «не получается» — это вы зря.
Если не секрет, что есть с хорошим кодом большого размера, например от миллиона строк кода? (в маленьких проектах это все не актуально — проблемы начинаются когда кода много).
Linux Kernel? Но по моим меркам 100к строк кода на Си — это уже большой проект, я редко когда держу в голове больше сотни строк.

В проектах с миллионом строг кода без хороших абстракций, отдельных подсистем и разбиения на независимые модули — вообще жить невозможно.
А вы посмотрите, фана ради, его TCP стек. Там как раз немного строчек, тысяч десять. Я когда-то несколько месяцев потратил чтобы хотя бы прмерно разобраться как это в общих чертах работает.
построчная отладка всего на свете специализированными инструментами несколько затруднительна в РНР (пока что мне удаётся уклониться от использования XDebug — хотя это хороший инструмент, не сомневаюсь). Выходит, что РНР-программисты умнее большинства согласно этой статье :)
Когда я работал программистом — несколько раз «находил» баги и придумывал их решения: утром в трамвае по дороге на работу. Далекооо от компьютера.
Нет, совпадение, тексты различаются. Здесь перевод лучше, по моему мнению.
это перевод, все совпадения с реальными персонажами случайны.
не заметил пачку. Спасибо, оформлю.
UFO landed and left these words here
Блин, каждый раз когда читаю ваши комментарии, смотрю на ваш ник, и… вспоминаю что нужно все же перейти на Vim.

Я думаю вы понимаете про что я:).
UFO landed and left these words here
в продолжение темы:
Ищи баг в себе, а не в программе
Ничего нового не узнал. Итак понятно, что перед отладкой нужно пошевелить извилинами. Это так же очевидно, как осмотреть кусок дерева прежде, чем его обрабатывать рубанком.
Э-э-э, а зачем осматривать кусок дерева? :-/
Затем, чтобы знать, где нужно срезать. Вы же не стали бы обрабатывать бревно рубанком с закрытыми глазами? Так же и с отладкой: прежде, чем запускать отладчик, неплохо бы представлять, что происходит в коде. Приведу пример: когда я работал в Realore Studios, мы с напарником битый час пытались выяснить, где собака зарыта. Был такой кусок кода:

for (size_t i = 0; i < OBJECTS_COUNT; ++i)
    objects[i]->Draw();

В один прекрасный момент отрисовка перестала происходить. Мы исследовали код со всех сторон, запускали в отладчике — всё было «нормально»: отладчик послушно ставил точку останова на ->Draw(), код выполнялся. Перерыли всю отрисовку во всех классах — код корректный. И тут меня осенило:

for (size_t i = 0; i < OBJECTS_COUNT; ++i)
{
    int a = 0;
    objects[i]->Draw();
}

Работает! В чём же дело? А в том, что мы изначально доверились отладчику и грешили на свой код, а добрый компилятор Visual Studio 2005 просто-напросто из-за бага в нём выкидывал тело цикла, что выяснилось при дизассемблировании. А отладчик радостно ставил точку останова на инструкцию jmp в конце цикла, сука такая.

Это я к тому, что перед отладкой неплохо бы хорошенько подумать головой. С тех пор я не запускаю отладчик, пока в общих чертах не буду представлять себе, что могло бы работать не так. Особенно это актуально в связи с использованием мной компилятора DMD 2.xxx при разработке на D2 (там всё ещё бывают баги генерации кода).
Затем, чтобы знать, где нужно срезать. Вы же не стали бы обрабатывать бревно рубанком с закрытыми глазами?

Смотреть и осматривать немного разные вещи. На уроках труда я строгал куски дерева с открытыми глазами, но осматривать их нас не учили.
кстати, о чем это он бложек бобука
Чушь, взял да перевел. Зато теперь буду знать, что у бобука есть бложек.
Чушь или не чушь, но оформлять топик надо как перевод, а не как пост. Особенно если участвуете в ППА.
Бобука
image

Ваше
image

Тоже случайное совпадение и чушь?
Оригинал посмотрите :) А перевод koshak-а реально луше и приятнее читать.
в оригинале — about *how* that problem. Выбор был или перевести КАК или выделить жирным. Я решил выделить жирным. Это что, роковая ошибка? У нас даже стиль перевода разный.

А вообще, почитайте вот это blog.translate.ru/2010/05/perevod-tuda-i-obratno/
А я то думаю, откуда это дежавю.
А на хабре что, очко сыграло коментнуть
Я знаком с прекрасным разработчиком по имени Велемир. Он отлаживает именно ментально. Сначала представляет себе систему, ее работу, потом придумывает, как ее поломать, потом проделывает в голове нужные шаги, находит место, где все сломалось у него в голове, а потом ставит первый и часто единственный верный breakpoint и запускает отладку приложения.

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

Вывод один — такой метод хорош только для своего кода, который ты написал, либо для кода, который ты в состоянии быстро и досканально изучить.
>>либо для кода, который ты в состоянии быстро и досканально изучить.
А «быстро и досконально» мы чаще можем при не больших по размеру. Другими словами, если в вашем методе слишком много целей, то вынесите достижение каждой цели в отдельный метод и будет вам чуть больше счастья )

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

Можно найти локальную ошибку дебаггером, а затем выяснять уже, откуда она появилась в этом месте. С определенной точки зрения и null reference exception является локальной проблемой, на которую часто можно поставить отбойник или (о ужас) catch для приведения программы в рабочее состояние. Но ведь никто так не делает, правда?
Я конечно не занимаюсь программированием профессионально, но заметил для себя несколько моментов:
1) Если что-то никак не получается починить или реализовать здесь и сейчас — лучше отвлечься, погулять, поделать что-нибудь отвлечённое — решение само придёт.
2) Если что-то никак не получается — можно с кем-нибудь поговорить, рассказать ход мыслей вслух — как правило после этого легко догадаться самому, а человеку, который на самом деле ничего не понял сказать «спасибо», хоть и он не поймёт за что — очень многие проблемы так разрешались.
рассказать ход мыслей вслух — как правило после этого легко догадаться самому, а человеку, который на самом деле ничего не понял сказать «спасибо», хоть и он не поймёт за что

Полностью согласен, если работаю не дома, то зачастую так и происходит.
Это стандарт. Сколько раз мне так писали и я сам так кому то пишу проблему и когда отправляешь сообщение, понимаешь, как это решить. В итоге получается как то так:

11:52 я: Слушай, вот такая то проблема, как решить, что делать? Все перепробовал, не получается
11:53 я: Упс, пока писал, понял, как, спасибо
11:58 он: не за что ;)
Ещё помогает если задаёш вопрос сам себе «а какие возможные решения проблемы я могу найти?»
Т.е. проблему пытаешься решить не «в лоб» а ищещ несколько вариантов решения проблемы, а затем выбираешь наилучший.
По сути это тоже самое что и рассказать о проблеме другому человеку, только этот другой, это ты сам.
Невозможно решить проблему на том же уровне, на котором она возникла. Нужно стать выше этой проблемы, поднявшись на следующий уровень.
Альберт Эйнштейн
Проблема в том что в голове помещается модель кода в котором не больше 100к примитивов. Именно поэтому и развиваются ЯП.
Также голова очень плохо работает с динамическими моделями, взаимодействиями с произвольными временными задержками. Также плохо умещаются зависимые состояния разных компонент. И много чего еще :)
А вот по этому бы вопросу очень хотелось увидеть вменяемый топик, очень интересно! :)
Но можно выделить только определённый участок модели и проанализировать только его и не задействовать всю модель в целом. Либо проанализировать более высокие сущности (по блокам) для поиска взаимосвязей.
Мозг можно натренировать
Это уже анализ кода или чтение документации и восстановление логики работы. Если что-то пишешь — то держишь весь нужный кусок модели в голове.
А тренировать — да, надо.
У меня как то это интуитивно происходит, подумать откуда могут ноги расти у ошибки и локализовать место поиска. Странно, что автор преподает это как навык 45 уровня. По-моему, это скорее базовый навык.
А о чем собственно совет? Думать? Ну да, спасибо, кэп. Впрочем, как говорит один умный человек, большинство людей проживает свою жизнь не приходя в сознание.
совет о том, чтобы сначала думать, а потом дебажить, а не только дебажить.
Я впервые эту мысль прочитал в Макконнеле в Главе №9 стр. 223 «Компиляция метода». Очень рекомендую, если вы еще не читали.
Это абсолютно верная статья. В своей работе я почти никогда не пользуюсь дебаггером — обычно хватает «эмуляции» работы программы в голове.
Встречал другую крайность. У коллеги не было настроен хоткей для отладки, да и компьютер был слабый. Из за этого он ленился запускать отладчик и мог долго сидеть, не понимая баг средствами мозга.
Когда отладчик все таки включался, ошибка находилась довольно быстро.
В общем, я выступаю за наиболее эффективное решение. Порой отладка «в лоб» эффективна.
Бывают ситуации когда баги появляются сами по себе (ну естественно не сами по себе, а из за действий пользователей), вот только что отработало криво, а теперь снова всё идеально. И разобрав построчно весь код, так и не находишь причину. И только представление того как всё это работает может дать полную картину и найти любое узкое меcто в программе. Сам пользуюсь этим методом.
Самый лучший совет, который когда либо я получал — это иметь предельную ясность того, о чем пишешь, в мельчайших деталях, продумываю все изначально.
Кен Томпсон, бесспорно, программист 80го левела. Но такое получается только с кодом, только что написанным, либо если долго поддерживаешь один и тот же софт, то случается понять где примерно бага лишь взглянув на ее текст и прикинув в голове, как такое могло случиться.
Но в реальном мире, к сожалению, когда приходит тикет, код уже давно забыт и пишется другой. Вспомнить нереально, и даже глядя в свой код нужно какое то время, чтоб вспомнить и понять как он работает, прежде чем искать собственно багу. Не говоря уж о чужом коде. И отладчик тут как нельзя кстати приходится, не только для собственно нахождения баги, но и для понимания работы в том числе.
УРА! Наконец-то я это прочитал! А то мне никто не верил!
да, я тоже часто сперва погружался головой в код…
со временем я стал понимать — где зарыта собака…
правда не всегда это прокатывает, видно еще опыта маловато
Подумалось: современное хайку.
Ну, лично я — не Томпсон.
И построить в голове модель, учитывающую состояние всех классов на 10000 строк, сервера, входящих данных, среды и БД — просто не в состоянии.

Поэтому отлаживаться приходится неэффективными методами — трассировкой и чтением сообщений об ошибках.
может у меня проект чуть менее масштабный, но
когда внедряешь некоторую фичу — можешь задним местом почуствовать: где что и когда наебн@тся
Про чувствительность заднего места в тексте ничего не было.
Было только отладку уже случившейся ошибки на (предположитьельно) PDP-11 с 50-ю килобайтами памяти и соответствующим размером программ.
Ээх, везёт… У нас в текущем проекте классы по 4000 строк не редкость.
Возможно я параноик, но я часто пишу код и провожу его отладку в голове.

Пример:
— Еду с работы домой, в голове дописываю по дороге несколько новых функций, запускаю, исправляю найденные ошибки.
— Приезжаю домой, открываю IDE и пишу уже готовый код.
— Вуаля! Всё работает!

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

Почти все ошибки исправляю так как описано в статье, т.к. чаще всего это ошибки логики. Спасибо! Теперь я знаю что это нормально, а не шизофрения.
Забавно, что все здесь говорят об ошибках в процессе написания.
Такое ощущение, что поддержкой своего кода заниматься не приходится никому.
Можно еще исполнить его в голове и выдать результат! Тогда даже писать не нужно…
Самый ценный совет, который получил Я — сначала нужно понять, что делаешь, затем составить UML-диаграммы вариантов использования и если нужно — последовательностей. Потом уже можно думать над сущностями.
Цель — интерфейс должен соответствовать диаграмме вариантов использования на 100%. Ни больше, ни меньше. А еще лучше — и всем остальным.
Sign up to leave a comment.

Articles