Keterbacaan pemrograman fungsional [tertutup]

13

Saya ingin tahu tentang ini karena saya ingat sebelum belajar bahasa fungsional, saya pikir mereka semua mengerikan, sangat, sangat tidak dapat dibaca. Sekarang saya tahu Haskell dan f #, saya merasa butuh sedikit lebih lama untuk membaca lebih sedikit kode, tetapi kode kecil itu jauh lebih banyak daripada jumlah yang setara dalam bahasa imperatif, jadi rasanya seperti keuntungan bersih dan saya tidak terlalu dipraktekkan secara fungsional.

Inilah pertanyaan saya, saya terus-menerus mendengar dari orang-orang OOP bahwa gaya fungsional sangat tidak dapat dibaca. Saya ingin tahu apakah ini masalahnya dan saya menipu diri sendiri, atau jika mereka meluangkan waktu untuk belajar bahasa fungsional, seluruh gaya tidak akan lagi lebih tidak dapat dibaca daripada OOP?

Adakah yang melihat bukti atau mendapatkan anekdot di mana mereka melihat ini dengan satu atau lain cara dengan frekuensi yang cukup untuk dikatakan? Jika menulis secara fungsional benar-benar mudah dibaca maka saya tidak ingin terus menggunakannya, tapi saya benar-benar tidak tahu apakah itu masalahnya atau tidak ..

Jimmy Hoffa
sumber
1
Saya ingat melihat kode untuk "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/nario ketika saya hampir tidak tahu apa-apa tentang pemrograman fungsional dan ingat berpikir 'Wow. Ini sepertinya sangat mudah dibaca '
WuHoUnited
3
@BlackICE linq dan lambdas jauh dari mendefinisikan "pemrograman fungsional". Pemrograman fungsional melibatkan sistem tipe lebih sering daripada tidak karena ketika Anda mulai mengenali fungsi sebagai tipe daripada hanya objek / kelas / catatan sebagai tipe, Anda berakhir dengan banyak sekali kemampuan dan teknik baru. Ekspresi LINQ dan Lambda (atau daftar monad dan fungsi urutan yang lebih tinggi) hanyalah dua teknik hasil spesifik, yang masih banyak lagi.
Jimmy Hoffa

Jawaban:

15

Keterbacaan kode sangat subjektif . Karena itu, orang yang berbeda akan menganggap kode yang sama dapat dibaca atau tidak dapat dibaca.

Suatu tugas, x = x + 1kedengarannya aneh bagi seorang ahli matematika, karena suatu tugas tampak mirip dengan perbandingan.

Pola desain OOP sederhana akan sama sekali tidak jelas untuk seseorang yang tidak terbiasa dengan pola-pola ini. Pertimbangkan singleton . Seseorang akan bertanya, "Mengapa saya memerlukan konstruktor pribadi? Apa metode misteriusnya getInstance() ? Mengapa kita tidak membuat variabel global dan menetapkan objek di sana?"

Hal yang sama berlaku untuk kode FP. Kecuali Anda tahu pola logis di balik layar, akan sangat sulit bahkan untuk memahami sesuatu yang sangat mendasar, misalnya bagaimana meneruskan fungsi sebagai argumen ke fungsi lain.

Karena itu, orang harus memahami bahwa FP bukan peluru perak. Ada banyak aplikasi di mana FP akan sulit untuk diterapkan dan oleh karena itu, ini akan menyebabkan kode yang lebih mudah dibaca .

bytebuster
sumber
Orang harus menciptakan sesuatu yang mirip dengan diri mereka sendiri (kemanusiaan). Misalnya bahkan dalam visi komputer kita memiliki jaring saraf sekarang. Tubuh manusia terdiri dari objek, atribut, metode dan kami menggambarkan hal-hal lain menggunakan objek, atribut, metode. Jadi pemrograman fungsional tidak masuk akal
user25
12

Jawaban singkat:

Salah satu elemen yang membuat orang mengatakan bahwa kode pemrograman fungsional sulit dibaca adalah memberikan preferensi pada sintaksis yang lebih ringkas.

Jawaban panjang:

Pemrograman fungsional itu sendiri tidak dapat dibaca atau tidak dapat dibaca, karena ini adalah paradigma, bukan gaya penulisan kode. Dalam C # misalnya, pemrograman fungsional terlihat seperti:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

dan akan dianggap dapat dibaca oleh setiap orang dengan pengalaman yang cukup di Java, C # atau bahasa serupa.

