เมื่อใดที่ฉันควรใช้ Debug.Assert ()


220

ฉันเป็นวิศวกรซอฟต์แวร์มืออาชีพมาประมาณหนึ่งปีแล้วหลังจากสำเร็จการศึกษาระดับปริญญาตรี ฉันรู้เกี่ยวกับการยืนยันในขณะที่ใน C ++ และ C แต่ไม่รู้ว่าพวกเขามีอยู่ใน C # และ. NET เลยจนกระทั่งเมื่อไม่นานมานี้

รหัสการผลิตของเราไม่มีการยืนยันใด ๆ และคำถามของฉันคือสิ่งนี้ ...

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

Debug.Assert(val != null);

หรือ

if ( val == null )
    throw new exception();

2
การแบ่งขั้วที่คุณตั้งไว้คือเงื่อนงำ มันไม่ได้เป็นคำถามของ - หรือสำหรับข้อยกเว้นและยืนยันมันทั้ง - และสำหรับรหัสการป้องกัน เมื่อใดที่ต้องทำซึ่งเป็นสิ่งที่คุณต้องการทำความเข้าใจ
Casper Leon Nielsen

5
ฉันเคยอ่านใครบางคนแนะนำว่าข้อยกเว้นหรือวิธีการอื่น ๆ ของการขัดข้องนั้นเหมาะสมสำหรับเงื่อนไขที่ "ไม่มีทางที่ฉันจะฟื้นตัวจากเรื่องนี้ได้อย่างสมเหตุสมผล" และการยืนยันก็เหมาะสมสำหรับเงื่อนไขที่ "สิ่งนี้ไม่ควรเกิดขึ้นเลย" แต่สถานการณ์ที่เป็นจริงใดที่ทำให้เงื่อนไขหลังนี้เป็นที่พึงพอใจ มาจากพื้นหลัง Python ที่การยืนยันยังคงดำเนินต่อไปฉันไม่เคยเข้าใจวิธี Java / C # ในการปิดการตรวจสอบความถูกต้องบางอย่างของคุณในการผลิต กรณีเดียวที่ฉันเห็นจริงๆคือถ้าการตรวจสอบมีราคาแพง
Mark Amery


2
ส่วนตัวฉันใช้ข้อยกเว้นสำหรับวิธีสาธารณะและยืนยันวิธีส่วนตัว
เฟรด

คำตอบ:


230

ในการดีบักแอปพลิเคชัน Microsoft .NET 2.0 John Robbins มีส่วนสำคัญในการยืนยัน ประเด็นหลักของเขาคือ:

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

PS: ถ้าคุณชอบ Code Complete ฉันแนะนำให้ติดตามด้วยหนังสือเล่มนี้ ฉันซื้อมันเพื่อเรียนรู้เกี่ยวกับการใช้ WinDBG และไฟล์ดัมพ์ แต่ครึ่งแรกนั้นเต็มไปด้วยเคล็ดลับเพื่อช่วยหลีกเลี่ยงข้อบกพร่องในตอนแรก


3
+1 สำหรับบทสรุปที่กระชับและเป็นประโยชน์ ใช้โดยตรงมาก สิ่งสำคัญที่ขาดหายไปสำหรับฉันคือเมื่อต้องใช้ Trace.Assert vs. Trace.Assert เช่นเมื่อคุณทำ / ไม่ต้องการในรหัสการผลิตของคุณ
Jon Coombs

2
JonCoombs คือ "Trace.Assert vs. Trace.Assert" คำพิมพ์?
thelem

1
@thelem บางทีจอนหมายกับDebug.Assert Trace.Assertหลังถูกดำเนินการในรุ่นที่วางจำหน่ายเช่นเดียวกับการสร้าง Debug
DavidRR

เหตุใดฉันจึงควรเลือก Debug ขอให้ส่งข้อยกเว้น
Barış Akkurt

86

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

