Fortumo test-ülesanne
Ühel ilusal sügispäeval tatsasin ma Fortumosse, et seal ühe valvsa arendaja pilgu all neile jupike koodi kirjutada.
Nädala eest sai seal end juba intervjueerida lastud, ning nüüd siis taheti testida, kas ma üldse koodi kirjutada mõistan. Muidugimõista olin ärevuses – kas suudan nad ära petta?
Võiks ju arvata, et ärevuseks polnud põhjust. Olin ma ju paari aasta eest Ameerikamaal edukalt ära petnud suure Sencha korporatsiooni. Mis siis nüüd väike kodumaine firmake ära pole? Aga eks tea ju iga sagedasem Juu-Tuubi vaataja, et tüüpiline Ühendriikide kodanik oma tarkusega teps mitte ei hiilga. Ning seda võin takkajärgi ka ise kinnitada - kui on tarvis anda hinnanguid skaalal „Halb – Keskmine – Hea“, siis valib USAkas harilikult „Suurepärase“. Eestis seevastu peab olema palju ettevaatlikum, sest on Eestlase jaoks ju parim toit teine Eestlane. Suurim kiitus, mis siin maal saada võib, on „Pole paha“.
Nii ma sinna siis läksin. Süda rinnus värisemas, pea läbikukkumise mõtteid täis, ja sisikond ärevusest keerlemas. Hea, et suutsin veel käed värisemast hoida – viimane oleks mulle koheselt progemiskeelu toonud.
Sedapuhku polnud minu partneriks mitte pea progemisboss, vaid üks pulgake allpool olev progeja. Sikutasin oma rüperaali lauale ning asusime asja kallale.
Ülesanne
Esialgseks ülesandeks oli luua monitoorija, mis kontrolliks kas Fortumo veebileht on üleval, ning probleemi korral saadaks e-postiga teavituse. Hiljem lisandusid siia veel vajadused:
-
Saata lisaks e-postile ka SMS.
-
Kontrollida, et veebileht poleks tühi.
-
Konfiguratsioonifail seadete mugavamaks määramiseks.
-
Kontrollida, et server ei ületaks vastuse saatmisel ajalimiiti. Ja saata teavitus vaid juhul kui vähe pikema aja jooksul kõik päringud üle limiidi lähevad.
Seejuures päris E-posti ja SMS-e saata ei tulnud - piisas vaid paarist väljamõeldud objektist, mis sellist teenust näiliselt osutasid.
Seega, minu suureks õnneks, ei midagi tehniliselt ega algoritmiliselt keerukat, sest oleks ma pidand Bayes’ filtreid kasutama, oleksin kahtlemata omadega käpuli olnud.
Mu ülesandeks jäi hoopis organiseerida programm nõnda, et see inimestele võimalikult loetav oleks. Lahe! Sest sellel alal oli mul lausanisti petuskeemi ette valmistatud. Nimelt, olin just lugenud üpris suurepärast Sandi Metzi raamatut „Practical Object-Oriented Design in Ruby,“ mis oli mu tarkvara disaini rakukesi just sedapidi loksutanud, et ma kõigele sellele tiba süstemaatilisemalt läheneda suudaks.
Lahendus
Otsustasin kirjutada võimalikult lihtsa skriptikese, mis lõputus tsüklis serveri pihta päringuid saadab:
Teavituste saatmiseks koostasin klassid MailNotifier
ja
SmsNotifier
. Millest lihtsa tsükliga üle käidi.
Seadete jaoks tegin lihtsa Ruby faili, mis defineeris globaalse
CONF
konstandi:
Erinevate serveri probleemide eristamiseks sai aga üks purakas if
:
See kahtlemata näeb halb välja, sest kontrollitakse argumendi klassi,
mille alusel erinevaid vea-teateid väljastatakse. Kuid ma ei näe, et
seda kuigivõrd paremini lahendada saaks - Net::HTTP
teavitab oma
päringute staatusest kõigi nende erinevate klasside läbi, ning ma
lihtsalt pean nende kõigiga tegelema. Ainus mis ma teha saan, on
kontsentreerida viited nendele klassidele kuhugi ühte kohta nii, et
need mööda kogu mu programmi laiali ei kanduks, ning seda ma püüdsingi teha.
Hilisema arutelu käigus jõudsime selleni, et kogu Net::HTTP
-ga
suhtlemine tuleks sulgeda väikese fassaadi taha, mis kõik need klassid
endasse peidaks. Lisaks aitaks tolle teegi välja eraldamine tublisti
kaasa testimisele.
Suuremaks pähkliks osutus aga viimane punkt: päringu ajalimiit. Eeskätt vajadus teavitus välja saata alles siis kui teatud aja jooksul on kõik päringud ajalimiidi ületanud.
Mõistagi polnud probleem selle nõude arvutile selgeks tegemises. Kui aga üritasin seda loogikat kenasse objektide keelde panna, ei tahtnud mul see mitte kuidagi välja kukkuda. Lõpuks jooksis mu mõistus päris puntrasse, ja ma tundsin, et nüüd ja siinsamas saabubki mu haletsusväärne lõpp.
Viimase õlekõrrena nõudsin endale paberit ja pliiatsit, et segased mõtted kääruliste ajusagarate vahelt puhtale lõuendile maalida. Ja mõningal määral see aitaski.
Ma küll ei suutnud seda loogikat ilusaks muuta, kuid vähemasti kapseldasin ta ühte klassi, et kõik see karvane värk ühes kohas kontrolli all hoida:
Rahule ma sellega muidugi ei jäänud, ja ütlesin niiviisi ka oma hindajale, ent ma ei suutnud tol hetkel ka midagi paremat välja mõelda. Seega kauni koodi koha pealt lõppkokkuvõttes ikkagi mõningane läbikukkumine.
Eks näis siis, kas ja kuidas see nüüd nende koguarvamust minust mõjutab…
Jätkumõtted
Kuna ma eelneva lahendusega siiski päris rahule ei jäänud, siis
nuputasin selle StatusHandler
klassi kallal ja jõudsin lõpuks
lahenduseni, kus ma staatuskoodi asemel saadan update
meetodile
hoopis staatuse objekti, mis teab ise kui pikk tema puhul ooteaeg on
enne teavituse väljasaatmist:
Sedaviisi ei pea StatusHandler
rakendama erikohtlemist Timeout
tüüpi veale, vaid arvestab potentsiaalse ooteajaga iga
staatusemuudatuse puhul. Kommentaare ja tühje ridu arvestamata on uus
kood täpselt sama pikk kui vana.
Täiendatud kood Githubis (koos selle ja mõningate teiste parandustega).