Funkcinis ir objektyvus programavimas

Sveiki, vaikinai, atsiprašau už vėlavimą tarp straipsnių. Šiame straipsnyje kalbėsiu apie skirtumą tarp FP (funkcinio programavimo) ir OOP (objektinio programavimo) ir kada geriausia juos naudoti.

Viską, ką galite padaryti su vienu stiliumi, dažniausiai galite padaryti su kitu stiliumi. Tačiau vienas gali būti geresnis už kitą, atsižvelgiant į problemą, kurią bandote išspręsti. Stiliai neriboja, kokias programas rašote, bet tai, kaip jas rašote. Nepaisant to, nė vienas stilius nėra geriausias. Geriausia žinoti abu, todėl bet kurią situaciją galite lengviausiai išspręsti. Taigi, eikime į tai!

Objektinis programavimas

Tai yra labiausiai žinoma paradigma. Kaip rodo pavadinimas, visa tai yra objektas. Objektuose yra ir duomenų, ir su jais susijusių funkcijų. Geriausia buvo tai apibūdinti naudojant automobilio analogiją.

Abstrakcija:
Negalite pasistatyti automobilio vienu ypu. Jūs turite padalyti jį į mažesnius gabalus. Ne tokia maža, kad būtų kuo mažesnė detalė. Bet ne toks didelis, kad taptų per didelis valdyti. Iš esmės, jūs suskaidote sudėtingą objektą į mažesnius komponentus.

Inkapsuliacija:
Suskaidę automobilį iki jo dalių. Jūs turite galvoti apie tų dalių savybes. Pvz .: padangos spindulys ir plotis bei naudojimas. Ta pačia prasme jūs sukonstruosite savo automobilį sudėję visus gabalus: objekto kompoziciją. Apsiuvimas iš esmės yra duomenų grupavimas ir funkcionalumas norint juos naudoti. Tai daro jūsų kodą labiau modulinį.

Paveldimumas:
Yra daugybė padangų rūšių. Sniego padangos, žieminės padangos, vasarinės padangos ir tt Visos jos turi panašias savybes ir tam tikrus skirtumus. Nenorėtumėte kiekvienai padangai rašyti atskiros klasės. Geriausias dalykas, kurį reikia padaryti, yra sukurti šabloną, kuriame yra bendrosios savybės, ir tada sukurti specialias klases, kuriose yra specializuotas kodas. Iš esmės jūs esate specialios padangos, kurias paveldite iš tėvų: Tai daro jūsų kodą daugkartinio naudojimo.

Polimorfizmas:
Tai paskutinė dalis. Kai vairuojate automobilį, jums nereikia žinoti, kaip viskas veikia. Norėdami sąveikauti su automobiliu, naudojate dujų pedalą, vairą ir pavarų perjungimą. Turite vieną ar daugiau sąsajų, skirtų bendrauti su visa programa, ir jūs neturite supratimo apie vidinį kodo veikimą. Tai užtikrins, kad niekas kitas, išskyrus jus, kūrėjas negali suklaidinti jūsų kodo.

Funkcinis programavimas

Funkcinio programavimo klavišas yra pavadinime: funkcijos. FP yra apie nekintamumą ir funkcijų komponavimą, o ne objektus. Peržvelkime pagrindinius bruožus tikrai greitai:

Funkcijos yra pirmos klasės. Jie gali būti perduoti, dinamiškai sukurti, saugoti duomenų struktūrose ir elgtis kaip su bet kuriuo kitu pirmos klasės objektu.

Naudokite grynas funkcijas. Gryna funkcija yra funkcija, neturinti jokio šalutinio poveikio. Programuodami grynosiomis funkcijomis, pastebėsite padidėjusį moduliškumą, kuris palengvina kodo tikrinimą, pakartotinį naudojimą, lygiagretinimą, apibendrinimą ir pagrindimą.

Funkcijas galima sudaryti. Tai panašu į kapsuliavimą OOP. Galite sukurti didesnes funkcijas derindami mažesnes funkcijas. Atminkite, kad funkcijos yra aukščiausios klasės.

Pirmenybė teikiama posakiams, o ne teiginiams. Išraiškos derlingumo vertės. Pareiškimai nėra ir yra padėti jums kontroliuoti programos eigą.

