การพิมพ์ไปที่ 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;
}

ตอนนี้ไม่ว่าด้วยเหตุผลใดรหัสของเราไม่ทำงาน บางทีมันกำลังโยนข้อผิดพลาดบางทีมันอาจจะคืนค่าผิดบางทีก็ติดอยู่ในวงวนไม่สิ้นสุด

สิ่งแรกที่โปรแกรมเมอร์คนแรกในปีแรกคือพิมพ์ไปที่ console / std out (เรียนรู้วิธีพิมพ์ 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;
}

ตอนนี้พวกเขาเรียกใช้รหัสพวกเขาได้รับการพิมพ์คอนโซลขนาดใหญ่ซึ่งพวกเขาสามารถผ่านการติดตามในสิ่งที่ผิดพลาด

อีกทางเลือกหนึ่งของหลักสูตรคือการกำหนดจุดพักและขั้นตอนผ่านรหัสในแต่ละจุด

ข้อได้เปรียบที่สำคัญอย่างหนึ่งของการพิมพ์ไปยังคอนโซลคือผู้พัฒนาสามารถเห็นการไหลของค่าในครั้งเดียวโดยไม่ต้องคลิกผ่านขั้นตอนอื่น ๆ

แต่ข้อเสียคือรหัสของคุณจะเต็มไปด้วยงบการพิมพ์เหล่านี้ที่จะต้องถูกลบออก

(เป็นไปได้ไหมที่จะบอกให้ดีบักพิมพ์เฉพาะค่าบางอย่างออกไปยังบันทึกหรือไม่จุดพักสามารถเพิ่มหรือเอาออกได้อย่างง่ายดายโดยไม่ต้องแก้ไขรหัส)

ฉันยังคงใช้การพิมพ์คอนโซลเป็นวิธีการตรวจแก้จุดบกพร่องหลักฉันสงสัยว่านี่เป็นเรื่องธรรมดา / มีประสิทธิภาพเมื่อเทียบกับสิ่งอื่นที่มีอยู่


1
คุณต้องเรียนรู้วิธีใช้ดีบักเกอร์และใช้กรอบการบันทึกที่เหมาะสม มันจะทำให้คุณมีความสุขมากกว่าการพิมพ์ไปที่คอนโซล (ซึ่งไม่มีอยู่จริง)

7
สิ่งสำคัญคือการเรียนรู้การใช้ดีบั๊กอย่างไรก็ตามมีหลายสถานการณ์ที่คุณอาจพบเมื่อการดีบัก printf เป็นวิธีการแก้ไขข้อบกพร่องเพียงอย่างเดียว
whatsisname

คำตอบ:


26

พิมพ์คำสั่งและดีบักเกอร์ซึ่งไม่ได้เกิดร่วมกัน พวกเขาเป็นเพียงเครื่องมือที่แตกต่างกันสำหรับคุณในการค้นหา / ระบุข้อบกพร่อง มีผู้ที่อ้างว่าพวกเขาไม่เคยสัมผัสตัวดีบั๊กและมีคนที่ไม่มีคำสั่งการบันทึก / พิมพ์เดียวที่ใดก็ได้ในรหัสที่พวกเขาเขียน คำแนะนำของฉันคือคุณไม่ต้องการอยู่ในกลุ่มใดกลุ่มหนึ่ง

แทนที่จะเรียนรู้การใช้การบันทึกและเรียนรู้การใช้ดีบักเกอร์ ด้วยประสบการณ์ที่คุณจะ (เกือบจะไม่ต้องคิด) เลือกเครื่องมือที่เหมาะสมและทำงานให้ถูกต้องและมีประสิทธิภาพ หากไม่มีประสบการณ์บางครั้งคุณอาจเลือกอย่างใดอย่างหนึ่งและบางทีคุณอาจต้องใช้เวลาอีกนิดหน่อยในการเปลี่ยนตัวแปรหรือกลั่นกรองไฟล์บันทึก แต่นั่นเป็นส่วนหนึ่งของกระบวนการเรียนรู้ทั้งหมด

ดังนั้นเพื่อตอบคำถามเฉพาะของคุณ ใช่. การใช้งานพิมพ์เพื่อติดตามการดำเนินการเป็นสิ่งที่ดีและมีการใช้กลยุทธ์การดีบักอย่างกว้างขวาง อย่างไรก็ตาม ...

แทนที่จะใช้คำสั่งพิมพ์พิจารณาการใช้กรอบการเข้าสู่ระบบ เฟรมเวิร์กการบันทึกมีแนวคิดของระดับการบันทึกเพื่อให้คุณสามารถเพิ่มข้อความล็อกจำนวนมาก แต่เลือกระดับสำหรับแต่ละข้อความ เมื่อแอปพลิเคชันของคุณทำงานภายใต้สภาวะปกติระดับของคุณจะเป็นข้อผิดพลาดหรือคำเตือนเพื่อให้รายงานเฉพาะสิ่งที่สำคัญเท่านั้น อย่างไรก็ตามเมื่อคุณติดตามรหัสและจำเป็นต้องเข้าใจขั้นตอนการดำเนินการคุณสามารถเปลี่ยน Logger เป็น INFO หรือ DEBUG และตอนนี้คำสั่ง "พิมพ์" ทั้งหมดที่คุณมีในรหัสจะรายงานข้อมูลเพิ่มเติม

