7 nasvetov, kako narediti sijaj knjižnice Kotlin

Predgovor

Ko začnemo programirati v novem jeziku, se sprva pogosto držimo paradigem in navad, ki so se razvile med programiranjem v jeziku, ki ga že poznamo. Čeprav se na začetku morda zdi v redu, je za ljudi, ki programirajo jezik, ki ga poskušate obvladati, nekaj očitno videti.

Ko sem pred približno dvema letoma prešel iz Jave na Kotlin, sem v bistvu delal "programiranje Java, ampak v Kotlinu". Čeprav je bil Kotlin zame kot dih svežega zraka, sem kot inženir Android začel uporabljati vse te razširjene funkcije in podatkovne razrede, ki niso bili vedno dosledni. Pretvoril sem obstoječo kodo Java v Kotlin in si jo ogledal, ko sem čez nekaj časa pomagal upoštevati nekaj idej, ko sem v Kotlinu oblikoval API-je za različne komponente ali knjižnice za večkratno uporabo.

Tu na BUX-u delamo na dveh aplikacijah, ki imajo nekaj skupnih knjižnic. Medtem ko je bila zaloga o zalogah (ki še ni izdana) napisana v Kotlinu od začetka, je bila prva CFD vloga napisana v Javi in ​​nato čez nekaj časa spremenjena v Kotlin. Trenutno je CFD aplikacija 78,7% Kotlin, kar pomeni, da še vedno delamo na tem mestu, zato je pomembno biti pozoren na knjižnične API-je, ki jih vzdržujeta dve ekipi, ki hkrati uporabljata Java in Kotlin.

Če imate obstoječo knjižnico Kotlin ali Java, ki jo želite Kotlinify, ali načrtujete API z Kotlinom iz nič, imejte z mano nekaj idej, kaj lahko storite, da olajšate življenje uporabnikov knjižnice.

1. Razširitvene funkcije

Večino časa, ko morate razširiti obstoječi razred z novo funkcionalnostjo, bodisi uporabite kakšno sestavo ali pridobite nov razred (kar lahko, če se široko uporablja, postane vaša hierarhija razreda tako krhka kot steklene skodelice IKEA). Ne glede na vaše želje, ima Kotlin svoj odgovor na to, imenovan razširitvene funkcije. Na kratko, vam omogoča, da dodate novo funkcijo obstoječemu razredu s precej čedno skladnjo. V Androidu lahko na primer novo metodo za razred View določite na naslednji način:

Glede na to lahko veliko knjižnic, ki zagotavljajo dodatne funkcije za obstoječe razrede (npr. View, Context itd.), Namesto da uporabljajo okraševalce, statične tovarniške metode ali kaj drugega, lahko brezhibno zagotavljajo svojo funkcionalnost kot funkcije razširitve, kot če bi to funkcionalnost bi v prvotnih razredih obstajala od začetka.

2. Privzete vrednosti argumentov

Kotlin je bil prvotno zasnovan kot jedrnata, čista in urejena različica Jave, vendar se izkaže, da to zelo dobro počne s privzetimi vrednostmi argumentov funkcije. Ponudnik API-ja lahko določi privzete vrednosti za argumente, ki jih je mogoče izpustiti. Zelo bi me presenetil, če še niste videli podobne kode med delom s SQLite v Androidu:

Čeprav je na tej metodi več napak kot tistih grdih ničel, tu ne sodim, ampak rečem, da teh časov ni več in bi resno dvomil v kodo, tako napisano v Kotlinu. Takšnih primerov je veliko, vendar na srečo lahko zdaj naredimo boljše in če namesto ali dodate Builderju ponudite zunanji API z določenimi nastavitvenimi parametri, razmislite o uporabi privzetih vrednosti argumentov. To bo imelo vsaj dve prednosti: prvič, ne boste prisilili uporabnika, da določi neobvezne parametre ali kar koli že lahko predhodno napovete, in drugo je, da bo imel uporabnik privzeto konfiguracijo, ki bo ravno izpadla -škatla:

Dobro je omeniti tudi to, da če postavite te argumente s privzetimi vrednostmi na koncu, uporabniku ne bo treba določiti imen za obvezne parametre.

3. Predmeti

Ste kdaj morali v Javi implementirati vzorec Singleton? Verjetno ste imeli, in če je tako, bi morali vedeti, kako okorno je lahko včasih:

