ประโยชน์ของความโปร่งใสในการอ้างอิงถึงโปรแกรมเมอร์คืออะไร?


18

ในการเขียนโปรแกรมประโยชน์ของความโปร่งใสในการอ้างอิงคืออะไร

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

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

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



2
ดูเพิ่มเติมที่: softwareengineering.stackexchange.com/questions/254304/ …
Giorgio

3
Transparecy อ้างอิงช่วยให้คุณใช้การให้เหตุผลเชิงเหตุผลเพื่อ: 1) พิสูจน์คุณสมบัติของรหัสและ 2) เขียนโปรแกรม มีหนังสือสองสามเล่มเกี่ยวกับ Haskell ที่ผู้เขียนควรเริ่มจากสมการบางอย่างที่คุณต้องการให้ฟังก์ชั่นเป็น fullfil และใช้เหตุผลเพียงแค่สมการที่ทำให้คุณได้รับการใช้งานของฟังก์ชั่นที่กล่าวมา ตอนนี้สามารถนำไปใช้กับการเขียนโปรแกรม "วันต่อวัน" ได้มากน้อยเพียงใดขึ้นอยู่กับบริบท ...
Bakuriu

2
@err คุณชอบโค้ดที่ง่ายต่อการ refactor เพราะคุณรู้หรือไม่ว่าการเรียกฟังก์ชั่นสองครั้งนั้นเหมือนกับการเก็บค่าไว้ในตัวแปรหรือไม่แล้วใช้ตัวแปรดังกล่าวสองครั้ง? คุณจะบอกว่าเป็นประโยชน์สำหรับการเขียนโปรแกรมแบบวันต่อวันของคุณ?
Andres F.

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

คำตอบ:


37

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

ยกตัวอย่างcomputeProductPriceวิธีการ

วิธีบริสุทธิ์จะถามคุณเกี่ยวกับปริมาณสินค้าสกุลเงิน ฯลฯ คุณรู้ว่าเมื่อใดก็ตามที่วิธีการนั้นถูกเรียกด้วยอาร์กิวเมนต์เดียวกันมันจะ มักจะผลิตผลเดียวกัน

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

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

ตัวอย่าง

ลองนึกภาพว่ามีวิธีการในกรอบที่แยกวิเคราะห์ตัวเลข:

decimal math.parse(string t)

มันไม่มีความโปร่งใสในการอ้างอิงเพราะมันขึ้นอยู่กับ:

  • ตัวแปรสภาพแวดล้อมที่ระบุระบบการกำหนดหมายเลขนั่นคือฐาน 10 หรืออย่างอื่น

  • ตัวแปรภายในmathไลบรารีที่ระบุความแม่นยำของตัวเลขในการแยกวิเคราะห์ ดังนั้นมูลค่าของ1แยกสตริงจะให้"12.3456"12.3

  • วัฒนธรรมซึ่งกำหนดรูปแบบที่คาดหวัง ตัวอย่างเช่นกับการfr-FRแยก"12.345"จะให้12345เพราะตัวแยกควรจะ,ไม่.

ลองจินตนาการว่ามันจะง่ายหรือยากแค่ไหนในการทำงานกับวิธีการดังกล่าว ด้วยอินพุตเดียวกันคุณสามารถมีผลลัพธ์ที่แตกต่างอย่างสิ้นเชิงขึ้นอยู่กับช่วงเวลาที่คุณเรียกใช้เมธอดเนื่องจากบางสิ่งบางอย่างเปลี่ยนตัวแปรสภาพแวดล้อมหรือเปลี่ยนวัฒนธรรมหรือตั้งค่าความแม่นยำที่แตกต่างกัน ตัวละครที่ไม่ได้กำหนดไว้ล่วงหน้าของวิธีการนี้จะนำไปสู่ข้อบกพร่องมากขึ้นและฝันร้ายการดีบัก โทรmath.parse("12345")และรับ5349เป็นคำตอบเนื่องจากโค้ดคู่ขนานบางตัวแยกวิเคราะห์ตัวเลขฐานแปดไม่ดี

วิธีการแก้ไขวิธีนี้เสียอย่างเห็นได้ชัด? โดยแนะนำการอ้างอิงที่โปร่งใส กล่าวอีกนัยหนึ่งโดยกำจัดรัฐโลกและย้ายทุกอย่างไปยังพารามิเตอร์ของวิธีการ:

decimal math.parse(string t, base=10, precision=20, culture=cultures.en_us)

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


4
แค่ภาคผนวก: ความโปร่งใสในการอ้างอิงใช้กับนิพจน์ทั้งหมดในภาษาไม่ใช่เพียงฟังก์ชั่น
Gardenhead

3
โปรดทราบว่ามีข้อ จำกัด เกี่ยวกับความโปร่งใสที่คุณสามารถทำได้ การทำให้packet = socket.recv()referential โปร่งใสค่อนข้างเอาชนะจุดของฟังก์ชัน
ทำเครื่องหมาย

