Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3

Esittelemme huomionne materiaalin käännöksen kolmannen osan siitä polusta, jonka Dropbox käytti toteuttaessaan Python-koodin tyypintarkistusjärjestelmää.

Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3

→ Edelliset osat: ensimmäinen и toinen

Saavutetaan 4 miljoonaa riviä kirjoitettua koodia

Toinen suuri haaste (ja toiseksi yleisin huolenaihe sisäisesti tutkittujen keskuudessa) oli Dropboxin tyyppitarkistusten kattaman koodin määrän lisääminen. Olemme kokeilleet useita lähestymistapoja tämän ongelman ratkaisemiseksi, kirjoitetun koodikannan koon luonnollisesta kasvattamisesta mypy-tiimin ponnistelujen keskittämiseen staattiseen ja dynaamiseen automatisoituun tyyppipäätelmään. Lopulta näytti siltä, ​​ettei yksinkertaista voittostrategiaa ollut, mutta pystyimme saavuttamaan nopean kasvun annotoidun koodin määrässä yhdistämällä monia lähestymistapoja.

Tämän seurauksena suurimmassa Python-tietovarastossamme (taustakoodilla) on lähes 4 miljoonaa riviä huomautettua koodia. Staattisen koodin kirjoituksen työ valmistui noin kolmessa vuodessa. Mypy tukee nyt erilaisia ​​koodikattavuusraportteja, jotka helpottavat kirjoittamisen edistymisen seurantaa. Erityisesti voimme luoda raportteja koodista, jossa on epäselvyyksiä tyypeissä, kuten esimerkiksi eksplisiittinen tyypin käyttö Any huomautuksissa, joita ei voida vahvistaa, tai sellaisissa asioissa, kuten kolmansien osapuolien kirjastojen tuonti, joissa ei ole tyyppimerkintöjä. Osana projektia Dropboxin tyypintarkistuksen tarkkuuden parantamiseksi osallistuimme joidenkin suosittujen avoimen lähdekoodin kirjastojen tyyppimääritelmien (ns. stub-tiedostojen) parantamiseen keskitetyssä Python-varastossa. kirjoitettu.

Otimme käyttöön (ja standardoimme myöhemmissä PEP:issä) tyyppijärjestelmän uusia ominaisuuksia, jotka mahdollistavat tarkemmat tyypit tietyille Python-malleille. Merkittävä esimerkki tästä on TypeDict, joka tarjoaa tyyppejä JSON-kaltaisille sanakirjoille, joissa on kiinteä joukko merkkijonoavaimia, joista jokaisella on oma tyyppinsä arvo. Jatkamme tyyppijärjestelmän laajentamista. Seuraava askel on todennäköisesti parantaa Pythonin numeeristen ominaisuuksien tukea.

Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3
Annotoidun koodin rivien lukumäärä: palvelin

Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3
Annotoidun koodin rivien lukumäärä: asiakas

Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3
Annotoidun koodin rivien kokonaismäärä

Tässä on yleiskatsaus tärkeimmistä ominaisuuksista, joita teimme lisätäksemme Dropboxin annotoidun koodin määrää:

Annotaatioiden tarkkuus. Lisäsimme vähitellen vaatimuksia uuden koodin merkitsemisen tarkkuudelle. Aloitimme linterivinkeillä, joissa ehdotettiin merkintöjen lisäämistä tiedostoihin, joissa oli jo joitakin huomautuksia. Vaadimme nyt tyyppimerkintöjä uusissa Python-tiedostoissa ja useimmissa olemassa olevissa tiedostoissa.

Raporttien kirjoittaminen. Lähetämme tiimeille viikoittain raportteja koodin kirjoittamisen tasosta ja annamme neuvoja siitä, mitä tulisi merkitä ensin.

Mypyn popularisointi. Puhumme mypystä tapahtumissa ja keskustelemme tiimien kanssa auttaaksemme heitä pääsemään alkuun tyyppimerkintöjen kanssa.

Äänestykset. Teemme määräajoin käyttäjätutkimuksia tunnistaaksemme tärkeimmät ongelmat. Olemme valmiita menemään melko pitkälle näiden ongelmien ratkaisemisessa (jopa luomalla uuden kielen mypyn nopeuttamiseksi!).

