Apakah pemrograman fungsional mengabaikan manfaat yang diperoleh dari "Pada Kriteria yang Akan Digunakan dalam Sistem Penguraian menjadi Modul" (menyembunyikan data)?

27

Ada sebuah artikel klasik bernama On the Criteria To Be Digunakan dalam Sistem Penguraian menjadi Modul yang baru saja saya baca untuk pertama kalinya. Masuk akal bagi saya, dan mungkin merupakan salah satu artikel yang menjadi dasar OOP. Kesimpulannya:

Kami telah mencoba menunjukkan dengan contoh-contoh ini bahwa hampir selalu salah untuk memulai penguraian suatu sistem menjadi modul-modul berdasarkan diagram alur. ... Setiap modul kemudian dirancang untuk menyembunyikan keputusan seperti itu dari yang lain

Menurut pendapat saya yang tidak berpendidikan dan tidak berpengalaman, pemrograman fungsional mengambil saran yang berlawanan dari artikel ini. Pemahaman saya adalah pemrograman fungsional membuat aliran data idiomatis. Data diteruskan dari satu fungsi ke fungsi lainnya, masing-masing fungsi sangat menyadari data dan "mengubahnya" di sepanjang jalan. Dan saya pikir saya telah melihat pembicaraan Hickey Kaya di mana dia berbicara tentang bagaimana menyembunyikan data berlebihan atau tidak perlu atau sesuatu, tapi saya tidak ingat pasti.

  1. Pertama saya ingin tahu apakah penilaian saya benar. Apakah paradigma FP dan artikel ini secara filosofis tidak setuju?
  2. Dengan asumsi mereka tidak setuju, bagaimana FP "mengompensasi" karena kurangnya data yang disembunyikan? Mungkin mereka mengorbankan data yang disembunyikan tetapi mendapatkan X, Y dan Z. Saya ingin tahu alasan mengapa X, Y dan Z dianggap lebih menguntungkan daripada menyembunyikan data.
  3. Atau, dengan asumsi mereka tidak setuju, mungkin FP merasa bahwa menyembunyikan data itu buruk. Jika demikian, mengapa menurutnya menyembunyikan data itu buruk?
  4. Dengan asumsi mereka setuju, saya ingin tahu apa implementasi menyembunyikan data oleh FP. Jelas melihat ini di OOP. Anda dapat memiliki privatebidang yang tidak dapat diakses siapa pun di luar kelas. Tidak ada analogi yang jelas tentang ini bagi saya di FP.
  5. Saya merasa ada pertanyaan lain yang harus saya tanyakan tetapi saya tidak tahu saya harus bertanya. Jangan ragu untuk menjawabnya juga.

Memperbarui

Saya menemukan pembicaraan Neal Ford ini yang memiliki slide yang sangat relevan di dalamnya. Saya akan menyematkan tangkapan layar di sini:

masukkan deskripsi gambar di sini

Daniel Kaplan
sumber
1
Saya tidak dapat menjawab pertanyaan lengkap, tetapi untuk (4), ada sistem modul dalam beberapa bahasa FP yang dapat menyediakan enkapsulasi.
Andres F.
@AndresF. ah ya itu benar. Saya lupa bahwa Haskell memiliki modul dan Anda dapat menyembunyikan tipe data dan fungsi di dalamnya. Mungkin ketika saya mengatakan FP saya benar-benar mengatakan Clojure. Anda dapat memiliki fungsi pribadi dan "bidang" di Clojure, tetapi saya merasa ini idiomik untuk membuat data Anda terlihat oleh apa saja dan meneruskannya di mana saja.
Daniel Kaplan
6
Apa yang sering Anda lakukan adalah membuat tipe Anda terlihat, tetapi sembunyikan konstruktor Anda. Jenis abstrak ini dilakukan dengan sangat baik oleh sistem modul OCaml
Daniel Gratzer
6
Dalam bahasa seperti ML, tidak memiliki akses ke konstruktor berarti bahwa Anda tidak dapat membuat pola yang cocok dengan nilai jenis itu untuk mendekonstruksinya. Satu-satunya hal yang dapat Anda lakukan dengan nilai-nilai itu adalah meneruskannya ke fungsi apa pun yang tersedia. Ini adalah abstraksi data yang sama seperti yang dilakukan di, katakanlah, C yang tidak memiliki gagasan kelas tentang apa yang publik atau pribadi.
Luc Danton
1
@ SK-logika: Dari sudut pandang "masalah ekspresi", mengungkapkan data itu baik ketika Anda ingin memperluas dengan fungsi baru di masa depan (dan tidak masalah menjaga data tetap) dan menyembunyikan data itu baik ketika Anda mau untuk memperluas dengan tipe data baru di masa depan (dengan biaya menjaga antarmuka fungsional tetap)
hugomg

