ลอง / จับ / บันทึก / Rethrow - เป็นรูปแบบการต่อต้านหรือไม่


19

ฉันสามารถดูโพสต์ได้หลายแห่งซึ่งมีความสำคัญของการจัดการข้อยกเว้นที่ตำแหน่งศูนย์กลางหรือที่ขอบเขตกระบวนการได้รับการเน้นว่าเป็นแนวปฏิบัติที่ดีแทนที่จะทิ้งขยะบล็อคโค้ดทุกอันรอบลอง / จับ ฉันเชื่ออย่างยิ่งว่าพวกเราส่วนใหญ่เข้าใจถึงความสำคัญของมัน แต่ฉันเห็นคนยังคงลงท้ายด้วยรูปแบบการป้องกัน catch-log-rethrow เป็นหลักเพราะเพื่อความสะดวกในการแก้ไขปัญหาในระหว่างการยกเว้นพวกเขาต้องการบันทึกข้อมูลเฉพาะบริบทเพิ่มเติม ผ่าน) และวิธีคือการห่อวิธีรอบลอง / catch / log / rethrow

public static bool DoOperation(int num1, int num2)
{
    try
    {
        /* do some work with num1 and num2 */
    }
    catch (Exception ex)
    {
        logger.log("error occured while number 1 = {num1} and number 2 = {num2}"); 
        throw;
    }
}

มีวิธีที่ถูกต้องในการบรรลุเป้าหมายนี้ในขณะที่ยังคงมีข้อยกเว้นในการจัดการแนวปฏิบัติที่ดีหรือไม่? ฉันได้ยินเกี่ยวกับกรอบ AOP เช่น PostSharp สำหรับเรื่องนี้ แต่อยากทราบว่ามีข้อเสียหรือประสิทธิภาพที่สำคัญที่เกี่ยวข้องกับกรอบ AOP เหล่านี้หรือไม่

ขอบคุณ!


6
มีความแตกต่างอย่างมากระหว่างการห่อแต่ละวิธีในลอง / จับบันทึกข้อยกเว้นและปล่อยให้ chug รหัสพร้อม และลอง / จับและ rethrowing ข้อยกเว้นด้วยข้อมูลเพิ่มเติม อย่างแรกคือการฝึกฝนที่แย่มาก ประการที่สองเป็นวิธีที่ดีที่สุดในการปรับปรุงประสบการณ์การดีบักของคุณ
ร่าเริง

ฉันกำลังบอกว่าลอง / จับแต่ละวิธีและเพียงเข้าสู่ระบบ catch catch และ rethrow - นี่เป็นสิ่งที่ทำได้หรือไม่
rahulaga_dev

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

1
ดูคำตอบของ @ Liath คำตอบใด ๆ ที่ฉันให้จะสะท้อนให้เห็นถึงเขาค่อนข้างมาก: จับข้อยกเว้นให้เร็วที่สุดเท่าที่จะทำได้และถ้าคุณสามารถทำอะไรในช่วงนั้นคือบันทึกข้อมูลที่มีประโยชน์ การดูสิ่งนี้ในฐานะที่เป็นปฏิปักษ์นั้นเป็นเรื่องไร้สาระในมุมมองของฉัน
David Arno

1
Liath: เพิ่มข้อมูลโค้ดขนาดเล็ก ฉันใช้ c #
rahulaga_dev

คำตอบ:


19

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

แนวคิดที่นี่คือเพื่อเพิ่มความสามารถในการดีบักแอปพลิเคชันของคุณ

ตัวอย่าง # 1:จัดการมัน

try
{
    doSomething();
}
catch (Exception e)
{
    log.Info("Couldn't do something", e);
    doSomethingElse();
}

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

การจัดการข้อยกเว้นอาจรวมถึงการแจ้งผู้ใช้ว่ามีปัญหาเกิดขึ้นบันทึกเหตุการณ์หรือเพียงแค่เพิกเฉย

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

try
{
    context.DrawLine(x1,y1, x2,y2);
}
catch (OutOfMemoryException)
{
    // WinForms throws OutOfMemory if the figure you are attempting to
    // draw takes up less than one pixel (true story)
}

ตัวอย่าง # 2:เพิ่มบริบทเพิ่มเติมและโยน

try
{
    doSomething(line);
}
catch (Exception e)
{
    throw new MyApplicationException(filename, line, e);
}

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

