Apakah pemrograman fungsional menambah kompleksitas dalam kode? [Tutup]

17

Selama setahun terakhir saya telah menulis kode Scala (berasal dari latar belakang Java). Saya sangat suka bagaimana Anda bisa membuat kode yang lebih sederhana dan lebih bersih, dengan vals, kelas kasus, fungsi peta / filter / lambda, implisit dan inferensi tipe. Saya telah menggunakannya sebagian besar untuk aplikasi berbasis Akka .

Tahun ini saya sedang mengerjakan proyek Scala dengan tim baru, yang sangat suka pemrograman fungsional. Mereka banyak menggunakan Scalaz , dan kode diisi di mana-mana dengan aplikatif, batas konteks, pembaca / penulis / monad negara, bahkan metode utama adalah "dibungkus" dalam monad I / O. Alasan mereka adalah bahwa ini membuat kompiler "bekerja untuk kita" dalam menyatakan bahwa kode itu benar, dan setiap fungsi bebas dari efek samping.

Meski begitu, dari sudut pandang saya semua sintaks ini benar-benar menghalangi logika bisnis. Misalnya, jenis "MyBusinessObject" baik-baik saja, juga jenis seperti "Daftar [MyBusinessObject]", "Opsi [MyBusinessObject]" atau bahkan "Future [MyBusinessObject]". Mereka semua memiliki makna dan tujuan yang jelas. Di sisi lain, kode seperti:

def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}

apakah ini menambah kompleksitas pada program, atau hanya saya yang tidak terbiasa dengan cara pemrograman seperti ini?

Luciano
sumber
6
Apa pertanyaan Anda yang bisa dijawab secara objektif?
Pemburu Rusa
1
Sepertinya itu mengarah ke satu ton kode dengan satu atau dua nama variabel huruf. Sepertinya APL sedikit. Itu bukan pelengkap.
user949300
3
Saya mulai bermain dengan Haskell tahun lalu. Itu tampak sangat kompleks pada saat itu, ketika saya tidak mengerti konsep seperti currying, functors, monads, dll. Haskell mirip dengan Scalaz karena memiliki banyak fungsi simbolik pendek, seperti >>=dan <$>, yang tidak berarti apa-apa sampai Anda tahu apa yang mereka lakukan. Namun, setelah mempelajari apa yang mereka maksud, mereka membaca dengan sangat alami dan cepat kepada saya sekarang. Bukan jawaban, hanya pengalaman obyektif saya dengan hal-hal seperti ini. Saya menggunakan Scala juga, tetapi tidak memiliki pengalaman dengan perpustakaan Scalaz.
KChaloux
3
Anda hanya tidak terbiasa dengan idiom. @ user949300 variabel pendek sebenarnya bukan masalah bagi banyak kode fungsional (pikirkan konvensi gaya Matematika!). Baca juga blog Tony Morris untuk diskusi yang lebih mendalam tentang apa yang lebih baik menyampaikan makna, jenis, atau nama variabel verbal.
Andres F.
3
@ user949300: nama-nama variabel pendek lebih disukai secara lokal, itu sama di dunia fungsional dan imperatif (Anda tidak akan menulis for(i=0; i<7; ++i) { trivialOperation(i); }dengan beberapa trivialOperationCountvariabel canggung , bukan?) Sekarang, bahasa pemrograman fungsional dengan pencocokan pola kadang-kadang akan memperkenalkan beberapa variabel lagi di mana Anda baru saja menuliskan panggilan metode aksesor di OO. Hasilnya umumnya lebih ringkas; mungkin sedikit kurang jelas, tetapi melihat deklarasi data biasanya membuatnya jelas dengan cepat. Mengetik statis sangat membantu, tidak seperti di APL.
leftaroundabout

Jawaban:

37

Ini tidak ada hubungannya dengan pemrograman fungsional - Anda dapat menemukan situasi semacam ini dalam konteks bahasa pemrograman lain - pengembang yang sangat menyukai konstruksi lanjutan bahasa "mereka" sehingga mereka mengabaikan akal sehat tentang keterbacaan dan menjaga hal-hal sederhana. Saya telah mengalami situasi seperti itu di C, C ++, Perl, Java, C #, Basic, dan bahasa non-fungsional lainnya. Bukan pemrograman fungsional yang menambah kompleksitas kode - programmer melakukannya.

Jangan salah paham, saya tidak menyarankan untuk menghindari fitur bahasa tingkat lanjut - tetapi penting untuk menemukan keseimbangan yang tepat dalam konteks yang diberikan. Saat menulis perpustakaan umum untuk penggunaan> 100.000 pengembang di seluruh dunia, ada langkah-langkah berbeda untuk diterapkan seperti ketika Anda menulis generator laporan individu hanya untuk kantor lokal Anda.

