¿Hay algún equivalente de Haskell-land al Bundler et. De Ruby-land? Al y, de no ser así, ¿cómo se construiría un proyecto tan estructurado?

Nota para los lectores : tengan paciencia conmigo. Prometo que hay una pregunta.


Tengo un problema que resolver y pensar para mí mismo “Oh, lo haré en Ruby”.

$ bundle gem problemsolver create problemsolver/Gemfile create problemsolver/Rakefile create problemsolver/.gitignore create problemsolver/problemsolver.gemspec create problemsolver/lib/problemsolver.rb create problemsolver/lib/problemsolver/version.rb Initializating git repo in /tmp/harang/problemsolver 

Elimine el comentario en s.add_development_dependency "rspec" en problemsolver/problemsolver.gemspec y luego

 $ bundle exec rspec --init The --configure option no longer needs any arguments, so true was ignored. create spec/spec_helper.rb create .rspec 

Las nuevas pruebas entran en spec/ y deben estar en archivos que terminan en _spec.rb . Por ejemplo, spec/version_spec.rb

 describe 'Problemsolver' do it 'should be at version 0.0.1' do Problemsolver::VERSION.should == '0.0.1' end end 

Para ejecutar las especificaciones, los corredores de cambio de código de ignorning como guard – son triviales:

 $ bundle exec rspec . Finished in 0.00021 seconds 1 example, 0 failures 

No puedes verlo, pero el mensaje está bien codificado por colores para un rápido “¿Me equivoqué?” ¿exploración? Las cosas que son muy buenas sobre esto:

  • La configuración fue rápida, casi sin cerebro (aunque averiguar qué órdenes invocar no es trivial).
  • El diseño estandarizado del árbol de origen reduce el período de familiarización con una nueva base de código, lo que hace que la colaboración sea más simple y reduce el tiempo de inactividad cuando se retira un proyecto que ha dejado un poco.
  • Una gran dependencia de las herramientas distribuye las mejores prácticas a través de la comunidad, aproximadamente a la velocidad de la creación de nuevos proyectos.

Agregar herramientas de cobertura, observadores de códigos, linters, herramientas de prueba de comportamiento y otros no es más difícil.


Esto contrasta desfavorablemente con la situación si uno piensa: “Oh, lo haré en Haskell”.

 $ mkdir problemsolver $ cd problemsolver/ $ cabal init Package name [default "problemsolver"]? Package version [default "0.1"]? 0.0.1 Please choose a license: 1) GPL 2) GPL-2 3) GPL-3 4) LGPL 5) LGPL-2.1 6) LGPL-3 * 7) BSD3 8) MIT 9) PublicDomain 10) AllRightsReserved 11) OtherLicense 12) Other (specify) Your choice [default "BSD3"]? Author name? Brian L. Troutwine Maintainer email [default "brian@troutwine.us"]? Project homepage/repo URL? Project synopsis? Solves a problem. Project category: 1) Codec 2) Concurrency 3) Control 4) Data 5) Database 6) Development 7) Distribution 8) Game 9) Graphics 10) Language 11) Math 12) Network 13) Sound 14) System 15) Testing 16) Text 17) Web 18) Other (specify) Your choice? ProblemSolver ProblemSolver is not a valid choice. Your choice? 18 Please specify? ProblemSolver What does the package build: 1) Library 2) Executable Your choice? 2 Generating LICENSE... Generating Setup.hs... Generating y.cabal... You may want to edit the .cabal file and add a Description field. 

“Genial”, piensa, “estaba tan molesto que apuesto a que las últimas prácticas de Haskell en desarrollo de software están esperando en mi disco”.

 $ ls LICENSE problemsolver.cabal Setup.hs 

