Referencinis skaidrumas programavime – kas tai ir kodėl svarbu

Sužinokite, kas yra referencinis skaidrumas programavime, kodėl grynos funkcijos svarbios ir kaip tai gerina našumą, saugumą bei kodo patikimumą.

Autorius: Leandro Alegsa
Referencinis skaidrumas yra kompiuterių programų dalių savybė. Programa ar jos dalis vadinama referentiškai skaidria, jei ją galima pakeisti gauta verte (išraiška gali būti pakeista jos rezultatu), nepakeičiant programos elgsenos. Kitaip tariant, referentiškai skaidri funkcija visada grąžina tą pačią reikšmę priimdama tą pačią įvestį ir neturi jokių šalutinių poveikių - dalių, kurios atlieka kitą veiksmą, išskyrus vertės grąžinimą. Priešingybė yra referentinis neskaidrumas, kai funkcijos rezultatas arba elgsena priklauso nuo išorinių būsenų arba pati funkcija keičia būseną.

Matematinis ir programavimo požiūris

Matematikoje funkcijos, apibrėžtos kaip matematinės, yra referentiškai skaidrios: jos tik priima parametrus ir grąžina reikšmę. Programavime dažnai pasitaiko skirtumas — funkcija gali nuskaityti sistemos laiką, generuoti atsitiktinius skaičius, skaityti ar rašyti failus, keisti globalią būseną arba išspausdinti tekstą į ekraną. Tokios elgsenos sukelia neskaidrumą. Dėl šio skirtumo kai kuriose kalbose ir kontekstuose tas, kas atlieka veiksmus, vadinama ne funkcija, o procedūra — nes procedūra gali keisti būseną arba turėti šalutinių poveikių.

Kodėl referencinis skaidrumas svarbus

Referencinis skaidrumas leidžia programuotojams ir kompiliatoriams galvoti apie kodą kaip apie perrašymo sistemą — išraiškas galima laisvai keisti jų reikšmėmis. Tai suteikia daug praktinių privalumų:
  • Lengviau įrodyti programos teisingumą ir nustatyti, kad ji atitinka specifikacijas — dėl lygybių savybės galima naudoti ekvacinį (equational) samprotavimą.
  • Algoritmo supaprastinimas — sudėtingesnes išraiškas galima tiesiog pakeisti jų rezultatais, siekiant supaprastinti arba optimizuoti skaičiavimus.
  • Paprastesnis kodo keitimas ir refaktorizacija — keičiant funkcijų diegimą, jos elgsena nepasikeičia, jei lieka gryna.
  • Galimybė optimizuoti našumą ir atminties naudojimą — grynas kodas leidžia saugiai taikyti keletą optimizacijų.

Įprastos optimizacijos ir kaip jas įjungia skaidrumas

Pastarąją užduotį galima atlikti keliais būdais — referencinis skaidrumas tiesiogiai leidžia jas naudoti ir užtikrina, kad jos būtų saugios:
  • Memoizavimas (rezultatų saugojimas po pirmo paskaičiavimo) — saugu saugoti funkcijos rezultatą, jei žinome, kad pakartotinai gavus tą patį argumentą rezultatas bus tas pats.
  • Bendrų neišraiškų šalinimas (common subexpression elimination) — kelis kartus skaičiuojama ta pati išraiška, todėl ją galima pakeisti vienu skaičiavimu.
  • Tingus vertinimas (lazy evaluation) — išraiška apskaičiuojama tik tuomet, kai jos rezultatas iš tikrųjų reikalingas.
  • Lygiagretinimas — nepriklausomi skaičiavimai gali būti vykdomi tuo pačiu metu be tarpusavio sinchronizacijos problemų, kai jie neturi šalutinių poveikių.

Pavyzdys (idėja)

Grynai funkcinėje funkcijoje f(x) = x * 2, jei visuomet tas pats įvesties x duoda tą patį rezultatą, galima drąsiai keisti f(4) į 8 kur tik randama, arba saugoti 8 ir neapskaičiuoti kiekvieną kartą. Tuo tarpu funkcija, kuri skaito failą ar generuoja atsitiktinius skaičius, nėra referentiškai skaidri, todėl tokių pakeitimų taikyti negalima be papildomų apribojimų.

