¿Hay algún equivalente de Haskell-land al Bundler et. De Ruby-land? Al y, si no, ¿cómo se podría diseñar un proyecto tan estructurado?
tdd setup-project (2)
Nota para los lectores : tengan paciencia conmigo. Prometo que hay una pregunta.
Tengo un problema que resolver y pensar "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
de 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ódigo, 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 "[email protected]"]?
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 programa 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 archivo dividido. - 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 el tema del diseño del proyecto por completo. Ninguno de los recursos con los que Don Stewart responde amablemente here 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 test-framework 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 programa 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 conseguir que mi entorno sea el adecuado. 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 mis pruebas son asimiladas, 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 fuentes 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? Si no es 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 enfeatures/
), - 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 corriente 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 compilador. 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 rebar 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 compilar tal cosa. Esto aún se encuentra con problemas que intenté identificar explícitamente en la publicación, pero es viable. La mejor oferta de Haskell, que yo sepa, es "Cómo escribir un programa 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 frasco 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 snap-framework 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 la cabal test
sea algo nueva 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 increíbles 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 rubí, a menudo se prefiere el primero. En mi experiencia, aunque funciona muy bien para hacer un {blog | cosa-social | gema | 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 estoy sorprendido, pero es muy difícil escribir tonterías sin estar Inmediatamente atrapado por el compilador. También hago rubí 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 quickcheck existe la quickcheck . 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 rubí en la tierra de 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 :)