Jawaban:

23

Artikel yang Anda sebutkan adalah tentang modularitas secara umum, dan akan berlaku sama untuk program yang terstruktur, fungsional, dan berorientasi objek. Saya telah mendengar artikel itu sebelumnya dari seseorang yang adalah seorang pria OOP besar, tetapi saya membacanya sebagai artikel tentang pemrograman secara umum, bukan sesuatu yang OOP spesifik. Ada sebuah artikel terkenal tentang pemrograman fungsional, Mengapa Masalah Pemrograman Fungsional , dan kalimat pertama dari kesimpulan menyatakan "Dalam makalah ini, kami berpendapat bahwa modularitas adalah kunci untuk pemrograman yang sukses." Jadi jawaban untuk (1) adalah tidak.

Fungsi yang dirancang dengan baik tidak mengasumsikan lebih banyak tentang data mereka daripada yang seharusnya, sehingga bagian tentang "sangat menyadari data" salah. (Atau setidaknya sama salahnya dengan OOP. Anda tidak dapat memprogram secara ketat pada abstraksi tingkat tinggi dan mengabaikan semua detail selamanya dalam paradigma apa pun. Pada akhirnya, beberapa bagian dari program ini benar-benar perlu mengetahui tentang rincian spesifik data.)

Penyembunyian data adalah istilah khusus OOP, dan itu tidak persis sama dengan menyembunyikan informasi yang dibahas dalam artikel. Informasi yang disembunyikan dalam artikel ini adalah tentang keputusan desain yang sulit dibuat atau kemungkinan akan berubah. Tidak setiap keputusan desain tentang format data sulit atau mungkin berubah, dan tidak setiap keputusan sulit atau mungkin berubah adalah tentang format data. Secara pribadi, saya tidak dapat melihat mengapa programmer OO ingin semuanya menjadi objek. Terkadang, Anda hanya membutuhkan struktur data sederhana.

Sunting: Saya menemukan kutipan yang relevan dari wawancara dengan Rich Hickey .

Fogus: Mengikuti gagasan itu — beberapa orang dikejutkan oleh fakta bahwa Clojure tidak terlibat dalam enkapsulasi penyembunyian data pada tipenya. Mengapa Anda memutuskan untuk tidak lagi menyembunyikan data?

Hickey: Mari kita perjelas bahwa Clojure sangat menekankan pemrograman pada abstraksi. Pada titik tertentu, seseorang akan perlu memiliki akses ke data. Dan jika Anda memiliki gagasan "pribadi", Anda perlu gagasan tentang hak istimewa dan kepercayaan yang sesuai. Dan itu menambah satu ton kompleksitas dan sedikit nilai, menciptakan kekakuan dalam suatu sistem, dan seringkali memaksa hal-hal untuk hidup di tempat yang tidak seharusnya. Ini merupakan tambahan dari kehilangan lainnya yang terjadi ketika informasi sederhana dimasukkan ke dalam kelas. Sejauh data tidak dapat diubah, ada sedikit bahaya yang dapat terjadi karena menyediakan akses, selain dari itu seseorang dapat bergantung pada sesuatu yang mungkin berubah. Baiklah, orang-orang melakukan itu sepanjang waktu dalam kehidupan nyata, dan ketika segalanya berubah, mereka beradaptasi. Dan jika mereka rasional, mereka tahu kapan mereka membuat keputusan berdasarkan sesuatu yang dapat berubah yang mungkin mereka perlu adaptasi di masa depan. Jadi, ini adalah keputusan manajemen risiko, yang menurut saya programmer harus bebas untuk membuat. Jika orang tidak memiliki kepekaan terhadap keinginan untuk memprogram abstraksi dan waspada untuk menikahi detail implementasi, maka mereka tidak akan pernah menjadi programmer yang baik.

