นี่จะเป็นคำตอบที่มากกว่าแนวคิดว่าทำไมคำเตือนเหล่านี้อาจมีอยู่แม้ว่าด้วยวิธีการลองกับทรัพยากร แต่น่าเสียดายที่ไม่ใช่วิธีการแก้ปัญหาที่ง่ายที่คุณอาจคาดหวังว่าจะได้รับ
การกู้คืนข้อผิดพลาดไม่สามารถล้มเหลว
finally
โมเดลโฟลว์การควบคุมหลังการทำธุรกรรมที่ดำเนินการโดยไม่คำนึงถึงว่าการทำธุรกรรมสำเร็จหรือล้มเหลว
ในกรณีที่ล้มเหลวfinally
จับตรรกะที่ดำเนินการในช่วงกลางของการกู้คืนจากข้อผิดพลาดก่อนที่จะได้รับการกู้คืนอย่างเต็มที่ (ก่อนที่เราจะไปถึงcatch
ปลายทางของเรา)
ลองนึกภาพปัญหาความคิดมันเป็นของขวัญที่จะพบข้อผิดพลาดในช่วงกลางของการกู้คืนจากข้อผิดพลาด
ลองนึกภาพเซิร์ฟเวอร์ฐานข้อมูลที่เราพยายามจะทำธุรกรรมและมันล้มเหลวไปครึ่งทาง (พูดว่าเซิร์ฟเวอร์มีหน่วยความจำเหลืออยู่ตรงกลาง) ตอนนี้เซิร์ฟเวอร์ต้องการย้อนกลับการทำธุรกรรมไปยังจุดราวกับว่าไม่มีอะไรเกิดขึ้น แต่ลองจินตนาการว่ามันเจอข้อผิดพลาดอื่นในกระบวนการย้อนกลับ ตอนนี้เราจบลงด้วยการทำธุรกรรมแบบกึ่งมุ่งมั่นไปยังฐานข้อมูล - อะตอมมิกและลักษณะที่แยกไม่ออกของธุรกรรมตอนนี้พังและความสมบูรณ์ของฐานข้อมูลจะถูกทำลาย
ปัญหาแนวคิดนี้มีอยู่ในภาษาใด ๆ ที่เกี่ยวข้องกับข้อผิดพลาดไม่ว่าจะเป็น C ที่มีการขยายพันธุ์รหัสคู่มือข้อผิดพลาดหรือ C ++ มีข้อยกเว้นและ destructors หรือ Java finally
และมีข้อยกเว้น
finally
ไม่สามารถล้มเหลวในภาษาที่ให้ไว้ในลักษณะเดียวกับที่ตัวทำลายไม่สามารถล้มเหลวใน C ++ ในกระบวนการพบข้อยกเว้น
วิธีเดียวที่จะหลีกเลี่ยงปัญหาเกี่ยวกับแนวคิดและปัญหาที่ยากลำบากนี้คือการทำให้แน่ใจว่ากระบวนการย้อนกลับธุรกรรมและการปล่อยทรัพยากรที่อยู่ตรงกลางไม่อาจพบข้อยกเว้น / ข้อผิดพลาดซ้ำ
ดังนั้นการออกแบบที่ปลอดภัยเพียงอย่างเดียวที่นี่คือการออกแบบที่writer.close()
ไม่สามารถล้มเหลวได้ มักจะมีวิธีในการออกแบบเพื่อหลีกเลี่ยงสถานการณ์ที่สิ่งต่าง ๆ สามารถล้มเหลวในช่วงกลางของการกู้คืนทำให้มันเป็นไปไม่ได้
เป็นวิธีเดียวที่น่าเสียดาย - การกู้คืนข้อผิดพลาดไม่สามารถล้มเหลว วิธีที่ง่ายที่สุดเพื่อให้แน่ใจว่านี่คือการทำให้ฟังก์ชั่น "การปลดปล่อยทรัพยากร" และ "ผลข้างเคียงย้อนกลับ" เหล่านั้นไม่สามารถล้มเหลวได้ ไม่ใช่เรื่องง่าย - การกู้คืนข้อผิดพลาดที่เหมาะสมนั้นยากและยังยากที่จะทดสอบ แต่วิธีการที่จะทำให้สำเร็จนั้นคือการทำให้แน่ใจว่าฟังก์ชั่นใด ๆ ที่ "ทำลาย", "ปิด", "ปิด", "ย้อนกลับ" ฯลฯ ไม่สามารถพบข้อผิดพลาดภายนอกในกระบวนการได้เนื่องจากฟังก์ชั่นดังกล่าวมักจะต้อง ถูกเรียกในช่วงกลางของการกู้คืนจากข้อผิดพลาดที่มีอยู่
ตัวอย่าง: การบันทึก
สมมติว่าคุณต้องการบันทึกสิ่งต่าง ๆ ภายในfinally
บล็อก นี้มักจะเป็นปัญหาใหญ่เว้นแต่การเข้าสู่ระบบไม่สามารถล้มเหลว การเข้าสู่ระบบเกือบจะแน่นอนอาจล้มเหลวเนื่องจากอาจต้องการผนวกข้อมูลเพิ่มเติมลงในไฟล์และที่สามารถหาสาเหตุหลายประการที่จะล้มเหลวได้อย่างง่ายดาย
ดังนั้นทางออกที่นี่คือการทำให้ฟังก์ชั่นการบันทึกใด ๆ ที่ใช้ในfinally
บล็อกไม่สามารถส่งไปยังผู้โทร (มันอาจจะล้มเหลว แต่มันจะไม่โยน) เราจะทำอย่างนั้นได้อย่างไร? หากภาษาของคุณอนุญาตให้มีการขว้างปาภายในบริบทของการจัดให้มีบล็อก try / catch ที่ซ้อนกันซึ่งเป็นวิธีหนึ่งในการหลีกเลี่ยงการขว้างปาไปยังผู้โทรโดยการกลืนข้อยกเว้นและเปลี่ยนเป็นรหัสข้อผิดพลาดเช่นอาจบันทึกแยกกัน กระบวนการหรือเธรดที่สามารถล้มเหลวแยกจากกันและอยู่นอกสแต็กการกู้คืนข้อผิดพลาดที่มีอยู่คลายออก ตราบใดที่คุณสามารถสื่อสารกับกระบวนการนั้นโดยไม่มีความเป็นไปได้ที่จะเกิดข้อผิดพลาดนั่นก็จะเป็นข้อยกเว้นที่ปลอดภัยเนื่องจากปัญหาด้านความปลอดภัยมีอยู่เฉพาะในสถานการณ์นี้ถ้าเราโยนซ้ำภายในเธรดเดียวกัน.
ในกรณีนี้เราสามารถหลีกเลี่ยงการบันทึกล้มเหลวหากไม่ได้บันทึกเนื่องจากไม่สามารถบันทึกและไม่ทำอะไรเลยไม่ใช่จุดจบของโลก (ไม่รั่วไหลของทรัพยากรหรือล้มเหลวในการย้อนกลับผลข้างเคียงเช่น)
อย่างไรก็ตามฉันมั่นใจว่าคุณสามารถเริ่มจินตนาการได้แล้วว่ามันยากอย่างเหลือเชื่อที่จะสร้างข้อยกเว้นซอฟต์แวร์อย่างแท้จริงได้อย่างไร อาจไม่จำเป็นต้องค้นหาสิ่งนี้อย่างเต็มที่ แต่เป็นซอฟต์แวร์ที่มีความสำคัญต่อภารกิจ แต่มันควรค่าที่จะทราบว่าจะทำอย่างไรเพื่อให้เกิดข้อยกเว้นด้านความปลอดภัยอย่างแท้จริงเนื่องจากผู้เขียนห้องสมุดที่ใช้งานทั่วไปมักจะคลำหาที่นี่และทำให้เกิดข้อยกเว้นด้านความปลอดภัยทั้งหมดของแอปพลิเคชันของคุณ
SomeFileWriter
หากSomeFileWriter
สามารถเข้าไปข้างในได้close
ฉันจะบอกว่าโดยทั่วไปแล้วไม่สามารถเข้ากันได้กับการจัดการข้อยกเว้นเว้นแต่คุณจะไม่พยายามปิดมันในบริบทที่เกี่ยวข้องกับการกู้คืนจากข้อยกเว้นที่มีอยู่ หากรหัสนี้อยู่นอกเหนือการควบคุมของคุณเราอาจเป็น SOL แต่มันจะคุ้มค่าที่จะแจ้งให้ผู้เขียนของปัญหาความปลอดภัยข้อยกเว้นโจ่งแจ้งนี้ หากอยู่ในการควบคุมของคุณคำแนะนำหลักของฉันคือการทำให้แน่ใจว่าการปิดนั้นจะไม่สามารถล้มเหลวด้วยวิธีการใดก็ได้ที่จำเป็น
ลองจินตนาการว่าระบบปฏิบัติการอาจล้มเหลวในการปิดไฟล์จริงหรือไม่ ตอนนี้โปรแกรมใด ๆ ที่พยายามปิดไฟล์เมื่อปิดระบบจะไม่สามารถปิดได้ เราควรจะทำอะไรตอนนี้เพียงแค่เปิดแอปพลิเคชันและในบริเวณขอบรก (อาจจะไม่ใช่) เพียงแค่รั่วไฟล์ทรัพยากรและละเลยปัญหา (อาจจะไม่เป็นไรถ้ามันไม่สำคัญมาก)? การออกแบบที่ปลอดภัยที่สุด: ทำให้เป็นไปไม่ได้ที่จะปิดไฟล์ไม่ได้