ตัวอย่าง # 3:อย่าทำอะไรเลยยกเว้น

try
{
    doSomething();
}
finally
{
   // cleanup resources but let the exception percolate
}

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


ฉันชอบ " ปัญหาไม่ใช่บล็อก catch ท้องถิ่นปัญหาคือบันทึกและการสร้างใหม่ " ฉันคิดว่านี่เป็นเหตุผลที่เหมาะสมที่จะตรวจสอบการบันทึกที่สะอาดยิ่งขึ้น แต่ในที่สุดมันก็หมายความว่าจะเป็นไรเมื่อลอง / จับได้ว่ากระจัดกระจายไปตามวิธีการทั้งหมดใช่ไหม? ฉันคิดว่าจะต้องมีแนวทางบางอย่างเพื่อให้แน่ใจว่าการปฏิบัตินี้ได้รับการปฏิบัติอย่างรอบคอบมากกว่าที่จะมีวิธีการทำเช่นนั้น
rahulaga_dev

ฉันให้แนวทางในการตอบ สิ่งนี้ไม่ได้ตอบคำถามของคุณ?
Berin Loritsch

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

7

ฉันไม่เชื่อว่าการจับในท้องถิ่นเป็นรูปแบบการต่อต้านในความเป็นจริงถ้าฉันจำได้อย่างถูกต้องมันบังคับใช้จริงใน Java!

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

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

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

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

ตัวอย่างเช่น:

public bool TryConnectToDatabase()
{
  try
  {
    this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
    return true;
  }
  catch(Exception ex)
  {
     this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
    return false;
  }
}

หรือตัวอย่างการทำใหม่:

public IDbConnection ConnectToDatabase()
{
  try
  {
    // connect to the database and return the connection, will throw if the connection cannot be made
  }
  catch(Exception ex)
  {
     this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
    throw;
  }
}

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

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

คุณไม่ได้พูดถึงภาษาที่คุณใช้ แต่เป็นนักพัฒนา. NET และได้เห็นสิ่งนี้หลายครั้งเกินไปที่จะไม่พูดถึงมัน

อย่าเขียน:

catch(Exception ex)
{
  throw ex;
}

ใช้:

catch(Exception ex)
{
  throw;
}

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

TLDR

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


3
จุดเข้าสู่ระบบในการจับคืออะไรเมื่อจะใช้ตัวบันทึกเดียวกันในตัวจัดการข้อยกเว้นระดับบนสุด?
ร่าเริง

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

2
ในกรณีดังกล่าวให้ส่งข้อยกเว้นใหม่พร้อมข้อมูลเพิ่มเติมและข้อยกเว้นภายใน
ร่าเริง

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

4
Java ไม่ได้บังคับให้คุณจัดการกับข้อยกเว้นมันบังคับให้คุณต้องระวัง คุณสามารถจับมันและทำอะไรก็ได้หรือเพียงแค่ประกาศว่ามันเป็นสิ่งที่ฟังก์ชั่นสามารถโยนและไม่ทำอะไรกับมันในฟังก์ชั่น .... nitpicking เล็กน้อยในคำตอบที่ดีงาม!
Newtopian

4

ขึ้นอยู่กับภาษามาก เช่น C ++ ไม่มีการติดตามสแต็กในข้อความแสดงข้อผิดพลาดข้อยกเว้นดังนั้นการติดตามข้อยกเว้นผ่าน catch-log – rethrow บ่อยจึงเป็นประโยชน์ ในทางตรงกันข้าม Java และภาษาที่คล้ายกันมีการติดตามสแต็กที่ดีมากแม้ว่ารูปแบบของการติดตามสแต็กเหล่านี้อาจไม่สามารถกำหนดค่าได้มาก การจับและการยกเว้นซ้ำในภาษาเหล่านี้นั้นไม่มีจุดหมายอย่างเต็มที่เว้นแต่คุณจะสามารถเพิ่มบริบทที่สำคัญบางอย่างได้ (เช่นการเชื่อมต่อข้อยกเว้น SQL ระดับต่ำกับบริบทของการดำเนินการทางตรรกะทางธุรกิจ)

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

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

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


4

เมื่อฉันเห็นtry/catch/logในทุก ๆ วิธีมันทำให้เกิดความกังวลว่านักพัฒนาไม่มีความคิดว่าแอพพลิเคชั่นของพวกเขาอาจจะหรืออาจจะไม่เกิดขึ้นสันนิษฐานว่าแย่ที่สุด

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

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

