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


237

อะไรคือความแตกต่างระหว่างกระบวนทัศน์การเขียนโปรแกรมเหล่านี้และพวกเขาเหมาะสมกับปัญหาเฉพาะหรือการใช้ประโยชน์จากกรณีอื่น ๆ ดีกว่ากันหรือไม่?

ตัวอย่างสถาปัตยกรรมชื่นชม!


นี่ไม่ใช่คำตอบเต็มรูปแบบ แต่ฉันเขียนนิดหน่อยว่าสไตล์ "การทำงาน" มีผลต่อ / ตรงกันข้าม "OO" อย่างไร (ในบริบทของ F #) ที่นี่: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511 รายการ
Brian

คุณอาจลองอ่านสิ่งนี้! มีตัวอย่างมากมายของเวลาที่จะใช้เป็นที่มดสิ่งที่เป็นความแตกต่างหลักข้อดี / ข้อเสีย ฯลฯ
Nikita Ignatov


1
ดูเพิ่มเติมที่: stackoverflow.com/questions/1530868
dreftymac

Uncle Bob ได้ทวีตเกี่ยวกับสิ่งนี้ และที่นี่ด้วย
jaco0646

คำตอบ:


129

พวกเขาทั้งหมดเป็นคนดีในแบบของพวกเขา - พวกเขาแตกต่างกันเพียงวิธีการในปัญหาเดียวกัน

ในรูปแบบขั้นตอนอย่างหมดจดข้อมูลมีแนวโน้มที่จะแยกจากฟังก์ชันที่ใช้งาน

ในรูปแบบวัตถุที่มุ่งเน้นข้อมูลมีแนวโน้มที่จะดำเนินการกับคอลเลกชันของฟังก์ชั่น

ในรูปแบบการทำงานข้อมูลและฟังก์ชั่นมีแนวโน้มที่จะมีความเหมือนกันมากขึ้น (เช่นใน Lisp และ Scheme) ในขณะที่ให้ความยืดหยุ่นมากขึ้นในแง่ของวิธีการใช้ฟังก์ชั่นจริง ๆ อัลกอริทึมมีแนวโน้มที่จะถูกกำหนดในแง่ของการเรียกซ้ำและองค์ประกอบมากกว่าวนซ้ำและซ้ำ

แน่นอนว่าภาษานั้นมีอิทธิพลต่อรูปแบบที่ต้องการเท่านั้น แม้ในภาษาบริสุทธิ์ที่ใช้งานได้เช่น Haskell คุณสามารถเขียนในรูปแบบขั้นตอน (แม้ว่าจะเป็นกำลังใจอย่างมาก) และแม้แต่ในภาษาขั้นตอนเช่น C คุณสามารถเขียนโปรแกรมในลักษณะเชิงวัตถุ (เช่นใน GTK + และ EFL API)

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

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


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

1
@ TechZilla: ฉันเห็นด้วยกับถ้อยคำของฉันไม่ดี แต่สิ่งที่ฉันหมายถึงคือไม่มีรายการคุณสมบัติที่คุณสามารถชี้และพูดภาษา X ได้ดีกว่า Y โดยไม่ต้องมีคุณสมบัติภาษา X เหมาะกับการเขียนอัลกอริทึม U และภาษา Y อาจเหมาะกว่าสำหรับการเขียนอัลกอริทึม V ในขณะที่ทั้งสองสามารถนำไปใช้ได้อย่างง่ายดายในภาษาใดภาษาหนึ่ง
greyfade

2
ความแตกต่างระหว่างขั้นตอนและการทำงานไม่ชัดเจนสำหรับฉัน ฉันกำลังเรียนรู้ Scheme / Rackett ที่วิทยาลัย แต่ฉันไม่เห็นความแตกต่างอย่างมากระหว่างมันกับขั้นตอน C หรือ PHP คุณสามารถยกตัวอย่างได้หรือไม่
Leonel

7
@ Leonel: ความแตกต่างที่ใหญ่ที่สุดที่คนส่วนใหญ่จะกล่าวถึงก็คือในภาษาขั้นตอนคุณอาจใช้ for for loop แต่ภาษาที่ใช้งานได้ไม่มีอะไรแบบนั้น - แทนคุณใช้การเรียกซ้ำไปยังฟังก์ชันเพื่อทำงานเดียวกัน ฟังก์ชั่นภาษายังทำให้ฟังก์ชั่นวัตถุชั้นหนึ่ง - คุณสามารถส่งผ่านพวกเขาไปรอบ ๆ เหมือนที่คุณต้องการตัวเลข - แต่คุณไม่สามารถทำได้ใน C (และการสนับสนุนของ PHP สำหรับมันเสีย)
greyfade

2
@tastro: เมื่อกระบวนทัศน์หนึ่งทำให้รู้สึกมากกว่าอีก นั่นคือทั้งหมดที่จริง บางครั้งมันสมเหตุสมผลมากกว่าที่จะวางโมเดลโค้ดของคุณเป็นองค์ประกอบของฟังก์ชั่นและบางครั้งมันก็สมเหตุสมผลที่จะทำโมเดลข้อมูลของคุณเป็นวัตถุ มีหลายวิธีในการแสดงอัลกอริทึมและโครงสร้างข้อมูล OOP และหน้าที่การใช้งานนั้นเป็นสองสิ่งนั้น
greyfade

25

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

ตัวอย่างเช่นหากคุณสร้างวิดีโอเกมมีตัวอย่างโค้ดและ SDK ที่ดีกว่าใน C ++ ดังนั้นคุณน่าจะดีกว่า สำหรับเว็บแอปพลิเคชั่นขนาดเล็กมีกรอบ Python, PHP และ Ruby ที่ยอดเยี่ยมที่จะทำให้คุณทำงานได้อย่างรวดเร็ว Java เป็นตัวเลือกที่ยอดเยี่ยมสำหรับโครงการขนาดใหญ่เนื่องจากการตรวจสอบเวลาคอมไพล์และไลบรารีและแพลตฟอร์มขององค์กร

มันเคยเป็นกรณีที่ห้องสมุดมาตรฐานสำหรับภาษาที่แตกต่างกันมีขนาดค่อนข้างเล็กและลอกเลียนแบบได้ง่าย - C, C ++, Assembler, ML, LISP และอื่น ๆ มาพร้อมกับพื้นฐาน แต่มีแนวโน้มที่จะไก่ออกมา เช่นการสื่อสารเครือข่ายการเข้ารหัสกราฟิกรูปแบบไฟล์ข้อมูล (รวมถึง XML) แม้แต่โครงสร้างข้อมูลพื้นฐานเช่นต้นไม้ที่สมดุลและแฮชเทเบิลก็หมดไป!

ภาษาสมัยใหม่เช่น Python, PHP, Ruby และ Java มาพร้อมกับไลบรารีมาตรฐานที่ดีกว่าและมีไลบรารี่ของบุคคลที่สามมากมายที่คุณสามารถใช้งานได้อย่างง่ายดายขอบคุณส่วนมากในการนำเนมสเปซมาใช้ และการรวบรวมขยะเพื่อสร้างมาตรฐานโครงร่างการจัดการหน่วยความจำของไลบรารี


5
Python, ruby, ... ไม่มีไลบรารี่ "มาตรฐาน" อย่าง C หรือ LISP เนื่องจากเป็นภาษาที่ใช้งานเพียงครั้งเดียว Python เป็นสิ่งที่ Guido กล่าวว่าไม่มีมาตรฐาน การใช้งาน C หรือ LISP (หรืออะไรก็ตาม) โดยเฉพาะในปัจจุบันนั้นมาพร้อมกับชุดของไลบรารีที่มีขนาดใหญ่กว่ามาตรฐาน
Dan Andreatta

8
คำถามเกี่ยวกับความแตกต่างระหว่างการเขียนโปรแกรมเชิงวัตถุหน้าที่และขั้นตอนการโปรแกรม ในขณะที่ภาษาที่กล่าวถึงในคำตอบเหล่านี้ให้ยืมตัวเองกับหนึ่งในวิธีการเหล่านี้คำตอบไม่ได้กล่าวถึงแนวคิดใด ๆ เหล่านี้ ... ไม่ว่า "ห้องสมุดที่มีอยู่ [... ] [คนดี] กระบวนทัศน์", ที่ไม่ตอบคำถามในมือดังนั้นจึงให้ลองถามคำถามที่ถูกต้องสมบูรณ์
rinogo

1
ircmaxell rant ที่เกี่ยวข้อง: blog.ircmaxell.com/2012/07/oop-vs-procedural-code.html
rinogo

20

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

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

ในขณะที่อยู่ในภาษาขั้นตอนเช่น C วิธีเดียวที่คุณสามารถส่งผ่านฟังก์ชั่นได้คือการใช้พอยน์เตอร์ของฟังก์ชั่น

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

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

ใน Python คุณไม่มีข้อ จำกัด นี้


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

ใช่ฉันเดาว่าไม่เกิดร่วมกันเป็นคำที่ดีกว่าสำหรับสิ่งนั้น! ขอบคุณ
hasen

14

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

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


17
ล่อลวงให้ downvote เพื่อสานต่อความเข้าใจผิดว่า "Object = GUI widget" แต่ฉันจะงด OOP ใช้งานได้ดีสำหรับการแสดงแนวคิดแบบนามธรรมเช่น "UserAccount" หรือ "PendingSale" เช่นเดียวกับองค์ประกอบอินเทอร์เฟซที่มองเห็นได้เช่น "หน้าต่าง" และ "ปุ่ม"
Dave Sherohman

5
ฉันเขียนว่าหน้าต่างสามารถเป็นวัตถุได้ คุณจะสรุปได้อย่างไรว่าวัตถุทุกชิ้นเป็นหน้าต่างจากที่นั่น มันเป็นเพียงตัวอย่าง แน่นอนว่า OOP สามารถนำไปใช้เป็นแบบจำลองเอนทิตีนามธรรมและความสัมพันธ์ของพวกเขาได้ อย่างไรก็ตามขอขอบคุณที่ไม่ downvoting ฉันไม่ได้มีคะแนนมากเลย: D
panschk

6
-1 OOP ไม่มีส่วนเกี่ยวข้องกับ GUI ของ วิธีที่ดีที่สุดสำหรับการออกแบบ guis คือการใช้ไฟล์ข้อความภายนอก (เช่น HTML) ในขณะที่สิ่งต่าง ๆ เช่นการประมวลผลสตริงจะทำได้ดีกว่ากับวัตถุจริงๆ (คิดเกี่ยวกับสายอักขระใน C) !!
hasen

1
ฉันไม่รู้ฉันอาจจะคุ้นเคยกับการเขียนโปรแกรมกับวัตถุต่างๆ แต่คุณจะทำสิ่งที่โต้ตอบได้อย่างไรเช่นการเปลี่ยนค่าใน TextBox X เมื่อค่าของ TextBox Y ถูกเปลี่ยนแปลงโดยไม่ใช้วัตถุ? เอาล่ะคุณก็สามารถใช้ vars ทั่วโลกสำหรับทุกอย่าง ...
panschk

1
การประมวลผลสตริงทำได้อย่างไม่น่าเชื่อใน Perl (100x ดีกว่าใน Java, C ++ หรือ C #) แต่ฟังก์ชั่นสตริงของภาษานั้นไม่ได้มุ่งเน้นวัตถุ การจัดการสตริงของ C นั้นแย่มาก แต่ C ไม่ใช่ภาษาขั้นตอนเดียว (หรือดีที่สุด)
Joe Pineda

6

ในการตอบคำถามของคุณเราจำเป็นต้องมีองค์ประกอบสองประการ:

  1. การทำความเข้าใจกับลักษณะของรูปแบบ / รูปแบบสถาปัตยกรรมที่แตกต่างกัน
  2. ความเข้าใจในลักษณะของกระบวนทัศน์การเขียนโปรแกรมที่แตกต่างกัน

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

ในระยะสั้นและทั่วไปขั้นตอนเป็นสิ่งที่ดีสำหรับแบบจำลองที่ตามขั้นตอน OOP นั้นดีสำหรับการออกแบบและ Function นั้นดีสำหรับการเขียนโปรแกรมระดับสูง

ฉันคิดว่าคุณควรลองอ่านประวัติในแต่ละกระบวนทัศน์และดูว่าทำไมผู้คนจึงสร้างมันขึ้นมาและคุณสามารถเข้าใจได้อย่างง่ายดาย

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


2

ฉันคิดว่าพวกเขามักจะไม่ใช่ "กับ" แต่คุณสามารถรวมพวกเขาได้ ฉันคิดว่าบ่อยครั้งคำที่คุณพูดถึงนั้นเป็นเพียงแค่ buzzwords มีคนไม่กี่คนที่รู้ว่า "เชิงวัตถุ" หมายถึงอะไรแม้ว่าพวกเขาจะเป็นผู้ประกาศข่าวประเสริฐที่สุดก็ตาม


1

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

ก) คุณประดิษฐ์ระบบที่ชาญฉลาดซึ่งจะเลียนแบบการสืบทอดในระดับหนึ่ง มันสามารถทำได้!

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

ii) คุณสามารถใช้คุณสมบัติการจัดตำแหน่งหน่วยความจำ struct เพื่อส่งเด็ก ๆ ไปยังผู้ปกครอง

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

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

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


