อาร์กิวเมนต์สำหรับหรือต่อต้านการใช้ลอง / จับเป็นตัวดำเนินการเชิงตรรกะ [ปิด]


36

ฉันเพิ่งค้นพบโค้ดที่น่ารักในแอพ บริษัท ของเราที่ใช้บล็อก Try-Catch เป็นตัวดำเนินการเชิงตรรกะ
หมายความว่า "ทำรหัสบางอย่างถ้านั่นทำให้เกิดข้อผิดพลาดนี้ให้ทำรหัสนี้ แต่ถ้านั่นทำให้เกิดข้อผิดพลาดนี้ให้ทำสิ่งที่ 3 แทน"
มันใช้ "สุดท้าย" เป็นคำสั่ง "อื่น" ที่ปรากฏ
ฉันรู้ว่านี่เป็นความผิดโดยเนื้อแท้ แต่ก่อนที่ฉันจะเลือกการต่อสู้ฉันหวังว่าจะมีข้อโต้แย้งที่คิดออกมาดี
และเฮ้ถ้าคุณมีข้อโต้แย้งสำหรับการใช้ลองจับในลักษณะนี้โปรดบอก

สำหรับผู้ที่สงสัยภาษาคือ C # และรหัสที่เป็นปัญหานั้นมีประมาณ 30+ บรรทัดและกำลังมองหาข้อยกเว้นเฉพาะมันไม่ได้จัดการข้อยกเว้นทั้งหมด


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

15
@FrustratedWIthFormsDesigner: นั่นเป็นเหตุผลที่ไม่ดี แล้วคนที่ไม่เชื่อมั่นล่ะ เกี่ยวกับคำถามจริงของฉันที่ฉันถามเหตุผลโดยเฉพาะเพราะฉันไม่สามารถบอกได้ว่า "ทำไม" เพียงแค่ฉันรู้ว่ามันผิด
James P. Wright

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

11
ฉันหวังว่าพวกเขาจะไม่ใช้บล็อก "สุดท้าย" เป็น "อื่น ๆ " เพราะบล็อก "ในที่สุด" จะทำงานอยู่เสมอหลังจากรหัสก่อนหน้านี้โดยไม่คำนึงถึงข้อยกเว้นใด ๆ ที่ถูกโยน
jimreed

2
พวกเขาใช้ภาษาอะไร พูดได้อย่างสมบูรณ์แบบว่า OCaml ซึ่งห้องสมุดมาตรฐานมีข้อยกเว้นอยู่เป็นประจำ การจัดการข้อยกเว้นนั้นถูกมาก แต่มันจะไม่มีประสิทธิภาพใน CLI หรือ JVM
SK-logic

คำตอบ:


50

