Pengaturcaraan Berfungsi untuk Pembangun Android - Bahagian 1

Akhir-akhir ini, saya menghabiskan banyak masa untuk belajar Elixir, bahasa pengaturcaraan fungsional yang hebat dan mesra kepada pemula.

Ini membuat saya berfikir: mengapa tidak menggunakan beberapa konsep dan teknik dari dunia fungsional dalam pengaturcaraan Android?

Apabila kebanyakan orang mendengar istilah Pengaturcaraan Fungsional, mereka memikirkan catatan Berita Peretas yang memperdengarkan mengenai Monad, Fungsi Pesanan Tinggi dan Jenis Data Abstrak. Nampaknya ini adalah alam semesta mistik yang jauh dari tugas pengaturcara harian, yang hanya disediakan untuk penggodam terkuat dari alam NĂºmenor.

Baiklah, kacau itu ! Saya di sini untuk memberitahu anda bahawa anda juga boleh mempelajarinya. Anda juga boleh menggunakannya. Anda juga boleh membuat aplikasi yang cantik dengannya. Aplikasi yang mempunyai pangkalan data yang elegan dan mudah dibaca dan mempunyai lebih sedikit kesilapan.

Selamat Datang ke Pengaturcaraan Fungsional (FP) untuk pembangun Android. Dalam siri ini, kita akan mempelajari asas-asas FP dan bagaimana kita dapat menggunakannya di Java lama yang baik dan Kotlin baru yang hebat. Ideanya adalah untuk memastikan konsepnya tetap dipraktikkan dan mengelakkan sebilangan besar istilah akademik.

FP adalah subjek yang besar. Kami hanya akan mempelajari konsep dan teknik yang berguna untuk menulis kod Android. Kami mungkin melayari beberapa konsep yang tidak dapat kami gunakan secara langsung demi kelengkapan tetapi saya akan berusaha menyimpan bahan yang relevan mungkin.

Sedia? Mari pergi.

Apa itu Pengaturcaraan Fungsional dan mengapa saya harus menggunakannya?

Soalan yang baik. Istilah pengaturcaraan fungsional adalah payung untuk pelbagai konsep pengaturcaraan yang tidak wajar dilakukan oleh pengamat ini. Pada intinya, Ini adalah gaya pengaturcaraan yang memperlakukan program sebagai penilaian fungsi matematik dan mengelakkan keadaan dan kesan sampingan yang boleh berubah (kita akan membincangkannya secepat ini)

Pada intinya, FP menekankan:

  • Kod deklaratif - Pengaturcara harus bimbang tentang apa dan membiarkan penyusun dan masa berjalan bimbang tentang caranya .
  • Keterangan yang jelas - Kod harus jelas seperti yang mungkin. Khususnya, kesan sampinganharus diasingkan untuk mengelakkan kejutan. Aliran data dan pengendalian ralat didefinisikan secara eksplisit dan konstruk seperti pernyataan GOTO dan Pengecualian dielakkan kerana mereka dapat meletakkan aplikasi anda dalam keadaan yang tidak dijangka.
  • Concurrency - Sebilangan besar kod berfungsi serentak secara lalai kerana konsep yang dikenali sebagai kesucian berfungsi . Kesepakatan umum nampaknya sifat ini secara khusus menyebabkan pengaturcaraan fungsional meningkat populariti kerana inti CPU tidak semakin cepat setiap tahun seperti biasa (lihat undang-undang Moore) dan kita harus menjadikan program kita lebih serentak untuk mengambil kesempatan seni bina pelbagai teras.
  • Fungsi Tertinggi - Fungsi adalah ahli kelas pertama seperti semua bahasa primitif lain. Anda boleh meneruskan fungsi seperti tali atau int.
  • Kebolehubahan - Pemboleh ubah tidak boleh diubah setelah dimulakan. Setelah sesuatu dibuat, perkara itu akan kekal selama-lamanya. Sekiranya anda mahu ia berubah, anda membuat perkara baru. Ini adalah satu lagi aspek keterangan dan mengelakkan kesan sampingan. Sekiranya anda mengetahui bahawa sesuatu tidak boleh berubah, anda mempunyai keyakinan lebih banyak mengenai keadaannya semasa anda menggunakannya.

