ความแตกต่างระหว่าง "เงื่อนไขเบื้องต้น" และ "ยืนยัน" อย่างรวดเร็ว?


105

อะไรคือความแตกต่างระหว่างprecondition(condition: Bool, message: String)และassert(condition: Bool, message: String)ในสวิฟท์?

ทั้งสองคนดูเหมือนกันกับฉัน เราควรใช้บริบทใด

คำตอบ:


125

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

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

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

ข้อความเต็มจากเอกสาร (ลองคลิกตัวเลือกassertและpreconditionใน Xcode):

เงื่อนไขเบื้องต้น

ตรวจสอบเงื่อนไขที่จำเป็นสำหรับการก้าวไปข้างหน้า

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

  • ในสนามเด็กเล่นและสร้าง -Onone (ค่าเริ่มต้นสำหรับการตั้งค่าการดีบัก Xcode ของ): ถ้าประเมินเท็จหยุดการทำงานของโปรแกรมในรัฐแก้ปัญหาได้หลังจากการพิมพ์conditionmessage

  • In -O builds (ค่าเริ่มต้นสำหรับ Xcode's Release configuration): หากconditionประเมินเป็นเท็จให้หยุดการทำงานของโปรแกรม

  • ใน -Ounchecked สร้างconditionไม่ได้รับการประเมิน แต่เพิ่มประสิทธิภาพอาจจะคิดว่ามันจะtrueประเมิน การไม่ปฏิบัติตามสมมติฐานใน -Ounchecked builds เป็นข้อผิดพลาดในการเขียนโปรแกรมที่ร้ายแรง

ยืนยัน

ยืนยันสไตล์ C แบบดั้งเดิมด้วยข้อความเสริม

ใช้ฟังก์ชันนี้สำหรับการตรวจสอบความเรียบร้อยภายในที่ทำงานอยู่ในระหว่างการทดสอบ แต่ไม่ส่งผลกระทบต่อประสิทธิภาพของรหัสการขนส่ง เพื่อตรวจสอบการใช้งานที่ไม่ถูกต้องในรุ่น Release; ดูprecondition.

  • ในสนามเด็กเล่นและสร้าง -Onone (ค่าเริ่มต้นสำหรับการตั้งค่าการดีบัก Xcode ของ): ถ้าประเมินเท็จหยุดการทำงานของโปรแกรมในรัฐแก้ปัญหาได้หลังจากการพิมพ์conditionmessage

  • In -O builds (ค่าเริ่มต้นสำหรับการกำหนดค่ารีลีสของ Xcode) conditionไม่ได้รับการประเมินและไม่มีเอฟเฟกต์

  • ใน -Ounchecked สร้างconditionไม่ได้รับการประเมิน แต่เพิ่มประสิทธิภาพอาจจะคิดว่ามันจะtrueประเมิน การไม่ปฏิบัติตามสมมติฐานใน -Ounchecked builds เป็นข้อผิดพลาดในการเขียนโปรแกรมที่ร้ายแรง


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

2
ในการตอบคำถามของคุณฉันใช้การยืนยันเป็นการส่วนตัวเพื่อจับสิ่งที่ไม่ควรเกิดขึ้นในงานสร้างของฉันในขณะที่ฉันเขียนและทดสอบ ลองนึกภาพคำสั่งยามอ่าน JSON ในที่ที่data["name"]ไม่มีอยู่จริง แต่ควร การมีเจ้าหน้าที่รักษาการณ์อยู่ข้างใน .. else {} จะช่วยให้ฉันจับข้อผิดพลาดของฉันได้โดยการขัดข้องและนำฉันไปสู่ปัญหา ในทำนองเดียวกันถ้ารหัสนี้อยู่ระหว่างการผลิตผู้ยืนยันจะไม่ขัดข้องกับโปรแกรมและรหัสสำรองใด ๆ ที่ฉันใช้ ( return nil) จะเข้ายึดครอง
Alec O

1
คุณไม่ควรตรวจสอบดัชนีและไม่ทำอะไรเลยแทนที่จะทำให้ทั้งแอปล่มใช่หรือไม่?
Iulian Onofrei

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

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

90

ฉันพบว่าSwift ยืนยัน - คู่มือที่ขาดหายไปจะเป็นประโยชน์

                        debug   release   release
function                -Onone  -O       -Ounchecked
assert()                YES     NO        NO
assertionFailure()      YES     NO        NO**
precondition()          YES     YES       NO
preconditionFailure()   YES     YES       YES**
fatalError()*           YES     YES       YES

และจากการอภิปรายที่น่าสนใจเกี่ยวกับ Swift Evolution

- ยืนยัน: ตรวจสอบรหัสของคุณเองเพื่อหาข้อผิดพลาดภายใน

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

นอกจากนี้คุณต้องระมัดระวังเกี่ยวกับสิ่งที่จะใช้ดูassertionFailure และ Optimization Level


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

@Honey ฉันคิดว่าเขาหมายถึงข้อโต้แย้ง / ผลลัพธ์จากการเรียก API เครือข่ายหรือปลั๊กอินของลูกค้าเอง
Chen Li Yong

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

@ onmyway133: จาก Xcode ความช่วยเหลือด่วนผมคิดว่าprecondition()และpreconditionFailure()จะมีพฤติกรรมเดียวกัน ความแตกต่างระหว่างฟังก์ชันเหล่านี้คือ: preconditionต้องมีเงื่อนไขภายในในขณะที่preconditionFailureเพียงแค่โยนออกไป
nahung89

13

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

ฉันพบคำอธิบายที่ดีนี้เมื่อจะใช้กับ NSHipster:

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

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


การยืนยันสามารถเปิดใช้งานและปิดใช้งานได้โดยใช้แฟล็กคอมไพเลอร์ สามารถใช้งานได้ในรหัสที่จัดส่ง
Pétur Ingi Egilsson

6

เงื่อนไขเบื้องต้น

func precondition(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

ตรวจสอบเงื่อนไขที่จำเป็นสำหรับการก้าวไปข้างหน้า

  1. ใช้ฟังก์ชั่นนี้เพื่อตรวจจับเงื่อนไขที่ทำให้โปรแกรมไม่สามารถดำเนินการต่อได้แม้จะอยู่ในรหัสการจัดส่งก็ตาม
  2. ใน Playgrounds และ -Onone builds (ค่าดีฟอลต์สำหรับคอนฟิกูเรชันดีบักของ Xcode): หากเงื่อนไขประเมินว่าเป็นเท็จให้หยุดการทำงานของโปรแกรมในสถานะที่ดีบักได้หลังจากพิมพ์ข้อความ
  3. In -O builds (ค่าดีฟอลต์สำหรับ Xcode's Release configuration): หากเงื่อนไขประเมินเป็นเท็จให้หยุดการทำงานของโปรแกรม
  4. ในการสร้างที่ไม่ถูกตรวจสอบเงื่อนไขจะไม่ได้รับการประเมิน แต่เครื่องมือเพิ่มประสิทธิภาพอาจสันนิษฐานว่าจะประเมินเป็นจริง ความล้มเหลวในการปฏิบัติตามสมมติฐานใน -Ounchecked builds เป็นข้อผิดพลาดในการเขียนโปรแกรมที่ร้ายแรง

ยืนยัน

func assert(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

ยืนยันสไตล์ C แบบดั้งเดิมด้วยข้อความเสริม

  1. ใช้ฟังก์ชันนี้สำหรับการตรวจสอบความเรียบร้อยภายในที่ทำงานอยู่ระหว่างการทดสอบ แต่ไม่มีผลกระทบต่อประสิทธิภาพของรหัสการขนส่ง เพื่อตรวจสอบการใช้งานที่ไม่ถูกต้องในรุ่น Release; ดูเงื่อนไขเบื้องต้น

  2. ใน Playgrounds และ -Onone builds (ค่าดีฟอลต์สำหรับคอนฟิกูเรชันดีบักของ Xcode): หากเงื่อนไขประเมินว่าเป็นเท็จให้หยุดการทำงานของโปรแกรมในสถานะที่ดีบักได้หลังจากพิมพ์ข้อความ

  3. In -O builds (ค่าดีฟอลต์สำหรับ Xcode's Release configuration) เงื่อนไขไม่ได้รับการประเมินและไม่มีเอฟเฟกต์
  4. ในการสร้างที่ไม่ถูกตรวจสอบเงื่อนไขจะไม่ได้รับการประเมิน แต่เครื่องมือเพิ่มประสิทธิภาพอาจสันนิษฐานว่าจะประเมินเป็นจริง ความล้มเหลวในการปฏิบัติตามข้อสันนิษฐานใน -Ounchecked builds เป็นข้อผิดพลาดในการเขียนโปรแกรมที่ร้ายแรง

0

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

การเพิ่มลิงค์เอกสาร

แนบรูปภาพจาก swift.org ด้วย

ป้อนคำอธิบายภาพที่นี่

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

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

และ

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

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