¿Cómo se modelan los programas clojure/lisp como un diagrama?
(6)
Bueno, UML está profundamente arraigado en el diseño OO (con C ++!), Por lo que será muy difícil mapear un enfoque funcional con UML. No conozco a Clojure tan bien, pero es posible que pueda representar cosas que se parecen a las clases e interfaces de Java (¿protocolos?), Para todas las demás será muy difícil. FP es más como una serie de transformaciones de entrada a salida, no hay un diagrama UML claro para eso (¿tal vez diagramas de actividad?). Los diagramas más comunes son para la estructura estática y la interacción entre objetos, pero no son realmente útiles para el paradigma de FP. Dependiendo de su objetivo, los componentes y los diagramas de despliegue pueden ser aplicables.
He intentado colocar mis diagramas de clojure en lo que está disponible en UML, usando bloques de clase como los espacios de nombres a nivel de archivo y enlaces de dependencia para mostrar relaciones, pero es incómodo y tiende a desalentar los patrones funcionales. También he intentado desarrollar soluciones ad-hoc, pero no puedo descubrir una solución que funcione tan bien como UML con, digamos, Java (los gráficos dirigidos simples parecen funcionar de manera vaga, pero esto no detalla los resultados) suficiente). Además, no estoy encontrando nada en la web sobre esto.
Solo para ser claros, no estoy tratando de hacer nada sofisticado como la generación de código; Solo estoy hablando de diagramas de lápiz y papel principalmente para mi propio beneficio. Supongo que no soy la primera persona que ha considerado esto para un lenguaje simple.
¿Qué soluciones se han propuesto? ¿Hay algún estándar de uso común? ¿Que recomiendas? ¿Qué herramientas utilizas?
Creo que es menos sobre el lenguaje y más sobre su modelo conceptual. Si está tomando un enfoque de "procesamiento de flujo", entonces un diagrama de red de flujo de datos podría ser el correcto, como en algunos de los diagramas de Esquema en SICP . Si está adoptando un enfoque más orientado a objetos (que está bien soportado en Lisp), los diagramas de actividad UML podrían tener más sentido.
Depende de lo que quieras describir en tu programa.
Dependencias
Use diagramas de clase para modelar las dependencias entre espacios de nombres; en este caso, es más claro si usa paquetes en lugar de clases en un diagrama.
También puedes usar diagramas de clase para modelar dependencias entre actores
Flujo de datos
También puede usar Diagramas de comunicación para modelar el flujo de datos en su programa. En este caso, represente cada espacio de nombres como una entidad y cada función como un método de esa entidad.
O, en el caso de los actores, representa a cada actor como una entidad y cada mensaje como un método.
En cualquier caso, no es útil tratar de describir el algoritmo de su programa en UML. En mi experiencia, están mejor descritos en los comentarios en el archivo fuente.
Mi idea personal es modelar el flujo de los datos y no la estructura del código porque, por lo que he visto de grandes proyectos de Clojure (no realmente tan grandes), el diseño del código tiende a ser realmente aburrido, con una enorme pila de composites. Utilidades y una clase que los enlaza con las transacciones de mapas, redure y STM.
Clojure es muy flexible en el modelo que elija, por lo que es posible que desee ir al revés. primero haga el diagrama y luego elija las partes y los patrones del lenguaje que expresan claramente el modelo que construyó.
No creo que algo como UML sea una buena opción para Clojure. UML está más bien centrado en el paradigma orientado a objetos que generalmente se desalienta en Clojure.
Cuando estoy haciendo programación funcional, tiendo a pensar mucho más en términos de datos y funciones :
- ¿Qué estructuras de datos necesito? En Clojure, esto generalmente se reduce a definir una estructura de mapa para cada entidad importante con la que estoy tratando. Una simple lista de campos es a menudo suficiente en casos simples. En casos más complejos con muchas entidades diferentes, probablemente querrá dibujar un árbol que muestre la estructura de sus datos (donde cada nodo en el árbol representa un mapa o tipo de registro)
- ¿Cómo fluyen estas estructuras de datos a través de diferentes funciones de transformación para obtener el resultado correcto? Idealmente, estas son funciones puras que toman un valor inmutable como entrada y producen un valor inmutable como salida. Típicamente los bosquejo como una tubería / diagrama de flujo .
Si has pensado bien en lo anterior, entonces la conversión al código Clojure es bastante fácil.
- Defina una o más funciones de construcción para sus estructuras de datos y escriba un par de pruebas para demostrar que están funcionando
- Escriba las funciones de transformación de abajo hacia arriba (es decir, consiga que las operaciones más básicas funcionen y se prueben primero, luego compóngalas juntas para definir las funciones más grandes). Escribir pruebas para cada función.
- Si necesita funciones de utilidad para GUI o IO, etc., escríbalas a pedido según sea necesario.
- Péguelo todo, probando en el REPL para asegurarse de que todo funcione.
Tenga en cuenta que los archivos de origen normalmente también se estructurarán en la secuencia enumerada anteriormente, con funciones más elementales en la parte superior y funciones compuestas de nivel superior hacia la parte inferior. No debería necesitar ninguna dependencia circular (eso es un mal olor de diseño en Clojure). Las pruebas son críticas: en mi opinión, mucho más importante en un lenguaje dinámico como Clojure que en un lenguaje OOP tipificado estáticamente.
La lógica general de mi código suele ser las últimas líneas de mi archivo de código fuente principal.
Yo también he estado luchando con esto. Encuentro que los diagramas de flujo funcionan muy bien para funciones y datos básicos. Es fácil mostrar los datos y el flujo de datos de esa manera. Los condicionales y la recursión son directos. Los diagramas de secuencia / colaboración UML pueden capturar algo de la misma información bastante bien.
Sin embargo, una vez que empiezas a usar HOF, esto no funciona en absoluto.
Los diagramas UML normales para paquetes funcionan bien para los espacios de nombres, no es que eso haga mucho.