เหตุใดฉันจึงควรเขียนข้อความทั้งหมดใน Try-Catch


12

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


4
ฟังดูเหมือนคำศัพท์ปากต่อปากโดยคนเดียวกันที่บอกว่าSQL ทั้งหมดควรถูกเขียนเป็นโพรซีเดอร์ที่เก็บไว้เพื่อประสิทธิภาพที่ดีขึ้น
spong

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

4
@ Jeff O - จริง ๆ แล้วฉันเชื่อว่าในการพัฒนาซอฟต์แวร์ฝ่ายตรงข้ามเป็นขบวนรถไฟบรรทุกสินค้า
Joris Timmermans

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

2
หัวเรื่องของคำขอไม่เกี่ยวข้อง ... เพียงแค่พูดว่า "หัวหน้า บริษัท ของฉันบอกว่าฉันควรเขียนรหัส ... " เป็นธงสีแดงขนาดใหญ่ มันคือการจัดการขนาดเล็ก ... นี่ไม่ใช่งานของเขา
JoelFan

คำตอบ:


14

หัวหน้า บริษัท ของฉันบอกว่าฉันต้องเขียนทั้งหมดนั่นคือทั้งหมดรหัสของฉันในงบลองจับ

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

การดูการติดตามสแต็กนั้นส่วนใหญ่เพียงพอที่จะเปิดเผยสาเหตุในรหัสของคุณแม้ว่าวิธีการข้อบกพร่องจะไม่สามารถทำการตรวจจับได้ มีบางครั้งที่นักพัฒนามีร่องรอยสแต็กในข้อยกเว้นเสียหาย แต่นั่นก็บ่อยกว่ากรณีที่คุณมีตัวจัดการข้อยกเว้นจำนวนมาก ชอบอะไรก็ได้เล็กน้อยดี แต่มีพิษมากเกินไป

การจัดการข้อยกเว้นนั้นง่ายมาก:

ตรวจจับข้อยกเว้น

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

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

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

อย่าลืมผิดพลาดเร็ว ๆ เมื่อมีสิ่งผิดปกติ (ไม่สามารถซ่อมแซมได้) การวางรหัสทั้งหมดในข้อความสั่ง try-catch นั้นเป็นเรื่องไร้สาระ แต่อย่าลืมรายงานและบันทึกข้อยกเว้นทั้งหมด


+1 ไม่เพียง แต่นำสิ่งนี้ไปสู่รหัสที่มีเสียงดัง แต่ยังมีประสิทธิภาพที่แย่ลง เมื่อคุณใส่คำสั่งในบล็อกลอง HotSpot Compiler จะไม่สามารถใช้การเพิ่มประสิทธิภาพที่เขาจะทำ
Oliver Weiler

@Oliver Weiler: คุณมีการอ้างอิงที่อธิบายถึงการเพิ่มประสิทธิภาพของคอมไพเลอร์ HotSpot ที่ไม่ได้ทำใน try / catch blocks หรือไม่?
Kaypro II

16

แต่มันก็ไม่ไก่ใจเกินไปที่จะคิดว่าจะมีข้อยกเว้นเมื่อสร้างป้ายกำกับตำแหน่งของแบบฟอร์ม ได้มีกรณีที่มีข้อยกเว้นในการดำเนินการอย่างง่ายเช่น

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

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


13
แอพของฉันรู้ดีกว่าการโยนข้อยกเว้นไม่เช่นนั้นพวกเขาจะได้รับการตีชีวิตของพวกเขา เมื่อพวกเขาคิดว่าคุณมีความมุ่งมั่นพวกเขาจะชนคุณทั้งหมด
JeffO

@Michael Borgwardt: ฮิฮิดังนั้นคุณก็ลงคะแนนฉัน คุณลงคะแนนในคำถามนี้และมีเพียง downvote เท่านั้นที่โพสต์ของฉัน คุณดูเหมือนจะมีปัญหาร้ายแรงกับอัตตาหรือความภาคภูมิใจในตนเองของคุณ ฉันสังเกตเห็นว่าในคำถามอื่น ๆ เช่นกัน คุณก็รู้โปรแกรมเมอร์คนอื่นก็มีคำตอบที่ดีเช่นกัน
เหยี่ยว