การจัดการข้อยกเว้นมีแนวโน้มที่จะเป็นวิธีที่มีราคาแพงในการจัดการการควบคุมการไหล (แน่นอนสำหรับ C # และ Java)

รันไทม์ทำงานค่อนข้างมากเมื่อมีการสร้างออบเจ็กต์ข้อยกเว้น - รับการติดตามสแต็กด้วยกันการหาข้อยกเว้นที่จัดการและอื่น ๆ

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

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

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


1
จุดดีเกี่ยวกับประสิทธิภาพแม้ว่าจะขึ้นอยู่กับเฉพาะของแพลตฟอร์ม
FrustratedWithFormsDesigner

4
ถ้าเป็นข้อเสียเพียงอย่างเดียวก็ต้องขอบคุณ - ฉันจะยกเลิกการทำงานทุกวันถ้าซื้อรหัสที่ดีกว่าให้ฉัน (ยกเว้นในเส้นทางที่มีความสำคัญต่อประสิทธิภาพนั่นคือ แต่โชคดีที่มีเพียง 20% ของรหัสทั้งหมดแม้ในแอปพลิเคชันทั่วไป -critical)

5
@delnan - ไม่ไม่ใช่ข้อเสียเดียว
Oded

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

4
"การจัดการข้อยกเว้นมีแนวโน้มที่จะเป็นวิธีที่มีราคาแพงในการจัดการการควบคุมการไหล" เป็นเท็จสำหรับ Python
S.Lott

17

ฉันเพิ่งค้นพบโค้ดที่น่ารักในแอพ บริษัท ของเราที่ใช้บล็อก Try-Catch เป็นตัวดำเนินการเชิงตรรกะ หมายความว่า "ทำรหัสบางอย่างถ้านั่นทำให้เกิดข้อผิดพลาดนี้ให้ทำรหัสนี้ แต่ถ้านั่นทำให้เกิดข้อผิดพลาดนี้ให้ทำสิ่งที่ 3 แทน" มันใช้ "สุดท้าย" เป็นคำสั่ง "อื่น" ที่ปรากฏ ฉันรู้ว่านี่เป็นสิ่งที่ผิดโดยกำเนิด ...

คุณรู้ได้อย่างไร? ฉันยอมแพ้ "ความรู้" ทุกอย่างและตอนนี้ก็เชื่อว่ารหัสที่ง่ายที่สุดดีที่สุด สมมติว่าคุณต้องการแปลงสตริงเป็นตัวเลือกที่ว่างเปล่าหากการแยกวิเคราะห์ล้มเหลว ไม่มีอะไรผิดปกติกับ:

try { 
    return Optional.of(Long.valueOf(s)); 
} catch (NumberFormatException) { 
    return Optional.empty(); 
}

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

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

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


4
ฉันคิดว่านี่เป็นข้อโต้แย้งที่ดีทีเดียว รหัสของคุณสะอาดและรัดกุมและสมเหตุสมผลในสิ่งที่กำลังทำ สิ่งนี้คล้ายกับสิ่งที่เกิดขึ้นในโค้ดที่ฉันเห็นมีความซับซ้อนมากกว่าซ้อนกันและมีโค้ดมากกว่า 30 บรรทัด
James P. Wright

@James: ดูเหมือนว่ารหัสจะดีถ้าคุณแยกวิธีเล็ก ๆ
kevin cline

1
หนึ่งอาจโต้แย้งว่า Java สามารถใช้อะไรมากกว่านี้เช่น TryParse ของ C # ใน C # int i; if(long.TryParse(s, out i)) return i; else return null;ว่ารหัสจะเป็น TryParse ส่งคืน false ถ้าไม่สามารถแยกวิเคราะห์สตริงได้ หากสามารถแยกวิเคราะห์ได้ตั้งค่าอาร์กิวเมนต์เอาต์พุตเป็นผลลัพธ์ของการวิเคราะห์คำและส่งคืนค่าจริง ไม่มีข้อยกเว้นเกิดขึ้น (แม้แต่ภายในใน TryParse) และโดยเฉพาะอย่างยิ่งไม่มีข้อยกเว้นประเภทที่หมายถึงข้อผิดพลาดของโปรแกรมเมอร์เช่น. NETs FormatExceptionบ่งชี้เสมอ
Kevin Cathcart

1
@ Kevin Cathcart แต่ทำไมถึงดีกว่า? รหัสที่จับ NumberFormatException นั้นชัดเจนมากสำหรับฉันจากนั้นตรวจสอบผลลัพธ์ของ TryParse เพื่อหาค่าว่าง
Winston Ewert

1
@ChrisMiskowiec ฉันคิดว่าอันไหนที่คุณเห็นชัดเจนกว่านั้นก็เป็นเรื่องของสิ่งที่คุณคุ้นเคย ฉันพบว่าการยกเว้นนั้นง่ายกว่ามากที่จะติดตามแล้วตรวจสอบค่าเวทมนตร์ แต่นั่นเป็นเรื่องส่วนตัว ฉันคิดว่าเราควรชอบข้อยกเว้นเพราะพวกเขามีค่าเริ่มต้นที่ผิดปกติ (เกิดความผิดพลาดของโปรแกรม) แทนที่จะเป็นค่าเริ่มต้นที่ซ่อนข้อผิดพลาด (ดำเนินการต่อเหมือนไม่มีอะไรเกิดขึ้น) มันเป็นความจริงที่. NET ทำงานได้ไม่ดีโดยมีข้อยกเว้น แต่นั่นเป็นผลมาจากการออกแบบของ. NET ไม่ใช่ลักษณะของข้อยกเว้น ถ้าใน. NET ใช่คุณต้องทำเช่นนั้น แต่โดยหลักการแล้วข้อยกเว้นจะดีกว่า
Winston Ewert

12

การตรวจแก้จุดบกพร่องและงานบำรุงรักษาเป็นเรื่องยากมากเมื่อดำเนินการตามขั้นตอนการควบคุมโดยใช้ข้อยกเว้น

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

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

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

  • ปัญหาการบำรุงรักษาโฟลว์การดำเนินการนั้นยากที่จะติดตามผ่านการข้ามยกเว้น นอกเหนือจากนั้นข้อยกเว้นอาจถูกโยนออกมาจากโค้ดประเภทกล่องดำภายในซึ่งอาจไม่ทำงานในรูปแบบที่เข้าใจง่ายเมื่อทำการยกเว้น

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


10

ฉันเคยเห็นรูปแบบนี้ใช้หลายครั้ง

มี 2 ​​ปัญหาที่สำคัญคือ

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

2
เพียงแค่วางมันไว้ที่นั่นหาก / อื่นถือเป็นการกระโดดด้วย ความแตกต่างคือมันเป็นกระโดดที่สามารถเกิดขึ้นได้เฉพาะที่จุดนั้น (และมันอ่านง่ายขึ้นมาก) และคุณไม่ต้องกังวลเกี่ยวกับชื่อของฉลาก (ซึ่งคุณไม่ต้องลอง / จับด้วยเช่นกัน แต่เปรียบเทียบกับข้ามไป) แต่เพียงแค่พูดว่า "มันเป็นการกระโดดซึ่งไม่ดี" ยังบอกด้วยว่าถ้า / อื่นไม่ดีเมื่อมันไม่ใช่
jsternberg

1
@jsternbarg: ใช่ถ้า / อื่นอยู่ใน factcompiled เพื่อข้ามไปที่ระดับเครื่อง แต่ที่ระดับภาษาเป้าหมายการกระโดดคือคำสั่งถัดไปในขณะที่ในกรณีของลูปมันเป็นคำสั่งปัจจุบัน ฉันจะเถียงว่านั่นเป็นขั้นตอนมากกว่าการกระโดด;)
back2dos

