เป็นไปตามเงื่อนไขหรือไม่ที่จะมีผลข้างเคียง? [ปิด]


10

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

if (a > 33 | b++ < 54) {...}

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

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

ฉันไม่สามารถจินตนาการถึงโลกที่บรรทัดของรหัสนี้จะเป็นที่ยอมรับได้ ฉันผิดหรือเปล่า? ตกลงไหม กรณีทั่วไปมากขึ้น: เงื่อนไขกับผลข้างเคียง? เหล่านั้นเคยตกลง?


7
เส้นนั้นควรจะถูกอบออกจากวงโคจร สองเท่าสำหรับการวัดที่ดี
Blrfl

8
นิน: ท่อเดียว (แถบแนวตั้ง) เป็นบิตหรือในภาษาส่วนใหญ่มากกว่าตรรกะ "หรือ" มันไม่ลัดวงจรถ้าด้านซ้ายมือเป็นความจริง เนื่องจากเงื่อนไขนี้มีผลข้างเคียงทางด้านขวามันจึงสร้างความแตกต่างอย่างมากในผลลัพธ์
Jonathan Eunice

2
มีสำนวนที่ใช้ในภาษาต่างๆที่จะตกอยู่ในหมวดหมู่นี้ แต่เพราะพวกเขาเป็น "ที่รู้จักกันดี" หรือ "ปกติ" ไม่ก่อให้เกิดปัญหา บรรทัดในคำถามดูเหมือนจะไม่อยู่ในหมวดหมู่การใช้สำนวนดังนั้นฉันจึงหลีกเลี่ยงได้
Jaydee

2
@ JonathanEunice ใช่คนบางคนสับสนเกี่ยวกับการประเมินการลัดวงจร ไม่ใช่การพิมพ์ผิดในส่วนของฉัน
rianjs

5
ดูที่ด้านสว่าง. ตอนนี้คุณรู้จัก บริษัท อีกแห่งหนึ่งที่คุณไม่ต้องการสัมภาษณ์
John R. Strohm

คำตอบ:


23

มีหนึ่งผลข้างเคียงกึ่งเงื่อนไขที่ฉันสามารถคิดว่าไม่เป็นไร:while(iter.MoveNext())

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

ฉันไม่สามารถคิดถึงสถานการณ์ที่บรรทัดนั้นจะยอมรับได้ แต่ฉันก็ไม่สามารถนึกถึงสถานการณ์ที่บรรทัดนั้นจะมีประโยชน์ดังนั้นจึงยากที่จะจินตนาการถึงบริบทที่มีอยู่


มันเป็นเพียงวิธีการโยนในวิธีการระหว่างเรียน มันไม่ได้ตั้งใจจะทำสิ่งที่มีประโยชน์
rianjs

4
การwhile(v = *p++)สแกนรูปแบบC / C ++ อย่างเท่าเทียมกันผ่านอาร์เรย์ที่ไม่มีการสิ้นสุด (เช่นสตริง C) นั้นค่อนข้างธรรมดาและได้รับการยอมรับอย่างกว้างขวาง
Phil Miller

3
ฉันมักจะพิจารณาเงื่อนไขแบบวนรอบของแบบฟอร์มwhile(c = input.read() != '\n')ว่าเป็นสำนวนที่สมเหตุสมผล

1
อาจมีสำนวนที่ยอมรับได้ทั่วไปอยู่บ้าง แต่ชัดเจนว่า "การมีความฉลาดในค่าใช้จ่ายของความชัดเจน" นั้นตกอยู่ในค่ายที่ไม่เคยมี
Julia Hayward

ฉันลืมเรื่อง iter.MoveNext () โดยสิ้นเชิง กรณีที่เหมาะสมอย่างยิ่งสำหรับเงื่อนไขที่มีผลข้างเคียง ขอบคุณ!
rianjs

8

ในโลกของฉันการอ่านจากหน่วยความจำอาจถือว่าเป็นผลข้างเคียง (เช่นการแมปหน่วยความจำ IO)

ตอนนี้ให้พิจารณาสิ่งต่อไปนี้:

    while( ( *memory_mapped_device_status_register & READY_FLAG) == 0) {
       // Wait
    }

และเปรียบเทียบกับ:

    status = *memory_mapped_device_status_register;
    while( ( status & READY_FLAG) == 0) {
        // Wait
        status = *memory_mapped_device_status_register;
    }

การหลีกเลี่ยงผลข้างเคียง (การอ่าน) ในเงื่อนไขช่วยให้สามารถอ่านได้หรือไม่ หรือว่าเป็นรหัสซ้ำและเพิ่มความยุ่งเหยิง?

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


3

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

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

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

ยิ่งการบรรเทาสถานการณ์เหล่านี้หายไปคนแปลกหน้าก็จะกลายเป็นสิ่งก่อสร้าง หากประเภทลูปเฉพาะ (เช่นif((c = getc()) == 'x') { quit(); }เป็นที่รู้จักและยอมรับโดยชุมชนภาษาก็มีปัญหาน้อยกว่าเมื่อคุณคิดค้นมันเองตามธรรมชาติ ฯลฯ ตัวอย่างบรรทัดของคุณไม่ตรงกับมาตรฐานนั้น แต่ฉันจินตนาการได้มาก สิ่งที่น่ากลัวกว่านั้นคือฉันจะไม่พิมพ์มันน่ากลัวมาก


2

ถึงแม้ว่ารหัสเหม็นจริง ๆ มันมีข้อดีของการเป็นเรียบง่าย (และอาจเร็วขึ้นถ้าคุณไม่มีคอมไพเลอร์ optimizing ดี) กว่าเทียบเท่า if (a > 33 | b < 54) {b++; ...} else b++;

แต่แน่นอนมันเป็นไปได้ที่จะปรับให้เหมาะสมกับสิ่งต่อไปนี้ (แต่ระวัง! อันนี้มีพฤติกรรมที่แตกต่างกันในกรณีที่ล้น!): b++; if (a > 33 | b < 53) {...}

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