Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3

Vi presenterar för er uppmärksamhet den tredje delen av översättningen av materialet om vägen som Dropbox tog när man implementerade ett typkontrollsystem för Python-kod.

Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3

→ Tidigare delar: först и andra

När 4 miljoner rader maskinskriven kod

En annan stor utmaning (och det näst vanligaste problemet bland de tillfrågade internt) var att öka mängden kod som omfattas av typkontroller i Dropbox. Vi har prövat flera tillvägagångssätt för att lösa detta problem, från att naturligt öka storleken på den maskinskrivna kodbasen till att fokusera mypy-teamets ansträngningar på statisk och dynamisk automatiserad typinferens. Till slut verkade det som om det inte fanns någon enkel vinnande strategi, men vi kunde uppnå snabb tillväxt i volymen av kommenterad kod genom att kombinera många tillvägagångssätt.

Som ett resultat har vårt största Python-förråd (med backend-kod) nästan 4 miljoner rader med kommenterad kod. Arbetet med statisk kodskrivning avslutades på cirka tre år. Mypy stöder nu olika typer av kodtäckningsrapporter som gör det enklare att övervaka skrivframsteg. I synnerhet kan vi generera rapporter om kod med oklarheter i typer, som till exempel explicit användning av en typ Any i annoteringar som inte kan verifieras, eller med saker som att importera tredjepartsbibliotek som inte har typkommentarer. Som en del av ett projekt för att förbättra noggrannheten för typkontroll i Dropbox, bidrog vi till att förbättra typdefinitionerna (så kallade stubbfiler) för några populära bibliotek med öppen källkod i ett centraliserat Python-förråd maskinskriven.

Vi implementerade (och standardiserade i efterföljande PEP) nya funktioner i typsystemet som tillåter mer exakta typer för vissa specifika Python-mönster. Ett anmärkningsvärt exempel på detta är TypeDict, som tillhandahåller typer för JSON-liknande ordböcker som har en fast uppsättning strängnycklar, var och en med ett värde av sin egen typ. Vi kommer att fortsätta bygga ut typsystemet. Vårt nästa steg blir sannolikt att förbättra stödet för Pythons numeriska kapacitet.

Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3
Antal rader med kommenterad kod: server

Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3
Antal rader med kommenterad kod: klient

Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3
Totalt antal rader med kommenterad kod

Här är en översikt över huvuddragen för de saker vi gjorde för att öka mängden kommenterad kod i Dropbox:

Anteckningsstränghet. Vi ökade gradvis kraven på noggrannheten med att kommentera ny kod. Vi började med linter-tips som föreslog att du skulle lägga till kommentarer till filer som redan hade några kommentarer. Vi kräver nu typkommentarer i nya Python-filer och i de flesta befintliga filer.

Skriva rapporter. Vi skickar team veckovisa rapporter om nivån på att skriva in sin kod och ger råd om vad som bör kommenteras först.

Popularisering av mypy. Vi pratar om mypy vid evenemang och pratar med team för att hjälpa dem komma igång med typkommentarer.

Omröstningar. Vi genomför periodiska användarundersökningar för att identifiera stora problem. Vi är redo att gå ganska långt för att lösa dessa problem (även skapa ett nytt språk för att påskynda mypy!).

Prestanda. Vi har avsevärt förbättrat prestandan för mypy genom att använda demonen och mypyc. Detta gjordes för att jämna ut de olägenheter som uppstår under anteckningsprocessen, och för att kunna arbeta med stora mängder kod.

Integration med redaktörer. Vi har byggt verktyg för att köra mypy i redigerare som är populära på Dropbox. Detta inkluderar PyCharm, Vim och VS Code. Detta förenklade avsevärt processen att kommentera koden och kontrollera dess funktionalitet. Dessa typer av åtgärder är vanliga när man kommenterar befintlig kod.

Statisk analys. Vi skapade ett verktyg för att härleda funktionssignaturer med hjälp av statiska analysverktyg. Det här verktyget kan bara fungera i relativt enkla situationer, men det hjälpte oss att öka vår kodtypstäckning utan större ansträngning.

Stöd för tredje parts bibliotek. Många av våra projekt använder verktygslådan SQLAlchemy. Den drar fördel av de dynamiska funktionerna hos Python som PEP 484-typer inte kan modellera direkt. Vi, i enlighet med PEP 561, skapade motsvarande stubfil och skrev ett plugin för mypy (öppen källa), vilket förbättrar SQLAlchemy-stödet.

Svårigheter vi stötte på

Vägen till 4 miljoner rader med maskinskriven kod har inte alltid varit lätt för oss. På den här stigen stötte vi på många gropar och gjorde flera misstag. Det här är några av de problem vi stötte på. Vi hoppas att berätta om dem hjälper andra att undvika liknande problem.