Debug.Assert()คุณยังจะโยนข้อยกเว้นก่อนที่จะเรียก การยืนยันเพียงทำให้แน่ใจว่าทุกอย่างเป็นไปตามที่คาดไว้ในขณะที่คุณยังคงพัฒนา


35
คุณช่วยอธิบายได้ไหมว่าทำไมถึงมีการยืนยันถ้าคุณยังคงมีข้อยกเว้นก่อนที่จะเรียกมัน หรือฉันเข้าใจผิดคำตอบของคุณ?
Roman Starkov

2
@romkyns คุณยังต้องรวมไว้เพราะถ้าคุณไม่ทำเมื่อคุณสร้างโครงการในโหมดReleaseการตรวจสอบ / การตรวจสอบข้อผิดพลาดทั้งหมดจะหายไป
Oscar Mederos

28
@ ออสการ์ฉันคิดว่านั่นเป็นจุดเริ่มต้นของการใช้งานการยืนยันในตอนแรก ... โอเคงั้นคุณก็ใส่ข้อยกเว้นไว้ข้างหน้าพวกเขา - แล้วทำไมต้องยืนยันด้วย?
Roman Starkov

4
@superjos: ฉันต้องไม่เห็นด้วย: จุด # 2 ในคำตอบของ MacLeod ระบุว่าคุณต้องการการยืนยันและข้อยกเว้น แต่ไม่ใช่ในสถานที่เดียวกัน มันไม่มีประโยชน์ที่จะโยน NullRefEx ในตัวแปรและหลังจากทำ Assert (วิธีการยืนยันจะไม่แสดงกล่องโต้ตอบในกรณีนี้ซึ่งเป็นจุดยืนยันทั้งหมด) สิ่งที่ MacLeod หมายถึงคือในบางสถานที่คุณจะต้องมีข้อยกเว้นในบางกรณี Assert ก็เพียงพอแล้ว
เดวิด

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

52

จากรหัสเสร็จสมบูรณ์

8 โปรแกรมป้องกัน

8.2 การยืนยัน

การยืนยันเป็นรหัสที่ใช้ในระหว่างการพัฒนา - โดยปกติแล้วเป็นรูทีนหรือมาโคร - ที่อนุญาตให้โปรแกรมตรวจสอบตัวเองเมื่อมันทำงาน เมื่อการยืนยันเป็นจริงนั่นหมายความว่าทุกอย่างทำงานตามที่คาดไว้ เมื่อเป็นเท็จนั่นหมายความว่าตรวจพบข้อผิดพลาดที่ไม่คาดคิดในรหัส ตัวอย่างเช่นหากระบบสันนิษฐานว่าไฟล์ข้อมูลลูกค้าจะไม่มีระเบียนมากกว่า 50,000 รายการโปรแกรมอาจมีการยืนยันว่าจำนวนระเบียนน้อยกว่าหรือเท่ากับ 50,000 ตราบใดที่จำนวนระเบียนน้อยกว่าหรือเท่ากับ 50,000 การยืนยันจะเงียบ หากพบมากกว่า 50,000 เร็กคอร์ดมันจะดัง "ยืนยัน" ว่ามีข้อผิดพลาดในโปรแกรม

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

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

( ... )

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


7
ดังนั้นจะเกิดอะไรขึ้นหากไฟล์ข้อมูลลูกค้าที่พบในการผลิตมีมากกว่า 50,000 รายการ? หากการยืนยันถูกรวบรวมจากรหัสการผลิตและสถานการณ์นี้ไม่ได้รับการจัดการเป็นอย่างอื่นปัญหาการสะกดนี้จะไม่เกิดขึ้น?
DavidRR

1
@DavidRR ใช่แน่นอน แต่ทันทีที่สัญญาณการผลิตเกิดปัญหาและนักพัฒนาบางคน (ซึ่งอาจไม่รู้รหัสนี้ดี) debugs ปัญหาการยืนยันจะล้มเหลวและนักพัฒนาจะรู้ทันทีว่าระบบไม่ได้ใช้ตามที่ตั้งใจไว้
Marc

