2011-03-18 24 views
7

Me gustaría ejecutar una sesión sobre Clojure. ¿Podría recomendar un problema que se puede resolver de forma elegante mediante la programación funcional con Clojure? ¿Puedes señalar recursos que cubren este tema?¿Qué es un buen escaparate para Clojure?

+0

¿Qué tipo de sesión? ¿Está buscando un problema y una solución que pueda explicarse en una hora, un día o una semana? Hay muchas posibilidades –

+0

Tenemos un evento de exhibición regular de toda la compañía para mostrar nuevas tecnologías. Está destinado a ser una sesión de 2 horas. – spa

Respuesta

12

Una gran cantidad de argumentos para utilizar Clojure parece estar relacionada con el manejo de concurrencia, pero no voy a tocar ese tema aquí.

Voy a enumerar algunos problemas que estoy obligado a tratar semana tras semana con Java y cómo los he solucionado en Clojure.

inmutabilidad

En Java inmutabilidad logro es muy, muy difícil. Además de seguir estrictas prácticas de codificación, tendrá que elegir sus marcos y bibliotecas con mucho cuidado. Además, como efecto colateral, escribirás una gran cantidad de código para crear una API limpia y utilizable, o simplemente forzarás al cliente a manejarlo.

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

En Clojure modelar sus datos en base a estructuras de datos inmutables por lo que todos los objetos son inmutables por defecto y debido a esta Clojure ofrece potentes funciones que operan sobre estas estructuras.

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

Conversiones

En Java tiene una clase de dominio Person con campos id, name, email, socialSecurityNumber y otros. Está creando un servicio web para recuperar los nombres y correos electrónicos de todas las personas en su base de datos. No desea exponer su dominio para crear una clase PersonDto que contenga name y email. Eso fue fácil, así que ahora necesita una función para mapear los datos de Person a PersonDto. Probablemente algo como esto:

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; 
    } 
} 

bien Está bien que no era tan malo, pero lo que si usted quiere poner más datos en el DTO? Bueno, el código de constructor en toPersonDto crecerá un poco, sin preocupaciones. ¿Qué pasa si hay dos casos de uso diferentes, uno como el anterior y otro en el que queremos enviar solo los correos electrónicos? Bueno, podríamos dejar name nulo (mala idea) o crear un nuevo DTO, quizás PersonWithEmailDto. Entonces creamos una clase nueva, algunos métodos nuevos para poblar la información ... ¿probablemente ve a dónde va esto?

Clojure, un lenguaje de tipos dinámicos con estructuras de datos inmutables, me permite hacer esto:

(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"} 

Y para manipular una lista de personas:

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

también la adición de datos ad hoc a una persona sería fácil:

(assoc person :tweets tweets) 

Y esto no rompería nada. En Java, si tus objetos son inmutables, probablemente no tengan setters, por lo que tendrías que escribir muchos boilerplates solo para modificar un campo (new Person(oldPerson.getName(), oldPerson.getEmail(), tweets)), o crear una clase totalmente nueva. Los objetos mutables ofrecen una buena API (oldPerson.setTweets(tweets)), pero son difíciles de probar y comprender.

Prueba

Una gran cantidad de código Java se basa en algún estado, incluso cuando no hay necesidad de hacerlo. Esto significa que puede simular este estado, lo que generalmente significa una repetición adicional y se vuelve más difícil si no ha creado su código con capacidad de prueba en mente. Por otro lado, las pruebas sin simulaciones suelen ser lentas y dependen del acceso a la base de datos o del tiempo u otra cosa que seguramente le fallará de vez en cuando.

Durante la codificación de Clojure, he notado que realmente no necesito indicar mucho. Prácticamente las únicas situaciones son cuando estoy recuperando algo del "exterior", ya sea una base de datos o algún servicio web.

Resumen

Mi código es un tubo, de un extremo consigo algunos datos, estos datos se modifican después en el tubo a través de la filtración, transformar o incorporarse a ella con algunos otros datos hasta que llega al final de el tubo. Dentro de la tubería no hay necesidad de cambiar realmente los datos, pero hay muchos casos en los que las funciones poderosas y las estructuras de datos inmutables son útiles y esta es la razón por la cual Clojure funciona de maravilla con un código como este.

+0

Guau, buen ejemplo. – defhlt

+0

Me gustó el resumen. Así es exactamente como me sentí trabajando con Clojure durante tres meses. –

1

Hace un par de meses me encontré con el mismo problema y decidimos resolver el problema de "Mona Lisa" en Clojure. El resultado fue this presentation. Básicamente demostramos que Clojure es extremadamente bueno para resolver problemas para los cuales el 'código como datos' brinda una solución elegante. Por ejemplo en algoritmos genéticos.

Cuestiones relacionadas