Kod Deklaratif, Eksplisit dan Serentak yang lebih senang difikirkan dan direka untuk mengelakkan kejutan? Saya harap saya berjaya menarik minat anda.

Dalam bahagian pertama siri ini, mari kita mulakan dengan beberapa konsep yang paling asas dalam FP: Kesucian , Kesan Sampingan dan Susunan .

Fungsi murni

Fungsi adalah suci jika outputnya hanya bergantung pada inputnya dan tidak mempunyai kesan sampingan (kita akan membincangkan sedikit kesan sampingan selepas ini). Mari kita lihat contohnya, kan?

Pertimbangkan fungsi ringkas ini yang menambah dua nombor. Ia membaca satu nombor dari fail dan nombor lain diteruskan sebagai parameter.

Jawa

int add(int x) { int y = readNumFromFile(); return x + y;}

Kotlin

fun add(x: Int): Int { val y: Int = readNumFromFile() return x + y}

Keluaran fungsi ini tidak bergantung sepenuhnya pada inputnya. Bergantung pada apa yang dikembalikan oleh readNumFromFile () , ia boleh mempunyai output yang berbeza untuk nilai x yang sama . Fungsi ini dikatakan tidak murni .

Mari ubah menjadi fungsi murni.

Jawa

int add(int x, int y) { return x + y;}

Kotlin

fun add(x: Int, y: Int): Int { return x + y}

Sekarang output fungsi hanya bergantung pada inputnya. Untuk x dan y yang diberikan , Fungsi akan selalu menghasilkan output yang sama. Fungsi ini kini dikatakan suci . Fungsi matematik juga beroperasi dengan cara yang sama. Output fungsi matematik hanya bergantung pada inputnya - Inilah sebabnya mengapa pengaturcaraan fungsional jauh lebih dekat dengan matematik daripada gaya pengaturcaraan biasa yang biasa kita gunakan.

PS Input kosong masih merupakan input. Sekiranya fungsi tidak memerlukan input dan mengembalikan pemalar yang sama setiap masa, fungsi tetap murni.

PPS Sifat selalu mengembalikan output yang sama untuk input tertentu juga dikenali sebagai ketelusan rujukan dan anda mungkin melihatnya digunakan ketika membicarakan fungsi murni.

Kesan sampingan

Mari kita terokai konsep ini dengan contoh fungsi penambahan yang sama. Kami akan mengubah fungsi penambahan untuk juga menuliskan hasilnya ke fail.

Jawa

int add(int x, int y) { int result = x + y; writeResultToFile(result); return result;}

Kotlin

fun add(x: Int, y: Int): Int { val result = x + y writeResultToFile(result) return result}

Fungsi ini sekarang menulis hasil pengiraan ke fail. iaitu sekarang mengubah keadaan dunia luar. Fungsi ini kini dikatakan mempunyai kesan sampingan dan bukan lagi fungsi murni.

Mana-mana kod yang mengubah keadaan dunia luar - mengubah pemboleh ubah, menulis ke fail, menulis ke DB, menghapus sesuatu dll - dikatakan mempunyai kesan sampingan.

Fungsi yang mempunyai kesan sampingan dielakkan dalam FP kerana tidak lagi murni dan bergantung pada konteks sejarah . Konteks kod tidak terkandung dalam diri. Ini menjadikan mereka lebih sukar untuk difikirkan.

Katakan anda menulis sekeping kod yang bergantung pada cache. Sekarang output kod anda bergantung pada sama ada seseorang menuliskan ke cache, apa yang ditulis di dalamnya, kapan ia ditulis, jika data itu berlaku dan lain-lain. Anda tidak dapat memahami apa yang sedang dilakukan oleh program anda kecuali anda memahami semua kemungkinan keadaan dari cache itu bergantung pada. Sekiranya anda memperluas ini untuk memasukkan semua perkara lain yang bergantung pada aplikasi anda - rangkaian, pangkalan data, fail, input pengguna dan sebagainya, menjadi sangat sukar untuk mengetahui apa sebenarnya yang berlaku dan memasukkan semuanya ke dalam kepala anda sekaligus.