Michael Shaw
sumber
2
Pemrogram OO tidak ingin semuanya menjadi objek. Tetapi beberapa hal (banyak hal) mendapat manfaat dari enkapsulasi. Saya mengalami kesulitan memahami bagaimana atau di mana jawaban Anda benar-benar menjawab pertanyaan itu. Tampaknya hanya menegaskan bahwa konsep tersebut tidak spesifik untuk OOP dan bahwa OOP memiliki masalah lain dan seterusnya - bisakah Anda memberikan contoh yang jelas, bahkan jika itu hanya beberapa baris kodesemu? Atau deskripsi papan tulis tentang desain yang mempertimbangkan hal ini? Atau apa pun yang akan memperkuat pernyataan di sini?
Aaronaught
2
@Aronaught: Saya membahas banyak (meskipun tidak semua) poin yang diajukan dalam pertanyaan, dan merujuk makalah tentang pemrograman fungsional yang melihat modularitas dengan cara yang mirip dengan makalah dalam pertanyaan. Sebagian besar, fakta bahwa konsep itu tidak spesifik untuk OOP adalah jawaban untuk pertanyaannya (kecuali saya salah paham pertanyaannya). Saya benar-benar tidak berbicara tentang OOP yang memiliki masalah lain di sini. Anda memiliki poin bagus tentang memberikan contoh; Saya akan melihat apakah saya bisa menghasilkan yang bagus.
Michael Shaw
2
"Kadang-kadang, struktur data sederhana adalah yang Anda butuhkan". +1. Sesuatu OOP masuk akal, kadang-kadang FP.
Laurent Bourgault-Roy
1
@Aronaught Jawaban ini tidak menunjukkan tentang modularitas (yang merupakan enkapsulasi dan penggunaan kembali) menjadi salah satu tujuan FP (seperti yang dibahas dalam "Mengapa Pemrograman Fungsional Penting"), oleh karena itu membuat jawaban untuk menunjuk (1) dari pertanyaan a " tidak".
Andres F.
2
@JimmyHoffa menyembunyikan informasi adalah prinsip yang waras bahkan di luar OO. Dalam haskell, saya masih ingin pengguna diizinkan bekerja dengan jumlah minimal pengetahuan tentang struktur data apa pun. Tentu, memiliki akses ke bagian dalam kurang berbahaya karena tidak ada yang bisa berubah. Tetapi semakin sedikit pengguna melihat tentang satu modul / struktur data / konsep abstrak apa pun, semakin banyak peluang refactoring yang Anda dapatkan. Saya tidak peduli apakah Peta adalah pohon biner seimbang atau mouse dalam kotak kecil di komputer saya. Ini adalah motivasi utama di balik penyembunyian data, dan valid di luar OO.
Simon Bergot
12

... dan mungkin merupakan salah satu artikel yang menjadi dasar OOP.

Tidak juga, tetapi hal itu menambah diskusi, khususnya bagi para praktisi yang, pada saat itu, dilatih untuk menguraikan sistem menggunakan kriteria pertama yang ia jelaskan di koran.

Pertama saya ingin tahu apakah penilaian saya benar. Apakah paradigma FP dan artikel ini secara filosofis tidak setuju?

Tidak. Terlebih lagi, bagi saya, uraian Anda tentang seperti apa program FP tidak berbeda dari yang lain yang menggunakan prosedur atau fungsi:

Data diteruskan dari satu fungsi ke fungsi lainnya, masing-masing fungsi sangat menyadari data dan "mengubahnya" di sepanjang jalan.

... kecuali bagian "keintiman", karena Anda dapat (dan sering melakukannya) memiliki fungsi yang beroperasi pada data abstrak, tepatnya untuk menghindari keintiman. Dengan demikian, Anda memiliki kontrol atas "keintiman" itu dan Anda dapat mengaturnya sesuka Anda, dengan mengatur antarmuka (mis. Fungsi) untuk apa yang ingin Anda sembunyikan.

