ฟังก์ชั่นการเขียนโปรแกรมเทียบกับการเขียนโปรแกรมเชิงวัตถุ [ปิด]


784

ฉันได้รับส่วนใหญ่สัมผัสกับการเขียนโปรแกรม OO เพื่อให้ห่างไกลและฉันหวังว่าจะได้เรียนรู้ภาษาที่ใช้งานได้ คำถามของฉันคือ:

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


นี้มีความเกี่ยวข้องprogrammers.stackexchange.com/questions/9730/...
kirill_igum

1
cs.se คำถามที่คล้ายกันนอกจากนี้ยังปิดสิ่งที่เป็นตัวอย่างที่เขียนโปรแกรมการทำงานให้ผลลัพธ์ที่ดีกว่ารูปแบบที่มีความจำเป็น ภูมิปัญญาดั้งเดิมดูเหมือนจะเป็นที่หนึ่งไม่ได้เหนือกว่าที่อื่น ๆ หรือพวกเขาจะไม่เทียบเท่ากับเกณฑ์ง่าย ๆ หรือว่าพวกเขาจะใช้เพื่อวัตถุประสงค์ที่แตกต่างกัน ... การเขียนโปรแกรมการทำงานมีต้นกำเนิดทางวิทยาศาสตร์ / วิชาการมากขึ้นและใช้และเป็นเรื่องธรรมดาในอุตสาหกรรม ดังนั้นคำถามก็ตั้ง "อุตสาหกรรมเทียบกับสถาบันการศึกษา" pov / ความขัดแย้งที่ไม่อาจแก้ไขได้ หนึ่งเตะคลาสสิกที่แสดงให้เห็นว่า OOP sytle ในการเขียนโปรแกรมการทำงานหนังสือ SICP / เอ็มไอที
vzn

" OO ทำให้เข้าใจรหัสได้โดยการห่อหุ้มชิ้นส่วนที่เคลื่อนที่ FP ทำให้เข้าใจรหัสได้โดยการลดส่วนที่เคลื่อนไหว " --Micheal Feathers, 2010
jaco0646

คำตอบ:


1193

คุณจะเลือกการเขียนโปรแกรมการทำงานมากกว่าวัตถุที่มุ่งเน้น?

เมื่อคุณคาดการณ์วิวัฒนาการซอฟต์แวร์ประเภทต่าง ๆ :

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

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

เมื่อวิวัฒนาการไปในทางที่ผิดคุณมีปัญหา:

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

  • การเพิ่มสิ่งใหม่ลงในโปรแกรมการใช้งานอาจจำเป็นต้องแก้ไขนิยามฟังก์ชันจำนวนมากเพื่อเพิ่มเคสใหม่

ปัญหานี้เป็นที่รู้จักกันดีมานานหลายปี ในปี 1998 ฟิล Wadler ขนานนามมันว่า "ปัญหาการแสดงออก" แม้ว่านักวิจัยบางคนคิดว่าปัญหาการแสดงออกสามารถแก้ไขได้ด้วยคุณสมบัติทางภาษาเช่นมิกซ์อิน แต่วิธีการแก้ปัญหาที่ได้รับการยอมรับอย่างกว้างขวางก็ยังไม่เป็นที่นิยม

อะไรคือคำจำกัดความของปัญหาทั่วไปที่การตั้งโปรแกรมการทำงานเป็นตัวเลือกที่ดีกว่า

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


119
มีบางเซนที่จริงจังอยู่เบื้องหลังคำตอบนี้ ฉันคิดว่ามันช่วยเพิ่มความจริงที่ว่ารูปแบบการออกแบบ OOP บางอย่าง (ผู้เข้าชม) จริง ๆ แล้วแฮ็กซึ่งพยายามที่จะเอาชนะปัญหาของการเพิ่มการดำเนินงานใหม่
Jacobs Data Solutions

54
ใน JavaScript คุณสามารถมีทุกสิ่ง
Erik Reppen

61
@ErikReppen ที่จุดคำถามเกิดขึ้นเมื่อใดที่คุณเลือกที่จะใช้คุณสมบัติการทำงานและเมื่อใดที่คุณเลือกที่จะใช้คุณสมบัติเชิงวัตถุ
Norman Ramsey

