Dove mettiamo il codice "chiedendo al mondo" quando separiamo il calcolo dagli effetti collaterali?


10

Secondo il principio di Separazione comando-query , oltre a Pensare nei dati e DDD con presentazioni Clojure, si dovrebbero separare gli effetti collaterali (modificando il mondo) da calcoli e decisioni, in modo che sia più facile capire e testare entrambe le parti.

Questo lascia una domanda senza risposta: dove relativamente al limite dovremmo porre "chiedere al mondo"? Da un lato, la richiesta di dati da sistemi esterni (come database, API dei servizi estetici, ecc.) Non è referenzialmente trasparente e quindi non dovrebbe stare insieme con puro codice computazionale e decisionale. D'altra parte, è problematico, o forse impossibile, stuzzicarli a parte la parte computazionale e passarli come argomento come perché potremmo non sapere in anticipo quali dati potremmo aver bisogno di richiedere.


1
È qui che entrano in gioco i concetti di callback. Se non si conosce in anticipo quali dati potrebbero essere necessari, fornire una richiamata al codice computazionale in cui è possibile specificare quali dati sono necessari e fare in modo che gli altri layer eseguano il recupero e la fornitura effettivi . Se deve essere asincrono, il callback potrebbe persino specificare un'altra funzione da chiamare con i dati recuperati quando sono diventati disponibili.
Marjan Venema,

1
@MarjanVenema, questa è l'unica opzione che mi viene in mente. Solo dal punto di vista teorico: se il metodo, altrimenti privo di effetti collaterali, invoca callback con effetti collaterali, diventa efficace. Probabilmente il mio problema qui è che presumo che il calcolo della separazione dagli effetti collaterali richieda che il calcolo sia referenzialmente trasparente. Anche se non è necessario vero.
Alexey,

1
Se questa è la tua preoccupazione, il tuo calcolo semplicemente non è abbastanza preciso. È necessario astrarre il processo decisionale su quali altri dati / passaggi sono necessari. Quindi dividi il calcolo completo in passaggi in base a dove vengono prese le decisioni su quali dati sono necessari. Quindi avere una sorta di "regista" che gestisce il flusso di lavoro per il calcolo completo: avviare ogni passaggio, recuperare informazioni da ogni passaggio, utilizzarlo per decidere il passaggio successivo e i dati necessari, avviare un processo di recupero per ottenerlo e quindi passare i dati recuperati al passaggio successivo nel calcolo.
Marjan Venema,

Risposte:


1

D'altra parte, è problematico, o forse impossibile, stuzzicarli a parte la parte computazionale e passarli come argomento come perché potremmo non sapere in anticipo quali dati potremmo aver bisogno di richiedere.

Questa è un'istanza in cui, come notato nei commenti, la capacità di recuperare dati (ad es. Funzione di prima classe, un oggetto che implementa un'interfaccia, ecc.) Fornisce un comodo meccanismo per isolare gli effetti collaterali.

Una funzione di ordine superiore il cui corpo è puro ha purezza non fissata: http://books.google.com/books?id=Yb8azEfnDYgC&pg=PA143#v=onepage&q&f=false

Ho scritto su questo, definendo questo tipo di funzione una funzione potenzialmente pura: http://adamjonrichardson.com/2014/01/13/potentially-pure-functions/

Se combini una funzione potenzialmente pura con funzioni fall-through (che mancano di strutture ramificate e fanno il meno possibile), una combinazione che chiamo set di isolamento, puoi isolare gli effetti collaterali in modo abbastanza efficace e creare un codice molto verificabile: http: // adamjonrichardson.com/2014/01/15/isolating-side-effects-using-isolation-sets/


0

Memorizzi il risultato nella classe, all'inizio sembra un po 'strano, ma risulta in un codice più semplice. ad es. nessuna variabile temporanea nel chiamante.

class database_querier
    feature -- queries
        was_previous_query_ok : boolean is
            do
                Result = …
            end

        previous_query_result : string is 
            requires
                was_previous_query_ok
            do
                Result = query_result
            end

    feature -- commands
        query_db (…) is
            do
                …
                query_result = bla
            end

    feature {none} --data
        query_result : string

1
Adoro vedere eiffel fuori allo stato brado.
SBI

@sbi è solo uno pseudo codice. :-)
ctrl-alt-delor

Abbastanza vicino da rendermi felice;)
SBI
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.