วิธีสอนการจัดการข้อยกเว้นสำหรับโปรแกรมเมอร์ใหม่ [ปิด]


21

คุณจะสอนการจัดการข้อยกเว้นให้โปรแกรมเมอร์อย่างไร มีการสอนสิ่งอื่น ๆ ทั้งหมดได้อย่างง่ายดาย - โครงสร้างข้อมูล, ASP.NET, WinForms, WPF, WCF - คุณตั้งชื่อมันทุกอย่างสามารถสอนได้อย่างง่ายดาย

ด้วยการจัดการข้อยกเว้นการสอนให้พวกเขาลองจับในที่สุดก็เป็นเพียงลักษณะทางวากยสัมพันธ์ของการจัดการข้อยกเว้น

สิ่งที่ควรสอนคือ - คุณใส่ส่วนใดของรหัสไว้ในบล็อคลอง คุณทำอะไรในบล็อกcatch

ให้ฉันอธิบายด้วยตัวอย่าง

คุณกำลังทำงานในโครงการ Windows Forms (ยูทิลิตี้ขนาดเล็ก) และคุณได้ออกแบบดังต่อไปนี้ด้วย 3 โครงการที่แตกต่างกัน

  1. UILayer
  2. BusinessLayer
  3. ชั้นข้อมูล

หากมีข้อยกเว้น (ให้เราพูดว่าการโหลด XDocument มีข้อผิดพลาดเกิดขึ้น) จะถูกยกขึ้นที่ DataLayer (UILayer เรียกว่า BusinessLayer ซึ่งในทางกลับกันเรียก DataLayer) คุณเพิ่งทำสิ่งต่อไปนี้

//In DataLayer
try {
    XDocument xd_XmlDocument = XDocument.Load("systems.xml");
} 
catch(Exception ex)
{
    throw ex;
}

ซึ่งถูกโยนอีกครั้งใน BusinessLayer และที่ติดอยู่ใน UILayer ที่ฉันเขียนไปยังล็อกไฟล์

นี่เป็นวิธีที่คุณใช้เกี่ยวกับการจัดการข้อยกเว้นหรือไม่


15
หากคุณกำลังจะทำเช่นนั้นคุณไม่ต้องการที่จะจับ (Exception ex) {throw ex; } - แทนที่จะจับ {โยน; }
Steven Evers

4
ให้ไม่ลืมบล็อกในที่สุด?
Chris

1
คุณควรระบุภาษาในแท็ก คุณได้รับรายละเอียดมากกว่าเป็นเรื่องปกติสำหรับการใช้งานข้อยกเว้นส่วนใหญ่และไม่สนใจสิ่งภายนอกบล็อก ใน C ++ ตัวอย่างเช่นส่วนที่สำคัญที่สุดของการจัดการข้อยกเว้นคือการรู้วิธีการเขียนโปรแกรมที่ปลอดภัย
David Thornley


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

คำตอบ:


29

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

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

การพูดว่า "catch ex, throw ex" ไม่ใช่วิธีที่ดีในการจัดการกับข้อยกเว้นเนื่องจากมันไม่ได้จัดการอะไรเลย นอกจากนี้ขึ้นอยู่กับว่ารูปแบบข้อยกเว้นในภาษาของคุณทำงานอย่างไรซึ่งอาจเป็นอันตรายได้จริงหากมันล้างข้อมูลการติดตามสแต็กที่คุณอาจเคยใช้เพื่อแก้ไขปัญหา เพียงแค่ปล่อยให้ข้อยกเว้นแพร่กระจายสแต็คการโทรจนกว่ามันจะกระทบกับรูทีนที่รู้วิธีจัดการ


4
+1 สำหรับ "... เพราะมันไม่ได้จัดการอะไรจริง ๆ " คนใหม่ที่จะจัดการข้อยกเว้นบ่อยครั้งที่คิดว่าการจับหมายถึงการจัดการและไม่ทราบว่าคุณไม่ได้ทำอะไรเพื่อแก้ไขปัญหาไม่ใช่การจัดการที่ยกเว้น เพียงแค่รหัสขยาย
จิมมี่ฮอฟฟา

13

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

บรรทัดล่าง: การแสดงวิธีจัดการข้อผิดพลาดใน C จะทำให้นักเรียนเข้าใจว่าข้อยกเว้นมีไว้เพื่ออะไรและทำไมการจับข้อยกเว้นที่คุณไม่สามารถจัดการได้จริงๆคือการจำลองวิธีการทำสิ่งต่าง ๆ ในยุคมืด


2
+1 สำหรับการฝึกการสอนของพวกเขาในรหัสส่งคืนสไตล์ C ดั้งเดิมและหมายเลขข้อผิดพลาดและแสดงให้พวกเขาเห็นว่ามันทำงานได้ไม่ดีและดังนั้นจึงสอนให้พวกเขารู้ว่ามันจะทำงานได้อย่างไรยอดเยี่ยม!
Kanini

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

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

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

