No estoy claro cómo TDD, la metodología, maneja el siguiente caso. Supongamos que quiero implementar el algoritmo mergesort, en Python. Empiezo escribiendo
assert mergesort([]) === []
y la prueba falla con
NameError: el nombre 'mergesort' no está definido
Luego agrego
def mergesort(a):
return []
y mi prueba pasa A continuación agrego
assert mergesort[5] == 5
y mi prueba falla con
AserciónError
que hago pasar con
def mergesort(a):
if not a:
return []
else:
return a
A continuación, agrego
assert mergesort([10, 30, 20]) == [10, 20, 30]
y ahora tengo que intentar hacer que esto pase. "Conozco" el algoritmo mergesort, así que escribo:
def mergesort(a):
if not a:
return []
else:
left, right = a[:len(a)//2], a[len(a)//2:]
return merge(mergesort(left)), mergesort(right))
Y esto falla con
NameError: el nombre 'fusionar' no está definido
Ahora aquí está la pregunta. ¿Cómo puedo salir corriendo y comenzar a implementar merge
usando TDD? Parece que no puedo porque tengo esta prueba de "suspensión" sin cumplir mergesort
, que no se cumplemerge
, ¡ que no pasará hasta que termine! Si esta prueba se detiene, realmente nunca puedo hacer TDD porque no seré "verde" durante la construcción de las iteraciones de TDD merge
.
Parece que estoy atrapado en los siguientes tres escenarios feos, y me gustaría saber (1) cuál de estos prefiere la comunidad TDD, o (2) ¿hay otro enfoque que me estoy perdiendo? ¡He visto varios recorridos del Tío Bob TDD y no recuerdo haber visto un caso como este antes!
Aquí están los 3 casos:
- Implemente la fusión en un directorio diferente con un conjunto de pruebas diferente.
- No se preocupe por ser ecológico cuando desarrolle la función auxiliar, solo realice un seguimiento manual de las pruebas que realmente desea aprobar.
- Comente (GASP!) O elimine las líneas en
mergesort
esa llamadamerge
; luego, después de llegarmerge
al trabajo, vuelva a colocarlos.
Todo esto me parece tonto (¿o estoy mirando esto mal?). ¿Alguien sabe el enfoque preferido?
mergesort
, dado que ya es un algoritmo muy bien definido, este proceso de descubrimiento no es necesario, y luego se convierte en una cuestión de mapear lo que ya sabe que es el diseño para una serie de pruebas unitarias. Presumiblemente, su prueba de nivel superior afirma que su método bajo prueba acepta una colección sin clasificar y devuelve una ordenada ...mergesort
. Si está buscando la forma "correcta" de hacer esto, no hay otra, que no sea ser exacto acerca de su mapeo delmergesort
algoritmo a una serie de pruebas unitarias; es decir, deberían reflejar lo quemergesort
realmente hace.mergesort
diseño emerja naturalmente del refactor rojo-verde, eso no sucederá a menos que guíe el proceso en función de su conocimiento actualmergesort
.merge
debe inventarse solo en la etapa de "refactorización". Si ve quemerge
se puede introducir ese método para aprobar la pruebamergesort
, primero haga que sus pruebas pasen sinmerge
método. Luego refactorice su implementación introduciendo elmerge
método.Respuestas:
Aquí hay algunas formas alternativas de ver sus opciones. Pero primero, las reglas de TDD, del tío Bob con énfasis en mí:
Entonces, una forma de leer la regla número 3 es que necesita la
merge
función para pasar la prueba, de modo que pueda implementarla, pero solo en su forma más básica.O, alternativamente, comienza escribiendo la operación de fusión en línea, y luego la refactoriza en una función después de hacer que la prueba funcione.
Otra interpretación es que está escribiendo mergesort, sabe que necesitará una
merge
operación (es decir, no es YAGNI, que es lo que la regla "suficiente" intenta reducir). Por lo tanto, debería haber comenzado con las pruebas para la fusión, y solo luego continuar con las pruebas para la clasificación general.fuente
merge
es sorprendentemente desordenado, en cuanto al caso (así como útil como un autónomo), la idea de hacerlo como una función separada tenía más sentido. Sin embargo, el estilo de hacerlo en línea en su forma básica y luego factorizarlo en la etapa de sombrero azul realmente parece ser correcto y mucho lo que estaba buscando.merge
operación antes de hacer la clasificación (así como también realizar pruebas por separado de lapartition
operación). Creo que el diseño emergente de los beneficios reclamados proviene de trabajar lentamente hacia un objetivo conocido. En el caso de mergesort, no creo que el objetivo sea la clasificación en general (porque entonces terminarás con una clasificación de burbujas). Conoces las operaciones básicas, así que trabajas para esas operaciones; el tipo es principalmente una idea de último momento.merge
funciónmergesort
y simule su comportamiento. Luego regrese e implemente lamerge
prueba primero. Los delegados son increíbles ™.