7 petua mengenai cara membuat perpustakaan Kotlin anda bersinar

Pengantar

Apabila kita memulakan pengaturcaraan dalam bahasa baru, pada mulanya kita sering berpegang pada paradigma dan kebiasaan yang dibangunkan semasa pengaturcaraan dalam bahasa yang kita sudah tahu. Walaupun ia mungkin kelihatan baik pada mulanya, bagi orang yang memprogram dalam bahasa yang anda cuba menguasai seketika kekasaran ini cukup jelas.

Apabila saya baru sahaja beralih dari Jawa ke Kotlin sekitar 2 tahun lalu, saya pada dasarnya melakukan "pengaturcaraan Java tetapi di Kotlin". Walaupun Kotlin seperti hawa nafas segar bagi saya, sebagai Jurutera Android saya menggunakan semua fungsi lanjutan dan kelas data nitty-gritty dan tidak selalu konsisten. Saya telah menukar kod Java sedia ada ke Kotlin dan melihatnya selepas beberapa waktu membantu saya menyimpan beberapa idea dalam minda apabila saya merangka API untuk komponen atau perpustakaan yang boleh diguna semula di Kotlin.

Di sini di BUX, kami sedang menjalankan dua aplikasi yang mempunyai beberapa perpustakaan bersama. Walaupun aplikasi Stok (yang belum dikeluarkan) ditulis di Kotlin dari awal, permohonan CFD pertama ditulis di Jawa dan kemudian ditukar ke Kotlin setelah beberapa saat. Pada masa ini, aplikasi CFD adalah 78.7% Kotlin, yang bermaksud kita masih mengusahakannya dan itulah sebabnya penting untuk memberi perhatian kepada API perpustakaan yang dikekalkan oleh dua pasukan yang menggunakan kedua-dua Java dan Kotlin pada masa yang sama.

Jadi jika anda mempunyai Kotlin atau perpustakaan Java sedia ada yang anda ingin Kotlinify atau anda merancang API menggunakan Kotlin dari awal, beri saya beberapa idea tentang apa yang anda boleh lakukan untuk menjadikan kehidupan pengguna perpustakaan lebih mudah.

1. Fungsi sambungan

Kebanyakan masa apabila anda perlu memanjangkan kelas sedia ada dengan fungsi baru anda sama ada menggunakan komposisi atau mendapatkan kelas baru (yang, jika digunakan secara meluas, boleh menjadikan hierarki kelas anda sebagai rapuh seperti cawan kaca dari IKEA). Tidak kira apa keistimewaan anda, Kotlin mempunyai jawapannya sendiri, yang dipanggil fungsi Sambungan. Ringkasnya, ia membolehkan anda menambah fungsi baru kepada kelas yang sedia ada dengan sintaks yang cukup kemas. Di Android, sebagai contoh, anda boleh menentukan kaedah baru untuk Lihat kelas dengan cara berikut:

Memandangkan perkara ini, banyak perpustakaan yang menyediakan fungsi tambahan untuk kelas sedia ada (egView, Context dll), bukannya menggunakan penghias, kaedah kilang statik atau sesuatu yang berbeza boleh mendapat manfaat daripada menyediakan fungsi mereka sebagai fungsi Sambungan dengan lancar, seolah-olah ini fungsi akan wujud dalam kelas asal dari awal.

2. Nilai hujah lalai

Kotlin pada asalnya direka untuk menjadi versi ringkas, kemas dan kemas Jawa dan ternyata ia berfungsi dengan baik dengan nilai argumen fungsi lalai. Pembekal API dapat menentukan nilai lalai untuk argumen yang boleh ditinggalkan. Saya akan benar-benar terkejut jika anda tidak melihat kod yang serupa semasa bekerja dengan SQLite di Android:

Walaupun terdapat lebih banyak kelemahan dalam kaedah ini daripada yang tidak jelas pada akhir, saya di sini bukan untuk menilai tetapi untuk mengatakan bahawa masa-masa ini telah hilang dan saya akan serius mempersoalkan kod yang ditulis dengan cara ini di Kotlin. Terdapat banyak contoh seperti ini tetapi, mujurlah, kita boleh berbuat lebih baik sekarang dan jika anda membekalkan API luaran dengan parameter penalaan tertentu, bukannya, atau sebagai tambahan untuk menyediakan Builder, pertimbangkan untuk menggunakan nilai hujah lalai. Ini akan mempunyai sekurang-kurangnya dua kelebihan: pertama sekali, anda tidak akan memaksa pengguna untuk menentukan parameter pilihan atau apa sahaja yang boleh anda peramal terlebih dahulu dan yang kedua ialah pengguna akan mempunyai konfigurasi lalai yang hanya akan bekerja out-of-the -kotak:

Juga, perkara yang baik untuk disenaraikan di sini adalah jika anda meletakkan argumen tersebut dengan nilai lalai pada akhirnya, pengguna tidak perlu menentukan nama untuk parameter mandatori.