นั่นคือเหตุผลที่คุณได้ +1 ของฉัน ผมรู้สึกว่าคำตอบของคุณอาจตีความได้ว่า "ไม่เคยใช้กลไกอื่น" :)
Matthieu เอ็ม

5

ฉันจะเริ่มต้นด้วยแนวทางการออกแบบสำหรับข้อยกเว้นสั้น ๆ และรวมถึง DO, DO NOT และหลีกเลี่ยง มันยังให้เหตุผลว่าทำไม

ในกรณีตัวอย่างของคุณส่วน revelvent จะเป็นการตัดข้อยกเว้น

และคาดว่าจะเขียนด้วยวิธีนี้ โปรดทราบว่ามันจับข้อยกเว้นที่เฉพาะเจาะจงและพยายามที่จะเพิ่มข้อมูลเพื่อให้ข้อความที่มีความหมายมากขึ้นถูกเผยแพร่ โปรดทราบว่าข้อยกเว้นภายในยังคงอยู่เพื่อการบันทึก

//In DataLayer

try
{
XDocument xd_XmlDocument = XDocument.Load("systems.xml");
}
catch(FileNotFoundException ex)
{
        throw new TransactionFileMissingException(
                     "Cannot Access System Information",ex);
}

UPDATE Kanini ถามว่าถูกต้องหรือไม่หากมีบล็อกข้อยกเว้นนี้ในชั้นข้อมูลหรือควรตรวจสอบไฟล์ที่มีอยู่ในชั้นธุรกิจ

ก่อนอื่นผมอยากจะชี้ให้เห็นว่าเหตุผลในการห่อข้อยกเว้นคือสิ่งนี้

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

ดังนั้นถ้าคุณรู้สึกว่ามีเลเยอร์ที่สูงกว่าควรรู้เกี่ยวกับไฟล์เลยเลเยอร์ข้อมูลของคุณควรมีลักษณะเช่นนี้

//In DataLayer

XDocument xd_XmlDocument = XDocument.Load("systems.xml");

ไม่ลองไม่จับ

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

ตามตัวอย่างที่เฉพาะเจาะจงเช่นนี้ยังมีปัญหาต่อไปนี้ใน XDocument โหลดสามารถโยน execeptions ที่สี่

  • ArgumentNullException
  • SecurityException
  • FileNotFoundException
  • UriFormatException

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

 if (File.Exists("systems.xml")) 
     XDocument.Load("systems.xml");

SecurityException ยิ่งแย่ลงเนื่องจากสาเหตุอื่น ๆ ที่ทำให้เกิดข้อผิดพลาดนี้หากกระบวนการอื่นคว้าการล็อกไฟล์แบบเอกสิทธิ์เฉพาะบุคคลคุณจะไม่ได้รับข้อผิดพลาดจนกว่าคุณจะลองเปิดอ่านเพราะมันไม่มีวิธี File.CanIOpenThis () และหากวิธีการดังกล่าวมีอยู่คุณยังคงมีปัญหาเช่นเดียวกับ File.Exists


แก้ไข: ขอบคุณ! แต่มันก็ถูกต้องที่จะมีบล็อกข้อยกเว้นนี้ในชั้นข้อมูล? สิ่งที่ควรตรวจสอบทั้งหมดว่าไฟล์นั้นมีอยู่หรือไม่อยู่ในชั้นธุรกิจหรือไม่? มิฉะนั้นฉันเห็นด้วยกับวิธีการของคุณในการเขียนรหัส
Kanini

แก้ไข: ในภาษาพื้นเมืองของฉัน, Kanini หมายถึงคอมพิวเตอร์ในขณะที่ Kani หมายถึงผลไม้ ;-)
Kanini

ฉันสามารถบอกได้ว่าคุณไม่ได้อารมณ์เสียจากข้อผิดพลาดของฉัน แต่ฉันเสียใจมากและฉันได้แก้ไขมันแล้ว
Conrad Frix

1
แก้ไข: อารมณ์เสียหรือไม่ ไม่ใช่เลย. ขบขันอย่างมาก พี่ชายของฉันไม่ได้หยุดหัวเราะตั้งแต่ฉันชี้เรื่องนี้ให้เขาฟังเป็นหลักเพราะฉันไม่ได้ดูเหมือนผลไม้ด้วยซ้ำยกเว้นบางทีรูปร่างแปลก ๆ ...
Kanini

4

ให้เล่นตามบทบาท (นี่ไม่ใช่เรื่องตลก)

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

ใช้ปัญหาที่ง่ายมากเช่นไฟล์ IO gui-> model-> file_io

คนที่เป็นผู้อ่านไฟล์จำเป็นต้องบอกคนถัดไป

ก่อนอื่นให้ทำด้วยรหัสส่งคืน (ใช้โน้ตโพสต์ - ไหม)

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

