Setelah mempelajari pemrograman fungsional dalam Haskell dan F #, paradigma OOP tampaknya terbelakang dengan kelas, antarmuka, objek. Aspek FP mana yang dapat saya bawa ke tempat kerja yang bisa dipahami rekan kerja saya? Apakah ada gaya KB yang layak untuk diajak bicara kepada bos saya tentang melatih kembali tim saya sehingga kami dapat menggunakannya?
Aspek yang mungkin dari KB:
- Kekekalan
- Aplikasi Parsial dan Kari
- Fungsi Kelas Pertama (pointer fungsi / Objek Fungsional / Pola Strategi)
- Evaluasi Malas (dan Monad)
- Fungsi Murni (tanpa efek samping)
- Ekspresi (vs. Pernyataan - setiap baris kode menghasilkan nilai alih-alih, atau selain menyebabkan efek samping)
- Pengulangan
- Pencocokan Pola
Apakah ini gratis untuk semua tempat kita dapat melakukan apa pun yang didukung oleh bahasa pemrograman hingga batas yang didukung oleh bahasa itu? Atau adakah pedoman yang lebih baik?
Jawaban:
Pemrograman fungsional adalah paradigma yang berbeda dari pemrograman berorientasi objek (pola pikir yang berbeda, dan cara berpikir yang berbeda tentang program). Anda mulai menyadari bahwa di sini ada lebih dari satu cara (berorientasi objek) untuk memikirkan masalah dan solusinya. Ada yang lain (pemrograman prosedural dan generik datang ke pikiran). Bagaimana Anda bereaksi terhadap pengetahuan baru ini, apakah Anda menerima dan mengintegrasikan alat dan pendekatan baru ini ke dalam keahlian Anda, akan menentukan apakah Anda tumbuh dan menjadi pengembang yang lebih lengkap dan terampil.
Kita semua terlatih untuk menangani dan merasa nyaman dengan tingkat kompleksitas tertentu. Saya suka menyebutnya batas hrair seseorang (dari Watership Down, seberapa tinggi Anda dapat menghitung). Merupakan hal yang hebat untuk memperluas pikiran Anda, kemampuan Anda untuk mempertimbangkan lebih banyak pilihan, dan memiliki lebih banyak alat untuk mendekati dan menyelesaikan masalah. Tetapi itu adalah perubahan, dan itu menarik Anda keluar dari zona nyaman Anda.
Satu masalah yang mungkin Anda temui adalah Anda menjadi kurang puas untuk mengikuti kerumunan "semuanya adalah objek". Anda mungkin harus mengembangkan kesabaran ketika Anda bekerja dengan orang-orang yang mungkin tidak mengerti (atau ingin memahami) mengapa pendekatan fungsional untuk pengembangan perangkat lunak bekerja dengan baik untuk masalah-masalah tertentu. Sama seperti pendekatan pemrograman generik bekerja dengan baik untuk masalah-masalah tertentu.
Semoga berhasil!
sumber
Pemrograman fungsional menghasilkan sangat praktis, sederhana, produktivitas dalam penulisan kode sehari-hari: beberapa fitur mendukung kesederhanaan, yang hebat karena semakin sedikit kode yang Anda tulis, semakin sedikit kegagalan yang Anda lakukan, dan semakin sedikit pemeliharaan yang diperlukan.
Menjadi ahli matematika, saya menemukan hal-hal fungsional yang mewah sangat menarik, tetapi biasanya berguna ketika merancang aplikasi: struktur ini dapat mengkodekan dalam struktur program banyak invarian dari program, tanpa mewakili invarian ini dengan variabel.
Kombinasi favorit saya mungkin terlihat sangat sepele, namun saya percaya itu memiliki dampak produktivitas yang sangat tinggi. Kombinasi ini adalah Aplikasi Parsial dan Currying dan Fungsi Kelas Pertama yang saya akan beri label ulang untuk for-loop lagi : alih-alih melewati tubuh loop ke fungsi iterasi atau pemetaan. Saya baru-baru ini disewa untuk pekerjaan C ++ dan saya perhatikan, saya benar-benar kehilangan kebiasaan menulis for-loop!
Kombinasi Rekursi dan Pencocokan Pola memusnahkan kebutuhan pola desain Pengunjung tersebut . Bandingkan saja kode yang Anda perlukan untuk memprogram seorang evaluator ekspresi boolean: dalam bahasa pemrograman fungsional apa pun ini harus sekitar 15 baris kode, dalam OOP hal yang benar untuk dilakukan adalah menggunakan pola desain Pengunjung tersebut , yang mengubah contoh mainan itu menjadi esai yang luas. Keuntungan sudah jelas dan saya tidak mengetahui adanya ketidaknyamanan.
sumber
list.forEach(System.out::println);
Dari sudut pandang FP pandang,println
adalah fungsi mengambil dua argumen, targetPrintStream
dan nilaiObject
tetapiCollection
'sforEach
metode mengharapkan fungsi dengan satu argumen hanya yang bisa diterapkan ke setiap elemen. Jadi argumen pertama terikat pada instance yang ditemukan dalamSystem.out
menghasilkan ke fungsi baru dengan satu argumen. Ini lebih sederhana daripadaBiConsumer<…> c=PrintStream::println; PrintStream a1=System.out; list.forEach(a2 -> c.accept(a1, a2));
Anda mungkin harus membatasi bagian mana dari pengetahuan Anda yang Anda gunakan di tempat kerja, cara Superman harus berpura-pura menjadi Clark Kent untuk menikmati fasilitas kehidupan normal. Tetapi mengetahui lebih banyak tidak akan pernah menyakiti Anda. Yang mengatakan, beberapa aspek Pemrograman Fungsional sesuai untuk toko Berorientasi Objek, dan aspek-aspek lain mungkin layak dibicarakan dengan bos Anda sehingga Anda dapat meningkatkan tingkat pengetahuan rata-rata toko Anda dan mendapatkan untuk menulis kode yang lebih baik sebagai hasilnya.
FP dan OOP tidak saling eksklusif. Lihatlah Scala. Beberapa orang berpikir itu adalah yang terburuk karena itu adalah FP yang tidak murni, tetapi beberapa berpikir itu yang terbaik untuk alasan yang sama.
Satu per satu, berikut adalah beberapa aspek yang bekerja sangat baik dengan OOP:
Pure Functions (tanpa efek samping) - Setiap bahasa pemrograman yang saya ketahui mendukung ini. Mereka membuat kode Anda jauh, lebih mudah untuk dipikirkan dan harus digunakan kapan pun praktis. Anda tidak harus menyebutnya FP. Sebut saja praktik pengkodean yang baik.
Kekekalan: String dapat dikatakan sebagai objek Java yang paling umum digunakan dan tidak dapat diubah. Saya membahas Immutable Java Objects dan Immutable Java Collections di blog saya. Beberapa di antaranya mungkin berlaku untuk Anda.
Fungsi Kelas Pertama (pointer fungsi / Objek Fungsional / Pola Strategi) - Java telah memiliki versi mutan yang pincang sejak versi 1.1 dengan sebagian besar kelas API (dan ada ratusan) yang mengimplementasikan antarmuka Listener. Runnable mungkin adalah objek fungsional yang paling umum digunakan. Fungsi Kelas Satu lebih berfungsi untuk mengkodekan dalam bahasa yang tidak mendukungnya secara asli, tetapi terkadang sepadan dengan usaha ekstra saat menyederhanakan aspek lain dari kode Anda.
Rekursi berguna untuk memproses pohon. Di toko OOP, itu mungkin merupakan penggunaan rekursi yang tepat dan tepat. Menggunakan rekursi untuk bersenang-senang di OOP mungkin harus disukai jika tanpa alasan lain daripada kebanyakan bahasa OOP tidak memiliki ruang stack secara default untuk membuat ini ide yang baik.
Ekspresi (vs Pernyataan - setiap baris kode menghasilkan nilai alih-alih, atau selain menyebabkan efek samping) - Satu-satunya operator evaluatif dalam C, C ++, dan Java adalah Operator Ternary . Saya membahas penggunaan yang sesuai di blog saya. Anda mungkin menemukan Anda menulis beberapa fungsi sederhana yang sangat dapat digunakan kembali dan evaluatif.
Malas Evaluasi (dan Monads) - sebagian besar terbatas pada inisialisasi malas di OOP. Tanpa fitur bahasa untuk mendukungnya, Anda mungkin menemukan beberapa API yang bermanfaat, tetapi menulis sendiri itu sulit. Maksimalkan penggunaan stream Anda - lihat antarmuka Writer dan Reader untuk contoh.
Aplikasi Parsial dan Kari - Tidak praktis tanpa fungsi kelas satu.
Pencocokan Pola - umumnya tidak disarankan dalam OOP.
Singkatnya, saya tidak berpikir pekerjaan harus menjadi gratis untuk semua tempat Anda dapat melakukan apa pun yang didukung oleh bahasa pemrograman hingga batas yang didukung oleh bahasa itu. Saya pikir keterbacaan oleh rekan kerja Anda harus menjadi tes lakmus Anda untuk kode yang dibuat untuk disewa. Di mana hal itu paling membuat Anda resah, saya ingin memulai pendidikan di tempat kerja untuk memperluas wawasan rekan kerja Anda.
sumber
public interface BiConsumer<T, U> { public void accept(T t, U u); }
Ada antarmuka fungsional lain yang berguna di java.util.fungsi.Most OOP languages don't have the stack space for it
Betulkah? Yang Anda perlukan hanyalah 30 level rekursi untuk mengelola milyaran node dalam pohon biner seimbang. Saya cukup yakin ruang stack saya cocok untuk banyak level lebih dari ini.Selain pemrograman fungsional dan pemrograman berorientasi objek, ada juga pemrograman deklaratif (SQL, XQuery). Mempelajari setiap gaya membantu Anda mendapatkan wawasan baru, dan Anda akan belajar memilih alat yang tepat untuk pekerjaan itu.
Tapi ya, bisa sangat frustasi untuk menulis kode dalam bahasa, dan tahu bahwa jika Anda menggunakan sesuatu yang lain, Anda bisa menjadi jauh lebih produktif untuk domain masalah tertentu. Namun, bahkan jika Anda menggunakan bahasa seperti Java, dimungkinkan untuk menerapkan konsep dari FP ke kode Java Anda, meskipun dengan cara bundaran. Kerangka kerja Guava misalnya melakukan beberapa hal ini.
sumber
Sebagai seorang programmer saya pikir Anda tidak boleh berhenti belajar. Yang mengatakan, sangat menarik bahwa belajar FP menodai keterampilan OOP Anda. Saya cenderung menganggap belajar OOP sebagai belajar cara mengendarai sepeda; Anda tidak pernah lupa bagaimana melakukannya.
Ketika saya mempelajari seluk beluk FP, saya mendapati diri saya berpikir lebih matematis dan mendapatkan perspektif yang lebih baik tentang cara saya menulis perangkat lunak. Itu pengalaman pribadi saya.
Ketika Anda mendapatkan lebih banyak pengalaman, konsep pemrograman inti akan jauh lebih sulit hilang. Jadi saya sarankan Anda santai di FP sampai konsep OOP benar-benar dipadatkan dalam pikiran Anda. FP adalah pergeseran paradigma yang pasti. Semoga berhasil!
sumber
Sudah ada banyak jawaban bagus, jadi pertanyaan saya akan menjawab sebagian pertanyaan Anda; yaitu, saya mengambil dasar pemikiran pertanyaan Anda, karena OOP dan fitur fungsional tidak saling eksklusif.
Jika Anda menggunakan C ++ 11, ada banyak fitur pemrograman fungsional yang dibangun ke perpustakaan bahasa / standar yang bersinergi (cantik) dengan OOP. Tentu saja, saya tidak yakin seberapa baik TMP akan diterima oleh bos atau rekan kerja Anda, tetapi intinya adalah Anda bisa mendapatkan banyak fitur ini dalam beberapa bentuk dalam bahasa non-fungsional / OOP, seperti C ++.
Menggunakan template dengan waktu rekursi kompilasi bergantung pada 3 poin pertama Anda,
Dalam nilai template yang tidak dapat diubah (konstanta waktu kompilasi), setiap iterasi dilakukan menggunakan rekursi, dan percabangan dilakukan menggunakan (lebih atau kurang) pencocokan pola, dalam bentuk resolusi kelebihan beban.
Adapun poin lainnya, menggunakan
std::bind
danstd::function
memberi Anda aplikasi fungsi parsial, dan pointer fungsi adalah bawaan untuk bahasa. Objek yang bisa dipanggil adalah objek fungsional (serta aplikasi fungsi parsial). Perhatikan bahwa dengan objek yang dapat dipanggil, maksud saya objek yang menentukannyaoperator ()
.Evaluasi malas dan fungsi murni akan sedikit lebih sulit; untuk fungsi murni, Anda dapat menggunakan fungsi lambda yang hanya menangkap berdasarkan nilai, tetapi ini tidak ideal.
Terakhir, inilah contoh penggunaan rekursi kompilasi-waktu dengan aplikasi fungsi parsial. Ini adalah contoh yang agak dibuat-buat, tetapi menunjukkan sebagian besar poin di atas. Itu akan secara rekursif mengikat nilai-nilai dalam tuple yang diberikan ke fungsi yang diberikan dan menghasilkan objek fungsi (callable)
sumber