การเขียนโปรแกรมที่ไม่เปลี่ยนรูปแบบและ Object Oriented


43

ในภาษา OOP ส่วนใหญ่โดยทั่วไปวัตถุจะเปลี่ยนแปลงไม่ได้ด้วยชุดข้อยกเว้นที่ จำกัด (เช่น tuples และสตริงใน python) ในภาษาที่ใช้งานได้ส่วนใหญ่ข้อมูลจะไม่เปลี่ยนรูป

วัตถุที่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนรูปแบบนำรายชื่อทั้งข้อดีและข้อเสียมาเอง

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

คำถามของฉันคือไม่สมบูรณ์ (! sic) เปลี่ยนไม่ -ie วัตถุที่ไม่สามารถกลายพันธุ์เมื่อมันได้รับ created- ทำให้รู้สึกใด ๆ ในบริบท OOP แล้ว?

มีการออกแบบหรือการนำโมเดลดังกล่าวไปใช้หรือไม่?

โดยพื้นฐานแล้วความไม่สามารถเปลี่ยนแปลงได้ (สมบูรณ์) และ OOP ตรงกันข้ามหรือมุมฉากหรือไม่?

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


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

4
ความไม่แน่นอนไม่ได้เป็นคุณสมบัติของภาษา OOP เช่น C # และ Java และไม่สามารถเปลี่ยนแปลงได้ คุณระบุความไม่แน่นอนหรือการเปลี่ยนแปลงไม่ได้โดยวิธีที่คุณเขียนชั้นเรียน
Robert Harvey

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

2
@MichaelT คำถามไม่ได้เกี่ยวกับการทำให้สิ่งต่าง ๆ ไม่แน่นอนมันเกี่ยวกับการทำให้ทุกสิ่งไม่เปลี่ยนรูป

คำตอบ:


43

OOP และการเปลี่ยนแปลงไม่ได้เกือบจะเป็นมุมฉากซึ่งกันและกัน อย่างไรก็ตามการเขียนโปรแกรมที่จำเป็นและไม่เปลี่ยนรูปไม่ได้

OOP สามารถสรุปได้ด้วยคุณสมบัติหลักสองประการ:

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

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

การห่อหุ้มทำให้รู้สึกน้อยลงโดยไม่ต้องมีความไม่แน่นอน (ไม่มีสถานะภายในที่อาจเสียหายจากการแทรกแซงจากภายนอก) แต่ก็ยังมีแนวโน้มที่จะทำให้ abstractions ง่ายขึ้นแม้ว่าทุกอย่างจะไม่เปลี่ยนรูป

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

