Apakah mencetak ke konsol / stdout strategi debugging yang baik?


11

Katakanlah kita memiliki fungsi seperti ini:

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;
}

Sekarang untuk alasan apa pun, kode kita tidak berfungsi. Mungkin itu melempar kesalahan, mungkin mengembalikan nilai yang salah, mungkin terjebak dalam loop yang tak terbatas.

Hal pertama yang dilakukan programmer tahun pertama, adalah mencetak ke konsol / std, (setelah mempelajari cara mencetak Hello World sebelum belajar menggunakan debugger).

Misalnya untuk men-debug kode ini mereka mungkin melakukan hal berikut:

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;
}

Sekarang mereka menjalankan kode, mereka mendapatkan cetakan konsol besar, yang dapat mereka lacak untuk melacak di mana ada masalah.

Alternatif tentu saja, adalah untuk mengatur breakpoint dan melangkah melalui kode di setiap titik.

Satu keuntungan utama dari mencetak ke konsol, adalah bahwa pengembang dapat melihat aliran nilai-nilai dalam sekali jalan, tanpa harus mengklik langkah-langkah dll.

Tetapi kerugiannya adalah, kode Anda kemudian penuh dengan semua pernyataan cetak ini yang kemudian harus dihapus.

(Apakah mungkin memberi tahu debugger untuk mencetak hanya nilai tertentu ke log ?, breakpoints kemudian dapat dengan mudah ditambahkan atau dihapus tanpa benar-benar memodifikasi kode.)

Saya masih menggunakan pencetakan konsol sebagai metode debugging utama, saya bertanya-tanya seberapa umum / efektifnya ini dibandingkan dengan sesuatu yang lain di luar sana.


1
Anda perlu mempelajari cara menggunakan debugger dan menggunakan kerangka kerja logging yang benar. Ini akan membuat Anda jauh lebih bahagia daripada mencetak ke konsol (itu tidak selalu ada).

7
Penting untuk belajar menggunakan debugger, namun, ada banyak situasi yang mungkin Anda temui di mana printf debugging adalah satu - satunya metode debugging yang tersedia.
whatsisname

Jawaban:


26

Pernyataan cetak dan debugger tidak saling eksklusif. Mereka hanyalah alat berbeda yang tersedia untuk Anda untuk menemukan / mengidentifikasi bug. Ada orang-orang yang akan mengklaim bagaimana mereka tidak pernah menyentuh debugger dan ada orang-orang yang tidak memiliki pernyataan logging / cetak tunggal di mana pun dalam kode yang mereka tulis. Saran saya adalah Anda tidak ingin berada di salah satu dari kelompok itu.

Alih-alih belajar menggunakan logging dan belajar menggunakan debugger. Dengan pengalaman Anda akan (hampir tanpa harus memikirkannya) memilih alat yang tepat dan menyelesaikan pekerjaan dengan akurat dan efisien. Tanpa pengalaman, kadang-kadang Anda akan memilih satu dari yang lain, dan mungkin itu akan membawa Anda sedikit lebih lama melihat-lihat variabel atau memilah-milah file log, tapi itu semua adalah bagian dari proses pembelajaran.

Jadi, untuk menjawab pertanyaan spesifik Anda. Iya. Menggunakan cetakan untuk melacak eksekusi adalah strategi debugging yang baik dan banyak digunakan. Namun...

Alih-alih menggunakan pernyataan cetak, pertimbangkan untuk menggunakan kerangka kerja logging. Kerangka kerja logging memiliki konsep level logging sehingga Anda dapat menambahkan sejumlah pesan log tetapi memilih level untuk masing-masing. Ketika aplikasi Anda berjalan dalam kondisi normal, level Anda akan KESALAHAN atau PERINGATAN sehingga hanya hal-hal penting yang dilaporkan. Namun ketika Anda menelusuri kode dan perlu memahami alur eksekusi, Anda dapat mengubah logger menjadi INFO atau DEBUG dan sekarang semua pernyataan "cetak" yang sudah Anda miliki dalam kode akan melaporkan info tambahan.

Menggunakan kerangka kerja logging ...

  1. Anda tidak perlu menghapus semua cetakan setelah Anda selesai.
  2. cetakan yang Anda tinggalkan dalam kode, dapat membantu Anda atau pengembang lain men-debug kode yang sama di masa mendatang
  3. Anda dapat men-debug kode ini di bidang tanpa harus membangunnya kembali setiap kali hanya untuk menambahkan cetakan yang Anda hapus.
  4. Anda akan dapat mengarahkan kembali pencatatan pesan di mana pun Anda inginkan, bukan hanya konsol. Mereka dapat pergi ke file, syslog, DB, socket ... dll

Pembaruan: Saya baru saja memperhatikan di bagian akhir Anda bertanya, "Apakah mungkin memberi tahu debugger untuk mencetak hanya nilai tertentu ke log". Bergantung pada debugger mana yang Anda gunakan. Banyak debugger modern memungkinkan Anda untuk menentukan tindakan untuk dipanggil ketika breakpoint terkena. Dalam beberapa (saya sudah melakukan ini dalam VS dan WinDbg), dimungkinkan untuk menentukan "cetak ini dan lanjutkan". Visual Studio menyebutnya "tracepoints" alih-alih "breakpoints"


+1 untuk paragraf pertama. Debugger dan log memecahkan dua masalah yang sangat berbeda.
Blrfl

1
Tapi jangan Anda setuju bahwa meninggalkan pernyataan log dalam kode jelek itu?
dwjohnston