Duomenys nekintami. Užuot pakeitę duomenų struktūrą, efektyviai sukuriate naują.

Duomenys yra transformuojami, o ne modifikuojami. Kadangi duomenys yra nekintantys, jie turi būti pakeisti. Taigi, perduodant duomenų struktūrą funkcijai, pasirodo nauja, o įvesta - nepakeista.

Bendra gija yra ta, kad nėra jokio šalutinio poveikio. Bet ką tai reiškia? Kaip jūs galite parašyti, kad neturi jokio šalutinio poveikio?

Šalutinis poveikis reiškia, kad kodas neturi pilietybės. Programos vykdymui nėra jokio kito pastebimo poveikio, išskyrus apskaičiuoti rezultatą atsižvelgiant į jos įvestis. Taip yra dėl referencinio skaidrumo idėjos. Išraiška yra santykinai skaidri, jei visoms programoms visus išraiškos atvejus programoje galima pakeisti išraiškos įvertinimo rezultatu, nepažeidžiant stebimos programos elgsenos.

Pavyzdžiui: 1 + 2 visada bus lygus 3. Ta prasme, tai yra gryna funkcija, nes išvestis niekada nesikeičia pagal duotas įvestis. Taigi visur, kur matote „1 + 2“, galite tiesiog pakeisti jį 3 ir nematyti jokio neigiamo poveikio bendrai vykdant programą.

Referencinis skaidrumas leidžia jums pasinaudoti pakeitimo modeliu. Galite galvoti apie posakius, kaip tai darytumėte algebroje. Galite išspręsti didelę lygtį pakeisdami kintamuosius jų reikšmėmis ir sumažinti ją iki paprasčiausios formos. Jūs pakeičiate lygius į lygius.

Kaip matote dešinėje, x yra referenciškai skaidrus. Nesvarbu, kiek kartų jūs skambinate atgaline tvarka ar kokiu nors kitu metodu, išvesties vertė visada yra ta pati. Nėra jokio šalutinio poveikio. Taigi galite pakeisti x faktine jo verte ir vis tiek gauti tą patį išvestį. Tai puiku, kai rašote kodą, kurį reikia paleisti vienu metu; jums nereikia jaudintis dėl šalutinio poveikio, dėl kurio gali kilti problemų. Dabar pažiūrėkime kodą su šalutiniu poveikiu.

Kaip matote, atvirkštinė „StringBuilder“ funkcija yra gryna, tačiau pridėjimo funkcija nėra. Kiekvieną kartą paskambinus pridedama, išėjimo vertė keičiasi. Tai reiškia, kad jis nėra referenciškai skaidrus. Tuo pačiu metu tai gali būti pražūtinga. Nesijaudinkite, bet bet kurią funkciją, turinčią šalutinį poveikį, galima suskaidyti į gryną pagrindinę funkciją ir vieną ar daugiau funkcijų, turinčių šalutinį poveikį.

Pereikime prie kodo, pateikto aukščiau pateiktame pavyzdyje. Mes sukūrėme funkciją deklaruoti nugalėtoją, kuri išspausdina aukščiausią balą surinkusį grotuvą. Paprasta tiesa? O kas, jei norėtume rasti žaidėją, kurio sąraše ar kitoje duomenų struktūroje yra didžiausias balas? O kas, jei norėtume pakartotinai naudoti kodo dalis? Negaliu to tiksliai padaryti atlikdamas pirmąjį „dekreWinner “apibrėžimą.

Bet jei funkciją padalintume į gryną funkciją ir tą, kuri turi šalutinį poveikį. Mes galime padaryti būtent tai. Kaip matote, mes galime patekti į žaidėjų sąrašą ir labai lengvai rasti žaidėją su aukščiausiu balu. Tai taip pat padarė mūsų kodą labiau modulinį ir leidžia mums sudaryti funkcijas.

Imperatyvus programavimas

Tai paprasčiausiai yra programavimas su teiginiais, modifikuojančiais programos būseną. Iki šiol tai darėme su OOP ir FP. Išplečiant, galite maišyti FP ir OOP principus pagal poreikį. Jie vienas kito neišskiria. Tai tiesiog galimybės optimaliai išspręsti tam tikras problemas.