48

FWIW ... ฉันพบว่าวิธีสาธารณะของฉันมักจะใช้if () { throw; }รูปแบบเพื่อให้แน่ใจว่าวิธีการนั้นถูกเรียกอย่างถูกต้อง Debug.Assert()วิธีการส่วนตัวของฉันมักจะใช้

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

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


3
นี่เป็นคำอธิบายที่ชัดเจนมากของการฝึกฝนที่ดีและให้คำตอบที่สมเหตุสมผลกับคำถามที่ถาม
Casper Leon Nielsen

42

ใช้ข้อความยืนยันเพื่อตรวจสอบสมมติฐานของนักพัฒนาซอฟต์แวร์และข้อยกเว้นเพื่อตรวจสอบสมมติฐานด้านสิ่งแวดล้อม


31

ถ้าฉันเป็นคุณฉันจะทำ:

Debug.Assert(val != null);
if ( val == null )
    throw new exception();

หรือเพื่อหลีกเลี่ยงการตรวจสอบสภาพซ้ำ

if ( val == null )
{
    Debug.Assert(false,"breakpoint if val== null");
    throw new exception();
}

5
วิธีนี้แก้ปัญหาได้อย่างไร ด้วยวิธีนี้ debug.assert จะไม่มีจุดหมาย
Quibblesome

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

2
+1 ผมมีปัญหามากที่ผู้คนก็จะพยายาม / ข้อยกเว้นจับไม่ต้องทำอะไรเพื่อให้การติดตามข้อผิดพลาดเป็นปัญหา
dance2die

5
ฉันคิดว่ามีหลายกรณีที่คุณอาจต้องการทำสิ่งนี้ แต่คุณไม่ควรรับข้อยกเว้นทั่วไป!
Casebash

8
@ MarkIngram -1 ถึงคำตอบของคุณและ +1 ความคิดเห็นของคุณเพื่อแสดงความคิดเห็น นี่เป็นเคล็ดลับที่ดีสำหรับสถานการณ์ที่แปลกประหลาด แต่ดูเหมือนว่าเป็นเรื่องแปลกประหลาดที่ต้องทำโดยทั่วไปสำหรับการตรวจสอบทั้งหมด
Mark Amery

24

หากคุณต้องการ Asserts ในรหัสการผลิตของคุณ (เช่น Release builds) คุณสามารถใช้ Trace.Assert แทน Debug.Assert

หลักสูตรนี้เพิ่มค่าใช้จ่ายในการปฏิบัติการของการผลิตของคุณ

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

คุณสามารถลบล้างพฤติกรรมนี้ได้โดยการลบ DefaultTraceListener: ดูที่เอกสารสำหรับ Trace.Listeners ใน MSDN

สรุป,

  • ใช้ Debug.Assert อย่างอิสระเพื่อช่วยตรวจจับข้อบกพร่องในการสร้าง Debug

  • หากคุณใช้ Trace.Assert ในโหมดส่วนต่อประสานผู้ใช้คุณอาจต้องการลบ DefaultTraceListener เพื่อหลีกเลี่ยงการทำให้ผู้ใช้สับสน

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


1
+1 สำหรับการชี้ให้เห็นความแตกต่างที่สำคัญระหว่าง Debug.Assert และ Trace.Assert เนื่องจาก OP ได้ถามเฉพาะเกี่ยวกับรหัสการผลิต
Jon Coombs

21

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

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


11

ในระยะสั้น