Obstajajo različne izvedbe, ki imajo vsaka svoje prednosti in slabosti. Kotlin naslavlja vseh 50 odtenkov implementacije vzorca Singleton z eno samo strukturo, imenovano objektna deklaracija. Poglejte ma, brez "dvojno preverjenega zaklepanja":

Kar je v zvezi s tem poleg sintakse, je to, da je inicializacija deklaracije objekta varna za navoje in se leno ob prvem dostopu do njih:

Za takšne knjižnice, kot so Fabric, Glide, Picasso ali katere koli druge, ki uporabljajo en primerek predmeta kot glavno vstopno točko v celotni API knjižnice, je to naravni način in ni razloga, da bi stari Java način uporabljali delati iste stvari.

4. Izvorne datoteke

Na enak način, kot Kotlin ponovno razmišlja o številnih skladenjskih izzivih, s katerimi se vsakodnevno srečujemo, razmišlja tudi o načinu organizacije kode, ki jo ustvarjamo. Kotlin izvorne datoteke služijo kot dom za več deklaracij, ki so pomensko blizu drug drugemu. Izkazalo se je, da so idealno mesto za definiranje nekaterih razširitvenih funkcij, povezanih z istim razredom. Oglejte si ta poenostavljeni delček iz izvorne kode Kotlina, kjer so vse razširitvene funkcije, ki se uporabljajo za manipuliranje besedila, v isti datoteki "Strings.kt":

Drug primeren primer njegove uporabe je definiranje protokola komunikacije z vašim API-jem skupaj s podatkovnimi razredi in vmesniki v eni izvorni datoteki. Uporabniku omogoči, da ne izgubi osredotočenosti s preklopom med različnimi datotekami, medtem ko sledi toku:

Toda ne pretiravajte z njim, saj tvegate, da boste uporabnika preverili z velikostjo datoteke in jo spremenili v razred RecyclerView s ~ 13.000 vrsticami .

5. Sorotišča

Če vaša knjižnica uporablja več niti za dostop do omrežja ali izvajanje katerega koli drugega dolgotrajnega dela, razmislite o tem, da API-ju zagotovite funkcije za zaustavitev. Od začetka Kotlin 1.3 sorodne prakse niso več eksperimentalne, kar je odlična priložnost, da jih začnete uporabljati v proizvodnji, če ste že dvomili. Postopki v nekaterih primerih so lahko dobra alternativa opazovanju RxJava in drugim načinom obravnave asinhronih klicev. Morda ste že videli, da je API poln metod s povratnimi klici ali v času, ko je Rx hype ovit z enojnim ali dokončnim:

Vendar smo zdaj v Kotlinovi dobi, zato bi jo lahko oblikovali tudi v prid uporabi sorotov:

Kljub dejstvu, da so sorodne funkcije boljše kot stare dobre Java teme, saj so lažje, bistveno prispevajo k berljivosti kode:

6. Pogodbe

Poleg stabilnih postopkov, Kotlin 1.3 razvijalcem predstavi tudi način interakcije s prevajalnikom. Pogodba je nova funkcija, ki nam kot razvijalcem knjižnic omogoča, da s prevajalnikom delimo znanje, ki ga imamo, tako da določimo tako imenovane učinke. Da bi lažje razumeli, kakšen je učinek, prinesimo najbližjo analogijo iz Jave. Večina vas je verjetno videla ali celo uporabljala razred Precondition iz Guave z veliko trditvami in njegovo prilagoditvijo znotraj knjižnic, kot je Dagger, ki ne želijo pridobiti celotne knjižnice:

Če je posredovani referenčni objekt ničen, bo metoda vrgla izjemo in preostalo kodo, postavljeno po tem, ko ta metoda ne bo dosežena, zato lahko varno predpostavimo, da sklicevanje tam ne bo nično. Tu nastane težava - čeprav imamo to znanje, ne pomaga prevajalcu narediti iste predpostavke. Tu nastopijo prikazi @ Nullable in @ NotNull, saj obstajajo zgolj zato, da pomagajo prevajalcu razumeti pogoje. To je res učinek - to je namig za prevajalnik, ki mu pomaga pri bolj izpopolnjeni analizi kode. Obstoječi učinek, ki ste ga že videli v Kotlinu, je pametno vnašanje določene vrste v blok po preverjanju njegove vrste:

Prevajalnik Kotlin je že pameten in brez dvoma se bo v prihodnosti še izboljševal, a z uvedbo pogodb so nam razvijalci Kotlin kot razvijalci knjižnic dali moč, da ga izboljšujejo tako, da napišejo lastne pametne prenose in ustvarijo učinke, ki pomagajo našim uporabnikom napišite čistejšo kodo. Zdaj pa naj napišemo metodo checkNotNul v Kotlinu s pogodbami, da pokažemo svoje sposobnosti:

Prav tako obstajajo različni učinki, vendar to ni uvod v pogodbe v polni velikosti in upam, da vam je samo dal predstavo, kako lahko od tega koristite. Poleg tega ima stdlib repozitorij na Githubu še veliko uporabnih pogodbenih primerov, ki jih je vredno preveriti.

Z veliko močjo prihaja velika odgovornost in pogodbe niso izjema. Vse, kar navedete v svoji pogodbi, prevajalnik obravnava kot Sveto pismo. Bolj tehnično prevajalnik ne dvomi ali ne potrdi vsega, kar napišete tam, zato morate sami skrbno pregledati kodo in se prepričati, da ne vnesete neskladnosti.

Kot ste morda opazili iz obvestila @ExperimentalContracts, so pogodbe še vedno v poskusni fazi, zato se lahko sčasoma ne spremeni le API, ampak tudi nekatere nove funkcije, ki izhajajo iz njega, ko postaja vse bolj zrel.

7. Interoperabilnost Java

Pri pisanju knjižnice v Kotlinu je pomembno tudi ohranjati širšo občinstvo z zagotavljanjem nemotene izkušnje integracije za druge razvijalce, ki uporabljajo Java. Zelo pomembno je, ker je še vedno veliko projektov, ki se držijo Jave in zaradi različnih razlogov ne želijo prepisovati obstoječe kode. Ker želimo, da bi skupnost Kotlin hitreje rasla, je bolje, da se tem projektom omogoči postopno, korak za korakom. Seveda na tej strani Zida ni sončno, vendar lahko nekatere stvari, ki jih kot vzdrževalec knjižnice počnete, počnete s tem.

Prva stvar je, da bodo Kotlinove razširitvene funkcije na Javi sestavljene v grde statične metode, kjer je prvi argument metode vrsta sprejemnika:

Čeprav nimate veliko nadzora tukaj, lahko vsaj spremenite ime ustvarjenega razreda, tako da na začetku izvorne datoteke dodate naslednjo vrstico, ki vsebuje funkcije nivoja paketa zgoraj:

Drug primer, kako lahko nekoliko vplivate na ustvarjeno kodo, je povezan z uporabo metod spremljevalnega predmeta:

Kotlin lahko prisili, da ustvari statične razrede namesto funkcij, opredeljenih v spremljevalnem objektu z uporabo @JvmStatic opombe:

V primerjavi s Kotlinom na Javi dveh funkcij s podobnimi imeni, vendar različnimi generičnimi vrstami, zaradi izbrisa tipa ni mogoče določiti skupaj, tako da bi lahko bil uporabnik Java zaustavitev. Upajmo, da se mu lahko izognete tako, da spremenite podpis metode z drugim pripisom:

In nenazadnje je zmožnost določanja preverjenih izjem v funkcijah za uporabnike Java, čeprav v Kotlinu niso neposredno na voljo. To je lahko priročno, saj je paradigma izjav o izjemi na Javi in ​​Kotlinu drugačna:

Večina stvari tukaj ni na voljo, vendar bodo zagotovo vir kudov za vašo knjižnico pri vaših uporabnikih Java.

Spodnja črta

Kotlin je odličen jezik, ki se nenehno premika naprej in v zvezi s knjižnico lahko naredite veliko stvari, da se njena uporaba nemoteno uporablja. Med vsem, kar uporabite od zgornjih idej, poskusite biti uporabnik na prvem mestu in pomislite, kaj bi radi, da bi to bilo in kako bi ga uporabljali. Hudič je v podrobnostih in upamo, da bodo te drobne stvari, ki jih uporabite, koristile vašim uporabnikom in izboljšale njihovo izkušnjo. Na zdravje!