ตอนนี้มันเกิดขึ้นแล้วที่ OOP มีการเชื่อมโยงกับการเขียนโปรแกรมที่จำเป็นในอดีต (Simula ขึ้นอยู่กับ Algol) และภาษา OOP หลักทั้งหมดมีรากที่จำเป็น (C ++, Java, C #, …ทั้งหมดถูกฝังใน C) สิ่งนี้ไม่ได้หมายความว่า OOP เองจะมีความจำเป็นหรือไม่แน่นอนซึ่งหมายความว่าการใช้ OOP โดยภาษาเหล่านี้จะช่วยให้เกิดความไม่แน่นอน


2
ขอบคุณมากโดยเฉพาะคำจำกัดความของคุณสมบัติหลักสองประการ
Hyperboreus

Dynamic Dispatch ไม่ใช่คุณสมบัติหลักของ OOP ไม่มี Encapsulation (ตามที่คุณยอมรับ)
หยุดทำร้ายโมนิก้า

5
@OrangeDog ใช่ไม่มีคำจำกัดความที่เป็นที่ยอมรับในระดับสากลของ OOP แต่ฉันต้องการคำนิยามเพื่อทำงานกับ ดังนั้นฉันจึงเลือกสิ่งที่ใกล้เคียงกับความจริงที่สุดเท่าที่จะทำได้โดยไม่ต้องเขียนวิทยานิพนธ์ทั้งหมดเกี่ยวกับเรื่องนี้ อย่างไรก็ตามฉันคำนึงถึงการจัดส่งแบบไดนามิกเป็นคุณลักษณะที่แตกต่างที่สำคัญเดียวของ OOP จากกระบวนทัศน์อื่น ๆ บางสิ่งที่ดูเหมือน OOP แต่ที่จริงแล้วการโทรทั้งหมดได้รับการแก้ไขแบบสแตติกเป็นเพียงการเขียนโปรแกรมแบบโมดูลาร์ที่มี ad-hoc polymorphism วัตถุเป็นคู่ของวิธีการและข้อมูลและเป็นเช่นเทียบเท่ากับการปิด
อมร

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

3
@CodeYogi การซ่อนข้อมูลเป็นประเภทที่พบมากที่สุดของการห่อหุ้ม อย่างไรก็ตามวิธีการจัดเก็บข้อมูลภายในโดยวัตถุไม่ได้เป็นเพียงรายละเอียดการใช้งานที่ควรซ่อนอยู่ สิ่งสำคัญเท่าเทียมกันคือการซ่อนวิธีการใช้อินเทอร์เฟซสาธารณะเช่นว่าฉันใช้วิธีการช่วยเหลือใด ๆ วิธีการช่วยเหลือเช่นนี้ควรเป็นแบบส่วนตัวโดยทั่วไปแล้วการพูด ดังนั้นเพื่อสรุป: การห่อหุ้มเป็นหลักการในขณะที่การซ่อนข้อมูลเป็นเทคนิคการห่อหุ้ม
amon

25

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

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

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

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


17

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

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

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

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


ขอขอบคุณ. คุณช่วยอธิบายรายละเอียดเล็กน้อยในย่อหน้าสุดท้ายของคุณ ("ชัดเจน" อาจเป็นเรื่องเล็กน้อย)
Hyperboreus

ทำไปแล้ว ....
Robert Harvey

1
@Hyperboreus มีหลายวิธีในการบรรลุความหลากหลาย การพิมพ์ย่อยด้วยการจัดส่งแบบไดนามิกแบบคงที่ความหลากหลาย (aka. ฟังก์ชั่นการบรรทุกเกินพิกัด) และความหลากหลายแบบพาราเมตริก ภาษา OOP สมัยใหม่รวมเอาทั้งสามวิธีเข้าด้วยกันในขณะที่ Haskell ส่วนใหญ่อาศัยตัวแปรหลากหลายและ ad-hoc polymorphism
amon

3
@RobertHarvey คุณบอกว่าคุณต้องการความไม่แน่นอนเนื่องจากคุณต้องวนซ้ำ (มิฉะนั้นคุณต้องใช้การเรียกซ้ำ) ก่อนที่ฉันจะเริ่มใช้ Haskell เมื่อสองปีก่อนฉันคิดว่าฉันต้องการตัวแปรที่ไม่แน่นอนเช่นกัน ฉันแค่บอกว่ามีวิธีอื่นในการ "วนรอบ" (แผนที่พับตัวกรองและอื่น ๆ ) เมื่อคุณวนลูปออกจากโต๊ะแล้วทำไมคุณถึงต้องการตัวแปรที่ไม่แน่นอน
cimmanon

1
@ RobertHarvey แต่นี่เป็นจุดที่ภาษาการเขียนโปรแกรม: สิ่งที่คุณสัมผัสและไม่ใช่สิ่งที่เกิดขึ้นภายใต้ประทุน หลังคือความรับผิดชอบของคอมไพเลอร์หรือล่ามไม่ใช่ของผู้พัฒนาแอปพลิเคชัน มิฉะนั้นกลับไปที่แอสเซมเบลอร์
Hyperboreus

5

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

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

  1. ไม่มีการอ้างอิงถึงวัตถุใด ๆ ที่จะได้สัมผัสกับสิ่งใด ๆ ที่อาจเปลี่ยนแปลงสถานะที่ห่อหุ้มอยู่ในนั้น

  2. เจ้าของอย่างน้อยหนึ่งการอ้างอิงไปยังวัตถุรู้การใช้งานทั้งหมดที่การอ้างอิงที่ยังหลงเหลืออยู่อาจได้รับการใส่

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

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

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


4

ใน c # บางประเภทไม่เปลี่ยนรูปเหมือนสตริง

ดูเหมือนว่าจะเป็นการชี้ให้เห็นว่าทางเลือกได้รับการพิจารณาอย่างมาก

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

ฉันได้ทำการทดลองกับผู้สร้างโปรไฟล์และการใช้ชนิดที่ไม่เปลี่ยนรูปนั้นเป็นความต้องการของ CPU และ RAM มากกว่า

นอกจากนี้ยังใช้งานง่ายหากคุณพิจารณาว่าสำหรับการแก้ไขตัวอักษรเพียงหนึ่งตัวในสตริง 4,000 ตัวอักษรคุณจะต้องคัดลอกอักขระทุกตัวในพื้นที่อื่นของ RAM


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

@delnan ฉันยังคิดว่าย่อหน้าสุดท้ายของคำตอบนั้นเกี่ยวกับรายละเอียดเกี่ยวกับการใช้งานมากกว่าความไม่แน่นอนเกี่ยวกับ (im)
Hyperboreus

@Hyperboreus: คุณคิดว่าฉันควรลบส่วนนั้นหรือไม่? แต่สตริงสามารถเปลี่ยนแปลงได้อย่างไรถ้ามันไม่เปลี่ยนรูป? ฉันหมายถึง .. ในความคิดของฉัน แต่แน่นอนว่าฉันผิดอาจเป็นเหตุผลหลักว่าทำไมวัตถุไม่เปลี่ยนรูป
Revious

1
@Revious ไม่ได้หมายความว่า ทิ้งไว้จึงทำให้เกิดการสนทนาและความคิดเห็นที่น่าสนใจและมุมมองที่น่าสนใจยิ่งขึ้น
Hyperboreus

1
@ ร้ายแรงใช่การอ่านจะช้าลงแม้ว่าจะไม่ช้าเท่ากับการเปลี่ยนstring(การแสดงดั้งเดิม) สตริง "" (ในการเป็นตัวแทนที่ฉันกำลังพูดถึง) หลังจากการปรับเปลี่ยน 1,000 ครั้งจะเหมือนกับสตริงที่สร้างขึ้นใหม่ (เนื้อหาโมดูโล) ไม่มีโครงสร้างข้อมูลถาวรที่เป็นประโยชน์หรือใช้กันอย่างแพร่หลายในด้านคุณภาพหลังจากการดำเนินการ X การกระจายตัวของหน่วยความจำไม่ใช่ปัญหาร้ายแรง (คุณมีการจัดสรรจำนวนมากใช่ แต่การกระจายตัวของหน่วยความจำเป็นปัญหาที่ไม่เกิดขึ้นในนักสะสมขยะสมัยใหม่)

0

การเปลี่ยนไม่ได้อย่างสมบูรณ์ของทุกสิ่งนั้นไม่สมเหตุสมผลใน OOP หรือกระบวนทัศน์อื่น ๆ ส่วนใหญ่สำหรับเรื่องนั้นด้วยเหตุผลสำคัญอย่างหนึ่ง:

ทุกโปรแกรมที่มีประโยชน์มีผลข้างเคียง

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

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

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


4
ฉันไม่เห็นว่าคำตอบของคุณเกี่ยวข้องกับคำถามอย่างไรเนื่องจากฉันไม่ได้พูดภาษาที่ใช้งานได้จริง ยกตัวอย่างเช่น: ข้อมูลที่ไม่เปลี่ยนรูปแบบไม่มีการมอบหมายการทำลายล้างไม่มีความสับสนเกี่ยวกับผลข้างเคียง นอกจากนี้คุณยังมีสถานะในภาษาที่ใช้งานได้เฉพาะที่สถานะ "ไหล" ผ่านฟังก์ชั่นซึ่งแตกต่างจากฟังก์ชั่นการใช้งานในรัฐ การเปลี่ยนแปลงสถานะ แต่จะไม่เปลี่ยนแปลงในสถานที่ แต่สถานะในอนาคตจะแทนที่สถานะปัจจุบัน Immutability ไม่ได้เกี่ยวกับว่าบัฟเฟอร์หน่วยความจำมีการเปลี่ยนแปลงหรือไม่มันเป็นเรื่องเกี่ยวกับการกลายพันธุ์เหล่านี้สามารถมองเห็นได้จากภายนอก
Hyperboreus

และรัฐในอนาคตแทนที่หนึ่งในปัจจุบันวิธีการที่ว่า? ในโปรแกรม OO สถานะนั้นเป็นคุณสมบัติของวัตถุบางแห่ง การเปลี่ยนสถานะต้องเปลี่ยนวัตถุ (หรือแทนที่ด้วยวัตถุอื่นซึ่งต้องการการเปลี่ยนแปลงวัตถุที่อ้างถึง (หรือแทนที่ด้วยวัตถุอื่นซึ่ง ... เอ๊ะ. คุณได้รับคะแนน) คุณอาจพบกับการแฮ็ค monadic บางประเภทซึ่งทุกการกระทำจะจบลงด้วยการสร้างแอปพลิเคชั่นใหม่ทั้งหมด ... แต่ถึงกระนั้นก็ต้องมีการบันทึกสถานะปัจจุบันของโปรแกรมไว้ที่ใดที่หนึ่ง
cHao

7
-1 สิ่งนี้ไม่ถูกต้อง คุณกำลังสับสนผลข้างเคียงกับการกลายพันธุ์และในขณะที่พวกเขามักจะได้รับการปฏิบัติเหมือนกันโดยภาษาที่ใช้งานได้พวกมันต่างกัน ทุกโปรแกรมที่มีประโยชน์มีผลข้างเคียง ไม่ใช่ทุกโปรแกรมที่มีประโยชน์มีการกลายพันธุ์
Michael Shaw

@Michael: เมื่อพูดถึง OOP การกลายพันธุ์และผลข้างเคียงนั้นพันกันจนไม่สามารถแยกออกจากกันได้ หากคุณไม่มีการกลายพันธุ์คุณจะไม่สามารถมีผลข้างเคียงโดยไม่มีการแฮ็กจำนวนมาก
cHao


-2

ฉันคิดว่ามันขึ้นอยู่กับว่าคำจำกัดความของ OOP ของคุณนั้นใช้รูปแบบการส่งข้อความหรือไม่

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

var brandNewVariable = pureFunction(foo);

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

sameOldObject.changeMe(foo);

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

var brandNewVariable = nonMutatingObject.askMe(foo);

แต่มันเป็นไปไม่ได้ที่จะผสมผสานข้อความที่ผ่านสไตล์และวัตถุที่ไม่เปลี่ยนรูป

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