Sintaks bahasa, di sisi lain, lebih kompak untuk banyak bahasa fungsional (termasuk Haskell dan F #) dibandingkan dengan bahasa OOP populer, memberikan preferensi pada simbol daripada kata dalam bahasa Inggris sederhana.

Ini juga berlaku untuk bahasa di luar FP. Jika Anda membandingkan bahasa OOP populer dengan beberapa bahasa yang kurang populer yang cenderung menggunakan lebih banyak kata bahasa Inggris, yang terakhir akan terasa lebih mudah dipahami bagi orang-orang yang tidak memiliki pengalaman pemrograman.

Membandingkan:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

untuk:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

Di jalan yang sama:

var a = ((b - c) in 1..n) ? d : 0;

dapat diekspresikan dalam bahasa imajiner sebagai:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

Kapan sintaks yang lebih pendek lebih baik?

Meskipun sintaksis yang lebih banyak lebih mudah dipahami oleh pemula, sintaksis yang lebih ringkas lebih mudah bagi pengembang yang berpengalaman. Kode yang lebih pendek berarti lebih sedikit karakter yang harus diketik, yang berarti lebih banyak produktivitas.

Terutama, itu benar-benar tidak masuk akal memaksa seseorang untuk mengetikkan kata kunci untuk menunjukkan sesuatu yang dapat disimpulkan dari sintaksis.

Contoh:

  • Di PHP Anda perlu mengetik functionsebelum setiap fungsi atau metode, tanpa alasan khusus untuk melakukannya.

  • Ada selalu membuatku ngeri karena memaksa para pengembang mengetik banyak kata-kata bahasa Inggris, terutama karena tidak ada IDE yang benar dengan pelengkapan otomatis. Saya belum menggunakan Ada baru-baru ini dan tutorial resmi mereka turun jadi saya tidak bisa memberikan contoh; jika ada yang punya contoh, silakan memodifikasi jawaban saya.

  • Sintaksnya 1..n, yang digunakan dalam banyak FP (dan Matlab), dapat diganti oleh between 1, natau between 1 and natau between (1, n). Kata betweenkunci membuatnya lebih mudah dimengerti bagi orang yang tidak terbiasa dengan sintaksis bahasa, tetapi tetap saja, dua titik lebih cepat untuk diketik.

Arseni Mourzenko
sumber
8
Saya setuju dengan sentimen, tetapi untuk alasan yang berbeda. Ini bukan tentang seberapa mudah seorang ahli dapat menulis kode, karena kode umumnya dibaca jauh lebih sering daripada yang ditulis. Kode yang lebih pendek juga dapat membantu keterbacaan, dengan tidak membuang waktu yang berharga, ruang layar, dan kapasitas mental jika sesuatu sudah jelas dari indikator yang lebih pendek (misalnya, baris baru alih-alih titik koma, keduanya kebetulan juga). Hal ini juga dapat menyakiti ketika menjadi terlalu samar (misalnya, saya lebih memilih for x in xslebih for x xs, karena membantu saya membedakan variabel loop dan kontainer).
Banyak orang yang saya temukan mengeluh tentang FP mengeluh tentang cuplikan C # yang Anda cantumkan seperti yang Anda katakan, itu juga merupakan contoh FP. Mungkin ini lebih merupakan masalah kolega saya daripada keterbacaan jika sebagian besar orang OOP menemukan bahwa potongan dapat dibaca, meskipun saya tidak sepenuhnya yakin sebagian besar orang OOP melakukan dari pengalaman saya .. jadi mengapa saya merasa sangat tidak yakin tentang topik ini.
Jimmy Hoffa
@Jimmy Hoffa: Lihat programmers.stackexchange.com/a/158721/6605 di mana saya membahas potongan C # dan bagaimana hal itu dirasakan oleh programmer pemula.
Arseni Mourzenko
1
@Sergiy: di Jawa atau C #, tanda tangan metode tidak memiliki methodkata kunci di dalamnya. Contoh: public int ComputePrice(Product product). Menambahkan kata kunci seperti itu, seperti yang dilakukan PHP, hanya menambah kekacauan alih-alih membuat hal-hal lebih mudah dibaca. Jika seorang programmer tidak dapat memahami bahwa suatu fungsi adalah fungsi dari tanda tangannya, baik programmer ini tidak memiliki pengalaman apa pun, atau kodenya jauh lebih tidak dapat dibaca daripada kode bagian terburuk yang pernah saya lihat.
Arseni Mourzenko
1
@Sergiy: ada beberapa kasus di mana verbosity dapat membantu (jika tidak, kita akan melihat bahasa dan kode seperti p i ComputePrice(product): _.unitPrice * ~.cart[_]), tetapi beberapa bahasa mendorongnya terlalu jauh. Contoh functionkata kunci yang berlebihan dalam PHP adalah contoh yang baik.
Arseni Mourzenko
6

Saya pikir salah satu alasannya adalah bahwa pemrograman fungsional cenderung bekerja dengan konsep yang jauh lebih abstrak. Ini membuat kode lebih pendek dan lebih mudah dibaca untuk orang yang tahu dan memahami konsep-konsep (karena mereka dengan tepat mengekspresikan esensi masalah), tetapi itu tidak dapat dibaca untuk orang-orang yang tidak terbiasa dengan mereka.

Sebagai contoh, untuk seorang programmer fungsional adalah wajar untuk menulis kode yang dapat gagal pada titik yang berbeda dalam Maybemonad, atau Eithermonad. Atau, untuk menulis perhitungan stateful dengan bantuan Statemonad. Tetapi bagi seseorang yang tidak memahami konsep monad, ini semua tampak seperti semacam sihir hitam.

Jadi saya pikir itu akan masuk akal untuk menggunakan bit pemrograman fungsional bahkan dalam tim orang-orang OOP, asalkan orang menggunakan konsep yang mudah dipahami atau dipelajari, seperti memetakan koleksi dengan fungsi atau penutupan .

(Dan tentu saja, itu juga tergantung pada programmer yang menulis beberapa kode. Anda dapat menulis kode yang sangat tidak dapat dibaca dalam bahasa apa pun, serta Anda dapat menulis dengan gaya yang bagus dan bersih.)

Petr Pudlák
sumber
2

Keterbacaan tidak ada hubungannya dengan paradigma, model dan semacamnya. Semakin banyak kode yang mencerminkan semantik domain masalah Anda, semakin banyak mengoperasikan terminologi dan idiom dari domain masalah seperti itu, semakin mudah dibaca.

Ini adalah alasan mengapa kode OOP tidak dapat dibaca sama sekali: tidak banyak masalah dunia nyata yang diekspresikan secara alami dalam hal taksonomi hierarkis. Obyek saling menyampaikan pesan adalah konsep yang aneh, dan sangat jauh dari sesuatu yang "nyata". Anehnya, ada banyak konsep dunia nyata yang secara alami dapat dipetakan ke idiom fungsional. Masalah cenderung didefinisikan secara deklaratif, oleh karena itu solusi deklaratif lebih alami.

Meskipun, ada banyak semantik lain yang bisa lebih dekat ke dunia nyata daripada fungsional murni, OOP murni, aliran data murni atau murni apa pun yang pernah ada. Dan karena fakta ini, pendekatan berorientasi bahasa untuk pemecahan masalah menghasilkan kode yang paling mudah dibaca, mengalahkan semua paradigma "murni" yang ada. Dengan bahasa khusus domain, setiap masalah diekspresikan dalam terminologi alaminya sendiri. Dan bahasa fungsional sedikit lebih baik daripada hal-hal utama OOP dalam memfasilitasi implementasi DSL (walaupun, pendekatan yang jauh lebih baik tersedia).

Logika SK
sumber
1

Keterbacaan kode bersifat subyektif. Saya yakin beberapa orang mengkritiknya karena kurang pengertian. Ada beberapa idiom yang berbeda dalam cara pola umum diimplementasikan. Misalnya, pola Pengunjung tidak terlalu masuk akal dalam bahasa dengan pencocokan pola .

Ketik inferensi dapat menjadi fitur yang rumit. Biasanya, ini adalah akselerator pembangunan yang hebat, namun, terkadang sulit untuk mengetahui jenis apa yang terlibat karena kurangnya konteks yang menyebabkan kesalahan membingungkan. Ini tidak terbatas pada apa bahasa Pemrograman Fungsional - Saya sudah melihatnya di template C ++ juga!

Bahasa modern cenderung multi-paradigma . Ini termasuk C # dan F #. Dimungkinkan untuk menulis gaya fungsional dalam C # dan gaya imperatif dalam F #. Orang yang sama yang mengkritik bahasa Fungsional mungkin menulis kode fungsional dalam bahasa berorientasi objek mereka.

Pengembangan komersial dalam bahasa Fungsional masih relatif belum matang. Saya telah melihat sejumlah kesalahan yang dianggap buruk dalam bahasa apa pun. Seperti:

  1. Mengubah gaya saat Anda mempelajari bahasa (dan bukan refactoring) yang mengarah ke inkonsistensi.
  2. Terlalu banyak dalam satu file.
  3. Terlalu banyak pernyataan dalam satu baris.
Dave Hillier
sumber
Mengenai kesalahan saya juga akan menambahkan: 4. Terlalu sering menggunakan simbol, misalnya: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Fitur implisit: deklarasi / kata kunci / pernyataan opsional, konversi implisit, dll .;
Sergiy Sokolenko