OK, quindi il titolo è un po 'clickbaity ma seriamente sono stato su un tell, non chiedere calcio per un po'. Mi piace come incoraggia i metodi da utilizzare come messaggi in modo orientato agli oggetti. Ma questo ha un fastidioso problema che mi ha sconvolto nella testa.
Sono arrivato a sospettare che un codice ben scritto possa seguire contemporaneamente i principi OO e i principi funzionali. Sto cercando di conciliare queste idee e il grande punto critico su cui sono arrivato è return
.
Una funzione pura ha due qualità:
Chiamarlo ripetutamente con gli stessi input dà sempre lo stesso risultato. Ciò implica che è immutabile. Il suo stato è impostato solo una volta.
Non produce effetti collaterali. L'unico cambiamento causato dal chiamarlo sta producendo il risultato.
Quindi, come si fa a essere puramente funzionali se si è giurato di usare return
come modo di comunicare i risultati?
Il tell, non chiedere idea funziona utilizzando ciò che alcuni considererebbero un effetto collaterale. Quando ho a che fare con un oggetto non lo chiedo del suo stato interno. Gli dico quello che devo fare e usa il suo stato interno per capire cosa fare con quello che gli ho detto di fare. Una volta che lo dico, non chiedo cosa abbia fatto. Mi aspetto solo che abbia fatto qualcosa per quello che gli è stato detto di fare.
Penso a Tell, Don't Ask come qualcosa di più di un nome diverso per l'incapsulamento. Quando uso return
non ho idea di come mi abbia chiamato. Non posso parlare del suo protocollo, devo forzarlo a gestire il mio protocollo. Che in molti casi viene espresso come stato interno. Anche se ciò che è esposto non è esattamente stato, di solito è solo un calcolo eseguito su argomenti di stato e input. Avere un'interfaccia per rispondere attraverso offre la possibilità di massaggiare i risultati in qualcosa di più significativo dello stato interno o dei calcoli. Questo è il passaggio di messaggi . Vedere questo esempio .
Nel lontano passato, quando in realtà le unità disco contenevano dischi e una chiavetta USB era ciò che facevi in macchina quando la ruota era troppo fredda per toccarla con le dita, mi hanno insegnato come le persone fastidiose considerino le funzioni che hanno parametri fuori. void swap(int *first, int *second)
sembrava così utile, ma siamo stati incoraggiati a scrivere funzioni che hanno restituito i risultati. Quindi ho preso a cuore questo sulla fede e ho iniziato a seguirlo.
Ma ora vedo persone che costruiscono architetture in cui gli oggetti lasciano che il modo in cui sono stati costruiti controlla dove inviano i loro risultati. Ecco un esempio di implementazione . L'iniezione dell'oggetto porta di output sembra un po 'come l'idea del parametro out da capo. Ma è così che gli oggetti Tell-Don't-Ask raccontano agli altri cosa hanno fatto.
Quando ho appreso per la prima volta degli effetti collaterali, l'ho pensato come il parametro di output. Ci è stato detto di non sorprendere le persone facendo in modo che alcuni dei lavori si svolgessero in modo sorprendente, cioè non seguendo la return result
convenzione. Ora certo, so che c'è un mucchio di problemi di threading asincrono parallelo con cui si nascondono gli effetti collaterali, ma il ritorno è davvero solo una convenzione che ti fa lasciare il risultato spinto nello stack in modo che qualunque cosa tu chiami, possa saltar fuori in seguito. Questo è tutto.
Cosa sto davvero cercando di chiedere:
È return
l'unico modo per evitare tutta quella sofferenza dell'effetto collaterale e ottenere la sicurezza del thread senza blocchi, ecc. O posso seguire dire, non chiedere in modo puramente funzionale?