Doc Brown
sumber
7
Ini juga banyak hubungannya dengan komunitas. Untuk pengembang dengan latar belakang Java atau C #, kodenya hampir tidak dapat dimengerti (dan komunitasnya juga tidak akan memahaminya). Tetapi jika Anda menulis Haskell, misalnya, dan Anda tidak menggunakan monad, aplikasi, fungsi, dan sebagainya, Anda membingungkan komunitas bahasa itu. "Kealamian" kode tidak melekat, tetapi relatif terhadap komunitasnya dan praktik-praktik yang sudah ada.
Andres F.
1
Ini sulit dilihat karena kebanyakan dari kita berasal dari latar belakang imperatif, yang terkadang membuat kita membuat asumsi yang salah tentang apa yang alami.
Andres F.
lihat saja pustaka SLT C ++, yang dapat ditulis agar jauh lebih mudah dibaca oleh amatir
ratchet freak
@ scratchetfreak: Saya kira maksud Anda STL. Saya pikir ini adalah contoh yang sangat bagus (dan memang, ini ada dalam benak saya dalam jawaban saya). Menggunakan template meta programming sangat masuk akal ketika Anda seorang programmer STL, karena itu membuat STL lebih dapat digunakan kembali. Dan orang-orang harus menjaga kode itu biasanya digunakan untuk templat pemrograman juga. Menggunakan metaprogramming template dengan cara seperti STL di seluruh aplikasi standar bisnis Anda dapat dengan mudah menyebabkan kode yang rumit dan sulit dikelola. Orang pasti dapat menemukan (jarang) kasus di mana TMP baik-baik saja bahkan dalam aplikasi bisnis, tentu saja.
Doc Brown
@DocBrown ya disleksia menendang pada waktu yang salah, tetapi jujur ​​jika saya memiliki setengah pikiran untuk (dan lebih banyak waktu daripada yang saya miliki sekarang), saya bisa menulis ulang banyak fungsi tubuh agar lebih mudah dibaca.
ratchet freak
7