1
tergantung pernyataan log apa yang Anda tinggalkan. Saya baru saja menemukan dan menghapus yang ini: "logger.error (" WHAT ")". Kalau tidak, saya memperlakukan kode logging seperti sisa kode saya. Memformatnya, membuatnya terlihat bagus dan membuatnya informatif. Ya, menaburkan pernyataan cetak setiap baris lainnya terlalu banyak dan ada saatnya saya terpaksa melakukannya. Tetapi secara umum, memiliki 10-20 pernyataan log di seluruh file (file / kelas berukuran cukup dan tidak raksasa) tidak buruk sama sekali.
DXM

Saya mendapatkan bahwa meninggalkan beberapa pernyataan log di mungkin berguna, misalnya jika Anda memiliki sistem produksi Anda mungkin ingin log berbagai variabel penting karena mereka digunakan jadi jika beberapa error yang muncul Anda dapat melihat langsung apa yang terjadi dalam produksi Anda lingkungan Hidup. Namun, untuk konteks pembangunan sepertinya berantakan. Misalnya, Anda sedang menulis fungsi parsing Anda, dan Anda belum memiliki regex yang benar - jadi Anda memasukkan serangkaian pernyataan log hanya untuk memeriksa apa yang terjadi, dan akhirnya mengatasinya. Saya tidak berpikir itu menambah nilai untuk meninggalkan mereka.
dwjohnston

1
@Izkata: itu semua akan tergantung pada spesifikasi bug spesifik Anda dan pada seberapa banyak logging kode Anda sudah lakukan. Poin yang saya coba sampaikan adalah bahwa selalu ada nilai memiliki pernyataan logging dan memilikinya di tingkat yang berbeda: ERR -> PERINGATAN ... -> DEBUG. Jika Anda membutuhkan lebih banyak untuk sesuatu yang sangat spesifik, tentu saja mulai menambahkan pernyataan cetak. Tetapi jawaban saya kepada seseorang yang menggunakan "cetak" sebagai pernyataan log, akan selalu beralih ke kerangka kerja dan mulai menggunakannya.
DXM

3

Loging / printing dan debuggers adalah teknik pelengkap yang memiliki kekuatan dan kelemahan yang berbeda - yang terbaik adalah menggunakan keduanya. Tapi secara keseluruhan, saya akan mengatakan bahwa debugger adalah alat yang unggul dalam banyak kasus dan harus digunakan terlebih dahulu, dengan penebangan / pencetakan hanya digunakan untuk hal-hal yang sebenarnya lebih baik.

Keuntungan dari debuggers:

  • Anda dapat memeriksa seluruh kondisi program, bukan hanya nilai yang Anda pikir akan dicetak sebelumnya. Ini secara besar - besaran dapat mempercepat proses debugging dengan mengurangi siklus umpan balik menjadi kurang dari satu detik. Terutama penting ketika dibutuhkan beberapa saat untuk mencapai bug.
  • Anda dapat melihat dari mana panggilan berasal dan bahkan memeriksa nilai di atas tumpukan jejak.
  • Anda dapat (sampai taraf tertentu tergantung pada bahasa / platfrom) kode debug yang tidak dapat Anda modifikasi dengan mudah karena Anda hanya memiliki kode biner atau byte yang dikompilasi.

Keuntungan dari Pencatatan / pencetakan:

  • Tidak memerlukan build debug atau konfigurasi khusus. Selalu berhasil.
  • Dapat digunakan untuk menganalisis kesalahan yang sulit direproduksi dan jarang terjadi
  • Dapat digunakan untuk menganalisis kesalahan tergantung waktu di mana jeda yang disebabkan oleh debugger dapat dengan mudah membuat bug menghilang.
  • Memberi Anda informasi permanen yang dapat dianalisis di waktu luang Anda. Anda dapat melompat bolak-balik antara output di berbagai titik dalam aliran program.

Keuntungan lain dari pencatatan adalah ketika Anda hanya mengalami masalah saat melewati kesekian melewati kode Anda dan benar-benar dapat menggunakan beberapa jejak balik bagaimana Anda sampai di sana. Sebagian besar debugger tidak memiliki tombol mundur, tetapi mencatat nilai apa yang dipanggil oleh fungsi tingkat yang lebih tinggi akan berfungsi, dan seringkali paling tidak membuat Anda lebih dekat ke kasing kecil yang dapat direproduksi.
Christopher Creutzig

1

Mencetak ke keluaran standar dengan cara bisa menjadi strategi yang baik untuk men-debug kode Anda, misalnya

  • saya menggunakan banyak pernyataan cetak untuk melihat apa yang terjadi di berbagai tingkat kode saya terutama jika saya tidak sepenuhnya memahami kesalahan

  • atau mungkin kesalahan tidak memiliki informasi terperinci yang mungkin mengarahkan saya ke bagian kode yang sebenarnya yang menyebabkan masalah.

Namun Anda harus terbiasa dengan alat debugging, ada banyak di luar sana tergantung pada bahasa atau platform apa yang Anda gunakan.

Juga metode lain adalah logging, saya mencatat kesalahan sepanjang waktu ketika bekerja pada aplikasi Android, juga dengan penanganan pengecualian, seseorang dapat dengan mudah mencatat jejak stack atau pesan kesalahan pengecualian yang diangkat.


3
posting ini agak sulit dibaca (dinding teks). Maukah Anda mengeditnya menjadi bentuk yang lebih baik?
nyamuk

Saya membuatnya agak mudah dibaca. Maaf untuk yang sebelumnya!
Plaix
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.