Jadi, saya tidak melihat alasan mengapa kita tidak dapat mengikuti kriteria penyembunyian informasi Parnas menggunakan pemrograman fungsional dan berakhir dengan implementasi indeks KWIC dengan manfaat yang sama dengan implementasi keduanya.

Dengan asumsi mereka setuju, saya ingin tahu apa implementasi menyembunyikan data oleh FP. Jelas melihat ini di OOP. Anda dapat memiliki bidang pribadi yang tidak dapat diakses siapa pun di luar kelas. Tidak ada analogi yang jelas tentang ini bagi saya di FP.

Sejauh menyangkut data, Anda dapat menguraikan abstraksi data dan abstraksi tipe data menggunakan FP. Semua ini menyembunyikan struktur beton dan manipulasi struktur beton ini menggunakan fungsi sebagai abstraksi.

EDIT

Ada semakin banyak pernyataan di sini yang menyatakan bahwa "menyembunyikan data" dalam konteks FP tidak begitu berguna (atau OOP-ish (?)). Jadi, izinkan saya memberi stempel di sini contoh yang sangat sederhana dan jelas dari SICP:

Misalkan sistem Anda perlu bekerja dengan bilangan rasional. Salah satu cara Anda mungkin ingin mewakili mereka adalah sebagai pasangan atau daftar dua bilangan bulat: pembilang dan penyebut. Demikian:

(define my-rat (cons 1 2)) ; here is my 1/2 

Jika Anda mengabaikan abstraksi data, kemungkinan besar Anda akan mendapatkan pembilang dan penyebut menggunakan cardan cdr:

(... (car my-rat)) ; do something with the numerator

Mengikuti pendekatan ini, semua bagian dari sistem yang memanipulasi bilangan rasional akan tahu bahwa bilangan rasional adalah cons- mereka akan consmembuat angka rasional dan mengekstraknya menggunakan operator daftar.

Satu masalah yang mungkin Anda hadapi adalah ketika Anda perlu mengurangi bentuk bilangan rasional - perubahan akan diperlukan di seluruh sistem. Juga, jika Anda memutuskan untuk mengurangi pada waktu pembuatan, Anda mungkin menemukan kemudian bahwa mengurangi ketika mengakses salah satu istilah rasional lebih baik, menghasilkan perubahan skala penuh lainnya.

Masalah lain adalah jika, secara hipotesis, representasi alternatif untuk mereka lebih disukai dan Anda memutuskan untuk meninggalkan consrepresentasi - perubahan skala penuh lagi.

Setiap upaya yang waras dalam menghadapi situasi ini kemungkinan akan mulai menyembunyikan representasi rasional di balik antarmuka. Pada akhirnya, Anda mungkin berakhir dengan sesuatu seperti ini:

  • (make-rat <n> <d>)mengembalikan bilangan rasional yang pembilangnya adalah bilangan bulat <n>dan yang penyebutnya bilangan bulat <d>.

  • (numer <x>)mengembalikan pembilang dari bilangan rasional <x>.

  • (denom <x>)mengembalikan penyebut bilangan rasional <x>.

dan sistem tidak akan lagi (dan seharusnya tidak lagi) tahu dari apa rasionalisasi dibuat. Hal ini karena cons, cardan cdrtidak intrinsik untuk rasional, tetapi make-rat, numerdan denom yang . Tentu saja, ini bisa dengan mudah menjadi sistem FP. Jadi, "penyembunyian data" (dalam hal ini, lebih dikenal sebagai abstraksi data, atau upaya untuk merangkum representasi dan struktur konkret) muncul sebagai konsep yang relevan dan teknik yang banyak digunakan dan dieksplorasi, baik dalam konteks OO, pemrograman fungsional atau terserah.

Dan intinya adalah ... meskipun orang mungkin mencoba untuk membuat perbedaan antara apa "jenis persembunyian" atau enkapsulasi yang mereka lakukan (apakah mereka menyembunyikan keputusan desain, atau struktur data atau algoritma - dalam kasus abstraksi prosedural), semuanya memiliki tema yang sama: mereka dimotivasi oleh satu atau lebih poin yang dibuat Parnas secara eksplisit. Itu adalah:

  • Changeability: apakah perubahan yang diperlukan dapat dilakukan secara lokal atau disebarkan melalui sistem.
  • Pengembangan Mandiri: sejauh mana dua bagian dari sistem dapat dikembangkan secara paralel.
  • Comprehensibility: seberapa banyak sistem yang dibutuhkan untuk diketahui untuk memahami salah satu bagiannya.

