Sot, ne ofrojmë vëmendjen tuaj pjesën e parë të përkthimit të materialit mbi mënyrën se si Dropbox bën kontrollin e tipeve të kodit Python.
NĂ« Dropbox, shkruhet shumĂ« nĂ« Python. Ky Ă«shtĂ« njĂ« gjuhĂ« qĂ« ne e pĂ«rdorim tepĂ«r gjerĂ«sishtâsi pĂ«r shĂ«rbimet backend ashtu edhe pĂ«r aplikacionet klientĂ«s nĂ« desktop. Ne gjithashtu pĂ«rdorim nĂ« masĂ« tĂ« madhe Go, TypeScript dhe Rust, por Python Ă«shtĂ« gjuha jonĂ« kryesore. Duke marrĂ« parasysh pĂ«rmasat tona, e cila pĂ«rfshin miliona rreshta tĂ« kodit Python, u tregua se tipizimi dinamik i kĂ«tij kodi e komplikon nĂ« mĂ«nyrĂ« tĂ« panevojshme kuptimin e tij dhe filloi tĂ« ndikojĂ« seriozisht nĂ« produktivitetin e punĂ«s. PĂ«r tĂ« lehtĂ«suar kĂ«tĂ« problem, filluam procesin graduales tĂ« kalimit tĂ« kodit tonĂ« nĂ« kontrollin static tĂ« tipeve duke pĂ«rdorur mypy. Kjo ndoshta Ă«shtĂ« sistemi mĂ« popullor i pavarur pĂ«r kontrollin e tipeve nĂ« Python. Mypy Ă«shtĂ« njĂ« projekt me burim tĂ« hapur, dhe zhvilluesit e saj kryesorĂ« punojnĂ« nĂ« Dropbox.
Dropbox u bĂ« njĂ« nga kompanitĂ« e para qĂ« futi kontrollin e tipeve statike nĂ« kodin Python nĂ« njĂ« shkallĂ« tĂ« tillĂ«. NĂ« ditĂ«t e sotme, mypy pĂ«rdoret nĂ« mijĂ«ra projekte. Ky mjet Ă«shtĂ« provuar pafundĂ«sisht, siç thuhet, 'nĂ« betejĂ«'. PĂ«r tĂ« arritur aty ku jemi tani, na nevojitej njĂ« rrugĂ« e gjatĂ«. NĂ« kĂ«tĂ« rrugĂ« pati shumĂ« pĂ«rpjekje tĂ« dĂ«shtuara dhe eksperimente tĂ« pakta. Ky material tregon historinĂ« e kontrollit tĂ« tipeve statike nĂ« Pythonânga fillimi i saj i vĂ«shtirĂ«, qĂ« ishte pjesĂ« e projektit tim hulumtues, deri nĂ« ditĂ«t e sotme, kur kontrolli dhe sugjerimet pĂ«r tipe janĂ« bĂ«rĂ« tĂ« zakonshme pĂ«r njĂ« numĂ«r tĂ« pafund zhvilluesish qĂ« shkruajnĂ« nĂ« Python. KĂ«to mekanizma tani mbĂ«shteten nga shumĂ« mjeteâsi IDE dhe analizatorĂ«t e kodit.
â
Pse është e nevojshme kontrolli i tipeve?
NĂ«se keni pĂ«rdorur ndonjĂ«herĂ« Python me tipizim dinamik, mund tĂ« keni disa pyetje rreth zhurmĂ«s qĂ« ka rreth tipizimit statik dhe mypy kĂ«to kohĂ«. Ndoshta ju pĂ«lqen Python pikĂ«risht pĂ«r shkak tĂ« tipizimit tĂ« tij dinamik, dhe ajo qĂ« po ndodh ju shqetĂ«son. ĂelĂ«si i vlerĂ«s sĂ« tipizimit statik Ă«shtĂ« shkalla e zgjidhjeve: sa mĂ« i madh tĂ« jetĂ« projekti juaj, aq mĂ« shumĂ« do tĂ« toni drejt tipizimit statik dhe, pĂ«rfundimisht, aq mĂ« shumĂ« do t'ju nevojitet tĂ« vĂ«rtetĂ« kjo.
Supozoni se një projekt ka arritur të jetë në dhjetëra mijëra rreshta dhe ka disa programues që punojnë mbi të. Duke shqyrtuar një projekt të tillë, ne, në bazë të përvojës sonë, mund të themi se kuptimi i kodit të tij do të jetë çelësi për mbështetje të produktivitetit të zhvilluesve. Pa annotime tipesh, ndonjëherë është e vështirë të zbulohet, për shembull, se cilat argumente duhet të kalohen në një funksion, ose se çfarë llojesh vlerash mund të kthejë një funksion i caktuar. Këtu janë disa pyetje tipike, përgjigjja e të cilave shpesh është e vështirë pa përdorimin e annotimeve tipesh:
- A mund të kthejë ky funksion
Asnjë? - Si duhet të jetë ky argument
items? - Cili është lloji i atributit
id:inta është kjo,str, apo ndoshta një tip përdoruesi? - A duhet të jetë ky argument një listë? A mund të kalojmë një tuple në të?
Nëse e shikojmë fragmentin e mëposhtëm të kodit, që është i pajisur me annotime tipesh, dhe përpiqemi të përgjigjemi ndaj pyetjeve të tilla, do të kuptojmë se kjo është një detyrë e thjeshtë:
class Resource:
    id: bytes
    ...
    def read_metadata(self,
                      items: Sequence[str]) -> Dict[str, MetadataItem]:
        ...read_metadatanuk kthenAsnjĂ«, pasi tipi i kthimit nuk Ă«shtĂ«Optional[âŠ].- Argumenti