9

บางครั้งข้อยกเว้นนั้นเร็วที่สุด ฉันเคยเห็นกรณีที่ข้อยกเว้นวัตถุ null เร็วกว่าแม้ใน Java มากกว่าการใช้โครงสร้างการควบคุม (ฉันไม่สามารถอ้างอิงการศึกษาได้ในขณะนี้ดังนั้นคุณจะต้องเชื่อใจฉัน) ปัญหาเกิดขึ้นเมื่อ Java ต้องใช้เวลาจริงและเติมการติดตามสแต็กของคลาสข้อยกเว้นแบบกำหนดเองแทนการใช้เนทีฟแบบดั้งเดิม (ซึ่งดูเหมือนว่าจะแคชอย่างน้อยบางส่วน) ก่อนที่จะบอกว่าบางสิ่งบางอย่างเร็วขึ้นหรือช้าลงฝ่ายเดียวก็เป็นการดีที่จะสร้างมาตรฐาน

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

ฉันเคยเห็นครั้งที่มันเร็วกว่าที่จะทำอะไรโง่ ๆ เช่นตารางการสืบค้นซึ่งไม่ได้มีอะไรมากกว่าที่จะคิดออกว่าตารางนั้นมีอยู่ใน PHP + MySQL หรือไม่ ( คำถามที่ฉันเปรียบเทียบว่านี่เป็นคำตอบเดียวที่ฉันยอมรับ .

จากทั้งหมดที่กล่าวมาการใช้ข้อยกเว้นควรถูก จำกัด ด้วยเหตุผลหลายประการ:

  1. การกลืนข้อยกเว้นโดยอุบัติเหตุโดยไม่ตั้งใจ นี่เป็นวิชาเอก หากคุณพบข้อยกเว้นเชิงลึกบางอย่างที่คนอื่นกำลังพยายามจัดการอยู่คุณต้องยิงโปรแกรมเมอร์ของคุณ (อาจเป็นคุณ!) ด้วยการเดินเท้า
  2. การทดสอบไม่ชัดเจน บล็อกของรหัสที่มีข้อยกเว้นนั้นอาจมีหนึ่งในหลายสิ่งผิดปกติ ในทางกลับกันบูลีนในขณะที่ในทางทฤษฎีแล้วมันอาจสร้างความรำคาญให้กับการดีบัก แต่โดยทั่วไปแล้วไม่ใช่ นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งเนื่องจากผู้try...catchสนับสนุนขั้นตอนการควบคุมโดยทั่วไป (จากประสบการณ์ของฉัน) ไม่ปฏิบัติตามปรัชญา "ลดโค้ดในการลองบล็อก"
  3. มันไม่อนุญาตให้มีการelse ifบล็อก พอกล่าวว่า (และถ้ามีคนเคาน์เตอร์ด้วย "แต่พวกเขาสามารถใช้คลาสการยกเว้นต่าง ๆ ได้" คำตอบของฉันคือ "ไปที่ห้องของคุณและไม่ออกมาจนกว่าคุณจะคิดถึงสิ่งที่คุณพูด")
  4. มันทำให้เข้าใจผิดทางไวยากรณ์ Exceptionสำหรับส่วนที่เหลือของโลก (ในขณะที่ไม่ปฏิบัติตามtry...catchปรัชญาการควบคุมการไหล) หมายถึงบางสิ่งบางอย่างได้เข้าสู่สถานะที่ไม่แน่นอน (แม้ว่าอาจจะกู้คืนได้) รัฐที่ไม่แน่นอนนั้นเป็นสิ่งที่ไม่ดีและมันควรจะทำให้พวกเราทุกคนตื่นขึ้นมาในตอนกลางคืนถ้าพวกเรามีข้อยกเว้นที่หลีกเลี่ยงได้จริง ๆ
  5. มันไม่สอดคล้องกับสไตล์การเข้ารหัสทั่วไป งานของเราทั้งด้วยรหัสและ UI ของเราคือการทำให้โลกนี้ชัดเจนที่สุด try...catchการควบคุมการไหลขัดต่อสิ่งที่ถือว่าเป็นแนวปฏิบัติที่ดีที่สุด ซึ่งหมายความว่าต้องใช้เวลามากขึ้นสำหรับคนที่เพิ่งเริ่มโครงการเพื่อเรียนรู้โครงการซึ่งหมายถึงการเพิ่มจำนวนชั่วโมงการทำงานเพื่อไม่ให้เกิดผลกำไรอย่างแน่นอน
  6. ซึ่งมักจะนำไปสู่การทำสำเนารหัส ในที่สุดบล็อกถึงแม้ว่าสิ่งนี้ไม่จำเป็นอย่างเคร่งครัด แต่จำเป็นต้องแก้ไขพอยน์เตอร์ห้อยต่องแต่งทั้งหมดที่เปิดทิ้งไว้โดยบล็อกลองขัดจังหวะ ลองบล็อกดู try{ obj.openSomething(); /*something which causes exception*/ obj.doStuff(); obj.closeSomething();}catch(Exception e){obj.closeSomething();}ซึ่งหมายความว่าคุณสามารถมี ในif...elseสถานการณ์ที่closeSomething()เป็นแบบดั้งเดิมมากขึ้นโอกาสน้อยลง (เป็นประสบการณ์ส่วนตัวอีกครั้ง) ในการทำสำเนาและวางงาน (เป็นที่ยอมรับข้อโต้แย้งนี้มีส่วนเกี่ยวข้องกับคนที่ฉันได้พบมากกว่าปรัชญาจริง)

AFAIK, # 6 เป็นปัญหาเฉพาะใน Java ซึ่งแตกต่างจากภาษาที่ทันสมัยอื่น ๆ ทั้งหมดไม่ได้มีการปิดหรือการจัดการทรัพยากรแบบกองซ้อน แน่นอนว่าไม่ใช่ปัญหาที่เกิดจากการใช้ข้อยกเว้น
วินไคลน์

4 และ 5 ดูเหมือนจะเป็นจุดเดียวกันกับฉัน 3-6 ใช้ไม่ได้ถ้าภาษาของคุณเป็นงูหลาม 1 และ 2 เป็นปัญหาที่อาจเกิดขึ้น แต่ฉันคิดว่าพวกเขาได้รับการจัดการโดยย่อโค้ดในบล็อคลอง
Winston Ewert

1
@ Winston ฉันไม่เห็นด้วย 1 และ 2 เป็นประเด็นสำคัญซึ่งในขณะที่ลดขนาดลงตามมาตรฐานการเข้ารหัสที่ดีขึ้นก็ยังทำให้สงสัยว่ามันอาจจะไม่ดีกว่าถ้าจะหลีกเลี่ยงข้อผิดพลาดที่อาจเกิดขึ้นได้ 3 ใช้หากภาษาของคุณคือ Python 4-5 สามารถสมัคร Python ได้ แต่ไม่จำเป็นต้อง 4 และ 5 นั้นเป็นจุดที่แตกต่างกันมาก รหัสที่ทำให้เข้าใจผิดอาจกำลังทำอะไรบางอย่างเช่นตั้งชื่อไกเพื่อเริ่มยานพาหนะด้วยปุ่ม "หยุด" ในทางกลับกันมันอาจคล้ายกับการหลีกเลี่ยงการเยื้องบล็อกทั้งหมดใน C.
cwallenpoole

3) Python มีบล็อกอื่นสำหรับข้อยกเว้น เป็นประโยชน์อย่างมากสำหรับการหลีกเลี่ยงปัญหาที่คุณมักจะได้รับในวันที่ 1 และ 2
Winston Ewert

