Preskoči na sadržaj

Tri vrste grešaka u dizajn sistemu koje TypeScript i ESLint propuste

U 75 komponenti našao sam 188 propusta, a svi su se sveli na tri uzroka: labele na čvorovima bez role, propove koje komponenta prihvati pa odbaci i zastarjele komentare.

4 min čitanja5 sekcija

Napravio sam cross-platform dizajn sistem. U vrijeme pregleda imao je 75 komponenti, tri targeta, 430 testova i oko 2.450 linija vlastitog koda za provjeru. Sve sam to pregledao čitajući kod i našao 188 propusta.

Svih 188 propusta svelo se na tri korijenska uzroka, a sva tri prolaze kroz cijeli toolchain: TypeScript, ESLint i build. Svaka automatska provjera koju sam imao pokazala je da je kod u redu.

Za svaki uzrok sam tražio razlog zbog kojeg ga nijedan alat ne prijavi, jer se tek tada nalaz iz pregleda može pretvoriti u pravilo koje će uhvatiti sljedeći slučaj.

01

Labela na čvoru koji nema rolu

accessibilityLabel na čvoru koji nema rolu ne izgovara nijedna platforma.

Na webu aria-label na golom elementu div ne radi ništa. Tako to definiše ARIA specifikacija: generička rola ne prihvata ime koje zada autor. Atribut postoji, ispravno je napisan i ignoriše se.

Na nativnoj strani accessibilityLabel bez accessible nikad se ne pročita. Labela je u stablu, ali je ništa ne čita.

Devet komponenti u mom sistemu imalo je ovaj problem. Labele su bile napisane upravo zbog pristupačnosti, a čitač ekrana nije izgovorio ništa.

Nijedan alat to ne prijavi jer je atribut validan: ima pravo ime, pravi tip i na pravom je mjestu. Statičko pravilo po kojem ovaj atribut ne znači ništa ako uz njega nema i drugog atributa bilo bi u opštem slučaju pogrešno. Takvo pravilo vrijedi samo za ovaj par atributa, na ovoj vrsti čvora.

Tih devet sam pronašao zato što je ispravan obrazac već postojao u istom paketu: Icon svoju labelu uvijek uparuje sa role="img". Kad sam vidio slučaj koji radi, pokvarene sam mogao pronaći pretragom koda, umjesto da pregledam komponentu po komponentu.

Od ovoga je nastalo pravilo provjere. Ako labela nema rolu, build sada pada.

02

Propovi koje tipovi prihvate, a komponenta odbaci

Komponenta prima Omit<BoxProps, 'as' | 'ref'>. Time u javnom ugovoru ostaju id, a11yRole, accessibilityLabel i pointerEvents, pa tipovi govore pozivaocu da ih smije proslijediti, a pozivaoci to i rade.

Ali grana koja ih ne destrukturira eksplicitno prosljeđuje ih dalje u ...box, u pomoćnu funkciju za stilove koja vraća samo propove s prefiksom $. Ta funkcija propove potroši i odbaci, pa oni nikad ne stignu do elementa.

Alati ne prijave ništa jer je izostavljen prop undefined, a undefined je validna vrijednost za opcioni prop. Ništa nije pogrešno tipizirano, pa nema ni greške tipa. Ugovor je obećao samo to da će prop biti prihvaćen.

Sistem tipova ne modelira razliku između toga da je prop prihvaćen i da je upotrijebljen. Hoće li prop biti upotrijebljen, zavisi od implementacije u runtimeu, a to se u potpisu ne može izraziti.

Imao sam četiri srodne komponente koje su povezivale tri različita podskupa tih propova. Jedna je prosljeđivala sva četiri propa, dvije su prosljeđivale po dva, ali ne ista dva, a jedna nijedan. Imale su isti osnovni tip i istu namjenu, ponašale su se na četiri različita načina i svaka je prošla typecheck.

