7 padomi, kā padarīt jūsu Kotlinas bibliotēku mirdzošu

Priekšvārds

Sākot programmēšanu jaunā valodā, sākumā mēs bieži pieturējamies pie paradigmām un paradumiem, kas izveidoti, programmējot valodā, kuru mēs jau zinām. Lai arī sākumā tas varētu šķist labi, cilvēkiem, kuri kādu laiku programmē valodā, kuru jūs mēģināt apgūt, šis nelīdzenums ir diezgan acīmredzams.

Kad pirms apmēram 2 gadiem es tikko pārslēdzos no Java uz Kotlin, es pamatā nodarbojos ar “Java programmēšanu, bet Kotlinā”. Kaut arī Kotlins man bija kā svaiga gaisa elpa, es kā Android inženieris izmantoju visas šīs nepatīkamās pagarinājuma funkcijas un datu klases, un tas ne vienmēr bija konsekvents. Es konvertēju esošo Java kodu uz Kotlin un apskatīju to pēc kāda laika man palīdzēja paturēt prātā dažas idejas, kad es izstrādāju API dažādiem atkārtoti lietojamiem komponentiem vai bibliotēkām Kotlinā.

Šeit, BUX, mēs strādājam pie divām lietojumprogrammām, kurām ir pāris kopīgas bibliotēkas. Kamēr Stocks lietojumprogramma (kas vēl nav izlaista) Kotlinā tika rakstīta jau no paša sākuma, pirmā CFD lietojumprogramma tika uzrakstīta Java valodā un pēc kāda laika tika pārveidota par Kotlin. Šobrīd CFD lietojumprogramma ir 78,7% Kotlin, kas nozīmē, ka mēs joprojām strādājam pie tā, un tāpēc ir svarīgi pievērst uzmanību bibliotēkas API, kuras uztur divas komandas, kuras vienlaikus izmanto gan Java, gan Kotlin.

Tātad, ja jums jau ir Kotlin vai Java bibliotēka, kuru vēlaties Kotlinificēt, vai arī jūs projektējat API, izmantojot Kotlin no nulles, ņemiet vērā man dažas idejas par to, ko jūs varat darīt, lai atvieglotu jūsu bibliotēkas lietotāju dzīvi.

1. Paplašināšanas funkcijas

Lielāko daļu laika, kad jums ir jāpaplašina esošā klase ar jaunu funkcionalitāti, jūs vai nu izmantojat kaut kādu kompozīciju, vai atvasināt jaunu klasi (kas plašas izmantošanas gadījumā var padarīt jūsu klases hierarhiju tik trauslu kā IKEA stikla krūzes). Neatkarīgi no tā, kāda ir jūsu izvēle, Kotlinai ir sava atbilde uz to, ko sauc par paplašināšanas funkcijām. Īsumā tas ļauj esošajai klasei pievienot jaunu funkciju ar diezgan glītu sintakse. Piemēram, operētājsistēmā Android Android varat definēt jaunu skata klases metodi šādā veidā:

Paturot to prātā, daudzām bibliotēkām, kas esošajām klasēm nodrošina papildu funkcionalitāti (piem., Skats, konteksts utt.), Tā vietā, lai izmantotu dekoratorus, statiskas rūpnīcas metodes vai kaut ko citu, var gūt labumu, ja to funkcionalitāte tiek nodrošināta kā paplašinājuma funkcijas vienlaidus, it kā tas funkcionalitāte pastāvētu sākotnējās klasēs no paša sākuma.

2. Arhīva noklusējuma vērtības

Kotlin sākotnēji tika veidota kā kodolīga, glīta un sakopta Java versija, un izrādās, ka tas to dara ļoti labi ar noklusējuma funkcijas argumenta vērtībām. API nodrošinātājs var norādīt noklusējuma vērtības argumentiem, kurus varētu izlaist. Es būtu patiesi pārsteigts, ja, strādājot ar SQLite operētājsistēmā Android, jūs nebūtu redzējis līdzīgu kodu:

Lai arī šajā metodē ir vairāk trūkumu nekā neglītajā nulles beigās, es šeit nemāku spriest, bet drīzāk saku, ka šie laiki ir pagājuši, un es nopietni apšaubīšu kodu, kas šādā veidā uzrakstīts Kotlīnā. Ir daudz tādu piemēru, kā šis, bet, par laimi, mēs tagad varam rīkoties labāk un ja piegādājat ārēju API ar noteiktiem skaņošanas parametriem, nevis Builder piedāvāšanai vai papildus tam, apsveriet iespēju izmantot noklusējuma argumenta vērtības. Tam būs vismaz divas priekšrocības: pirmkārt, jūs nepiespiedīsit lietotāju norādīt izvēles parametrus vai jebko citu, ko jūs varat iepriekš paredzēt, un, otrkārt, lietotājam būs noklusējuma konfigurācija, kas vienkārši darbosies ārpus tā. -kastē:

Jāatzīmē arī laba lieta, ja beigās ievietojat šos argumentus ar noklusējuma vērtībām, lietotājam nevajadzēs norādīt obligāto parametru nosaukumus.

3. Objekti

Vai jums kādreiz pašam bija jāievieš Singleton shēma Java? Jums, iespējams, bija, un ja tā, tad jums vajadzētu zināt, cik apgrūtinoši tas dažreiz varētu būt:

Ir dažādas ieviešanas, kurām ir savi plusi un mīnusi. Kotlin pievēršas visiem šiem 50 Singleton modeļa ieviešanas toņiem ar vienotu struktūru, ko sauc par objekta deklarāciju. Izskaties ma, nav “divreiz pārbaudītas bloķēšanas”:

Jauki, izņemot sintaksi, ir tas, ka objekta deklarācijas inicializēšana ir droša pavedieniem un tiek inicializēta, kad tai pirmo reizi piekļūst:

Tādām bibliotēkām kā Fabric, Glide, Picasso vai jebkurai citai, kas kā atsevišķu objekta eksemplāru izmanto kā galveno ieejas punktu kopējai bibliotēkas API, tas ir dabisks veids, kā iet tagad, un nav iemesla izmantot veco Java veidu, lai dari tās pašas lietas.

4. Avota faili

Tieši tāpat Kotlin pārdomā daudz sintaktisko izaicinājumu, ar kuriem mēs ikdienā saskaramies, tas arī pārdomā veidus, kā mēs organizējam izveidoto kodu. Kotlin avota faili kalpo kā mājvieta vairākām deklarācijām, kas ir semantiski tuvu viena otrai. Izrādās, ka tās ir ideāla vieta, lai definētu dažas paplašināšanas funkcijas, kas saistītas ar to pašu klasi. Apskatiet šo vienkāršoto fragmentu no Kotlin avota koda, kur visas teksta manipulēšanai izmantotās paplašinājumu funkcijas atrodas tajā pašā failā “Strings.kt”:

Vēl viens piemērots tā izmantošanas piemērs ir saziņas protokola ar jūsu API definēšana kopā ar datu klasēm un saskarnēm vienā avota failā. Tas ļaus lietotājam nezaudēt fokusu, pārslēdzoties starp dažādiem failiem, sekojot plūsmai:

Nepārlieciet to pārāk tālu, jo jūs riskējat apbēdināt lietotāju ar faila lielumu un pārvērst to RecyclerView klasē ar ~ 13.000 rindām lines .

5. Kārtība

Ja jūsu bibliotēka izmanto vairākus pavedienus, lai piekļūtu tīklam vai veiktu jebkuru citu ilgstošu darbu, apsveriet iespēju nodrošināt API ar apturēšanas funkcijām. Sākot no Kotlin 1.3, sākumstadijas vairs nav eksperimentālas, un tā ir lieliska iespēja tos sākt izmantot ražošanā, ja par to iepriekš esat šaubījies. Kārtība dažos gadījumos varētu būt laba alternatīva novērojamajam no RxJava un citiem veidiem, kā rīkoties ar asinhronajiem zvaniem. Tas, ko jūs, iespējams, jau redzējāt, ir API pilna ar metodēm ar rezultātu atzvanīšanu vai Rx hype laikā, kas ietīta ar vienu vai pabeigtu:

Bet tagad mēs atrodamies Kotlinas laikmetā, tāpēc to varētu izveidot arī par labu korutīnu lietošanai:

Neskatoties uz to, ka korutīni darbojas labāk nekā vecie labie Java pavedieni, ņemot vērā to, ka tie ir vieglāki, tie ievērojami veicina koda lasāmību:

6. Līgumi

Kopā ar stabilām pamatprogrammām Kotlin 1.3 arī izstrādātājiem piedāvā iespēju mijiedarboties ar kompilatoru. Līgums ir jauna funkcija, kas ļauj mums kā bibliotēku izstrādātājiem dalīties ar apkopotāju zināšanās, kas mums ir, norādot tā sauktos efektus. Lai būtu vieglāk saprast, kāds ir efekts, tuvākās analogijas atnesīsim no Java. Lielākā daļa no jums, iespējams, ir redzējuši vai pat izmantojuši priekšnosacījumu klasi no Gvajavas ar daudziem apgalvojumiem un tās pielāgošanu tādās bibliotēkās kā Dagger, kuras nevēlas ielādēt visu bibliotēku kopumā:

Ja nodotais atsauces objekts ir nulle, metodē tiks izmantots izņēmums, un atlikušais kods, kas tiks ievietots pēc šīs metodes sasniegšanas, tādējādi mēs varam droši uzskatīt, ka atsauce tur nebūs spēkā. Šeit rodas problēma - kaut arī mums ir šīs zināšanas, tas nepalīdz kompilatoram izdarīt to pašu pieņēmumu. Šajā vietā parādās @ Nullable un @ NotNull anotācijas, jo tās eksistē tikai un vienīgi, lai sastādītājiem palīdzētu izprast nosacījumus. Tas ir tas, kāds patiesībā ir efekts - tas ir mājiens kompilatoram, kas tam palīdz veikt sarežģītāku koda analīzi. Esošais efekts, ko jūs jau esat redzējis Kotlinā, ir noteikta veida vieda pārraide blokā pēc tā veida pārbaudes:

