-
-
Save alcidesfp/3783163 to your computer and use it in GitHub Desktop.
| #!/usr/local/bin/csi -s | |
| ;; -*- coding:utf-8; mode:Scheme -*- | |
| (use extras) | |
| (define (pide-nombre) | |
| (display "Hola, ¿Cuál es tu nombre?: ") | |
| (read-line)) | |
| (define (pide-ann) | |
| (display "¿En qué año naciste?: ") | |
| (string->number (read-line))) | |
| (define (calcula-edad ann-nac #!optional (ann-actual 2012)) | |
| (if ann-nac (- ann-actual ann-nac) 0 )) | |
| (begin | |
| (display "¡Hola a todos desde Scheme!\n") | |
| (let* ((nombre (pide-nombre)) | |
| (edad (calcula-edad (pide-ann)))) | |
| (format #t "Hola ~a.~%" nombre) | |
| (format #t "En el año ~a tendrás ~a años.~%" 2012 edad))) |
Al refactorizar el código en un estilo más idiomático de Scheme, aplicando los principios de programación funcional y en específico eliminando las asignaciones/mutaciones de variables (set!'s) se obtiene esta última versión la cual resulta ser mucho mas modular, ya puede ser sujeta de pruebas unitarias y de caracterización directamente, está mucho mas cohesionada y menos acoplada en sus partes, los niveles de abstracción y ocupación están separados, es mucho más fácilmente modificable, mantenible, extensible.
Bueno, aquí voy a demostrar lo mucho que ignoro sobre scheme:
- En la linea 14, no sé si en verdad esta validación "defensiva" va aquí o debería ser parte de pide-ann.
- Fuera de la documentación que proporciona por su mera existencia, el begin cumple con alguna otra función?
- No me queda claro cómo se pueden "inyectar" valores al programa si es que no quieres usar la entrada por teclado (p.e. una prueba unitaria)
Lo que si me llama poderosamente la atención es la manera en que al eliminar los set's se encuentran puntos de sección naturales en el código. Habría que intentarlo en algo más "sofisticado" (er.. complejo) para ver qué sucede. Tal vez descubriste un principio más general de lo que el gist deja ver.
Estimado Alfred: Tres meses después, irónicamente, debido a la terrible gripa que me ha aquejado antes, durante y después de Navidad, por fin tengo tiempo para responder los comentarios que me haces favor de expresar por este medio:
- La validación a la que te refieres en la línea 14 es la solución mas simple. Se basa en el hecho de que la función string->number regresa #f si el argumento no es convertible o es nulo. De otra manera las funciones pide-ann y calcula-edad quedarían como sigue:
(define (pide-ann)
(display "¿En que año naciste?:")
(let ((ann (string->number (read-line)) ))
(if (not ann) 0 ann) ))
(define (calcula-edad ann-nac #!optional (ann-actual 2012))
(if (= 0 ann-nac) 0 (- ann-actual ann-nac)) )En este caso es solamente una línea mas de código, pero ya nos sugiere la necesidad de una prueba unitaria y la consiguiente refactorización (rangos permitidos, valores a considerar, criterios de error, etc) La cual ya es posible sin mayores esfuerzos teniendo el código escrito de esta forma.
(cond-expand (chicken (use srfi-64))
(kawa (require 'srfi-64)))
(define pruebas ;;Lista de valores de pruebas
'((ann1 edad1)
(ann2 edad2)
(ann3 edad3)
(ann4 edad4)))
(test-begin "prueba-calcula-edad")
(for-each
(lambda (elem)
(let* ((arg (car elem)) (act-val (cadr elem)) (exp-val (calcula-edad arg)))
(test-equal exp-val act-val))) pruebas)
(test-end)- La forma begin es la manera natural en Scheme de agrupar en un bloque de código varias expresiones para su evaluación secuencial (el equivalente a PROGN de Common-Lisp). En mi caso, la utilizo como una convención estilística de agrupación de las expresiones del programa principal, la cual me permite su rápida evaluación, activar/desactivar su ejecución o bien renombrarlas/moverlas a otra función de un solo teclazo.
- Las funciones pide-nombre y pide-ann esencialmente no hacen nada mas que llamar a las funciones de la biblioteca estándar de Scheme (display, readline, string->number, etc) y son realmente parte de la interfaz de usuario (IU) (CLI en este caso) por lo cual no les he asignado ninguna responsabilidad adicional y por lo tanto están fuera del alcance de las pruebas aquí consideradas. No está dentro de mi alcance inmediato hacer pruebas de caracterización para las bibliotecas de Scheme. Aunque con el código ya desacoplado de la UI, no dudo que se puedan hacer pruebas con una interfaz de usuario mas compleja (Kawa / Swing).
Sin mas por el momento, me despido de ti, enviándote un cordial saludo.
Esta primera versión sufre también de los problemas típicos asociados a este estilo: No es verificable directamente ni sujeto de pruebas unitarias o de caracterización, mezcla varios niveles de abstracción y de ocupación/operación (concerns) diferentes, no es modular (alto acoplamiento / baja cohesión), Todo esto con el resultado típico: No es fácilmente modificable ni mantenible ni extensible. En este caso es un script muy pequeño pero es ilustrativo de lo que pasa en la gran mayoría del código.