Esitys. Olemme parantaneet mypyn suorituskykyä huomattavasti käyttämällä daemonia ja mypycia. Tämä tehtiin tasoittaakseen merkintäprosessin aikana ilmeneviä haittoja ja voidakseen työskennellä suurten koodimäärien kanssa.

Integrointi editorien kanssa. Olemme rakentaneet työkaluja tukemaan mypyn käyttöä Dropboxissa suosituissa muokkausohjelmissa. Tämä sisältää PyCharm, Vim ja VS Code. Tämä yksinkertaisti huomattavasti koodin merkitsemistä ja sen toimivuuden tarkistamista. Tämäntyyppiset toiminnot ovat yleisiä, kun olemassa olevaa koodia merkitään.

Staattinen analyysi. Loimme työkalun funktioiden allekirjoitusten päättelemiseen staattisten analyysityökalujen avulla. Tämä työkalu toimii vain suhteellisen yksinkertaisissa tilanteissa, mutta se auttoi meitä lisäämään koodityyppien kattavuutta ilman paljon vaivaa.

Tuki kolmansien osapuolien kirjastoille. Monet projekteistamme käyttävät SQLAlchemy-työkalupakkia. Se hyödyntää Pythonin dynaamisia ominaisuuksia, joita PEP 484 -tyypit eivät pysty mallintamaan suoraan. Loimme PEP 561:n mukaisesti vastaavan tynkätiedoston ja kirjoitimme liitännäisen mypylle (avoin lähdekoodi), mikä parantaa SQLAlchemy-tukea.

Kohtaamiamme vaikeuksia

Polku 4 miljoonaan riviin kirjoitettua koodia ei ole aina ollut meille helppo. Tällä polulla kohtasimme monia kuoppia ja teimme useita virheitä. Nämä ovat joitakin kohtaamiamme ongelmia. Toivomme, että niistä kertominen auttaa muita välttämään samanlaisia ​​ongelmia.

Puuttuvat tiedostot. Aloitimme työmme tarkistamalla vain pienen määrän tiedostoja. Mitään, joka ei sisälly näihin tiedostoihin, ei tarkistettu. Tiedostot lisättiin skannausluetteloon, kun ensimmäiset merkinnät ilmestyivät niihin. Jos jotain tuotiin moduulista, joka sijaitsee varmennusalueen ulkopuolella, puhuimme työskentelystä arvojen kanssa, kuten Any, joita ei testattu ollenkaan. Tämä johti merkittävään kirjoitustarkkuuden heikkenemiseen erityisesti siirtymisen alkuvaiheessa. Tämä lähestymistapa on toiminut yllättävän hyvin toistaiseksi, vaikka tyypillinen tilanne on, että tiedostojen lisääminen tarkastelun piiriin paljastaa ongelmia muissa koodikannan osissa. Pahimmassa tapauksessa, kun yhdistettiin kaksi erillistä koodialuetta, joissa toisistaan ​​riippumatta tyypit oli jo tarkistettu, kävi ilmi, että näiden alueiden tyypit eivät olleet yhteensopivia keskenään. Tämä johti tarpeeseen tehdä monia muutoksia huomautuksiin. Kun katsomme nyt taaksepäin, ymmärrämme, että meidän olisi pitänyt lisätä ydinkirjastomoduulit mypyn tyypintarkistusalueelle aikaisemmin. Tämä tekisi työstämme paljon ennakoitavampaa.

Kommentoi vanhaa koodia. Kun aloitimme, meillä oli noin 4 miljoonaa riviä olemassa olevaa Python-koodia. Oli selvää, että kaiken tämän koodin merkitseminen ei ollut helppo tehtävä. Olemme luoneet PyAnnotate-nimisen työkalun, joka voi kerätä tyyppitietoja testien aikana ja lisätä tyyppimerkintöjä koodiisi kerättyjen tietojen perusteella. Emme kuitenkaan ole havainneet tämän työkalun erityisen laajaa käyttöönottoa. Tyyppitietojen kerääminen oli hidasta, ja automaattisesti luodut merkinnät vaativat usein useita manuaalisia muokkauksia. Ajattelimme käyttää tätä työkalua automaattisesti joka kerta, kun tarkistamme koodia, tai keräämme tyyppitietoja pienen määrän todellisten verkkopyyntöjen analysoinnin perusteella, mutta päätimme olla tekemättä, koska kumpikaan lähestymistapa oli liian riskialtis.

