การประเมินการลัดวงจรเมื่อใดที่ไม่ดี


12

เพื่อความชัดเจนมากขึ้นฉันจะระบุว่าฉันใช้เวลากับภาษาต่าง ๆ มากมาย แต่จนถึงตอนนี้ก็อาจเป็นไปได้ว่ามันจะใช้งานได้ตลอดเวลาหรือไม่รองรับเลย

ตอนนี้ทำงานมีฉันเริ่มต้นในโครงการที่ต้อง VB.net และฉันเห็นมันให้มันทั้งสองในแง่ของและและandalso อันแรกไม่ลัดวงจรและอันที่สองทำ

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

ฉันรู้ว่านี่อาจเป็นทางเลือกที่ดีกว่าดังนั้นถ้าฉันต้องใส่มันในบางที่อื่นก็แค่บอกฉันว่าที่ไหน

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



1
ดูเพิ่มเติมที่: softwareengineering.stackexchange.com/questions/246549/…
Doc Brown

คำตอบ:


5

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

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

ในกรณีอื่นคุณไม่ต้องการประเมินคำศัพท์ใด ๆ ที่เหลือหากการประเมินก่อนหน้านี้คืนค่าเท็จ

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

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

VB ANDALSO ของกรอบและดูเหมือนว่าจะพยายามที่จะทำให้การปฏิบัติที่ยอมรับได้มากขึ้น

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


4
ในขณะที่ถูกต้องตามข้อเท็จจริงแล้วมันไม่ใช่การออกแบบที่ยอดเยี่ยม
Robert Harvey

2
@ RobertHarvey ฉันไม่สามารถเขียนระบบควบคุมที่ไม่มีผลข้างเคียงและฉันไม่สามารถควบคุมระบบได้อย่างถูกต้องหากฉันไม่ตอบสนองต่อผลลัพธ์ ในคำอื่น ๆ ได้รับมัน;)
jwdonahue

7
ไม่ แต่คุณสามารถกำหนดผลลัพธ์ของฟังก์ชันที่มีผลข้างเคียงเหล่านั้นให้กับตัวแปรบูลีนตรวจสอบตัวแปรเหล่านั้นในifสภาพของคุณและยังเป็นไฟฟ้าลัดวงจร ฉันเห็นด้วยว่ามันเป็นความแตกต่างโวหาร แต่ก็มีข้อดีที่ทำให้สิ่งต่าง ๆ ชัดเจน
Robert Harvey

3
@ jwdonahue ไม่เป็นไรที่จะใช้ "คำใหญ่" ถ้าความเสี่ยงของความสับสนอยู่ในระดับต่ำ ความเสี่ยงที่จะเกิดความสับสนและการหายตัวไปของความผิดปกติของบล็อกรหัสเช่นนี้นั้นสูงมากและอาจเป็นความหายนะต่อตรรกะ มันไม่เคยดีเลยที่จะทำให้นักพัฒนาการอ่านคิดหนักมาก
jpmc26

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

20

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

การประเมินการลัดวงจรเมื่อใดที่ไม่ดี

เป็นเพียง: เมื่อมีการละเมิดกันไปข้างหลัง

ตกลงตอนนี้คุณสามารถพูดได้ว่า VB.NET นั้นไม่เข้ากันได้กับ VB6 หรือ VBA เก่ามาก แต่อย่างน้อยก็มีบางส่วนของภาษา การตัดสินใจของ Microsoft ในการรักษาความหมาย AND และ OR หรือเก่า (โดยไม่ทำให้เกิดการลัดวงจร) ทำให้เกิดข้อผิดพลาดประเภทใหญ่มากเมื่อทำการย้ายโปรแกรม VB เก่าไปยัง VB.NET

ในทางกลับกันนักออกแบบภาษา VB.NET อาจแบ่งปันความคิดเห็นของคุณเกี่ยวกับการลัดวงจรเป็นสิ่งที่ดี เมื่อฉันจำได้อย่างถูกต้องรุ่น VB.NET ก่อนวางจำหน่ายครั้งแรกที่ให้บริการ AND หรือ OR กับการลัดวงจร แต่ความคิดเห็นของนักพัฒนาต้องไม่ดีนัก MS ถอนการตัดสินใจนี้ก่อนที่ VB.NET 1.0 จะปรากฏขึ้น ดังนั้นนักออกแบบจึงตัดสินใจที่จะใช้งานมันในแง่ของคำหลักใหม่ANDALSOและORELSEเป็นการแลกเปลี่ยนระหว่างความเข้ากันได้ย้อนหลังและประโยชน์

IMHO นี่เป็นการตัดสินใจที่ดี ฉันต้องพอร์ตโปรแกรมเก่าหลายโปรแกรมในทศวรรษที่ผ่านมาและไม่ต้องทำการวิเคราะห์ผลกระทบอย่างหนักสำหรับนิพจน์เชิงตรรกะทั้งหมดรวมถึงและและ / หรือหรือ (การเล่นสำนวนเจตนา) ทำให้งานนั้นง่ายขึ้นและประหยัดมากขึ้น ในทางกลับกันเมื่อใดก็ตามที่ฉันต้องเขียนนิพจน์ตรรกะใหม่ใน VB.NET ตัวเลือกเริ่มต้นของฉันสำหรับผู้ประกอบการเป็นรูปแบบการลัดวงจรนั่นคือสิ่งที่ฉันเคยใช้จาก C, C ++, C # ฯลฯ และช่วยให้ ฉันจะเขียนสำนวนต่าง ๆ ในรูปแบบที่กระชับยิ่งขึ้น (แม้ว่า ANDALSO ต้องการตัวอักษร 4 ตัวในการพิมพ์)