Contoh di atas diambil dari buku SICP jadi, untuk diskusi lengkap dan presentasi konsep-konsep ini dalam buku, saya sangat merekomendasikan memeriksa bab 2 . Saya juga merekomendasikan untuk membiasakan diri dengan Tipe Data Abstrak dalam konteks FP, yang membawa masalah lain ke tabel.

Thiago Silva
sumber
Saya setuju bahwa persembunyian data relevan dengan FP. Dan, seperti yang Anda katakan, ada cara untuk mencapai ini.
Andres F.
2
Anda baru saja membuat poin saya dengan indah: Anda memiliki fungsi-fungsi ini yang tidak menyembunyikan data, mereka adalah ekspresi yang menggambarkan cara mendapatkan data, sehingga dengan memiliki abstraksi dalam ekspresi daripada bidang data Anda tidak perlu khawatir tentang persembunyian data dengan membuat beberapa objek kompleks dengan anggota pribadi atau dengan membuat nilai kontra Anda tidak dapat diakses, kegiatan pembuatan, pengambilan dan interaksi dengan data rasional dinyatakan oleh karena itu data rasional yang sebenarnya tidak perlu disembunyikan karena mengubah data tidak akan ubah ekspresi Anda.
Jimmy Hoffa
8

Keyakinan Anda bahwa pemrograman fungsional tidak memiliki data yang disembunyikan adalah salah. Hanya dibutuhkan pendekatan berbeda untuk menyembunyikan data. Salah satu cara paling umum untuk menyembunyikan data dalam pemrograman fungsional adalah melalui penggunaan fungsi polimorfik yang menggunakan fungsi sebagai argumen. Misalnya fungsi ini

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

hanya dapat melihat struktur terluar data (yaitu bahwa itu adalah daftar) ia tidak dapat melihat apa pun tentang data yang berisi daftar dan hanya dapat beroperasi pada data melalui fungsi tunggal yang diteruskan ke itu.

Fungsi yang dilewatkan sebagai argumen analog dengan metode publik pada tipe data yang berisi daftar. Ini memberikan cara operasi yang terbatas pada data, tetapi tidak mengekspos cara kerja internal tipe data.

Dirk Holsopple
sumber
5

Saya akan mengambil risiko di sini dan mengatakan bahwa konsep itu tidak relevan di FP seperti di OO.

tl; dr; Maksud dari penyembunyian data adalah untuk memastikan bahwa tanggung jawab dipertahankan di mana seharusnya mereka berada, dan Anda tidak memiliki aktor luar yang mengacaukan data yang tidak mereka ketahui. Dalam data FP dihasilkan oleh ekspresi, dan dengan cara ini Anda tidak dapat mengacaukan data karena itu bukan sifat yang bisa berubah seperti halnya komputasi komposer yang benar-benar mengubah aturan permainan.


Dalam pengalaman saya dengan FP; yang diakui tidak signifikan, saya cenderung menemukan satu kontras dengan OO dalam apa yang menunjukkan pemodelan data yang baik / umum.

Kontras ini adalah bahwa dalam OO secara umum Anda memodelkan hal-hal untuk mewakili data Anda. Analogi mobil wajib:

OO

  • Anda memiliki Object mobil, yang menyembunyikan detail tentang mobil seperti penerapan AC (apakah digerakkan oleh sabuk, atau digerakkan oleh tekanan udara? Konsumen tidak perlu tahu, jadi sembunyikan).
  • Objek mobil ini memiliki banyak properti dan metode yang menggambarkan semua fakta tentang mobil serta cara Anda dapat bekerja dengan mobil.
  • Objek mobil ini memiliki sifat yang merupakan komponen dari mobil yang lebih jauh bersembunyi dari Mobil keseluruhan implementasi khusus mereka, dan fakta data mereka memungkinkan komponen mobil dapat dipertukarkan.