สำหรับรหัสส่งคืนให้ส่งโน้ตโพสต์อิท

สำหรับข้อยกเว้นให้จับมือกันในอากาศแล้วพูดว่าปัญหาคืออะไร

จากนั้นให้พวกเขาทำ "catch x, throw x" และดูว่าการวินิจฉัยแย่ลงมากเพียงใดที่ GUI ได้รับ "โมเดลมีข้อยกเว้น"

ฉันคิดว่าสิ่งนี้จะทำงานเพื่อฝึกอบรมคนที่คุณมีเพราะคนเข้าใจการมีปฏิสัมพันธ์กับคนอื่นได้ดี


+1 สำหรับแนวคิดการสวมบทบาท เราไม่เคยคิดถึงมันมาก่อน ใครบ้างที่คิดว่าการเขียนโปรแกรมการสอนสามารถทำได้ผ่านบทบาทสมมุติ?
Kanini

1

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

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

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

ตัวอย่างที่ดีของสิ่งนี้อาจมาจากการเชื่อมต่อเครือข่าย:

  • เราทำการเชื่อมต่อ
  • การเชื่อมต่อก็โอเคเราจึงใช้มัน
  • เมื่อเสร็จแล้วเราจะปิดและทรัพยากรฟรี

หรือในกรณียกเว้น:

  • ทำการเชื่อมต่อ
  • ข้อยกเว้นเกิดขึ้นที่สิ่งที่จัดการ
  • ณ จุดนี้เราเพิ่มการเชื่อมต่อและทรัพยากรที่เกี่ยวข้อง

1

มอบแอปพลิเคชันให้กับมือใหม่ที่มีการจัดการข้อยกเว้นที่ดีมาก โยนข้อยกเว้นบางแห่งและให้พวกเขาแก้ปัญหาด้วยความช่วยเหลือของบันทึก โดยการติดตามการถ่ายทอดของข้อยกเว้นพวกเขาควรจะสามารถแก้ปัญหาได้ ทำแบบฝึกหัดนี้ 3 หรือ 4 ครั้ง ตอนนี้เพียงแค่ลบการจัดการข้อยกเว้นทั้งหมดออกจากโค้ดและให้พวกเขาลองติดตามข้อยกเว้นเดียวกัน

ฉันเชื่อว่าการชื่นชมโค้ดการจัดการข้อยกเว้นจะได้รับการชื่นชมในทันที


ฟังดูเหมือนแผน คุณมีรหัสตัวอย่างใด ๆ ในอินเทอร์เน็ต (เช่น sourceforge.net) ที่คุณอยากจะแนะนำไหม
Kanini

0

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


@denny: ในขณะที่ฉันเห็นด้วยกับ "การจัดการข้อยกเว้นเท่านั้นจะตอบสนองเมื่อเกิดข้อผิดพลาด (หรือข้อยกเว้น)" ฉันค่อนข้างไม่แน่ใจเกี่ยวกับข้อความที่ว่า "การจัดการข้อยกเว้นและคำสั่งควบคุมการไหลเป็นพื้นฐานเดียวกัน" ฉันไม่เห็นด้วยอย่างเคารพ บล็อก catch ยอมรับอย่างเป็นสิ่งที่ควรทำภายใต้เงื่อนไขนั้น บล็อกการลองใช้ไม่ได้เกี่ยวกับโฟลว์หรือการควบคุม ในที่สุดบล็อกอีกครั้งไม่ได้เกี่ยวกับการไหลหรือการควบคุม บางทีฉันอาจเข้าใจผิดคำตอบของคุณ แต่คุณสามารถชี้แจงเพื่อประโยชน์ของฉันและผู้อื่นได้หรือไม่?
Kanini

0

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

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

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


0

หลอกลิงกำลังใช้แป้นพิมพ์

ฉันเคยบอกพวกเขาเมื่อพวกเขากำลังเขียนรหัสเพื่อแสร้งว่าลิงกำลังนั่งอยู่ที่คีย์บอร์ดและใช้แอปพลิเคชันนี้

สิ่งนี้สอนให้พวกเขารู้ถึงสิ่งต่าง ๆ ทุกอย่าง

  • ไม่มีข้อมูล
  • ไฟล์หายไป
  • อักขระอัลฟ่าเมื่อคุณคาดหวังตัวเลข
  • การหารด้วยศูนย์

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


ลิง? ฉันคิดว่าผู้ใช้ทางธุรกิจของคุณไม่เคยได้ยินเช่นนั้น ;-)
Kanini

@Kanini - เป็นคนดี นั่นคือในวันนาวิกโยธินของฉัน ฉันแค่อยากให้คนของฉันคิดนอกกรอบเมื่อมันเกิดข้อผิดพลาดในการวางกับดัก ฉันแค่พูดว่าดักข้อผิดพลาด ... ฉันหมายถึงการจัดการข้อยกเว้น
Michael Riley - AKA Gunny
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.