ฉันต้องการเพิ่มสิ่งอื่นที่คำตอบอื่น ๆ บอกไว้ แต่ฉันไม่คิดว่ามีการพูดถึงอย่างชัดเจน:
@puck พูดว่า "ยังไม่มีการรับประกันอาร์กิวเมนต์แรกที่กล่าวถึงในชื่อฟังก์ชั่นเป็นพารามิเตอร์ตัวแรกจริงๆ"
@cbojar พูดว่า "ใช้ชนิดแทนอาร์กิวเมนต์ที่ไม่ชัดเจน"
ปัญหาคือภาษาการเขียนโปรแกรมไม่เข้าใจชื่อ: พวกมันแค่ถือว่าเป็นสัญลักษณ์ทึบแสงแบบอะตอม ดังนั้นเช่นเดียวกับความคิดเห็นของรหัสไม่จำเป็นต้องมีความสัมพันธ์ใด ๆ ระหว่างสิ่งที่ชื่อฟังก์ชั่นและวิธีการใช้งานจริง
เปรียบเทียบassertExpectedEqualsActual(foo, bar)
กับทางเลือกอื่น (จากหน้านี้และที่อื่น ๆ ) เช่น:
# Putting the arguments in a labelled structure
assertEquals({expected: foo, actual: bar})
# Using a keyword arguments language feature
assertEquals(expected=foo, actual=bar)
# Giving the arguments different types, forcing us to wrap them
assertEquals(Expected(foo), Actual(bar))
# Breaking the symmetry and attaching the code to one of the arguments
bar.Should().Be(foo)
สิ่งเหล่านี้มีโครงสร้างมากกว่าชื่อ verbose ซึ่งทำให้ภาษาที่ไม่ใช่สิ่งทึบแสงดู คำจำกัดความและการใช้งานของฟังก์ชั่นนี้ยังขึ้นอยู่กับโครงสร้างนี้ดังนั้นจึงไม่สามารถหลุดพ้นจากสิ่งที่การนำไปใช้งาน (เช่นชื่อหรือความคิดเห็นสามารถทำได้)
เมื่อฉันพบหรือมองข้ามปัญหาเช่นนี้ก่อนที่ฉันจะตะโกนใส่คอมพิวเตอร์ของฉันด้วยความหงุดหงิดฉันต้องใช้เวลาซักครู่ก่อนที่จะถามว่า 'ยุติธรรม' ที่โทษเครื่องเลยหรือเปล่า พูดอีกอย่างคือเครื่องให้ข้อมูลเพียงพอที่จะแยกแยะสิ่งที่ฉันต้องการจากสิ่งที่ฉันขอหรือไม่
การเรียกร้องเช่นassertEqual(expected, actual)
ทำให้ความรู้สึกมากที่สุดเท่าassertEqual(actual, expected)
ดังนั้นจึงเป็นเรื่องง่ายที่เราจะได้รับพวกเขาผสมขึ้นและสำหรับเครื่องไถข้างหน้าและทำสิ่งที่ผิด หากเราใช้assertExpectedEqualsActual
แทนอาจทำให้เรามีข้อผิดพลาดน้อยลง แต่จะไม่ให้ข้อมูลเพิ่มเติมกับเครื่อง (ไม่สามารถเข้าใจภาษาอังกฤษได้และการเลือกชื่อไม่ควรส่งผลต่อความหมาย)
สิ่งที่ทำให้ "มีโครงสร้าง" เป็นที่นิยมมากกว่าเช่นอาร์กิวเมนต์คำหลักเขตข้อมูลที่มีป้ายกำกับประเภทที่แตกต่าง ฯลฯ คือข้อมูลเพิ่มเติมยังสามารถอ่านได้ด้วยเครื่อง assertEqual
กรณีที่ไม่เลวร้ายเกินไปเนื่องจากปัญหาที่เกิดขึ้นก็จะเป็นแค่ข้อความที่ไม่ถูกต้อง ตัวอย่างที่น่ากลัวกว่าอาจเป็นString replace(String old, String new, String content)
เรื่องที่สับสนได้ง่ายString replace(String content, String old, String new)
ซึ่งมีความหมายแตกต่างกันมาก วิธีการรักษาที่ง่ายคือการจับคู่[old, new]
ซึ่งจะทำให้เกิดข้อผิดพลาดทำให้เกิดข้อผิดพลาดได้ทันที (แม้จะไม่มีประเภท)
โปรดทราบว่าแม้จะมีประเภทเราอาจพบว่าตัวเองไม่ 'บอกเครื่องสิ่งที่เราต้องการ' ตัวอย่างเช่นรูปแบบการต่อต้านที่เรียกว่า "การเขียนโปรแกรมแบบสตริง" ถือว่าข้อมูลทั้งหมดเป็นสตริงซึ่งทำให้ง่ายต่อการโต้แย้งรวมกัน (เช่นกรณีนี้) เพื่อลืมขั้นตอนบางอย่าง (เช่นการหลบหนี) เพื่อทำลายค่าคงที่โดยไม่ตั้งใจ ทำ JSON ที่ไม่สามารถตรวจสอบได้) ฯลฯ
สิ่งนี้เกี่ยวข้องกับ "ตาบอดแบบบูลีน" ซึ่งเราคำนวณกลุ่มบูลีน (หรือตัวเลข ฯลฯ ) ในส่วนหนึ่งของรหัส แต่เมื่อพยายามใช้ในอีกรูปแบบหนึ่งนั้นไม่ชัดเจนว่าเป็นตัวแทนจริงหรือไม่ เราทำให้พวกมันมั่วสุมกัน ฯลฯ เปรียบเทียบสิ่งนี้กับเช่น enums ที่แตกต่างกันซึ่งมีชื่อที่สื่อความหมาย (เช่นLOGGING_DISABLED
มากกว่าfalse
) และทำให้เกิดข้อความแสดงข้อผิดพลาดถ้าเราทำให้พวกมันสับสน