Našao sam to poređenjem srodnih komponenti. Kad se čita zasebno, svaka od njih izgleda ispravno. Kad ih čitate jednu uz drugu, nedosljednost se vidi za nekoliko sekundi.

03

Komentari koji opisuju raniju verziju sistema

Komentar spominje neko ograničenje. Kasnije se ograničenje ukloni, a komentar ostane.

Od tri vrste, na ovu bih najviše upozorio, jer se kod ponaša ispravno, a šteta je u onome u šta developeri počnu vjerovati. Developer pročita da nešto nije podržano, povjeruje u to i zaobilazi ograničenje koje je prestalo postojati prije šest mjeseci. Kod koji napiše ispravan je, ali nepotreban, a niko to nikad ne sazna.

Postoji i gora varijanta. Tokom jedne izmjene JSDoc blok se pomjerio za jedan prop, pa je jedan prop imao dva opisa, a njegov susjed nijedan. To je dovoljno loše već u editoru. U mom sistemu dokumentacija se generiše iz izvornog koda u katalog, pa je pogrešan opis postao javna dokumentacija tog propa.

Nijedan alat ovo ne uhvati jer je riječ o komentaru, a ništa u JavaScript toolchainu ne provjerava je li tekst tačan. Linteri provjeravaju je li JSDoc pravilno oblikovan, ali ne mogu znati opisuje li ono što kod radi.

Druge dvije vrste imaju oblik koji se može tražiti. Za ovu treba znati šta sistem trenutno radi i uporediti to s onim što tvrdi komentar, a to se saznaje samo čitanjem koda. Od sve tri, samo ovu i dalje mora uhvatiti čovjek.

04

Pitanja koja nijedna provjera ne postavlja

Svaka automatska provjera odgovara na jedno pitanje. Typecheck pita odgovaraju li vrijednosti tipovima, lint pita poštuje li sintaksa pravila, a build pita kompajlira li se kod.

Nijedna ne pita radi li atribut išta, stiže li prop do elementa i je li rečenica u komentaru još tačna. To su pitanja o tome šta kod znači, a to nijedan alat u lancu ne provjerava.

05

Šta sam promijenio

Dvije od tri vrste postale su pravila provjere. Osim pravila za labele bez role, sada se svaki prop deklarisan u ugovoru mora moći pratiti do elementa. Treća vrsta nije postala pravilo, jer tu pravilo nema šta provjeriti.

Veća promjena bila je u samom pregledu. Tražiti i popravljati 188 pojedinačnih propusta bilo bi rasipanje truda. Kad sam pronašao tri uzroka i popravio njih, sljedećih stotinu propusta je spriječeno, a ne pronađeno.

Pregled sam trebao uraditi kad je sistem imao 30 komponenti, umjesto da čekam da ih bude 75. Sva tri uzroka postojala su već kod 30 komponenti. Tada bi ih bilo jeftinije popraviti, a svaka komponenta napravljena poslije naslijedila bi ispravan obrazac umjesto pokvarenog.

Vaši uzroci bit će drugačiji od ova tri. Ali i za vas važi da je pregled koji stane na nalazima urađen samo napola. Druga polovina je pronaći uzroke tih nalaza, a taj dio posla poskupljuje sa svakom novom komponentom napravljenom po pokvarenom obrascu.

Kako je nastao ovaj tekstIz pregleda cross-platform dizajn sistema koji sam napravio za Next.js, React Native i Vite SPA.Pročitajte više o projektu →Povezana uslugaPristupačnostPogledajte uslugu →Sljedeći tekstTestiranje dizajn sistema na pravoj stranici: 7 komponenti i 8 nedostatakaPročitajte →

Blog

Ako radite na nečemu sličnom, javite nam se s detaljima.

Prvi poziv traje 30 minuta i ni na šta vas ne obavezuje.

Opišite nam svoj projekatcontact@microtech.consulting