Javascript callback design: è OK avere effetti collaterali?

3

Considera questa funzione javascript:

function(){
    var someArr = [...];
    var someObj = {...};
    someArr.forEach(function(item){
        if (matchItem(item)){
            someObj.callMethod(item.someProp);
        }
    });
}

Supponendo che il codice dato funzioni correttamente, diamo un'occhiata al suo design. Come puoi notare, someArr.forEach riceve una funzione di callback. Nel frattempo, l'oggetto someObj appartiene all'ambito di tale callback. Quindi dall'interno della funzione di callback possiamo manipolare someObj .

I.e., in questo caso il callback produce effetti collaterali.

Potremmo anche associare someObj a this oggetto del callback:

function(){
    var someArr = [...];
    var someObj = {...};
    someArr.forEach(
        function(item){
            if (matchItem(item)){
                this.callMethod(item.someProp);
            }
        },
        someObj
    );
}

Ancora una volta, stiamo producendo alcuni effetti collaterali qui, anche se in modo più esplicito. In generale, questo approccio non può essere considerato funzionale, in quanto viola il principio di assenza di effetti collaterali.

Come dovremmo progettare il codice in tali situazioni? In che modo è più robusto? Quali sono le migliori pratiche?

Grazie!

    
posta iTollu 08.05.2015 - 12:38
fonte

1 risposta

4

Il Array.prototype.forEach è significato per effetti collaterali, non restituisce nulla. Che ti piaccia o meno dipende dalla tua applicazione, non esiste una best practice chiara.

La programmazione orientata agli oggetti è stateful by design , è pensata per effetti collaterali e per oggetti che cambiano altri oggetti, questo è l'intero punto.

La programmazione funzionale è immutable by design *, l'idea è che hai poco o nessun effetto collaterale nella tua applicazione, eccetto al limite della tua applicazione (Tu devo esercitare l'output in qualche modo, questo è un effetto collaterale). In genere si desidera che ogni funzione accetti l'input, lo elabora in qualche modo e quindi restituisce un output, senza modificare alcuno degli oggetti immessi.

* Non è del tutto preciso. Il funzionale incoraggia l'immutabilità e ci sono linguaggi funzionali che applicano la regola degli effetti senza effetti collaterali, ma puoi produrre effetti collaterali nella programmazione dello stile funzionale.

Personalmente, mi piace di più lo stile funzionale, tengo i miei oggetti immutabili o il più immutabili possibile. Posso garantire che se ho

var obj = {hello: 'world'};

Alla fine dell'ambito, obj sarebbe ancora {hello: 'world'} , indipendentemente dalle funzioni in cui è stato inoltrato. Nessuna delle funzioni l'ha modificata lungo la strada .

TL; DR - Non ci sono chiare migliori pratiche qui. Va bene avere effetti collaterali, purché tu sia consapevole dei rischi che le cose cambiano sotto i tuoi piedi.

    
risposta data 07.09.2015 - 12:48
fonte

Leggi altre domande sui tag