Yang perlu diperhatikan di sini adalah ketika Anda memodelkan hal-hal dalam format OO, itu semua tentang mewakili hal-hal sebagai Data. Anda memiliki objek dengan properti, banyak dari properti itu adalah objek dengan lebih banyak properti. Anda memiliki beberapa metode di sana-sini yang melekat pada objek-objek itu, tetapi semua yang mereka lakukan biasanya adalah menyatukan sifat-sifat objek dengan cara ini dan itu, sekali lagi pemodelan ini sangat berpusat pada data; itu adalah Anda memodelkan data Anda untuk berinteraksi dengan berfokus pada penataan itu untuk menyediakan semua poin data Anda sehingga konsumen dapat mengubah data dengan cara ini dan itu.

FP

  • Anda memiliki banyak perhitungan yang memungkinkan Anda untuk menggambarkan perilaku
  • Ungkapan perilaku ini terkait dengan cara yang dapat diterjemahkan ke cara perilaku mobil terkait satu sama lain, seperti mobil yang mengalami akselerasi / perlambatan, ada dua perilaku yang menentang satu sama lain dengan cara yang sama.

Perbedaan besar antara OO dan FP yang selalu menyerang saya adalah seperti yang saya katakan di atas cara Anda memodelkan data. Dalam OO seperti yang disebutkan di atas Anda memodelkan data sebagai data, dalam FP Anda memodelkan data sebagai perhitungan, ekspresi, algoritma, ini lebih tentang pemodelan aktivitas data Anda daripada fakta-fakta itu. Pikirkan tentang pemodelan data dasar dalam matematika, selalu tentang mendapatkan persamaan yang dapat menghasilkan data Anda, yang memodelkan data Anda sebagai aktivitas yang menyebabkannya, berbeda dengan OO, pemodelan akan menghasilkan cara untuk mewakili data yang Anda miliki. Itu banyak perbedaan antara FP dan OO.

Ingat, untuk banyak waktu LISP, salah satu bahasa FP dasar, hidup dengan sejumlah kecil tipe data primitif. Ini berfungsi karena pendekatannya bukan tentang pemodelan representasi kompleks data Anda, melainkan komputasi yang menghasilkan dan mengekspresikan perilaku sistem Anda.

Ketika saya mulai menulis beberapa kode dalam FP, saya mulai dengan menulis kode yang melakukan sesuatu, di mana ketika saya mulai menulis kode dalam OO, saya mulai dengan menulis model yang menggambarkan sesuatu. Melakukan hal-hal tersembunyi dalam FP dengan menjadi ekspresi, melakukan hal-hal yang diekspos dalam OO dengan dijelaskan dengan data, menyembunyikan batas data ini kata paparan.


Kembali ke pertanyaan yang ada, apa yang dikatakan FP tentang penyembunyian data, apakah ia menghargainya atau tidak setuju atau tidak?

Saya katakan itu tidak masalah, di OO data Anda adalah nyali dan bagian penting dalam program Anda yang harus disembunyikan dari campur tangan. Dalam FP, nyali dan pengetahuan sistem Anda semuanya tersembunyi dalam algoritme dan komputasi yang mengekspresikan sistem. Secara definisi ini kurang lebih tidak berubah, satu-satunya cara untuk mengubah ekspresi komputasi adalah hal-hal seperti makro, tetapi meskipun demikian, definisi mutasi Anda adalah ekspresi itu sendiri yang tidak dapat diajak campur tangan lebih jauh.

Jimmy Hoffa
sumber
ini brilian, saya sangat menikmati membacanya. Terima kasih atas kontribusi Anda
Chris McCall
5

Ada sedikit paradoks di sini. Meskipun pemrograman fungsional berfokus pada, yah, fungsi, dan seringkali memiliki fungsi yang bekerja langsung pada tipe data primitif, ia cenderung memiliki lebih banyak data yang bersembunyi daripada pemrograman berorientasi objek.

Bagaimana ini? Pikirkan tentang antarmuka OO yang bagus yang menyembunyikan data yang mendasarinya - mungkin koleksi (saya mencoba untuk mengambil sesuatu yang hampir di mana-mana). Anda mungkin tidak perlu mengetahui tipe objek yang mendasari dalam koleksi atau tipe objek yang mengimplementasikan koleksi, selama Anda tahu koleksi mengimplementasikan, katakanlah, IEnumerable. Jadi, Anda memiliki data yang disembunyikan.