Pvz .: „Java“ yra klasikinė OOP kalba. Tačiau, kaip „Java 8“, jis tapo funkcionalesnis palaikant „lambda“ funkcijas. Tai nėra visiškai funkcionalus, bet jis ten pasiekiamas.

Naudojimo atvejai

Naudojant FP, reikia atsiminti, kad konkrečios įvesties išvestis visada bus vienoda, o įvestis visada yra nekintama. Būsenos pokyčių nėra. Taigi, kai jums reikia parašyti saugų siūlų kodą, eikite į FP.

Naudojant OOP, būsenos pokyčiai yra norma. Konkretus įėjimas ne visada lemia tą patį išėjimą. Pvz .: pagalvokite apie paieškos variklį. „Google“ ne visada pateikia tuos pačius rezultatus tuo pačiu paieškos klavišu. Tai prieštarauja FP principams. Taigi šiuo atveju naudokite OOP.

Yra daugiau situacijų, kai viena gali būti geresnė už kitą. Atminties sunaudojimas yra didesnis OOP, nes viskas yra objektas. Kiekvieną kartą pridedant naują elementą, FP turi sukurti naują nekintančios duomenų struktūros kopiją. Kiekvienas iš jų turi savo trūkumų.

Tikimės, kad tai buvo gana geras abiejų skirtumų aprašymas. Kažkada aš padarysiu įrašą apie FP dizaino modelius. Akivaizdu, kad jie skirsis nuo OOP. Taigi, tikrai svarbu juos žinoti. Taigi, budėkite!

Kaip mane jaučia FP ir OOP.

Redaguoti

Norėčiau atkreipti dėmesį į keletą dalykų:

„Java“ nėra visiškai OOP kalba. Jis turi primityvius ir statinius narius, nė vienas iš jų nėra objektai. Tačiau „Scala“ yra visiškai OOP kalba. Žinoma, galite rašyti programas, kurios yra „FP“ ir „OOP“ mišinys „Scala“. Bet „Scala“ viskas yra objektas, net funkcijos.

Taigi, kodėl verta rinktis „Java“? Na, „Scala“ palaiko visas FP koncepcijas, o „Java“ palaiko tik keletą. Tai suteikia prieigą prie daugybės galingų konstrukcijų, tokių kaip modelių atitikimas ir tt. Turite prieigą prie bet kurios „Java“ prieinamos bibliotekos. Galiausiai ji veikia JVM. Jis gali veikti ne tokiu greičiu kaip „Java“ kodas, tačiau jūs perkate keletą mikrosekundžių visam funkcionalumui.

Kalbant apie naudojimo atvejus, leiskite man papasakoti apie tai, ką jau sakiau.

Jei turite sukurti vartotojo sąsają, aišku, jūs eisite su OOP. Viskas šioje situacijoje yra objektas.

Jei turite daug skirtingų susijusių duomenų tipų, kurie dalijasi funkcionalumu ir planuojate ateityje sukurti daugiau, greičiausiai turėsite pasinaudoti palikimu. Tai leis jums sukurti modulinį ir daugkartinį kodą. Eik su OOP.

Jei turite tik kelis duomenų tipus, tačiau turite atlikti daug su jais susijusių operacijų ir mažai tikėtina, kad ateityje pridėsite naujų tipų, paveldėjimo nereikia. Eik su FP.

Jei konkreti operacija gali būti modeliuojama kaip matematikos operacija, eikite su FP. Tai gali atrodyti painu, todėl išplėsiu. Tarkime, kad norite parašyti programą, kurioje būtų sudėti dalykai. Tai galite padaryti naudodamiesi OOP, tačiau tai daug lengviau padaryti naudojant FP. Objekto akimirksniu paėmimas užima laiko ir vietos. Kodėl nerimauti dėl viso to?

FP paprastai yra puikus modeliuojant operacijas, kurios, atrodo, atitinka matematinį modelį (pvz .: rekursiniai metodai). Jei galite modeliuoti programą kaip matematinį įrodymą, eikite su FP. Tai sąžiningai geriausias patarimas, kurį galiu jums duoti.

Nei viena iš šių paradigmų viena kitos neatmeta. Galite parašyti geresnes programas, jei naudojate abiejų derinį. Jums tiesiog reikia žinoti, kada naudoti kurį. Taigi, eik eksperimentuoti!