Asserts จะใช้สำหรับยามและสำหรับการตรวจสอบการออกแบบโดยข้อ จำกัด สัญญา ได้แก่ :

  • Assertsควรใช้สำหรับการสร้าง Debug และไม่ใช่การสร้างเท่านั้น โดยทั่วไป Asserts จะถูกละเว้นโดยคอมไพเลอร์ใน Release builds
  • Asserts สามารถตรวจสอบข้อบกพร่อง / เงื่อนไขที่ไม่คาดคิดซึ่งอยู่ในการควบคุมของระบบของคุณ
  • Asserts ไม่ใช่กลไกสำหรับการตรวจสอบบรรทัดแรกของอินพุตของผู้ใช้หรือกฎเกณฑ์ทางธุรกิจ
  • Assertsไม่ควรใช้เพื่อตรวจสอบสภาพแวดล้อมที่ไม่คาดคิด (ซึ่งอยู่นอกการควบคุมของรหัส) เช่นหน่วยความจำไม่เพียงพอ, เครือข่ายล้มเหลว, ฐานข้อมูลล้มเหลว ฯลฯ แม้ว่าจะพบได้ยาก แต่ต้องมีเงื่อนไขเหล่านี้ (และรหัสแอปของคุณ ความล้มเหลวของฮาร์ดแวร์หรือทรัพยากรหมดไป) โดยทั่วไปแล้วจะมีการโยนข้อยกเว้น - แอปพลิเคชันของคุณสามารถดำเนินการแก้ไขได้ (เช่นลองการดำเนินการฐานข้อมูลหรือเครือข่ายลองเพิ่มหน่วยความจำแคช) หรือยกเลิกอย่างสง่างามหากไม่สามารถจัดการข้อยกเว้นได้
  • การยืนยันที่ล้มเหลวควรเป็นอันตรายต่อระบบของคุณเช่นไม่เหมือนกับข้อยกเว้นอย่าพยายามจับหรือจัดการล้มเหลวAssertsรหัสของคุณทำงานในพื้นที่ที่ไม่คาดคิด การติดตามสแต็กและการดัมพ์ข้อผิดพลาดสามารถใช้เพื่อกำหนดสิ่งที่ผิดพลาด

การยืนยันมีประโยชน์มหาศาล:

  • เพื่อช่วยในการค้นหาการตรวจสอบความถูกต้องที่ขาดหายไปของอินพุตของผู้ใช้หรือข้อบกพร่องอัปสตรีมในรหัสระดับที่สูงขึ้น
  • การยืนยันในฐานรหัสนำเสนอสมมติฐานที่ชัดเจนในรหัสไปยังเครื่องอ่านอย่างชัดเจน
  • Assert จะถูกตรวจสอบที่ runtime ในDebugbuilds
  • เมื่อรหัสได้รับการทดสอบอย่างละเอียดแล้วการสร้างรหัสใหม่เป็น Release จะลบค่าใช้จ่ายในการตรวจสอบข้อสมมติฐาน (แต่ด้วยประโยชน์ที่การสร้าง Debug ในภายหลังจะยกเลิกการตรวจสอบหากจำเป็น)

... รายละเอียดเพิ่มเติม

