2011-03-18 18 views
7

Mi piacerebbe eseguire una sessione su Clojure. Potresti consigliare un problema che può essere risolto elegantemente usando la programmazione funzionale con Clojure? Puoi indicare le risorse che coprono questo argomento?Che cos'è una buona vetrina per Clojure?

+0

Che tipo di sessione? Stai cercando un problema e una soluzione che possa essere spiegata in un'ora, un giorno, una settimana? Ci sono molte possibilità. –

+0

Abbiamo un evento vetrina regolare in tutta la società per mostrare nuove tecnologie. È inteso come 2 ore di mani in sessione. – spa

risposta

12

un sacco di argomenti per l'utilizzo di Clojure sembra essere correlato alla sua gestione della concorrenza, ma non voglio toccare questo tema qui.

Elencherò alcuni problemi che sono costretto ad affrontare settimana dopo settimana con Java e come li ho o li risolverei in Clojure.

Immutabilità

In Java raggiungimento immutabilità è molto molto difficile. Oltre a seguire rigorose pratiche di codifica, dovrai scegliere con cura i tuoi quadri e le tue librerie. Inoltre, come effetto collaterale scriverai molto codice per creare un'API pulita e utilizzabile, o semplicemente costringerai il cliente a gestirlo.

final Person person = personDao.getById(id); 
// I would like to "change" the person's email, but no setters... :(

In Clojure si modella i dati sulla base di strutture di dati immutabili così tutti gli oggetti sono immutabili per difetto e per questo Clojure offre potenti funzioni che operano su queste strutture.

(let [person   (get-by-id person-dao id) 
     person-with-email (assoc person :email email)] 
    ; Use person-with-email... 

Conversioni

In Java di avere una classe di dominio Person con campi id, name, email, socialSecurityNumber e altri. Stai creando un servizio web per recuperare i nomi e le email di tutte le persone nel tuo database. Non si desidera esporre il dominio in modo da creare una classe PersonDto contenente name e email. È stato facile, quindi ora hai bisogno di una funzione per mappare i dati da Person a PersonDto. Probabilmente qualcosa di simile:

public class PersonPopulator { 
    public PersonDto toPersonDto(Person person) { 
     return new PersonDto(person.getName(), person.getEmail()); 
    } 

    public List<PersonDto> toPersonDtos(List<Person> persons) { 
     List<PersonDto> personDtos = new ArrayList<PersonDto>(); 
     for (Person person : persons) { 
      personDtos.add(toPersonDto(person)); 
     } 
     return personDtos; 
    } 
} 

Ok bene che non era così male, ma se si vuole mettere più dati in DTO? Bene il codice costruttore in toPersonDto crescerà un po ', senza preoccupazioni. Cosa succede se ci sono due diversi casi d'uso, uno come sopra e un altro dove vogliamo inviare solo le e-mail? Bene potremmo lasciare il name null (cattiva idea) o creare un nuovo DTO, forse PersonWithEmailDto. Quindi dovremmo creare una nuova classe, alcuni nuovi metodi per popolare i dati ... probabilmente vedi dove sta andando?

Clojure, un linguaggio tipizzato in modo dinamico con strutture di dati immutabili, mi permette di fare questo:

(defn person-with-fields [person & fields] 
    (reduce #(assoc %1 %2 (get person %2)) {} fields)) 

(person-with-fields {:id 1 
        :name "John Doe" 
        :email "[email protected]" 
        :ssn "1234567890"} :name :email) 
; -> {:email "[email protected]", :name "John Doe"} 

E per manipolare una lista di persone:

(map #(person-with-fields % :name :email) persons) 

anche l'aggiunta di dati ad hoc per un sarebbe facile:

(assoc person :tweets tweets) 

E questo non spezzerebbe nulla. In Java, se i tuoi oggetti sono immutabili, probabilmente non hanno setter, quindi dovresti scrivere un bel po 'di codice per modificare un campo (new Person(oldPerson.getName(), oldPerson.getEmail(), tweets), o creare una classe completamente nuova. Gli oggetti mutabili offrono una bella API (oldPerson.setTweets(tweets)), ma sono difficili da testare e capire.

Testing

Un sacco di codice Java si basa su un certo stato, anche quando non v'è alcun bisogno di esso. Ciò significa che è possibile prendere in giro questo stato, il che di solito significa ulteriore standard di stampa e diventa più difficile se non si è creato il codice tenendo a mente la testabilità. D'altro canto, i test senza mock sono solitamente lenti e dipendono dall'accesso o dall'ora del database o da qualcos'altro che di sicuro verrà a mancare su di voi di volta in volta.

Mentre la codifica Clojure ho notato che non ho veramente bisogno dello stato più di tanto. Praticamente le uniche situazioni sono quando sto recuperando qualcosa dal "fuori", sia esso un database o qualche servizio web.

Sommario

mio codice è un tubo, da un'estremità ottengo alcuni dati, questi dati vengono poi cambiato nel tubo tramite filtraggio, trasformandolo o unirsi con altri dati fino alla fine la pipa. All'interno del tubo non è necessario modificare realmente i dati, ma in molti casi sono utili funzioni potenti e strutture di dati immutabili e questo è il motivo per cui Clojure fa miracoli con codice come questo.

+0

Wow, ottimo esempio. – defhlt

+0

Mi è piaciuto il riassunto. Questo è esattamente come mi sentivo mentre lavoravo con Clojure per tre mesi. –

1

Un paio di mesi fa, mi imbatto nello stesso problema e abbiamo deciso di risolvere il problema 'la Gioconda' in Clojure. Il risultato è stato this presentation. Fondamentalmente abbiamo dimostrato che Clojure è estremamente interessante per risolvere problemi per i quali "codice come dati" offre una soluzione elegante. Ad esempio negli algoritmi genetici.

Problemi correlati