การจัดการกับปัญหาสถานะในการเขียนโปรแกรมการทำงาน


18

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


4
ขั้นตอนแรกน่าจะตระหนักว่าปัญหาไม่ได้เกิดขึ้นโดยธรรมชาติ
Telastyn

4
ปัญหาบางอย่างเกิดขึ้นโดยธรรมชาติเช่นเขียนลงในฐานข้อมูลหรือวาด gui จากตัวอย่างการจำลองอนุภาคของฉันสิ่งที่จะเป็นทางเลือกในการคิดเกี่ยวกับมัน การคืนอนุภาคใหม่ทุกครั้งที่มีการอัปเดตตำแหน่งเพื่อหลีกเลี่ยงสภาวะที่ดูเหมือนจะไม่มีประสิทธิภาพสำหรับฉันและไม่ใช่แบบจำลองที่ดีของโลกแห่งความจริง
Andrew Martin

4
อาจจะยกเว้นเช่นฐานข้อมูลปัญหาเหล่านี้จะไม่ stateful โดยเนื้อแท้ ตัวอย่างเช่นสำหรับการเขียนโปรแกรม GUI คุณกำลังใช้สถานะที่ไม่แน่นอนว่าเป็นรูปแบบเวลาที่ไม่ดี ฟังก์ชั่นการเขียนโปรแกรมปฏิกิริยาตอบสนองช่วยให้คุณสร้างแบบจำลองเวลาได้อย่างชัดเจนโดยไม่ต้องพึ่งพาสถานะโดยให้กระแสของเหตุการณ์ที่คุณสามารถรวมได้
Tikhon Jelvis

1
มีวิธีแก้ปัญหาที่ง่ายกว่า: เมื่อคุณพบปัญหาที่ไม่ได้จำลองแบบง่าย ๆ ด้วยเทคนิค FP อย่าใช้การเขียนโปรแกรมเชิงฟังก์ชันเพื่อแก้ปัญหา เครื่องมือที่เหมาะสมสำหรับงานและสิ่งที่ ...
เมสันล้อ

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

คำตอบ:


20

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

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


5
+1 มันก็โอเคที่จะมีสถานะเป็น FP ไม่ใช่แค่สถานะไม่แน่นอน
jhewlett

1
ขอบคุณสำหรับข้อมูลเชิงลึกนี้ ความกังวลของฉันเกี่ยวกับความไร้ประสิทธิภาพถูกขัดขวางโดย @logc; รายละเอียดทางเทคนิคของวิธีการเปลี่ยนสถานะเป็นปัญหาการใช้งานในระดับต่ำที่ภาษาตัวเองควรจะแก้ปัญหา ฉันดู Rich Hickey อธิบายว่าเขาทำอย่างนี้กับ Clojure ในวิดีโอได้อย่างไร
Andrew Martin

1
@jhewlett: เพื่อให้แม่นยำยิ่งขึ้น: FP มีสถานะแม้รัฐจะไม่แน่นอน แต่พวกเขาไม่ได้เป็นตัวแทนโดยใช้ตัวแปรที่ไม่แน่นอน
Giorgio

9

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

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

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

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

จากทั้งหมดที่กล่าวถึงแม้ใน Haskell จะมีmonad stateที่ช่วยในการสร้างแบบจำลองสถานการณ์ที่ "การรักษาสถานะ" นั้นเป็นทางออกที่ใช้งานง่ายกว่าสำหรับปัญหา แต่โปรดสังเกตเห็นปัญหาบางอย่างที่คุณพบ " stateful โดยเนื้อแท้เช่นการเขียนไปยังฐานข้อมูล " มีการแก้ปัญหาไม่เปลี่ยนรูปเหมือน Datomic สิ่งนี้อาจทำให้คุณประหลาดใจจนกระทั่งคุณเข้าใจว่ามันเป็นแนวคิด


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

@Doval: "แม้ว่าคอมไพเลอร์สามารถทำได้ แต่เป็นไปได้เฉพาะในกรณีที่คุณไม่ยึดติดกับรายการรุ่นก่อนหน้า": นี่เป็นการเตือนฉันถึงประเภทที่ไม่ซ้ำใน Clean
Giorgio

4

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

Rich Hickey ให้แสงสว่างกับความคิดเหล่านี้:

มีการพูดคุยอื่นแต่สิ่งนี้ควรส่งคุณไปในทิศทางที่ถูกต้อง


3

เมื่อเขียนแอปพลิเคชันขนาดใหญ่และใหญ่ปานกลางฉันมักพบว่ามีประโยชน์ในการแยกความแตกต่างระหว่างส่วนต่าง ๆ ของแอปพลิเคชันที่เป็นของรัฐ

โครงสร้างคลาส / ข้อมูลในส่วน stateful เก็บข้อมูลของแอปพลิเคชันและฟังก์ชั่นในส่วนนี้ทำงานด้วยความรู้โดยนัยของข้อมูลของแอปพลิเคชัน

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

ส่วนที่ยากที่สุดคือการหาว่าคลาส / ฟังก์ชันใดที่จะใส่ในส่วนไร้สัญชาติและคลาส / ฟังก์ชันใดที่จะใส่ในส่วน stateful และมีวินัยในการวางไว้ในไฟล์ / ไลบรารีแยกต่างหาก


คำถามนี้จะตอบคำถามได้อย่างไร (ไม่ใช่การลงคะแนน)
kravemir

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