Tämän seurauksena voidaan todeta, että sen omistajat merkitsivät suurimman osan koodista manuaalisesti. Ohjataksemme tätä prosessia oikeaan suuntaan, laadimme raportteja erityisen tärkeistä moduuleista ja toiminnoista, jotka tarvitsevat huomautuksia. On esimerkiksi tärkeää tarjota tyyppimerkinnät kirjastomoduulille, jota käytetään sadoissa paikoissa. Mutta vanha palvelu, joka korvataan uudella, ei ole enää niin tärkeä huomautettava. Kokeilemme myös staattisen analyysin käyttöä luodaksemme tyyppimerkintöjä vanhalle koodille.

Syklinen tuonti. Yllä puhuin syklisestä tuonnista ("riippuvuuskimppu"), jonka olemassaolo vaikeutti mypyn nopeuttamista. Meidän piti myös tehdä kovasti töitä saadaksemme mypyn tukemaan kaikenlaisia ​​idioomeja, joita nämä sykliset tuonnit aiheuttavat. Saimme äskettäin päätökseen suuren järjestelmän uudelleensuunnitteluprojektin, joka korjasi useimmat mypyn kiertotuontiin liittyvät ongelmat. Nämä ongelmat johtuivat itse asiassa projektin varhaisista ajoista, Aloresta, opetuskielestä, johon mypy-projekti alun perin keskittyi. Alore-syntaksin avulla on helppo ratkaista ongelmia syklisillä tuontikomennoilla. Moderni mypy on perinyt joitain rajoituksia aiemmasta, yksinkertaisesta toteutuksestaan ​​(joka sopi erinomaisesti Alorelle). Python tekee ympyrämuotoisten tuontien kanssa työskentelyn vaikeaksi, lähinnä siksi, että lausekkeet ovat moniselitteisiä. Esimerkiksi osoitustoiminto voi itse asiassa määrittää tyyppialiaksen. Mypy ei aina pysty havaitsemaan tällaisia ​​asioita, ennen kuin suurin osa tuontisilmukasta on käsitelty. Aloressa ei ollut tällaisia ​​epäselvyyksiä. Järjestelmäkehityksen alkuvaiheessa tehdyt huonot päätökset voivat olla ohjelmoijalle epämiellyttävä yllätys monta vuotta myöhemmin.

Tulokset: polku 5 miljoonaan koodiriviin ja uusiin horisontteihin

Mypy-projekti on edennyt pitkän tien - varhaisista prototyypeistä järjestelmään, joka ohjaa 4 miljoonaa riviä tuotantokoodityyppejä. Mypyn kehittyessä Pythonin tyyppiset vihjeet standardisoitiin. Nykyään Python-koodin kirjoittamisen ympärille on kehittynyt tehokas ekosysteemi. Siinä on paikka kirjaston tuelle, se sisältää aputyökaluja IDE:ille ja editoreille, siinä on useita tyyppiohjausjärjestelmiä, joista jokaisella on omat hyvät ja huonot puolensa.

Vaikka tyypin tarkistus on jo annettu Dropboxissa, uskon, että olemme vielä alkuaikoina Python-koodin kirjoittamisessa. Uskon, että tyyppitarkistustekniikat kehittyvät ja paranevat edelleen.

Jos et ole vielä käyttänyt tyyppitarkistusta suuressa Python-projektissasi, niin tiedä, että nyt on hyvä aika siirtyä staattiseen kirjoittamiseen. Olen puhunut niiden kanssa, jotka ovat tehneet samanlaisen muutoksen. Kukaan heistä ei katunut sitä. Tyyppitarkistus tekee Pythonista kielen, joka soveltuu paljon paremmin suurten projektien kehittämiseen kuin "tavallinen Python".

Hyvä lukijat! Käytätkö tyyppitarkistusta Python-projekteissasi?

Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3
Polku 4 miljoonan Python-koodirivin tyyppitarkistukseen. Osa 3

Lähde: will.com

Lisää kommentti