itemsâ Ă«shtĂ« njĂ« sekuencĂ« stringjesh. Nuk mund tĂ« iterosh nĂ« tĂ« nĂ« njĂ« rend tĂ« rastĂ«sishĂ«m. - Atributi
idâ Ă«shtĂ« njĂ« string bytes.
Në një botë ideale, do të pritej që të gjitha këto nuanca të ishin të përshkruara në dokumentacionin e integruar (docstring). Por, përvoja ofron shumë shembuj që dokumentacioni i tillë në kodin me të cilin punojmë shpesh mungon. Madje edhe nëse një dokumentacion i tillë është i pranishëm në kod, nuk mund të llogaritet një saktësi e plotë. Ky dokumentacion mund të jetë i paqartë, i pasaktë, duke lënë shumë mundësi për keqkuptime. Në ekipet e mëdha ose në projekte të mëdha, ky problem mund të bëhet jashtëzakonisht akut.
Megjithëse Python jep rezultate të shkëlqyera në fazat e hershme ose të ndërmjetme të projekteve, në një moment të caktuar, projektet e suksesshme dhe kompanitë që përdorin Python mund të përballen me një pyetje jetike: "A duhet të riformatojmë gjithçka në një gjuhë statike të tipizuar?".
Sistemet e verifikimit të tipave si mypy zgjidhin problemin e mësipërm, duke ofruar për zhvilluesit një gjuhë formale për të përshkruar tipat, dhe duke kontrolluar që përshkrimi i tipeve të jetë në përputhje me zbatimin e programeve (dhe, opsionalisht, verifikojnë ekzistencën e tyre). Në përgjithësi mund të thuhet se këto sisteme na ofrojnë diçka si një dokumentacion të kujdesshëm.
Aplikimi i sistemeve të tilla ka avantazhe të tjera, dhe ato janë tashmë mjaft të rëndësishme:
- Sistemi i verifikimit tĂ« tipave mund tĂ« zbulojĂ« disa gabime tĂ« vogla (dhe gjithashtu â edhe jo aq tĂ« vogla). NjĂ« shembull tipik Ă«shtĂ« kur harrojnĂ« tĂ« trajtojnĂ« njĂ« vlerĂ«
Asnjëose ndonjë kush tjetër të veçantë. - Rifaktorimi i kodit bëhet dukshëm më i lehtë, pasi sistemi i verifikimit të tipave shpesh përcakton shumë saktë se cilin kod duhet të ndryshojmë. Në këtë rast, nuk kemi nevojë të llogarisim në një mbulueshmëri 100% të kodit me teste, gjë që, në çdo rast, është zakonsisht e pamundur. Nuk kemi nevojë të studiojmë thellësitë e raporteve të gjurmimit të stack-ut për të zbuluar arsyen e problematit.
- Edhe në projektet e mëdha, mypy shpesh mund të kryejë një kontroll të plotë të tipave në fraza sekondash. Ndërsa ekzekutimi i testeve zakonisht merr disa dhjetëra sekonda ose madje minuta. Sistemi i kontrollimit të tipave ofron programeve një reagim të menjëhershëm dhe u lejon atyre të punojnë më shpejt. Ata nuk kanë nevojë të shkruajnë më teste modulare që janë të brishta dhe të vështira për t'u mbajtur, të cilat zëvendësojnë entitetet reale me mock-e dhe patch-e vetëm për të marrë rezultatet e testeve të kodit më shpejt.
IDE-të dhe redaktuesit, si PyCharm ose Visual Studio Code, përdorin mundësitë e anotacioneve të tipeve për t'iu ofruar zhvilluesve funksionalitet për autokompletimin e kodit, ndriçimin e gabimeve, dhe mbështetje për konstrukte gjuhësore të zakonshme. Dhe këto janë vetëm disa nga përfitimet që ofron tipizimi. Për disa programues, të gjitha këto janë argumenti kryesor në favor të tipizimit. Kjo është ajo që sjell dobi menjëherë pas zbatimit në punë. Ky rast përdorimi i tipeve nuk kërkon përdorimin e një sistemi të veçantë të kontrollit të tipeve, si mypy, megjithatë, duhet theksuar se mypy ndihmon në ruajtjen e përputhshmërisë midis anotacioneve të tipeve dhe kodit.
Historia e mypy
Historia e mypy nisi nĂ« MbretĂ«rinĂ« e Bashkuar, nĂ« Kembrixh, disa vjet para se unĂ« tĂ« bashkohesha me Dropbox. UnĂ« u angazhvova, nĂ« kuadĂ«r tĂ« njĂ« studimi doktoraturĂ«, me pyetjen e unifikimit tĂ« gjuhĂ«ve statikisht tĂ« tipizuara dhe dinamikisht tĂ« tipizuara. NjĂ« artikull nga Jeremy Siek dhe Walid Taha mbi tipizimin gradual mĂ« inspiroi, si dhe projekti Typed Racket. UnĂ« po pĂ«rpiqesha tĂ« gjeja mĂ«nyra pĂ«r tĂ« pĂ«rdorur tĂ« njĂ«jtĂ«n gjuhĂ« programuese pĂ«r projekte tĂ« ndryshme â nga skenarĂ«t e vegjĂ«l deri te bazat e kodit qĂ« pĂ«rbĂ«heshin nga miliona rreshta. NĂ« tĂ« njĂ«jtĂ«n kohĂ«, dĂ«shiroja qĂ« nĂ« çdo projekt, pavarĂ«sisht nga madhĂ«sia, tĂ« mos ishte e nevojshme tĂ« bĂ«heshin kompromise tĂ« mĂ«dha. NjĂ« pjesĂ« e rĂ«ndĂ«sishme e gjithĂ« kĂ«saj ishte ideja e kalimit gradual nga njĂ« prototip i pa tipizuar i projektit nĂ« njĂ« produkt tĂ« gatshĂ«m statikisht tĂ« tipizuar tĂ« testuar mirĂ«. NĂ« ditĂ«t e sotme, kĂ«to ide priren tĂ« pranohen si tĂ« drejta, por nĂ« vitin 2010 kjo ishte njĂ« problem qĂ« ende po hetohej aktivisht.
Puna ime fillestare në fushën e kontrollit të tipeve nuk ishte e orientuar drejt Python. Në vend të tij, unë përdorja një gjuhë të vogël 'të bëra vetë' Ja një shembull që do t'ju ndihmojë të kuptoni se për çfarë po flitet (annotimet e tipeve këtu janë opsionale):
def Fib(n as Int) as Int
  if n <= 1
    return n
  else
    return Fib(n - 1) + Fib(n - 2)
  end