ตัวประมวลผล c ++ ตัวแรกไม่มีอะไรมากไปกว่าตัวประมวลผลล่วงหน้าที่สร้างรหัส C ดังนั้นคุณลักษณะทั้งหมดของ c ++ - รวมถึงการสืบทอดหลายอย่างสามารถใช้งานได้โดยใช้ C (การเลียนแบบการจัดการข้อยกเว้น c ++ ใน C จะต้องมีการสนับสนุนแพลตฟอร์มบางอย่างสำหรับข้อยกเว้น แต่การใช้งาน c ++ ต้องการสิ่งนั้นด้วยเช่นกัน แนวคิดไม่ถูกต้อง)
Chris Becke

2
@ Chris Becke คำตอบของคุณเป็นปรัชญาเกินไป สำหรับหนึ่ง C มีหลายมาตรฐาน (ในช่วงหลายปีที่ผ่านมา) แทบจะไม่เคยมีคอมไพเลอร์ C ที่เป็นลูกบุญธรรมทั้งหมดที่ใช้ c ++ เพียงอย่างเดียว จะบอกว่า C ++ เป็นชุดของ C เพราะมันใช้ไวยากรณ์ C ไม่ได้มีความหมายอะไรมากเพราะคุณไม่สามารถเขียนโค้ดสำหรับคอมไพเลอร์ C หนึ่งที่คอมไพล์ในคอมไพเลอร์ C อื่นโดยไม่ต้องใช้ความพยายามอย่างมาก นอกจากนี้ยังมีคุณสมบัติภาษา (ระบบประเภท, รองรับ OOD) ในภาษาอื่นซึ่งจะไม่สามารถนำไปใช้ใน C โดยไม่ต้องใช้ C เพื่อออกแบบภาษาใหม่ (ซึ่งเป็นสาเหตุที่มี 'ภาษาใหม่')
Sprague

คุณรู้. ฉันไม่สามารถดูความคิดเห็นของฉันที่เกี่ยวข้องกับโพสต์นี้ได้อีก : P
Chris Becke

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