Debug.Assertเป็นการแสดงออกถึงเงื่อนไขที่สันนิษฐานเกี่ยวกับสถานะของส่วนที่เหลือของบล็อกรหัสภายในการควบคุมของโปรแกรม ซึ่งอาจรวมถึงสถานะของพารามิเตอร์ที่ให้ไว้สถานะของสมาชิกของอินสแตนซ์ของคลาสหรือว่าการส่งคืนจากการเรียกใช้เมธอดอยู่ในช่วงสัญญา / ออกแบบ โดยทั่วไปการยืนยันควรทำเธรด / กระบวนการ / โปรแกรมด้วยข้อมูลที่จำเป็นทั้งหมด (Stack Trace, Crash Dump, ฯลฯ ) ตามที่ระบุถึงสถานะของบั๊กหรือเงื่อนไขที่ไม่ได้รับการพิจารณาซึ่งไม่ได้ออกแบบมาสำหรับ (เช่นอย่าพยายามจับหรือ จัดการกับความล้มเหลวในการยืนยันความถูกต้องด้วยข้อยกเว้นที่เป็นไปได้หนึ่งข้อเมื่อการยืนยันตัวเองอาจทำให้เกิดความเสียหายได้มากกว่าข้อบกพร่อง (เช่นตัวควบคุมการจราจรทางอากาศไม่ต้องการ YSOD เมื่อเครื่องบินไปดำน้ำ การผลิต ... )

เมื่อใดที่คุณควรใช้Asserts? - ณ จุดใดก็ได้ในระบบหรือไลบรารี API หรือบริการที่อินพุตเข้าสู่ฟังก์ชันหรือสถานะของคลาสนั้นถูกต้อง (เช่นเมื่อการตรวจสอบเสร็จสิ้นลงในอินพุตของผู้ใช้ในระดับงานนำเสนอของระบบ โดยทั่วไปแล้วชั้นธุรกิจและชั้นข้อมูลจะสมมติว่าการตรวจสอบว่างการตรวจสอบช่วงการตรวจสอบความยาวสตริง ฯลฯ ในอินพุตได้ทำไปแล้ว - การAssertตรวจสอบทั่วไปรวมถึงกรณีที่การสันนิษฐานที่ไม่ถูกต้องอาจส่งผลให้เกิดการปฏิเสธวัตถุเป็นศูนย์ตัวหารที่เป็นศูนย์การคำนวณทางคณิตศาสตร์ที่เป็นตัวเลขหรือวันที่มากเกินไปและการออกนอกวง / ทั่วไปไม่ได้ออกแบบมาสำหรับพฤติกรรม จะเป็นการระมัดระวังหากAssertอายุอยู่ระหว่าง 0 ถึง 125 หรือมากกว่านั้น - ค่าของ -100 และ 10 ^ 10 ไม่ได้ถูกออกแบบมาสำหรับ)

สัญญาสุทธิรหัส
ในสุทธิกองสัญญารหัสสามารถนำมาใช้ในการนอกเหนือไปหรือเป็นทางเลือกกับผู้Debug.Assertใช้ รหัสสัญญาสามารถทำเป็นทางการตรวจสอบสถานะและสามารถช่วยในการตรวจสอบการละเมิดสมมติฐานที่ ~ เวลารวบรวม (หรือหลังจากนั้นไม่นานถ้าเรียกใช้เป็นพื้นหลังตรวจสอบใน IDE)

ตรวจสอบการออกแบบตามสัญญา (DBC) ที่มีอยู่รวมถึง:

  • Contract.Requires - เงื่อนไขเบื้องต้นตามสัญญา
  • Contract.Ensures - PostConditions ที่ทำสัญญา
  • Invariant - เป็นการแสดงออกถึงข้อสันนิษฐานเกี่ยวกับสถานะของวัตถุ ณ ทุกจุดในช่วงอายุของมัน
  • Contract.Assumes - ทำให้ตัวตรวจสอบแบบคงที่สงบลงเมื่อมีการเรียกวิธีการตกแต่งที่ไม่ใช่สัญญา

น่าเสียดายที่ Code Contracts นั้นตายไปแล้วเนื่องจาก MS หยุดพัฒนามัน
Mike Lowery

10

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

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

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

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


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

+1 สำหรับ"สิ่งที่ฉันไม่ชอบคือความจริงที่ว่ามันทำให้ debug build ทำงานแตกต่างจาก build build หากการยืนยัน debug ล้มเหลว แต่ฟังก์ชั่นทำงานใน release แล้วมันมีความหมายอย่างไร?" ใน. NET System.Diagnostics.Trace.Assert()ดำเนินการในรุ่นที่วางจำหน่ายเช่นเดียวกับการสร้าง Debug
DavidRR

7

ตามมาตรฐาน IDesignคุณควร

ยืนยันทุกข้อสมมติฐาน โดยเฉลี่ยแล้วทุก ๆ บรรทัดที่ห้าเป็นการยืนยัน

using System.Diagnostics;

object GetObject()
{...}

object someObject = GetObject();
Debug.Assert(someObject != null);

ในฐานะที่เป็นข้อจำกัดความรับผิดชอบฉันควรพูดถึงฉันไม่พบว่ามันใช้งานได้จริงในการใช้ IRL นี้ แต่นี่คือมาตรฐานของพวกเขา


ดูเหมือน Juval Lowy ชอบอ้างตัวเอง
devlord

6

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

จากตัวอย่าง check-for-null ของคุณหากนี่เป็น API ภายในเท่านั้นฉันอาจใช้การยืนยัน หากอยู่ใน API สาธารณะฉันจะใช้การตรวจสอบและส่งข้อความอย่างชัดเจน


ใน. NET หนึ่งสามารถใช้System.Diagnostics.Trace.Assert()เพื่อดำเนินการยืนยันในการสร้าง (การผลิต) การสร้าง
DavidRR

กฎการวิเคราะห์รหัสCA1062: ตรวจสอบข้อขัดแย้งของวิธีการสาธารณะ ต้องตรวจสอบข้อโต้แย้งnullเมื่อ: "วิธีการที่มองเห็นจากภายนอกเป็นหนึ่งในข้อโต้แย้งอ้างอิงโดยไม่ตรวจสอบว่าอาร์กิวเมนต์นั้นเป็น โมฆะ หรือไม่" ArgumentNullExceptionในสถานการณ์เช่นนี้วิธีการหรือสถานที่ให้บริการควรโยน
DavidRR

6

การยืนยันทั้งหมดควรเป็นรหัสที่สามารถปรับให้เหมาะกับ:

Debug.Assert(true);

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

public static void ConsumeEnumeration<T>(this IEnumerable<T> source)
{
  if(source != null)
    using(var en = source.GetEnumerator())
      RunThroughEnumerator(en);
}
public static T GetFirstAndConsume<T>(this IEnumerable<T> source)
{
  if(source == null)
    throw new ArgumentNullException("source");
  using(var en = source.GetEnumerator())
  {
    if(!en.MoveNext())
      throw new InvalidOperationException("Empty sequence");
    T ret = en.Current;
    RunThroughEnumerator(en);
    return ret;
  }
}
private static void RunThroughEnumerator<T>(IEnumerator<T> en)
{
  Debug.Assert(en != null);
  while(en.MoveNext());
}

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

ในกรณีแรกไม่มีปัญหา

ในกรณีที่สองมีปัญหากับรหัสการโทร - มันไม่ควรเรียกGetFirstAndConsumeด้วย null ดังนั้นจึงได้รับการยกเว้นกลับ

ในกรณีที่สามมีปัญหากับรหัสนี้เนื่องจากควรตรวจสอบแล้วen != nullก่อนที่จะมีการเรียกใช้เพื่อให้ไม่เป็นปัญหาจริง หรือกล่าวอีกนัยหนึ่งมันควรเป็นโค้ดที่สามารถปรับให้เหมาะกับทฤษฎีได้Debug.Assert(true)โดย sicne en != nullควรเป็นtrue!


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

@ DavidRR แน่นอนว่าฉันไม่สามารถเป็นโมฆะและยืนยันในรหัสจึงเป็นชื่อ แน่นอนฉันอาจจะผิดหรือถูกทำผิดโดยการเปลี่ยนแปลงและนั่นคือมูลค่าของการเรียกร้องยืนยัน
Jon Hanna

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

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

4

ฉันคิดว่าฉันจะเพิ่มอีกสี่กรณีที่ Debug.Assert สามารถเป็นทางเลือกที่เหมาะสม

1)สิ่งที่ฉันไม่ได้เห็นกล่าวถึงที่นี่เป็นความคุ้มครองเพิ่มเติมแนวคิดอ้างสามารถให้ในระหว่างการทดสอบแบบอัตโนมัติ เป็นตัวอย่างง่ายๆ:

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

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

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