Kaip praktikoje užtikrinti ar padidinti skaidrumą

- Rašykite kuo daugiau grynų funkcijų: mažinkite priklausomybę nuo globalių kintamųjų ir I/O operacijų. - Izoliuokite šalutinius poveikius: naudokite griežtą sluoksniavimą, kur vienas sluoksnis atlieka verslo logiką (gryną), o kitas — I/O bei būsenos valdymą. - Naudokite nekintamą (immutable) duomenų struktūrą, kad būtų mažiau netikėtų būsenos pakeitimų. - Įprasinkite perduoti priklausomybes per parametrus (dependency injection), o ne skaityti jas tiesiogiai iš globalių šaltinių. - Apsvarstykite funkcinio programavimo kalbas arba efektų sistemas (monadas, efektų įrašai), jei reikia griežtai atskirti skaidrias ir ne skaidrias dalis.

Apribojimai ir realybės

Visos programos, kurios dirba su I/O, vartotojo sąsaja ar aparatine įranga, tam tikru mastu turi šalutinių poveikių — visiškai „bešalutinis“ programavimas ne visada praktiškas. Todėl realiose sistemose siekiama maksimaliai atskirti grynas dalis nuo negrynų ir valdyti algoritmų bei optimizacijų saugumą. Funkcinės kalbos (pvz., Haskell) ir kai kurios impozicijos bei bibliotekos suteikia įrankius, leidžiančius aiškiai modeliuoti ir kontroliuoti efektus. Apibendrinant: referencinis skaidrumas — tai galingas konceptas, kuris palengvina programų formalų samprotavimą, testavimą, optimizavimą ir paralelizavimą. Net jei negalima jo pasiekti visuose programos komponentuose, verta siekti kuo didesnio atvirumo ir viešo šalutinių poveikių valdymo, kad gauta nauda būtų didžiausia.

Klausimai ir atsakymai

Klausimas: Kas yra referencinis skaidrumas?


A: Nuorodomasis skaidrumas - tai kompiuterių programų dalių savybė, kai programos dalį galima pakeisti jos grąžinama verte, nekeičiant programos elgsenos.

K: Kas yra referentinio skaidrumo priešingybė?


A: Referentinio skaidrumo priešingybė yra referentinis neskaidrumas.

K: Ar visos matematikos funkcijos yra referentiškai skaidrios?


Atsakymas: Taip, visos matematikos funkcijos yra referentiškai skaidrios, nes matematinė funkcija gali tik priimti reikšmes ir išmesti reikšmę.

K: Kaip referencinis skaidrumas padeda programuotojams ir kompiliatoriams?


A. Referencinis skaidrumas leidžia programuotojams ir kompiliatoriams mąstyti apie kodą kaip apie perrašymo sistemą - kažką, kas priima išraišką ir pakeičia ją kažkuo kitu. Tai padeda spręsti tokias užduotis, kaip programos ar kodo teisingumo įrodymas, algoritmo supaprastinimas, lengvesnis kodo keitimas, kai vis dar esame tikri, kad jis daro tai, ką turi daryti, ir greitesnis kodo veikimas ar mažesnės atminties naudojimas.

K: Kokie metodai naudojami siekiant, kad kodas veiktų greičiau arba naudotų mažiau atminties?


A: Kai kurie metodai, naudojami siekiant, kad kodas veiktų greičiau arba naudotų mažiau atminties, yra šie: memoizavimas (atsakymų išsaugojimas po pirmojo karto), bendrų neišraiškų eliminavimas (nustatymas, ar verta sujungti dvi tas pačias kodo dalis), tingus įvertinimas (atsakymo neradimas, kol kodo tikrai nereikia) ir lygiagretinimas (darbas su keliais uždaviniais vienu metu).

Klausimas: Ar programavimo funkcijos skiriasi nuo matematikos funkcijų?


Atsakymas: Taip, programavimo funkcijos skiriasi nuo matematikos funkcijų - Programuojant funkcija taip pat gali sužinoti, kokia dabar metų diena, arba išspausdinti pranešimą į ekraną, o matematinių funkcijų atveju tai neįmanoma.


Ieškoti
AlegsaOnline.com - 2020 / 2025 - License CC3