Является ли печать в console / stdout хорошей стратегией отладки?

11

Допустим, у нас есть такая функция:

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

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

Первым делом любого программиста первого года обучения является вывод на консоль / стандартный вывод (научившись печатать Hello World, прежде чем научиться использовать отладчик).

Например, для отладки этого кода они могут сделать следующее:

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Теперь они запускают код, получают распечатку большой консоли, через которую они могут проследить, где что-то идет не так.

Альтернативой, конечно, является установка точек останова и пошаговое выполнение кода в каждой точке.

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

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

(Возможно ли, возможно, сказать отладчику печатать только определенные значения в журнале ?, точки останова могут быть легко добавлены или удалены без фактического изменения кода.)

Я все еще использую консольную печать в качестве основного метода отладки, мне интересно, насколько это распространено / эффективно по сравнению с чем-то еще.

dwjohnston
источник
1
Вы должны научиться использовать отладчик и использовать правильную структуру ведения журналов. Это сделает вас намного счастливее, чем печатать на консоли (это не всегда существует).
7
Важно научиться использовать отладчики, однако во многих ситуациях вы можете столкнуться с тем, что отладка printf является единственным доступным методом отладки.
whatsisname

Ответы:

26

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

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

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

Вместо использования операторов печати рассмотрите возможность использования каркаса ведения журнала. Каркасы журналов имеют концепцию уровней журналирования, поэтому вы можете добавить целую кучу сообщений журнала, но выбрать уровень для каждого из них. Когда ваше приложение работает в нормальных условиях, ваш уровень будет ОШИБКА или ПРЕДУПРЕЖДЕНИЕ, так что будут сообщаться только важные вещи. Однако, когда вы просматриваете код и вам необходимо понять поток выполнения, вы можете изменить регистратор на INFO или DEBUG, и теперь все те операторы «print», которые у вас уже есть в коде, сообщат дополнительную информацию.

Использование каркаса логирования ...

  1. Вам не нужно будет удалять все отпечатки после того, как вы закончите.
  2. Отпечатки, которые вы оставите в коде, могут помочь вам или любому другому разработчику отладить этот же код в будущем.
  3. вы сможете отлаживать этот код в поле без необходимости перестраивать его каждый раз, просто добавляя отпечатки, которые вы удалили.
  4. вы сможете перенаправлять сообщения регистрации куда угодно, а не только на консоль. Они могут перейти в файл, системный журнал, БД, сокет и т. Д.

Обновление: я только заметил, что в конце вы спрашивали: «Возможно ли, возможно, сказать отладчику распечатать только определенные значения в журнале». В зависимости от того, какой отладчик вы используете. Многие современные отладчики позволяют вам определять действие, которое будет вызываться при достижении точки останова. В некоторых (я сделал это в VS и WinDbg), можно указать «напечатать это и возобновить». Visual Studio называет их «точками трассировки» вместо «точек останова»

DXM
источник
+1 за первый абзац. Отладчики и логи решают две совершенно разные задачи.
Blrfl
1
Но разве вы не согласны с тем, что если оставить в журнале операторы журнала, это может испортить ситуацию?
dwjohnston
1
зависит от того, какие записи журнала вы оставляете на месте. Я только что нашел и удалил это: "logger.error (" ЧТО ")". В противном случае я обращаюсь с журнальным кодом так же, как с остальным кодом. Отформатируйте его, сделайте так, чтобы он выглядел красиво, и сделайте его информативным. Да, разбрасывать заявление о печати в каждой строке - это слишком много, и мне приходилось прибегать к этому. Но, как правило, наличие 10-20 операторов журнала во всем файле (файлы / классы имеют разумный размер и не являются гигантскими) совсем не плохо.
ДХМ
Я понимаю, что некоторые операторы журнала могут быть полезны, например, если у вас есть производственная система, вы можете регистрировать различные важные переменные по мере их использования, поэтому, если возникает какая-то ошибка , вы сразу можете увидеть, что произошло в вашей работе. окружающая обстановка. Однако для контекста развития это кажется грязным. Например, вы пишете свою функцию синтаксического анализа, и вы не совсем правильно поняли свое регулярное выражение - поэтому вы вводите серию операторов журнала просто для того, чтобы проверить, что происходит, и в конечном итоге разобраться в этом. Я не думаю, что это добавляет ценности в будущем, чтобы оставить их.
dwjohnston
1
@Izkata: все это будет зависеть от специфики вашей конкретной ошибки и от того, сколько логирования уже делает ваш код. Суть, которую я пытаюсь донести, заключается в том, что всегда полезно иметь операторы логирования и иметь их на разных уровнях: ERR -> WARN ... -> DEBUG. Если вам нужно что-то особенное, обязательно начните добавлять операторы печати. Но мой ответ кому-то, кто использует «print» в качестве оператора логирования, всегда будет переключаться на фреймворк и начинать его использовать.
ДХМ
3

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

Преимущества отладчиков:

  • Вы можете проверить все состояние программы, а не только те значения, которые вы предполагали распечатать заранее. Это может значительно ускорить процесс отладки за счет сокращения цикла обратной связи до менее чем секунды. Особенно важно, когда для устранения ошибки требуется некоторое время.
  • Вы можете видеть, откуда поступили вызовы, и даже проверять значения в трассировке стека.
  • Вы можете (в некоторой степени, в зависимости от языка / платформы) отладочный код, который вы не можете легко изменить, поскольку у вас есть только скомпилированный двоичный или байтовый код.

Преимущества регистрации / печати:

  • Не требует специальной отладочной сборки или конфигурации. Это всегда работает.
  • Может использоваться для анализа ошибок, которые трудно воспроизвести и которые встречаются редко
  • Может использоваться для анализа ошибок, зависящих от времени, когда пауза, вызванная отладчиком, может легко устранить ошибку.
  • Предоставляет вам постоянную информацию, которую вы можете анализировать на досуге. Вы можете переключаться между выходными данными в разных точках потока программы.
Майкл Боргвардт
источник
Еще одним преимуществом ведения журнала является то, что вы сталкиваетесь с проблемой только во время повторного прохождения кода и действительно можете использовать некоторую обратную связь того, как вы туда попали. Большинство отладчиков не имеют кнопки реверса, но регистрация значений, с которыми была вызвана функция более высокого уровня, будет работать, и часто, по крайней мере, приближает вас к небольшому воспроизводимому случаю.
Кристофер Кройциг
1

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

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

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

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

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

Plaix
источник
3
этот пост довольно трудно читать (стена текста). Не могли бы вы изменить его в лучшую форму?
комнат
Я сделал это немного читабельным. Извините за предыдущий!
Plaix