@ ฟอลคอน: ฉันไม่ได้ลงคะแนนอะไรกับคำถามนี้ ฉันไม่รู้ว่าอะไรนำคุณไปสู่ความเชื่ออย่างอื่น แต่ถ้าใครมีปัญหาอัตตาที่จริงจังนั่นก็คือคุณ
Michael Borgwardt

@Michael Borwardt: บางทีฉันผิด ในกรณีที่ฉันขอโทษ อาจเป็นเพียง downvote จากคำถามของคุณเองที่ทำให้ฉันคิดว่าคุณ downvote ที่นี่ ขอโทษ
Falcon

8

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

หากคุณไม่สามารถแน่ใจได้ 100% ว่าคุณสามารถจัดการกับทุกข้อยกเว้นที่อาจถูกจับได้คุณควรเขียนตัวจัดการข้อยกเว้นทั่วไปบางประเภทห่อวงหลักของโปรแกรมไว้ในนั้น - กลไกที่แน่นอนของวิธีการทำอย่างชัดเจน ขึ้นอยู่กับภาษาที่คุณใช้งานอยู่ที่นั่นบันทึกรายละเอียดเกี่ยวกับข้อยกเว้นให้มากที่สุดเท่าที่จะทำได้บันทึกสถานะของโปรแกรม (ที่อื่นนอกเหนือจากที่เก็บข้อมูลใด ๆ ที่ผู้ใช้กำลังทำงานอยู่ - จำไว้ว่ามันอาจเสียหายทั้งหมด ณ จุดนี้ ) และอื่น ๆ จากนั้นสร้างข้อยกเว้นขึ้นใหม่แล้วปล่อยให้ระบบปฏิบัติการจัดการได้อย่างไรก็ตามจะเห็นว่าเหมาะสม ในตัวจัดการข้อยกเว้น catch-all นี้ต้องเตรียมพร้อมสำหรับความล้มเหลวที่ร้ายแรง. จากนั้นเมื่อโปรแกรมเริ่มต้นใหม่ให้ดูว่าสถานะนี้มีประโยชน์หรือไม่และเรียกคืนสิ่งที่สามารถกู้คืนได้หากเป็น และอาจเสนอให้ผู้ใช้ส่งรายงานข้อผิดพลาดกลับมาหาคุณ


5
+1: อย่าจับข้อยกเว้นหากคุณไม่สามารถจัดการกับมันได้อย่างถูกต้องทันที (อนิจจาบางครั้งคุณต้องดักจับมันเพื่อปล่อยให้เป็นอิสระอีกครั้ง แต่ติดแท็กเป็นประเภทที่แตกต่างกันซึ่งเป็นส่วนหนึ่งของการข่มขู่ API: ฉันเกลียดที่)
Donal Fellows

6

โดยรวมแล้วการใช้ลอง / จับที่มากเลิกใช้เนื่องจาก catch block มีราคาแพงมากจากจุดของทรัพยากร ลอง / การใช้งานจับทำให้ผมนึกถึงการบริหารความเสี่ยง การบริหารความเสี่ยงมีสองมิติ:

  1. ความน่าจะเป็นของความเสี่ยงที่เกิดขึ้น
  2. ความเสียหายที่มันสามารถมีได้

ตอนนี้ถ้าคุณออกไปจากบ้านเปียโนล้มลงบนหัวของคุณที่ไหนสักแห่งในขณะที่ไม่เป็นเช่นนั้นที่จะเกิดขึ้น (อาจ 0.001%) แต่สามารถฆ่าคุณ

การจัดการข้อยกเว้นเป็นเช่นนั้น ลองบล็อกไม่แพง แต่ catch block นั้นมีราคาแพงมากเพราะมันต้องการสร้าง table of stack trace และทำสิ่งอื่น ๆ ดังนั้นในการตัดสินใจเกี่ยวกับ try / catch blocks คุณควรพิจารณาจำนวนครั้งที่คุณอาจกด catch block หากในจำนวน 10,000 ประเพณีคุณทำได้เพียงครั้งเดียวแล้วใช้งาน แต่ถ้าเป็นแบบฟอร์มและผู้ใช้อาจไม่ได้กรอกข้อมูลถูกต้อง 50% ครั้งคุณควรหลีกเลี่ยงการวางบล็อกลองใช้ / การกระทำที่นั่น

ในสถานที่ที่มีความน่าจะเป็นของการเกิดข้อยกเว้นสูงแนะนำให้ใช้if {} else {}บล็อกเพื่อหลีกเลี่ยงการเกิดข้อยกเว้น ตัวอย่างเช่นที่คุณต้องการหารสองตัวเลขแทนการเขียน:

