Je ne sais pas comment TDD, la méthodologie, gère le cas suivant. Supposons que je veuille implémenter l'algorithme de fusion, en Python. Je commence par écrire
assert mergesort([]) === []
et le test échoue avec
NameError: le nom 'mergesort' n'est pas défini
J'ajoute ensuite
def mergesort(a):
return []
et mon test réussit. Ensuite j'ajoute
assert mergesort[5] == 5
et mon test échoue avec
AssertionError
avec qui je fais passer
def mergesort(a):
if not a:
return []
else:
return a
Ensuite, j'ajoute
assert mergesort([10, 30, 20]) == [10, 20, 30]
et je dois maintenant essayer de faire ce passage. Je "connais" l'algorithme de fusion, donc j'écris:
def mergesort(a):
if not a:
return []
else:
left, right = a[:len(a)//2], a[len(a)//2:]
return merge(mergesort(left)), mergesort(right))
Et cela échoue avec
NameError: le nom «fusion» n'est pas défini
Voici maintenant la question. Comment puis-je exécuter et commencer à implémenter en merge
utilisant TDD? Il semble que je ne peux pas parce que j'ai ce "suspendre" non rempli, échec du test mergesort
, qui ne passera pas tant que ce merge
n'est pas terminé! Si ce test traîne, je ne pourrai jamais vraiment faire de TDD car je ne serai pas "vert" lors de la construction de mes itérations TDD merge
.
Il semble que je sois coincé avec les trois scénarios laids suivants et que j'aimerais savoir (1) lequel de ceux-ci la communauté TDD préfère, ou (2) y a-t-il une autre approche qui me manque? J'ai regardé plusieurs procédures pas à pas d'oncle Bob TDD et je ne me souviens pas avoir vu un cas comme celui-ci auparavant!
Voici les 3 cas:
- Implémentez la fusion dans un répertoire différent avec une suite de tests différente.
- Ne vous inquiétez pas d'être écologique lorsque vous développez la fonction d'assistance, il vous suffit de suivre manuellement les tests que vous souhaitez vraiment passer.
- Mettez en commentaire (GASP!) Ou supprimez les lignes de
mergesort
cet appelmerge
; puis après avoir commencémerge
à travailler, remettez-les en place.
Tout cela me semble stupide (ou est-ce que je regarde mal?). Quelqu'un connaît-il l'approche préférée?
mergesort
, puisqu'il s'agit déjà d'un algorithme très bien défini, ce processus de découverte n'est pas nécessaire, et il s'agit alors de mapper ce que vous savez déjà être la conception à une série de tests unitaires. Vraisemblablement, votre test de niveau supérieur affirme que votre méthode sous test accepte une collection non triée et retourne une collection triée ...mergesort
. Si vous cherchez la "bonne" façon de procéder, il n'y en a pas d'autre que d'être précis dans le mappage de l'mergesort
algorithme avec une série de tests unitaires; c'est-à-dire qu'ils devraient refléter ce quemergesort
fait réellement.mergesort
design émerge naturellement du refactor rouge-vert, cela ne se produira que si vous guidez le processus en fonction de vos connaissances existantesmergesort
.merge
doit être inventé uniquement sur l'étape de "refactoring". Si vous voyez que cettemerge
méthode peut être introduite pour réussir votre test,mergesort
faites d'abord passer vos tests sansmerge
méthode. Refactorisez ensuite votre implémentation en introduisant lamerge
méthode.Réponses:
Voici quelques façons alternatives d'examiner vos options. Mais d'abord, les règles de TDD, de l' oncle Bob avec emphase par moi:
Ainsi, une façon de lire la règle numéro 3 est que vous ayez besoin de la
merge
fonction pour réussir le test, afin que vous puissiez l'implémenter - mais uniquement sous sa forme la plus élémentaire.Ou, vous pouvez également commencer par écrire l'opération de fusion en ligne, puis la refactoriser dans une fonction après avoir fait fonctionner le test.
Une autre interprétation est que vous écrivez mergesort, vous savez que vous aurez besoin d'une
merge
opération (c'est-à-dire que ce n'est pas YAGNI, ce que la règle "suffisante" tente de limiter). Par conséquent, vous devriez avoir commencé avec des tests pour la fusion, puis seulement procéder à des tests pour le tri global.la source
merge
c'est étonnamment désordonné, au cas par cas (ainsi qu'utile en tant que autonome), l'idée de le faire en tant que fonction distincte avait plus de sens. Cependant, le style de le faire en ligne dans sa forme de base, puis de le prendre en compte au stade du chapeau bleu semble vraiment être juste et correspond vraiment à ce que je cherchais.merge
opération avant de faire le tri (ainsi que des tests séparés de l'partition
opération). Je pense que la conception émergente des avantages revendiqués vient du fait de travailler lentement vers un objectif connu. Dans le cas du mergesort, je ne pense pas que l'objectif soit le tri en général (car vous vous retrouverez alors avec le tri à bulles). Vous connaissez les opérations de base, vous travaillez donc vers ces opérations; le tri est surtout une réflexion après coup.merge
fonctionmergesort
et simulez son comportement. Revenez ensuite en arrière et implémentez lemerge
test en premier. Les délégués sont géniaux ™.