3. Objek

Adakah anda pernah melaksanakan corak Singleton di Java sendiri? Anda mungkin ada dan jika demikian, anda harus tahu betapa sukarnya ia kadang-kadang:

Terdapat perlaksanaan yang berlainan dengan kebaikan dan keburukan masing-masing. Kotlin alamat semua 50 warna pola pelaksanaan Singleton dengan satu struktur tunggal yang disebut perisytiharan objek. Lihatlah, tiada "penguncian dua kali":

Apa yang keren mengenainya selain daripada sintaks adalah inisialisasi objek pengisytiharan kedua-dua benang selamat dan diinisikan malas apabila diakses buat kali pertama:

Bagi perpustakaan seperti Fabric, Glide, Picasso atau mana-mana yang menggunakan contoh tunggal objek sebagai titik masuk utama kepada API pustaka keseluruhan, ia adalah cara semula jadi untuk pergi sekarang dan tidak ada sebab untuk menggunakan cara Java lama untuk melakukan perkara yang sama.

4. Fail sumber

Dengan cara yang sama Kotlin memikirkan semula banyak cabaran sintaksis yang kita hadapi setiap hari, dan juga memikirkan semula cara kita menyusun kod yang kita buat. Fail-fail sumber Kotlin berfungsi sebagai rumah bagi pelbagai deklarasi yang sememangnya hampir satu sama lain. Ternyata mereka adalah tempat yang sempurna untuk menentukan beberapa fungsi sambungan yang berkaitan dengan kelas yang sama. Lihat coretan ringkas ini dari kod sumber Kotlin, di mana semua fungsi lanjutan yang digunakan untuk memanipulasi teks terletak dalam fail yang sama "Strings.kt":

Satu lagi contoh yang sesuai penggunaannya ialah menentukan protokol komunikasi dengan API anda bersama-sama dengan kelas data dan antara muka dalam satu fail sumber tunggal. Ia akan membolehkan pengguna tidak kehilangan tumpuan dengan menukar antara fail yang berbeza semasa mengikuti aliran:

Tetapi jangan terlalu jauh dengannya kerana anda berisiko untuk membanjiri pengguna dengan saiz fail dan mengubahnya menjadi kelas RecyclerView dengan talian ~ 13.000 .

5. Coroutines

Sekiranya pustaka anda menggunakan pelbagai benang untuk mengakses rangkaian atau melaksanakan kerja lama yang lain, pertimbangkan untuk menyediakan API dengan fungsi yang menggantung. Bermula dari Kotlin 1.3 coroutines tidak lagi eksperimen lagi yang merupakan peluang besar untuk mula menggunakannya dalam pengeluaran jika anda telah ragu-ragu sebelum ini. Coroutines dalam beberapa kes mungkin menjadi alternatif yang baik kepadaObservable dari RxJava dan cara lain untuk menangani panggilan asynchronous. Apa yang mungkin anda lihat sebelum ini adalah API yang penuh dengan kaedah dengan panggilan balik hasil atau pada masa gembar Rx dibungkus dengan Single atau Completable:

Tetapi kita kini berada di era Kotlin supaya ia dapat direka untuk memihak kepada penggunaan coroutines juga:

Walaupun fakta bahawa coroutines melakukan lebih baik daripada benang Jawa lama yang baik dari segi menjadi lebih ringan, mereka menyumbang dengan ketara kepada kebolehbacaan kod:

6. Kontrak

Bersama dengan corak yang stabil, Kotlin 1.3 juga memperkenalkan pemaju cara untuk berinteraksi dengan pengkompil. Kontrak merupakan ciri baru yang membolehkan kami sebagai pemaju perpustakaan untuk berkongsi dengan pengkompil pengetahuan yang kami ada dengan menyatakan kesan yang dipanggil. Untuk menjadikannya lebih mudah untuk memahami apa kesannya, mari kita membawa analogi yang paling dekat dari Jawa. Kebanyakan anda mungkin telah melihat atau menggunakan Kelas pra-syarat dari Guava dengan banyak pernyataan dan penyesuaiannya dalam perpustakaan seperti Dagger yang tidak mahu mengambil seluruh perpustakaan sama sekali:

Sekiranya objek rujukan yang diluluskan adalah batal maka kaedah tersebut akan membuang pengecualian dan baki kod yang diletakkan selepas kaedah ini tidak dapat dicapai, dengan itu kita boleh dengan selamat menganggap bahawa rujukan tidak akan dibatalkan di sana. Di sini masalahnya - walaupun kita mempunyai pengetahuan ini, ia tidak membantu pengkompil untuk melakukan asumsi yang sama. Ini adalah di mana @ Nullable dan @ NotNull anotasi datang ke tempat kejadian kerana mereka semata-mata wujud untuk membantu pengkompil memahami keadaan. Ini adalah kesan yang sebenarnya - ia adalah petunjuk kepada pengkompil yang membantu untuk melakukan analisis kod yang lebih canggih. Kesan yang sedia ada yang telah anda lihat di Kotlin adalah pintar-jenis jenis tertentu dalam blok selepas memeriksa jenisnya:

