Pemrograman fungsional vs Pemrograman Berorientasi Objek [ditutup]

784

Saya terutama telah terpapar dengan pemrograman OO sejauh ini dan saya menantikan untuk belajar bahasa fungsional. Pertanyaan saya adalah:

  • Kapan Anda memilih pemrograman fungsional daripada berorientasi objek?
  • Apa definisi masalah yang khas di mana pemrograman fungsional merupakan pilihan yang lebih baik?
Olivier Lalonde
sumber
ini adalah programer yang
kirill_igum
1
pertanyaan serupa cs.se juga menutup apa contoh di mana pemrograman fungsional memberikan hasil yang lebih baik daripada gaya imperatif . kebijaksanaan konvensional tampaknya adalah bahwa satu tidak lebih unggul dari yang lain, atau mereka tidak dapat dibandingkan pada kriteria sederhana, atau bahwa mereka digunakan untuk tujuan yang berbeda ... pemrograman fungsional memiliki lebih banyak asal-usul & penggunaan ilmiah / akademik dan kurang umum di industri , jadi pertanyaannya juga mengatur "konflik industri vs akademis" yang tidak terselesaikan. satu ref klasik yang menunjukkan sytle OOP dalam pemrograman fungsional, buku SICP / MIT
vzn
" OO membuat kode dapat dipahami dengan merangkum bagian yang bergerak. FP membuat kode dapat dipahami dengan meminimalkan bagian yang bergerak. " --Micheal Feathers, 2010
jaco0646

Jawaban:

1193

Kapan Anda memilih pemrograman fungsional daripada berorientasi objek?

Ketika Anda mengantisipasi berbagai jenis evolusi perangkat lunak:

  • Bahasa berorientasi objek baik ketika Anda memiliki serangkaian operasi pada hal-hal , dan ketika kode Anda berkembang, Anda terutama menambahkan hal-hal baru. Ini dapat dicapai dengan menambahkan kelas baru yang menerapkan metode yang ada, dan kelas yang ada dibiarkan sendiri.

  • Bahasa fungsional baik ketika Anda memiliki satu set hal yang tetap , dan ketika kode Anda berkembang, Anda terutama menambahkan operasi baru pada hal-hal yang ada. Ini dapat dicapai dengan menambahkan fungsi baru yang menghitung dengan tipe data yang ada, dan fungsi yang ada dibiarkan sendiri.

Ketika evolusi salah jalan, Anda memiliki masalah:

  • Menambahkan operasi baru ke program berorientasi objek mungkin memerlukan pengeditan banyak definisi kelas untuk menambahkan metode baru.

  • Menambahkan hal baru ke program fungsional mungkin memerlukan pengeditan banyak definisi fungsi untuk menambahkan kasus baru.

Masalah ini telah dikenal selama bertahun-tahun; pada tahun 1998, Phil Wadler menjulukinya "masalah ekspresi" . Meskipun beberapa peneliti berpikir bahwa masalah ekspresi dapat diatasi dengan fitur bahasa seperti mixin, solusi yang diterima secara luas belum mencapai arus utama.

Apa definisi masalah yang khas di mana pemrograman fungsional merupakan pilihan yang lebih baik?

Bahasa fungsional unggul dalam memanipulasi data simbolik dalam bentuk pohon. Contoh favorit adalah kompiler, di mana bahasa sumber dan menengah jarang berubah (kebanyakan hal yang sama ), tetapi penulis kompiler selalu menambahkan terjemahan baru dan peningkatan atau optimisasi kode (operasi baru pada hal-hal). Kompilasi dan terjemahan yang lebih umum adalah "aplikasi pembunuh" untuk bahasa fungsional.

Norman Ramsey
sumber
119
Ada beberapa zen yang serius di balik jawaban ini. Saya pikir itu menerangi kenyataan bahwa pola desain OOP tertentu (Pengunjung) sebenarnya adalah retasan yang berupaya mengatasi masalah penambahan operasi baru.
Jacobs Data Solutions
54
Dalam JavaScript, Anda dapat memiliki semua hal.
Erik Reppen
61
@ErikReppen pada titik mana pertanyaan muncul, kapan Anda memilih untuk menggunakan fitur fungsional, dan kapan Anda memilih untuk menggunakan fitur berorientasi objek?
Norman Ramsey
7
@NormanRamsey Sama sekali tidak biasa mencampurnya dalam JS dan fungsi-fungsi kelas satu terkait dengan banyak fitur terkait JS OOP. Penyortiran array JS mengambil fungsi sebagai arg yang dapat menghasilkan beberapa struktur data yang kuat. Penutupan + fungsi yang lewat digunakan untuk menjaga objek jquery sangat ringan dalam memori, karena sebagian besar metode hanyalah referensi. Dll ...
Erik Reppen
9
@NormanRamsey: Jawaban yang sangat bagus, di sepanjang baris SICP. Menurut klasifikasi ini, pemrograman fungsional dan prosedural dikelompokkan bersama di sisi yang berlawanan dari pemrograman berorientasi objek. Ini bisa menjelaskan booming OOP selama akhir 1980-an awal 1990-an: ketika GUI menjadi arus utama, OOP terbukti menjadi pendekatan yang baik untuk memodelkannya karena Anda biasanya memiliki rangkaian operasi tetap (cat, buka, tutup, ubah ukuran) dan semakin banyak widget. Tentu saja, ini tidak berarti bahwa OOP lebih baik daripada prosedural untuk aplikasi apa pun, seperti yang Anda gambarkan.
Giorgio
177