Dalam pemrograman fungsional, Anda dapat menulis fungsi yang bekerja secara efektif dengan antarmuka IEnumerable, tetapi beroperasi pada tipe data primitif (atau pada tipe data apa pun). Tetapi bagaimana jika tipe itu tidak pernah mengimplementasikan metode IEnumerable? Inilah kuncinya, Anda selalu dapat memiliki "metode" yang membentuk bagian yang diperlukan dari "antarmuka" menjadi parameter yang diteruskan ke fungsi Anda. Atau Anda bisa menggabungkan fungsi dengan data dan melakukan hal-hal dengan cara seperti OO.

Perhatikan bahwa Anda tidak menyembunyikan data dengan jumlah yang lebih sedikit daripada yang Anda miliki di OO. Fungsi umum saya yang bekerja pada tipe apa pun jelas tidak mengakses data dalam tipe itu - yang terjadi di dalam fungsi yang dilewatkan sebagai parameter ke fungsi umum, tetapi fungsi umum tidak pernah mengintip ke dalam fungsi tersebut untuk melihat data.

Jadi, sejauh poin 1 Anda, saya tidak berpikir FP dan artikelnya benar-benar tidak setuju. Saya tidak berpikir karakterisasi FP Anda tidak menyembunyikan data sudah benar. Orang bisa mengimplementasikan desain yang disukai penulis di FP, tentu saja.

Sejauh poin 4 (2 dan 3 tidak masuk akal untuk menjawab mengingat apa yang saya katakan untuk poin 1) itu bervariasi. Ini juga bervariasi dalam bahasa OO, dan di banyak bidang pribadi bersifat pribadi oleh konvensi daripada ditegakkan oleh bahasa.

psr
sumber
Dengan kata lain: dalam pemrograman fungsional, lebih banyak lagi yang "tersembunyi" secara default, hanya karena tidak ada! Hanya hal-hal yang secara eksplisit Anda bawa ke ruang lingkup yang "tidak disembunyikan".
leftaroundabout
3

Pertama, terima kasih atas tautannya ke artikel hebat ini, saya tidak tahu sejauh ini, dan itu memberi saya banyak masukan tentang beberapa hal yang saya diskusikan dengan beberapa perancang perangkat lunak lain dari komunitas pada tahun-tahun terakhir. Inilah pendapat saya tentang hal itu:

Pertama saya ingin tahu apakah penilaian saya benar. Apakah paradigma FP dan artikel ini secara filosofis tidak setuju?

Desain FP sangat berfokus pada aliran data (yang menurut IMHO tidak terlalu buruk seperti yang disiratkan oleh artikel). Jika ini merupakan "ketidaksepakatan" yang lengkap, dapat diperdebatkan.

Dengan asumsi mereka tidak setuju, bagaimana FP "mengompensasi" karena kurangnya data yang disembunyikan? Mungkin mereka mengorbankan data yang disembunyikan tetapi mendapatkan X, Y dan Z. Saya ingin tahu alasan mengapa X, Y dan Z dianggap lebih menguntungkan daripada menyembunyikan data.

IMHO itu tidak mengkompensasi. Lihat di bawah.

Atau, dengan asumsi mereka tidak setuju, mungkin FP merasa bahwa menyembunyikan data itu buruk. Jika demikian, mengapa menurutnya menyembunyikan data itu buruk?

Saya rasa sebagian besar pengguna atau perancang FP tidak merasakan atau berpikir dengan cara ini, lihat di bawah.

Dengan asumsi mereka setuju, saya ingin tahu apa implementasi menyembunyikan data oleh FP. Jelas melihat ini di OOP. Anda dapat memiliki bidang pribadi yang tidak dapat diakses siapa pun di luar kelas. Tidak ada analogi yang jelas tentang ini bagi saya di FP.