1
เพื่อให้ชัดเจนฉันไม่ได้เรียกร้องให้ใช้ข้อยกเว้นคือกลไกควบคุมการไหลทั่วไปของคุณ ฉันสนับสนุนการขว้างข้อยกเว้นสำหรับโหมด "ความล้มเหลว" ใด ๆ ไม่ว่าจะเล็กเพียงใดก็ตาม ฉันคิดว่ารุ่นการจัดการข้อยกเว้นนั้นสะอาดกว่าและมีโอกาสน้อยกว่าที่จะซ่อนข้อบกพร่องจากนั้นรุ่นตรวจสอบค่าส่งคืน และอย่างที่ฉันต้องการภาษาที่จะทำให้มันยากที่จะจับข้อผิดพลาดซ้อน
Winston Ewert

4

เหตุผลหลักของฉันคือการใช้ลอง / จับสำหรับตรรกะแบ่งไหลตรรกะ การติดตาม "ตรรกะ" ผ่านการสร้างที่ไม่ใช่เชิงตรรกะคือ (สำหรับฉัน) ตอบโต้ได้ง่ายและสับสน ฉันเคยอ่านตรรกะของฉันว่า "ถ้าเป็นเงื่อนไขแล้วก็ A B อื่น" การอ่านคำสั่งเดียวกับ "ลองจับแล้วดำเนินการ B" รู้สึกแปลก มันจะยิ่งแปลกถ้าคำสั่งAคือการมอบหมายอย่างง่ายต้องใช้รหัสพิเศษเพื่อบังคับให้มีข้อยกเว้นถ้าconditionเป็นเท็จ (และการทำที่อาจจะต้องมี - สถานะifต่อไป)


