Turbūt retas rimtesnis programuotojas nežino šių taisyklių. Jos yra kertinis akmuo norint parašyti gerą kodą. Kaip žinome, KISS (Keep It Simple, Stupid) principas teigia, kad kodą turime rašyti kuo paprasčiau ir aiškiau. Tuo tarpu DRY (Don't Repeat Yourself) sako, kad kodas neturi kartotis. Šios taisyklės, iš esmės, įstumia mus į OOP pasaulį. Nes kitaip tiesiog būtų neįmanoma jų įgyvendinti.
Tačiau kad ir kaip gražiai šios rekomendacijos skambėtų, realus gyvenimas rodo, kad jos ne visada suderinamos, o kartais – kertasi iš esmės. Įtariu, kad tai skamba kontraversiškai, todėl pabandysiu kaip galima aiškiau išdėstyti savo argumentus šiuo klausimu.
Pradėkime nuo KISS. Remiantis OOP logika, metodai turi būti nedideli ir atlikti paprastus veiksmus. Ir tai visiškai suprantama. Kodas tampa skaitomesnis, lengviau atsekti, kas iš kur ateina. Žinoma, kiekvienas programuotojas pats pasirenka, iki kokio smulkumo skaidyti metodus. Ir tai labai priklauso nuo to, kokio lankstumo jis nori. Štai nuo čia įsijungia DRY principas, kuris liepia mums nekartoti kodo ir, jei matome, kad galime kažką iškelti į aukštesnį lygį, tai taip ir darome. Iki kokio lygio bus iškeliama, galima sakyti, irgi individualus programuotojo pasirinkimas.
Bet dabar – turime paradoksą: į kuo aukštesnį lygį iškeliami apdorojantys metodai, tuo painesnė darosi sistema, kadangi beveik visada aukštesnis lygis reiškia sudėtingesnę apdorojimo logiką. Ir jei to nepaisysime, nereikės ilgai laukti, kol turėsime tokią kodo maišalynę, iš kurios ką nors ištraukti ar įdėti bus tikras košmaras.
Kad būtų lengviau įsivaizduoti, apie ką kalbu, paimkime pavyzdį su CRUD (Create, Read, Update, Delete) + ORM (Object Relation Mapping) metodika. Tarkime, apsirašome kiekvieną CRUD metodą. Tai bus mūsų atominis (žemiausias) duomenų apdorojimo lygis. Tada apsirašome metodus kiekvienai duomenų struktūrai, kurią norime apdoroti (įvairiausios patikros (validation), apdirbimai (proccesing) ir t.t.). Berašant neretai pastebime, kad tam tikros duomenų struktūros yra panašios ir iš esmės galima būtų naudoti joms tuos pačius CRUD apdorojimo metodus. Vadinasi, galime iškelti tai į aukštesnį lygį. Bet ar tikrai reikia? Ar noras laikytis DRY principo, nepažeis KISS? Daugumai programuotojų toks pasirinkimas ateina intuityviai. Jie jaučia, ar nepersistengs rašydami paprastai arba lanksčiai. Kitaip sakant, ieškomas aukso viduriukas. Bet tai ateina tik su patirtimi. Pradedantieji visiškai nejaučia šio dalyko, todėl neretai matome kodą, kuris pernelyg supaprastinas ir stipriai pažeidžia DRY. Arba atvirkščiai – per didelis noras visą apdorojimą iškelti į aukščiausią lygį padaro kodą sunkiai prižiūrimą ir įskaitomą.
Žinoma, bet apie KISS ir DRY galima kalbėti ir kitaip. Įsivaizduokime piramidę. Lipimas aukštyn – DRY, lipimas žemyn – KISS. Tačiau programavimo pasaulyje nei vienas, nei kitas kraštutinumas nėra gerai. Jei užlipsime per aukštai, užtruksime daugiau laiko, kol nusileisime žemyn. Ir atvirkščiai. Žinoma, jei būsime apačioje, bus labai lengva įjungti naują apdorojimo metodiką. Tik tam reikės laiko ir kantrybės. Jei būsime aukštai, kardinaliai kitokios metodikos įjungimas taps dar sudėtingesniu dalyku.
Programuotojai dažnai pasirenka du būdus, kaip spręsti šią dilemą: 1. Mąstymas į priekį. 2. Go with the flow + refactoring'as.
Pirmas būdas pats pasako, kad kuriant sistemą reikia stengtis numatyti kaip galima daugiau variantų, kurie gali įvykti jai gyvuojant. Norint taip gerai parašyti, programuotojai turi turėti itin didelę patirtį ir sugebėjimą mąstyti rekursyviai tiek į gylį, tiek į plotį. Deja, patirtis rodo, kad šiuo metodu vadovaujasi dažnai ne itin įgudę programuotojai. Jie prirašo tokio kodo, nuo kurio plaukai šiaušiasi (pats retkarčiais pašiurpstu pažiūrėjęs į savo senesnį kodą).
Antras būdas populiarumu nė kiek nenusileidžia pirmajam ir neretai būna teisingesnis pasirinkimas. Kodas rašomas remiantis jo funkcionalumu DABAR, o ne tuo, koks jis gali būti ar nebūti ateityje. Jį parašius atliekamas refactoring'as. Čia į pagalbą įsijungia Unit testai ir kt. Tačiau kad ir kaip gražiai teoriniame lygyje šis būdas skambėtų, realybė yra kitokia. Pripažinkime, kad ten, kur valanda yra įvertinta pinigais, niekas neduoda laiko kodo šlifavimui. Svarbu – tik veikiantis produktas. Ir jei parašei kodą su mintimi, kad ateityje jį pašlifuosi, tai 99% atvejų su tuo produktu bus problemų.
Bet grįžkime prie DRY ir KISS ir to, kaip jie susiję su programavimo būdais. Kaip ir minėjau, ši teorija išplaukia iš asmeninės patirties. Todėl aš neretai nusižengiu DRY principui. Taip darau todėl, kad visados palieku erdvės pakeitimams, net jei tai reikštų, kad pakeitęs vienur, turėsiu pakeisti ir kitur. Kaip minėjau aprašyme apie CRUD ir ORM – jei iš pažiūros dvi struktūros gali būti iškeliamos į aukštesnį lygį, tai niekas negarantuoja, kad ateityje jos taps tiek skirtingos, jog norint atlikti reikiamus pakeitimus turėsi perrašyti jų apdorojimą. Kam tas vargas? Geriau pasilikti atsargos, kuri leis lengvai ištraukti ar pridėti naują apdorojimo metodiką. Žinoma, čia viskas labai priklauso nuo to, su kokiais duomenimis yra dirbama, kaip apdoromaja ir t.t. Todėl šioje vietoje vieningo sprendimo nėra. Reikalingas aukso viduriukas, kurio radimą lemia tiek asmeninė patirtis, tiek žinios, tiek polinkiai, tiek pati kuriama sistema.
Reziume: be DRY ir be KISS – nė žingsnio, bet nė viena iš jų neturi imti viršaus. Ir jei labai atkakliai taikysime KISS, neišvengsime kartojimosi. O jei išganymu laikysime DRY, turėsime aibę problemų ateityje.
Būtų įdomu sulaukti jūsų komentarų ir pasiūlymų, kaip būtų galima save kontroliuoti, kad perdaug nebūtų nueita į DRY ar KISS šalį. Žinoma, čia jau galima kalbėti apie sistemų architektūras, bet mano žiniomis, tokios, kuri visiškai išspręstų šią dilemą – nėra.
Apie mane: Be programavimo taip pat domiuosi kontraversiškomis idėjomis apie pasaulį apskritai. Man priklauso www.zeitgeist.lt – puslapis, įkurtas remiantis „Zeitgeist The Movie“ dokumentinio filmo idėjomis. Todėl, jei domitės ne tik programavimo klausimais, bet ir globaliais – naudingos informacijos rasite ten.
|