Anda tidak perlu harus memilih di antara kedua paradigma tersebut. Anda dapat menulis perangkat lunak dengan arsitektur OO menggunakan banyak konsep fungsional. FP dan OOP bersifat ortogonal .

Ambil contoh C #. Bisa dibilang sebagian besar OOP, tetapi ada banyak konsep dan konstruksi KB. Jika Anda mempertimbangkan Linq , konstruksi paling penting yang memungkinkan Linq ada adalah sifat fungsional: ekspresi lambda .

Contoh lain, F #. Bisa dibilang itu kebanyakan FP, tetapi ada banyak konsep dan konstruk OOP yang tersedia. Anda dapat mendefinisikan kelas, kelas abstrak, antarmuka, berurusan dengan warisan. Anda bahkan dapat menggunakan kemampuan berubah-ubah saat membuat kode Anda lebih jelas atau ketika itu secara dramatis meningkatkan kinerja.

Banyak bahasa modern multi-paradigma.

Bacaan yang disarankan

Karena saya berada di kapal yang sama (latar belakang OOP, belajar FP), saya sarankan beberapa bacaan yang sangat saya hargai:

Bruno Reis
sumber
8
@duffymo: komentar Anda, seperti yang Anda katakan, sebagian besar tidak berguna. Tidak ada yang mau perbandingan bahasa, mesin virtual atau platform, terima kasih.
Bruno Reis
6
@ Bruno - respons terhadap "kekuatan .NET". Bersantai.
duffymo
6
Lucu, saya tidak melihat Anda mencaci Dykam tentang komentarnya yang tidak berguna. Apakah Anda dinominasikan sebagai moderator sementara saya tidak melihat? Tidak ada yang menyala di sini kecuali Anda. Saya akan mengatakannya lagi - santai.
duffymo
4
Heh, maaf jika saya mulai menyala. Saya tidak bermaksud mengatakan platform lain kurang kuat, hanya saja. NET tidak hanya mendukung OOP. Misalnya memiliki optimasi panggilan ekor.
Dykam
5
@nawfal, sampai Anda dapat menunjuk beberapa fitur intrinsik dalam dua paradigma dan mengatakan bahwa mereka tidak kompatibel, mereka ortogonal: itu adalah inti dari diskusi. FP tidak kompatibel dengan pemrograman imperatif menurut definisi, tetapi OOP tidak terbatas pada pemrograman imperatif. Alasan kami memiliki kata-kata yang berbeda untuk konsep-konsep ini adalah agar kami dapat membicarakannya: ketika Anda menyatukannya, Anda hanya memaksa kami untuk membuat kata-kata baru yang tidak perlu.
DavidS
31

Penawaran Pemrograman Berorientasi Objek:

  1. Enkapsulasi, untuk
    • mengendalikan mutasi keadaan internal
    • membatasi penggandengan ke representasi internal
  2. Subtipe, memungkinkan:
    • penggantian jenis yang kompatibel (polimorfisme)
    • cara kasar berbagi implementasi antar kelas (warisan implementasi)

Pemrograman Fungsional, di Haskell atau bahkan di Scala, dapat memungkinkan penggantian melalui mekanisme kelas tipe yang lebih umum. Keadaan internal yang berubah-ubah tidak dianjurkan atau dilarang. Enkapsulasi representasi internal juga dapat dicapai. Lihat Haskell vs OOP untuk perbandingan yang baik.

Pernyataan Norman bahwa "Menambahkan hal baru ke program fungsional mungkin memerlukan pengeditan banyak definisi fungsi untuk menambahkan kasus baru." tergantung pada seberapa baik kode fungsional telah menggunakan kelas tipe. Jika Pencocokan Pola pada Tipe Data Abstrak tertentu tersebar di seluruh basis kode, Anda memang akan menderita masalah ini, tetapi mungkin ini adalah desain yang buruk untuk memulai.

DIedit Referensi dihapus untuk konversi implisit ketika membahas kelas tipe. Dalam Scala, kelas tipe dikodekan dengan parameter implisit, bukan konversi, meskipun konversi implisit adalah cara lain untuk mencapai subtitusi tipe yang kompatibel.

retronym
sumber
3
Typeclasses bukan mekanisme untuk konversi implisit ke jenis lain. Mereka adalah deskripsi dari serangkaian fungsi yang didefinisikan untuk suatu tipe sehingga memberikan bentuk polimorfisme. Hal yang paling dekat dari Java-style OOP adalah interface, meskipun typeclasses Haskell memiliki beberapa perbedaan penting.
Zak
25
  1. Jika Anda berada di lingkungan yang sangat padat, maka pemrograman fungsional murni bermanfaat. Kurangnya keadaan yang bisa berubah membuat konkurensi hampir sepele. Lihat Erlang.

  2. Dalam bahasa multi-paradigma, Anda mungkin ingin memodelkan beberapa hal secara fungsional jika keberadaan keadaan yang dapat diubah harus merupakan detail implementasi, dan dengan demikian FP adalah model yang baik untuk domain masalah. Sebagai contoh, lihat daftar pemahaman dalam Python atau std.range dalam bahasa pemrograman D. Ini terinspirasi oleh pemrograman fungsional.

dsimcha
sumber