Functions without side effects
Pročítal jsem si na webu nějaké materiály o funkcionálním programování. Jedním ze základních principů je, že funkce nesmí mít vedlejší efekty (side effects). Výčet a definice těchto principů se v různých zdrojích liší, mne konkrétně oslovily tyto:
- Pokud je funkce volána s parametry, které nezpůsobují vedlejší efekty, její opakované volání (se stejnými parametry) vrací vždy stejný výsledek.
- Funkce nesmí měnit vstupní parametry a globální proměnné.
- Funkce nesmí měnit své chování na základě stavů definovaných mimo funkci.
Tyto principy se samozřejmě dají použít v jakémkoli typu programování, tedy i nejrozšířenějším OOP. A pokud se při vývoji používá TDD, nebo aspoň člověk zodpovědně píše unit testy, dojde k těmto principům zcela přirozeně.
Proč vlastně o něčem takovém (možná triviálním) píšu? Dopisoval jsem teď nedávno unit testy k hotové aplikaci a čas od času jsem narazil na kód, který porušoval všechny tři výše uvedené principy zároveň. Takový kód se samozřejmě velice špatně a také velice pracně testuje. Pro představu:
private void checkSMS() {
if (sms == OperationEnum.ADDED) {
if (servis24 == OperationEnum.ADDED
|| servis24 ==
OperationEnum.NOT_CHANGED) {
codeOperationsList.add(OperationCodeEnum
.FILING_SMS_WITH_S24
.getCode());
} else {
codeOperationsList.add(OperationCodeEnum
.FILING_SMS_WITHOUT_S24
.getCode());
}
}
}
Když to vezmu odspoda:
- Funkce se rozhoduje na základě (globálních) flagů
sms
aservis24
. - Funkce mění globální/instanční proměnnou
codeOperationList
. - Funkce vrací
void
. Tedy ať už dělá cokoliv, je to side efect.
(Předchozí ukázka je samozřejmě z Javy, takže s/funkce/metoda/g
.)
No a jaké z toho všeho plyne poučení? Pište funkcionální metody! A pište unit testy! Aplikace pak půjde líp otestovat. Lépe spravovat. A po čase snadněji porozumíte kódu.