หากคุณไม่มั่นใจฉันขอแนะนำให้อ่านบทความที่ยอดเยี่ยมของ Joel Spolsky เกี่ยวกับชุดหูฟัง Martianซึ่งเป็นเรื่องเกี่ยวกับสาเหตุที่การตัดสินใจออกแบบช่วงแรก ๆ ในการพัฒนาซอฟต์แวร์ไม่สามารถเพิกถอนได้ง่ายหลังจากส่วนประกอบหรือภาษาหรือ API ที่ถือหุ้นมาถึงฐานผู้ใช้ .


ตกลงสิ่งนี้มีคุณสมบัติเป็นการคุยโวและลิงก์ไปยังชุดหูฟัง Martian ดูเหมือนจะไม่เกี่ยวข้องเลย
jwdonahue

6
@ jwdonahue: ฉันไม่รู้ว่าทำไมคุณถึงคิดว่านี่เป็นคำพูดที่ค่อนข้างตรงกันข้าม และบทความเกี่ยวกับชุดหูฟัง Martian เป็นเหตุให้การตัดสินใจออกแบบในการพัฒนาซอฟต์แวร์หลายทศวรรษก่อนไม่สามารถเพิกถอนได้ง่ายหลังจากส่วนประกอบหรือภาษาหรือ API ในสเตคได้เข้าถึงฐานผู้ใช้ที่มีขนาดที่แน่นอน การเปรียบเทียบนั้นยากที่จะเข้าใจจริงๆเหรอ? VB6 ได้รับความนิยมอย่างมากในอดีตและฉันมั่นใจว่ายังมีอีกหลายแสน บริษัท ในโลกที่มีแอปที่มีความสำคัญต่อการทำงานใน VB6 หรือ VBA
Doc Brown

ฉันไม่เห็นว่าบทความ "headian headian" เป็นอย่างไร สิ่งที่จำเป็นเพื่อให้แน่ใจว่าการทำงานร่วมกันระหว่าง X และ Y (เช่นถั่วและสลักเกลียว) คือการมีมาตรฐานแยกต่างหากสำหรับ X และ Y เช่นนี้น็อตที่แย่ที่สุดจะรองรับสายฟ้าที่แย่กว่าที่ระบุเล็กน้อยและในทางกลับกัน เราควรพยายามเขียนรายละเอียดเพื่อหลีกเลี่ยงการทำน็อตหรือสลักเกลียวโดยไม่จำเป็นต้องมีราคาแพงหรือมีจำนวนเล็กน้อยที่ไม่จำเป็นระหว่างสกรูและน็อต แต่การระบุทั้งสองส่วนแยกกันทำให้มั่นใจว่าการทำงานร่วมกันน่าเชื่อถือ ให้บริการทั้งสองด้าน
supercat

3
@supercat: นี่เป็นเรื่องของ trillions ของถั่ว (หรือบรรทัดของรหัส VB6) ที่มีอยู่แล้วและใช้งานอยู่และตอนนี้สลักเกลียว (หรือในกรณีนี้คอมไพเลอร์ VB) จะถูกแทนที่ด้วยรุ่นใหม่กว่า หากน็อตที่มีอยู่นั้นพอดีกับน็อตที่ไม่ใช่ตัวชี้วัดเท่านั้นมันไม่ประหยัดที่จะทำให้ระบบน็อตตัวใหม่กว่าเท่านั้น
Doc Brown

tl; dr: VB เป็นภาษาของ BASIC ภาษาสืบมาจากปี 1964 และใน BASIC การAndดำเนินการไม่ได้ลัดวงจรไม่ได้อยู่ใน SQL (1974) หรือ FORTRAN (1956) หรือ Pascal (1970)
Ben

3

การประเมินระยะสั้นเมื่อไม่ดีจะเกิดขึ้นเมื่อใด

มันจะแย่ทันทีที่คุณเริ่มพึ่งพาผลข้างเคียงของนิพจน์ที่คุณคาดว่าจะถูกเรียกใช้ในการประเมินผลโดยรวมของบูลีน


1

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

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


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

@ jwdonahue ฉันไม่เข้าใจประเด็นของคุณ ขอโทษ
JimmyJames

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

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

1
ฉันอัปเดตคำตอบพร้อมเครดิตให้คุณ
jwdonahue

0

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

C และ C ++ มีการดำเนินงานระดับบิตและ & | ซึ่งในทางปฏิบัติจะให้การทำงานแบบไม่ลัดวงจร และคอมไพเลอร์มีอิสระที่จะประเมินวิธีที่พวกเขาชอบหากมันไม่ได้สร้างความแตกต่างที่สังเกตได้


@Dupuplicator: ตามที่ระบุไว้ Pascal ไม่ได้กำหนดว่า AND / หรือใช้การประเมินการลัดวงจร นั่นหมายถึง "ไม่รู้"
supercat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.