ตรวจสอบพารามิเตอร์ที่ใส่คำอธิบายประกอบด้วย @Nonnull เป็นค่าว่างหรือไม่


19

เราได้เริ่มใช้ FindBugs และใส่คำอธิบายประกอบพารามิเตอร์ของเรา@Nonnullอย่างเหมาะสมและใช้งานได้ดีในการชี้จุดบกพร่องในช่วงต้นรอบ จนถึงตอนนี้เราได้ตรวจสอบข้อโต้แย้งเหล่านี้อย่างต่อเนื่องเพื่อnullใช้ของ Guava checkNotNullแต่ฉันต้องการตรวจสอบnullเฉพาะที่ขอบ - สถานที่ที่ค่าสามารถเข้ามาโดยไม่ได้รับการตรวจสอบnullเช่นคำขอ SOAP

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

ฉันเข้าใจ@Nonnullว่าไม่ได้บล็อกnullค่าตัวเอง

แต่ให้ที่ FindBugs จะชี้ให้เห็นได้ทุกค่าจะถูกโอนจากสนามป้ายให้เป็นหนึ่งในการทำเครื่องหมาย@Nonnullไม่สามารถเราขึ้นอยู่กับมันจะจับกรณีเหล่านี้ (ซึ่งมันไม่) โดยไม่ต้องตรวจสอบค่าเหล่านี้สำหรับnullทุกที่ที่พวกเขาได้รับการผ่านรอบใน ระบบ? ฉันไร้เดียงสาที่ต้องการเชื่อถือเครื่องมือและหลีกเลี่ยงการตรวจสอบ verbose เหล่านี้หรือไม่

Bottom line:แม้ว่าจะปลอดภัยที่จะลบการnullตรวจสอบครั้งที่สองด้านล่าง แต่เป็นการปฏิบัติที่ไม่ดีหรือไม่?

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

คำตอบ:


6

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

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

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

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

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

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

คำอธิบายประกอบ @nonnull สามารถเห็นได้ว่าเป็นเงื่อนไขเบื้องต้นที่ใช้สำหรับการวิเคราะห์แบบคงที่โดยเครื่องมือ FindBugs หากคุณต้องการวิธีการเช่นการตรวจสอบการยืนยันรันไทม์นั่นคือกลยุทธ์แรกที่ล้มเหลวคุณควรพิจารณาใช้คำสั่งการยืนยันเป็น Java ในตัว หรืออาจจะปรับให้เข้ากับกลยุทธ์สเปคที่ซับซ้อนยิ่งขึ้นโดยใช้ภาษาสเปคอินเตอร์เฟสพฤติกรรมเช่น Java Modeling Language (JML)

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

หากคุณแบ่งปันมุมมองของฉันเกี่ยวกับ @nonnull ว่าเป็นสัญญา (ไฟ) มันเป็นเรื่องธรรมดาที่จะไม่เพิ่มการตรวจสอบเพิ่มเติมเพราะแนวคิดดั้งเดิมที่อยู่เบื้องหลังหลักการนี้คือการหลีกเลี่ยงการเขียนโปรแกรมป้องกัน


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

4

พิจารณาเหตุผลที่คุณไม่เขียน

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

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

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


3
@Nonnullกำหนดสัญญาว่าสายที่จะต้องไม่ผ่านnullการสร้างและ FindBugs ใช้การวิเคราะห์แบบคงที่จะหาสายที่อาจช่วยให้null--specifically สายที่ส่งผ่านค่าไม่ได้ทำเครื่องหมาย@Nonnullตัวเอง แต่ผู้โทรสามารถส่งต่อnullและเพิกเฉยต่อคำเตือนจาก FindBugs ได้
David Harkness

การเขียนโปรแกรมไม่ได้เป็นความมหัศจรรย์สีดำ โชคไม่ดีที่คำเตือนและความประหลาดใจมีอยู่มากมายโดยเฉพาะอย่างยิ่งเมื่อทำงานกับรหัสการทำงานพร้อมกันบางส่วนที่นั่น♬ ~ ᕕ (ᐛ) Har
Tim Harper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.