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 a servis24.
  • 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.