[{"data":1,"prerenderedAt":6236},["ShallowReactive",2],{"blog-post-\u002Fblogs\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies":3,"related-\u002Fblogs\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies":6205},{"id":4,"title":5,"alt":6,"authors":7,"body":16,"date":6178,"description":6179,"extension":6180,"image":6181,"meta":6182,"navigation":330,"ogImage":6181,"path":6183,"published":330,"reviewers":6184,"seo":6199,"stem":6200,"tags":6201,"__hash__":6204},"blogs\u002Fblogs\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies\u002Findex.md","TDD: comment faire un strike avec la méthode ZOMBIES","Illustration abstraite d’un développeur lançant une boule de bowling sur une piste traversée de symboles et schémas de code, tandis que des silhouettes de zombies numériques émergent en arrière-plan et que des quilles lumineuses l’attendent au bout de la piste.",[8],{"id":9,"name":10,"image":11,"linkedin":12,"x":13,"jobTitle":14,"bio":15},"188f4462-cd38-80d5-b9e6-ec28a94d11e5","Bastien Dufour",".\u002Fassets\u002Fauthor-bastien-dufour.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fb-dufour\u002F",null,"Senior Software Engineer","I use vim btw",{"type":17,"value":18,"toc":6159},"minimark",[19,23,29,40,51,56,63,66,72,78,81,132,136,139,153,160,163,168,171,185,205,227,230,236,247,266,275,278,281,284,288,294,510,513,517,524,535,541,724,728,735,745,764,1040,1043,1049,1059,1075,1362,1373,1446,1453,1463,1481,1751,1754,1763,1777,2082,2085,2094,2119,2468,2471,2550,2554,2560,2570,2587,2846,2852,2862,2872,3108,3114,3120,3234,3241,3245,3249,3258,3268,3292,3649,3652,3658,3668,3674,4007,4014,4020,4027,4077,4103,4281,4300,4335,4344,4347,4425,4428,4727,4733,4737,4747,4767,4773,5218,5221,5225,5235,5252,5266,5269,5541,5555,5565,5569,5572,6027,6030,6034,6037,6063,6070,6076,6080,6087,6093,6102,6105,6114,6118,6121,6131,6142,6149,6152,6155],[20,21,22],"p",{},"Les zombies, ça vous parle ? Ceux que nous allons évoquer ici n’ont aucun lien avec ceux de Walking Dead ou du superbe titre du groupe The Cranberries. Non, les zombies dont nous allons parler aujourd’hui se trouvent dans votre code.",[20,24,25],{},[26,27,28],"strong",{},"Long story short :",[20,30,31,32,39],{},"Lorsque par le passé j’ai commencé le ",[33,34,38],"a",{"href":35,"rel":36},"https:\u002F\u002Fblog.hoppr.tech\u002Fblogs\u002F2026-06-30-tdd-jen-entends-beaucoup-parler-mais-cest-quoi-au-juste",[37],"nofollow","TDD",", j’avais beau avoir lu énormément de livres sur le sujet, il m’était par moments toujours difficile de savoir par où commencer.",[20,41,42,43,46,47,50],{},"Plus tard, un de mes amis m’a souvent demandé « Ok c’est cool le TDD mais j’ai toujours du mal à savoir par où commencer », « Quel est le premier test à faire ? », « Est-ce que ma baby step est bonne ? ». Ce sont autant de questions que j’ai pu me poser au cours des différentes problématiques rencontrées. Évidemment avec le temps et la pratique, ces questions tendent à s’estomper. Mais ",[26,44,45],{},"le"," truc qui m’a bien aidé au début c’est une méthodologie qui m’a permis de poser la bonne approche pour le TDD : les ",[26,48,49],{},"zombies",".",[52,53,55],"h2",{"id":54},"zombies-cest-quoi","Z.O.M.B.I.E.S, c'est quoi ?",[20,57,58,59,62],{},"De son nom de code ",[26,60,61],{},"Z.O.M.B.I.E.S",". Il s’agit surtout d’une heuristique qui permet de guider le prochain test en TDD.",[20,64,65],{},"Il ne s’agit pas d’une méthode TDD complète qui elle, ne change pas et conserve le même cycle :",[67,68,69],"blockquote",{},[20,70,71],{},"Red → Green → Refactor",[20,73,74,77],{},[26,75,76],{},"Zombies"," aide à faire progresser les tests des cas les plus simples aux plus riches.",[20,79,80],{},"La méthode se compose ainsi :",[82,83,84,96,102,108,114,120,126],"ul",{},[85,86,87,90,91,95],"li",{},[26,88,89],{},"Z — Zero"," : commencer par zéro, vide, ",[92,93,94],"code",{},"None",", aucune donnée.",[85,97,98,101],{},[26,99,100],{},"O — One"," : tester avec un seul élément ou un cas minimal.",[85,103,104,107],{},[26,105,106],{},"M — Many"," : tester avec plusieurs éléments.",[85,109,110,113],{},[26,111,112],{},"B — Boundary"," : tester les valeurs limites.",[85,115,116,119],{},[26,117,118],{},"I — Interface"," : vérifier l’interface publique et les interactions avec d’autres composants.",[85,121,122,125],{},[26,123,124],{},"E — Exceptions"," : tester les erreurs et cas exceptionnels.",[85,127,128,131],{},[26,129,130],{},"S — Simple Scenarios \u002F Simple Solutions"," : privilégier d’abord les scénarios et implémentations les plus simples.",[52,133,135],{"id":134},"le-kata-calculer-un-score-de-bowling","Le kata : calculer un score de bowling",[20,137,138],{},"Pour notre exemple, nous allons être super originaux ! Nous allons refaire le geste de calcul d’un score de bowling.",[20,140,141,142,147,148,152],{},"Alors, c’est un sujet assez commun je vous l’accorde mais je pense qu’il illustre bien l’application de ZOMBIES – bon il faut aussi avouer que je n’avais pas d’inspiration. Pour ce qui est du langage, on va le faire en ",[33,143,146],{"href":144,"rel":145},"https:\u002F\u002Frust-lang.org\u002Ffr\u002F",[37],"rust"," parce que ",[149,150,151],"del",{},"c’est le meilleur language ever"," pourquoi pas ?",[20,154,155],{},[156,157],"img",{"alt":158,"src":159},"Un gif avec un homme qui pointe du doigt en disant “YOU STAY RIGHT HERE!”","\u002Fcontent-assets\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies\u002Fassets\u002Fimg1.webp",[20,161,162],{},"Hop hop hop, ne prenez pas peur en lisant rust, c’est simple et vous allez comprendre ne vous en faites pas.",[164,165,167],"h3",{"id":166},"les-règles-du-jeu","Les règles du jeu",[20,169,170],{},"Avant cela, petite mise au point sur les règles de scoring au bowling avant d’aborder le sujet afin que tout le monde parte sur la même base :",[20,172,173,174,177,178,181,182,50],{},"Une partie comporte ",[26,175,176],{},"10 frames",". Dans les neuf premières, le joueur ",[26,179,180],{},"lance une ou deux fois"," pour faire tomber les ",[26,183,184],{},"dix quilles",[82,186,187,193,199],{},[85,188,189,192],{},[26,190,191],{},"Frame ouverte"," : les quilles tombées aux deux lancers s’additionnent",[85,194,195,198],{},[26,196,197],{},"Spare"," (les dix quilles en deux lancers) : 10 points, plus le lancer suivant",[85,200,201,204],{},[26,202,203],{},"Strike"," (les dix quilles au premier lancer) : 10 points, plus les deux lancers suivants",[20,206,207,208,211,212,215,216,219,220,223,224,50],{},"À la ",[26,209,210],{},"10e frame",", un spare donne droit à ",[26,213,214],{},"un"," lancer supplémentaire ; un strike, à ",[26,217,218],{},"deux",". Ces lancers bonus servent à calculer le score de la frame. Le score maximal d’une partie est ",[26,221,222],{},"300 points"," , un total atteignable uniquement en faisant un strike à chaque lancer, soit ",[26,225,226],{},"12 strikes",[20,228,229],{},"À des fins de simplification, nous allons éviter de manipuler directement une liste de lancers puisque ce n’est pas le sujet de l’article.",[20,231,232,233,50],{},"Nous partirons donc du payload suivant : ",[92,234,235],{},"Vec\u003C(Roll, Roll, Option\u003CRoll>)>",[20,237,238,239,242,243,246],{},"Concrètement, il s’agit d’une liste (",[92,240,241],{},"Vec\u003CT>",") contenant jusqu’à 10 frames. Chaque frame est représentée par un tuple ",[92,244,245],{},"(...)"," :",[82,248,249,256,259],{},[85,250,251,252,255],{},"le premier ",[92,253,254],{},"Roll"," correspond au premier lancer",[85,257,258],{},"le deuxième au second lancer",[85,260,261,262,265],{},"le type ",[92,263,264],{},"Option\u003CRoll>"," représente un éventuel troisième lancer, uniquement possible lors de la dernière frame",[20,267,268,270,271,274],{},[92,269,254],{}," est simplement un alias de ",[92,272,273],{},"i32",". Retenez donc qu’il s’agit d’un entier relatif.",[20,276,277],{},"Ce n’est clairement pas une modélisation idéale – à ne pas reproduire chez vous – mais soit ; imaginons que ce payload nous soit fourni par un service externe un peu douteux.",[20,279,280],{},"L’objectif ici est surtout d’avoir une représentation simple des frames et des lancers, afin de nous concentrer sur ce qui nous intéresse vraiment : la progression en TDD.",[20,282,283],{},"Maintenant que le vocabulaire et le besoin sont posés, par quoi commence-t-on ?",[164,285,287],{"id":286},"mise-en-place-des-tests","Mise en place des tests",[20,289,290,291,50],{},"En rust, les tests unitaires se situent dans le même fichier que le code testé ; commençons donc par un fichier ",[92,292,293],{},"calculate_bowling_score.rs",[295,296,300],"pre",{"className":297,"code":298,"language":146,"meta":299,"style":299},"language-rust shiki shiki-themes github-dark-default","type Roll = i32;\n\nfn calculate_bowling_score() {}\n\n#[cfg(test)] \u002F\u002F configure le module pour les tests\nmod tests {\n    use super::*; \u002F\u002F nous permet d'avoir acces dans ce module aux elements au dessus\n\n    \u002F\u002F il n'y a pas de trace de `Option\u003Ci32>` en troisieme position\n    \u002F\u002F car on ne parle pas **encore** de la derniere frame et de ses 3 lancers\n    fn assert_score(frames: Vec\u003C(Roll, Roll)>, expected: i32) {\n    assert_eq!(calculate_bowling_score(frames), expected);\n    }\n        \n    #[test]\n    fn first_test() {\n        todo!();\n    }\n}\n","",[92,301,302,325,332,345,350,360,372,391,396,402,408,446,461,467,473,479,490,499,504],{"__ignoreMap":299},[303,304,307,311,315,318,321],"span",{"class":305,"line":306},"line",1,[303,308,310],{"class":309},"suJrU","type",[303,312,314],{"class":313},"sQhOw"," Roll",[303,316,317],{"class":309}," =",[303,319,320],{"class":313}," i32",[303,322,324],{"class":323},"sZEs4",";\n",[303,326,328],{"class":305,"line":327},2,[303,329,331],{"emptyLinePlaceholder":330},true,"\n",[303,333,335,338,342],{"class":305,"line":334},3,[303,336,337],{"class":309},"fn",[303,339,341],{"class":340},"sc3cj"," calculate_bowling_score",[303,343,344],{"class":323},"() {}\n",[303,346,348],{"class":305,"line":347},4,[303,349,331],{"emptyLinePlaceholder":330},[303,351,353,356],{"class":305,"line":352},5,[303,354,355],{"class":323},"#[cfg(test)] ",[303,357,359],{"class":358},"sH3jZ","\u002F\u002F configure le module pour les tests\n",[303,361,363,366,369],{"class":305,"line":362},6,[303,364,365],{"class":309},"mod",[303,367,368],{"class":313}," tests",[303,370,371],{"class":323}," {\n",[303,373,375,378,382,385,388],{"class":305,"line":374},7,[303,376,377],{"class":309},"    use",[303,379,381],{"class":380},"sFSAA"," super",[303,383,384],{"class":309},"::*",[303,386,387],{"class":323},"; ",[303,389,390],{"class":358},"\u002F\u002F nous permet d'avoir acces dans ce module aux elements au dessus\n",[303,392,394],{"class":305,"line":393},8,[303,395,331],{"emptyLinePlaceholder":330},[303,397,399],{"class":305,"line":398},9,[303,400,401],{"class":358},"    \u002F\u002F il n'y a pas de trace de `Option\u003Ci32>` en troisieme position\n",[303,403,405],{"class":305,"line":404},10,[303,406,407],{"class":358},"    \u002F\u002F car on ne parle pas **encore** de la derniere frame et de ses 3 lancers\n",[303,409,411,414,417,420,423,426,429,431,434,436,439,441,443],{"class":305,"line":410},11,[303,412,413],{"class":309},"    fn",[303,415,416],{"class":340}," assert_score",[303,418,419],{"class":323},"(frames",[303,421,422],{"class":309},":",[303,424,425],{"class":313}," Vec",[303,427,428],{"class":323},"\u003C(",[303,430,254],{"class":313},[303,432,433],{"class":323},", ",[303,435,254],{"class":313},[303,437,438],{"class":323},")>, expected",[303,440,422],{"class":309},[303,442,320],{"class":313},[303,444,445],{"class":323},") {\n",[303,447,449,452,455,458],{"class":305,"line":448},12,[303,450,451],{"class":340},"    assert_eq!",[303,453,454],{"class":323},"(",[303,456,457],{"class":340},"calculate_bowling_score",[303,459,460],{"class":323},"(frames), expected);\n",[303,462,464],{"class":305,"line":463},13,[303,465,466],{"class":323},"    }\n",[303,468,470],{"class":305,"line":469},14,[303,471,472],{"class":323},"        \n",[303,474,476],{"class":305,"line":475},15,[303,477,478],{"class":323},"    #[test]\n",[303,480,482,484,487],{"class":305,"line":481},16,[303,483,413],{"class":309},[303,485,486],{"class":340}," first_test",[303,488,489],{"class":323},"() {\n",[303,491,493,496],{"class":305,"line":492},17,[303,494,495],{"class":340},"        todo!",[303,497,498],{"class":323},"();\n",[303,500,502],{"class":305,"line":501},18,[303,503,466],{"class":323},[303,505,507],{"class":305,"line":506},19,[303,508,509],{"class":323},"}\n",[20,511,512],{},"Bien, maintenant que nos tests sont setup, nous pouvons commencer.",[52,514,516],{"id":515},"z-partir-de-zéro","Z - Partir de zéro",[20,518,519,520,523],{},"La première lettre de zombies nous dit ",[26,521,522],{},"Z pour Zero"," ou aucune donnée. Pour notre exemple littéralement “commencer par zéro”, donc allons-y:",[20,525,526,529,530],{},[26,527,528],{},"Scénario : dix frames à zéro donnent"," ",[26,531,532],{},[92,533,534],{},"0",[20,536,537,538,50],{},"On commence par le test où l’on simule un joueur qui a fait des gouttières toute sa partie – le pauvre – il est donc censé avoir 0 points, super le test est rouge. On peut le faire passer au vert de la manière la plus simple possible : on ",[26,539,540],{},"retourne 0",[295,542,544],{"className":297,"code":543,"language":146,"meta":299,"style":299},"fn calculate_bowling_score() {}\npub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n   0\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_a_loser() {\n    let full_lose: Vec\u003C(i32, i32)> = (0..10)\n        .map(|_| (0, 0))\n        .collect(); \u002F\u002F une liste de 10 de (0, 0)\n    assert_score(full_lose, 0);\n}\n",[92,545,546,554,589,594,598,602,607,611,616,625,665,694,707,720],{"__ignoreMap":299},[303,547,548,550,552],{"class":305,"line":306},[303,549,337],{"class":309},[303,551,341],{"class":340},[303,553,344],{"class":323},[303,555,556,559,562,564,567,569,571,573,575,577,579,582,585,587],{"class":305,"line":327},[303,557,558],{"class":309},"pub",[303,560,561],{"class":309}," fn",[303,563,341],{"class":340},[303,565,566],{"class":323},"(raw_scores",[303,568,422],{"class":309},[303,570,425],{"class":313},[303,572,428],{"class":323},[303,574,254],{"class":313},[303,576,433],{"class":323},[303,578,254],{"class":313},[303,580,581],{"class":323},")>) ",[303,583,584],{"class":309},"->",[303,586,320],{"class":313},[303,588,371],{"class":323},[303,590,591],{"class":305,"line":334},[303,592,593],{"class":380},"   0\n",[303,595,596],{"class":305,"line":347},[303,597,509],{"class":323},[303,599,600],{"class":305,"line":352},[303,601,331],{"emptyLinePlaceholder":330},[303,603,604],{"class":305,"line":362},[303,605,606],{"class":358},"\u002F\u002F ...\n",[303,608,609],{"class":305,"line":374},[303,610,331],{"emptyLinePlaceholder":330},[303,612,613],{"class":305,"line":393},[303,614,615],{"class":323},"#[test]\n",[303,617,618,620,623],{"class":305,"line":398},[303,619,337],{"class":309},[303,621,622],{"class":340}," calculate_for_a_loser",[303,624,489],{"class":323},[303,626,627,630,633,635,637,639,641,643,645,648,651,654,656,659,662],{"class":305,"line":404},[303,628,629],{"class":309},"    let",[303,631,632],{"class":323}," full_lose",[303,634,422],{"class":309},[303,636,425],{"class":313},[303,638,428],{"class":323},[303,640,273],{"class":313},[303,642,433],{"class":323},[303,644,273],{"class":313},[303,646,647],{"class":323},")> ",[303,649,650],{"class":309},"=",[303,652,653],{"class":323}," (",[303,655,534],{"class":380},[303,657,658],{"class":309},"..",[303,660,661],{"class":380},"10",[303,663,664],{"class":323},")\n",[303,666,667,670,673,675,678,681,683,685,687,689,691],{"class":305,"line":410},[303,668,669],{"class":309},"        .",[303,671,672],{"class":340},"map",[303,674,454],{"class":323},[303,676,677],{"class":309},"|",[303,679,680],{"class":323},"_",[303,682,677],{"class":309},[303,684,653],{"class":323},[303,686,534],{"class":380},[303,688,433],{"class":323},[303,690,534],{"class":380},[303,692,693],{"class":323},"))\n",[303,695,696,698,701,704],{"class":305,"line":448},[303,697,669],{"class":309},[303,699,700],{"class":340},"collect",[303,702,703],{"class":323},"(); ",[303,705,706],{"class":358},"\u002F\u002F une liste de 10 de (0, 0)\n",[303,708,709,712,715,717],{"class":305,"line":463},[303,710,711],{"class":340},"    assert_score",[303,713,714],{"class":323},"(full_lose, ",[303,716,534],{"class":380},[303,718,719],{"class":323},");\n",[303,721,722],{"class":305,"line":469},[303,723,509],{"class":323},[52,725,727],{"id":726},"o-introduire-un-premier-cas","O - Introduire un premier cas",[20,729,730,731,734],{},"La lettre ",[26,732,733],{},"O pour One"," nous invite maintenant à introduire une première donnée qui change le résultat : une seule quille renversée.",[20,736,737,529,740],{},[26,738,739],{},"Scénario : une quille à la première frame, puis des zéros, donnent",[26,741,742],{},[92,743,744],{},"1",[20,746,747,748,750,751,529,754,529,759,763],{},"Notre joueur renverse une quille sur son premier lancer, puis fait des gouttières jusqu’à la fin de la partie. Le nouveau test est rouge : la fonction retourne toujours ",[92,749,534],{},". Pour le faire passer au vert, on ajoute un cas spécifique : ",[26,752,753],{},"si le premier lancer vaut",[26,755,756,758],{},[92,757,744],{},"****, on retourne",[26,760,761],{},[92,762,744],{}," .",[295,765,767],{"className":297,"code":766,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, _second) = raw_scores.first().unwrap();\n\n    if *first == 1 {\n        return 1;\n    }\n\n    0\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_one_pin() {\n    let lose: Vec\u003C(Roll, Roll)> = (0..9)\n        .map(|_| (0, 0))\n        .collect();\n\n    let scores: Vec\u003C(Roll, Roll)> = [vec![(1, 0)], lose].concat();\n\n    assert_score(scores, 1);\n}\n",[92,768,769,799,826,830,849,858,862,866,871,875,879,883,887,891,900,934,958,966,970,1018,1023,1035],{"__ignoreMap":299},[303,770,771,773,775,777,779,781,783,785,787,789,791,793,795,797],{"class":305,"line":306},[303,772,558],{"class":309},[303,774,561],{"class":309},[303,776,341],{"class":340},[303,778,566],{"class":323},[303,780,422],{"class":309},[303,782,425],{"class":313},[303,784,428],{"class":323},[303,786,254],{"class":313},[303,788,433],{"class":323},[303,790,254],{"class":313},[303,792,581],{"class":323},[303,794,584],{"class":309},[303,796,320],{"class":313},[303,798,371],{"class":323},[303,800,801,803,806,808,811,813,816,819,821,824],{"class":305,"line":327},[303,802,629],{"class":309},[303,804,805],{"class":323}," (first, _second) ",[303,807,650],{"class":309},[303,809,810],{"class":323}," raw_scores",[303,812,50],{"class":309},[303,814,815],{"class":340},"first",[303,817,818],{"class":323},"()",[303,820,50],{"class":309},[303,822,823],{"class":340},"unwrap",[303,825,498],{"class":323},[303,827,828],{"class":305,"line":334},[303,829,331],{"emptyLinePlaceholder":330},[303,831,832,835,838,841,844,847],{"class":305,"line":347},[303,833,834],{"class":309},"    if",[303,836,837],{"class":309}," *",[303,839,840],{"class":323},"first ",[303,842,843],{"class":309},"==",[303,845,846],{"class":380}," 1",[303,848,371],{"class":323},[303,850,851,854,856],{"class":305,"line":352},[303,852,853],{"class":309},"        return",[303,855,846],{"class":380},[303,857,324],{"class":323},[303,859,860],{"class":305,"line":362},[303,861,466],{"class":323},[303,863,864],{"class":305,"line":374},[303,865,331],{"emptyLinePlaceholder":330},[303,867,868],{"class":305,"line":393},[303,869,870],{"class":380},"    0\n",[303,872,873],{"class":305,"line":398},[303,874,509],{"class":323},[303,876,877],{"class":305,"line":404},[303,878,331],{"emptyLinePlaceholder":330},[303,880,881],{"class":305,"line":410},[303,882,606],{"class":358},[303,884,885],{"class":305,"line":448},[303,886,331],{"emptyLinePlaceholder":330},[303,888,889],{"class":305,"line":463},[303,890,615],{"class":323},[303,892,893,895,898],{"class":305,"line":469},[303,894,337],{"class":309},[303,896,897],{"class":340}," calculate_for_one_pin",[303,899,489],{"class":323},[303,901,902,904,907,909,911,913,915,917,919,921,923,925,927,929,932],{"class":305,"line":475},[303,903,629],{"class":309},[303,905,906],{"class":323}," lose",[303,908,422],{"class":309},[303,910,425],{"class":313},[303,912,428],{"class":323},[303,914,254],{"class":313},[303,916,433],{"class":323},[303,918,254],{"class":313},[303,920,647],{"class":323},[303,922,650],{"class":309},[303,924,653],{"class":323},[303,926,534],{"class":380},[303,928,658],{"class":309},[303,930,931],{"class":380},"9",[303,933,664],{"class":323},[303,935,936,938,940,942,944,946,948,950,952,954,956],{"class":305,"line":481},[303,937,669],{"class":309},[303,939,672],{"class":340},[303,941,454],{"class":323},[303,943,677],{"class":309},[303,945,680],{"class":323},[303,947,677],{"class":309},[303,949,653],{"class":323},[303,951,534],{"class":380},[303,953,433],{"class":323},[303,955,534],{"class":380},[303,957,693],{"class":323},[303,959,960,962,964],{"class":305,"line":492},[303,961,669],{"class":309},[303,963,700],{"class":340},[303,965,498],{"class":323},[303,967,968],{"class":305,"line":501},[303,969,331],{"emptyLinePlaceholder":330},[303,971,972,974,977,979,981,983,985,987,989,991,993,996,999,1002,1004,1006,1008,1011,1013,1016],{"class":305,"line":506},[303,973,629],{"class":309},[303,975,976],{"class":323}," scores",[303,978,422],{"class":309},[303,980,425],{"class":313},[303,982,428],{"class":323},[303,984,254],{"class":313},[303,986,433],{"class":323},[303,988,254],{"class":313},[303,990,647],{"class":323},[303,992,650],{"class":309},[303,994,995],{"class":323}," [",[303,997,998],{"class":340},"vec!",[303,1000,1001],{"class":323},"[(",[303,1003,744],{"class":380},[303,1005,433],{"class":323},[303,1007,534],{"class":380},[303,1009,1010],{"class":323},")], lose]",[303,1012,50],{"class":309},[303,1014,1015],{"class":340},"concat",[303,1017,498],{"class":323},[303,1019,1021],{"class":305,"line":1020},20,[303,1022,331],{"emptyLinePlaceholder":330},[303,1024,1026,1028,1031,1033],{"class":305,"line":1025},21,[303,1027,711],{"class":340},[303,1029,1030],{"class":323},"(scores, ",[303,1032,744],{"class":380},[303,1034,719],{"class":323},[303,1036,1038],{"class":305,"line":1037},22,[303,1039,509],{"class":323},[20,1041,1042],{},"Les deux tests passent désormais : la partie à zéro et celle à un point. On s’arrête là pour cette baby step.",[20,1044,1045,1046,1048],{},"Pour la suivante on reste sur ",[26,1047,733],{},", avec une autre valeur pour le premier lancer. Cet exemple nous aidera à faire émerger une règle plus générale.",[20,1050,1051,529,1054],{},[26,1052,1053],{},"Scénario : cinq quilles à la première frame, puis des zéros, donnent",[26,1055,1056],{},[92,1057,1058],{},"5",[20,1060,1061,1062,1064,1065,529,1067,529,1071,50],{},"Notre joueur renverse maintenant 5 quilles sur son premier lancer. Le nouveau test est rouge : notre fonction retourne ",[92,1063,534],{}," pour cette valeur. On avance d’une baby step en ajoutant un deuxième cas spécifique : ",[26,1066,753],{},[26,1068,1069,758],{},[92,1070,1058],{},[26,1072,1073],{},[92,1074,1058],{},[295,1076,1078],{"className":297,"code":1077,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, _second) = raw_scores.first().unwrap();\n\n    if *first == 1 {\n        return 1;\n    }\n\n    if *first == 5 {\n        return 5;\n    }\n\n    0\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_five_pins() {\n    let lose: Vec\u003C(Roll, Roll)> = (0..9)\n        .map(|_| (0, 0))\n        .collect();\n\n    let scores: Vec\u003C(Roll, Roll)> = [vec![(5, 0)], lose].concat();\n\n    assert_score(scores, 5);\n}\n",[92,1079,1080,1110,1132,1136,1150,1158,1162,1166,1181,1189,1193,1197,1201,1205,1209,1213,1217,1221,1230,1262,1286,1294,1298,1341,1346,1357],{"__ignoreMap":299},[303,1081,1082,1084,1086,1088,1090,1092,1094,1096,1098,1100,1102,1104,1106,1108],{"class":305,"line":306},[303,1083,558],{"class":309},[303,1085,561],{"class":309},[303,1087,341],{"class":340},[303,1089,566],{"class":323},[303,1091,422],{"class":309},[303,1093,425],{"class":313},[303,1095,428],{"class":323},[303,1097,254],{"class":313},[303,1099,433],{"class":323},[303,1101,254],{"class":313},[303,1103,581],{"class":323},[303,1105,584],{"class":309},[303,1107,320],{"class":313},[303,1109,371],{"class":323},[303,1111,1112,1114,1116,1118,1120,1122,1124,1126,1128,1130],{"class":305,"line":327},[303,1113,629],{"class":309},[303,1115,805],{"class":323},[303,1117,650],{"class":309},[303,1119,810],{"class":323},[303,1121,50],{"class":309},[303,1123,815],{"class":340},[303,1125,818],{"class":323},[303,1127,50],{"class":309},[303,1129,823],{"class":340},[303,1131,498],{"class":323},[303,1133,1134],{"class":305,"line":334},[303,1135,331],{"emptyLinePlaceholder":330},[303,1137,1138,1140,1142,1144,1146,1148],{"class":305,"line":347},[303,1139,834],{"class":309},[303,1141,837],{"class":309},[303,1143,840],{"class":323},[303,1145,843],{"class":309},[303,1147,846],{"class":380},[303,1149,371],{"class":323},[303,1151,1152,1154,1156],{"class":305,"line":352},[303,1153,853],{"class":309},[303,1155,846],{"class":380},[303,1157,324],{"class":323},[303,1159,1160],{"class":305,"line":362},[303,1161,466],{"class":323},[303,1163,1164],{"class":305,"line":374},[303,1165,331],{"emptyLinePlaceholder":330},[303,1167,1168,1170,1172,1174,1176,1179],{"class":305,"line":393},[303,1169,834],{"class":309},[303,1171,837],{"class":309},[303,1173,840],{"class":323},[303,1175,843],{"class":309},[303,1177,1178],{"class":380}," 5",[303,1180,371],{"class":323},[303,1182,1183,1185,1187],{"class":305,"line":398},[303,1184,853],{"class":309},[303,1186,1178],{"class":380},[303,1188,324],{"class":323},[303,1190,1191],{"class":305,"line":404},[303,1192,466],{"class":323},[303,1194,1195],{"class":305,"line":410},[303,1196,331],{"emptyLinePlaceholder":330},[303,1198,1199],{"class":305,"line":448},[303,1200,870],{"class":380},[303,1202,1203],{"class":305,"line":463},[303,1204,509],{"class":323},[303,1206,1207],{"class":305,"line":469},[303,1208,331],{"emptyLinePlaceholder":330},[303,1210,1211],{"class":305,"line":475},[303,1212,606],{"class":358},[303,1214,1215],{"class":305,"line":481},[303,1216,331],{"emptyLinePlaceholder":330},[303,1218,1219],{"class":305,"line":492},[303,1220,615],{"class":323},[303,1222,1223,1225,1228],{"class":305,"line":501},[303,1224,337],{"class":309},[303,1226,1227],{"class":340}," calculate_for_five_pins",[303,1229,489],{"class":323},[303,1231,1232,1234,1236,1238,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1260],{"class":305,"line":506},[303,1233,629],{"class":309},[303,1235,906],{"class":323},[303,1237,422],{"class":309},[303,1239,425],{"class":313},[303,1241,428],{"class":323},[303,1243,254],{"class":313},[303,1245,433],{"class":323},[303,1247,254],{"class":313},[303,1249,647],{"class":323},[303,1251,650],{"class":309},[303,1253,653],{"class":323},[303,1255,534],{"class":380},[303,1257,658],{"class":309},[303,1259,931],{"class":380},[303,1261,664],{"class":323},[303,1263,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284],{"class":305,"line":1020},[303,1265,669],{"class":309},[303,1267,672],{"class":340},[303,1269,454],{"class":323},[303,1271,677],{"class":309},[303,1273,680],{"class":323},[303,1275,677],{"class":309},[303,1277,653],{"class":323},[303,1279,534],{"class":380},[303,1281,433],{"class":323},[303,1283,534],{"class":380},[303,1285,693],{"class":323},[303,1287,1288,1290,1292],{"class":305,"line":1025},[303,1289,669],{"class":309},[303,1291,700],{"class":340},[303,1293,498],{"class":323},[303,1295,1296],{"class":305,"line":1037},[303,1297,331],{"emptyLinePlaceholder":330},[303,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329,1331,1333,1335,1337,1339],{"class":305,"line":1300},23,[303,1302,629],{"class":309},[303,1304,976],{"class":323},[303,1306,422],{"class":309},[303,1308,425],{"class":313},[303,1310,428],{"class":323},[303,1312,254],{"class":313},[303,1314,433],{"class":323},[303,1316,254],{"class":313},[303,1318,647],{"class":323},[303,1320,650],{"class":309},[303,1322,995],{"class":323},[303,1324,998],{"class":340},[303,1326,1001],{"class":323},[303,1328,1058],{"class":380},[303,1330,433],{"class":323},[303,1332,534],{"class":380},[303,1334,1010],{"class":323},[303,1336,50],{"class":309},[303,1338,1015],{"class":340},[303,1340,498],{"class":323},[303,1342,1344],{"class":305,"line":1343},24,[303,1345,331],{"emptyLinePlaceholder":330},[303,1347,1349,1351,1353,1355],{"class":305,"line":1348},25,[303,1350,711],{"class":340},[303,1352,1030],{"class":323},[303,1354,1058],{"class":380},[303,1356,719],{"class":323},[303,1358,1360],{"class":305,"line":1359},26,[303,1361,509],{"class":323},[20,1363,1364,1365,433,1367,1369,1370,1372],{},"Les trois exemples attendent désormais la valeur du premier lancer : ",[92,1366,534],{},[92,1368,744],{}," ou ",[92,1371,1058],{},". On peut donc supprimer les cas particuliers lors du refactoring :",[295,1374,1376],{"className":297,"code":1375,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, _second) = raw_scores.first().unwrap();\n\n    *first\n}\n",[92,1377,1378,1408,1430,1434,1442],{"__ignoreMap":299},[303,1379,1380,1382,1384,1386,1388,1390,1392,1394,1396,1398,1400,1402,1404,1406],{"class":305,"line":306},[303,1381,558],{"class":309},[303,1383,561],{"class":309},[303,1385,341],{"class":340},[303,1387,566],{"class":323},[303,1389,422],{"class":309},[303,1391,425],{"class":313},[303,1393,428],{"class":323},[303,1395,254],{"class":313},[303,1397,433],{"class":323},[303,1399,254],{"class":313},[303,1401,581],{"class":323},[303,1403,584],{"class":309},[303,1405,320],{"class":313},[303,1407,371],{"class":323},[303,1409,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428],{"class":305,"line":327},[303,1411,629],{"class":309},[303,1413,805],{"class":323},[303,1415,650],{"class":309},[303,1417,810],{"class":323},[303,1419,50],{"class":309},[303,1421,815],{"class":340},[303,1423,818],{"class":323},[303,1425,50],{"class":309},[303,1427,823],{"class":340},[303,1429,498],{"class":323},[303,1431,1432],{"class":305,"line":334},[303,1433,331],{"emptyLinePlaceholder":330},[303,1435,1436,1439],{"class":305,"line":347},[303,1437,1438],{"class":309},"    *",[303,1440,1441],{"class":323},"first\n",[303,1443,1444],{"class":305,"line":352},[303,1445,509],{"class":323},[20,1447,1448,1449,1452],{},"On poursuit encore avec ",[26,1450,1451],{},"O",", en faisant maintenant marquer des points au deuxième lancer de la première frame.",[20,1454,1455,529,1458],{},[26,1456,1457],{},"Scénario : six quilles, puis deux quilles à la première frame, donnent",[26,1459,1460],{},[92,1461,1462],{},"8",[20,1464,1465,1466,750,1469,529,1472,529,1477,50],{},"Cette fois, le joueur renverse six quilles au premier lancer et deux au second, puis fait uniquement des gouttières. Le nouveau test est rouge : notre fonction retourne seulement ",[92,1467,1468],{},"6",[26,1470,1471],{},"si le deuxième lancer vaut",[26,1473,1474,758],{},[92,1475,1476],{},"2",[26,1478,1479],{},[92,1480,1462],{},[295,1482,1484],{"className":297,"code":1483,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, second) = raw_scores.first().unwrap();\n\n    if *first == 6 && *second == 2 {\n        return 8;\n    }\n\n    *first\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_six_then_two_pins() {\n    let lose: Vec\u003C(Roll, Roll)> = (0..9)\n        .map(|_| (0, 0))\n        .collect();\n\n    let scores: Vec\u003C(Roll, Roll)> = [vec![(6, 2)], lose].concat();\n\n    assert_score(scores, 8);\n}\n",[92,1485,1486,1516,1539,1543,1571,1580,1584,1588,1594,1598,1602,1606,1610,1614,1623,1655,1679,1687,1691,1733,1737,1747],{"__ignoreMap":299},[303,1487,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506,1508,1510,1512,1514],{"class":305,"line":306},[303,1489,558],{"class":309},[303,1491,561],{"class":309},[303,1493,341],{"class":340},[303,1495,566],{"class":323},[303,1497,422],{"class":309},[303,1499,425],{"class":313},[303,1501,428],{"class":323},[303,1503,254],{"class":313},[303,1505,433],{"class":323},[303,1507,254],{"class":313},[303,1509,581],{"class":323},[303,1511,584],{"class":309},[303,1513,320],{"class":313},[303,1515,371],{"class":323},[303,1517,1518,1520,1523,1525,1527,1529,1531,1533,1535,1537],{"class":305,"line":327},[303,1519,629],{"class":309},[303,1521,1522],{"class":323}," (first, second) ",[303,1524,650],{"class":309},[303,1526,810],{"class":323},[303,1528,50],{"class":309},[303,1530,815],{"class":340},[303,1532,818],{"class":323},[303,1534,50],{"class":309},[303,1536,823],{"class":340},[303,1538,498],{"class":323},[303,1540,1541],{"class":305,"line":334},[303,1542,331],{"emptyLinePlaceholder":330},[303,1544,1545,1547,1549,1551,1553,1556,1559,1561,1564,1566,1569],{"class":305,"line":347},[303,1546,834],{"class":309},[303,1548,837],{"class":309},[303,1550,840],{"class":323},[303,1552,843],{"class":309},[303,1554,1555],{"class":380}," 6",[303,1557,1558],{"class":309}," &&",[303,1560,837],{"class":309},[303,1562,1563],{"class":323},"second ",[303,1565,843],{"class":309},[303,1567,1568],{"class":380}," 2",[303,1570,371],{"class":323},[303,1572,1573,1575,1578],{"class":305,"line":352},[303,1574,853],{"class":309},[303,1576,1577],{"class":380}," 8",[303,1579,324],{"class":323},[303,1581,1582],{"class":305,"line":362},[303,1583,466],{"class":323},[303,1585,1586],{"class":305,"line":374},[303,1587,331],{"emptyLinePlaceholder":330},[303,1589,1590,1592],{"class":305,"line":393},[303,1591,1438],{"class":309},[303,1593,1441],{"class":323},[303,1595,1596],{"class":305,"line":398},[303,1597,509],{"class":323},[303,1599,1600],{"class":305,"line":404},[303,1601,331],{"emptyLinePlaceholder":330},[303,1603,1604],{"class":305,"line":410},[303,1605,606],{"class":358},[303,1607,1608],{"class":305,"line":448},[303,1609,331],{"emptyLinePlaceholder":330},[303,1611,1612],{"class":305,"line":463},[303,1613,615],{"class":323},[303,1615,1616,1618,1621],{"class":305,"line":469},[303,1617,337],{"class":309},[303,1619,1620],{"class":340}," calculate_for_six_then_two_pins",[303,1622,489],{"class":323},[303,1624,1625,1627,1629,1631,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653],{"class":305,"line":475},[303,1626,629],{"class":309},[303,1628,906],{"class":323},[303,1630,422],{"class":309},[303,1632,425],{"class":313},[303,1634,428],{"class":323},[303,1636,254],{"class":313},[303,1638,433],{"class":323},[303,1640,254],{"class":313},[303,1642,647],{"class":323},[303,1644,650],{"class":309},[303,1646,653],{"class":323},[303,1648,534],{"class":380},[303,1650,658],{"class":309},[303,1652,931],{"class":380},[303,1654,664],{"class":323},[303,1656,1657,1659,1661,1663,1665,1667,1669,1671,1673,1675,1677],{"class":305,"line":481},[303,1658,669],{"class":309},[303,1660,672],{"class":340},[303,1662,454],{"class":323},[303,1664,677],{"class":309},[303,1666,680],{"class":323},[303,1668,677],{"class":309},[303,1670,653],{"class":323},[303,1672,534],{"class":380},[303,1674,433],{"class":323},[303,1676,534],{"class":380},[303,1678,693],{"class":323},[303,1680,1681,1683,1685],{"class":305,"line":492},[303,1682,669],{"class":309},[303,1684,700],{"class":340},[303,1686,498],{"class":323},[303,1688,1689],{"class":305,"line":501},[303,1690,331],{"emptyLinePlaceholder":330},[303,1692,1693,1695,1697,1699,1701,1703,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1725,1727,1729,1731],{"class":305,"line":506},[303,1694,629],{"class":309},[303,1696,976],{"class":323},[303,1698,422],{"class":309},[303,1700,425],{"class":313},[303,1702,428],{"class":323},[303,1704,254],{"class":313},[303,1706,433],{"class":323},[303,1708,254],{"class":313},[303,1710,647],{"class":323},[303,1712,650],{"class":309},[303,1714,995],{"class":323},[303,1716,998],{"class":340},[303,1718,1001],{"class":323},[303,1720,1468],{"class":380},[303,1722,433],{"class":323},[303,1724,1476],{"class":380},[303,1726,1010],{"class":323},[303,1728,50],{"class":309},[303,1730,1015],{"class":340},[303,1732,498],{"class":323},[303,1734,1735],{"class":305,"line":1020},[303,1736,331],{"emptyLinePlaceholder":330},[303,1738,1739,1741,1743,1745],{"class":305,"line":1025},[303,1740,711],{"class":340},[303,1742,1030],{"class":323},[303,1744,1462],{"class":380},[303,1746,719],{"class":323},[303,1748,1749],{"class":305,"line":1037},[303,1750,509],{"class":323},[20,1752,1753],{},"Cette baby step fait passer notre nouvel exemple. Les suivants nous permettront de généraliser le calcul aux deux lancers de la frame.",[20,1755,1756,529,1759],{},[26,1757,1758],{},"Scénario : deux quilles, puis quatre quilles à la première frame, donnent",[26,1760,1761],{},[92,1762,1468],{},[20,1764,1765,1766,529,1768,529,1773,50],{},"Notre joueur renverse deux quilles au premier lancer et quatre au second, puis fait uniquement des gouttières. On ajoute un nouveau cas spécifique : ",[26,1767,1471],{},[26,1769,1770,758],{},[92,1771,1772],{},"4",[26,1774,1775],{},[92,1776,1468],{},[295,1778,1780],{"className":297,"code":1779,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, second) = raw_scores.first().unwrap();\n\n    if *first == 6 && *second == 2 {\n        return 8;\n    }\n\n    if *first == 2 && *second == 4 {\n        return 6;\n    }\n\n    *first\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_two_then_four_pins() {\n    let lose: Vec\u003C(Roll, Roll)> = (0..9)\n        .map(|_| (0, 0))\n        .collect();\n\n    let scores: Vec\u003C(Roll, Roll)> = [vec![(2, 4)], lose].concat();\n\n    assert_score(scores, 6);\n}\n",[92,1781,1782,1812,1834,1838,1862,1870,1874,1878,1903,1911,1915,1919,1925,1929,1933,1937,1941,1945,1954,1986,2010,2018,2022,2064,2068,2078],{"__ignoreMap":299},[303,1783,1784,1786,1788,1790,1792,1794,1796,1798,1800,1802,1804,1806,1808,1810],{"class":305,"line":306},[303,1785,558],{"class":309},[303,1787,561],{"class":309},[303,1789,341],{"class":340},[303,1791,566],{"class":323},[303,1793,422],{"class":309},[303,1795,425],{"class":313},[303,1797,428],{"class":323},[303,1799,254],{"class":313},[303,1801,433],{"class":323},[303,1803,254],{"class":313},[303,1805,581],{"class":323},[303,1807,584],{"class":309},[303,1809,320],{"class":313},[303,1811,371],{"class":323},[303,1813,1814,1816,1818,1820,1822,1824,1826,1828,1830,1832],{"class":305,"line":327},[303,1815,629],{"class":309},[303,1817,1522],{"class":323},[303,1819,650],{"class":309},[303,1821,810],{"class":323},[303,1823,50],{"class":309},[303,1825,815],{"class":340},[303,1827,818],{"class":323},[303,1829,50],{"class":309},[303,1831,823],{"class":340},[303,1833,498],{"class":323},[303,1835,1836],{"class":305,"line":334},[303,1837,331],{"emptyLinePlaceholder":330},[303,1839,1840,1842,1844,1846,1848,1850,1852,1854,1856,1858,1860],{"class":305,"line":347},[303,1841,834],{"class":309},[303,1843,837],{"class":309},[303,1845,840],{"class":323},[303,1847,843],{"class":309},[303,1849,1555],{"class":380},[303,1851,1558],{"class":309},[303,1853,837],{"class":309},[303,1855,1563],{"class":323},[303,1857,843],{"class":309},[303,1859,1568],{"class":380},[303,1861,371],{"class":323},[303,1863,1864,1866,1868],{"class":305,"line":352},[303,1865,853],{"class":309},[303,1867,1577],{"class":380},[303,1869,324],{"class":323},[303,1871,1872],{"class":305,"line":362},[303,1873,466],{"class":323},[303,1875,1876],{"class":305,"line":374},[303,1877,331],{"emptyLinePlaceholder":330},[303,1879,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898,1901],{"class":305,"line":393},[303,1881,834],{"class":309},[303,1883,837],{"class":309},[303,1885,840],{"class":323},[303,1887,843],{"class":309},[303,1889,1568],{"class":380},[303,1891,1558],{"class":309},[303,1893,837],{"class":309},[303,1895,1563],{"class":323},[303,1897,843],{"class":309},[303,1899,1900],{"class":380}," 4",[303,1902,371],{"class":323},[303,1904,1905,1907,1909],{"class":305,"line":398},[303,1906,853],{"class":309},[303,1908,1555],{"class":380},[303,1910,324],{"class":323},[303,1912,1913],{"class":305,"line":404},[303,1914,466],{"class":323},[303,1916,1917],{"class":305,"line":410},[303,1918,331],{"emptyLinePlaceholder":330},[303,1920,1921,1923],{"class":305,"line":448},[303,1922,1438],{"class":309},[303,1924,1441],{"class":323},[303,1926,1927],{"class":305,"line":463},[303,1928,509],{"class":323},[303,1930,1931],{"class":305,"line":469},[303,1932,331],{"emptyLinePlaceholder":330},[303,1934,1935],{"class":305,"line":475},[303,1936,606],{"class":358},[303,1938,1939],{"class":305,"line":481},[303,1940,331],{"emptyLinePlaceholder":330},[303,1942,1943],{"class":305,"line":492},[303,1944,615],{"class":323},[303,1946,1947,1949,1952],{"class":305,"line":501},[303,1948,337],{"class":309},[303,1950,1951],{"class":340}," calculate_for_two_then_four_pins",[303,1953,489],{"class":323},[303,1955,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974,1976,1978,1980,1982,1984],{"class":305,"line":506},[303,1957,629],{"class":309},[303,1959,906],{"class":323},[303,1961,422],{"class":309},[303,1963,425],{"class":313},[303,1965,428],{"class":323},[303,1967,254],{"class":313},[303,1969,433],{"class":323},[303,1971,254],{"class":313},[303,1973,647],{"class":323},[303,1975,650],{"class":309},[303,1977,653],{"class":323},[303,1979,534],{"class":380},[303,1981,658],{"class":309},[303,1983,931],{"class":380},[303,1985,664],{"class":323},[303,1987,1988,1990,1992,1994,1996,1998,2000,2002,2004,2006,2008],{"class":305,"line":1020},[303,1989,669],{"class":309},[303,1991,672],{"class":340},[303,1993,454],{"class":323},[303,1995,677],{"class":309},[303,1997,680],{"class":323},[303,1999,677],{"class":309},[303,2001,653],{"class":323},[303,2003,534],{"class":380},[303,2005,433],{"class":323},[303,2007,534],{"class":380},[303,2009,693],{"class":323},[303,2011,2012,2014,2016],{"class":305,"line":1025},[303,2013,669],{"class":309},[303,2015,700],{"class":340},[303,2017,498],{"class":323},[303,2019,2020],{"class":305,"line":1037},[303,2021,331],{"emptyLinePlaceholder":330},[303,2023,2024,2026,2028,2030,2032,2034,2036,2038,2040,2042,2044,2046,2048,2050,2052,2054,2056,2058,2060,2062],{"class":305,"line":1300},[303,2025,629],{"class":309},[303,2027,976],{"class":323},[303,2029,422],{"class":309},[303,2031,425],{"class":313},[303,2033,428],{"class":323},[303,2035,254],{"class":313},[303,2037,433],{"class":323},[303,2039,254],{"class":313},[303,2041,647],{"class":323},[303,2043,650],{"class":309},[303,2045,995],{"class":323},[303,2047,998],{"class":340},[303,2049,1001],{"class":323},[303,2051,1476],{"class":380},[303,2053,433],{"class":323},[303,2055,1772],{"class":380},[303,2057,1010],{"class":323},[303,2059,50],{"class":309},[303,2061,1015],{"class":340},[303,2063,498],{"class":323},[303,2065,2066],{"class":305,"line":1343},[303,2067,331],{"emptyLinePlaceholder":330},[303,2069,2070,2072,2074,2076],{"class":305,"line":1348},[303,2071,711],{"class":340},[303,2073,1030],{"class":323},[303,2075,1468],{"class":380},[303,2077,719],{"class":323},[303,2079,2080],{"class":305,"line":1359},[303,2081,509],{"class":323},[20,2083,2084],{},"Les exemples passent, mais les cas particuliers s’accumulent. Un prochain exemple nous aidera à faire émerger la règle commune.",[20,2086,2087,529,2090],{},[26,2088,2089],{},"Scénario : trois quilles, puis cinq quilles à la première frame, donnent",[26,2091,2092],{},[92,2093,1462],{},[20,2095,2096,2097,2100,2101,529,2104,529,2108,529,2111,529,2115,50],{},"Le nouveau test est rouge : notre fonction retourne seulement ",[92,2098,2099],{},"3",". On ajoute un cas spécifique : ",[26,2102,2103],{},"si les deux lancers valent",[26,2105,2106],{},[92,2107,2099],{},[26,2109,2110],{},"et",[26,2112,2113,758],{},[92,2114,1058],{},[26,2116,2117],{},[92,2118,1462],{},[295,2120,2122],{"className":297,"code":2121,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, second) = raw_scores.first().unwrap();\n\n    if *first == 3 && *second == 5 {\n        return 8;\n    }\n\n    if *first == 6 && *second == 2 {\n        return 8;\n    }\n\n    if *first == 2 && *second == 4 {\n        return 6;\n    }\n\n    *first\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_three_then_five_pins() {\n    let lose: Vec\u003C(Roll, Roll)> = (0..9)\n        .map(|_| (0, 0))\n        .collect();\n\n    let scores: Vec\u003C(Roll, Roll)> = [vec![(3, 5)], lose].concat();\n\n    assert_score(scores, 8);\n}\n",[92,2123,2124,2154,2176,2180,2205,2213,2217,2221,2245,2253,2257,2261,2285,2293,2297,2301,2307,2311,2315,2319,2323,2327,2336,2368,2392,2400,2404,2447,2452,2463],{"__ignoreMap":299},[303,2125,2126,2128,2130,2132,2134,2136,2138,2140,2142,2144,2146,2148,2150,2152],{"class":305,"line":306},[303,2127,558],{"class":309},[303,2129,561],{"class":309},[303,2131,341],{"class":340},[303,2133,566],{"class":323},[303,2135,422],{"class":309},[303,2137,425],{"class":313},[303,2139,428],{"class":323},[303,2141,254],{"class":313},[303,2143,433],{"class":323},[303,2145,254],{"class":313},[303,2147,581],{"class":323},[303,2149,584],{"class":309},[303,2151,320],{"class":313},[303,2153,371],{"class":323},[303,2155,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174],{"class":305,"line":327},[303,2157,629],{"class":309},[303,2159,1522],{"class":323},[303,2161,650],{"class":309},[303,2163,810],{"class":323},[303,2165,50],{"class":309},[303,2167,815],{"class":340},[303,2169,818],{"class":323},[303,2171,50],{"class":309},[303,2173,823],{"class":340},[303,2175,498],{"class":323},[303,2177,2178],{"class":305,"line":334},[303,2179,331],{"emptyLinePlaceholder":330},[303,2181,2182,2184,2186,2188,2190,2193,2195,2197,2199,2201,2203],{"class":305,"line":347},[303,2183,834],{"class":309},[303,2185,837],{"class":309},[303,2187,840],{"class":323},[303,2189,843],{"class":309},[303,2191,2192],{"class":380}," 3",[303,2194,1558],{"class":309},[303,2196,837],{"class":309},[303,2198,1563],{"class":323},[303,2200,843],{"class":309},[303,2202,1178],{"class":380},[303,2204,371],{"class":323},[303,2206,2207,2209,2211],{"class":305,"line":352},[303,2208,853],{"class":309},[303,2210,1577],{"class":380},[303,2212,324],{"class":323},[303,2214,2215],{"class":305,"line":362},[303,2216,466],{"class":323},[303,2218,2219],{"class":305,"line":374},[303,2220,331],{"emptyLinePlaceholder":330},[303,2222,2223,2225,2227,2229,2231,2233,2235,2237,2239,2241,2243],{"class":305,"line":393},[303,2224,834],{"class":309},[303,2226,837],{"class":309},[303,2228,840],{"class":323},[303,2230,843],{"class":309},[303,2232,1555],{"class":380},[303,2234,1558],{"class":309},[303,2236,837],{"class":309},[303,2238,1563],{"class":323},[303,2240,843],{"class":309},[303,2242,1568],{"class":380},[303,2244,371],{"class":323},[303,2246,2247,2249,2251],{"class":305,"line":398},[303,2248,853],{"class":309},[303,2250,1577],{"class":380},[303,2252,324],{"class":323},[303,2254,2255],{"class":305,"line":404},[303,2256,466],{"class":323},[303,2258,2259],{"class":305,"line":410},[303,2260,331],{"emptyLinePlaceholder":330},[303,2262,2263,2265,2267,2269,2271,2273,2275,2277,2279,2281,2283],{"class":305,"line":448},[303,2264,834],{"class":309},[303,2266,837],{"class":309},[303,2268,840],{"class":323},[303,2270,843],{"class":309},[303,2272,1568],{"class":380},[303,2274,1558],{"class":309},[303,2276,837],{"class":309},[303,2278,1563],{"class":323},[303,2280,843],{"class":309},[303,2282,1900],{"class":380},[303,2284,371],{"class":323},[303,2286,2287,2289,2291],{"class":305,"line":463},[303,2288,853],{"class":309},[303,2290,1555],{"class":380},[303,2292,324],{"class":323},[303,2294,2295],{"class":305,"line":469},[303,2296,466],{"class":323},[303,2298,2299],{"class":305,"line":475},[303,2300,331],{"emptyLinePlaceholder":330},[303,2302,2303,2305],{"class":305,"line":481},[303,2304,1438],{"class":309},[303,2306,1441],{"class":323},[303,2308,2309],{"class":305,"line":492},[303,2310,509],{"class":323},[303,2312,2313],{"class":305,"line":501},[303,2314,331],{"emptyLinePlaceholder":330},[303,2316,2317],{"class":305,"line":506},[303,2318,606],{"class":358},[303,2320,2321],{"class":305,"line":1020},[303,2322,331],{"emptyLinePlaceholder":330},[303,2324,2325],{"class":305,"line":1025},[303,2326,615],{"class":323},[303,2328,2329,2331,2334],{"class":305,"line":1037},[303,2330,337],{"class":309},[303,2332,2333],{"class":340}," calculate_for_three_then_five_pins",[303,2335,489],{"class":323},[303,2337,2338,2340,2342,2344,2346,2348,2350,2352,2354,2356,2358,2360,2362,2364,2366],{"class":305,"line":1300},[303,2339,629],{"class":309},[303,2341,906],{"class":323},[303,2343,422],{"class":309},[303,2345,425],{"class":313},[303,2347,428],{"class":323},[303,2349,254],{"class":313},[303,2351,433],{"class":323},[303,2353,254],{"class":313},[303,2355,647],{"class":323},[303,2357,650],{"class":309},[303,2359,653],{"class":323},[303,2361,534],{"class":380},[303,2363,658],{"class":309},[303,2365,931],{"class":380},[303,2367,664],{"class":323},[303,2369,2370,2372,2374,2376,2378,2380,2382,2384,2386,2388,2390],{"class":305,"line":1343},[303,2371,669],{"class":309},[303,2373,672],{"class":340},[303,2375,454],{"class":323},[303,2377,677],{"class":309},[303,2379,680],{"class":323},[303,2381,677],{"class":309},[303,2383,653],{"class":323},[303,2385,534],{"class":380},[303,2387,433],{"class":323},[303,2389,534],{"class":380},[303,2391,693],{"class":323},[303,2393,2394,2396,2398],{"class":305,"line":1348},[303,2395,669],{"class":309},[303,2397,700],{"class":340},[303,2399,498],{"class":323},[303,2401,2402],{"class":305,"line":1359},[303,2403,331],{"emptyLinePlaceholder":330},[303,2405,2407,2409,2411,2413,2415,2417,2419,2421,2423,2425,2427,2429,2431,2433,2435,2437,2439,2441,2443,2445],{"class":305,"line":2406},27,[303,2408,629],{"class":309},[303,2410,976],{"class":323},[303,2412,422],{"class":309},[303,2414,425],{"class":313},[303,2416,428],{"class":323},[303,2418,254],{"class":313},[303,2420,433],{"class":323},[303,2422,254],{"class":313},[303,2424,647],{"class":323},[303,2426,650],{"class":309},[303,2428,995],{"class":323},[303,2430,998],{"class":340},[303,2432,1001],{"class":323},[303,2434,2099],{"class":380},[303,2436,433],{"class":323},[303,2438,1058],{"class":380},[303,2440,1010],{"class":323},[303,2442,50],{"class":309},[303,2444,1015],{"class":340},[303,2446,498],{"class":323},[303,2448,2450],{"class":305,"line":2449},28,[303,2451,331],{"emptyLinePlaceholder":330},[303,2453,2455,2457,2459,2461],{"class":305,"line":2454},29,[303,2456,711],{"class":340},[303,2458,1030],{"class":323},[303,2460,1462],{"class":380},[303,2462,719],{"class":323},[303,2464,2466],{"class":305,"line":2465},30,[303,2467,509],{"class":323},[20,2469,2470],{},"Tous nos exemples attendent la somme des deux lancers de la première frame. On peut donc remplacer les cas particuliers par cette addition lors du refactoring :",[295,2472,2474],{"className":297,"code":2473,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, second) = raw_scores.first().unwrap();\n\n    *first + *second\n}\n",[92,2475,2476,2506,2528,2532,2546],{"__ignoreMap":299},[303,2477,2478,2480,2482,2484,2486,2488,2490,2492,2494,2496,2498,2500,2502,2504],{"class":305,"line":306},[303,2479,558],{"class":309},[303,2481,561],{"class":309},[303,2483,341],{"class":340},[303,2485,566],{"class":323},[303,2487,422],{"class":309},[303,2489,425],{"class":313},[303,2491,428],{"class":323},[303,2493,254],{"class":313},[303,2495,433],{"class":323},[303,2497,254],{"class":313},[303,2499,581],{"class":323},[303,2501,584],{"class":309},[303,2503,320],{"class":313},[303,2505,371],{"class":323},[303,2507,2508,2510,2512,2514,2516,2518,2520,2522,2524,2526],{"class":305,"line":327},[303,2509,629],{"class":309},[303,2511,1522],{"class":323},[303,2513,650],{"class":309},[303,2515,810],{"class":323},[303,2517,50],{"class":309},[303,2519,815],{"class":340},[303,2521,818],{"class":323},[303,2523,50],{"class":309},[303,2525,823],{"class":340},[303,2527,498],{"class":323},[303,2529,2530],{"class":305,"line":334},[303,2531,331],{"emptyLinePlaceholder":330},[303,2533,2534,2536,2538,2541,2543],{"class":305,"line":347},[303,2535,1438],{"class":309},[303,2537,840],{"class":323},[303,2539,2540],{"class":309},"+",[303,2542,837],{"class":309},[303,2544,2545],{"class":323},"second\n",[303,2547,2548],{"class":305,"line":352},[303,2549,509],{"class":323},[52,2551,2553],{"id":2552},"m-passer-à-plusieurs-cas","M - Passer à plusieurs cas",[20,2555,730,2556,2559],{},[26,2557,2558],{},"M pour Many"," nous invite maintenant à considérer plusieurs frames qui marquent des points.",[20,2561,2562,529,2565],{},[26,2563,2564],{},"Scénario : dix frames à deux quilles, puis deux quilles, donnent",[26,2566,2567],{},[92,2568,2569],{},"40",[20,2571,2572,2573,750,2575,529,2578,529,2583,50],{},"Notre joueur renverse deux quilles à chaque lancer, pendant toute la partie. Le nouveau test est rouge : notre fonction calcule uniquement la première frame et retourne ",[92,2574,1772],{},[26,2576,2577],{},"si toutes les frames valent",[26,2579,2580,758],{},[92,2581,2582],{},"2+2",[26,2584,2585],{},[92,2586,2569],{},[295,2588,2590],{"className":297,"code":2589,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let (first, second) = raw_scores.first().unwrap();\n\n    if raw_scores\n        .iter()\n        .all(|(first, second)| *first == 2 && *second == 2)\n    {\n        return 40;\n    }\n\n    *first + *second\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_two_then_two_on_every_frame() {\n    let scores: Vec\u003C(Roll, Roll)> = (0..10)\n        .map(|_| (2, 2))\n        .collect();\n\n    assert_score(scores, 40);\n}\n",[92,2591,2592,2622,2644,2648,2655,2665,2701,2706,2715,2719,2723,2735,2739,2743,2747,2751,2755,2764,2796,2820,2828,2832,2842],{"__ignoreMap":299},[303,2593,2594,2596,2598,2600,2602,2604,2606,2608,2610,2612,2614,2616,2618,2620],{"class":305,"line":306},[303,2595,558],{"class":309},[303,2597,561],{"class":309},[303,2599,341],{"class":340},[303,2601,566],{"class":323},[303,2603,422],{"class":309},[303,2605,425],{"class":313},[303,2607,428],{"class":323},[303,2609,254],{"class":313},[303,2611,433],{"class":323},[303,2613,254],{"class":313},[303,2615,581],{"class":323},[303,2617,584],{"class":309},[303,2619,320],{"class":313},[303,2621,371],{"class":323},[303,2623,2624,2626,2628,2630,2632,2634,2636,2638,2640,2642],{"class":305,"line":327},[303,2625,629],{"class":309},[303,2627,1522],{"class":323},[303,2629,650],{"class":309},[303,2631,810],{"class":323},[303,2633,50],{"class":309},[303,2635,815],{"class":340},[303,2637,818],{"class":323},[303,2639,50],{"class":309},[303,2641,823],{"class":340},[303,2643,498],{"class":323},[303,2645,2646],{"class":305,"line":334},[303,2647,331],{"emptyLinePlaceholder":330},[303,2649,2650,2652],{"class":305,"line":347},[303,2651,834],{"class":309},[303,2653,2654],{"class":323}," raw_scores\n",[303,2656,2657,2659,2662],{"class":305,"line":352},[303,2658,669],{"class":309},[303,2660,2661],{"class":340},"iter",[303,2663,2664],{"class":323},"()\n",[303,2666,2667,2669,2672,2674,2676,2679,2681,2683,2685,2687,2689,2691,2693,2695,2697,2699],{"class":305,"line":362},[303,2668,669],{"class":309},[303,2670,2671],{"class":340},"all",[303,2673,454],{"class":323},[303,2675,677],{"class":309},[303,2677,2678],{"class":323},"(first, second)",[303,2680,677],{"class":309},[303,2682,837],{"class":309},[303,2684,840],{"class":323},[303,2686,843],{"class":309},[303,2688,1568],{"class":380},[303,2690,1558],{"class":309},[303,2692,837],{"class":309},[303,2694,1563],{"class":323},[303,2696,843],{"class":309},[303,2698,1568],{"class":380},[303,2700,664],{"class":323},[303,2702,2703],{"class":305,"line":374},[303,2704,2705],{"class":323},"    {\n",[303,2707,2708,2710,2713],{"class":305,"line":393},[303,2709,853],{"class":309},[303,2711,2712],{"class":380}," 40",[303,2714,324],{"class":323},[303,2716,2717],{"class":305,"line":398},[303,2718,466],{"class":323},[303,2720,2721],{"class":305,"line":404},[303,2722,331],{"emptyLinePlaceholder":330},[303,2724,2725,2727,2729,2731,2733],{"class":305,"line":410},[303,2726,1438],{"class":309},[303,2728,840],{"class":323},[303,2730,2540],{"class":309},[303,2732,837],{"class":309},[303,2734,2545],{"class":323},[303,2736,2737],{"class":305,"line":448},[303,2738,509],{"class":323},[303,2740,2741],{"class":305,"line":463},[303,2742,331],{"emptyLinePlaceholder":330},[303,2744,2745],{"class":305,"line":469},[303,2746,606],{"class":358},[303,2748,2749],{"class":305,"line":475},[303,2750,331],{"emptyLinePlaceholder":330},[303,2752,2753],{"class":305,"line":481},[303,2754,615],{"class":323},[303,2756,2757,2759,2762],{"class":305,"line":492},[303,2758,337],{"class":309},[303,2760,2761],{"class":340}," calculate_for_two_then_two_on_every_frame",[303,2763,489],{"class":323},[303,2765,2766,2768,2770,2772,2774,2776,2778,2780,2782,2784,2786,2788,2790,2792,2794],{"class":305,"line":501},[303,2767,629],{"class":309},[303,2769,976],{"class":323},[303,2771,422],{"class":309},[303,2773,425],{"class":313},[303,2775,428],{"class":323},[303,2777,254],{"class":313},[303,2779,433],{"class":323},[303,2781,254],{"class":313},[303,2783,647],{"class":323},[303,2785,650],{"class":309},[303,2787,653],{"class":323},[303,2789,534],{"class":380},[303,2791,658],{"class":309},[303,2793,661],{"class":380},[303,2795,664],{"class":323},[303,2797,2798,2800,2802,2804,2806,2808,2810,2812,2814,2816,2818],{"class":305,"line":506},[303,2799,669],{"class":309},[303,2801,672],{"class":340},[303,2803,454],{"class":323},[303,2805,677],{"class":309},[303,2807,680],{"class":323},[303,2809,677],{"class":309},[303,2811,653],{"class":323},[303,2813,1476],{"class":380},[303,2815,433],{"class":323},[303,2817,1476],{"class":380},[303,2819,693],{"class":323},[303,2821,2822,2824,2826],{"class":305,"line":1020},[303,2823,669],{"class":309},[303,2825,700],{"class":340},[303,2827,498],{"class":323},[303,2829,2830],{"class":305,"line":1025},[303,2831,331],{"emptyLinePlaceholder":330},[303,2833,2834,2836,2838,2840],{"class":305,"line":1037},[303,2835,711],{"class":340},[303,2837,1030],{"class":323},[303,2839,2569],{"class":380},[303,2841,719],{"class":323},[303,2843,2844],{"class":305,"line":1300},[303,2845,509],{"class":323},[20,2847,2848,2849,2851],{},"On poursuit avec ",[26,2850,2558],{},", en changeant les valeurs de lancers sur toute la partie. À partir d’ici, nous allons un peu accélérer car je pense que vous avez compris la logique.",[20,2853,2854,529,2857],{},[26,2855,2856],{},"Scénario : dix frames à trois quilles, puis deux quilles, donnent",[26,2858,2859],{},[92,2860,2861],{},"50",[20,2863,2864,2865,2868,2869,2871],{},"On refait la même chose qu’au test précédent mais cette fois, toutes les frames font ",[92,2866,2867],{},"3+2"," on s’attend à ",[92,2870,2861],{}," comme résultat.",[295,2873,2875],{"className":297,"code":2874,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    \u002F\u002F ...\n\n    if raw_scores\n        .iter()\n        .all(|(first, second)| *first == 3 && *second == 2)\n    {\n        return 50;\n    }\n\n    *first + *second\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_three_then_two_on_every_frame() {\n    let scores: Vec\u003C(Roll, Roll)> = (0..10)\n        .map(|_| (3, 2))\n        .collect();\n\n    assert_score(scores, 50);\n}\n",[92,2876,2877,2907,2912,2916,2922,2930,2964,2968,2977,2981,2985,2997,3001,3005,3009,3013,3017,3026,3058,3082,3090,3094,3104],{"__ignoreMap":299},[303,2878,2879,2881,2883,2885,2887,2889,2891,2893,2895,2897,2899,2901,2903,2905],{"class":305,"line":306},[303,2880,558],{"class":309},[303,2882,561],{"class":309},[303,2884,341],{"class":340},[303,2886,566],{"class":323},[303,2888,422],{"class":309},[303,2890,425],{"class":313},[303,2892,428],{"class":323},[303,2894,254],{"class":313},[303,2896,433],{"class":323},[303,2898,254],{"class":313},[303,2900,581],{"class":323},[303,2902,584],{"class":309},[303,2904,320],{"class":313},[303,2906,371],{"class":323},[303,2908,2909],{"class":305,"line":327},[303,2910,2911],{"class":358},"    \u002F\u002F ...\n",[303,2913,2914],{"class":305,"line":334},[303,2915,331],{"emptyLinePlaceholder":330},[303,2917,2918,2920],{"class":305,"line":347},[303,2919,834],{"class":309},[303,2921,2654],{"class":323},[303,2923,2924,2926,2928],{"class":305,"line":352},[303,2925,669],{"class":309},[303,2927,2661],{"class":340},[303,2929,2664],{"class":323},[303,2931,2932,2934,2936,2938,2940,2942,2944,2946,2948,2950,2952,2954,2956,2958,2960,2962],{"class":305,"line":362},[303,2933,669],{"class":309},[303,2935,2671],{"class":340},[303,2937,454],{"class":323},[303,2939,677],{"class":309},[303,2941,2678],{"class":323},[303,2943,677],{"class":309},[303,2945,837],{"class":309},[303,2947,840],{"class":323},[303,2949,843],{"class":309},[303,2951,2192],{"class":380},[303,2953,1558],{"class":309},[303,2955,837],{"class":309},[303,2957,1563],{"class":323},[303,2959,843],{"class":309},[303,2961,1568],{"class":380},[303,2963,664],{"class":323},[303,2965,2966],{"class":305,"line":374},[303,2967,2705],{"class":323},[303,2969,2970,2972,2975],{"class":305,"line":393},[303,2971,853],{"class":309},[303,2973,2974],{"class":380}," 50",[303,2976,324],{"class":323},[303,2978,2979],{"class":305,"line":398},[303,2980,466],{"class":323},[303,2982,2983],{"class":305,"line":404},[303,2984,331],{"emptyLinePlaceholder":330},[303,2986,2987,2989,2991,2993,2995],{"class":305,"line":410},[303,2988,1438],{"class":309},[303,2990,840],{"class":323},[303,2992,2540],{"class":309},[303,2994,837],{"class":309},[303,2996,2545],{"class":323},[303,2998,2999],{"class":305,"line":448},[303,3000,509],{"class":323},[303,3002,3003],{"class":305,"line":463},[303,3004,331],{"emptyLinePlaceholder":330},[303,3006,3007],{"class":305,"line":469},[303,3008,606],{"class":358},[303,3010,3011],{"class":305,"line":475},[303,3012,331],{"emptyLinePlaceholder":330},[303,3014,3015],{"class":305,"line":481},[303,3016,615],{"class":323},[303,3018,3019,3021,3024],{"class":305,"line":492},[303,3020,337],{"class":309},[303,3022,3023],{"class":340}," calculate_for_three_then_two_on_every_frame",[303,3025,489],{"class":323},[303,3027,3028,3030,3032,3034,3036,3038,3040,3042,3044,3046,3048,3050,3052,3054,3056],{"class":305,"line":501},[303,3029,629],{"class":309},[303,3031,976],{"class":323},[303,3033,422],{"class":309},[303,3035,425],{"class":313},[303,3037,428],{"class":323},[303,3039,254],{"class":313},[303,3041,433],{"class":323},[303,3043,254],{"class":313},[303,3045,647],{"class":323},[303,3047,650],{"class":309},[303,3049,653],{"class":323},[303,3051,534],{"class":380},[303,3053,658],{"class":309},[303,3055,661],{"class":380},[303,3057,664],{"class":323},[303,3059,3060,3062,3064,3066,3068,3070,3072,3074,3076,3078,3080],{"class":305,"line":506},[303,3061,669],{"class":309},[303,3063,672],{"class":340},[303,3065,454],{"class":323},[303,3067,677],{"class":309},[303,3069,680],{"class":323},[303,3071,677],{"class":309},[303,3073,653],{"class":323},[303,3075,2099],{"class":380},[303,3077,433],{"class":323},[303,3079,1476],{"class":380},[303,3081,693],{"class":323},[303,3083,3084,3086,3088],{"class":305,"line":1020},[303,3085,669],{"class":309},[303,3087,700],{"class":340},[303,3089,498],{"class":323},[303,3091,3092],{"class":305,"line":1025},[303,3093,331],{"emptyLinePlaceholder":330},[303,3095,3096,3098,3100,3102],{"class":305,"line":1037},[303,3097,711],{"class":340},[303,3099,1030],{"class":323},[303,3101,2861],{"class":380},[303,3103,719],{"class":323},[303,3105,3106],{"class":305,"line":1300},[303,3107,509],{"class":323},[20,3109,3110,3111,3113],{},"Maintenant, j’ai bien envie de refactorer pour que notre algo additionne tous les ",[92,3112,254],{},"s, pas vous ?",[20,3115,3116],{},[3117,3118,3119],"em",{},"By the book, il nous faudrait idéalement faire un 3e test qui nous permette de valider que notre supposition (celle d’additionner tous les lancers) soit la bonne. Toujours dans notre idée d’accélérer un peu, on va se permettre de sauter quelques étapes pour passer de suite au refactor la supposition étant suffisamment forte selon moi.",[295,3121,3123],{"className":297,"code":3122,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let mut result: i32 = 0;\n\n    for (first, second) in raw_scores.iter() {\n        result += *first + *second;\n    }\n\n    result\n}\n",[92,3124,3125,3155,3176,3180,3198,3217,3221,3225,3230],{"__ignoreMap":299},[303,3126,3127,3129,3131,3133,3135,3137,3139,3141,3143,3145,3147,3149,3151,3153],{"class":305,"line":306},[303,3128,558],{"class":309},[303,3130,561],{"class":309},[303,3132,341],{"class":340},[303,3134,566],{"class":323},[303,3136,422],{"class":309},[303,3138,425],{"class":313},[303,3140,428],{"class":323},[303,3142,254],{"class":313},[303,3144,433],{"class":323},[303,3146,254],{"class":313},[303,3148,581],{"class":323},[303,3150,584],{"class":309},[303,3152,320],{"class":313},[303,3154,371],{"class":323},[303,3156,3157,3159,3162,3165,3167,3169,3171,3174],{"class":305,"line":327},[303,3158,629],{"class":309},[303,3160,3161],{"class":309}," mut",[303,3163,3164],{"class":323}," result",[303,3166,422],{"class":309},[303,3168,320],{"class":313},[303,3170,317],{"class":309},[303,3172,3173],{"class":380}," 0",[303,3175,324],{"class":323},[303,3177,3178],{"class":305,"line":334},[303,3179,331],{"emptyLinePlaceholder":330},[303,3181,3182,3185,3187,3190,3192,3194,3196],{"class":305,"line":347},[303,3183,3184],{"class":309},"    for",[303,3186,1522],{"class":323},[303,3188,3189],{"class":309},"in",[303,3191,810],{"class":323},[303,3193,50],{"class":309},[303,3195,2661],{"class":340},[303,3197,489],{"class":323},[303,3199,3200,3203,3206,3208,3210,3212,3214],{"class":305,"line":352},[303,3201,3202],{"class":323},"        result ",[303,3204,3205],{"class":309},"+=",[303,3207,837],{"class":309},[303,3209,840],{"class":323},[303,3211,2540],{"class":309},[303,3213,837],{"class":309},[303,3215,3216],{"class":323},"second;\n",[303,3218,3219],{"class":305,"line":362},[303,3220,466],{"class":323},[303,3222,3223],{"class":305,"line":374},[303,3224,331],{"emptyLinePlaceholder":330},[303,3226,3227],{"class":305,"line":393},[303,3228,3229],{"class":323},"    result\n",[303,3231,3232],{"class":305,"line":398},[303,3233,509],{"class":323},[20,3235,3236,3237,3240],{},"Voici donc notre refactor, on additionne toutes les frames. ",[3117,3238,3239],{},"« Beurk, une for loop »"," et en rust qui plus est… je vous entends et vous avez raison, c’est pas le truc le plus sexy qui existe. On pourrait partir sur quelque chose de plus déclaratif dès maintenant ; j’ai toutefois tendance à préférer le procédural au début sans trop savoir encore dans quelle direction nous allons partir. Vous verrez qu’on terminera sur du code qui sera plus sympa à lire.",[52,3242,3244],{"id":3243},"b-explorer-les-limites","B - Explorer les limites",[164,3246,3248],{"id":3247},"le-spare","Le spare",[20,3250,730,3251,3254,3255,50],{},[26,3252,3253],{},"B pour Boundary"," nous invite à explorer une limite où les règles du calcul changent : lorsque les deux lancers d’une frame totalisent dix quilles, on obtient un ",[26,3256,3257],{},"spare",[20,3259,3260,529,3263],{},[26,3261,3262],{},"Scénario : un spare à cinq puis cinq, suivi de cinq puis zéro, donne",[26,3264,3265],{},[92,3266,3267],{},"20",[20,3269,3270,3271,3274,3275,3277,3278,3281,3282,3284,3285,529,3289,50],{},"Notre joueur renverse cinq quilles à chacun des deux premiers lancers, puis cinq quilles au lancer suivant. Le nouveau test est rouge : notre fonction additionne les quilles et retourne ",[92,3272,3273],{},"15",". Avec un ",[26,3276,3257],{},", la première frame vaut dix points, auxquels on ajoute le prochain lancer : ",[92,3279,3280],{},"10 + 5",". La deuxième frame vaut ",[92,3283,1058],{},", soit ",[26,3286,3287],{},[92,3288,3267],{},[26,3290,3291],{},"au total",[295,3293,3295],{"className":297,"code":3294,"language":146,"meta":299,"style":299},"pub fn calculate_bowling_score(raw_scores: Vec\u003C(Roll, Roll)>) -> i32 {\n    let mut result: i32 = 0;\n\n    for index in 0..raw_scores.len() {\n        let (first, second) = raw_scores[index];\n\n        if is_spare(first, second) {\n            let next = raw_scores[index + 1];\n            result += 10 + next.0;\n            continue;\n        }\n\n        result += first + second;\n    }\n\n    result\n}\n\nfn is_spare(first: Roll, second: Roll) -> bool {\n    first + second == 10\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_a_spare_followed_by_five_pins() {\n    \u002F\u002F ...\n\n    let scores: Vec\u003C(Roll, Roll)> =\n        [vec![(5, 5), (5, 0)], lose].concat();\n\n    assert_score(scores, 20);\n}\n",[92,3296,3297,3327,3345,3349,3372,3384,3388,3399,3419,3441,3448,3453,3457,3471,3475,3479,3483,3487,3491,3521,3536,3540,3544,3548,3552,3556,3565,3569,3573,3596,3628,3633,3644],{"__ignoreMap":299},[303,3298,3299,3301,3303,3305,3307,3309,3311,3313,3315,3317,3319,3321,3323,3325],{"class":305,"line":306},[303,3300,558],{"class":309},[303,3302,561],{"class":309},[303,3304,341],{"class":340},[303,3306,566],{"class":323},[303,3308,422],{"class":309},[303,3310,425],{"class":313},[303,3312,428],{"class":323},[303,3314,254],{"class":313},[303,3316,433],{"class":323},[303,3318,254],{"class":313},[303,3320,581],{"class":323},[303,3322,584],{"class":309},[303,3324,320],{"class":313},[303,3326,371],{"class":323},[303,3328,3329,3331,3333,3335,3337,3339,3341,3343],{"class":305,"line":327},[303,3330,629],{"class":309},[303,3332,3161],{"class":309},[303,3334,3164],{"class":323},[303,3336,422],{"class":309},[303,3338,320],{"class":313},[303,3340,317],{"class":309},[303,3342,3173],{"class":380},[303,3344,324],{"class":323},[303,3346,3347],{"class":305,"line":334},[303,3348,331],{"emptyLinePlaceholder":330},[303,3350,3351,3353,3356,3358,3360,3362,3365,3367,3370],{"class":305,"line":347},[303,3352,3184],{"class":309},[303,3354,3355],{"class":323}," index ",[303,3357,3189],{"class":309},[303,3359,3173],{"class":380},[303,3361,658],{"class":309},[303,3363,3364],{"class":323},"raw_scores",[303,3366,50],{"class":309},[303,3368,3369],{"class":340},"len",[303,3371,489],{"class":323},[303,3373,3374,3377,3379,3381],{"class":305,"line":352},[303,3375,3376],{"class":309},"        let",[303,3378,1522],{"class":323},[303,3380,650],{"class":309},[303,3382,3383],{"class":323}," raw_scores[index];\n",[303,3385,3386],{"class":305,"line":362},[303,3387,331],{"emptyLinePlaceholder":330},[303,3389,3390,3393,3396],{"class":305,"line":374},[303,3391,3392],{"class":309},"        if",[303,3394,3395],{"class":340}," is_spare",[303,3397,3398],{"class":323},"(first, second) {\n",[303,3400,3401,3404,3407,3409,3412,3414,3416],{"class":305,"line":393},[303,3402,3403],{"class":309},"            let",[303,3405,3406],{"class":323}," next ",[303,3408,650],{"class":309},[303,3410,3411],{"class":323}," raw_scores[index ",[303,3413,2540],{"class":309},[303,3415,846],{"class":380},[303,3417,3418],{"class":323},"];\n",[303,3420,3421,3424,3426,3429,3432,3435,3437,3439],{"class":305,"line":398},[303,3422,3423],{"class":323},"            result ",[303,3425,3205],{"class":309},[303,3427,3428],{"class":380}," 10",[303,3430,3431],{"class":309}," +",[303,3433,3434],{"class":323}," next",[303,3436,50],{"class":309},[303,3438,534],{"class":380},[303,3440,324],{"class":323},[303,3442,3443,3446],{"class":305,"line":404},[303,3444,3445],{"class":309},"            continue",[303,3447,324],{"class":323},[303,3449,3450],{"class":305,"line":410},[303,3451,3452],{"class":323},"        }\n",[303,3454,3455],{"class":305,"line":448},[303,3456,331],{"emptyLinePlaceholder":330},[303,3458,3459,3461,3463,3466,3468],{"class":305,"line":463},[303,3460,3202],{"class":323},[303,3462,3205],{"class":309},[303,3464,3465],{"class":323}," first ",[303,3467,2540],{"class":309},[303,3469,3470],{"class":323}," second;\n",[303,3472,3473],{"class":305,"line":469},[303,3474,466],{"class":323},[303,3476,3477],{"class":305,"line":475},[303,3478,331],{"emptyLinePlaceholder":330},[303,3480,3481],{"class":305,"line":481},[303,3482,3229],{"class":323},[303,3484,3485],{"class":305,"line":492},[303,3486,509],{"class":323},[303,3488,3489],{"class":305,"line":501},[303,3490,331],{"emptyLinePlaceholder":330},[303,3492,3493,3495,3497,3500,3502,3504,3507,3509,3511,3514,3516,3519],{"class":305,"line":506},[303,3494,337],{"class":309},[303,3496,3395],{"class":340},[303,3498,3499],{"class":323},"(first",[303,3501,422],{"class":309},[303,3503,314],{"class":313},[303,3505,3506],{"class":323},", second",[303,3508,422],{"class":309},[303,3510,314],{"class":313},[303,3512,3513],{"class":323},") ",[303,3515,584],{"class":309},[303,3517,3518],{"class":313}," bool",[303,3520,371],{"class":323},[303,3522,3523,3526,3528,3531,3533],{"class":305,"line":1020},[303,3524,3525],{"class":323},"    first ",[303,3527,2540],{"class":309},[303,3529,3530],{"class":323}," second ",[303,3532,843],{"class":309},[303,3534,3535],{"class":380}," 10\n",[303,3537,3538],{"class":305,"line":1025},[303,3539,509],{"class":323},[303,3541,3542],{"class":305,"line":1037},[303,3543,331],{"emptyLinePlaceholder":330},[303,3545,3546],{"class":305,"line":1300},[303,3547,606],{"class":358},[303,3549,3550],{"class":305,"line":1343},[303,3551,331],{"emptyLinePlaceholder":330},[303,3553,3554],{"class":305,"line":1348},[303,3555,615],{"class":323},[303,3557,3558,3560,3563],{"class":305,"line":1359},[303,3559,337],{"class":309},[303,3561,3562],{"class":340}," calculate_for_a_spare_followed_by_five_pins",[303,3564,489],{"class":323},[303,3566,3567],{"class":305,"line":2406},[303,3568,2911],{"class":358},[303,3570,3571],{"class":305,"line":2449},[303,3572,331],{"emptyLinePlaceholder":330},[303,3574,3575,3577,3579,3581,3583,3585,3587,3589,3591,3593],{"class":305,"line":2454},[303,3576,629],{"class":309},[303,3578,976],{"class":323},[303,3580,422],{"class":309},[303,3582,425],{"class":313},[303,3584,428],{"class":323},[303,3586,254],{"class":313},[303,3588,433],{"class":323},[303,3590,254],{"class":313},[303,3592,647],{"class":323},[303,3594,3595],{"class":309},"=\n",[303,3597,3598,3601,3603,3605,3607,3609,3611,3614,3616,3618,3620,3622,3624,3626],{"class":305,"line":2465},[303,3599,3600],{"class":323},"        [",[303,3602,998],{"class":340},[303,3604,1001],{"class":323},[303,3606,1058],{"class":380},[303,3608,433],{"class":323},[303,3610,1058],{"class":380},[303,3612,3613],{"class":323},"), (",[303,3615,1058],{"class":380},[303,3617,433],{"class":323},[303,3619,534],{"class":380},[303,3621,1010],{"class":323},[303,3623,50],{"class":309},[303,3625,1015],{"class":340},[303,3627,498],{"class":323},[303,3629,3631],{"class":305,"line":3630},31,[303,3632,331],{"emptyLinePlaceholder":330},[303,3634,3636,3638,3640,3642],{"class":305,"line":3635},32,[303,3637,711],{"class":340},[303,3639,1030],{"class":323},[303,3641,3267],{"class":380},[303,3643,719],{"class":323},[303,3645,3647],{"class":305,"line":3646},33,[303,3648,509],{"class":323},[20,3650,3651],{},"Ici, je fais un pas plus large : j’introduis directement la détection du spare et la lecture du lancer suivant. Avec de la pratique, on peut sauter quelques étapes. Si la modification devient difficile, on peut revenir au dernier état vert et reprendre avec des pas plus petits.",[20,3653,3654,3655,50],{},"Le spare étant pris en compte, on profite de la phase de refactoring pour faire évoluer notre modèle, ce qui va naturellement nous faire toucher la lettre ",[26,3656,3657],{},"I de ZOMBIES : Interface",[20,3659,3660,529,3663],{},[26,3661,3662],{},"Refactoring : regrouper le calcul dans",[26,3664,3665],{},[92,3666,3667],{},"BowlingGame",[20,3669,3670,3671,3673],{},"On introduit une structure ",[92,3672,3667],{}," et on y déplace le calcul du score ainsi que la détection du spare. À ce stade, ce type ne contient aucune donnée : les frames sont toujours passées à la méthode de calcul.",[295,3675,3677],{"className":297,"code":3676,"language":146,"meta":299,"style":299},"\u002F\u002F pour ceux qui sont habitues a l'oop, imagez la chose ainsi:\n\u002F\u002F je cree une class `BowlingGame`, elle n'a pour l'instant aucun attribut\npub struct BowlingGame;\n\n\u002F\u002F je lui attache des methodes\nimpl BowlingGame {\n    pub fn calculate_score(&self, scores: Vec\u003C(Roll, Roll)>) -> i32 {\n        let mut result: i32 = 0;\n\n        for index in 0..scores.len() {\n            let (first, second) = scores[index];\n\n            if self.is_spare(first, second) {\n                \u002F\u002F ...\n            }\n\n            result += first + second;\n        }\n\n        result\n    }\n\n    fn is_spare(first: Roll, second: Roll) -> bool {\n        first + second == 10\n    }\n}\n\n\u002F\u002F ...\n\nfn assert_score(frames: Vec\u003C(Roll, Roll)>, expected: i32) {\n    let bowling_game = BowlingGame; \u002F\u002F \"j'instancie\" `BowlingGame`\n\n    assert_eq!(bowling_game.calculate_score(frames), expected);\n}\n",[92,3678,3679,3684,3689,3701,3705,3710,3719,3760,3778,3782,3804,3815,3819,3834,3839,3844,3848,3860,3864,3868,3873,3877,3881,3907,3920,3924,3928,3932,3936,3940,3968,3984,3988,4002],{"__ignoreMap":299},[303,3680,3681],{"class":305,"line":306},[303,3682,3683],{"class":358},"\u002F\u002F pour ceux qui sont habitues a l'oop, imagez la chose ainsi:\n",[303,3685,3686],{"class":305,"line":327},[303,3687,3688],{"class":358},"\u002F\u002F je cree une class `BowlingGame`, elle n'a pour l'instant aucun attribut\n",[303,3690,3691,3693,3696,3699],{"class":305,"line":334},[303,3692,558],{"class":309},[303,3694,3695],{"class":309}," struct",[303,3697,3698],{"class":313}," BowlingGame",[303,3700,324],{"class":323},[303,3702,3703],{"class":305,"line":347},[303,3704,331],{"emptyLinePlaceholder":330},[303,3706,3707],{"class":305,"line":352},[303,3708,3709],{"class":358},"\u002F\u002F je lui attache des methodes\n",[303,3711,3712,3715,3717],{"class":305,"line":362},[303,3713,3714],{"class":309},"impl",[303,3716,3698],{"class":313},[303,3718,371],{"class":323},[303,3720,3721,3724,3726,3729,3731,3734,3737,3740,3742,3744,3746,3748,3750,3752,3754,3756,3758],{"class":305,"line":374},[303,3722,3723],{"class":309},"    pub",[303,3725,561],{"class":309},[303,3727,3728],{"class":340}," calculate_score",[303,3730,454],{"class":323},[303,3732,3733],{"class":309},"&",[303,3735,3736],{"class":380},"self",[303,3738,3739],{"class":323},", scores",[303,3741,422],{"class":309},[303,3743,425],{"class":313},[303,3745,428],{"class":323},[303,3747,254],{"class":313},[303,3749,433],{"class":323},[303,3751,254],{"class":313},[303,3753,581],{"class":323},[303,3755,584],{"class":309},[303,3757,320],{"class":313},[303,3759,371],{"class":323},[303,3761,3762,3764,3766,3768,3770,3772,3774,3776],{"class":305,"line":393},[303,3763,3376],{"class":309},[303,3765,3161],{"class":309},[303,3767,3164],{"class":323},[303,3769,422],{"class":309},[303,3771,320],{"class":313},[303,3773,317],{"class":309},[303,3775,3173],{"class":380},[303,3777,324],{"class":323},[303,3779,3780],{"class":305,"line":398},[303,3781,331],{"emptyLinePlaceholder":330},[303,3783,3784,3787,3789,3791,3793,3795,3798,3800,3802],{"class":305,"line":404},[303,3785,3786],{"class":309},"        for",[303,3788,3355],{"class":323},[303,3790,3189],{"class":309},[303,3792,3173],{"class":380},[303,3794,658],{"class":309},[303,3796,3797],{"class":323},"scores",[303,3799,50],{"class":309},[303,3801,3369],{"class":340},[303,3803,489],{"class":323},[303,3805,3806,3808,3810,3812],{"class":305,"line":410},[303,3807,3403],{"class":309},[303,3809,1522],{"class":323},[303,3811,650],{"class":309},[303,3813,3814],{"class":323}," scores[index];\n",[303,3816,3817],{"class":305,"line":448},[303,3818,331],{"emptyLinePlaceholder":330},[303,3820,3821,3824,3827,3829,3832],{"class":305,"line":463},[303,3822,3823],{"class":309},"            if",[303,3825,3826],{"class":380}," self",[303,3828,50],{"class":309},[303,3830,3831],{"class":340},"is_spare",[303,3833,3398],{"class":323},[303,3835,3836],{"class":305,"line":469},[303,3837,3838],{"class":358},"                \u002F\u002F ...\n",[303,3840,3841],{"class":305,"line":475},[303,3842,3843],{"class":323},"            }\n",[303,3845,3846],{"class":305,"line":481},[303,3847,331],{"emptyLinePlaceholder":330},[303,3849,3850,3852,3854,3856,3858],{"class":305,"line":492},[303,3851,3423],{"class":323},[303,3853,3205],{"class":309},[303,3855,3465],{"class":323},[303,3857,2540],{"class":309},[303,3859,3470],{"class":323},[303,3861,3862],{"class":305,"line":501},[303,3863,3452],{"class":323},[303,3865,3866],{"class":305,"line":506},[303,3867,331],{"emptyLinePlaceholder":330},[303,3869,3870],{"class":305,"line":1020},[303,3871,3872],{"class":323},"        result\n",[303,3874,3875],{"class":305,"line":1025},[303,3876,466],{"class":323},[303,3878,3879],{"class":305,"line":1037},[303,3880,331],{"emptyLinePlaceholder":330},[303,3882,3883,3885,3887,3889,3891,3893,3895,3897,3899,3901,3903,3905],{"class":305,"line":1300},[303,3884,413],{"class":309},[303,3886,3395],{"class":340},[303,3888,3499],{"class":323},[303,3890,422],{"class":309},[303,3892,314],{"class":313},[303,3894,3506],{"class":323},[303,3896,422],{"class":309},[303,3898,314],{"class":313},[303,3900,3513],{"class":323},[303,3902,584],{"class":309},[303,3904,3518],{"class":313},[303,3906,371],{"class":323},[303,3908,3909,3912,3914,3916,3918],{"class":305,"line":1343},[303,3910,3911],{"class":323},"        first ",[303,3913,2540],{"class":309},[303,3915,3530],{"class":323},[303,3917,843],{"class":309},[303,3919,3535],{"class":380},[303,3921,3922],{"class":305,"line":1348},[303,3923,466],{"class":323},[303,3925,3926],{"class":305,"line":1359},[303,3927,509],{"class":323},[303,3929,3930],{"class":305,"line":2406},[303,3931,331],{"emptyLinePlaceholder":330},[303,3933,3934],{"class":305,"line":2449},[303,3935,606],{"class":358},[303,3937,3938],{"class":305,"line":2454},[303,3939,331],{"emptyLinePlaceholder":330},[303,3941,3942,3944,3946,3948,3950,3952,3954,3956,3958,3960,3962,3964,3966],{"class":305,"line":2465},[303,3943,337],{"class":309},[303,3945,416],{"class":340},[303,3947,419],{"class":323},[303,3949,422],{"class":309},[303,3951,425],{"class":313},[303,3953,428],{"class":323},[303,3955,254],{"class":313},[303,3957,433],{"class":323},[303,3959,254],{"class":313},[303,3961,438],{"class":323},[303,3963,422],{"class":309},[303,3965,320],{"class":313},[303,3967,445],{"class":323},[303,3969,3970,3972,3975,3977,3979,3981],{"class":305,"line":3630},[303,3971,629],{"class":309},[303,3973,3974],{"class":323}," bowling_game ",[303,3976,650],{"class":309},[303,3978,3698],{"class":313},[303,3980,387],{"class":323},[303,3982,3983],{"class":358},"\u002F\u002F \"j'instancie\" `BowlingGame`\n",[303,3985,3986],{"class":305,"line":3635},[303,3987,331],{"emptyLinePlaceholder":330},[303,3989,3990,3992,3995,3997,4000],{"class":305,"line":3646},[303,3991,451],{"class":340},[303,3993,3994],{"class":323},"(bowling_game",[303,3996,50],{"class":309},[303,3998,3999],{"class":340},"calculate_score",[303,4001,460],{"class":323},[303,4003,4005],{"class":305,"line":4004},34,[303,4006,509],{"class":323},[20,4008,4009,4010,4013],{},"On adapte notre fonction utilitaire ",[92,4011,4012],{},"assert_score"," pour appeler cette nouvelle interface. Les tests existants continuent ainsi à exprimer les mêmes scénarios. Cette baby step modifie l’organisation du code, sans ajouter de nouvelle règle de calcul.",[20,4015,4016,4017,50],{},"Le spare nous a montré que toutes les frames ne se calculent pas de la même manière. ",[26,4018,4019],{},"On continue de profiter de la phase de refactoring",[20,4021,4022,4023,4026],{},"On introduit donc ",[92,4024,4025],{},"Frame",", une énumération qui distingue ces deux situations et conserve les deux lancers.",[295,4028,4030],{"className":297,"code":4029,"language":146,"meta":299,"style":299},"enum Frame {\n    Score(Roll, Roll),\n    Spare(Roll, Roll),\n}\n",[92,4031,4032,4042,4058,4073],{"__ignoreMap":299},[303,4033,4034,4037,4040],{"class":305,"line":306},[303,4035,4036],{"class":309},"enum",[303,4038,4039],{"class":313}," Frame",[303,4041,371],{"class":323},[303,4043,4044,4047,4049,4051,4053,4055],{"class":305,"line":327},[303,4045,4046],{"class":340},"    Score",[303,4048,454],{"class":323},[303,4050,254],{"class":313},[303,4052,433],{"class":323},[303,4054,254],{"class":313},[303,4056,4057],{"class":323},"),\n",[303,4059,4060,4063,4065,4067,4069,4071],{"class":305,"line":334},[303,4061,4062],{"class":340},"    Spare",[303,4064,454],{"class":323},[303,4066,254],{"class":313},[303,4068,433],{"class":323},[303,4070,254],{"class":313},[303,4072,4057],{"class":323},[303,4074,4075],{"class":305,"line":347},[303,4076,509],{"class":323},[20,4078,4079,4080,4082,4083,4086,4087,4090,4091,4094,4095,4098,4099,4102],{},"Pour transformer une paire de lancers en ",[92,4081,4025],{},", on utilise ",[92,4084,4085],{},"TryFrom",", un trait fourni par Rust. Un trait définit un contrat ; ici, celui d’une conversion. ",[92,4088,4089],{},"Ok"," contient la valeur construite, tandis que ",[92,4092,4093],{},"Err"," permet de signaler une erreur. Retenez qu’un ",[92,4096,4097],{},"trait"," est l’équivalent d’une ",[92,4100,4101],{},"interface"," boostée aux hormones.",[295,4104,4106],{"className":297,"code":4105,"language":146,"meta":299,"style":299},"impl TryFrom\u003C(Roll, Roll)> for Frame {\n    type Error = String;\n\n    fn try_from(value: (Roll, Roll)) -> Result\u003CSelf, Self::Error> {\n        let (first, second) = value;\n\n        if first + second == 10 {\n            return Ok(Frame::Spare(first, second));\n        }\n\n        Ok(Frame::Score(first, second))\n    }\n}\n",[92,4107,4108,4132,4147,4151,4198,4209,4213,4229,4248,4252,4256,4273,4277],{"__ignoreMap":299},[303,4109,4110,4112,4115,4117,4119,4121,4123,4125,4128,4130],{"class":305,"line":306},[303,4111,3714],{"class":309},[303,4113,4114],{"class":313}," TryFrom",[303,4116,428],{"class":323},[303,4118,254],{"class":313},[303,4120,433],{"class":323},[303,4122,254],{"class":313},[303,4124,647],{"class":323},[303,4126,4127],{"class":309},"for",[303,4129,4039],{"class":313},[303,4131,371],{"class":323},[303,4133,4134,4137,4140,4142,4145],{"class":305,"line":327},[303,4135,4136],{"class":309},"    type",[303,4138,4139],{"class":313}," Error",[303,4141,317],{"class":309},[303,4143,4144],{"class":313}," String",[303,4146,324],{"class":323},[303,4148,4149],{"class":305,"line":334},[303,4150,331],{"emptyLinePlaceholder":330},[303,4152,4153,4155,4158,4161,4163,4165,4167,4169,4171,4174,4176,4179,4182,4185,4187,4189,4192,4195],{"class":305,"line":347},[303,4154,413],{"class":309},[303,4156,4157],{"class":340}," try_from",[303,4159,4160],{"class":323},"(value",[303,4162,422],{"class":309},[303,4164,653],{"class":323},[303,4166,254],{"class":313},[303,4168,433],{"class":323},[303,4170,254],{"class":313},[303,4172,4173],{"class":323},")) ",[303,4175,584],{"class":309},[303,4177,4178],{"class":313}," Result",[303,4180,4181],{"class":323},"\u003C",[303,4183,4184],{"class":380},"Self",[303,4186,433],{"class":323},[303,4188,4184],{"class":380},[303,4190,4191],{"class":309},"::",[303,4193,4194],{"class":313},"Error",[303,4196,4197],{"class":323},"> {\n",[303,4199,4200,4202,4204,4206],{"class":305,"line":352},[303,4201,3376],{"class":309},[303,4203,1522],{"class":323},[303,4205,650],{"class":309},[303,4207,4208],{"class":323}," value;\n",[303,4210,4211],{"class":305,"line":362},[303,4212,331],{"emptyLinePlaceholder":330},[303,4214,4215,4217,4219,4221,4223,4225,4227],{"class":305,"line":374},[303,4216,3392],{"class":309},[303,4218,3465],{"class":323},[303,4220,2540],{"class":309},[303,4222,3530],{"class":323},[303,4224,843],{"class":309},[303,4226,3428],{"class":380},[303,4228,371],{"class":323},[303,4230,4231,4234,4237,4239,4241,4243,4245],{"class":305,"line":393},[303,4232,4233],{"class":309},"            return",[303,4235,4236],{"class":313}," Ok",[303,4238,454],{"class":323},[303,4240,4025],{"class":313},[303,4242,4191],{"class":309},[303,4244,197],{"class":340},[303,4246,4247],{"class":323},"(first, second));\n",[303,4249,4250],{"class":305,"line":398},[303,4251,3452],{"class":323},[303,4253,4254],{"class":305,"line":404},[303,4255,331],{"emptyLinePlaceholder":330},[303,4257,4258,4261,4263,4265,4267,4270],{"class":305,"line":410},[303,4259,4260],{"class":313},"        Ok",[303,4262,454],{"class":323},[303,4264,4025],{"class":313},[303,4266,4191],{"class":309},[303,4268,4269],{"class":340},"Score",[303,4271,4272],{"class":323},"(first, second))\n",[303,4274,4275],{"class":305,"line":448},[303,4276,466],{"class":323},[303,4278,4279],{"class":305,"line":463},[303,4280,509],{"class":323},[20,4282,4283,4284,4286,4287,653,4290,4293,4294,4297,4298,50],{},"On regroupe ensuite les frames dans ",[92,4285,3667],{},", une ",[26,4288,4289],{},"structure",[92,4291,4292],{},"struct",") représentant la partie. Le bloc ",[92,4295,4296],{},"impl BowlingGame"," lui associe des opérations, comme ",[92,4299,3999],{},[295,4301,4303],{"className":297,"code":4302,"language":146,"meta":299,"style":299},"pub struct BowlingGame {\n    scores: Vec\u003CFrame>,\n}\n",[92,4304,4305,4315,4331],{"__ignoreMap":299},[303,4306,4307,4309,4311,4313],{"class":305,"line":306},[303,4308,558],{"class":309},[303,4310,3695],{"class":309},[303,4312,3698],{"class":313},[303,4314,371],{"class":323},[303,4316,4317,4320,4322,4324,4326,4328],{"class":305,"line":327},[303,4318,4319],{"class":323},"    scores",[303,4321,422],{"class":309},[303,4323,425],{"class":313},[303,4325,4181],{"class":323},[303,4327,4025],{"class":313},[303,4329,4330],{"class":323},">,\n",[303,4332,4333],{"class":305,"line":334},[303,4334,509],{"class":323},[20,4336,4337,4338,4340,4341,4343],{},"On utilise également ",[92,4339,4085],{}," pour construire cette partie depuis notre liste de paires : chaque paire devient une ",[92,4342,4025],{},", et une liste vide ou trop longue retourne une erreur.",[20,4345,4346],{},"Enfin, on adapte notre utilitaire de test à cette nouvelle interface. Les scénarios existants restent identiques.",[295,4348,4350],{"className":297,"code":4349,"language":146,"meta":299,"style":299},"fn assert_score(frames: Vec\u003C(Roll, Roll)>, expected: i32) {\n    let bowling_game = BowlingGame::try_from(frames).unwrap();\n\n    assert_eq!(bowling_game.calculate_score(), expected);\n}\n",[92,4351,4352,4380,4404,4408,4421],{"__ignoreMap":299},[303,4353,4354,4356,4358,4360,4362,4364,4366,4368,4370,4372,4374,4376,4378],{"class":305,"line":306},[303,4355,337],{"class":309},[303,4357,416],{"class":340},[303,4359,419],{"class":323},[303,4361,422],{"class":309},[303,4363,425],{"class":313},[303,4365,428],{"class":323},[303,4367,254],{"class":313},[303,4369,433],{"class":323},[303,4371,254],{"class":313},[303,4373,438],{"class":323},[303,4375,422],{"class":309},[303,4377,320],{"class":313},[303,4379,445],{"class":323},[303,4381,4382,4384,4386,4388,4390,4392,4395,4398,4400,4402],{"class":305,"line":327},[303,4383,629],{"class":309},[303,4385,3974],{"class":323},[303,4387,650],{"class":309},[303,4389,3698],{"class":313},[303,4391,4191],{"class":309},[303,4393,4394],{"class":340},"try_from",[303,4396,4397],{"class":323},"(frames)",[303,4399,50],{"class":309},[303,4401,823],{"class":340},[303,4403,498],{"class":323},[303,4405,4406],{"class":305,"line":334},[303,4407,331],{"emptyLinePlaceholder":330},[303,4409,4410,4412,4414,4416,4418],{"class":305,"line":347},[303,4411,451],{"class":340},[303,4413,3994],{"class":323},[303,4415,50],{"class":309},[303,4417,3999],{"class":340},[303,4419,4420],{"class":323},"(), expected);\n",[303,4422,4423],{"class":305,"line":352},[303,4424,509],{"class":323},[20,4426,4427],{},"Une fois les modifications sur notre fonction de calcul des scores appliquées, nous nous retrouvons avec l’algo suivant :",[295,4429,4431],{"className":297,"code":4430,"language":146,"meta":299,"style":299},"impl BowlingGame {\n    pub fn calculate_score(&self) -> i32 {\n        let scores = &self.scores;\n        let mut result: i32 = 0;\n\n        for index in 0..scores.len() {\n            let frame = &scores[index];\n\n            if matches!(frame, Frame::Spare(_, _)) { \u002F\u002F si c'est un spare\n                let next_roll = match &scores[index + 1] { \u002F\u002F on prend le lancer suivant\n                    Frame::Score(first, _) | Frame::Spare(first, _) => *first,\n                };\n\n                result += 10 + next_roll; \u002F\u002F et on l'additionne\n                continue;\n            }\n\n            if let Frame::Score(first, second) = frame { \u002F\u002F si c'est une frame normale\n                result += first + second; \u002F\u002F ca ne change pas, on additionne\n            }\n        }\n\n        result\n    }\n}\n",[92,4432,4433,4441,4463,4482,4500,4504,4524,4538,4542,4564,4592,4622,4627,4631,4648,4655,4659,4663,4687,4703,4707,4711,4715,4719,4723],{"__ignoreMap":299},[303,4434,4435,4437,4439],{"class":305,"line":306},[303,4436,3714],{"class":309},[303,4438,3698],{"class":313},[303,4440,371],{"class":323},[303,4442,4443,4445,4447,4449,4451,4453,4455,4457,4459,4461],{"class":305,"line":327},[303,4444,3723],{"class":309},[303,4446,561],{"class":309},[303,4448,3728],{"class":340},[303,4450,454],{"class":323},[303,4452,3733],{"class":309},[303,4454,3736],{"class":380},[303,4456,3513],{"class":323},[303,4458,584],{"class":309},[303,4460,320],{"class":313},[303,4462,371],{"class":323},[303,4464,4465,4467,4470,4472,4475,4477,4479],{"class":305,"line":334},[303,4466,3376],{"class":309},[303,4468,4469],{"class":323}," scores ",[303,4471,650],{"class":309},[303,4473,4474],{"class":309}," &",[303,4476,3736],{"class":380},[303,4478,50],{"class":309},[303,4480,4481],{"class":323},"scores;\n",[303,4483,4484,4486,4488,4490,4492,4494,4496,4498],{"class":305,"line":347},[303,4485,3376],{"class":309},[303,4487,3161],{"class":309},[303,4489,3164],{"class":323},[303,4491,422],{"class":309},[303,4493,320],{"class":313},[303,4495,317],{"class":309},[303,4497,3173],{"class":380},[303,4499,324],{"class":323},[303,4501,4502],{"class":305,"line":352},[303,4503,331],{"emptyLinePlaceholder":330},[303,4505,4506,4508,4510,4512,4514,4516,4518,4520,4522],{"class":305,"line":362},[303,4507,3786],{"class":309},[303,4509,3355],{"class":323},[303,4511,3189],{"class":309},[303,4513,3173],{"class":380},[303,4515,658],{"class":309},[303,4517,3797],{"class":323},[303,4519,50],{"class":309},[303,4521,3369],{"class":340},[303,4523,489],{"class":323},[303,4525,4526,4528,4531,4533,4535],{"class":305,"line":374},[303,4527,3403],{"class":309},[303,4529,4530],{"class":323}," frame ",[303,4532,650],{"class":309},[303,4534,4474],{"class":309},[303,4536,4537],{"class":323},"scores[index];\n",[303,4539,4540],{"class":305,"line":393},[303,4541,331],{"emptyLinePlaceholder":330},[303,4543,4544,4546,4549,4552,4554,4556,4558,4561],{"class":305,"line":398},[303,4545,3823],{"class":309},[303,4547,4548],{"class":340}," matches!",[303,4550,4551],{"class":323},"(frame, ",[303,4553,4025],{"class":313},[303,4555,4191],{"class":309},[303,4557,197],{"class":340},[303,4559,4560],{"class":323},"(_, _)) { ",[303,4562,4563],{"class":358},"\u002F\u002F si c'est un spare\n",[303,4565,4566,4569,4572,4574,4577,4579,4582,4584,4586,4589],{"class":305,"line":404},[303,4567,4568],{"class":309},"                let",[303,4570,4571],{"class":323}," next_roll ",[303,4573,650],{"class":309},[303,4575,4576],{"class":309}," match",[303,4578,4474],{"class":309},[303,4580,4581],{"class":323},"scores[index ",[303,4583,2540],{"class":309},[303,4585,846],{"class":380},[303,4587,4588],{"class":323},"] { ",[303,4590,4591],{"class":358},"\u002F\u002F on prend le lancer suivant\n",[303,4593,4594,4597,4599,4601,4604,4606,4608,4610,4612,4614,4617,4619],{"class":305,"line":410},[303,4595,4596],{"class":313},"                    Frame",[303,4598,4191],{"class":309},[303,4600,4269],{"class":340},[303,4602,4603],{"class":323},"(first, _) ",[303,4605,677],{"class":309},[303,4607,4039],{"class":313},[303,4609,4191],{"class":309},[303,4611,197],{"class":340},[303,4613,4603],{"class":323},[303,4615,4616],{"class":309},"=>",[303,4618,837],{"class":309},[303,4620,4621],{"class":323},"first,\n",[303,4623,4624],{"class":305,"line":448},[303,4625,4626],{"class":323},"                };\n",[303,4628,4629],{"class":305,"line":463},[303,4630,331],{"emptyLinePlaceholder":330},[303,4632,4633,4636,4638,4640,4642,4645],{"class":305,"line":469},[303,4634,4635],{"class":323},"                result ",[303,4637,3205],{"class":309},[303,4639,3428],{"class":380},[303,4641,3431],{"class":309},[303,4643,4644],{"class":323}," next_roll; ",[303,4646,4647],{"class":358},"\u002F\u002F et on l'additionne\n",[303,4649,4650,4653],{"class":305,"line":475},[303,4651,4652],{"class":309},"                continue",[303,4654,324],{"class":323},[303,4656,4657],{"class":305,"line":481},[303,4658,3843],{"class":323},[303,4660,4661],{"class":305,"line":492},[303,4662,331],{"emptyLinePlaceholder":330},[303,4664,4665,4667,4670,4672,4674,4676,4679,4681,4684],{"class":305,"line":501},[303,4666,3823],{"class":309},[303,4668,4669],{"class":309}," let",[303,4671,4039],{"class":313},[303,4673,4191],{"class":309},[303,4675,4269],{"class":340},[303,4677,4678],{"class":323},"(first, second) ",[303,4680,650],{"class":309},[303,4682,4683],{"class":323}," frame { ",[303,4685,4686],{"class":358},"\u002F\u002F si c'est une frame normale\n",[303,4688,4689,4691,4693,4695,4697,4700],{"class":305,"line":506},[303,4690,4635],{"class":323},[303,4692,3205],{"class":309},[303,4694,3465],{"class":323},[303,4696,2540],{"class":309},[303,4698,4699],{"class":323}," second; ",[303,4701,4702],{"class":358},"\u002F\u002F ca ne change pas, on additionne\n",[303,4704,4705],{"class":305,"line":1020},[303,4706,3843],{"class":323},[303,4708,4709],{"class":305,"line":1025},[303,4710,3452],{"class":323},[303,4712,4713],{"class":305,"line":1037},[303,4714,331],{"emptyLinePlaceholder":330},[303,4716,4717],{"class":305,"line":1300},[303,4718,3872],{"class":323},[303,4720,4721],{"class":305,"line":1343},[303,4722,466],{"class":323},[303,4724,4725],{"class":305,"line":1348},[303,4726,509],{"class":323},[20,4728,4729,4730,4732],{},"Nous avons bien refactoré, on peut continuer. On revient à ",[26,4731,3253],{}," avec une nouvelle limite : dix quilles renversées dès le premier lancer constituent un strike. Son bonus correspond aux deux lancers suivants.",[164,4734,4736],{"id":4735},"le-strike","Le strike",[20,4738,4739,529,4742],{},[26,4740,4741],{},"Scénario : un strike, suivi de quatre puis trois quilles, donne",[26,4743,4744],{},[92,4745,4746],{},"24",[20,4748,4749,4750,4753,4754,4757,4758,3284,4761,529,4765,50],{},"Notre joueur renverse les dix quilles au premier lancer, puis quatre et trois à la frame suivante. Le nouveau test est rouge : notre code considère encore la première frame comme un spare et retourne ",[92,4751,4752],{},"21",". Le strike doit valoir ",[92,4755,4756],{},"10 + 4 + 3",", puis la frame suivante vaut ",[92,4759,4760],{},"7",[26,4762,4763],{},[92,4764,4746],{},[26,4766,3291],{},[20,4768,4769,4770,4772],{},"On ajoute une variante ",[92,4771,203],{},", que l’on reconnaît avant de vérifier le spare. Pour calculer les bonus, on transforme les frames suivants en une suite de lancers : un strike fournit un seul lancer, les autres en fournissent deux.",[295,4774,4776],{"className":297,"code":4775,"language":146,"meta":299,"style":299},"enum Frame {\n    \u002F\u002F ...\n    Strike,\n}\n\nimpl BowlingGame {\n    pub fn calculate_score(&self) -> i32 {\n        \u002F\u002F ...\n        for index in 0..scores.len() {\n            let frame = &scores[index];\n\n            if matches!(frame, Frame::Spare(_, _)) {\n                let next_roll: Roll = scores\n                    .iter()\n                    \u002F\u002F du chaining de fonctions que je vous épargne\n                    .sum();\n\n                result += 10 + next_roll;\n                continue;\n            }\n\n            if matches!(frame, Frame::Strike) {\n                let next_two_rolls: Roll = scores\n                    .iter()\n                    \u002F\u002F exactement le meme chaining\n                    .sum();\n\n                result += 10 + next_two_rolls;\n                continue;\n            }\n\n            if let Frame::Score(first, second) = frame {\n                result += first + second;\n            }\n        }\n\n        result\n    }\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_a_strike_followed_by_four_then_three_pins() {\n    \u002F\u002F...\n    let scores: Vec\u003C(Roll, Roll)> =\n        [vec![(10, 0), (4, 3)], lose].concat();\n\n    assert_score(scores, 24);\n}\n",[92,4777,4778,4786,4790,4798,4802,4806,4814,4836,4841,4861,4873,4877,4894,4910,4919,4924,4933,4937,4950,4956,4960,4964,4980,4995,5003,5008,5016,5020,5033,5039,5043,5047,5066,5078,5082,5087,5092,5097,5102,5107,5112,5117,5122,5127,5137,5143,5166,5197,5202,5213],{"__ignoreMap":299},[303,4779,4780,4782,4784],{"class":305,"line":306},[303,4781,4036],{"class":309},[303,4783,4039],{"class":313},[303,4785,371],{"class":323},[303,4787,4788],{"class":305,"line":327},[303,4789,2911],{"class":358},[303,4791,4792,4795],{"class":305,"line":334},[303,4793,4794],{"class":313},"    Strike",[303,4796,4797],{"class":323},",\n",[303,4799,4800],{"class":305,"line":347},[303,4801,509],{"class":323},[303,4803,4804],{"class":305,"line":352},[303,4805,331],{"emptyLinePlaceholder":330},[303,4807,4808,4810,4812],{"class":305,"line":362},[303,4809,3714],{"class":309},[303,4811,3698],{"class":313},[303,4813,371],{"class":323},[303,4815,4816,4818,4820,4822,4824,4826,4828,4830,4832,4834],{"class":305,"line":374},[303,4817,3723],{"class":309},[303,4819,561],{"class":309},[303,4821,3728],{"class":340},[303,4823,454],{"class":323},[303,4825,3733],{"class":309},[303,4827,3736],{"class":380},[303,4829,3513],{"class":323},[303,4831,584],{"class":309},[303,4833,320],{"class":313},[303,4835,371],{"class":323},[303,4837,4838],{"class":305,"line":393},[303,4839,4840],{"class":358},"        \u002F\u002F ...\n",[303,4842,4843,4845,4847,4849,4851,4853,4855,4857,4859],{"class":305,"line":398},[303,4844,3786],{"class":309},[303,4846,3355],{"class":323},[303,4848,3189],{"class":309},[303,4850,3173],{"class":380},[303,4852,658],{"class":309},[303,4854,3797],{"class":323},[303,4856,50],{"class":309},[303,4858,3369],{"class":340},[303,4860,489],{"class":323},[303,4862,4863,4865,4867,4869,4871],{"class":305,"line":404},[303,4864,3403],{"class":309},[303,4866,4530],{"class":323},[303,4868,650],{"class":309},[303,4870,4474],{"class":309},[303,4872,4537],{"class":323},[303,4874,4875],{"class":305,"line":410},[303,4876,331],{"emptyLinePlaceholder":330},[303,4878,4879,4881,4883,4885,4887,4889,4891],{"class":305,"line":448},[303,4880,3823],{"class":309},[303,4882,4548],{"class":340},[303,4884,4551],{"class":323},[303,4886,4025],{"class":313},[303,4888,4191],{"class":309},[303,4890,197],{"class":340},[303,4892,4893],{"class":323},"(_, _)) {\n",[303,4895,4896,4898,4901,4903,4905,4907],{"class":305,"line":463},[303,4897,4568],{"class":309},[303,4899,4900],{"class":323}," next_roll",[303,4902,422],{"class":309},[303,4904,314],{"class":313},[303,4906,317],{"class":309},[303,4908,4909],{"class":323}," scores\n",[303,4911,4912,4915,4917],{"class":305,"line":469},[303,4913,4914],{"class":309},"                    .",[303,4916,2661],{"class":340},[303,4918,2664],{"class":323},[303,4920,4921],{"class":305,"line":475},[303,4922,4923],{"class":358},"                    \u002F\u002F du chaining de fonctions que je vous épargne\n",[303,4925,4926,4928,4931],{"class":305,"line":481},[303,4927,4914],{"class":309},[303,4929,4930],{"class":340},"sum",[303,4932,498],{"class":323},[303,4934,4935],{"class":305,"line":492},[303,4936,331],{"emptyLinePlaceholder":330},[303,4938,4939,4941,4943,4945,4947],{"class":305,"line":501},[303,4940,4635],{"class":323},[303,4942,3205],{"class":309},[303,4944,3428],{"class":380},[303,4946,3431],{"class":309},[303,4948,4949],{"class":323}," next_roll;\n",[303,4951,4952,4954],{"class":305,"line":506},[303,4953,4652],{"class":309},[303,4955,324],{"class":323},[303,4957,4958],{"class":305,"line":1020},[303,4959,3843],{"class":323},[303,4961,4962],{"class":305,"line":1025},[303,4963,331],{"emptyLinePlaceholder":330},[303,4965,4966,4968,4970,4972,4974,4976,4978],{"class":305,"line":1037},[303,4967,3823],{"class":309},[303,4969,4548],{"class":340},[303,4971,4551],{"class":323},[303,4973,4025],{"class":313},[303,4975,4191],{"class":309},[303,4977,203],{"class":313},[303,4979,445],{"class":323},[303,4981,4982,4984,4987,4989,4991,4993],{"class":305,"line":1300},[303,4983,4568],{"class":309},[303,4985,4986],{"class":323}," next_two_rolls",[303,4988,422],{"class":309},[303,4990,314],{"class":313},[303,4992,317],{"class":309},[303,4994,4909],{"class":323},[303,4996,4997,4999,5001],{"class":305,"line":1343},[303,4998,4914],{"class":309},[303,5000,2661],{"class":340},[303,5002,2664],{"class":323},[303,5004,5005],{"class":305,"line":1348},[303,5006,5007],{"class":358},"                    \u002F\u002F exactement le meme chaining\n",[303,5009,5010,5012,5014],{"class":305,"line":1359},[303,5011,4914],{"class":309},[303,5013,4930],{"class":340},[303,5015,498],{"class":323},[303,5017,5018],{"class":305,"line":2406},[303,5019,331],{"emptyLinePlaceholder":330},[303,5021,5022,5024,5026,5028,5030],{"class":305,"line":2449},[303,5023,4635],{"class":323},[303,5025,3205],{"class":309},[303,5027,3428],{"class":380},[303,5029,3431],{"class":309},[303,5031,5032],{"class":323}," next_two_rolls;\n",[303,5034,5035,5037],{"class":305,"line":2454},[303,5036,4652],{"class":309},[303,5038,324],{"class":323},[303,5040,5041],{"class":305,"line":2465},[303,5042,3843],{"class":323},[303,5044,5045],{"class":305,"line":3630},[303,5046,331],{"emptyLinePlaceholder":330},[303,5048,5049,5051,5053,5055,5057,5059,5061,5063],{"class":305,"line":3635},[303,5050,3823],{"class":309},[303,5052,4669],{"class":309},[303,5054,4039],{"class":313},[303,5056,4191],{"class":309},[303,5058,4269],{"class":340},[303,5060,4678],{"class":323},[303,5062,650],{"class":309},[303,5064,5065],{"class":323}," frame {\n",[303,5067,5068,5070,5072,5074,5076],{"class":305,"line":3646},[303,5069,4635],{"class":323},[303,5071,3205],{"class":309},[303,5073,3465],{"class":323},[303,5075,2540],{"class":309},[303,5077,3470],{"class":323},[303,5079,5080],{"class":305,"line":4004},[303,5081,3843],{"class":323},[303,5083,5085],{"class":305,"line":5084},35,[303,5086,3452],{"class":323},[303,5088,5090],{"class":305,"line":5089},36,[303,5091,331],{"emptyLinePlaceholder":330},[303,5093,5095],{"class":305,"line":5094},37,[303,5096,3872],{"class":323},[303,5098,5100],{"class":305,"line":5099},38,[303,5101,466],{"class":323},[303,5103,5105],{"class":305,"line":5104},39,[303,5106,509],{"class":323},[303,5108,5110],{"class":305,"line":5109},40,[303,5111,331],{"emptyLinePlaceholder":330},[303,5113,5115],{"class":305,"line":5114},41,[303,5116,606],{"class":358},[303,5118,5120],{"class":305,"line":5119},42,[303,5121,331],{"emptyLinePlaceholder":330},[303,5123,5125],{"class":305,"line":5124},43,[303,5126,615],{"class":323},[303,5128,5130,5132,5135],{"class":305,"line":5129},44,[303,5131,337],{"class":309},[303,5133,5134],{"class":340}," calculate_for_a_strike_followed_by_four_then_three_pins",[303,5136,489],{"class":323},[303,5138,5140],{"class":305,"line":5139},45,[303,5141,5142],{"class":358},"    \u002F\u002F...\n",[303,5144,5146,5148,5150,5152,5154,5156,5158,5160,5162,5164],{"class":305,"line":5145},46,[303,5147,629],{"class":309},[303,5149,976],{"class":323},[303,5151,422],{"class":309},[303,5153,425],{"class":313},[303,5155,428],{"class":323},[303,5157,254],{"class":313},[303,5159,433],{"class":323},[303,5161,254],{"class":313},[303,5163,647],{"class":323},[303,5165,3595],{"class":309},[303,5167,5169,5171,5173,5175,5177,5179,5181,5183,5185,5187,5189,5191,5193,5195],{"class":305,"line":5168},47,[303,5170,3600],{"class":323},[303,5172,998],{"class":340},[303,5174,1001],{"class":323},[303,5176,661],{"class":380},[303,5178,433],{"class":323},[303,5180,534],{"class":380},[303,5182,3613],{"class":323},[303,5184,1772],{"class":380},[303,5186,433],{"class":323},[303,5188,2099],{"class":380},[303,5190,1010],{"class":323},[303,5192,50],{"class":309},[303,5194,1015],{"class":340},[303,5196,498],{"class":323},[303,5198,5200],{"class":305,"line":5199},48,[303,5201,331],{"emptyLinePlaceholder":330},[303,5203,5205,5207,5209,5211],{"class":305,"line":5204},49,[303,5206,711],{"class":340},[303,5208,1030],{"class":323},[303,5210,4746],{"class":380},[303,5212,719],{"class":323},[303,5214,5216],{"class":305,"line":5215},50,[303,5217,509],{"class":323},[20,5219,5220],{},"La duplication entre les deux calculs que sont strike et spare est visible ; nous allons refactorer ça un peu plus tard.",[164,5222,5224],{"id":5223},"la-dernière-frame","La dernière frame",[20,5226,5227,529,5230],{},[26,5228,5229],{},"Scénario : une partie parfaite donne",[26,5231,5232],{},[92,5233,5234],{},"300",[20,5236,5237,5238,5241,5242,5245,5246,5248,5249,5251],{},"Notre joueur est devenu très doué après toutes ces défaites. Il enchaîne maintenant les strikes pendant toute la partie. Le nouveau test est rouge : notre calcul retourne ",[92,5239,5240],{},"270",". Les huit premières frames valent chacune ",[92,5243,5244],{},"30",", la neuvième vaut ",[92,5247,3267],{}," et la dernière vaut ",[92,5250,661],{},". Il manque les deux lancers bonus de la dernière frame.",[20,5253,5254,5255,5258,5259,5262,5263,5265],{},"Le truc, c’est que nous devons maintenant faire évoluer notre modèle car nous ne représentons pas ",[3117,5256,5257],{},"encore"," trois lancers pour la dernière frame. Je vous la fait courte mais on ajoute ",[92,5260,5261],{},"LastFrame(Roll, Roll, Roll)"," à notre enum. On adapte notre utilitaire et les données des tests : les couples existants deviennent des tuples avec ",[92,5264,94],{},". Le test de la partie parfaite représente maintenant neuf strikes, puis une dernière frame contenant trois strikes.",[20,5267,5268],{},"Enfin, nous faisons la modification dans notre algo.",[295,5270,5272],{"className":297,"code":5271,"language":146,"meta":299,"style":299},"\u002F\u002F Dans la boucle de calculate_score,\n\u002F\u002F après le traitement des spares et des strikes:\n\nif let Frame::LastFrame(first, second, third) = frame {\n    result += first + second + third;\n    continue;\n}\n\nif let Frame::Score(first, second) = frame {\n    result += first + second;\n}\n\n\u002F\u002F ...\n\n#[test]\nfn calculate_for_a_perfect_game() {\n    let strikes: Vec\u003C(Roll, Roll, Option\u003CRoll>)> = (0..9)\n        .map(|_| (10, 0, None))\n        .collect();\n\n    let scores = [strikes, vec![(10, 10, Some(10))]].concat();\n\n    assert_score(scores, 300);\n}\n",[92,5273,5274,5279,5284,5288,5309,5327,5334,5338,5342,5360,5372,5376,5380,5384,5388,5392,5401,5444,5472,5480,5484,5523,5527,5537],{"__ignoreMap":299},[303,5275,5276],{"class":305,"line":306},[303,5277,5278],{"class":358},"\u002F\u002F Dans la boucle de calculate_score,\n",[303,5280,5281],{"class":305,"line":327},[303,5282,5283],{"class":358},"\u002F\u002F après le traitement des spares et des strikes:\n",[303,5285,5286],{"class":305,"line":334},[303,5287,331],{"emptyLinePlaceholder":330},[303,5289,5290,5293,5295,5297,5299,5302,5305,5307],{"class":305,"line":347},[303,5291,5292],{"class":309},"if",[303,5294,4669],{"class":309},[303,5296,4039],{"class":313},[303,5298,4191],{"class":309},[303,5300,5301],{"class":340},"LastFrame",[303,5303,5304],{"class":323},"(first, second, third) ",[303,5306,650],{"class":309},[303,5308,5065],{"class":323},[303,5310,5311,5314,5316,5318,5320,5322,5324],{"class":305,"line":352},[303,5312,5313],{"class":323},"    result ",[303,5315,3205],{"class":309},[303,5317,3465],{"class":323},[303,5319,2540],{"class":309},[303,5321,3530],{"class":323},[303,5323,2540],{"class":309},[303,5325,5326],{"class":323}," third;\n",[303,5328,5329,5332],{"class":305,"line":362},[303,5330,5331],{"class":309},"    continue",[303,5333,324],{"class":323},[303,5335,5336],{"class":305,"line":374},[303,5337,509],{"class":323},[303,5339,5340],{"class":305,"line":393},[303,5341,331],{"emptyLinePlaceholder":330},[303,5343,5344,5346,5348,5350,5352,5354,5356,5358],{"class":305,"line":398},[303,5345,5292],{"class":309},[303,5347,4669],{"class":309},[303,5349,4039],{"class":313},[303,5351,4191],{"class":309},[303,5353,4269],{"class":340},[303,5355,4678],{"class":323},[303,5357,650],{"class":309},[303,5359,5065],{"class":323},[303,5361,5362,5364,5366,5368,5370],{"class":305,"line":404},[303,5363,5313],{"class":323},[303,5365,3205],{"class":309},[303,5367,3465],{"class":323},[303,5369,2540],{"class":309},[303,5371,3470],{"class":323},[303,5373,5374],{"class":305,"line":410},[303,5375,509],{"class":323},[303,5377,5378],{"class":305,"line":448},[303,5379,331],{"emptyLinePlaceholder":330},[303,5381,5382],{"class":305,"line":463},[303,5383,606],{"class":358},[303,5385,5386],{"class":305,"line":469},[303,5387,331],{"emptyLinePlaceholder":330},[303,5389,5390],{"class":305,"line":475},[303,5391,615],{"class":323},[303,5393,5394,5396,5399],{"class":305,"line":481},[303,5395,337],{"class":309},[303,5397,5398],{"class":340}," calculate_for_a_perfect_game",[303,5400,489],{"class":323},[303,5402,5403,5405,5408,5410,5412,5414,5416,5418,5420,5422,5425,5427,5429,5432,5434,5436,5438,5440,5442],{"class":305,"line":492},[303,5404,629],{"class":309},[303,5406,5407],{"class":323}," strikes",[303,5409,422],{"class":309},[303,5411,425],{"class":313},[303,5413,428],{"class":323},[303,5415,254],{"class":313},[303,5417,433],{"class":323},[303,5419,254],{"class":313},[303,5421,433],{"class":323},[303,5423,5424],{"class":313},"Option",[303,5426,4181],{"class":323},[303,5428,254],{"class":313},[303,5430,5431],{"class":323},">)> ",[303,5433,650],{"class":309},[303,5435,653],{"class":323},[303,5437,534],{"class":380},[303,5439,658],{"class":309},[303,5441,931],{"class":380},[303,5443,664],{"class":323},[303,5445,5446,5448,5450,5452,5454,5456,5458,5460,5462,5464,5466,5468,5470],{"class":305,"line":501},[303,5447,669],{"class":309},[303,5449,672],{"class":340},[303,5451,454],{"class":323},[303,5453,677],{"class":309},[303,5455,680],{"class":323},[303,5457,677],{"class":309},[303,5459,653],{"class":323},[303,5461,661],{"class":380},[303,5463,433],{"class":323},[303,5465,534],{"class":380},[303,5467,433],{"class":323},[303,5469,94],{"class":313},[303,5471,693],{"class":323},[303,5473,5474,5476,5478],{"class":305,"line":506},[303,5475,669],{"class":309},[303,5477,700],{"class":340},[303,5479,498],{"class":323},[303,5481,5482],{"class":305,"line":1020},[303,5483,331],{"emptyLinePlaceholder":330},[303,5485,5486,5488,5490,5492,5495,5497,5499,5501,5503,5505,5507,5510,5512,5514,5517,5519,5521],{"class":305,"line":1025},[303,5487,629],{"class":309},[303,5489,4469],{"class":323},[303,5491,650],{"class":309},[303,5493,5494],{"class":323}," [strikes, ",[303,5496,998],{"class":340},[303,5498,1001],{"class":323},[303,5500,661],{"class":380},[303,5502,433],{"class":323},[303,5504,661],{"class":380},[303,5506,433],{"class":323},[303,5508,5509],{"class":313},"Some",[303,5511,454],{"class":323},[303,5513,661],{"class":380},[303,5515,5516],{"class":323},"))]]",[303,5518,50],{"class":309},[303,5520,1015],{"class":340},[303,5522,498],{"class":323},[303,5524,5525],{"class":305,"line":1037},[303,5526,331],{"emptyLinePlaceholder":330},[303,5528,5529,5531,5533,5535],{"class":305,"line":1300},[303,5530,711],{"class":340},[303,5532,1030],{"class":323},[303,5534,5234],{"class":380},[303,5536,719],{"class":323},[303,5538,5539],{"class":305,"line":1343},[303,5540,509],{"class":323},[20,5542,5543,5544,5546,5547,3284,5549,529,5553,50],{},"Le test de la partie parfaite passe maintenant : les neuf premières frames valent chacune ",[92,5545,5244],{},", puis les trois lancers de la dernière frame ajoutent ",[92,5548,5244],{},[26,5550,5551],{},[92,5552,5234],{},[26,5554,3291],{},[20,5556,5557,5558,5561,5562,50],{},"Retenez que ",[26,5559,5560],{},"boundary"," = tester les transitions\u002Fvaleurs limites où le ",[26,5563,5564],{},"comportement risque de changer",[52,5566,5568],{"id":5567},"le-résultat","Le résultat",[20,5570,5571],{},"Cet article étant déjà bien assez long, je vous passe plusieurs itérations de refactoring. Voici la solution que nous avons développé jusqu’à maintenant.",[295,5573,5575],{"className":297,"code":5574,"language":146,"meta":299,"style":299},"const BOWLING_PINS: i32 = 10;\n\n\u002F\u002F ...\n\nimpl BowlingGame {\n    pub fn calculate_score(&self) -> i32 {\n        self.scores\n            .iter()\n            .enumerate()\n            .map(|(index, frame)| match frame {\n                Frame::Strike => BOWLING_PINS + self.sum_next_rolls(index, 2),\n                Frame::Spare(_, _) => BOWLING_PINS + self.sum_next_rolls(index, 1),\n                Frame::Score(first, second) => first + second,\n                Frame::LastFrame(first, second, third) => first + second + third,\n            })\n            .sum()\n    }\n\n    fn sum_next_rolls(&self, index: usize, nb_rolls: usize) -> i32 {\n        self.scores\n            .iter()\n            .skip(index + 1)\n            .flat_map(|frame| match frame {\n                Frame::Score(first, second)\n                | Frame::Spare(first, second) => vec![*first, *second],\n                Frame::Strike => vec![BOWLING_PINS],\n                Frame::LastFrame(first, second, third) => {\n                    vec![*first, *second, *third]\n                }\n            })\n            .take(nb_rolls)\n            .sum()\n    }\n}\n",[92,5576,5577,5595,5599,5603,5607,5615,5637,5647,5656,5665,5684,5714,5743,5762,5785,5790,5798,5802,5806,5842,5850,5858,5874,5894,5905,5937,5957,5971,5992,5997,6001,6011,6019,6023],{"__ignoreMap":299},[303,5578,5579,5582,5585,5587,5589,5591,5593],{"class":305,"line":306},[303,5580,5581],{"class":309},"const",[303,5583,5584],{"class":380}," BOWLING_PINS",[303,5586,422],{"class":309},[303,5588,320],{"class":313},[303,5590,317],{"class":309},[303,5592,3428],{"class":380},[303,5594,324],{"class":323},[303,5596,5597],{"class":305,"line":327},[303,5598,331],{"emptyLinePlaceholder":330},[303,5600,5601],{"class":305,"line":334},[303,5602,606],{"class":358},[303,5604,5605],{"class":305,"line":347},[303,5606,331],{"emptyLinePlaceholder":330},[303,5608,5609,5611,5613],{"class":305,"line":352},[303,5610,3714],{"class":309},[303,5612,3698],{"class":313},[303,5614,371],{"class":323},[303,5616,5617,5619,5621,5623,5625,5627,5629,5631,5633,5635],{"class":305,"line":362},[303,5618,3723],{"class":309},[303,5620,561],{"class":309},[303,5622,3728],{"class":340},[303,5624,454],{"class":323},[303,5626,3733],{"class":309},[303,5628,3736],{"class":380},[303,5630,3513],{"class":323},[303,5632,584],{"class":309},[303,5634,320],{"class":313},[303,5636,371],{"class":323},[303,5638,5639,5642,5644],{"class":305,"line":374},[303,5640,5641],{"class":380},"        self",[303,5643,50],{"class":309},[303,5645,5646],{"class":323},"scores\n",[303,5648,5649,5652,5654],{"class":305,"line":393},[303,5650,5651],{"class":309},"            .",[303,5653,2661],{"class":340},[303,5655,2664],{"class":323},[303,5657,5658,5660,5663],{"class":305,"line":398},[303,5659,5651],{"class":309},[303,5661,5662],{"class":340},"enumerate",[303,5664,2664],{"class":323},[303,5666,5667,5669,5671,5673,5675,5678,5680,5682],{"class":305,"line":404},[303,5668,5651],{"class":309},[303,5670,672],{"class":340},[303,5672,454],{"class":323},[303,5674,677],{"class":309},[303,5676,5677],{"class":323},"(index, frame)",[303,5679,677],{"class":309},[303,5681,4576],{"class":309},[303,5683,5065],{"class":323},[303,5685,5686,5689,5691,5693,5696,5698,5700,5702,5704,5707,5710,5712],{"class":305,"line":410},[303,5687,5688],{"class":313},"                Frame",[303,5690,4191],{"class":309},[303,5692,203],{"class":313},[303,5694,5695],{"class":309}," =>",[303,5697,5584],{"class":380},[303,5699,3431],{"class":309},[303,5701,3826],{"class":380},[303,5703,50],{"class":309},[303,5705,5706],{"class":340},"sum_next_rolls",[303,5708,5709],{"class":323},"(index, ",[303,5711,1476],{"class":380},[303,5713,4057],{"class":323},[303,5715,5716,5718,5720,5722,5725,5727,5729,5731,5733,5735,5737,5739,5741],{"class":305,"line":448},[303,5717,5688],{"class":313},[303,5719,4191],{"class":309},[303,5721,197],{"class":340},[303,5723,5724],{"class":323},"(_, _) ",[303,5726,4616],{"class":309},[303,5728,5584],{"class":380},[303,5730,3431],{"class":309},[303,5732,3826],{"class":380},[303,5734,50],{"class":309},[303,5736,5706],{"class":340},[303,5738,5709],{"class":323},[303,5740,744],{"class":380},[303,5742,4057],{"class":323},[303,5744,5745,5747,5749,5751,5753,5755,5757,5759],{"class":305,"line":463},[303,5746,5688],{"class":313},[303,5748,4191],{"class":309},[303,5750,4269],{"class":340},[303,5752,4678],{"class":323},[303,5754,4616],{"class":309},[303,5756,3465],{"class":323},[303,5758,2540],{"class":309},[303,5760,5761],{"class":323}," second,\n",[303,5763,5764,5766,5768,5770,5772,5774,5776,5778,5780,5782],{"class":305,"line":469},[303,5765,5688],{"class":313},[303,5767,4191],{"class":309},[303,5769,5301],{"class":340},[303,5771,5304],{"class":323},[303,5773,4616],{"class":309},[303,5775,3465],{"class":323},[303,5777,2540],{"class":309},[303,5779,3530],{"class":323},[303,5781,2540],{"class":309},[303,5783,5784],{"class":323}," third,\n",[303,5786,5787],{"class":305,"line":475},[303,5788,5789],{"class":323},"            })\n",[303,5791,5792,5794,5796],{"class":305,"line":481},[303,5793,5651],{"class":309},[303,5795,4930],{"class":340},[303,5797,2664],{"class":323},[303,5799,5800],{"class":305,"line":492},[303,5801,466],{"class":323},[303,5803,5804],{"class":305,"line":501},[303,5805,331],{"emptyLinePlaceholder":330},[303,5807,5808,5810,5813,5815,5817,5819,5822,5824,5827,5830,5832,5834,5836,5838,5840],{"class":305,"line":506},[303,5809,413],{"class":309},[303,5811,5812],{"class":340}," sum_next_rolls",[303,5814,454],{"class":323},[303,5816,3733],{"class":309},[303,5818,3736],{"class":380},[303,5820,5821],{"class":323},", index",[303,5823,422],{"class":309},[303,5825,5826],{"class":313}," usize",[303,5828,5829],{"class":323},", nb_rolls",[303,5831,422],{"class":309},[303,5833,5826],{"class":313},[303,5835,3513],{"class":323},[303,5837,584],{"class":309},[303,5839,320],{"class":313},[303,5841,371],{"class":323},[303,5843,5844,5846,5848],{"class":305,"line":1020},[303,5845,5641],{"class":380},[303,5847,50],{"class":309},[303,5849,5646],{"class":323},[303,5851,5852,5854,5856],{"class":305,"line":1025},[303,5853,5651],{"class":309},[303,5855,2661],{"class":340},[303,5857,2664],{"class":323},[303,5859,5860,5862,5865,5868,5870,5872],{"class":305,"line":1037},[303,5861,5651],{"class":309},[303,5863,5864],{"class":340},"skip",[303,5866,5867],{"class":323},"(index ",[303,5869,2540],{"class":309},[303,5871,846],{"class":380},[303,5873,664],{"class":323},[303,5875,5876,5878,5881,5883,5885,5888,5890,5892],{"class":305,"line":1300},[303,5877,5651],{"class":309},[303,5879,5880],{"class":340},"flat_map",[303,5882,454],{"class":323},[303,5884,677],{"class":309},[303,5886,5887],{"class":323},"frame",[303,5889,677],{"class":309},[303,5891,4576],{"class":309},[303,5893,5065],{"class":323},[303,5895,5896,5898,5900,5902],{"class":305,"line":1343},[303,5897,5688],{"class":313},[303,5899,4191],{"class":309},[303,5901,4269],{"class":340},[303,5903,5904],{"class":323},"(first, second)\n",[303,5906,5907,5910,5912,5914,5916,5918,5920,5923,5926,5929,5932,5934],{"class":305,"line":1348},[303,5908,5909],{"class":309},"                |",[303,5911,4039],{"class":313},[303,5913,4191],{"class":309},[303,5915,197],{"class":340},[303,5917,4678],{"class":323},[303,5919,4616],{"class":309},[303,5921,5922],{"class":340}," vec!",[303,5924,5925],{"class":323},"[",[303,5927,5928],{"class":309},"*",[303,5930,5931],{"class":323},"first, ",[303,5933,5928],{"class":309},[303,5935,5936],{"class":323},"second],\n",[303,5938,5939,5941,5943,5945,5947,5949,5951,5954],{"class":305,"line":1359},[303,5940,5688],{"class":313},[303,5942,4191],{"class":309},[303,5944,203],{"class":313},[303,5946,5695],{"class":309},[303,5948,5922],{"class":340},[303,5950,5925],{"class":323},[303,5952,5953],{"class":380},"BOWLING_PINS",[303,5955,5956],{"class":323},"],\n",[303,5958,5959,5961,5963,5965,5967,5969],{"class":305,"line":2406},[303,5960,5688],{"class":313},[303,5962,4191],{"class":309},[303,5964,5301],{"class":340},[303,5966,5304],{"class":323},[303,5968,4616],{"class":309},[303,5970,371],{"class":323},[303,5972,5973,5976,5978,5980,5982,5984,5987,5989],{"class":305,"line":2449},[303,5974,5975],{"class":340},"                    vec!",[303,5977,5925],{"class":323},[303,5979,5928],{"class":309},[303,5981,5931],{"class":323},[303,5983,5928],{"class":309},[303,5985,5986],{"class":323},"second, ",[303,5988,5928],{"class":309},[303,5990,5991],{"class":323},"third]\n",[303,5993,5994],{"class":305,"line":2454},[303,5995,5996],{"class":323},"                }\n",[303,5998,5999],{"class":305,"line":2465},[303,6000,5789],{"class":323},[303,6002,6003,6005,6008],{"class":305,"line":3630},[303,6004,5651],{"class":309},[303,6006,6007],{"class":340},"take",[303,6009,6010],{"class":323},"(nb_rolls)\n",[303,6012,6013,6015,6017],{"class":305,"line":3635},[303,6014,5651],{"class":309},[303,6016,4930],{"class":340},[303,6018,2664],{"class":323},[303,6020,6021],{"class":305,"line":3646},[303,6022,466],{"class":323},[303,6024,6025],{"class":305,"line":4004},[303,6026,509],{"class":323},[20,6028,6029],{},"Je vous avais bien dit que nous aurions quelque chose de plus sexy à lire par la suite.",[52,6031,6033],{"id":6032},"e-quest-ce-quon-a-oublié","E - Qu’est ce qu’on a oublié ?",[20,6035,6036],{},"Très bien, on a fait le tour selon vous ?",[20,6038,6039,6040,6043,6044,6047,6048,6051,6052,6055,6056,6059,6060,50],{},"Et bien en réalité, pas vraiment. Nous avons en effet une solution qui fonctionne. Nous avons commencé avec littéralement ",[26,6041,6042],{},"Zero"," coups réussis puis, nous avons ajouté plusieurs cas minimaux avec ",[26,6045,6046],{},"One",". Par la suite, nous avons introduit ",[26,6049,6050],{},"Many"," coups réussis. Nous avons testé les ",[26,6053,6054],{},"Boundary"," qui causent des changements de comportement dans le calcul. Nous avons refactor pour encapsuler le domaine métier et tester les ",[26,6057,6058],{},"Interface"," de nos objets. Le tout en suivant ",[26,6061,6062],{},"Simple Solutions",[20,6064,6065,6066,6069],{},"Si vous avez l’oeil, vous l’avez peut-être remarqué depuis le début mais il nous manque des tests pour les ",[26,6067,6068],{},"Exception",". Chose plutôt importante, on ne va pas se mentir. C’est en ça que zombies est utile, se dire « Mince j’ai peut-être loupé quelque chose » ou encore « On fait quoi si on reçoit une frame où plus de 10 quilles sont tombées ? ».",[20,6071,6072,6073,6075],{},"Le but premier de ",[26,6074,49],{},", c’est de pousser à la réflexion. Je ne dis pas que c’est une méthode que vous pourrez utiliser systématiquement de manière aussi naïve que pour notre exemple. Ni qu’il faut absolument retranscrire toutes les variantes lors de chaque développement ; non, c’est uniquement là afin de vous aider à vous poser les bonnes questions.",[52,6077,6079],{"id":6078},"s-et-le-s-dans-tout-ça","S - Et le S dans tout ça ?",[20,6081,6082,6083,6086],{},"Le ",[26,6084,6085],{},"S"," de ZOMBIES n’a pas vraiment eu droit à son propre chapitre, et c’est volontaire.",[20,6088,6089,6090,50],{},"Contrairement aux autres lettres, il ne représente pas forcément une étape précise de notre progression. Il nous accompagne plutôt tout au long du développement : ",[26,6091,6092],{},"commencer par le scénario le plus simple possible et y répondre avec la solution la plus simple possible",[20,6094,6095,6096,6098,6099,6101],{},"C’est exactement ce que nous avons fait depuis le début. Pour notre première partie à zéro, nous avons simplement retourné ",[92,6097,534],{},". Puis, lorsqu’un nouveau test nous a demandé de retourner ",[92,6100,744],{},", nous avons ajouté le cas minimum nécessaire. Ce n’est qu’après plusieurs exemples que nous avons fait émerger une règle plus générale.",[20,6103,6104],{},"L’idée n’est donc pas d’anticiper la solution finale, mais de laisser les tests nous y conduire progressivement. Tant que la solution la plus simple permet de passer au vert, elle est suffisante. Le refactoring viendra ensuite lorsque les exemples nous donneront suffisamment d’informations pour généraliser.",[20,6106,6107,6110,6111,50],{},[26,6108,6109],{},"Simple Scenario \u002F Simple Solution",", c’est finalement ce qui permet de conserver nos baby steps… réellement ",[3117,6112,6113],{},"baby",[52,6115,6117],{"id":6116},"zombies-à-lère-de-lia","Z.O.M.B.I.E.S à l’ère de l’IA ?",[20,6119,6120],{},"C’est vrai, c’est une question que l’on pourrait se poser et qui semble plutôt légitime dans la mesure où l’on écrit de moins en moins de code. L’ami dont je vous parlais au début m’a récemment dit « Oui, de toutes manières, j’ai un peu drop le TDD puisque c’est l’IA qui dev ». J’ai trouvé ça dommage.",[20,6122,6123,6124,6126,6127,6130],{},"Je pense qu’il est important de rappeler que le propos du TDD n’a jamais été de tester mais bien de développer. Que ce soit en test first ou en TDD, à la main ou via de la genAI, je suis d’avis que ",[26,6125,49],{}," peut avoir sa place au sein de votre boite à outils et cela plus que jamais. Surtout dans un monde où l’on ship de plus en plus de code facilement. Couplé au BDD et au ",[3117,6128,6129],{},"tres amigos"," il pourra vous aider à définir une spec qui fasse sens pour le besoin, pas plus, pas moins.",[20,6132,6133,6134,6137,6138,6141],{},"Le seul que l’on perd dans cette équation c’est le ",[26,6135,6136],{},"S de Simple Scénario\u002FSimple Solution","… parce que oui, indéniablement, l’IA a tendance à surcomplexifier ce qu’elle produit ou à le rendre moins ",[3117,6139,6140],{},"human readable",". Certains poseront la question « Est-ce qu’on ne s’en fiche pas un peu maintenant que l’on produit du code pour que l’IA le lise ? ». J’apporterais un peu de nuance en disant que : « D’accord, peut-être pas besoin d’une fluent API ici ou là, peut-être que simplement le nom de ma variable est suffisant à la compréhension générale du code ».",[20,6143,6144,6145,6148],{},"En revanche, je pense qu’il est important de définir un juste milieu au sein de vos équipes. ",[3117,6146,6147],{},"Je suis d’avis"," que le trouver est essentiel ; dans la mesure où il faut relire le code critique que les IA produisent.",[20,6150,6151],{},"Je vous laisse sur cette réflexion en espérant que l’article vous ait appris quelque chose.",[20,6153,6154],{},"Pour ceux qui voudraient se lancer au TDD ou à rust 🦀, comme on dit : il n’y a plus qu’à. Prenez un Kata, votre IDE et c’est parti !",[6156,6157,6158],"style",{},"html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":299,"searchDepth":327,"depth":327,"links":6160},[6161,6162,6166,6167,6168,6169,6174,6175,6176,6177],{"id":54,"depth":327,"text":55},{"id":134,"depth":327,"text":135,"children":6163},[6164,6165],{"id":166,"depth":334,"text":167},{"id":286,"depth":334,"text":287},{"id":515,"depth":327,"text":516},{"id":726,"depth":327,"text":727},{"id":2552,"depth":327,"text":2553},{"id":3243,"depth":327,"text":3244,"children":6170},[6171,6172,6173],{"id":3247,"depth":334,"text":3248},{"id":4735,"depth":334,"text":4736},{"id":5223,"depth":334,"text":5224},{"id":5567,"depth":327,"text":5568},{"id":6032,"depth":327,"text":6033},{"id":6078,"depth":327,"text":6079},{"id":6116,"depth":327,"text":6117},"2026-10-26T09:23:15.193Z","Les zombies, ça vous parle ? Ceux que nous allons évoquer ici n’ont aucun lien avec ceux de Walking Dead ou du superbe titre du groupe The Cranberries. Non, les zombies dont nous allons parler aujourd","md",".\u002Fassets\u002Fcover-image.webp",{},"\u002Fblogs\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies",[6185,6190,6195],{"id":6186,"name":6187,"image":6188,"linkedin":6189,"x":13,"jobTitle":14},"3f3f4462-cd38-80e4-9d5b-e3b8f7378c03","Maxime Gonzalez",".\u002Fassets\u002Freviewer-maxime-gonzalez.webp","www.linkedin.com\u002Fin\u002Fmaxime-gonzalez-4a70b111a",{"id":6191,"name":6192,"image":6193,"linkedin":6194,"x":13},"33bf4462-cd38-80da-845c-c63b2fd024bf","Florian Hirson",".\u002Fassets\u002Freviewer-florian-hirson.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fflorian-hirson\u002F",{"id":6196,"name":6197,"image":6198,"linkedin":13,"x":13},"3d0f4462-cd38-80c3-9ded-e6303c15ff2f","Nuno","\u002Fdefault-author-image.webp",{"title":5,"description":6179},"blogs\u002F2026-10-26-tdd-comment-faire-un-strike-avec-la-methode-zombies\u002Findex",[6202,146,6203],"tdd","craft","jjYbdN9TkhUaeR2S8b-VArF63FLEQbzX028UCJpLpuM",[6206,6215,6221,6229],{"path":6207,"title":6208,"image":6209,"date":6210,"tags":6211},"\u002Fblogs\u002F2026-06-30-tdd-jen-entends-beaucoup-parler-mais-cest-quoi-au-juste","TDD : J’en entends beaucoup parler, mais c’est quoi au juste ?","\u002Fcontent-assets\u002F2026-06-30-tdd-jen-entends-beaucoup-parler-mais-cest-quoi-au-juste\u002Fassets\u002Fcover-image.webp","30 juin 2026",[6212,6203,6202,6213,6214],"testing","java","test",{"path":6216,"title":6217,"image":6218,"date":6219,"tags":6220},"\u002Fblogs\u002F2026-10-21-refactorer-son-poste-de-travail-un-guide-ergonomique-pour-les-developpeuses-et-developpeurs","Refactorer son poste de travail : un guide ergonomique pour les développeuses et développeurs","\u002Fcontent-assets\u002F2026-10-21-refactorer-son-poste-de-travail-un-guide-ergonomique-pour-les-developpeuses-et-developpeurs\u002Fassets\u002Fcover-image.webp","21 octobre 2026",[6203],{"path":6222,"title":6223,"image":6224,"date":6225,"tags":6226},"\u002Fblogs\u002F2026-10-12-cartographier-son-systeme-dinformation-sans-tout-redeployer-la-methode-des-tests-de-maillon","Cartographier son système d'information sans tout redéployer : la méthode des tests de maillon","\u002Fcontent-assets\u002F2026-10-12-cartographier-son-systeme-dinformation-sans-tout-redeployer-la-methode-des-tests-de-maillon\u002Fassets\u002Fcover-image.webp","12 octobre 2026",[6203,6227,6228],"architecture","microservices",{"path":6230,"title":6231,"image":6232,"date":6233,"tags":6234},"\u002Fblogs\u002F2026-09-08-structured-concurrency-ou-comment-ne-jamais-fuiter-une-coroutine-coroutines-25","Structured concurrency, ou comment ne jamais fuiter une coroutine : Coroutines (2\u002F5)","\u002Fcontent-assets\u002F2026-09-08-structured-concurrency-ou-comment-ne-jamais-fuiter-une-coroutine-coroutines-25\u002Fassets\u002Fcover-image.webp","8 septembre 2026",[6235,6203,6213],"kotlin",1793011510188]