2)นอกจากนี้การทดสอบบางอย่างจะง่ายต่อการเขียน แต่ค่าใช้จ่ายสูงและไม่จำเป็นที่กำหนดสมมติฐานเริ่มต้น ตัวอย่างเช่น:

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

3)ถัดไปในบางกรณีของผลิตภัณฑ์อาจไม่มีปฏิสัมพันธ์วินิจฉัยเป็นประโยชน์สำหรับการทั้งหมดหรือบางส่วนของการดำเนินงานเมื่อนำไปใช้งานในโหมดการเปิดตัว ตัวอย่างเช่น:

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

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

หากการString.Findดำเนินการหลักระบุว่าจะส่งคืน-1เมื่อไม่พบเกณฑ์การค้นหาคุณอาจสามารถดำเนินการหนึ่งอย่างปลอดภัยแทนที่จะดำเนินการสามข้อ อย่างไรก็ตามหากมีการส่งคืนจริง-2คุณอาจไม่มีแนวทางที่เหมาะสม มันจะไม่เป็นประโยชน์ในการแทนที่การคำนวณที่ง่ายกว่าด้วยการทดสอบที่แยกต่างหากสำหรับ-1ค่าและไม่มีเหตุผลในสภาพแวดล้อมการปล่อยส่วนใหญ่เพื่อทิ้งรหัสของคุณด้วยการทดสอบเพื่อให้มั่นใจว่าไลบรารีหลักทำงานได้ตามที่คาดไว้ ในกรณีนี้ Asserts เหมาะอย่างยิ่ง