Inilah intinya - Anda mungkin telah melihat begitu banyak sistem OOP diimplementasikan dengan cara non-fungsional yang Anda yakini OOP tidak berfungsi. Dan itu salah, IMHO OOP dan FP sebagian besar konsep ortogonal, dan Anda dapat dengan sempurna membangun sistem OO fungsional, yang memberi Anda jawaban yang jelas untuk pertanyaan Anda. Implementasi "objek" klasik dalam FP dilakukan dengan memanfaatkan penutupan , dan jika Anda ingin objek digunakan dalam sistem fungsional, titik kuncinya adalah untuk mendesainnya agar tidak berubah.

Jadi untuk membuat sistem yang lebih besar, IMHO Anda dapat membuat modul, kelas dan objek menggunakan konsep OO, persis seperti yang dijelaskan di bawah "Modularisasi 2" dalam artikel tanpa meninggalkan "jalur FP". Anda akan menggunakan konsep modul bahasa FP favorit Anda, menjadikan semua objek Anda tidak berubah dan menggunakan "yang terbaik dari kedua dunia".

Doc Brown
sumber
3

TL; DR : Tidak

Apakah paradigma FP dan artikel ini secara filosofis tidak setuju?

Tidak, tidak. Pemrograman Fungsional adalah deklaratif yang merupakan "gaya membangun struktur dan elemen program komputer, yang mengekspresikan logika perhitungan tanpa menjelaskan aliran kontrolnya." Ini kurang tentang mengikuti diagram alur dan lebih seperti membuat aturan yang membuat aliran muncul sendiri.

Pemrograman prosedural jauh lebih dekat dengan pengkodean diagram alur daripada pemrograman fungsional. Ini mengikuti bahwa transformasi yang terjadi, dan mengkodekan dari transformasi tersebut menjadi prosedur yang dieksekusi dalam urutan, persis seperti aliran dalam diagram alur yang dijelaskan.

Sedangkan bahasa prosedural memodelkan eksekusi program sebagai urutan perintah imperatif yang dapat secara implisit mengubah keadaan bersama, eksekusi bahasa pemrograman fungsional model sebagai evaluasi ekspresi kompleks yang hanya bergantung satu sama lain dalam hal argumen dan nilai balik. Karena alasan ini, program fungsional dapat memiliki urutan eksekusi kode yang lebih bebas, dan bahasa dapat menawarkan sedikit kontrol atas urutan di mana berbagai bagian dari program dieksekusi. (Misalnya, argumen untuk permohonan prosedur dalam Skema dieksekusi dalam urutan sewenang-wenang.)

Menyembunyikan Data

  • Pemrograman Fungsional memiliki metode penyembunyian data sendiri, misalnya penutupan berpikir . Itu adalah data yang disembunyikan oleh enkapsulasi dalam penutupan. Sulit bagi bidang untuk menjadi lebih banyak data pribadi yang telah ditutup karena hanya penutupan yang memiliki referensi ke data dan Anda tidak dapat merujuknya secara eksternal ke penutupan.
  • Salah satu alasan untuk menyembunyikan data adalah untuk menstabilkan antarmuka pemrograman dengan menyembunyikan data yang bermutasi. Pemrograman fungsional tidak memiliki data yang bermutasi, oleh karena itu tidak perlu banyak menyembunyikan data.
dietbuddha
sumber
3
"Pemrograman fungsional tidak memiliki data yang bermutasi, oleh karena itu tidak perlu banyak menyembunyikan data." - Ini adalah pernyataan yang sangat menyesatkan. Anda berkata pada diri sendiri (dan saya setuju) bahwa salah satu alasan untuk merangkum perilaku adalah untuk memiliki kendali atas mutasi data. Tetapi untuk menyimpulkan bahwa kurangnya mutasi hampir membuat enkapsulasi tidak berguna adalah suatu bentangan besar. ADT dan abstraksi data pada umumnya meresap dalam literatur dan sistem FP.
Thiago Silva
Saya tidak pernah mengatakan itu "hampir membuat enkapsulasi tidak berguna". Itulah pikiran dan pikiran Anda sendiri. Saya katakan Anda tidak perlu melakukan banyak data bersembunyi karena kurangnya variabel bermutasi. Ini tidak membuat enkapsulasi atau menyembunyikan data tidak berguna, itu hanya mengurangi itu digunakan karena kasus-kasus itu tidak ada. Semua kasus lain di mana penyembunyian data dan enkapsulasi berguna masih valid.
dietbuddha