2

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

ฉันหมายถึงมีความเป็นไปได้หลายอย่าง:

  1. พวกเขาไร้ความสามารถ
  2. มีเหตุผลที่สมบูรณ์แบบสำหรับสิ่งที่พวกเขาทำซึ่งอาจไม่ปรากฏตั้งแต่แรกเห็น
  3. บางครั้งมันเป็นคำถามของการลิ้มรสและอาจทำให้การไหลเวียนของโปรแกรมซับซ้อนขึ้น
  4. เป็นที่ระลึกถึงอดีตที่ไม่มีใครเปลี่ยนแปลงเลยและพวกเขาจะมีความสุขถ้ามีคนทำ

... ฉันคิดว่าสิ่งเหล่านี้มีแนวโน้มที่เท่าเทียมกัน ดังนั้นขอให้พวกเขาเป็นอย่างดี


1

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

แก้ไข:

เหตุผล: คุณสามารถยืนยันได้ว่าถ้าคุณใช้ลอง catch เป็นตัวดำเนินการแบบมีเงื่อนไขคุณจะอธิบายถึงข้อยกเว้น REAL อย่างไร


2
OP กำลังขอเหตุผล / ข้อโต้แย้ง คุณยังไม่ได้ให้ข้อมูลใด ๆ
Oded

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

@delnan - ขอบคุณ! คุณได้พิสูจน์แล้วว่าเป็นจุดที่ฉันจะทำ หากมีคนตอบสิ่งที่คุณพูดกับทั้งเหตุผลของฉันและของ Oded ฉันจะหยุดพูดเพราะเขาไม่ได้มองหาเหตุผลที่เขาดื้อและไม่ต้องเสียเวลากับความดื้อรั้น
AJC

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