4

อ้างอิงคำพูดที่นำมาจากThe Pragmatic Programmer: จาก Journeyman ถึง Master

เปิดการยืนยันไว้

มีความเข้าใจผิดทั่วไปเกี่ยวกับการยืนยันที่ประกาศโดยคนที่เขียนคอมไพเลอร์และสภาพแวดล้อมทางภาษา มันเป็นอะไรแบบนี้

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

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

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

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

แม้ว่าคุณจะมีปัญหาด้านประสิทธิภาพให้ปิดเฉพาะคำยืนยันที่ทำให้คุณรู้สึก


2

คุณควรใช้วิธีที่สองเสมอ (โยนข้อยกเว้น)

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


1
ไม่ได้เช่นเดียวกับคำตอบอื่น ๆ ที่นี่: คุณไม่เข้าใจความแตกต่างอย่างแท้จริงดังนั้นคุณจึงเลือกไม่รับสิ่งใดสิ่งหนึ่งได้โดยตั้งค่าขั้วสองขั้วที่ผิดระหว่างพวกเขาในกระบวนการ Dw
Casper Leon Nielsen

3
นี่เป็นคำตอบที่ถูกต้องเพียงข้อเดียวของรายการ IMO อย่ายกเลิกมันอย่างง่ายดายแคสเปอร์ Debug Assert เป็นรูปแบบการต่อต้าน หากค่าคงที่ของเวลา debug ค่าคงที่ ณ รันไทม์ การอนุญาตให้แอปของคุณดำเนินการต่อโดยค่าคงที่ที่ไม่ทำงานจะทำให้คุณอยู่ในสภาวะที่ไม่สามารถกำหนดได้และอาจเกิดปัญหาที่เลวร้ายยิ่งกว่าการล่ม IMO จะดีกว่าถ้ามีรหัสเดียวกันทั้งในการสร้างซึ่งล้มเหลวอย่างรวดเร็วด้วยสัญญาที่เสียหายและใช้การจัดการข้อผิดพลาดที่มีประสิทธิภาพในระดับสูงสุด เช่นแยกส่วนประกอบและใช้ความสามารถในการเริ่มต้นใหม่ (เช่นแท็บที่หยุดทำงานในเบราว์เซอร์จะไม่ทำให้เบราว์เซอร์ทั้งหมดขัดข้อง)
justin.m.chase