Nulls เป็นตัวอย่าง หากคุณได้รับค่าเป็นอาร์กิวเมนต์หรือผลลัพธ์ของการเรียกเมธอดและมันไม่ควรเป็นโมฆะให้โยนข้อยกเว้น อย่าเพิ่งบันทึกผลลัพธ์ที่NullReferenceExceptionถูกส่งออกไปห้าบรรทัดในภายหลังเนื่องจากค่า Null ไม่ว่าคุณจะได้รับข้อยกเว้น แต่อย่างใดอย่างหนึ่งบอกคุณบางอย่างในขณะที่อื่น ๆ ที่ทำให้คุณมองหา

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


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

สกอตต์ฉันมีความรู้สึกเดียวกัน เมื่อใดก็ตามที่ฉันเห็นบันทึกและแสดงเพียงเพื่อบันทึกบริบทฉันรู้สึกเหมือนนักพัฒนาไม่สามารถควบคุมค่าคงที่ของชั้นเรียนหรือไม่สามารถป้องกันการเรียกวิธีการ ทุกวิธีแทนวิธีทั้งหมดถูกห่อในลอง / catch / log / throw และมันก็แย่มาก
Max

2

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

public static bool DoOperation(int num1, int num2)
{
    try
    {
        /* do some work with num1 and num2 */
    }
    catch (Exception ex)
    {
        throw new Exception("error occured while number 1 = {num1} and number 2 = {num2}", ex);
    }
}

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

คุณอาจต้องการใช้คลาสยกเว้นที่กำหนดเอง แต่จุดนั้นเหมือนกัน

try / catch / log / rethrow เป็นระเบียบเพราะจะนำไปสู่ความสับสนบันทึก - เช่นถ้ามีข้อยกเว้นที่แตกต่างกันเกิดขึ้นในหัวข้ออื่นในระหว่างการบันทึกข้อมูลบริบทและบันทึกข้อยกเว้นจริงที่ในการจัดการระดับบนสุด? ลอง / จับ / โยนเป็นเรื่องปกติ แต่ถ้าข้อยกเว้นใหม่เพิ่มข้อมูลให้กับต้นฉบับ


ประเภทข้อยกเว้นดั้งเดิมคืออะไร ถ้าเราห่อมันก็หายไป มันเป็นปัญหาหรือไม่? มีคนอาศัย SqlTimeoutException เป็นตัวอย่าง
Max

@ Max: ประเภทยกเว้นดั้งเดิมยังคงมีให้เป็นข้อยกเว้นภายใน
JacquesB

นั่นคือสิ่งที่ฉันหมายถึง! ตอนนี้ทุกคนเรียก call stack ซึ่งกำลังจับตามองสำหรับ SqlException จะไม่มีวันได้รับมัน
Max

1

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

บ่อยครั้งที่คุณจะเห็นรูปแบบของข้อยกเว้นหลายประการที่ถูกดักจับและสร้างใหม่เป็นข้อยกเว้นทั่วไปเช่นการจับ DatabaseConnectionException, InvalidQueryException และ InvalidSQLParameterException และทำการสร้าง DatabaseException ใหม่ แม้ว่าจะเป็นเช่นนี้ฉันจะยืนยันว่าข้อยกเว้นเฉพาะเหล่านี้ทั้งหมดควรได้รับจาก DatabaseException ตั้งแต่แรกดังนั้นจึงไม่จำเป็นต้องทำการกู้ใหม่

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

ที่กล่าวว่า AOP อาจเป็นวิธีแก้ปัญหาอย่างรวดเร็วสำหรับคุณแม้ว่าโดยทั่วไปแล้วจะมีการชะลอตัวเล็กน้อยโดยรวม ฉันอยากจะแนะนำให้คุณลบคำสั่ง try catch ที่ไม่จำเป็นแทนโดยที่ไม่มีการเพิ่มมูลค่าใด ๆ


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

1
@DavidArno จริง แต่บริบทใด ๆ ที่คุณสามารถระบุไม่สามารถระบุได้เช่นกัน try { tester.test(); } catch (NullPointerException e) { logger.error("Variable tester was null!"); }มิฉะนั้นคุณจะต้อง การติดตามสแต็กนั้นเพียงพอในกรณีส่วนใหญ่ แต่หากขาดนั้นประเภทของข้อผิดพลาดมักจะเพียงพอ
Neil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.