กำลังใช้กรอบการบันทึก ...

  1. คุณไม่จำเป็นต้องลบงานพิมพ์ทั้งหมดหลังจากทำเสร็จแล้ว
  2. ภาพพิมพ์ที่คุณทิ้งไว้ในรหัสสามารถช่วยคุณหรือนักพัฒนาซอฟต์แวร์อื่นแก้จุดบกพร่องรหัสเดียวกันในอนาคต
  3. คุณจะสามารถดีบักรหัสนี้ในฟิลด์โดยไม่ต้องสร้างใหม่ทุกครั้งเพื่อเพิ่มงานพิมพ์ที่คุณลบ
  4. คุณจะสามารถเปลี่ยนเส้นทางข้อความบันทึกได้ทุกที่ที่คุณต้องการไม่ใช่แค่คอนโซล พวกเขาสามารถไปที่ไฟล์ syslog, DB, socket ... เป็นต้น

อัปเดต: ฉันเพิ่งสังเกตเห็นในตอนท้ายที่คุณถามว่า "เป็นไปได้หรือไม่ที่จะบอกให้ดีบั๊กพิมพ์ค่าบางอย่างออกจากระบบ" ขึ้นอยู่กับดีบักเกอร์ที่คุณใช้ ตัว debuggers ที่ทันสมัยจำนวนมากอนุญาตให้คุณกำหนดการกระทำที่จะเรียกใช้เมื่อมีการตีเบรกพอยต์ ในบางส่วน (ฉันเคยทำสิ่งนี้ใน VS และ WinDbg) เป็นไปได้ที่จะระบุ "พิมพ์และดำเนินการต่อ" Visual Studio เรียกพวกเขาว่า "tracepoints" แทน "เบรกพอยต์"


+1 สำหรับวรรคแรก ตัวแก้จุดบกพร่องและบันทึกแก้ปัญหาที่แตกต่างกันสองอย่าง
Blrfl

1
แต่คุณไม่เห็นด้วยว่าการออกจากบันทึกการใช้งานในรหัสนั้นน่าเกลียด?
dwjohnston

1
ขึ้นอยู่กับชนิดของคำสั่งบันทึกที่คุณออก ฉันเพิ่งพบและลบอันนี้: "logger.error (" WHAT ")" มิฉะนั้นฉันปฏิบัติกับรหัสการบันทึกเช่นเดียวกับส่วนที่เหลือของรหัสของฉัน จัดรูปแบบทำให้ดูดีและทำให้เป็นข้อมูล ใช่โรยคำสั่งพิมพ์ทุกบรรทัดอื่น ๆ น้อยเกินไปและมีบางครั้งที่ฉันต้องหันไปที่ แต่โดยทั่วไปแล้วการมีคำสั่งบันทึก 10-20 ไฟล์ทั้งหมด (ไฟล์ / คลาสมีขนาดที่สมเหตุสมผลและไม่ใหญ่โต) ก็ไม่เลวเลย
DXM

ฉันได้รับที่ออกจากงบบันทึกบางอย่างในอาจจะมีประโยชน์ตัวอย่างเช่นถ้าคุณมีระบบการผลิตที่คุณอาจต้องการที่จะเข้าสู่ระบบตัวแปรสำคัญต่างๆที่พวกเขากำลังใช้ดังนั้นหากมีข้อผิดพลาดบางอย่างไม่ปลูกขึ้นคุณสามารถมองเห็นได้ทันทีว่าเกิดอะไรขึ้นในการผลิตของคุณ สิ่งแวดล้อม อย่างไรก็ตามสำหรับบริบทของการพัฒนาดูเหมือนว่าจะยุ่งเหยิง ตัวอย่างเช่นคุณกำลังเขียนฟังก์ชันการแยกวิเคราะห์และคุณไม่มี regex ของคุณค่อนข้างถูกต้อง - ดังนั้นคุณใส่ชุดของคำสั่งบันทึกเพื่อตรวจสอบสิ่งที่เกิดขึ้นและในที่สุดก็เรียงลำดับ ฉันไม่คิดว่ามันจะเป็นการเพิ่มคุณค่าในอนาคตที่จะปล่อยให้พวกเขาเข้ามา
dwjohnston

1
@Izkata: ทั้งหมดขึ้นอยู่กับข้อผิดพลาดเฉพาะของคุณและการบันทึกรหัสของคุณแล้ว จุดที่ฉันพยายามที่จะแก้ไขคือมีค่าของการมีคำสั่งการบันทึกและให้พวกเขาในระดับที่แตกต่างกัน: ERR -> WARN ... -> DEBUG หากคุณต้องการสิ่งที่เฉพาะเจาะจงมากขึ้นแน่นอนว่าโดยเริ่มเพิ่มคำสั่งพิมพ์ แต่คำตอบของฉันต่อคนที่ใช้ "พิมพ์" เป็นคำสั่งบันทึกจะถูกเปลี่ยนเป็นกรอบงานและเริ่มใช้มัน
DXM