Adakah ini bermakna kita tidak menggunakan rangkaian, pangkalan data dan cache? Sudah tentu tidak. Pada akhir pelaksanaan, anda mahu aplikasi melakukan sesuatu. Dalam kes aplikasi Android, biasanya bermaksud mengemas kini UI sehingga pengguna dapat memperoleh sesuatu yang berguna dari aplikasi kami.

Idea terhebat FP bukanlah untuk melepaskan sepenuhnya kesan sampingan tetapi untuk membendung dan mengasingkannya. Daripada aplikasi kita dipenuhi dengan fungsi yang mempunyai kesan sampingan, kita mendorong kesan sampingan ke pinggir sistem kita sehingga memberi kesan sekecil mungkin, menjadikan aplikasi kita lebih mudah difikirkan. Kami akan membincangkannya secara terperinci semasa kami meneroka seni bina fungsional untuk aplikasi kami dalam siri ini.

Memesan

Sekiranya kita mempunyai sekumpulan fungsi murni yang tidak mempunyai kesan sampingan, maka urutan pelaksanaannya menjadi tidak relevan.

Katakan kita mempunyai fungsi yang memanggil 3 fungsi murni secara dalaman:

Jawa

void doThings() { doThing1(); doThing2(); doThing3();}

Kotlin

fun doThings() { doThing1() doThing2() doThing3()}

Kami tahu pasti bahawa fungsi-fungsi ini tidak saling bergantung antara satu sama lain (kerana output dari satu bukan input yang lain) dan kami juga tahu bahawa mereka tidak akan mengubah apa-apa dalam sistem (kerana mereka suci). Ini menjadikan urutan pelaksanaannya dapat ditukar ganti.

Urutan pelaksanaan dapat diubah dan dioptimumkan untuk fungsi murni bebas. Perhatikan bahawa jika input doThing2 () adalah hasil dari doThing1 () maka ini harus dilaksanakan dengan teratur, tetapi doThing3 () masih dapat diperintahkan untuk dilaksanakan sebelum doThing1 ().

Apakah harta pesanan ini memberi kita? Bersamaan, itulah! Kita boleh menjalankan fungsi ini pada 3 teras CPU yang terpisah tanpa perlu risau apa-apa!

Dalam banyak kes, penyusun dalam bahasa fungsional murni yang maju seperti Haskell dapat mengetahui dengan secara rasmi menganalisis kod anda sama ada itu bersamaan atau tidak, dan dapat menghentikan anda daripada menembak diri sendiri dengan kebuntuan, keadaan perlumbaan dan seumpamanya. Pengkompilasi ini secara teorinya juga dapat secara automatik menyelaraskan kod anda (ini sebenarnya tidak ada di mana-mana penyusun yang saya tahu ketika ini tetapi penyelidikan sedang dijalankan).

Walaupun penyusun anda tidak melihat perkara ini, sebagai pengaturcara, ada baiknya anda mengetahui sama ada kod anda serentak hanya dengan melihat tandatangan fungsi dan mengelakkan bug berulir yang tidak menyenangkan cuba menyelaraskan kod penting yang mungkin penuh dengan tersembunyi kesan sampingan.

Ringkasan

Saya harap bahagian pertama ini menarik minat anda mengenai FP. Fungsi murni dan kesan sampingan menjadikannya lebih mudah untuk memikirkan kod dan merupakan langkah pertama untuk mencapai kesesuaian.

Sebelum kita mencapai persetujuan, kita harus belajar mengenai kebolehubahan . Kami akan melakukan perkara itu di Bahagian 2 siri ini dan melihat bagaimana fungsi dan kebolehubahan yang murni dapat membantu kami menulis kod serentak yang mudah dan mudah difahami tanpa menggunakan kunci dan bisu.

Baca seterusnya

Pengaturcaraan Berfungsi untuk pembangun Android - Bahagian 2

Sekiranya anda belum membaca bahagian 1, baca di sini: medium.com

Sekiranya anda menyukai ini, klik? di bawah. Saya perhatikan setiap satu dan saya bersyukur untuk setiap satu daripada mereka.

Untuk lebih banyak idea mengenai pengaturcaraan, ikuti saya sehingga anda akan diberitahu semasa saya menulis catatan baru.