Kotlin kompilators jau ir gudrs, un nav šaubu, ka tas arī turpmāk uzlabosies, bet, ieviešot līgumus, Kotlin izstrādātāji mums kā bibliotēku izstrādātājiem deva pilnvaras to uzlabot, rakstot paši savus viedos veidus un radot efektus, kas mūsu lietotājiem palīdz rakstīt tīrāku kodu. Pārrakstīsim CheckNotNul metodi Kotlīnā, izmantojot līgumus, lai parādītu viņu iespējas:

Ir arī dažādi efekti, taču tas nav pilna apjoma ievads līgumos, un es ceru, ka tas tikai deva jums priekšstatu par to, kā jūs varat gūt labumu no tā. Papildus tam Stdlib krātuvē Github ir daudz noderīgu līgumu piemēru, kurus ir vērts pārbaudīt.

Ar lielu spēku nāk liela atbildība, un līgumi nav izņēmums. Neatkarīgi no tā, ko jūs norādāt līgumā, sastādītājs izturas kā pret Svēto Bībeli. Tehniskāk sakot, kompilators neapšauba un neapstiprina visu, ko jūs tur rakstāt, tāpēc jums pašiem ir rūpīgi jāpārbauda kods un jāpārliecinās, ka jūs neieviesat nekādas neatbilstības.

Kā jūs, iespējams, pamanījāt no anotācijas @ExperimentalContracts, līgumi joprojām ir eksperimentālā fāzē, tāpēc laika gaitā var mainīties ne tikai API, bet arī no tā varētu rasties dažas jaunas funkcijas, jo tas kļūst arvien nobriedušāks.

7. Java savietojamība

Rakstot bibliotēku Kotlīnā, ir svarīgi arī saglabāt auditoriju plašāku, nodrošinot vienmērīgu integrācijas pieredzi saviem kolēģiem izstrādātājiem, kuri lieto Java. Tas ir ļoti svarīgi, jo joprojām ir daudz projektu, kas pielietoja Java un dažādu iemeslu dēļ nevēlas pārrakstīt esošo kodu. Tā kā mēs vēlamies, lai Kotlinu kopiena augtu ātrāk, ir labāk ļaut šiem projektiem to darīt pakāpeniski, soli pa solim. Protams, nav tik saulains šajā The Wall pusē, taču ir dažas lietas, ko jūs kā bibliotēkas uzturētājs varat darīt šajā sakarā.

Pirmais ir tas, ka Kotlin paplašināšanas funkcijas Java tiks apkopotas neglītā statiskā metodē, kur metodes pirmais arguments ir uztvērēja tips:

Lai gan jums šeit nav daudz kontroles, jūs vismaz varat mainīt ģenerētās klases nosaukumu, avota faila sākumā ar šādu paketi pievienojot šādu rindu:

Vēl viens piemērs tam, kā jūs varat nedaudz ietekmēt ģenerēto kodu, ir saistīts ar pavadobjekta metožu izmantošanu:

Izmantojot @JvmStatic anotāciju, Kotlinu var piespiest ģenerēt statiskas klases to funkciju vietā, kas noteiktas biedrobjektā:

Salīdzinot ar Kotlinu, Java programmā divas funkcijas ar līdzīgiem nosaukumiem, bet atšķirīgus sugas tipus nevar definēt kopā tipa dzēšanas dēļ, tāpēc Java lietotājiem tā var būt aizbāznis. Cerams, ka no tā varēsit izvairīties, mainot metodes parakstu ar citu anotāciju:

Pēdējais, bet ne mazāk svarīgais, ir spēja definēt pārbaudītos izņēmumus Java lietotājiem paredzētajās funkcijās, kaut arī tie Kotlinā nav tieši pieejami. Tas varētu būt parocīgi, jo Java un Kotlin izņēmumu deklarēšanas paradigma ir atšķirīga:

Lielākā daļa šeit esošo lietu nav obligātas, taču tās noteikti var būt jūsu bibliotēkas avotu avoti no jūsu Java lietotājiem.

Grunts līnija

Kotlīnu valoda ir lieliska valoda, kas nepārtraukti virzās uz priekšu, un ir daudz lietu, ko varat darīt ar bibliotēku, lai padarītu tās lietošanu vienmērīgu. Starp visu, ko jūs izmantojat no iepriekš minētajām idejām, vispirms mēģiniet būt lietotājs un padomājiet, kāds jūs to vēlētos un kā jūs to izmantotu. Velns ir detaļās, un cerams, ka šīs sīkās lietas, kuras jūs piemērojat, nāks par labu lietotājiem un uzlabos viņu pieredzi. Priekā!