Saya akan mengatakan bahwa Anda tidak terbiasa dengan cara kode mereka setidaknya bagian dari gambar. Saya dalam situasi yang sama seperti Anda (datang dari C # ke F # dan bekerja dengan orang-orang dengan latar belakang Haskell), dan sementara saya merasa itu adalah pengalaman yang menarik, saya memiliki momen ketika saya membenturkan kepala ke dinding, mengurai sebuah terutama komposisi fungsi titik-berbelit-belit hanya untuk memahami apa yang terjadi di sana. Itu hal budaya.

Adapun apakah kode khusus ini menambah kompleksitas ke program - saya tidak tahu. Setuju bahwa sepotong kode generik dapat menjadi kompleks itu sendiri. Tetapi ini adalah utilitas, bukan bagian dari logika bisnis. Jika Anda ingin tahu apakah itu membuat basis kode lebih kompleks atau lebih sederhana, Anda harus membayangkan bagaimana itu harus terlihat tanpa potongan kode itu. Seringkali dengan konstruksi generik sedemikian rupa sehingga kompleks sendiri, tetapi kompleksitas yang dapat Anda muat pada satu layar. Pada saat yang sama mereka membuat seluruh basis kode sedikit lebih sederhana. Ini khususnya terjadi pada monad.

Kemudian lagi, itu juga bisa menjadi kasus 'seni demi seni', seperti yang disarankan @Doc Brown. Tidak bisa mengesampingkannya juga.

scrwtp
sumber
5

Saya berpendapat bahwa secara umum pemrograman fungsional mengurangi kompleksitas dengan menghilangkan keadaan yang bisa berubah, sehingga mengurangi jumlah kasus yang harus dipertimbangkan ketika mencoba memahami bagaimana bagian kode bekerja.

Namun, pemrograman fungsional memungkinkan tingkat abstraksi yang lebih tinggi, dan sementara kode yang sangat abstrak bisa sangat berguna, tetapi juga sulit untuk dipahami karena secara definisi dipisahkan dari konteks yang biasanya Anda gunakan untuk memandu pemahaman Anda. Komentar Anda "Mereka semua memiliki makna dan tujuan yang jelas" tentang objek bisnis tidak diragukan lagi benar, tetapi benar-benar merupakan cerminan dari fakta bahwa logika itu sangat spesifik untuk kebutuhan dan konteks yang sudah Anda pahami. Keberadaan konstruk seperti Monad memungkinkan Anda membuat sesuatu yang sangat berguna dengan sedikit usaha, tetapi web dipenuhi dengan halaman yang mencoba menjelaskan apa itu Monad. Itu abstraksi untukmu.

Juga, Scalaz ditulis oleh orang-orang yang telah makan dan bernafas dengan FP sejak lama; mereka ingin membawa fungsionalitas yang tersedia di Haskell ke Scala. Dengan melakukan itu mereka tidak berusaha pedagogis. Scalaz memanfaatkan kosakata dan gaya yang tampak jelas dan langsung bagi penulis tetapi asing bagi yang belum tahu. Metode yang membingungkan bagi kami semua tampak begitu jelas bagi para penulis, mengingat latar belakang Haskell mereka, sehingga mereka bahkan tidak memerlukan komentar.

Selain itu, sebagai bahasa pemrograman fungsional, Scala memiliki beberapa kekurangan (sebagian karena JVM memiliki kekurangan) yang memaksa penulis Scalaz untuk menulis kode yang lebih buruk dalam beberapa kasus. Sebagai contoh, kurangnya eliminasi panggilan ekor memaksa penggunaan trampolin dalam beberapa kode, dan kurangnya "sistem jenis" dapat menyulitkan tanda tangan jenis.

Dan akhirnya, Scalaz memanfaatkan dirinya sendiri. Itu bisa dianggap sebagai tanda kekuatannya, tetapi bagi yang belum tahu itu bisa menjadikan sumber teka-teki - setiap potongan kode acak yang Anda lihat cenderung memanfaatkan sesuatu yang tampak asing bagi Anda.

Tetap bertahan. Dan ini mungkin bisa membantu.

AmigoNico
sumber
-4

Apakah ini menambah kompleksitas pada program, atau hanya karena Anda tidak terbiasa dengan cara pemrograman seperti ini?

Menurut Anda mengapa kemungkinan ini tidak sama?

Kode yang ditulis dengan baik dapat dibaca oleh orang-orang yang tidak terbiasa dengan bahasa pemrograman tertentu. Beberapa bahasa (BASIC, Pascal, dll) dapat dibaca dan dipahami oleh anak-anak sekolah yang belum pernah melihat bahasa pemrograman sebelumnya.

Jika seseorang yang memiliki pengalaman dengan bahasa lain dan pengalaman dengan Scala (dan yang saya anggap telah bekerja dengan Scalaz selama setidaknya satu minggu dan memiliki rekan kerja untuk menjelaskan hal-hal yang lebih rumit) masih bingung; maka itu bukti bahwa ia telah menambah kompleksitas.

Brendan
sumber
11
Ini tidak benar:"Well written code can be read by people who aren't familiar with the specific programming language."
Andres F.
@Andres: Memang benar ... sampai titik tertentu. Kode yang ditulis dengan baik akan memisahkan logika bisnis dari detail implementasi, dan logika bisnis harus dapat dibaca, karena sebagian besar dari apa yang dilakukannya adalah melakukan panggilan langsung ke fungsi-fungsi helper yang telah dikenal baik. Pembantu tersebut dapat menggunakan semua jenis fitur bahasa, tentu saja, dan membutuhkan pengalaman yang berat dengan bahasa dan perpustakaan untuk memahami.
Ben Voigt
4
Saya percaya berikut adalah APL idiomatik: x[⍋x←6?40]. Menurut Anda apa yang terjadi? Saya yakin tidak akan tahu ...
bdesham
3
@ Brendan Hanya dalam paradigma yang sama (dan bahkan kemudian, terkadang tidak). Misalnya, Prolog, Java, dan APL sangat berbeda sehingga saya berpendapat bahwa jika Anda hanya tahu satu dari mereka (dan tidak ada bahasa lain), Anda tidak dapat membaca dua lainnya, tidak peduli seberapa baik Anda tahu yang pertama. (Serius, dalam contoh bdesham, bagaimana iblis yang harus Anda tafsirkan "pohon natal" jika Anda tidak tahu APL?)
Izkata
1
Brendan, definisi Anda tentang yang ditulis dengan baik tidak standar. Ditulis dengan baik selalu relatif terhadap bahasa dan komunitasnya. Sebuah program dalam bahasa X ditulis dengan baik jika tidak bermasalah, efisien dan jelas ... untuk audiens yang diberikan! Ini berlaku untuk bahasa tertulis secara umum, omong-omong: selalu kenal audiens Anda. Apa yang cocok untuk (katakanlah) makalah ilmiah mungkin tidak cocok untuk email ke ibumu.
Andres F.