endPërdorimi i një gjuhë të thjeshtë të zhvilluar vetë është një qasje e zakonshme e aplikuar në hulumtime shkencore. Kjo është ndoshta për shkak se një gjë e tillë lejon realizimin e eksperimenteve shpejt, si dhe për faktin se ata gjëra që nuk kanë lidhje me hulumtimin mund të injorohen pa pengesa. Gjuhtët e programimit realisht të përdorura zakonisht përbëjnë fenomene masive me realizime komplekse, dhe kjo e ngadalëson eksperimentin. Megjithatë, çdo rezultat i bazuar në një gjuhë të thjeshtë duket paksa dyshues, pasi gjatë marrjes së këtyre rezultateve, hulumtuesi mund të ketë sakrifikuar konsiderata që janë të rëndësishme për përdorimin praktik të gjuhëve.
Mjeti im për kontrollin e tipeve për Alore dukej mjaft premtues, por dëshiroja ta provonja atë duke realizuar eksperimente me kod real, të cilin mund të thuhet se nuk kishte në Alore. Për fat të mirë, gjuha Alore në masë të madhe ishte bazuar në të njëjtat ide si Python. Ishte mjaft e thjeshtë të ripërpunoja mjetin për kontrollin e tipeve në mënyrë që të punonte me sintaksën dhe semantikën e Python. Kjo më lejoi të provonja kontrollin e tipeve në kodin open-source të Python. Për më tepër, shkrova një transpajler për të transformuar kodin e shkruar në Alore në kodin Python dhe e përdora atë për të përkthyer kodin e mjetit tim për kontrollin e tipeve. Tani kisha një sistem për kontrollin e tipeve të shkruar në Python, që mbështeste një nëngrup të Python, një lloj të këtij gjuhe! (Disa zgjidhje arkitekturore që kishin kuptim për Alore, nuk ishin të përshtatshme për Python, kjo ende duket në disa pjesë të bazës së kodit mypy.)
Në të vërtetë, gjuha e mbështetur nga sistemi im i tipeve, në atë moment, nuk mund të quhej plotësisht Python: ishte një variacion i Python për shkak të disa kufizimeve të sintaksës së annotimeve të tipeve Python 3.
Dukej si një përzierje e Java dhe Python:
int fib(int n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)Një nga idetë e mia në atë kohë ishte të përdorja annotime tipesh për të përmirësuar performancën duke kompajluar këtë lloj Python-i në C, ose ndoshta në kodin byte të JVM. Arrita deri në fazën e shkruarjes së një prototipi të kompajlerit, por e lashë këtë përpjekje, pasi verifikimi i tipeve vetë duket se ishte mjaft i dobishëm.
Në fund, e prezantova projektin tim në konferencën PyCon 2013 në Santa Clara. Diskutova gjithashtu për këtë me Guido van Rossum, diktatorin jetësor të Python-it. Ai më bind të heq dorë nga sintaksa ime dhe të qëndroj në sintaksën standarde të Python 3. Python 3 mbështet annotimet e funksioneve, si rezultat shembulli im mund të rishkruhej siç shihet më poshtë, duke marrë një program normal Python:
def fib(n: int) -> int:
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)Më duhej të shkoja në disa kompromise (duhet të theksoj se shpika sintaksën time pikërisht për këtë arsye). Në veçanti, Python 3.3, versioni më i ri i gjuhës në atë kohë, nuk mbështeste annotimet e variablave. Diskutova me Guido përmes emailit mundësitë e ndryshme të formatizimit sintaksor të këtyre annotimeve. Vendosëm të përdorim komentet me tipe për variablat. Kjo lehtësoi arritjen e qëllimit, por dukej disi e ngarkuar (Python 3.6 na dha një sintaksë më të rehatshme):
products = [] # type: List[str] # EwwKomentet me tipe, për më tepër, ishin të dobishme për mbështetje të Python 2, i cili nuk ka mbështetje të brendshme për annotimet e tipeve:
def fib(n):
    # type: (int) -> int
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)Doli se kĂ«to (dhe kompromise tĂ« tjera) nĂ« tĂ« vĂ«rtetĂ« nuk kishin ndonjĂ« rĂ«ndĂ«si tĂ« madhe â pĂ«rfitimet e tipizimit statik çuan nĂ« faktin se pĂ«rdoruesit shpejt e haruan sintaksĂ«n jo pĂ«rkryer. Tani, nĂ« kodin Python, ku kontrolloheshin tipet, nuk pĂ«rdoren asnjĂ« strukturĂ« sintaksore e veçantĂ«, kĂ«shtu qĂ« mjetet dhe proceset ekzistuese tĂ« pĂ«rpunimit tĂ« kodit vazhduan tĂ« funksiononin normalisht, gjĂ« qĂ« e lehtĂ«soi ndjeshĂ«m mĂ«simin e kĂ«tij instrumenti nga zhvilluesit.
Guido gjithashtu më bind të bashkohem me Dropbox pas mbrojtjes së provimit tim. Këtu fillon e gjithë historia interesante e mypy.
To be continued...
Të nderuar lexues! Nëse përdorni Python, ju lutemi na tregoni për projektet e cila shkalla po zhvilloni në këtë gjuhë.
Burimi: habr.com