1
อาจมีประโยชน์ในการรวม Trace.Assert ไว้ในการสนทนาของคุณที่นี่เนื่องจากไม่สามารถไล่ตามอาร์กิวเมนต์เดียวกันได้
Jon Coombs

0

คุณควรใช้ Debug.Assert เพื่อทดสอบหาข้อผิดพลาดเชิงตรรกะในโปรแกรมของคุณ ผู้รวบรวมสามารถแจ้งให้คุณทราบถึงข้อผิดพลาดทางไวยากรณ์เท่านั้น ดังนั้นคุณควรใช้คำสั่ง Assert เพื่อทดสอบหาข้อผิดพลาดเชิงตรรกะ เช่นเดียวกับการทดสอบว่าโปรแกรมที่ขายรถยนต์ที่ BMW เท่านั้นที่มีสีน้ำเงินควรได้รับส่วนลด 15% complier ไม่สามารถบอกคุณได้ว่าโปรแกรมของคุณถูกต้องตามหลักเหตุผลในการดำเนินการนี้ แต่ข้อความยืนยันสามารถทำได้


2
ขออภัย แต่ข้อยกเว้นทำสิ่งเดียวกันทั้งหมดดังนั้นคำตอบนี้ไม่ได้ตอบคำถามจริง
โรมัน Starkov

0

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

ในกรณีแรกการยืนยันไม่จำเป็นต้องแม้แต่ในรหัสสุดท้าย คุณควรใช้Debug.Assertในระหว่างการพัฒนาและคุณสามารถลบออกหาก / เมื่อไม่ต้องการอีกต่อไป ถ้าคุณต้องการที่จะปล่อยพวกเขาหรือถ้าคุณลืมที่จะลบพวกเขาไม่มีปัญหาเพราะพวกเขาจะไม่มีผลใด ๆ ในการรวบรวมการปล่อย

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

Trace.Assertมีวิธีที่สมบูรณ์แบบเพื่อบรรลุเป้าหมายนี้ มันจะไม่ถูกลบออกในการผลิตและสามารถกำหนดค่ากับผู้ฟังที่แตกต่างกันโดยใช้ app.config ดังนั้นสำหรับการพัฒนาตัวจัดการเริ่มต้นนั้นใช้ได้และสำหรับการผลิตคุณสามารถสร้าง TraceListener แบบง่าย ๆ เช่นด้านล่างซึ่งจะทำการยกเว้นและเปิดใช้งานในไฟล์ config การผลิต

using System.Diagnostics;

public class ExceptionTraceListener : DefaultTraceListener
{
    [DebuggerStepThrough]
    public override void Fail(string message, string detailMessage)
    {
        throw new AssertException(message);
    }
}

public class AssertException : Exception
{
    public AssertException(string message) : base(message) { }
}

และในไฟล์ config การผลิต:

<system.diagnostics>
  <trace>
    <listeners>
      <remove name="Default"/>
      <add name="ExceptionListener" type="Namespace.ExceptionTraceListener,AssemblyName"/>
    </listeners>
  </trace>
 </system.diagnostics>

-1

ฉันไม่ทราบว่ามันอยู่ใน C # และ. NET แต่ใน C จะยืนยัน () จะทำงานเฉพาะเมื่อคอมไพล์ด้วย -DDEBUG - enduser จะไม่เห็น assert () หากคอมไพล์โดยไม่มี สำหรับนักพัฒนาเท่านั้น ฉันใช้มันบ่อยมากบางครั้งก็ง่ายต่อการติดตามบั๊ก


-1

ฉันจะไม่ใช้มันในรหัสการผลิต โยนข้อยกเว้นจับและบันทึก

นอกจากนี้ยังต้องระวังใน asp.net ด้วยเนื่องจาก assert สามารถแสดงบนคอนโซลและหยุดการร้องขอได้

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