1
ควรเป็นวัฒนธรรม = culture.invariant หากคุณไม่ต้องการสร้างซอฟต์แวร์ที่ทำงานได้อย่างถูกต้องในสหรัฐอเมริกาโดยไม่ตั้งใจ
user253751

@immibis: หืมคำถามที่ดี สิ่งที่จะเป็นกฎแยกสำหรับinvariant? ไม่ว่าจะเป็นen_usในกรณีใดเหตุใดรบกวนหรือสอดคล้องกับประเทศอื่นในกรณีนี้ซึ่งหนึ่งและสาเหตุนี้แทนen_usหรือพวกเขามีกฎเฉพาะที่ไม่ตรงกับประเทศใด ๆ อยู่แล้ว ซึ่งจะไร้ประโยชน์ ไม่มี "คำตอบที่แท้จริง" ระหว่าง12,345.67และ12 345,67: "กฎเริ่มต้น" ใด ๆ จะใช้ได้กับบางประเทศและจะไม่ทำงานเพื่อคนอื่น
Arseni Mourzenko

3
@ArseniMourzenko โดยทั่วไปแล้วจะเป็น "ตัวหารร่วมที่ต่ำที่สุด" และคล้ายกับไวยากรณ์ที่ภาษาโปรแกรมส่วนใหญ่ใช้ 12345แยกวิเคราะห์เป็น 12345 12 345หรือ12,345หรือ12.345เป็นข้อผิดพลาด 12.345แยกวิเคราะห์เป็นจำนวนจุดลอยตัวไม่เปลี่ยนแปลงเสมอให้ผล 12.345 ตามการประชุมภาษาการเขียนโปรแกรมของการใช้ เป็นตัวแยกทศนิยม สตริงจะถูกจัดเรียงตามจุดโค้ด Unicode และตรงตามตัวพิมพ์ใหญ่ - เล็ก และอื่น ๆ
user253751

11

คุณมักจะเพิ่มจุดพักเข้ากับจุดในรหัสของคุณและเรียกใช้แอพในเครื่องมือดีบั๊กเพื่อหาว่าเกิดอะไรขึ้น? หากคุณทำเช่นนี้นั่นเป็นเพราะคุณไม่ได้ใช้ Referential transparent (RT) ในการออกแบบของคุณ และดังนั้นจึงต้องเรียกใช้รหัสเพื่อทำงานในสิ่งที่มันทำ

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

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


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

นั่นเป็นจุดที่ดี ฉันมีปัญหาเล็กน้อยกับรหัสที่ง่ายกว่าคือการอ่าน / เหตุผลการโต้แย้งเนื่องจากง่ายต่อการอ่านหรือเหตุผลเป็นลักษณะค่อนข้างคลุมเครือและอัตนัยของรหัส
Eyal Roth

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

9

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

result1 = foo("bar", 12)
// 100 lines of code
result2 = foo("bar", 12)

มีresult1และresult2ที่เหมือนกันหรือแตกต่างกันอย่างไร หากปราศจากความโปร่งใสอ้างอิงคุณไม่มีความคิด คุณต้องอ่านเนื้อความจริงfooเพื่อให้แน่ใจและเป็นไปได้ว่าร่างกายของฟังก์ชันใด ๆfooโทรออกและอื่น ๆ

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

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


1
คุณกล่าวถึงความโปร่งใสในการอ้างอิงช่วยให้คุณสามารถให้เหตุผลเกี่ยวกับผลลัพธ์ของการโทรไปยัง foo () และทราบว่าresult1และresult2เหมือนกันหรือไม่ อีกแง่มุมที่สำคัญคือถ้าfoo("bar", 12)โปร่งใสแล้วคุณไม่ต้องถามตัวเองว่าการโทรนี้สร้างเอฟเฟกต์ที่อื่นหรือไม่ (ตั้งค่าตัวแปรบางอย่าง - ลบไฟล์หรืออะไรก็ตาม)
Giorgio

"Referential Integrity" เพียงอย่างเดียวที่ฉันคุ้นเคยจะเกี่ยวข้องกับฐานข้อมูลเชิงสัมพันธ์
ทำเครื่องหมาย

1
@ Mark มันเป็นคำผิด คาร์ลหมายถึงความโปร่งใสในการอ้างอิงซึ่งเห็นได้ชัดจากคำตอบที่เหลือของเขา
Andres F.

6

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

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

ฟังก์ชั่นขนาดใหญ่เหล่านั้นมีเวทย์มนตร์และฉันกลัวที่จะสัมผัสพวกเขาเพราะพวกเขาสามารถทำลายในวิธีที่งดงาม

ฟังก์ชั่นที่บริสุทธิ์นั้นไม่ได้มีไว้สำหรับฟังก์ชั่นการเขียนโปรแกรมเท่านั้น แต่สำหรับทุกโปรแกรม

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