Saknade filer. Vi började vårt arbete med att bara kontrollera en liten mängd filer. Allt som inte ingick i dessa filer kontrollerades inte. Filer lades till i skanningslistan när de första anteckningarna dök upp i dem. Om något importerades från en modul som ligger utanför verifieringsomfånget, pratade vi om att arbeta med värden som Any, som inte testades alls. Detta ledde till en betydande förlust av skrivnoggrannhet, särskilt i de tidiga stadierna av migration. Detta tillvägagångssätt har fungerat förvånansvärt bra hittills, även om en typisk situation är att lägga till filer i granskningens omfattning avslöjar problem i andra delar av kodbasen. I värsta fall, när två isolerade kodområden slogs samman, där, oberoende av varandra, typer redan var kontrollerade, visade det sig att typerna av dessa områden var inkompatibla med varandra. Detta ledde till behovet av att göra många ändringar i anteckningarna. När vi ser tillbaka nu inser vi att vi borde ha lagt till kärnbiblioteksmoduler till mypys typkontrollområde tidigare. Detta skulle göra vårt arbete mycket mer förutsägbart.

Kommentera gammal kod. När vi började hade vi cirka 4 miljoner rader med befintlig Python-kod. Det var tydligt att det inte var en lätt uppgift att kommentera all denna kod. Vi har skapat ett verktyg som heter PyAnnotate som kan samla in typinformation när tester körs och kan lägga till typkommentarer till din kod baserat på den insamlade informationen. Vi har dock inte märkt en särskilt utbredd användning av detta verktyg. Insamling av typinformation gick långsamt och automatiskt genererade anteckningar krävde ofta många manuella redigeringar. Vi funderade på att köra det här verktyget automatiskt varje gång vi granskar kod, eller på att samla in typinformation baserat på analys av en liten volym av faktiska nätverksförfrågningar, men beslutade att inte göra det eftersom båda tillvägagångssätten var för riskabla.

Som ett resultat kan det noteras att det mesta av koden antecknades manuellt av dess ägare. För att styra denna process i rätt riktning utarbetar vi rapporter om särskilt viktiga moduler och funktioner som behöver kommenteras. Till exempel är det viktigt att tillhandahålla typkommentarer för en biblioteksmodul som används på hundratals platser. Men en gammal tjänst som byts ut mot en ny är inte längre så viktig att kommentera. Vi experimenterar också med att använda statisk analys för att generera typkommentarer för äldre kod.

Cyklisk import. Ovan pratade jag om cykliska importer (”beroendehärvorna”), vars existens gjorde det svårt att påskynda mypy. Vi var också tvungna att arbeta hårt för att få mypy att stödja alla typer av idiom som orsakas av dessa cykliska importer. Vi har nyligen slutfört ett stort systemomformningsprojekt som fixade de flesta av mypys problem angående cirkulär import. Dessa problem härrörde faktiskt från de allra första dagarna av projektet, tillbaka från Alore, det pedagogiska språket som mypy-projektet ursprungligen var fokuserat på. Alore-syntax gör det enkelt att lösa problem med cykliska importkommandon. Modern mypy har ärvt några begränsningar från dess tidigare enkla implementering (som passade utmärkt för Alore). Python gör det svårt att arbeta med cirkulär import, främst för att uttrycken är tvetydiga. Till exempel kan en tilldelningsoperation faktiskt definiera ett typalias. Mypy kan inte alltid upptäcka sådant här förrän det mesta av importslingan har bearbetats. Det fanns inga sådana oklarheter i Alore. Dåliga beslut som fattas i de tidiga stadierna av systemutveckling kan innebära en obehaglig överraskning för programmeraren många år senare.

Resultat: vägen till 5 miljoner rader kod och nya horisonter

Mypy-projektet har kommit långt - från tidiga prototyper till ett system som kontrollerar 4 miljoner rader av produktionskodtyper. Allt eftersom mypy utvecklades standardiserades Pythons typtips. Dessa dagar har ett kraftfullt ekosystem utvecklats kring att skriva Python-kod. Den har en plats för biblioteksstöd, den innehåller extraverktyg för IDE:er och redaktörer, den har flera typkontrollsystem, som vart och ett har sina egna för- och nackdelar.

Även om typkontroll redan är givet på Dropbox, tror jag att vi fortfarande är i början av att skriva Python-kod. Jag tror att typkontrolltekniker kommer att fortsätta att utvecklas och förbättras.

Om du inte redan har använt typkontroll i ditt storskaliga Python-projekt, vet att det nu är en mycket bra tid att börja gå över till statisk typning. Jag har pratat med dem som har gjort en liknande övergång. Ingen av dem ångrade sig. Typkontroll gör Python till ett språk som är mycket bättre lämpat för att utveckla stora projekt än "vanlig Python".

Kära läsare! Använder du typkontroll i dina Python-projekt?

Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3
Vägen till att typkontrollera 4 miljoner rader Python-kod. Del 3

Källa: will.com

Lägg en kommentar