3

การบันทึก / การพิมพ์และ debuggers เป็นเทคนิคเสริมที่มีความแข็งแรงและจุดอ่อนต่างกัน - ควรใช้ทั้งสองอย่าง แต่โดยรวมแล้วฉันบอกว่าเครื่องมือดีบั๊กเป็นเครื่องมือที่ดีที่สุดในกรณีส่วนใหญ่และควรใช้ก่อนด้วยการบันทึก / พิมพ์ใช้สำหรับสิ่งที่ดีกว่าจริง ๆ เท่านั้น

ข้อดีของการ debuggers:

  • คุณสามารถตรวจสอบสถานะโปรแกรมทั้งหมดไม่เพียง แต่ค่าที่คุณคิดว่าจะพิมพ์ออกมาล่วงหน้า นี้สามารถอย่างหนาแน่นเพิ่มความเร็วในการแก้จุดบกพร่องโดยการลดรอบการตอบรับที่จะน้อยกว่าที่สอง สำคัญอย่างยิ่งเมื่อต้องใช้เวลาในการเข้าถึงข้อบกพร่อง
  • คุณสามารถดูได้ว่าการโทรมาจากที่ไหนและยังตรวจสอบค่าการติดตามสแต็ก
  • คุณสามารถ (ในระดับที่ขึ้นอยู่กับภาษา / platfrom) รหัสการแก้ปัญหาที่คุณไม่สามารถแก้ไขได้อย่างง่ายดายเพราะคุณมีเพียงไบนารีที่รวบรวมหรือรหัสไบต์

ข้อดีของการบันทึก / พิมพ์:

  • ไม่จำเป็นต้องมีการตรวจแก้จุดบกพร่องพิเศษหรือการกำหนดค่า มันได้ผลเสมอ
  • สามารถใช้ในการวิเคราะห์ข้อผิดพลาดที่ยากที่จะทำซ้ำและเกิดขึ้นน้อยครั้ง
  • สามารถใช้ในการวิเคราะห์ข้อผิดพลาดขึ้นอยู่กับเวลาที่การหยุดชั่วคราวที่เกิดจากดีบักเกอร์สามารถทำให้บั๊กหายไปได้อย่างง่ายดาย
  • ให้ข้อมูลถาวรที่คุณสามารถวิเคราะห์ได้ในยามว่าง คุณสามารถข้ามไปมาระหว่างผลลัพธ์ที่จุดต่าง ๆ ในผังโปรแกรม

ข้อได้เปรียบอีกประการของการบันทึกคือเมื่อคุณพบปัญหาเมื่อรหัสผ่านที่เท่าไรไม่ทราบและสามารถใช้ backtrace ได้จริง ๆ ว่าคุณไปถึงที่นั่นได้อย่างไร โปรแกรมดีบั๊กส่วนใหญ่ไม่มีปุ่มย้อนกลับ แต่บันทึกสิ่งที่ฟังก์ชั่นระดับสูงกว่าถูกเรียกใช้ด้วยจะทำงานได้และอย่างน้อยคุณก็จะเข้าใกล้กรณีที่ทำซ้ำได้ขนาดเล็ก
Christopher Creutzig

1

ตัวอย่างเช่นการพิมพ์ไปยังเอาต์พุตมาตรฐานอาจเป็นกลยุทธ์ที่ดีในการดีบักโค้ดของคุณ

  • ฉันใช้คำสั่งการพิมพ์จำนวนมากเพื่อดูว่าเกิดอะไรขึ้นในระดับต่าง ๆ ของรหัสของฉันโดยเฉพาะถ้าฉันไม่เข้าใจข้อผิดพลาดอย่างสมบูรณ์

  • หรือข้อผิดพลาดอาจไม่มีข้อมูลรายละเอียดใด ๆ ที่อาจชี้ให้ฉันเห็นว่าส่วนใดของรหัสที่ทำให้เกิดปัญหา

อย่างไรก็ตามคุณจำเป็นต้องคุ้นเคยกับการแก้ไขข้อบกพร่องของเครื่องมือมีจำนวนมากขึ้นอยู่กับภาษาหรือแพลตฟอร์มที่คุณใช้

อีกวิธีหนึ่งคือการบันทึกฉันบันทึกข้อผิดพลาดตลอดเวลาเมื่อทำงานกับแอปพลิเคชัน Android รวมถึงการจัดการข้อยกเว้นเราสามารถบันทึกการติดตามสแต็กหรือข้อความแสดงข้อผิดพลาดของข้อยกเว้นที่เกิดขึ้นได้อย่างง่ายดาย


3
โพสต์นี้ค่อนข้างอ่านยาก (ผนังข้อความ) คุณจะช่วยแก้ไขมันให้เป็นรูปร่างที่ดีขึ้นได้ไหม
ริ้น

ฉันทำให้อ่านได้เล็กน้อย ขออภัยก่อนหน้านี้!
Plaix
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.