1
การใช้ try-catch เป็นโอเปอเรเตอร์ที่มีเงื่อนไขไม่สามารถป้องกันได้จากการทำงานไปจนถึงข้อยกเว้น "ของจริง"
Winston Ewert

1

มีข้อยกเว้นสำหรับเมื่อสิ่งที่ยอดเยี่ยมเกิดขึ้น โปรแกรมทำงานตามเวิร์กโฟลว์ปกติหรือไม่


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

ไม่ "ยอดเยี่ยม" เสมอไป ตัวอย่างเช่นการไม่ค้นหากุญแจใน hashtable นั้นไม่ใช่สิ่งที่ยอดเยี่ยม แต่ไลบรารี OCaml มักจะทำให้เกิดข้อยกเว้นในกรณีเช่นนี้ และมันก็โอเค - การจัดการข้อยกเว้นนั้นราคาถูกมาก
SK-logic

1
-1: คำพูดซ้ำซาก
คุกกี้แป้งข้าว

1

เหตุผลที่ใช้ข้อยกเว้น:

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

เหตุผลที่จะไม่ใช้ข้อยกเว้น:

  1. หลายภาษาไม่ได้ออกแบบมาเพื่อให้มีข้อยกเว้นอย่างรวดเร็ว
  2. ข้อยกเว้นที่เดินทางหลายเลเยอร์ขึ้นไปสแต็กสามารถปล่อยให้สถานะไม่สอดคล้องกันในการปลุกของพวกเขา

ในที่สุด:

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


0

ฉันใช้ try-> catch เป็นโฟลว์คอนโทรลในบางสถานการณ์ หากตรรกะหลักของคุณขึ้นอยู่กับสิ่งที่ล้มเหลว แต่คุณไม่ต้องการเพียงแค่ทำการยกเว้นและออกจาก ... นั่นคือสิ่งที่ try-> catch block มีไว้ให้ ฉันเขียนสคริปต์ unix ที่ไม่ได้ตรวจสอบกับเซิร์ฟเวอร์จำนวนมากและสิ่งที่สำคัญกว่านั้นสำหรับพวกเขาที่จะไม่ทำให้ล้มเหลว

ดังนั้นลองแผนและถ้าแผนตายจับและทำงานด้วย Plan B ... และถ้าแผน B ล้มเหลวในการใช้งานในที่สุดก็จะเตะออกแผนซีซึ่งอาจจะเป็นหนึ่งในการแก้ไขปัญหาของการบริการที่ล้มเหลวใน A หรือ B หรือหน้า ผม.


0

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


"มาตรฐานใน C ++ คือข้อยกเว้นควรถูกบันทึกไว้สำหรับเหตุการณ์ที่ยอดเยี่ยมอย่างแท้จริง" นี่เป็นเรื่องไร้สาระ แม้นักประดิษฐ์ของภาษาไม่เห็นด้วยกับคุณ
arayq2

-1

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

ถึงกระนั้นมันก็เป็นการปฏิบัติที่เลวร้ายเกินไป


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

ถ้าหลามกำลังทำการยกเว้นเนื่องจากไฟล์ไม่มีอยู่มันก็ดูเหมือนว่าจะส่งเสริมนิสัยที่ไม่ดีตามที่เดลนันอธิบาย
ต่อ Johansson

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

1
นี่ไม่ใช่นิสัยที่ไม่ดี เป็นสไตล์ที่แนะนำใน Python
Winston Ewert

@ back2dos คุณสามารถป้องกันมันได้เมื่อจัดการกับทรัพยากรภายนอกเช่นผู้ใช้รายอื่นของระบบฐานข้อมูล / ไฟล์หรือไม่?
Winston Ewert

-1

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


-1

ดูเหมือนว่าใช้การจัดการข้อยกเว้นเพื่อสร้างตรรกะ goto ที่ด้านบนของภาษาที่ไม่มีคำสั่ง goto

ด้วยเหตุผลหลายประการว่าทำไม goto logic ไม่ดีคุณสามารถอ้างถึงคำถามนี้: https://stackoverflow.com/questions/46586/goto-still-considered-harmful

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