try
{
    int result = a/b;
}
catch (DivisionByZeroException ex)
{
    // Showing a message here, and logging of course.
}

คุณควรเขียน:

if (b == 0)
{
    int result = a/b;
}
else
{
    // Showing a message to user to change the value of b, etc.
}

2
+1 สำหรับการใช้ if / else เพื่อจัดการกับ "ข้อยกเว้น" ที่เป็นเพียงตรรกะแอปพลิเคชัน
Morgan Herlocker

หากเกี่ยวข้องกับผู้ใช้โปรดจำไว้ว่าคอมพิวเตอร์นั้นเร็วกว่าคนอย่างมาก ข้อยกเว้นในการส่งแบบฟอร์ม 50% ยังมีแนวโน้มที่จะเกิดขึ้นเพียงไม่กี่ครั้งต่อวินาทีแม้จะมีผู้ใช้จำนวนมาก
Donal Fellows

1
ฉันไม่เห็นด้วยกับคุณเกี่ยวกับการหลีกเลี่ยงการลอง / จับบล็อก การพยายามคาดการณ์ข้อยกเว้นอย่างต่อเนื่องนั้นเกิดจากข้อผิดพลาดมีราคาแพงในเวลาของนักพัฒนาซอฟต์แวร์และทำให้โค้ดของคุณอ่านยากขึ้น การวนซ้ำที่ส่งข้อยกเว้นเป็นล้าน ๆ ครั้งและการจับจะใช้เวลา 500 มิลลิวินาทีในการเรียกใช้บนเครื่องของฉัน (เทียบกับ 1 มิลลิวินาทีสำหรับการวนซ้ำที่ว่างเปล่า) ซึ่งไม่ใช่ความแตกต่างของประสิทธิภาพในโลกแห่งความเป็นจริงใน 99.99% ของกรณี (และรหัส UI ทั้งหมด) คุณควรใช้ข้อยกเว้นยกเว้นในกรณีที่คุณรู้ว่าการลงโทษนั้นสำคัญเพราะจะทำให้โค้ดของคุณน่าเชื่อถือมากขึ้นและให้คุณสมมติว่าโค้ดก่อนหน้านี้ทำงานสำเร็จ
Kaypro II

@ cosmic.osmo คุณดึงสแต็กสแตร็กหรือจับได้หรือไม่

3

คุณควรใช้ try-catch ตามความเหมาะสม แต่โปรดได้โปรดอย่าจับข้อยกเว้นทั้งหมดและอย่าแม้แต่บันทึก ณ จุดนี้มันมีกลิ่นรหัสและการทำงานต่ำ


1
+1 สำหรับการบันทึก โปรแกรมในป่าคือกล่องดำ เมื่อพวกเขาล้มเหลวบันทึกว่า "นี่คือสิ่งที่เกิดขึ้น" ไปไกลมากในการแก้ปัญหา ฉันมีข้อผิดพลาดในโปรแกรมของฉันที่ไม่ได้รับการรายงานและพวกเขาถูกเปิดเผยหลังจากที่ฉันพบพวกเขาในบันทึก
Andrew Neely

2

โดยส่วนตัวแล้วฉันไม่สามารถทนต่อข้อยกเว้นพวกเขาเป็นคนดีมากยากที่จะจัดการอย่างถูกต้อง และพยายามที่จะทำลายข้อมูลที่เสียหายได้มากมากยากมาก!

http://blogs.msdn.com/b/mgrier/archive/2004/02/18/75324.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

http://www.joelonsoftware.com/items/2003/10/13.html

หากคุณไม่เรียกใช้ฟังก์ชันทั้งหมดเช่น:

try
{
    TrivialFunction();
}
catch(TypeAException)
{
    //MaybeFix
}
catch(TypeBException)
{
    //MaybeFix
}
catch(TypeCException)
{
    //NO FIX - CORRUPT DATA
}
catch(TypeDException)
{
    //NO FIX - UNKNOWN STATE
}
catch(OutOfMemoryException)
{
    //Try to fix this one! Destructors might allocate on their own ;)
}
catch(Exception)
{
    //Nothing to see here, move on, everything is OK ;)
}

ไม่มีทางที่คุณจะทำความสะอาดอย่างถูกต้องในทุกจุดทางออก ข้อยกเว้นคือยาก!

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

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