7
@NormanRamsey มันไม่ใช่เรื่องแปลกอะไรเลยที่จะรวมมันใน JS และฟังก์ชั่นชั้นหนึ่งจะเชื่อมโยงกับคุณสมบัติที่เกี่ยวข้องกับ JS OOP มากมาย การเรียงลำดับอาร์เรย์ของ JS ใช้ฟังก์ชั่นเป็น arg ซึ่งสามารถสร้างโครงสร้างข้อมูลที่มีประสิทธิภาพได้ Closures + ฟังก์ชั่นส่งผ่านถูกใช้เพื่อให้วัตถุ jquery พูดเบามากหน่วยความจำเนื่องจากวิธีการส่วนใหญ่เป็นเพียงการอ้างอิง อื่น ๆ ...
Erik Reppen

9
@NormanRamsey: คำตอบที่ดีมากตามแนวของ SICP ตามการจำแนกประเภทนี้การเขียนโปรแกรมเชิงฟังก์ชันและขั้นตอนจะถูกจัดกลุ่มเข้าด้วยกันทางด้านตรงข้ามของการเขียนโปรแกรมเชิงวัตถุ สิ่งนี้สามารถอธิบายความเจริญของ OOP ในช่วงปลายปี 1980-ies ต้นปี 1990-ies: เมื่อ GUIs กลายเป็นกระแสหลัก OOP ที่พิสูจน์แล้วว่าเป็นแนวทางที่ดีสำหรับการสร้างแบบจำลองพวกเขาเพราะโดยปกติคุณมีชุดปฏิบัติการคงที่ (ทาสีเปิดปิดปรับขนาด) และวิดเจ็ตจำนวนมากขึ้นเรื่อย ๆ แน่นอนว่านี่ไม่ได้หมายความว่า OOP นั้นดีกว่าขั้นตอนสำหรับแอปพลิเคชันใด ๆ ตามที่คุณแสดง
Giorgio

177

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

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

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

ภาษาสมัยใหม่หลายภาษาเป็นกระบวนทัศน์ที่หลากหลาย

อ่านที่แนะนำ

ในขณะที่ฉันอยู่ในเรือลำเดียวกัน (พื้นหลังของ OOP, การเรียนรู้ FP) ฉันขอแนะนำให้คุณอ่านบางอย่างที่ฉันชื่นชมจริงๆ:


8
@duffymo: ความคิดเห็นของคุณในแบบที่คุณเป็นส่วนใหญ่ไม่มีจุดหมาย ไม่มีใครต้องการเปรียบเทียบภาษาเครื่องเสมือนหรือแพลตฟอร์มขอบคุณ
Bruno Reis

6
@Bruno - การตอบสนองต่อ "พลังของ. NET" ผ่อนคลาย.
duffymo

6
ตลก, ฉันไม่เห็นคุณกำลังหลบซ่อน Dykam เกี่ยวกับความคิดเห็นที่ไร้จุดหมายของเขา คุณได้รับการเสนอชื่อเป็นผู้ดำเนินรายการในขณะที่ฉันไม่ได้มองหาหรือไม่? ไม่มีใครลุกโชนที่นี่ยกเว้นคุณ ฉันจะพูดอีกครั้ง - ผ่อนคลาย
duffymo

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

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

31

ข้อเสนอการเขียนโปรแกรมเชิงวัตถุ:

  1. การห่อหุ้ม
    • การกลายพันธุ์ควบคุมของรัฐภายใน
    • จำกัด การมีเพศสัมพันธ์กับการเป็นตัวแทนภายใน
  2. ชนิดย่อยที่อนุญาต:
    • การทดแทนประเภทที่เข้ากันได้ (polymorphism)
    • วิธีการแบ่งปันการใช้งานระหว่างชั้นเรียนอย่างหยาบ

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

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

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


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

25
  1. หากคุณอยู่ในสภาพแวดล้อมที่พร้อมกันอย่างมากการเขียนโปรแกรมที่ใช้งานได้จริงนั้นมีประโยชน์ การขาดสถานะที่ไม่แน่นอนทำให้เกิดภาวะพร้อมกันเล็กน้อย ดู Erlang

  2. ในภาษาหลายรูปแบบคุณอาจต้องการสร้างแบบจำลองบางสิ่งบางอย่างทำงานได้หากการดำรงอยู่ของรัฐที่ไม่แน่นอนจะต้องมีรายละเอียดการใช้งานและทำให้ FP เป็นแบบจำลองที่ดีสำหรับโดเมนปัญหา ตัวอย่างเช่นดูรายการความเข้าใจใน Python หรือstd.rangeในภาษาการเขียนโปรแกรม D เหล่านี้เป็นแรงบันดาลใจจากการเขียนโปรแกรมการทำงาน

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