Pengkompil Kotlin sudah pintar dan tidak ragu-ragu ia akan terus bertambah baik pada masa depan tetapi dengan pengenalan Kontrak, pemaju Kotlin memberi kami pemaju perpustakaan kuasa untuk meningkatkannya dengan menulis pemula pintar kita sendiri dan membuat kesan yang membantu pengguna kami untuk tulis kod cleaner. Sekarang, mari kita tulis semula kaedah checkNotNul di Kotlin menggunakan Kontrak untuk menunjukkan keupayaan mereka:

Terdapat kesan yang berbeza juga tetapi ini bukan pengenalan penuh kepada Kontrak dan saya berharap ia memberi anda gambaran tentang bagaimana anda boleh mendapat manfaat daripadanya. Di samping itu, repositori stdlib di Github mempunyai banyak contoh Kontrak berguna yang bernilai semak.

Dengan kuasa besar datang tanggungjawab yang besar dan Kontrak bukan pengecualian. Apa sahaja yang anda nyatakan dalam Kontrak anda dirawat oleh pengkompil sebagai Holy Bible. Lebih terperinci pengkompil tidak mempersoalkan atau mengesahkan semua yang anda tulis di sana supaya anda perlu memeriksa dengan teliti kod anda sendiri dan pastikan anda tidak memperkenalkan sebarang ketidakkonsistenan.

Seperti yang mungkin anda perhatikan dari anotasi @ExperimentalContracts, Kontrak masih dalam fasa percubaan supaya bukan sahaja API mungkin berubah dari masa ke masa tetapi juga beberapa ciri baharu mungkin diterbitkan daripadanya kerana ia menjadi semakin matang.

7. Kesepakatan antara Java

Apa yang penting ketika menulis sebuah perpustakaan di Kotlin adalah untuk menjaga penonton yang lebih luas dengan menyediakan pengalaman integrasi lancar untuk pemaju sesama anda yang menggunakan Java. Ia amat penting kerana masih terdapat banyak projek yang melekat pada Java dan tidak mahu menulis semula kod sedia ada untuk pelbagai sebab. Oleh kerana kita mahu komuniti Kotlin berkembang dengan lebih cepat, lebih baik untuk membolehkan projek-projek itu dilakukan secara beransur-ansur, langkah demi langkah. Sudah tentu, ia bukan cerah di sisi The Wall tetapi, ada beberapa perkara yang anda boleh lakukan sebagai penyenggara perpustakaan.

Perkara pertama ialah fungsi sambungan Kotlin di Jawa akan disusun menjadi kaedah statik yang hodoh di mana argumen pertama kaedah itu adalah jenis penerima:

Walaupun anda tidak mempunyai banyak kawalan di sini, anda sekurang-kurangnya boleh menukar nama kelas yang dihasilkan dengan menambah baris berikut pada permulaan fail sumber yang mengandungi fungsi tahap pakej di atas:

Satu lagi contoh bagaimana anda boleh memberi kesan sedikit kepada kod yang dihasilkan berkaitan dengan penggunaan kaedah objek teman:

Anda boleh memaksa Kotlin untuk menghasilkan kelas statik di tempat fungsi yang ditakrifkan dalam objek rakan menggunakan @JvmStatic anotasi:

Berbanding dengan Kotlin, di Jawa dua fungsi dengan nama yang sama tetapi jenis generik yang berbeza tidak boleh didefinisi bersama kerana jenis pemadaman, sehingga ia dapat menjadi penunjukan bagi pengguna Java. Mudah-mudahan, anda boleh mengelakkannya dengan mengubah tandatangan kaedah dengan anotasi lain:

Dan yang terakhir tetapi paling tidak adalah keupayaan untuk menentukan pengecualian diperiksa dalam fungsi untuk pengguna Java walaupun mereka tidak tersedia secara langsung di Kotlin. Ini boleh menjadi berguna kerana paradigma pengecualian pengecualian di Jawa dan Kotlin berbeza:

Kebanyakan perkara di sini adalah pilihan tetapi mereka mungkin menjadi sumber kudos untuk perpustakaan anda dari pengguna Java anda.

Pokoknya

Kotlin adalah bahasa yang hebat yang sentiasa bergerak ke hadapan dan terdapat banyak perkara yang boleh anda lakukan mengenai perpustakaan untuk membuat penggunaannya lancar. Di antara semua yang anda gunakan dari idea-idea di atas, cuba menjadi pengguna di tempat pertama dan fikirkan apa yang anda suka dan bagaimana anda akan menggunakannya. Iblis adalah dalam butiran dan diharapkan, perkara-perkara kecil yang anda gunakan akan memberi manfaat kepada pengguna anda dan membuat pengalaman mereka lebih baik. Cheers!