Permíteme resumir mis sentimientos: :(

El archivo cabal generado ni siquiera tiene un Main especificado, y mucho menos instrucciones para configurar un proyecto rudimentario. Aún así, está bien. Si andas dando vueltas por un momento intentando encontrar las palabras clave de búsqueda adecuadas, aterrizarás en Cómo escribir un progtwig de Haskell, lo cual está bien, excepto:

  • Todo el código fuente de Haq se introduce en el directorio raíz.
  • El código de prueba para Haq está solo en Test.hs , es solo QuickCheck y no tiene facilidad para continuar el proyecto con pruebas de archivos divididos.
  • Todo esto debe ser escrito o copiado manualmente para cada nuevo proyecto.

Al revisar el Capítulo 11 de Real World Haskell, encontrará que ni siquiera menciona cabal y evita completamente el tema del diseño del proyecto. Ninguno de los recursos con los que Don Stewart responde amablemente aquí se aborda en ninguno de los puntos mencionados anteriormente y, señalaré, el Sr. Stewart no explica cómo usar ninguna de las herramientas a las que se hace referencia.

Tenga en cuenta que la respuesta aceptada en el flujo de trabajo de prueba de Haskell hace referencia a un proyecto que desde entonces se ha avanzado lo suficiente como para no ser una buena respuesta, pero dice

Como el examen cabal aún no existe, ¡tenemos un estudiante trabajando en él para el código de verano de este año! – El mejor mecanismo que tenemos es usar el mecanismo de gancho de usuario de Cabal.

¡Hey, está bien, la documentación de la camarilla! La sección apropiada tiene ejemplos, pero están muy bien diseñados pero no dejan de dar la impresión de que todos están solos y le deseamos buena suerte.

Por supuesto, siempre hay un marco de prueba que parece bueno, pero el código de ejemplo no ofrece nada más allá de lo que se ve en la wiki y no es escalable en el sentido de que tan pronto como mi progtwig crece en complejidad, estoy en el Enganche para desarrollar formas de dividir las pruebas en módulos manejables. Ni siquiera estoy seguro de lo que está pasando con HTF y estoy de acuerdo con la evaluación del Sr. Volkov .

El comentario del Sr. Jelvis sobre la pregunta de HTF vinculada fue de particular interés para mí: la cadena de herramientas de Haskell sufre, muy gravemente, de una tiranía de pequeñas decisiones. Realmente no puedo seguir con la tarea en cuestión: resolver mi problema en Haskell, porque estoy en el anzuelo de lograr que mi entorno sea el correcto. Por qué esto es malo:

  • Es un esfuerzo inútil. A menos que esté escribiendo una herramienta de prueba, muy rara vez me preocuparé sobre cómo se comprueban mis pruebas, solo desde dónde .
  • Es dificil de aprender Parece que no hay un recurso singular para configurar un proyecto con pruebas integradas, y las diversas fonts que existen son lo suficientemente diversas como para ser inútiles.
  • Es difícil de reproducir. Con tantas piezas en movimiento para organizar, estoy obligado a hacerlo de manera diferente cada vez.
  • Como corolario, es idiosincrásico. Eso significa que es difícil colaborar y recoger proyectos inactivos.

Esto simplemente apesta.

Aunque tal vez me equivoque. ¿Existe alguna herramienta mal publicitada o herramientas estrechamente desarrolladas para hacer algo similar a Bundler + Rspec en el espacio de Haskell? De no ser así, ¿hay un ejemplo canónico mal anunciado de pruebas de Haskell modernas con todas las golosinas de referencia del Sr. Stewart integradas? El proyecto creado o demostrado:

  • por convención y herramientas deben mantener el código de prueba separado del código de la aplicación de una manera bien definida (en Ruby-land, las pruebas Rspec van en spec/ , características de pepino en features/ ),
  • no debe exigir a los usuarios finales que compilen e instalen dependencias de prueba
  • debe ser fácilmente reproducible, deseablemente en no más de 10 minutos y
  • Deben estar estandarizados o tener la esperanza de estandarización.

¿Me equivoco al creer que no hay nada como esto en la tierra de Haskell?


Edit0: Tenga en cuenta que la comunidad del lenguaje Ruby no es la única comparación aplicable. Paul R. tiene razón al identificar la fuerte stream de configuración sobre la convención. Otros idiomas resuelven el problema de lograr que una estructura de proyecto escalable despegue de otras maneras:

  • C :: Este lenguaje es venerable y está tan bien documentado que tendrá problemas para descubrir qué enfoque bien documentado debe tomar. Sin herramientas como tales.
  • Java :: Configuración por convención: estás vinculado a él en el nivel del comstackdor. Muchas herramientas y muy bien documentadas.
  • Scala :: Soporte fuerte para herramientas.
  • Erlang :: Venerable y vagamente documentado si sabes lo que estás buscando. Podría decirse que la configuración supera la convención si está utilizando barras de refuerzo o si está apuntando a la OTP.

La solución de Paul R. de usar una plantilla personalizada funciona muy bien si, como C, hay suficiente documentación para comstackr tal cosa. Esto todavía se encuentra con problemas que intenté identificar explícitamente en la publicación, pero es factible. La mejor oferta de Haskell, que yo sepa, es “Cómo escribir un progtwig de Haskell”, pero no llega a ser más que el equivalente a dejar a un Cub Scout solitario en el bosque con una linterna y un flask de agua.

Además, sí, los tipos estáticos son excelentes y resuelven muchos problemas que de otro modo necesitarían pruebas explícitas. Si fueran una solución final, o en su mayoría suficiente, incluso, el marco de snap no se probaría tan a fondo. (Podría decirse que “Copiar snap-core” es una respuesta a mi pregunta).

Actualmente no hay una única forma de configurar un testuite. Con suerte, la gente se estandarizará en la cabal test , que está fuera de la caja. De hecho, tanto HUnit como QuickCheck también se proporcionan con la plataforma Haskell, por lo que la configuración de las pruebas no requiere la descarga de dependencias adicionales.

Tienes razón en que una antigua respuesta aceptada no proporciona información sobre la cabal test . Lo edité, y ahora lo hace! También es probable que tenga razón en que la página enlazada en la wiki de Haskell (también escrita antes de que esté disponible la cabal test ) no proporciona información sobre las mejores prácticas de prueba actuales. Es un wiki, ¡y animo a la gente a editarlo! Sin embargo, tenga en cuenta que la página sí proporciona un enlace a otra página que describe cómo se podría estructurar un proyecto Haskell más complejo.

tldr; Utilice la cabal test . Me gusta el test-framework de test-framework , que puede integrar con cabal test si así lo desea. Lamentamos que cabal test sea ​​algo nuevo y que no todos los recursos que tenemos (generalmente editables por la comunidad) se hayan actualizado para señalarlo y describir cómo usarlo. Actualizar una gran cantidad de recursos y crear tutoriales es el trabajo de una comunidad. Probablemente deberíamos hacer un mejor trabajo promoviendo muchas de las nuevas herramientas impresionantes introducidas en el ecosistema de Haskell en los últimos años.

Hay muchos puntos aquí. Primero, hay una comparación de convención sobre configuración con configuración explícita. En la tierra Ruby, a menudo se prefiere el primero. En mi experiencia, aunque funciona muy bien para hacer un {blog | cosa-social | gem | biblioteca} -en 5 minutos de screencast y experimentos rápidos, tiene mucho menos valor en tus proyectos reales (más de 5 minutos ) como el tiempo de inicio se amortiza rápidamente. Además, hay una razón por la que las herramientas proporcionan facilidades de configuración: hay muchas necesidades y usos diferentes. Por lo tanto, mi consejo para su problema cabal-init es: haga su propio archivo de plantilla. Ponga el talón para todo lo que necesite, con excelentes comentarios, y utilícelo cuando lo necesite.

En cuanto a las pruebas, el paisaje es tranquilo entre ruby ​​y haskell. En Ruby, uno puede escribir foo do { oh dear I am typing nonsense here } y no hay otra forma de capturar esta tontería que ejecutar el código. Así que las pruebas automatizadas son absolutamente necesarias. Sin embargo, en la tierra de los haskell, hay un gran análisis estático de su código junto con un paradigma muy sano (puramente funcional, no estricto), y después de años de uso, todavía me sorprende que sea difícil escribir tonterías sin ser Inmediatamente atrapado por el comstackdor. También hago Ruby en el trabajo, y en realidad, el 90% de mis pruebas son “verificaciones estáticas” manuales de hombres pobres.

Aún así, hay espacio para un diseño incorrecto o errores de esquinas, por eso existe la comprobación rápida . Encontrará automáticamente (sí, realmente automáticamente) errores de esquina y le ayudará mucho a encontrar errores de diseño. Aún puede escribir pruebas unitarias con uno de los paquetes existentes si necesita verificaciones manuales.

Así que mi conclusión aquí es: no se sorprenda de encontrar sombras en todas partes si sombrea la luz de Ruby en la tierra haskell. Las cosas son muy diferentes aquí, y necesitan ser experimentadas para tomar el poder. Eso no significa que todo sea perfecto, en realidad, la mejora de la cadena de herramientas es un deseo expresado comúnmente. Solo los puntos que mencionó no son realmente problemáticos, y realmente no merecen el vocabulario que eligió. Intenta primero, juzga después 🙂