Å odien mÄs piedÄvÄjam jÅ«su uzmanÄ«bai pirmo daļu par to, kÄ Dropbox veic Python koda tipu kontroli.
Dropbox daudz raksta Python valodÄ. TÄ ir valoda, ko mÄs izmantojam ÄrkÄrtÄ«gi plaÅ”i ā gan aizmugures servisos, gan darbvirsmas klientu lietotnÄs. MÄs arÄ« ievÄrojami lietojam Go, TypeScript un Rust, taÄu Python ir mÅ«su galvenÄ valoda. Å emot vÄrÄ mÅ«su mÄrogus, jo runa ir par miljoniem rindiÅu Python koda, izrÄdÄ«jÄs, ka dinamiskÄ tipizÄÅ”ana bÅ«tiski apgrÅ«tina tÄ sapraÅ”anu un sÄkusi nopietni ietekmÄt darba produktivitÄti. Lai mazinÄtu Å”o problÄmu, mÄs sÄkÄm pakÄpeniski pÄrvÄrst mÅ«su kodu statiskajÄ tipu pÄrbaudÄ, izmantojot mypy. Tas, iespÄjams, ir vispopulÄrÄkÄ neatkarÄ«gÄ tipu pÄrbaudes sistÄma Python valodai. Mypy ir atvÄrtÄ koda projekts, un tÄ galvenie izstrÄdÄtÄji strÄdÄ Dropbox.
Dropbox ir bijusi viena no pirmajÄm uzÅÄmumÄm, kas ieviesusi statisku tipu pÄrbaudi Python kodÄ Å”ÄdÄ mÄrogÄ. MÅ«sdienÄs mypy tiek izmantots tÅ«kstoÅ”iem projektu. Å is rÄ«ks ir bez skaitÄmu reizi āpÄrbaudÄ«ts kaujÄā. Mums, lai nokļūtu lÄ«dz Å”eit, kur mÄs esam tagad, bija jÄveic garÅ” ceļŔ. Å ajÄ ceÄ¼Ä bija daudz neveiksmÄ«gu mÄÄ£inÄjumu un izgÄzuÅ”os eksperimentu. Å is materiÄls stÄsta par statiskÄs tipu pÄrbaudes vÄsturi Python ā no tÄs sarežģītÄ sÄkuma, kas bija daļa no maniem zinÄtniskajiem pÄtÄ«jumiem, lÄ«dz Å”odienai, kad tipu pÄrbaudes un tipu norÄdÄ«jumi ir kļuvuÅ”i ierasti neskaitÄmiem izstrÄdÄtÄjiem, kuri raksta Python. Å ie mehÄnismi tagad tiek atbalstÄ«ti daudzu rÄ«ku ā tÄdu kÄ IDE un koda analizatori.
ā
KÄpÄc nepiecieÅ”ama tipu pÄrbaude?
Ja jÅ«s kÄdreiz esat izmantojis dinamiskÄs tipizÄcijas Python, jums var rasties neskaidrÄ«bas par to, kÄdÄļ apkÄrt statiskajai tipizÄcijai un mypy pÄdÄjÄ laikÄ ir radusies tik liela ažiotÄža. VarbÅ«t jÅ«s tieÅ”i mÄ«lat Python tÄ dinamiskÄs tipizÄcijas dÄļ, un viss, kas notiek, jÅ«s vienkÄrÅ”i sarÅ«gtina. AtslÄga uz statiskÄs tipizÄcijas vÄrtÄ«bu ir risinÄjumu mÄrogs: jo lielÄks ir jÅ«su projekts, jo spÄcÄ«gÄk jÅ«s tendÄjaties uz statisko tipizÄciju, un galu galÄ, jo vairÄk tas patieÅ”Äm ir nepiecieÅ”ams.
PieÅemsim, ka projekts ir sasniedzis desmitiem tÅ«kstoÅ”u rindu, un izrÄdÄs, ka pie tÄ strÄdÄ vairÄki programmÄtÄji. Izskatot lÄ«dzÄ«gu projektu, balstoties uz mÅ«su pieredzi, varam teikt, ka koda sapratne kļūs par galveno faktoru izstrÄdÄtÄju produktivitÄtes nodroÅ”inÄÅ”anÄ. Bez tipu anotÄcijÄm ir grÅ«ti noskaidrot, piemÄram, kÄdi argumenti jÄnodod funkcijai vai kÄdu tipu vÄrtÄ«bas kÄda funkcija var atgriezt. Å eit ir tipiski jautÄjumi, uz kuriem bieži vien ir grÅ«ti atbildÄt, neizmantojot tipu anotÄcijas:
- Vai Ŕī funkcija var atgriezt
None? - Kas jÄbÅ«t Å”im argumentam
items? - KÄds ir atribÅ«ta tips
id:intvai tas ir,str, vai varbÅ«t kÄds pielÄgots tips? - Vai Å”im argumentam jÄbÅ«t sarakstam? Vai tajÄ var nodot tuple?
Ja aplÅ«ko nÄkamo koda fragmentu ar tipu anotÄcijÄm un mÄÄ£ina atbildÄt uz lÄ«dzÄ«giem jautÄjumiem, izrÄdÄ«sies, ka tas ir visvienkÄrÅ”Äkais uzdevums:
class Resource:
id: bytes
...
def read_metadata(self,
items: Sequence[str]) -> Dict[str, MetadataItem]:
...read_metadataneatgriežNone, jo atgrieztÄ tipa navOptional[ā¦].- Arguments
itemsir virknes tipa. To nevar itera atseviÅ”Ä·Ä secÄ«bÄ. - AtribÅ«ts
idir baitu virkne.
IdeÄlÄ pasaulÄ varÄtu cerÄt, ka visas Å”Ädas nianses bÅ«s aprakstÄ«tas iebÅ«vÄtajÄ dokumentÄcijÄ (docstring). TomÄr pieredze sniedz daudz piemÄru tam, ka tÄda dokumentÄcija bieži vien nav pieejama kode, ar kuru jÄsaskaras. Pat ja tÄda dokumentÄcija ir, nevar paļauties uz tÄs absolÅ«to pareizÄ«bu. Å Ä« dokumentÄcija var bÅ«t neskaidra, neprecÄ«za, radot iespÄjas tÄs nepareizai izpratnei. LielÄs komandÄs vai lielos projektos Ŕī problÄma var kļūt ÄrkÄrtÄ«gi akÅ«ta.
Lai gan Python lieliski darbojas agrÄ«nÄs vai vidÄjÄs projektu stadijÄs, noteiktÄ brÄ«dÄ« veiksmÄ«gi projekti un uzÅÄmumi, kas izmanto Python, var saskarties ar dzÄ«votspÄjÄ«gu jautÄjumu: āVai mums jÄnodod viss uz statiski tipizÄtu valodu?ā.
Veidu pÄrbaudes sistÄmas, piemÄram, mypy, risina iepriekÅ” minÄto problÄmu, jo tÄs nodroÅ”ina izstrÄdÄtÄjiem formÄlu valodu, lai aprakstÄ«tu tipus, un pÄrbauda, vai tipo apraksti atbilst programmas realizÄcijai (un, kas nav obligÄti, arÄ« to pastÄvÄÅ”anu). KopumÄ var teikt, ka Ŕīs sistÄmas sniedz mums kaut ko lÄ«dzÄ«gu rÅ«pÄ«gi pÄrbaudÄ«tai dokumentÄcijai.
Å Ädu sistÄmu pielietoÅ”anai ir arÄ« citi ieguvumi, kas noteikti nav triviali:
- Veidu pÄrbaudes sistÄma var atklÄt dažas nelielas (kÄ arÄ« ā ne tik nelielas) kļūdas. Tipisks piemÄrs ir tas, kad tiek aizmirsts apstrÄdÄt vÄrtÄ«bu
Nonevai kÄdu citu Ä«paÅ”u nosacÄ«jumu. - Kods ir ÄtrÄk refaktorizÄjams, jo veidu pÄrbaudes sistÄma bieži ļoti precÄ«zi norÄda, kuru kodu jÄmaina. TajÄ paÅ”Ä laikÄ mums nav jÄpÄrliecinÄs par 100% kodu testÄÅ”anas pÄrklÄjumu, kas parasti ir nereÄli. Mums nav jÄiet dziļumos steka pÄdÄjo ziÅojumu izsekoÅ”anÄ, lai noskaidrotu problÄmas cÄloni.
- Pat lielos projektos mypy bieži spÄj veikt pilnÄ«gu tipa pÄrbaudi dažu sekunžu laikÄ. SavukÄrt testu izpilde parasti aizÅem desmitiem sekunžu vai pat minÅ«tes. Tipu pÄrbaudes sistÄma nodroÅ”ina programmÄtÄjam tÅ«lÄ«tÄju atsauksmi un ļauj ÄtrÄk paveikt darbu. ViÅam vairs nav jÄraksta trausli un grÅ«ti uzturami moduļu testi, kas aizvieto reÄlÄs entitÄtes ar moku un plecu palÄ«giem tikai tÄdÄļ, lai ÄtrÄk iegÅ«tu kodÄÅ”anas testu rezultÄtus.
IDE un redaktori, piemÄram, PyCharm vai Visual Studio Code, izmanto tipu anotÄciju iespÄjas, lai nodroÅ”inÄtu izstrÄdÄtÄjiem automÄtiskÄs kodÄÅ”anas pabeigÅ”anas funkcijas, kļūdu izcelÅ”anu un atbalstu bieži izmantotÄm valodas konstrukcijÄm. Un tas ir tikai daži no ieguvumiem, ko sniedz tipizÄcija. Dažiem programmÄtÄjiem tas viss ir galvenais arguments par labu tipizÄcijai. Tas rada labumu tÅ«lÄ«t pÄc ievieÅ”anas. Å is veids, kÄ izmantot tipus, neprasa atseviŔķas tipu pÄrbaudes sistÄmas, piemÄram, mypy, kaut gan jÄatzÄ«mÄ, ka mypy palÄ«dz uzturÄt atbilstÄ«bu tipu anotÄcijÄm un kodam.
mypy priekÅ”vÄsture
mypy stÄsts sÄkÄs ApvienotajÄ KaralistÄ, KembridžÄ, dažus gadus pirms es pievienojos Dropbox. Es veicu doktorantÅ«ras pÄtÄ«jumu par statiski tipizÄtu un dinamisku valodu apvienoÅ”anu. Mani iedvesmoja Džeremija SÄ«eka un ValÄ«da Taha raksts par pakÄpenisku tipizÄciju, kÄ arÄ« projekts Typed Racket. Es mÄÄ£inÄju atrast veidus, kÄ izmantot vienu un to paÅ”u programmÄÅ”anas valodu dažÄdiem projektiem ā no maziem skriptiem lÄ«dz kodu bÄzÄm, kuras sastÄv no vairÄkÄm miljoniem rindiÅu. Man bija svarÄ«gi, lai jebkura mÄroga projektÄ nebÅ«tu jÄveic pÄrÄk lieli kompromisi. SvarÄ«ga Ŕī procesa daļa bija ideja par pakÄpenisku pÄreju no netipizÄta prototipa uz visaptveroÅ”i testÄtu statiski tipizÄtu gatavu produktu. MÅ«sdienÄs Ŕīs idejas lielÄ mÄrÄ tiek uzskatÄ«tas par paÅ”saprotamÄm, taÄu 2010. gadÄ tÄ bija problÄma, kas vÄl joprojÄm tika aktÄ«vi pÄta.
Mana sÄkotnÄjÄ darba joma tipa pÄrbaudÄs nebija vÄrsta uz Python. TÄ vietÄ es izmantoju mazu 'paÅ”darinÄtu' valodu Å is ir piemÄrs, kas ļaus jums saprast, par ko ir runa (tipu anotÄcijas Å”eit nav obligÄtas):
def Fib(n as Int) as Int
if n <= 1
return n
else
return Fib(n - 1) + Fib(n - 2)
end
endVienkÄrÅ”a valoda, kas izstrÄdÄta paÅ”gatavotam projektam, ir parasta pieeja, ko izmanto zinÄtniskajos pÄtÄ«jumos. Tas tÄ ir, ne mazÄkÄ mÄrÄ, jo tas ļauj Ätri veikt eksperimentus, kÄ arÄ« to, kas nav saistÄ«ts ar pÄtÄ«jumu, var brÄ«vi ignorÄt. ReÄli lietotie programmÄÅ”anas valodas parasti ir milzÄ«gas parÄdÄ«bas ar sarežģītÄm realizÄcijÄm, un tas palÄnina eksperimentus. TomÄr jebkuri rezultÄti, kas balstÄ«ti uz vienkÄrÅ”otu valodu, Ŕķiet nedaudz aizdomÄ«gi, jo, iegÅ«stot Å”os rezultÄtus, pÄtnieks varbÅ«t ir upurÄjis apsvÄrumus, kas ir svarÄ«gi valodu praktiskai izmantoÅ”anai.
Mans tipu pÄrbaudes rÄ«ks Alore izskatÄ«jÄs ļoti solÄ«gs, taÄu es vÄlÄjos to pÄrbaudÄ«t, veicot eksperimentus ar reÄlu kodu, kura, teiksim, Alore nebija. Par laimi, valoda Alore lielÄ mÄrÄ balstÄ«jÄs uz tÄm paÅ”Äm idejÄm kÄ Python. Bija vienkÄrÅ”i pÄrveidot tipu pÄrbaudes rÄ«ku, lai tas varÄtu strÄdÄt ar Python sintaksi un semantiku. Tas ļÄva izmÄÄ£inÄt tipu pÄrbaudi atvÄrtÄ koda Python kodÄ. TurklÄt es uzrakstÄ«ju transpaileri, lai pÄrvÄrstu kodu, kas uzrakstÄ«ts Alore, Python kodÄ, un izmantoju to, lai pÄrveidotu mana tipu pÄrbaudes rÄ«ka kodu. Tagad man bija tipu pÄrbaudes sistÄma, kas rakstÄ«ta Python, kura atbalstÄ«ja Python apakÅ”kopu, noteiktu Ŕīs valodas paveidu! (Dažas arhitektÅ«ras izvÄles, kas bija jÄgpilnas Alore, sliktÄk derÄja Python, tas joprojÄm ir redzams dažÄs mypy koda bÄzes daļÄs.)
PatiesÄ«bÄ, valoda, ko atbalstÄ«ja mana tipu sistÄma, Å”ajÄ brÄ«dÄ« ne gluži varÄja saukt par Python: tÄ bija Python variÄcija, kas radusies no dažÄm Python 3 tipu anotÄciju sintakses ierobežojumiem.
TÄ izskatÄ«jÄs kÄ Java un Python sajaukums:
int fib(int n):
if n <= 1:
return n
else:
return fib(n - 1) + fib(n - 2)Viens no manÄm idejÄm tajÄ laikÄ bija izmantot tipu anotÄcijas, lai uzlabotu veiktspÄju, kompilÄjot Å”o Python paveidu C vai iespÄjams, JVM bytecode. Es nonÄcu lÄ«dz prototipa kompilatora rakstīŔanai, bet atstÄju Å”o ieceri, jo tipa pÄrbaude pati par sevi izskatÄ«jÄs pietiekami noderÄ«ga.
Galu galÄ es prezentÄju savu projektu konferencÄ PyCon 2013 SanhojÄ. Es arÄ« par to parunÄju ar Guido van Rossum, žÄlastÄ«bas dzÄ«ves diktatoru Python. ViÅÅ” pÄrliecinÄja mani atteikties no sava sintaksiska un pieturÄties pie standarta Python 3 sintakses. Python 3 atbalsta funkciju anotÄcijas, lÄ«dz ar to manu piemÄru varÄja pÄrformatÄt tÄ, kÄ norÄdÄ«ts zemÄk, iegÅ«stot parastu Python programmu:
def fib(n: int) -> int:
if n <= 1:
return n
else:
return fib(n - 1) + fib(n - 2)Man vajadzÄja piekrist daudziem kompromisiem (pirmkÄrt, gribu atzÄ«mÄt, ka tieÅ”i tÄpÄc es izgudroju savu sintaksi). Proti, Python 3.3, tajÄ laikÄ jaunÄkÄ valodas versija, neatbalstÄ«ja mainÄ«go anotÄcijas. Es pa e-pastu apspriedu ar Guido dažÄdas Å”Ädu anotÄciju sintaktiskÄs noformÄÅ”anas iespÄjas. MÄs izlÄmÄm izmantot komentÄrus ar tipu norÄdÄm, lai sasniegtu iecerÄto mÄrÄ·i, bet tas izskatÄ«jÄs nedaudz neveikli (Python 3.6 mums sniedza patÄ«kamÄku sintaksi):
products = [] # type: List[str] # EwwTipa komentÄri, turklÄt, noderÄja, atbalstot Python 2, kurÄ nav iebÅ«vÄta tipa anotÄciju atbalsta:
f fib(n):
# type: (int) -> int
if n <= 1:
return n
else:
return fib(n - 1) + fib(n - 2)IzrÄdÄ«jÄs, ka Å”ie (un citi) kompromisi patiesÄ«bÄ nebija tik bÅ«tiski ā statiskÄs tipizÄcijas priekÅ”rocÄ«bas noveda pie tÄ, ka lietotÄji drÄ«z vien aizmirsÄ«s par nepilnÄ«go sintaksi. TÄ kÄ tagad Python kodÄ, kurÄ tika kontrolÄti tipi, netika izmantotas Ä«paÅ”as sintaktiskÄs konstrukcijas, esoÅ”ie Python rÄ«ki un procesi, kas apstrÄdÄ kodu, turpinÄja darboties normÄli, kas ievÄrojami atviegloja izstrÄdÄtÄju jaunÄ rÄ«ka apgūŔanu.
Guido, turklÄt, pÄrliecinÄja mani pievienoties Dropbox pÄc tam, kad es aizstÄvÄju savu diplomdarbu. Te sÄkas viss interesantÄkais mypy stÄstÄ.
TurpinÄjums sekosā¦
CienÄ«jamie lasÄ«tÄji! Ja, ja izmantojat Python, lÅ«dzu, pastÄstiet, kÄdu projektu mÄrogu jÅ«s izstrÄdÄjat Å”ajÄ valodÄ.
Avots: habr.com
