คนส่วนใหญ่ดูเหมือนจะรักษาจุดบกพร่องในฐานะศิลปะมากกว่าวิทยาศาสตร์ สำหรับคนที่นี่ซึ่งถือว่าเป็นวิทยาศาสตร์แทนที่จะเป็นศิลปะ - โดยปกติคุณใช้กระบวนการใดเมื่อเผชิญกับปัญหา / ข้อบกพร่อง / ปัญหาใหม่
คนส่วนใหญ่ดูเหมือนจะรักษาจุดบกพร่องในฐานะศิลปะมากกว่าวิทยาศาสตร์ สำหรับคนที่นี่ซึ่งถือว่าเป็นวิทยาศาสตร์แทนที่จะเป็นศิลปะ - โดยปกติคุณใช้กระบวนการใดเมื่อเผชิญกับปัญหา / ข้อบกพร่อง / ปัญหาใหม่
คำตอบ:
โดยทั่วไปแล้วสิ่งที่ฉันทำคือ:
พยายามแยกปัญหา คิดถึงสิ่งที่เปลี่ยนไปเมื่อพบข้อบกพร่องเป็นครั้งแรก คุณทำงานอะไร คุณเปลี่ยนรหัสส่วนใด 99% ของข้อบกพร่องของฉันได้รับการแก้ไขด้วยวิธีนี้ มันมักจะเป็นสิ่งที่โง่
หากฉันเดาได้ว่าปัญหาอยู่ที่ใดให้ดูโค้ดที่ดูเหมือนจะเป็นสาเหตุ อ่านมัน อ่านออกเสียงแม้กระทั่ง ถามตัวเองว่า: "ฉันกำลังพยายามทำอะไรให้สำเร็จ" สำหรับปัญหาบางประเภท: อาจมีผลข้างเคียงหรืออาจได้รับผลกระทบจากโค้ดในที่อื่น ๆ ในแบบที่ฉันไม่เคยคิดมาก่อน
ลองด้วยวิธีต่างๆในการวิเคราะห์สิ่งที่ผิดพลาดที่ไหนและเมื่อใด (ดูด้านล่าง)
ถ้าฉันยังไม่มีเงื่อนงำฉันตรวจสอบว่าแหล่งที่มารุ่นเก่าของฉันมีปัญหาเดียวกันลองค้นหาเมื่อในไทม์ไลน์การพัฒนาของฉันเมื่อปัญหาปรากฏขึ้นเป็นครั้งแรก ในการทำเช่นนี้คุณต้องทำงานกับระบบควบคุมเวอร์ชันที่ดีเช่น git (git มีคุณสมบัติที่เรียกว่า bisect อย่างแท้จริงสำหรับการดีบักแบบนี้)
หากยังไม่มีเงื่อนงำหยุดพัก .... มันมักจะช่วยได้จริง
กลับไปที่กระดานวาดรูป - ตรวจสอบว่าโปรแกรมของคุณควรทำงานอย่างไรและดูว่าเหมาะสมหรือไม่
มันขึ้นอยู่กับชนิดของปัญหา แต่สมมติว่าฉันมีความคิดทั่วไปเกี่ยวกับปัญหาที่อาจเกิดขึ้นจากนั้น:
หากฉันสงสัยว่าปัญหาเกิดขึ้นในบางส่วนของรหัส / การเปลี่ยนแปลงล่าสุดฉันลองก่อนที่จะลบ / แสดงความคิดเห็น / เปลี่ยนแปลงหรืออะไรก็ตามที่ทำให้ข้อผิดพลาดหายไปโดยการทำให้โค้ดง่ายขึ้นจากนั้นนำโค้ดที่มีปัญหากลับมา ดูดีที่มัน
เรียกใช้ดีบักเกอร์ที่มีจุดพัก (ถ้าเป็นไปได้ทั้งหมด) และดูว่าข้อมูลของฉันกำลังพยายามค้นหาเมื่อเริ่มทำงานไม่ดีเพื่อให้ได้แนวคิดที่ดีขึ้นว่ามีอะไรผิดพลาดเกิดขึ้น
bzr qdiff
คำสั่ง
ฉันพยายามใช้การพัฒนาด้วยการทดสอบ ( TDD ) ฉันเขียนการทดสอบที่จำลองข้อผิดพลาดจากนั้นลองทดสอบเพื่อให้ผ่าน บางครั้งการเขียนการทดสอบช่วยในการค้นหาข้อบกพร่อง
สิ่งนี้ทำให้ฉันออกจากตัวดีบักได้ตลอดเวลาและให้การทดสอบการถดถอยเพื่อป้องกันการนำข้อผิดพลาดกลับมาใช้ใหม่
ลิงค์บางส่วน:
มีจำนวนของคำจำกัดความของคำว่าวิทยาศาสตร์มี แต่เสียงเหมือนคุณกำลังอาจจะหมายถึงสิ่งที่อาจจะเรียกว่าถูกต้องมากขึ้นว่า " วิธีการทางวิทยาศาสตร์ " วิธีการทางวิทยาศาสตร์อาจสรุปได้ว่าการสังเกตปรากฏการณ์บางอย่าง (อาจเป็นข้อผิดพลาดหรือพฤติกรรมของโปรแกรมที่ไม่คาดคิด) การกำหนดสมมติฐานหรือสมมติฐานเพื่ออธิบายพฤติกรรมและการทดลองที่น่าจะพิสูจน์ได้มากที่สุด (การเขียนการทดสอบ
ประเภทของข้อผิดพลาด (ปรากฏการณ์) ที่สามารถเกิดขึ้นได้นั้นไม่มีที่สิ้นสุดจริงและบางอย่างไม่จำเป็นต้องมีกระบวนการที่กำหนดไว้อย่างดี ตัวอย่างเช่นบางครั้งคุณสังเกตเห็นข้อผิดพลาดและคุณรู้ทันทีว่าอะไรเป็นสาเหตุของปัญหาเพียงเพราะคุณคุ้นเคยกับรหัสมาก บางครั้งคุณก็รู้ว่าการป้อนข้อมูลบางอย่าง (การกระทำชุดขั้นตอน ฯลฯ ) ผลลัพธ์ที่ไม่ถูกต้องเกิดขึ้น (ขัดข้องเอาต์พุตไม่ดี ฯลฯ ) สำหรับกรณีเหล่านั้นมักไม่ต้องการความคิด "วิทยาศาสตร์" มากนัก ความคิดบางอย่างสามารถช่วยลดพื้นที่การค้นหาได้ แต่วิธีการทั่วไปก็คือการใช้รหัสในโปรแกรมดีบั๊กและดูว่ามีอะไรผิดพลาดบ้าง
อย่างไรก็ตามในสถานการณ์ที่ฉันพบว่าน่าสนใจที่สุดและมีคุณค่าต่อกระบวนการทางวิทยาศาสตร์คือที่ที่คุณได้รับผลลัพธ์และขอให้อธิบายว่ามันเกิดขึ้นได้อย่างไร ตัวอย่างที่ชัดเจนของสิ่งเหล่านี้คือดัมพ์ล้มเหลว คุณสามารถโหลดการถ่ายโอนข้อมูลความผิดพลาดและสังเกตสถานะของระบบและงานของคุณคือการอธิบายว่ามันได้รับในสถานะที่ การถ่ายโอนข้อมูลความผิดพลาด (หรือหลัก) อาจแสดงข้อยกเว้นการหยุดชะงักข้อผิดพลาดภายในหรือสถานะ "ไม่พึงปรารถนา" บางอย่างตามที่กำหนดโดยผู้ใช้ (เช่นความเฉื่อยชา) สำหรับสถานการณ์เหล่านี้โดยทั่วไปฉันทำตามขั้นตอนต่าง ๆ ตามบรรทัดเหล่านี้:
การสังเกตที่แคบ : ศึกษาข้อมูลโดยตรงเกี่ยวกับปัญหาเฉพาะที่เกี่ยวข้อง สิ่งที่ชัดเจนที่นี่คือ call stack, ตัวแปรในตัวเครื่องหากคุณเห็น, บรรทัดของรหัสที่อยู่รอบ ๆ ปัญหา การศึกษาสถานที่เฉพาะประเภทนี้ไม่สามารถใช้ได้เสมอไป ตัวอย่างเช่นการศึกษาระบบ "ช้า" อาจไม่มีตำแหน่งเริ่มต้นที่ชัดเจนเช่นนี้ แต่สถานการณ์ความผิดพลาดหรือข้อผิดพลาดภายในอาจมีจุดสนใจทันทีและชัดเจน ขั้นตอนหนึ่งที่เฉพาะเจาะจงที่นี่อาจใช้เครื่องมือเช่น windbg (เรียกใช้! analyse -v บนการถ่ายโอนข้อมูลความผิดพลาดที่โหลดและดูสิ่งที่มันบอกคุณ)
การสังเกตอย่างกว้าง : ศึกษาส่วนอื่น ๆ ของระบบ ตรวจสอบสถานะของเธรดทั้งหมดในระบบดูข้อมูลทั่วโลก (จำนวนผู้ใช้ / การดำเนินงาน / รายการธุรกรรมที่ใช้งาน / กระบวนการ / วิดเจ็ต ฯลฯ ) ข้อมูลระบบ (OS) เป็นต้นหากผู้ใช้ให้รายละเอียดภายนอกใด ๆ ลองคิดถึงสิ่งเหล่านั้นควบคู่ไปกับสิ่งที่คุณสังเกตเห็น ตัวอย่างเช่นหากพวกเขาบอกคุณว่าปัญหาเกิดขึ้นทุกบ่ายวันอังคารให้ถามตัวเองว่าอาจหมายถึงอะไร
สมมติฐาน: นี่เป็นส่วนที่สนุกอย่างแท้จริง (และฉันก็ไม่ได้รู้สึกกลัวกับความสนุก) บ่อยครั้งต้องมีการคิดเชิงตรรกะอย่างมากในทางกลับกัน มันสนุกมากที่จะคิดว่าระบบเข้าสู่สถานะปัจจุบันอย่างไร ฉันสงสัยว่านี่เป็นส่วนที่หลายคนคิดว่าเป็นศิลปะ และฉันคิดว่ามันอาจจะเป็นถ้าโปรแกรมเมอร์เพิ่งเริ่มการขว้างสิ่งต่าง ๆ ที่มันเพื่อดูว่าไม้ แต่ด้วยประสบการณ์นี้อาจเป็นกระบวนการที่กำหนดไว้ค่อนข้างดี หากคุณคิดอย่างมีเหตุผล ณ จุดนี้มักจะเป็นไปได้ที่จะกำหนดชุดของเส้นทางที่เป็นไปได้ที่นำไปสู่สถานะที่กำหนด ฉันรู้ว่าเราอยู่ในสถานะ S5 สำหรับสิ่งที่จะเกิดขึ้น S4a หรือ S4b จำเป็นต้องเกิดขึ้นและอาจเป็น S3 ก่อน S4a เป็นต้นและบ่อยครั้งที่ไม่สามารถมีหลายรายการที่อาจนำไปสู่สถานะที่กำหนด บางครั้งมันอาจช่วยในการเขียนลงบนแผ่นรอยขีดข่วนการไหลง่ายหรือสถานะแผนภาพหรือชุดของขั้นตอนที่เกี่ยวข้องกับเวลา กระบวนการจริงที่นี่จะแตกต่างกันมากขึ้นอยู่กับสถานการณ์ แต่ความคิดที่จริงจัง (และการตรวจสอบอีกครั้งในขั้นตอนก่อนหน้า) ในเวลานี้มักจะให้คำตอบที่น่าเชื่อถืออย่างน้อยหนึ่งข้อ โปรดทราบว่าส่วนที่สำคัญอย่างยิ่งของขั้นตอนนี้คือการกำจัดสิ่งที่เป็นไปไม่ได้ การลบสิ่งที่เป็นไปไม่ได้สามารถช่วยลดพื้นที่การแก้ปัญหา (จำสิ่งที่ Sherlock Holmes พูดเกี่ยวกับสิ่งที่เหลืออยู่หลังจากที่คุณกำจัดสิ่งที่เป็นไปไม่ได้) โปรดทราบว่าส่วนที่สำคัญอย่างยิ่งของขั้นตอนนี้คือการกำจัดสิ่งที่เป็นไปไม่ได้ การลบสิ่งที่เป็นไปไม่ได้สามารถช่วยลดพื้นที่การแก้ปัญหา (จำสิ่งที่ Sherlock Holmes พูดเกี่ยวกับสิ่งที่เหลืออยู่หลังจากที่คุณกำจัดสิ่งที่เป็นไปไม่ได้) โปรดทราบว่าส่วนที่สำคัญอย่างยิ่งของขั้นตอนนี้คือการกำจัดสิ่งที่เป็นไปไม่ได้ การลบสิ่งที่เป็นไปไม่ได้สามารถช่วยลดพื้นที่การแก้ปัญหา (จำสิ่งที่ Sherlock Holmes พูดเกี่ยวกับสิ่งที่เหลืออยู่หลังจากที่คุณกำจัดสิ่งที่เป็นไปไม่ได้)
การทดลอง : ในขั้นตอนนี้ลองทำซ้ำปัญหาตามสมมติฐานที่ได้รับในขั้นตอนก่อนหน้า หากคุณคิดอย่างจริงจังในขั้นตอนก่อนหน้าสิ่งนี้ควรตรงไปตรงมามาก บางครั้งฉัน "โกง" และแก้ไขรหัสฐานเพื่อช่วยในการทดสอบที่กำหนด ตัวอย่างเช่นเมื่อเร็ว ๆ นี้ฉันกำลังตรวจสอบความผิดพลาดที่ฉันสรุปมาจากสภาพการแข่งขัน ในการตรวจสอบฉันเพียงแค่ใส่ Sleep (500) ระหว่างโค้ดสองสามบรรทัดเพื่อให้เธรดอื่นทำสิ่งที่ไม่ดีในเวลา "ถูกต้อง" ฉันไม่รู้ว่าสิ่งนี้ได้รับอนุญาตในวิทยาศาสตร์ "ของจริง" หรือไม่ แต่มันก็สมเหตุสมผลดีในรหัสที่คุณเป็นเจ้าของ
หากคุณประสบความสำเร็จในการทำซ้ำโอกาสที่คุณเกือบจะเสร็จสิ้น (สิ่งที่เหลืออยู่คือขั้นตอนง่าย ๆ ในการแก้ไข ... แต่นั่นเป็นอีกวัน) อย่าลืมตรวจสอบการทดสอบใหม่ในระบบการทดสอบการถดถอย และฉันควรชี้ให้เห็นว่าฉันตั้งใจว่าประโยคก่อนหน้านี้เกี่ยวกับการแก้ไขมันง่ายที่จะเป็นลิ้นในแก้ม การค้นพบวิธีแก้ปัญหาและการนำไปใช้งานนั้นจำเป็นต้องใช้งานที่กว้างขวาง ฉันคิดว่าการแก้ไขข้อบกพร่องไม่ได้เป็นส่วนหนึ่งของกระบวนการแก้ไขข้อบกพร่อง แต่เป็นการพัฒนา และหากการแก้ไขมีส่วนเกี่ยวข้องก็ควรจะต้องมีการออกแบบและการตรวจสอบจำนวนหนึ่ง
ลองลดขนาดกรณีทดสอบ เมื่อมันมีขนาดเล็กพอก็มักจะง่ายต่อการค้นหารหัสที่สอดคล้องที่ก่อให้เกิดปัญหา
เป็นไปได้ว่าการเช็คอินใหม่จะทำให้เกิดปัญหาและการสร้างรายวันก่อนหน้านี้ใช้ได้ ในกรณีดังกล่าวบันทึกการเปลี่ยนแปลงของคุณจากตัวควบคุมแหล่งข้อมูลจะช่วยให้คุณตัดสินใจได้ว่าจะจับใคร
นอกจากนี้หากคุณอยู่ใน C / C ++ ให้ลองใช้ valgrind หรือทำให้บริสุทธิ์เพื่อแยกปัญหาที่เกี่ยวข้องกับหน่วยความจำ
ส่วนที่ยากที่สุดของการแก้ไขข้อบกพร่องคือการแยกปัญหาโดยเฉพาะอย่างยิ่งเมื่อปัญหาฝังอยู่ใต้หลายชั้น ที่วิทยาลัยฉันเรียนการบันทึกเสียงเพลงและมีวิชา Studio Electronics ที่ใช้โดยตรงที่นี่ ฉันจะใช้การดีบักสภาพแวดล้อมสตูดิโอเป็นตัวอย่างของกระบวนการแก้ไขข้อบกพร่องอย่างเป็นระบบ
การแก้จุดบกพร่องรหัสไม่แตกต่างกันจริงๆ การดีบักนั้นง่ายกว่ามากเมื่อรหัสกำลังส่งข้อยกเว้น คุณสามารถติดตามย้อนกลับจากการติดตามสแต็กของข้อยกเว้นนั้นและตั้งจุดพักที่ตำแหน่งสำคัญ โดยปกติหลังจากที่คุณตั้งค่าตัวแปรหรือบนบรรทัดที่เรียกใช้เมธอดที่ส่งข้อยกเว้น คุณอาจพบว่าค่าอย่างน้อยหนึ่งค่าไม่ถูกต้อง ถ้ามันไม่ถูกต้อง (เป็นโมฆะเมื่อไม่ควรมีหรือค่าอยู่นอกช่วง) ก็เป็นกระบวนการค้นพบว่าทำไมมันไม่ถูกต้อง จุดแตกหักใน IDE นั้นเทียบเท่ากับจุดทดสอบอิเล็กทรอนิกส์ (ออกแบบมาสำหรับโพรบของมิเตอร์เพื่อตรวจสอบวงจร)
ตอนนี้เมื่อฉันได้ผ่านส่วนที่ยากของการค้นพบว่าปัญหาที่แท้จริงของฉันคืออะไรฉันจะเขียนการทดสอบหน่วยเพื่อตรวจสอบว่าในอนาคต
ด้วยข้อผิดพลาดที่น่ารังเกียจที่ฉันต่อสู้เพื่อติดตามในช่วงบ่ายกลยุทธ์ที่มีประสิทธิภาพที่สุดของฉันคือการยืนขึ้นและเดินออกไปไม่กี่นาที โดยปกติแล้วแนวคิดใหม่เกี่ยวกับแหล่งที่มาของข้อผิดพลาดที่เป็นไปได้เริ่มไหลเข้ามาหลังจากนั้นเพียง 30 วินาที
สำหรับ aproach ในทางปฏิบัติมากขึ้น:
หากข้อผิดพลาดเกี่ยวข้องกับข้อยกเว้นที่ไม่สามารถจัดการได้ - ดูที่การติดตามสแต็ก การอ้างอิงแบบไม่มีค่า, ดัชนีไม่อยู่ในขอบเขตเป็นต้นและข้อยกเว้นที่คุณกำหนดเองนั้นเป็นเรื่องธรรมดามากที่สุดคุณสามารถกำหนดข้อผิดพลาดนี้ให้กับนักพัฒนารุ่นเยาว์ได้ซึ่งอาจเป็นเรื่องง่ายและประสบการณ์การเรียนรู้ที่ดี
ถ้ามันไม่ได้เกิดขึ้นในทุก ๆ เครื่องมันอาจเป็นรูปแบบของปัญหาการแข่งขัน / การทำเกลียว สิ่งเหล่านี้สนุกสุด ๆ ในการติดตามวางโปรแกรมเมอร์อาวุโสของคุณลงไป มีการบันทึกจำนวนมากความรู้ที่ดีและเครื่องมือที่ดี
ข้อบกพร่องที่ใหญ่อีกประเภทหนึ่งคือเมื่อทีมทดสอบหรือลูกค้าไม่ชอบพฤติกรรมที่เฉพาะเจาะจง ตัวอย่างเช่นพวกเขาไม่ชอบที่คุณตัดสินใจที่จะแสดง ID ผู้ใช้หรือเมื่อค้นหาคุณไม่ได้รับการป้อนอัตโนมัติ เหล่านี้เป็นข้อบกพร่องของแท้พิจารณาการจัดการผลิตภัณฑ์ที่ดีขึ้นและ devs ด้วยมุมมองที่กว้างขึ้น ควรใช้เวลานักพัฒนาค่อนข้างสั้นในการ "แก้ไข" สิ่งนี้ถ้าเขาสร้างระบบโดยคำนึงถึงการขยายตัว
80% ของข้อบกพร่องอื่น ๆ ทั้งหมดได้รับการแก้ไขโดยมีระบบการบันทึกที่ดีและรวบรวมข้อมูลเพียงพอที่จะแก้ไข ใช้การติดตามการ build-in ด้วยระบบการบันทึกที่ซับซ้อนหลายระดับเช่น Log4Net / Log4J
ข้อบกพร่องด้านประสิทธิภาพเป็นหมวดหมู่ของพวกเขาเองกฎที่ยิ่งใหญ่กว่าคือ "วัดก่อนแก้ไขทีหลัง!" และคุณจะต้องประหลาดใจเมื่อเห็นว่ามีนักพัฒนาซอฟต์แวร์กี่คนที่เดาว่าปัญหาอยู่ที่ใดและเข้าแก้ไขเพื่อดูเท่านั้น ต่อมาลดลงเพียง 3-4% ในเวลาตอบสนอง
ฉันมีสองแนวทาง:
Divide and Conquer
กระบวนทัศน์วิธีการนี้ช่วยฉันได้บ่อยครั้ง