[{"data":1,"prerenderedAt":3350},["ShallowReactive",2],{"blog-failure-mode-driven-development":3,"blog-surround-failure-mode-driven-development":1693,"blog-related-failure-mode-driven-development":2327},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topics":11,"body":15,"_type":1687,"_id":1688,"_source":1689,"_file":1690,"_stem":1691,"_extension":1692},"\u002Fblog\u002Ffailure-mode-driven-development","blog",false,"","Failure-mode driven development","Sketch what can break and how you recover before you write the happy path. A follow-up to comment-driven development.","2026-07-12T10:00:00+07:00",[12,13,14],"programming","process","reliability",{"type":16,"children":17,"toc":1677},"root",[18,35,40,45,50,59,66,71,76,105,110,128,133,139,144,371,376,382,387,1538,1543,1549,1554,1559,1564,1569,1574,1580,1585,1590,1596,1601,1606,1611,1616,1622,1655,1660,1666,1671],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23,26,33],{"type":24,"value":25},"text","A while back I wrote about ",{"type":19,"tag":27,"props":28,"children":30},"a",{"href":29},"\u002Fblog\u002Fcomment-driven-development",[31],{"type":24,"value":32},"comment-driven development",{"type":24,"value":34},". I still do that: sketch the steps as comments first, then turn them into code when the flow is clear. It keeps me from coding half-formed ideas into a mess.",{"type":19,"tag":20,"props":36,"children":37},{},[38],{"type":24,"value":39},"I also keep shipping the same kind of bug.",{"type":19,"tag":20,"props":41,"children":42},{},[43],{"type":24,"value":44},"The comments look finished. Check stock, take money, send email, done. Then production hits the stuff I never wrote down. Stock vanishes between the check and the write. Payment lands and the library insert dies. The queue is down so the user paid and never gets a receipt.",{"type":19,"tag":20,"props":46,"children":47},{},[48],{"type":24,"value":49},"So I started doing the same sketch habit in the other direction. Before the success path, I write what can break and what I do next. Call it failure-mode driven development if you want a name. Honestly I just call it \"listing the ways this can hurt people\" and then I code.",{"type":19,"tag":51,"props":52,"children":53},"blockquote",{},[54],{"type":19,"tag":20,"props":55,"children":56},{},[57],{"type":24,"value":58},"Same disclaimer as the CDD post: this is a teaching sketch. Ignore SOLID for a minute. Ignore whether PurchaseBook should be five classes. The point is the order of thought, not a production service.",{"type":19,"tag":60,"props":61,"children":63},"h2",{"id":62},"what-counts-as-a-failure-mode",[64],{"type":24,"value":65},"What counts as a failure mode",{"type":19,"tag":20,"props":67,"children":68},{},[69],{"type":24,"value":70},"A failure mode is specific. \"Handle errors\" is not one.",{"type":19,"tag":20,"props":72,"children":73},{},[74],{"type":24,"value":75},"Useful:",{"type":19,"tag":77,"props":78,"children":79},"ul",{},[80,95,100],{"type":19,"tag":81,"props":82,"children":83},"li",{},[84,86,93],{"type":24,"value":85},"Balance already reduced, then ",{"type":19,"tag":87,"props":88,"children":90},"code",{"className":89},[],[91],{"type":24,"value":92},"AddHistory",{"type":24,"value":94}," throws",{"type":19,"tag":81,"props":96,"children":97},{},[98],{"type":24,"value":99},"Book looked available on read, gone at commit",{"type":19,"tag":81,"props":101,"children":102},{},[103],{"type":24,"value":104},"Purchase committed, email queue rejects the message",{"type":19,"tag":20,"props":106,"children":107},{},[108],{"type":24,"value":109},"Useless:",{"type":19,"tag":77,"props":111,"children":112},{},[113,118,123],{"type":19,"tag":81,"props":114,"children":115},{},[116],{"type":24,"value":117},"Something went wrong",{"type":19,"tag":81,"props":119,"children":120},{},[121],{"type":24,"value":122},"Handle exceptions",{"type":19,"tag":81,"props":124,"children":125},{},[126],{"type":24,"value":127},"Be careful with races",{"type":19,"tag":20,"props":129,"children":130},{},[131],{"type":24,"value":132},"If I cannot say what recovery looks like, I do not understand the failure yet. That line sounds a bit preachy even as I type it, but it is still the test I use.",{"type":19,"tag":60,"props":134,"children":136},{"id":135},"sketch-failures-first",[137],{"type":24,"value":138},"Sketch failures first",{"type":19,"tag":20,"props":140,"children":141},{},[142],{"type":24,"value":143},"Same \"purchase a book\" shape as CDD, failures on top:",{"type":19,"tag":145,"props":146,"children":150},"pre",{"className":147,"code":148,"language":149,"meta":7,"style":7},"language-csharp shiki shiki-themes one-dark-pro","\u002F\u002F Purchase a book\n\u002F\u002F\n\u002F\u002F Failure modes (write these first):\n\u002F\u002F - Book unavailable now, or becomes unavailable after the check\n\u002F\u002F - Balance insufficient, or balance changes after the check\n\u002F\u002F - Payment history write fails after balance was reduced\n\u002F\u002F - Library row fails after payment was recorded\n\u002F\u002F - Email queue is down after the purchase is committed\n\u002F\u002F - Partial commit if money and library are not in one transaction\n\u002F\u002F\n\u002F\u002F Recovery \u002F decisions:\n\u002F\u002F - Unavailable or insufficient: fail fast, no side effects\n\u002F\u002F - Balance reduced + payment fails: put money back, or better: one DB transaction\n\u002F\u002F - Payment ok + library fails: reverse payment, or retry library with an outbox\n\u002F\u002F - Purchase committed + email fails: keep purchase, retry email later, do not unwind money\n\u002F\u002F - Money + library in one transaction; email stays async\n\u002F\u002F\n\u002F\u002F Happy path (only after the list above stops being wishful):\n\u002F\u002F - Check availability\n\u002F\u002F - Check balance\n\u002F\u002F - Deduct balance\n\u002F\u002F - Record payment\n\u002F\u002F - Add book to library\n\u002F\u002F - Enqueue confirmation email\n","csharp",[151],{"type":19,"tag":87,"props":152,"children":153},{"__ignoreMap":7},[154,166,175,184,193,202,211,220,229,238,246,255,264,273,282,291,300,308,317,326,335,344,353,362],{"type":19,"tag":155,"props":156,"children":159},"span",{"class":157,"line":158},"line",1,[160],{"type":19,"tag":155,"props":161,"children":163},{"style":162},"--shiki-default:#7F848E;--shiki-default-font-style:italic",[164],{"type":24,"value":165},"\u002F\u002F Purchase a book\n",{"type":19,"tag":155,"props":167,"children":169},{"class":157,"line":168},2,[170],{"type":19,"tag":155,"props":171,"children":172},{"style":162},[173],{"type":24,"value":174},"\u002F\u002F\n",{"type":19,"tag":155,"props":176,"children":178},{"class":157,"line":177},3,[179],{"type":19,"tag":155,"props":180,"children":181},{"style":162},[182],{"type":24,"value":183},"\u002F\u002F Failure modes (write these first):\n",{"type":19,"tag":155,"props":185,"children":187},{"class":157,"line":186},4,[188],{"type":19,"tag":155,"props":189,"children":190},{"style":162},[191],{"type":24,"value":192},"\u002F\u002F - Book unavailable now, or becomes unavailable after the check\n",{"type":19,"tag":155,"props":194,"children":196},{"class":157,"line":195},5,[197],{"type":19,"tag":155,"props":198,"children":199},{"style":162},[200],{"type":24,"value":201},"\u002F\u002F - Balance insufficient, or balance changes after the check\n",{"type":19,"tag":155,"props":203,"children":205},{"class":157,"line":204},6,[206],{"type":19,"tag":155,"props":207,"children":208},{"style":162},[209],{"type":24,"value":210},"\u002F\u002F - Payment history write fails after balance was reduced\n",{"type":19,"tag":155,"props":212,"children":214},{"class":157,"line":213},7,[215],{"type":19,"tag":155,"props":216,"children":217},{"style":162},[218],{"type":24,"value":219},"\u002F\u002F - Library row fails after payment was recorded\n",{"type":19,"tag":155,"props":221,"children":223},{"class":157,"line":222},8,[224],{"type":19,"tag":155,"props":225,"children":226},{"style":162},[227],{"type":24,"value":228},"\u002F\u002F - Email queue is down after the purchase is committed\n",{"type":19,"tag":155,"props":230,"children":232},{"class":157,"line":231},9,[233],{"type":19,"tag":155,"props":234,"children":235},{"style":162},[236],{"type":24,"value":237},"\u002F\u002F - Partial commit if money and library are not in one transaction\n",{"type":19,"tag":155,"props":239,"children":241},{"class":157,"line":240},10,[242],{"type":19,"tag":155,"props":243,"children":244},{"style":162},[245],{"type":24,"value":174},{"type":19,"tag":155,"props":247,"children":249},{"class":157,"line":248},11,[250],{"type":19,"tag":155,"props":251,"children":252},{"style":162},[253],{"type":24,"value":254},"\u002F\u002F Recovery \u002F decisions:\n",{"type":19,"tag":155,"props":256,"children":258},{"class":157,"line":257},12,[259],{"type":19,"tag":155,"props":260,"children":261},{"style":162},[262],{"type":24,"value":263},"\u002F\u002F - Unavailable or insufficient: fail fast, no side effects\n",{"type":19,"tag":155,"props":265,"children":267},{"class":157,"line":266},13,[268],{"type":19,"tag":155,"props":269,"children":270},{"style":162},[271],{"type":24,"value":272},"\u002F\u002F - Balance reduced + payment fails: put money back, or better: one DB transaction\n",{"type":19,"tag":155,"props":274,"children":276},{"class":157,"line":275},14,[277],{"type":19,"tag":155,"props":278,"children":279},{"style":162},[280],{"type":24,"value":281},"\u002F\u002F - Payment ok + library fails: reverse payment, or retry library with an outbox\n",{"type":19,"tag":155,"props":283,"children":285},{"class":157,"line":284},15,[286],{"type":19,"tag":155,"props":287,"children":288},{"style":162},[289],{"type":24,"value":290},"\u002F\u002F - Purchase committed + email fails: keep purchase, retry email later, do not unwind money\n",{"type":19,"tag":155,"props":292,"children":294},{"class":157,"line":293},16,[295],{"type":19,"tag":155,"props":296,"children":297},{"style":162},[298],{"type":24,"value":299},"\u002F\u002F - Money + library in one transaction; email stays async\n",{"type":19,"tag":155,"props":301,"children":303},{"class":157,"line":302},17,[304],{"type":19,"tag":155,"props":305,"children":306},{"style":162},[307],{"type":24,"value":174},{"type":19,"tag":155,"props":309,"children":311},{"class":157,"line":310},18,[312],{"type":19,"tag":155,"props":313,"children":314},{"style":162},[315],{"type":24,"value":316},"\u002F\u002F Happy path (only after the list above stops being wishful):\n",{"type":19,"tag":155,"props":318,"children":320},{"class":157,"line":319},19,[321],{"type":19,"tag":155,"props":322,"children":323},{"style":162},[324],{"type":24,"value":325},"\u002F\u002F - Check availability\n",{"type":19,"tag":155,"props":327,"children":329},{"class":157,"line":328},20,[330],{"type":19,"tag":155,"props":331,"children":332},{"style":162},[333],{"type":24,"value":334},"\u002F\u002F - Check balance\n",{"type":19,"tag":155,"props":336,"children":338},{"class":157,"line":337},21,[339],{"type":19,"tag":155,"props":340,"children":341},{"style":162},[342],{"type":24,"value":343},"\u002F\u002F - Deduct balance\n",{"type":19,"tag":155,"props":345,"children":347},{"class":157,"line":346},22,[348],{"type":19,"tag":155,"props":349,"children":350},{"style":162},[351],{"type":24,"value":352},"\u002F\u002F - Record payment\n",{"type":19,"tag":155,"props":354,"children":356},{"class":157,"line":355},23,[357],{"type":19,"tag":155,"props":358,"children":359},{"style":162},[360],{"type":24,"value":361},"\u002F\u002F - Add book to library\n",{"type":19,"tag":155,"props":363,"children":365},{"class":157,"line":364},24,[366],{"type":19,"tag":155,"props":367,"children":368},{"style":162},[369],{"type":24,"value":370},"\u002F\u002F - Enqueue confirmation email\n",{"type":19,"tag":20,"props":372,"children":373},{},[374],{"type":24,"value":375},"Happy path is almost the same list as before. The difference is I already decided where atomicity lives, and which failures should slap the user versus which ones support can clean up later.",{"type":19,"tag":60,"props":377,"children":379},{"id":378},"then-shape-the-code-around-that",[380],{"type":24,"value":381},"Then shape the code around that",{"type":19,"tag":20,"props":383,"children":384},{},[385],{"type":24,"value":386},"I still start with comments. The first real code is often the transaction boundary and the ugly branches, not the pretty email template.",{"type":19,"tag":145,"props":388,"children":390},{"className":147,"code":389,"language":149,"meta":7,"style":7},"\u002F\u002F Purchase a book\npublic async Task PurchaseBook(Book book)\n{\n    \u002F\u002F Money + ownership together. Email is outside this transaction on purpose.\n    await using var tx = await _dbContext.Database.BeginTransactionAsync();\n\n    try\n    {\n        \u002F\u002F Unavailable (including races under concurrency)\n        if (!_bookService.IsAvailable(book))\n        {\n            throw new Exception($\"{book.Title} is currently unavailable\");\n        }\n\n        \u002F\u002F Insufficient funds\n        if (!_userService.HasEnoughBalanceToPurchase(book.Price))\n        {\n            throw new Exception(\"You don't have enough balance\");\n        }\n\n        _userService.ReduceBalance(book.Price);\n\n        var payment = _paymentService.AddHistory(new Payment\n        {\n            Status = PaymentStatus.Paid,\n            Amount = book.Price\n        });\n\n        _libraryService.Add(new Library\n        {\n            Book = book,\n            Payment = payment\n        });\n\n        await _dbContext.SaveChangesAsync();\n        await tx.CommitAsync();\n\n        \u002F\u002F Queue can die after commit. Purchase stays; delivery retries.\n        try\n        {\n            var emailBody = _emailRenderService.Render(\n                EmailTemplate.PurchaseConfirmation,\n                payment);\n\n            _emailQueueService.Add(new EmailQueue\n            {\n                Recipient = _userService.GetEmail(),\n                Subject = \"Thank you for your purchase\",\n                Body = emailBody,\n            });\n        }\n        catch (Exception ex)\n        {\n            \u002F\u002F In real code: log, outbox, alert. Here: do not roll back money for an email.\n            Console.WriteLine($\"Purchase committed but email failed: {ex.Message}\");\n        }\n    }\n    catch\n    {\n        await tx.RollbackAsync();\n        throw;\n    }\n}\n",[391],{"type":19,"tag":87,"props":392,"children":393},{"__ignoreMap":7},[394,401,448,456,464,528,537,545,553,561,607,615,676,684,691,699,749,756,784,791,798,835,842,882,889,921,947,956,964,991,999,1020,1038,1046,1054,1080,1106,1114,1123,1132,1140,1177,1199,1212,1220,1246,1255,1287,1309,1330,1339,1347,1373,1381,1390,1448,1456,1465,1474,1482,1507,1521,1529],{"type":19,"tag":155,"props":395,"children":396},{"class":157,"line":158},[397],{"type":19,"tag":155,"props":398,"children":399},{"style":162},[400],{"type":24,"value":165},{"type":19,"tag":155,"props":402,"children":403},{"class":157,"line":168},[404,410,415,421,427,433,438,443],{"type":19,"tag":155,"props":405,"children":407},{"style":406},"--shiki-default:#C678DD",[408],{"type":24,"value":409},"public",{"type":19,"tag":155,"props":411,"children":412},{"style":406},[413],{"type":24,"value":414}," async",{"type":19,"tag":155,"props":416,"children":418},{"style":417},"--shiki-default:#E5C07B",[419],{"type":24,"value":420}," Task",{"type":19,"tag":155,"props":422,"children":424},{"style":423},"--shiki-default:#61AFEF",[425],{"type":24,"value":426}," PurchaseBook",{"type":19,"tag":155,"props":428,"children":430},{"style":429},"--shiki-default:#ABB2BF",[431],{"type":24,"value":432},"(",{"type":19,"tag":155,"props":434,"children":435},{"style":417},[436],{"type":24,"value":437},"Book",{"type":19,"tag":155,"props":439,"children":440},{"style":417},[441],{"type":24,"value":442}," book",{"type":19,"tag":155,"props":444,"children":445},{"style":429},[446],{"type":24,"value":447},")\n",{"type":19,"tag":155,"props":449,"children":450},{"class":157,"line":177},[451],{"type":19,"tag":155,"props":452,"children":453},{"style":429},[454],{"type":24,"value":455},"{\n",{"type":19,"tag":155,"props":457,"children":458},{"class":157,"line":186},[459],{"type":19,"tag":155,"props":460,"children":461},{"style":162},[462],{"type":24,"value":463},"    \u002F\u002F Money + ownership together. Email is outside this transaction on purpose.\n",{"type":19,"tag":155,"props":465,"children":466},{"class":157,"line":195},[467,472,477,482,488,494,499,504,509,514,518,523],{"type":19,"tag":155,"props":468,"children":469},{"style":429},[470],{"type":24,"value":471},"    await ",{"type":19,"tag":155,"props":473,"children":474},{"style":406},[475],{"type":24,"value":476},"using",{"type":19,"tag":155,"props":478,"children":479},{"style":406},[480],{"type":24,"value":481}," var",{"type":19,"tag":155,"props":483,"children":485},{"style":484},"--shiki-default:#E06C75",[486],{"type":24,"value":487}," tx",{"type":19,"tag":155,"props":489,"children":491},{"style":490},"--shiki-default:#56B6C2",[492],{"type":24,"value":493}," =",{"type":19,"tag":155,"props":495,"children":496},{"style":429},[497],{"type":24,"value":498}," await ",{"type":19,"tag":155,"props":500,"children":501},{"style":417},[502],{"type":24,"value":503},"_dbContext",{"type":19,"tag":155,"props":505,"children":506},{"style":429},[507],{"type":24,"value":508},".",{"type":19,"tag":155,"props":510,"children":511},{"style":417},[512],{"type":24,"value":513},"Database",{"type":19,"tag":155,"props":515,"children":516},{"style":429},[517],{"type":24,"value":508},{"type":19,"tag":155,"props":519,"children":520},{"style":423},[521],{"type":24,"value":522},"BeginTransactionAsync",{"type":19,"tag":155,"props":524,"children":525},{"style":429},[526],{"type":24,"value":527},"();\n",{"type":19,"tag":155,"props":529,"children":530},{"class":157,"line":204},[531],{"type":19,"tag":155,"props":532,"children":534},{"emptyLinePlaceholder":533},true,[535],{"type":24,"value":536},"\n",{"type":19,"tag":155,"props":538,"children":539},{"class":157,"line":213},[540],{"type":19,"tag":155,"props":541,"children":542},{"style":406},[543],{"type":24,"value":544},"    try\n",{"type":19,"tag":155,"props":546,"children":547},{"class":157,"line":222},[548],{"type":19,"tag":155,"props":549,"children":550},{"style":429},[551],{"type":24,"value":552},"    {\n",{"type":19,"tag":155,"props":554,"children":555},{"class":157,"line":231},[556],{"type":19,"tag":155,"props":557,"children":558},{"style":162},[559],{"type":24,"value":560},"        \u002F\u002F Unavailable (including races under concurrency)\n",{"type":19,"tag":155,"props":562,"children":563},{"class":157,"line":240},[564,569,574,579,584,588,593,597,602],{"type":19,"tag":155,"props":565,"children":566},{"style":406},[567],{"type":24,"value":568},"        if",{"type":19,"tag":155,"props":570,"children":571},{"style":429},[572],{"type":24,"value":573}," (",{"type":19,"tag":155,"props":575,"children":576},{"style":490},[577],{"type":24,"value":578},"!",{"type":19,"tag":155,"props":580,"children":581},{"style":417},[582],{"type":24,"value":583},"_bookService",{"type":19,"tag":155,"props":585,"children":586},{"style":429},[587],{"type":24,"value":508},{"type":19,"tag":155,"props":589,"children":590},{"style":423},[591],{"type":24,"value":592},"IsAvailable",{"type":19,"tag":155,"props":594,"children":595},{"style":429},[596],{"type":24,"value":432},{"type":19,"tag":155,"props":598,"children":599},{"style":484},[600],{"type":24,"value":601},"book",{"type":19,"tag":155,"props":603,"children":604},{"style":429},[605],{"type":24,"value":606},"))\n",{"type":19,"tag":155,"props":608,"children":609},{"class":157,"line":248},[610],{"type":19,"tag":155,"props":611,"children":612},{"style":429},[613],{"type":24,"value":614},"        {\n",{"type":19,"tag":155,"props":616,"children":617},{"class":157,"line":257},[618,623,628,633,637,643,648,652,656,661,666,671],{"type":19,"tag":155,"props":619,"children":620},{"style":406},[621],{"type":24,"value":622},"            throw",{"type":19,"tag":155,"props":624,"children":625},{"style":429},[626],{"type":24,"value":627}," new ",{"type":19,"tag":155,"props":629,"children":630},{"style":417},[631],{"type":24,"value":632},"Exception",{"type":19,"tag":155,"props":634,"children":635},{"style":429},[636],{"type":24,"value":432},{"type":19,"tag":155,"props":638,"children":640},{"style":639},"--shiki-default:#98C379",[641],{"type":24,"value":642},"$\"",{"type":19,"tag":155,"props":644,"children":645},{"style":429},[646],{"type":24,"value":647},"{",{"type":19,"tag":155,"props":649,"children":650},{"style":417},[651],{"type":24,"value":601},{"type":19,"tag":155,"props":653,"children":654},{"style":429},[655],{"type":24,"value":508},{"type":19,"tag":155,"props":657,"children":658},{"style":417},[659],{"type":24,"value":660},"Title",{"type":19,"tag":155,"props":662,"children":663},{"style":429},[664],{"type":24,"value":665},"}",{"type":19,"tag":155,"props":667,"children":668},{"style":639},[669],{"type":24,"value":670}," is currently unavailable\"",{"type":19,"tag":155,"props":672,"children":673},{"style":429},[674],{"type":24,"value":675},");\n",{"type":19,"tag":155,"props":677,"children":678},{"class":157,"line":266},[679],{"type":19,"tag":155,"props":680,"children":681},{"style":429},[682],{"type":24,"value":683},"        }\n",{"type":19,"tag":155,"props":685,"children":686},{"class":157,"line":275},[687],{"type":19,"tag":155,"props":688,"children":689},{"emptyLinePlaceholder":533},[690],{"type":24,"value":536},{"type":19,"tag":155,"props":692,"children":693},{"class":157,"line":284},[694],{"type":19,"tag":155,"props":695,"children":696},{"style":162},[697],{"type":24,"value":698},"        \u002F\u002F Insufficient funds\n",{"type":19,"tag":155,"props":700,"children":701},{"class":157,"line":293},[702,706,710,714,719,723,728,732,736,740,745],{"type":19,"tag":155,"props":703,"children":704},{"style":406},[705],{"type":24,"value":568},{"type":19,"tag":155,"props":707,"children":708},{"style":429},[709],{"type":24,"value":573},{"type":19,"tag":155,"props":711,"children":712},{"style":490},[713],{"type":24,"value":578},{"type":19,"tag":155,"props":715,"children":716},{"style":417},[717],{"type":24,"value":718},"_userService",{"type":19,"tag":155,"props":720,"children":721},{"style":429},[722],{"type":24,"value":508},{"type":19,"tag":155,"props":724,"children":725},{"style":423},[726],{"type":24,"value":727},"HasEnoughBalanceToPurchase",{"type":19,"tag":155,"props":729,"children":730},{"style":429},[731],{"type":24,"value":432},{"type":19,"tag":155,"props":733,"children":734},{"style":417},[735],{"type":24,"value":601},{"type":19,"tag":155,"props":737,"children":738},{"style":429},[739],{"type":24,"value":508},{"type":19,"tag":155,"props":741,"children":742},{"style":417},[743],{"type":24,"value":744},"Price",{"type":19,"tag":155,"props":746,"children":747},{"style":429},[748],{"type":24,"value":606},{"type":19,"tag":155,"props":750,"children":751},{"class":157,"line":302},[752],{"type":19,"tag":155,"props":753,"children":754},{"style":429},[755],{"type":24,"value":614},{"type":19,"tag":155,"props":757,"children":758},{"class":157,"line":310},[759,763,767,771,775,780],{"type":19,"tag":155,"props":760,"children":761},{"style":406},[762],{"type":24,"value":622},{"type":19,"tag":155,"props":764,"children":765},{"style":429},[766],{"type":24,"value":627},{"type":19,"tag":155,"props":768,"children":769},{"style":417},[770],{"type":24,"value":632},{"type":19,"tag":155,"props":772,"children":773},{"style":429},[774],{"type":24,"value":432},{"type":19,"tag":155,"props":776,"children":777},{"style":639},[778],{"type":24,"value":779},"\"You don't have enough balance\"",{"type":19,"tag":155,"props":781,"children":782},{"style":429},[783],{"type":24,"value":675},{"type":19,"tag":155,"props":785,"children":786},{"class":157,"line":319},[787],{"type":19,"tag":155,"props":788,"children":789},{"style":429},[790],{"type":24,"value":683},{"type":19,"tag":155,"props":792,"children":793},{"class":157,"line":328},[794],{"type":19,"tag":155,"props":795,"children":796},{"emptyLinePlaceholder":533},[797],{"type":24,"value":536},{"type":19,"tag":155,"props":799,"children":800},{"class":157,"line":337},[801,806,810,815,819,823,827,831],{"type":19,"tag":155,"props":802,"children":803},{"style":417},[804],{"type":24,"value":805},"        _userService",{"type":19,"tag":155,"props":807,"children":808},{"style":429},[809],{"type":24,"value":508},{"type":19,"tag":155,"props":811,"children":812},{"style":423},[813],{"type":24,"value":814},"ReduceBalance",{"type":19,"tag":155,"props":816,"children":817},{"style":429},[818],{"type":24,"value":432},{"type":19,"tag":155,"props":820,"children":821},{"style":417},[822],{"type":24,"value":601},{"type":19,"tag":155,"props":824,"children":825},{"style":429},[826],{"type":24,"value":508},{"type":19,"tag":155,"props":828,"children":829},{"style":417},[830],{"type":24,"value":744},{"type":19,"tag":155,"props":832,"children":833},{"style":429},[834],{"type":24,"value":675},{"type":19,"tag":155,"props":836,"children":837},{"class":157,"line":346},[838],{"type":19,"tag":155,"props":839,"children":840},{"emptyLinePlaceholder":533},[841],{"type":24,"value":536},{"type":19,"tag":155,"props":843,"children":844},{"class":157,"line":355},[845,850,855,859,864,868,872,877],{"type":19,"tag":155,"props":846,"children":847},{"style":406},[848],{"type":24,"value":849},"        var",{"type":19,"tag":155,"props":851,"children":852},{"style":484},[853],{"type":24,"value":854}," payment",{"type":19,"tag":155,"props":856,"children":857},{"style":490},[858],{"type":24,"value":493},{"type":19,"tag":155,"props":860,"children":861},{"style":417},[862],{"type":24,"value":863}," _paymentService",{"type":19,"tag":155,"props":865,"children":866},{"style":429},[867],{"type":24,"value":508},{"type":19,"tag":155,"props":869,"children":870},{"style":423},[871],{"type":24,"value":92},{"type":19,"tag":155,"props":873,"children":874},{"style":429},[875],{"type":24,"value":876},"(new ",{"type":19,"tag":155,"props":878,"children":879},{"style":417},[880],{"type":24,"value":881},"Payment\n",{"type":19,"tag":155,"props":883,"children":884},{"class":157,"line":364},[885],{"type":19,"tag":155,"props":886,"children":887},{"style":429},[888],{"type":24,"value":614},{"type":19,"tag":155,"props":890,"children":892},{"class":157,"line":891},25,[893,898,902,907,911,916],{"type":19,"tag":155,"props":894,"children":895},{"style":484},[896],{"type":24,"value":897},"            Status",{"type":19,"tag":155,"props":899,"children":900},{"style":490},[901],{"type":24,"value":493},{"type":19,"tag":155,"props":903,"children":904},{"style":417},[905],{"type":24,"value":906}," PaymentStatus",{"type":19,"tag":155,"props":908,"children":909},{"style":429},[910],{"type":24,"value":508},{"type":19,"tag":155,"props":912,"children":913},{"style":417},[914],{"type":24,"value":915},"Paid",{"type":19,"tag":155,"props":917,"children":918},{"style":429},[919],{"type":24,"value":920},",\n",{"type":19,"tag":155,"props":922,"children":924},{"class":157,"line":923},26,[925,930,934,938,942],{"type":19,"tag":155,"props":926,"children":927},{"style":484},[928],{"type":24,"value":929},"            Amount",{"type":19,"tag":155,"props":931,"children":932},{"style":490},[933],{"type":24,"value":493},{"type":19,"tag":155,"props":935,"children":936},{"style":417},[937],{"type":24,"value":442},{"type":19,"tag":155,"props":939,"children":940},{"style":429},[941],{"type":24,"value":508},{"type":19,"tag":155,"props":943,"children":944},{"style":417},[945],{"type":24,"value":946},"Price\n",{"type":19,"tag":155,"props":948,"children":950},{"class":157,"line":949},27,[951],{"type":19,"tag":155,"props":952,"children":953},{"style":429},[954],{"type":24,"value":955},"        });\n",{"type":19,"tag":155,"props":957,"children":959},{"class":157,"line":958},28,[960],{"type":19,"tag":155,"props":961,"children":962},{"emptyLinePlaceholder":533},[963],{"type":24,"value":536},{"type":19,"tag":155,"props":965,"children":967},{"class":157,"line":966},29,[968,973,977,982,986],{"type":19,"tag":155,"props":969,"children":970},{"style":417},[971],{"type":24,"value":972},"        _libraryService",{"type":19,"tag":155,"props":974,"children":975},{"style":429},[976],{"type":24,"value":508},{"type":19,"tag":155,"props":978,"children":979},{"style":423},[980],{"type":24,"value":981},"Add",{"type":19,"tag":155,"props":983,"children":984},{"style":429},[985],{"type":24,"value":876},{"type":19,"tag":155,"props":987,"children":988},{"style":417},[989],{"type":24,"value":990},"Library\n",{"type":19,"tag":155,"props":992,"children":994},{"class":157,"line":993},30,[995],{"type":19,"tag":155,"props":996,"children":997},{"style":429},[998],{"type":24,"value":614},{"type":19,"tag":155,"props":1000,"children":1002},{"class":157,"line":1001},31,[1003,1008,1012,1016],{"type":19,"tag":155,"props":1004,"children":1005},{"style":484},[1006],{"type":24,"value":1007},"            Book",{"type":19,"tag":155,"props":1009,"children":1010},{"style":490},[1011],{"type":24,"value":493},{"type":19,"tag":155,"props":1013,"children":1014},{"style":484},[1015],{"type":24,"value":442},{"type":19,"tag":155,"props":1017,"children":1018},{"style":429},[1019],{"type":24,"value":920},{"type":19,"tag":155,"props":1021,"children":1023},{"class":157,"line":1022},32,[1024,1029,1033],{"type":19,"tag":155,"props":1025,"children":1026},{"style":484},[1027],{"type":24,"value":1028},"            Payment",{"type":19,"tag":155,"props":1030,"children":1031},{"style":490},[1032],{"type":24,"value":493},{"type":19,"tag":155,"props":1034,"children":1035},{"style":484},[1036],{"type":24,"value":1037}," payment\n",{"type":19,"tag":155,"props":1039,"children":1041},{"class":157,"line":1040},33,[1042],{"type":19,"tag":155,"props":1043,"children":1044},{"style":429},[1045],{"type":24,"value":955},{"type":19,"tag":155,"props":1047,"children":1049},{"class":157,"line":1048},34,[1050],{"type":19,"tag":155,"props":1051,"children":1052},{"emptyLinePlaceholder":533},[1053],{"type":24,"value":536},{"type":19,"tag":155,"props":1055,"children":1057},{"class":157,"line":1056},35,[1058,1063,1067,1071,1076],{"type":19,"tag":155,"props":1059,"children":1060},{"style":429},[1061],{"type":24,"value":1062},"        await ",{"type":19,"tag":155,"props":1064,"children":1065},{"style":417},[1066],{"type":24,"value":503},{"type":19,"tag":155,"props":1068,"children":1069},{"style":429},[1070],{"type":24,"value":508},{"type":19,"tag":155,"props":1072,"children":1073},{"style":423},[1074],{"type":24,"value":1075},"SaveChangesAsync",{"type":19,"tag":155,"props":1077,"children":1078},{"style":429},[1079],{"type":24,"value":527},{"type":19,"tag":155,"props":1081,"children":1083},{"class":157,"line":1082},36,[1084,1088,1093,1097,1102],{"type":19,"tag":155,"props":1085,"children":1086},{"style":429},[1087],{"type":24,"value":1062},{"type":19,"tag":155,"props":1089,"children":1090},{"style":417},[1091],{"type":24,"value":1092},"tx",{"type":19,"tag":155,"props":1094,"children":1095},{"style":429},[1096],{"type":24,"value":508},{"type":19,"tag":155,"props":1098,"children":1099},{"style":423},[1100],{"type":24,"value":1101},"CommitAsync",{"type":19,"tag":155,"props":1103,"children":1104},{"style":429},[1105],{"type":24,"value":527},{"type":19,"tag":155,"props":1107,"children":1109},{"class":157,"line":1108},37,[1110],{"type":19,"tag":155,"props":1111,"children":1112},{"emptyLinePlaceholder":533},[1113],{"type":24,"value":536},{"type":19,"tag":155,"props":1115,"children":1117},{"class":157,"line":1116},38,[1118],{"type":19,"tag":155,"props":1119,"children":1120},{"style":162},[1121],{"type":24,"value":1122},"        \u002F\u002F Queue can die after commit. Purchase stays; delivery retries.\n",{"type":19,"tag":155,"props":1124,"children":1126},{"class":157,"line":1125},39,[1127],{"type":19,"tag":155,"props":1128,"children":1129},{"style":406},[1130],{"type":24,"value":1131},"        try\n",{"type":19,"tag":155,"props":1133,"children":1135},{"class":157,"line":1134},40,[1136],{"type":19,"tag":155,"props":1137,"children":1138},{"style":429},[1139],{"type":24,"value":614},{"type":19,"tag":155,"props":1141,"children":1143},{"class":157,"line":1142},41,[1144,1149,1154,1158,1163,1167,1172],{"type":19,"tag":155,"props":1145,"children":1146},{"style":406},[1147],{"type":24,"value":1148},"            var",{"type":19,"tag":155,"props":1150,"children":1151},{"style":484},[1152],{"type":24,"value":1153}," emailBody",{"type":19,"tag":155,"props":1155,"children":1156},{"style":490},[1157],{"type":24,"value":493},{"type":19,"tag":155,"props":1159,"children":1160},{"style":417},[1161],{"type":24,"value":1162}," _emailRenderService",{"type":19,"tag":155,"props":1164,"children":1165},{"style":429},[1166],{"type":24,"value":508},{"type":19,"tag":155,"props":1168,"children":1169},{"style":423},[1170],{"type":24,"value":1171},"Render",{"type":19,"tag":155,"props":1173,"children":1174},{"style":429},[1175],{"type":24,"value":1176},"(\n",{"type":19,"tag":155,"props":1178,"children":1180},{"class":157,"line":1179},42,[1181,1186,1190,1195],{"type":19,"tag":155,"props":1182,"children":1183},{"style":417},[1184],{"type":24,"value":1185},"                EmailTemplate",{"type":19,"tag":155,"props":1187,"children":1188},{"style":429},[1189],{"type":24,"value":508},{"type":19,"tag":155,"props":1191,"children":1192},{"style":417},[1193],{"type":24,"value":1194},"PurchaseConfirmation",{"type":19,"tag":155,"props":1196,"children":1197},{"style":429},[1198],{"type":24,"value":920},{"type":19,"tag":155,"props":1200,"children":1202},{"class":157,"line":1201},43,[1203,1208],{"type":19,"tag":155,"props":1204,"children":1205},{"style":484},[1206],{"type":24,"value":1207},"                payment",{"type":19,"tag":155,"props":1209,"children":1210},{"style":429},[1211],{"type":24,"value":675},{"type":19,"tag":155,"props":1213,"children":1215},{"class":157,"line":1214},44,[1216],{"type":19,"tag":155,"props":1217,"children":1218},{"emptyLinePlaceholder":533},[1219],{"type":24,"value":536},{"type":19,"tag":155,"props":1221,"children":1223},{"class":157,"line":1222},45,[1224,1229,1233,1237,1241],{"type":19,"tag":155,"props":1225,"children":1226},{"style":417},[1227],{"type":24,"value":1228},"            _emailQueueService",{"type":19,"tag":155,"props":1230,"children":1231},{"style":429},[1232],{"type":24,"value":508},{"type":19,"tag":155,"props":1234,"children":1235},{"style":423},[1236],{"type":24,"value":981},{"type":19,"tag":155,"props":1238,"children":1239},{"style":429},[1240],{"type":24,"value":876},{"type":19,"tag":155,"props":1242,"children":1243},{"style":417},[1244],{"type":24,"value":1245},"EmailQueue\n",{"type":19,"tag":155,"props":1247,"children":1249},{"class":157,"line":1248},46,[1250],{"type":19,"tag":155,"props":1251,"children":1252},{"style":429},[1253],{"type":24,"value":1254},"            {\n",{"type":19,"tag":155,"props":1256,"children":1258},{"class":157,"line":1257},47,[1259,1264,1268,1273,1277,1282],{"type":19,"tag":155,"props":1260,"children":1261},{"style":484},[1262],{"type":24,"value":1263},"                Recipient",{"type":19,"tag":155,"props":1265,"children":1266},{"style":490},[1267],{"type":24,"value":493},{"type":19,"tag":155,"props":1269,"children":1270},{"style":417},[1271],{"type":24,"value":1272}," _userService",{"type":19,"tag":155,"props":1274,"children":1275},{"style":429},[1276],{"type":24,"value":508},{"type":19,"tag":155,"props":1278,"children":1279},{"style":423},[1280],{"type":24,"value":1281},"GetEmail",{"type":19,"tag":155,"props":1283,"children":1284},{"style":429},[1285],{"type":24,"value":1286},"(),\n",{"type":19,"tag":155,"props":1288,"children":1290},{"class":157,"line":1289},48,[1291,1296,1300,1305],{"type":19,"tag":155,"props":1292,"children":1293},{"style":484},[1294],{"type":24,"value":1295},"                Subject",{"type":19,"tag":155,"props":1297,"children":1298},{"style":490},[1299],{"type":24,"value":493},{"type":19,"tag":155,"props":1301,"children":1302},{"style":639},[1303],{"type":24,"value":1304}," \"Thank you for your purchase\"",{"type":19,"tag":155,"props":1306,"children":1307},{"style":429},[1308],{"type":24,"value":920},{"type":19,"tag":155,"props":1310,"children":1312},{"class":157,"line":1311},49,[1313,1318,1322,1326],{"type":19,"tag":155,"props":1314,"children":1315},{"style":484},[1316],{"type":24,"value":1317},"                Body",{"type":19,"tag":155,"props":1319,"children":1320},{"style":490},[1321],{"type":24,"value":493},{"type":19,"tag":155,"props":1323,"children":1324},{"style":484},[1325],{"type":24,"value":1153},{"type":19,"tag":155,"props":1327,"children":1328},{"style":429},[1329],{"type":24,"value":920},{"type":19,"tag":155,"props":1331,"children":1333},{"class":157,"line":1332},50,[1334],{"type":19,"tag":155,"props":1335,"children":1336},{"style":429},[1337],{"type":24,"value":1338},"            });\n",{"type":19,"tag":155,"props":1340,"children":1342},{"class":157,"line":1341},51,[1343],{"type":19,"tag":155,"props":1344,"children":1345},{"style":429},[1346],{"type":24,"value":683},{"type":19,"tag":155,"props":1348,"children":1350},{"class":157,"line":1349},52,[1351,1356,1360,1364,1369],{"type":19,"tag":155,"props":1352,"children":1353},{"style":406},[1354],{"type":24,"value":1355},"        catch",{"type":19,"tag":155,"props":1357,"children":1358},{"style":429},[1359],{"type":24,"value":573},{"type":19,"tag":155,"props":1361,"children":1362},{"style":417},[1363],{"type":24,"value":632},{"type":19,"tag":155,"props":1365,"children":1366},{"style":484},[1367],{"type":24,"value":1368}," ex",{"type":19,"tag":155,"props":1370,"children":1371},{"style":429},[1372],{"type":24,"value":447},{"type":19,"tag":155,"props":1374,"children":1376},{"class":157,"line":1375},53,[1377],{"type":19,"tag":155,"props":1378,"children":1379},{"style":429},[1380],{"type":24,"value":614},{"type":19,"tag":155,"props":1382,"children":1384},{"class":157,"line":1383},54,[1385],{"type":19,"tag":155,"props":1386,"children":1387},{"style":162},[1388],{"type":24,"value":1389},"            \u002F\u002F In real code: log, outbox, alert. Here: do not roll back money for an email.\n",{"type":19,"tag":155,"props":1391,"children":1393},{"class":157,"line":1392},55,[1394,1399,1403,1408,1412,1417,1421,1426,1430,1435,1439,1444],{"type":19,"tag":155,"props":1395,"children":1396},{"style":417},[1397],{"type":24,"value":1398},"            Console",{"type":19,"tag":155,"props":1400,"children":1401},{"style":429},[1402],{"type":24,"value":508},{"type":19,"tag":155,"props":1404,"children":1405},{"style":423},[1406],{"type":24,"value":1407},"WriteLine",{"type":19,"tag":155,"props":1409,"children":1410},{"style":429},[1411],{"type":24,"value":432},{"type":19,"tag":155,"props":1413,"children":1414},{"style":639},[1415],{"type":24,"value":1416},"$\"Purchase committed but email failed: ",{"type":19,"tag":155,"props":1418,"children":1419},{"style":429},[1420],{"type":24,"value":647},{"type":19,"tag":155,"props":1422,"children":1423},{"style":417},[1424],{"type":24,"value":1425},"ex",{"type":19,"tag":155,"props":1427,"children":1428},{"style":429},[1429],{"type":24,"value":508},{"type":19,"tag":155,"props":1431,"children":1432},{"style":417},[1433],{"type":24,"value":1434},"Message",{"type":19,"tag":155,"props":1436,"children":1437},{"style":429},[1438],{"type":24,"value":665},{"type":19,"tag":155,"props":1440,"children":1441},{"style":639},[1442],{"type":24,"value":1443},"\"",{"type":19,"tag":155,"props":1445,"children":1446},{"style":429},[1447],{"type":24,"value":675},{"type":19,"tag":155,"props":1449,"children":1451},{"class":157,"line":1450},56,[1452],{"type":19,"tag":155,"props":1453,"children":1454},{"style":429},[1455],{"type":24,"value":683},{"type":19,"tag":155,"props":1457,"children":1459},{"class":157,"line":1458},57,[1460],{"type":19,"tag":155,"props":1461,"children":1462},{"style":429},[1463],{"type":24,"value":1464},"    }\n",{"type":19,"tag":155,"props":1466,"children":1468},{"class":157,"line":1467},58,[1469],{"type":19,"tag":155,"props":1470,"children":1471},{"style":406},[1472],{"type":24,"value":1473},"    catch\n",{"type":19,"tag":155,"props":1475,"children":1477},{"class":157,"line":1476},59,[1478],{"type":19,"tag":155,"props":1479,"children":1480},{"style":429},[1481],{"type":24,"value":552},{"type":19,"tag":155,"props":1483,"children":1485},{"class":157,"line":1484},60,[1486,1490,1494,1498,1503],{"type":19,"tag":155,"props":1487,"children":1488},{"style":429},[1489],{"type":24,"value":1062},{"type":19,"tag":155,"props":1491,"children":1492},{"style":417},[1493],{"type":24,"value":1092},{"type":19,"tag":155,"props":1495,"children":1496},{"style":429},[1497],{"type":24,"value":508},{"type":19,"tag":155,"props":1499,"children":1500},{"style":423},[1501],{"type":24,"value":1502},"RollbackAsync",{"type":19,"tag":155,"props":1504,"children":1505},{"style":429},[1506],{"type":24,"value":527},{"type":19,"tag":155,"props":1508,"children":1510},{"class":157,"line":1509},61,[1511,1516],{"type":19,"tag":155,"props":1512,"children":1513},{"style":406},[1514],{"type":24,"value":1515},"        throw",{"type":19,"tag":155,"props":1517,"children":1518},{"style":429},[1519],{"type":24,"value":1520},";\n",{"type":19,"tag":155,"props":1522,"children":1524},{"class":157,"line":1523},62,[1525],{"type":19,"tag":155,"props":1526,"children":1527},{"style":429},[1528],{"type":24,"value":1464},{"type":19,"tag":155,"props":1530,"children":1532},{"class":157,"line":1531},63,[1533],{"type":19,"tag":155,"props":1534,"children":1535},{"style":429},[1536],{"type":24,"value":1537},"}\n",{"type":19,"tag":20,"props":1539,"children":1540},{},[1541],{"type":24,"value":1542},"Still one fat method on purpose, same spirit as the CDD demo. Production code would split this. The lesson is not \"ship a god method.\" The lesson is: you already knew email is allowed to fail after money moved, so you did not put the queue call inside the money transaction and then invent panic at 2am.",{"type":19,"tag":60,"props":1544,"children":1546},{"id":1545},"how-i-actually-do-it-on-a-ticket",[1547],{"type":24,"value":1548},"How I actually do it on a ticket",{"type":19,"tag":20,"props":1550,"children":1551},{},[1552],{"type":24,"value":1553},"I name the feature in one line. Purchase a book. Export a report. Apply a coupon.",{"type":19,"tag":20,"props":1555,"children":1556},{},[1557],{"type":24,"value":1558},"Then I spend a few minutes only on failure modes. Sticky notes, comments, whatever. No \"real\" code yet. For each mode I pick roughly one of: fail fast, retry, compensate, or ignore and measure.",{"type":19,"tag":20,"props":1560,"children":1561},{},[1562],{"type":24,"value":1563},"I draw the all-or-nothing boundary next. Usually a database transaction. Sometimes a saga if the world is worse than that. I write that decision above the happy path so I cannot forget it when I am deep in autocomplete.",{"type":19,"tag":20,"props":1565,"children":1566},{},[1567],{"type":24,"value":1568},"Only then do I fill the sunny steps with CDD-style comments and implement.",{"type":19,"tag":20,"props":1570,"children":1571},{},[1572],{"type":24,"value":1573},"If the failure list is three vague bullets, I dig more. Real money or data flows always have more ways to die than I want to admit on a Monday.",{"type":19,"tag":60,"props":1575,"children":1577},{"id":1576},"when-not-to-bother",[1578],{"type":24,"value":1579},"When not to bother",{"type":19,"tag":20,"props":1581,"children":1582},{},[1583],{"type":24,"value":1584},"This is not a 40 page threat model for a script that renames files. It is not \"write every catch before lunch.\" A local PowerShell helper does not need an outbox.",{"type":19,"tag":20,"props":1586,"children":1587},{},[1588],{"type":24,"value":1589},"Match the depth to the blast radius. If it moves money, deletes data, or sends the only copy of a receipt, do the list. If it does not, stop overthinking and ship.",{"type":19,"tag":60,"props":1591,"children":1593},{"id":1592},"cdd-and-this-together",[1594],{"type":24,"value":1595},"CDD and this, together",{"type":19,"tag":20,"props":1597,"children":1598},{},[1599],{"type":24,"value":1600},"CDD answers: what are the steps when everything works?",{"type":19,"tag":20,"props":1602,"children":1603},{},[1604],{"type":24,"value":1605},"This answers: what are the steps when something does not?",{"type":19,"tag":20,"props":1607,"children":1608},{},[1609],{"type":24,"value":1610},"I use both. CDD stops me from coding fog. The failure list stops me from shipping a function that looks finished while the user is half paid and half entitled.",{"type":19,"tag":20,"props":1612,"children":1613},{},[1614],{"type":24,"value":1615},"When a bug report lands, I check the failure list first. If the mode was never written, that is the real bug. The design never considered it.",{"type":19,"tag":60,"props":1617,"children":1619},{"id":1618},"quick-questions-i-keep-nearby",[1620],{"type":24,"value":1621},"Quick questions I keep nearby",{"type":19,"tag":77,"props":1623,"children":1624},{},[1625,1630,1635,1640,1645,1650],{"type":19,"tag":81,"props":1626,"children":1627},{},[1628],{"type":24,"value":1629},"What does the user see for this mode?",{"type":19,"tag":81,"props":1631,"children":1632},{},[1633],{"type":24,"value":1634},"Did any durable write already happen?",{"type":19,"tag":81,"props":1636,"children":1637},{},[1638],{"type":24,"value":1639},"Retry, compensate, or stop?",{"type":19,"tag":81,"props":1641,"children":1642},{},[1643],{"type":24,"value":1644},"Can email or a webhook fail after commit?",{"type":19,"tag":81,"props":1646,"children":1647},{},[1648],{"type":24,"value":1649},"Do two concurrent requests make this worse?",{"type":19,"tag":81,"props":1651,"children":1652},{},[1653],{"type":24,"value":1654},"Can support explain the outcome from logs alone?",{"type":19,"tag":20,"props":1656,"children":1657},{},[1658],{"type":24,"value":1659},"If I cannot answer those without squinting, the happy path is not ready.",{"type":19,"tag":60,"props":1661,"children":1663},{"id":1662},"thats-basically-it",[1664],{"type":24,"value":1665},"That's basically it",{"type":19,"tag":20,"props":1667,"children":1668},{},[1669],{"type":24,"value":1670},"Start with comments if that is how you think. Just do not stop at the sunny path. Spend a few minutes on how the feature fails and how you climb out. You will still delete most of the comments later. The decisions those comments forced tend to stick.",{"type":19,"tag":1672,"props":1673,"children":1674},"style",{},[1675],{"type":24,"value":1676},"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":7,"searchDepth":168,"depth":168,"links":1678},[1679,1680,1681,1682,1683,1684,1685,1686],{"id":62,"depth":168,"text":65},{"id":135,"depth":168,"text":138},{"id":378,"depth":168,"text":381},{"id":1545,"depth":168,"text":1548},{"id":1576,"depth":168,"text":1579},{"id":1592,"depth":168,"text":1595},{"id":1618,"depth":168,"text":1621},{"id":1662,"depth":168,"text":1665},"markdown","content:blog:failure-mode-driven-development.md","content","blog\u002Ffailure-mode-driven-development.md","blog\u002Ffailure-mode-driven-development","md",[1694,1695],null,{"_path":1696,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1697,"description":1698,"date":1699,"topics":1700,"body":1704,"_type":1687,"_id":2324,"_source":1689,"_file":2325,"_stem":2326,"_extension":1692},"\u002Fblog\u002Ftildewin-macos-style-window-switching-on-windows","TildeWin: macOS-style window switching on Windows","A small AutoHotkey v2 script that brings Cmd+` style same-app window switching to Windows.","2026-04-23T20:45:00+07:00",[1701,1702,1703],"autohotkey","windows","productivity",{"type":16,"children":1705,"toc":2316},[1706,1719,1741,1747,1752,1777,1789,1795,1800,1805,1844,1849,1855,1867,1872,1941,1952,1957,1990,1995,2001,2023,2060,2091,2103,2109,2129,2152,2164,2250,2278,2284,2307,2312],{"type":19,"tag":20,"props":1707,"children":1708},{},[1709,1711,1717],{"type":24,"value":1710},"One shortcut I keep missing on Windows is ",{"type":19,"tag":87,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":24,"value":1716},"Cmd + grave",{"type":24,"value":1718}," from macOS. If you have multiple windows open from the same app, it cycles through only those windows. It is especially useful with browsers, terminals, editors, and File Explorer.",{"type":19,"tag":20,"props":1720,"children":1721},{},[1722,1724,1730,1732,1740],{"type":24,"value":1723},"Windows has ",{"type":19,"tag":87,"props":1725,"children":1727},{"className":1726},[],[1728],{"type":24,"value":1729},"Alt + Tab",{"type":24,"value":1731},", but that cycles through every window. It also has taskbar grouping, but cycling through a grouped app usually means reaching for the mouse. I wanted the same direct keyboard behavior, so I made a tiny AutoHotkey script called ",{"type":19,"tag":27,"props":1733,"children":1737},{"href":1734,"rel":1735},"https:\u002F\u002Fgithub.com\u002Fibnuh\u002Ftildewin",[1736],"nofollow",[1738],{"type":24,"value":1739},"TildeWin",{"type":24,"value":508},{"type":19,"tag":60,"props":1742,"children":1744},{"id":1743},"what-it-does",[1745],{"type":24,"value":1746},"What it does",{"type":19,"tag":20,"props":1748,"children":1749},{},[1750],{"type":24,"value":1751},"TildeWin adds these shortcuts:",{"type":19,"tag":77,"props":1753,"children":1754},{},[1755,1766],{"type":19,"tag":81,"props":1756,"children":1757},{},[1758,1764],{"type":19,"tag":87,"props":1759,"children":1761},{"className":1760},[],[1762],{"type":24,"value":1763},"Win + grave",{"type":24,"value":1765},": switch to the next window in the current app.",{"type":19,"tag":81,"props":1767,"children":1768},{},[1769,1775],{"type":19,"tag":87,"props":1770,"children":1772},{"className":1771},[],[1773],{"type":24,"value":1774},"Win + Shift + grave",{"type":24,"value":1776},": switch to the previous window in the current app.",{"type":19,"tag":20,"props":1778,"children":1779},{},[1780,1782,1787],{"type":24,"value":1781},"So if I am focused on a Chrome window, ",{"type":19,"tag":87,"props":1783,"children":1785},{"className":1784},[],[1786],{"type":24,"value":1763},{"type":24,"value":1788}," moves to another Chrome window. If I am focused on VS Code, it cycles through VS Code windows. Other apps stay out of the way.",{"type":19,"tag":60,"props":1790,"children":1792},{"id":1791},"why-autohotkey",[1793],{"type":24,"value":1794},"Why AutoHotkey",{"type":19,"tag":20,"props":1796,"children":1797},{},[1798],{"type":24,"value":1799},"AutoHotkey is still the simplest tool for this kind of Windows automation. The script can ask Windows which window is active, find other windows from the same process, filter out windows that should not be switch targets, then activate the next one.",{"type":19,"tag":20,"props":1801,"children":1802},{},[1803],{"type":24,"value":1804},"For this first version, grouping is based on executable name:",{"type":19,"tag":77,"props":1806,"children":1807},{},[1808,1817,1826,1835],{"type":19,"tag":81,"props":1809,"children":1810},{},[1811],{"type":19,"tag":87,"props":1812,"children":1814},{"className":1813},[],[1815],{"type":24,"value":1816},"chrome.exe",{"type":19,"tag":81,"props":1818,"children":1819},{},[1820],{"type":19,"tag":87,"props":1821,"children":1823},{"className":1822},[],[1824],{"type":24,"value":1825},"Code.exe",{"type":19,"tag":81,"props":1827,"children":1828},{},[1829],{"type":19,"tag":87,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":24,"value":1834},"explorer.exe",{"type":19,"tag":81,"props":1836,"children":1837},{},[1838],{"type":19,"tag":87,"props":1839,"children":1841},{"className":1840},[],[1842],{"type":24,"value":1843},"notepad.exe",{"type":19,"tag":20,"props":1845,"children":1846},{},[1847],{"type":24,"value":1848},"That covers the apps I use most. It is not a perfect clone of Windows taskbar grouping, but it is small, predictable, and easy to change.",{"type":19,"tag":60,"props":1850,"children":1852},{"id":1851},"the-script",[1853],{"type":24,"value":1854},"The script",{"type":19,"tag":20,"props":1856,"children":1857},{},[1858,1860,1866],{"type":24,"value":1859},"The full script is in the repo: ",{"type":19,"tag":27,"props":1861,"children":1863},{"href":1734,"rel":1862},[1736],[1864],{"type":24,"value":1865},"github.com\u002Fibnuh\u002Ftildewin",{"type":24,"value":508},{"type":19,"tag":20,"props":1868,"children":1869},{},[1870],{"type":24,"value":1871},"The important part is this:",{"type":19,"tag":145,"props":1873,"children":1876},{"className":1874,"code":1875,"language":1701,"meta":7,"style":7},"language-autohotkey shiki shiki-themes one-dark-pro","#vkC0::SwitchSameAppWindow(1)\n#+vkC0::SwitchSameAppWindow(-1)\n",[1877],{"type":19,"tag":87,"props":1878,"children":1879},{"__ignoreMap":7},[1880,1912],{"type":19,"tag":155,"props":1881,"children":1882},{"class":157,"line":158},[1883,1888,1893,1898,1902,1908],{"type":19,"tag":155,"props":1884,"children":1885},{"style":406},[1886],{"type":24,"value":1887},"#vkC0",{"type":19,"tag":155,"props":1889,"children":1890},{"style":429},[1891],{"type":24,"value":1892},"::",{"type":19,"tag":155,"props":1894,"children":1895},{"style":423},[1896],{"type":24,"value":1897},"SwitchSameAppWindow",{"type":19,"tag":155,"props":1899,"children":1900},{"style":429},[1901],{"type":24,"value":432},{"type":19,"tag":155,"props":1903,"children":1905},{"style":1904},"--shiki-default:#D19A66",[1906],{"type":24,"value":1907},"1",{"type":19,"tag":155,"props":1909,"children":1910},{"style":429},[1911],{"type":24,"value":447},{"type":19,"tag":155,"props":1913,"children":1914},{"class":157,"line":168},[1915,1920,1924,1928,1933,1937],{"type":19,"tag":155,"props":1916,"children":1917},{"style":406},[1918],{"type":24,"value":1919},"#+vkC0",{"type":19,"tag":155,"props":1921,"children":1922},{"style":429},[1923],{"type":24,"value":1892},{"type":19,"tag":155,"props":1925,"children":1926},{"style":423},[1927],{"type":24,"value":1897},{"type":19,"tag":155,"props":1929,"children":1930},{"style":429},[1931],{"type":24,"value":1932},"(-",{"type":19,"tag":155,"props":1934,"children":1935},{"style":1904},[1936],{"type":24,"value":1907},{"type":19,"tag":155,"props":1938,"children":1939},{"style":429},[1940],{"type":24,"value":447},{"type":19,"tag":20,"props":1942,"children":1943},{},[1944,1950],{"type":19,"tag":87,"props":1945,"children":1947},{"className":1946},[],[1948],{"type":24,"value":1949},"vkC0",{"type":24,"value":1951}," is the grave\u002Fbacktick key on a US-style keyboard. I used the virtual key name because the backtick character has special meaning in AutoHotkey strings and comments can get confusing quickly.",{"type":19,"tag":20,"props":1953,"children":1954},{},[1955],{"type":24,"value":1956},"The script skips windows that should not behave like normal app windows:",{"type":19,"tag":77,"props":1958,"children":1959},{},[1960,1965,1970,1975,1980,1985],{"type":19,"tag":81,"props":1961,"children":1962},{},[1963],{"type":24,"value":1964},"minimized windows",{"type":19,"tag":81,"props":1966,"children":1967},{},[1968],{"type":24,"value":1969},"hidden or cloaked windows",{"type":19,"tag":81,"props":1971,"children":1972},{},[1973],{"type":24,"value":1974},"tool windows",{"type":19,"tag":81,"props":1976,"children":1977},{},[1978],{"type":24,"value":1979},"no-activate windows",{"type":19,"tag":81,"props":1981,"children":1982},{},[1983],{"type":24,"value":1984},"disabled windows",{"type":19,"tag":81,"props":1986,"children":1987},{},[1988],{"type":24,"value":1989},"desktop and taskbar shell windows",{"type":19,"tag":20,"props":1991,"children":1992},{},[1993],{"type":24,"value":1994},"This makes the shortcut feel closer to how I expect app window switching to work.",{"type":19,"tag":60,"props":1996,"children":1998},{"id":1997},"setup",[1999],{"type":24,"value":2000},"Setup",{"type":19,"tag":2002,"props":2003,"children":2004},"ol",{},[2005,2018],{"type":19,"tag":81,"props":2006,"children":2007},{},[2008,2010,2017],{"type":24,"value":2009},"Install ",{"type":19,"tag":27,"props":2011,"children":2014},{"href":2012,"rel":2013},"https:\u002F\u002Fwww.autohotkey.com\u002F",[1736],[2015],{"type":24,"value":2016},"AutoHotkey v2",{"type":24,"value":508},{"type":19,"tag":81,"props":2019,"children":2020},{},[2021],{"type":24,"value":2022},"Download or clone TildeWin:",{"type":19,"tag":145,"props":2024,"children":2028},{"className":2025,"code":2026,"language":2027,"meta":7,"style":7},"language-powershell shiki shiki-themes one-dark-pro","git clone https:\u002F\u002Fgithub.com\u002Fibnuh\u002Ftildewin.git\n","powershell",[2029],{"type":19,"tag":87,"props":2030,"children":2031},{"__ignoreMap":7},[2032],{"type":19,"tag":155,"props":2033,"children":2034},{"class":157,"line":158},[2035,2040,2045,2050,2055],{"type":19,"tag":155,"props":2036,"children":2037},{"style":429},[2038],{"type":24,"value":2039},"git clone https:",{"type":19,"tag":155,"props":2041,"children":2042},{"style":490},[2043],{"type":24,"value":2044},"\u002F\u002Fgithub.com\u002F",{"type":19,"tag":155,"props":2046,"children":2047},{"style":429},[2048],{"type":24,"value":2049},"ibnuh",{"type":19,"tag":155,"props":2051,"children":2052},{"style":490},[2053],{"type":24,"value":2054},"\u002F",{"type":19,"tag":155,"props":2056,"children":2057},{"style":429},[2058],{"type":24,"value":2059},"tildewin.git\n",{"type":19,"tag":2002,"props":2061,"children":2062},{"start":177},[2063,2075,2080],{"type":19,"tag":81,"props":2064,"children":2065},{},[2066,2068,2074],{"type":24,"value":2067},"Run ",{"type":19,"tag":87,"props":2069,"children":2071},{"className":2070},[],[2072],{"type":24,"value":2073},"tildewin.ahk",{"type":24,"value":508},{"type":19,"tag":81,"props":2076,"children":2077},{},[2078],{"type":24,"value":2079},"Open multiple windows from the same app.",{"type":19,"tag":81,"props":2081,"children":2082},{},[2083,2085,2090],{"type":24,"value":2084},"Press ",{"type":19,"tag":87,"props":2086,"children":2088},{"className":2087},[],[2089],{"type":24,"value":1763},{"type":24,"value":508},{"type":19,"tag":20,"props":2092,"children":2093},{},[2094,2096,2101],{"type":24,"value":2095},"To run it automatically on startup, put a shortcut to ",{"type":19,"tag":87,"props":2097,"children":2099},{"className":2098},[],[2100],{"type":24,"value":2073},{"type":24,"value":2102}," in the Windows Startup folder.",{"type":19,"tag":60,"props":2104,"children":2106},{"id":2105},"changing-the-hotkey",[2107],{"type":24,"value":2108},"Changing the hotkey",{"type":19,"tag":20,"props":2110,"children":2111},{},[2112,2114,2119,2121,2127],{"type":24,"value":2113},"If ",{"type":19,"tag":87,"props":2115,"children":2117},{"className":2116},[],[2118],{"type":24,"value":1763},{"type":24,"value":2120}," does not feel right, the script includes ",{"type":19,"tag":87,"props":2122,"children":2124},{"className":2123},[],[2125],{"type":24,"value":2126},"Alt + grave",{"type":24,"value":2128}," bindings as comments:",{"type":19,"tag":145,"props":2130,"children":2132},{"className":1874,"code":2131,"language":1701,"meta":7,"style":7},"; !vkC0::SwitchSameAppWindow(1)\n; !+vkC0::SwitchSameAppWindow(-1)\n",[2133],{"type":19,"tag":87,"props":2134,"children":2135},{"__ignoreMap":7},[2136,2144],{"type":19,"tag":155,"props":2137,"children":2138},{"class":157,"line":158},[2139],{"type":19,"tag":155,"props":2140,"children":2141},{"style":162},[2142],{"type":24,"value":2143},"; !vkC0::SwitchSameAppWindow(1)\n",{"type":19,"tag":155,"props":2145,"children":2146},{"class":157,"line":168},[2147],{"type":19,"tag":155,"props":2148,"children":2149},{"style":162},[2150],{"type":24,"value":2151},"; !+vkC0::SwitchSameAppWindow(-1)\n",{"type":19,"tag":20,"props":2153,"children":2154},{},[2155,2157,2162],{"type":24,"value":2156},"Uncomment those lines and comment out the ",{"type":19,"tag":87,"props":2158,"children":2160},{"className":2159},[],[2161],{"type":24,"value":1887},{"type":24,"value":2163}," lines:",{"type":19,"tag":145,"props":2165,"children":2167},{"className":1874,"code":2166,"language":1701,"meta":7,"style":7},"; #vkC0::SwitchSameAppWindow(1)\n; #+vkC0::SwitchSameAppWindow(-1)\n\n!vkC0::SwitchSameAppWindow(1)\n!+vkC0::SwitchSameAppWindow(-1)\n",[2168],{"type":19,"tag":87,"props":2169,"children":2170},{"__ignoreMap":7},[2171,2179,2187,2194,2222],{"type":19,"tag":155,"props":2172,"children":2173},{"class":157,"line":158},[2174],{"type":19,"tag":155,"props":2175,"children":2176},{"style":162},[2177],{"type":24,"value":2178},"; #vkC0::SwitchSameAppWindow(1)\n",{"type":19,"tag":155,"props":2180,"children":2181},{"class":157,"line":168},[2182],{"type":19,"tag":155,"props":2183,"children":2184},{"style":162},[2185],{"type":24,"value":2186},"; #+vkC0::SwitchSameAppWindow(-1)\n",{"type":19,"tag":155,"props":2188,"children":2189},{"class":157,"line":177},[2190],{"type":19,"tag":155,"props":2191,"children":2192},{"emptyLinePlaceholder":533},[2193],{"type":24,"value":536},{"type":19,"tag":155,"props":2195,"children":2196},{"class":157,"line":186},[2197,2202,2206,2210,2214,2218],{"type":19,"tag":155,"props":2198,"children":2199},{"style":406},[2200],{"type":24,"value":2201},"!vkC0",{"type":19,"tag":155,"props":2203,"children":2204},{"style":429},[2205],{"type":24,"value":1892},{"type":19,"tag":155,"props":2207,"children":2208},{"style":423},[2209],{"type":24,"value":1897},{"type":19,"tag":155,"props":2211,"children":2212},{"style":429},[2213],{"type":24,"value":432},{"type":19,"tag":155,"props":2215,"children":2216},{"style":1904},[2217],{"type":24,"value":1907},{"type":19,"tag":155,"props":2219,"children":2220},{"style":429},[2221],{"type":24,"value":447},{"type":19,"tag":155,"props":2223,"children":2224},{"class":157,"line":195},[2225,2230,2234,2238,2242,2246],{"type":19,"tag":155,"props":2226,"children":2227},{"style":406},[2228],{"type":24,"value":2229},"!+vkC0",{"type":19,"tag":155,"props":2231,"children":2232},{"style":429},[2233],{"type":24,"value":1892},{"type":19,"tag":155,"props":2235,"children":2236},{"style":423},[2237],{"type":24,"value":1897},{"type":19,"tag":155,"props":2239,"children":2240},{"style":429},[2241],{"type":24,"value":1932},{"type":19,"tag":155,"props":2243,"children":2244},{"style":1904},[2245],{"type":24,"value":1907},{"type":19,"tag":155,"props":2247,"children":2248},{"style":429},[2249],{"type":24,"value":447},{"type":19,"tag":20,"props":2251,"children":2252},{},[2253,2255,2261,2263,2268,2270,2276],{"type":24,"value":2254},"In AutoHotkey syntax, ",{"type":19,"tag":87,"props":2256,"children":2258},{"className":2257},[],[2259],{"type":24,"value":2260},"#",{"type":24,"value":2262}," means Win, ",{"type":19,"tag":87,"props":2264,"children":2266},{"className":2265},[],[2267],{"type":24,"value":578},{"type":24,"value":2269}," means Alt, and ",{"type":19,"tag":87,"props":2271,"children":2273},{"className":2272},[],[2274],{"type":24,"value":2275},"+",{"type":24,"value":2277}," means Shift.",{"type":19,"tag":60,"props":2279,"children":2281},{"id":2280},"things-to-know",[2282],{"type":24,"value":2283},"Things to know",{"type":19,"tag":77,"props":2285,"children":2286},{},[2287,2292,2297,2302],{"type":19,"tag":81,"props":2288,"children":2289},{},[2290],{"type":24,"value":2291},"Admin windows may need the script to run as administrator.",{"type":19,"tag":81,"props":2293,"children":2294},{},[2295],{"type":24,"value":2296},"Browser tabs are not separate windows. This switches browser windows, not tabs.",{"type":19,"tag":81,"props":2298,"children":2299},{},[2300],{"type":24,"value":2301},"Apps with unusual window models may not behave perfectly.",{"type":19,"tag":81,"props":2303,"children":2304},{},[2305],{"type":24,"value":2306},"The current version does not use Windows AppUserModelID yet, so process-name grouping is the main rule.",{"type":19,"tag":20,"props":2308,"children":2309},{},[2310],{"type":24,"value":2311},"That is enough for my daily use right now. It is one of those tiny utilities that removes a little friction every time I switch contexts.",{"type":19,"tag":1672,"props":2313,"children":2314},{},[2315],{"type":24,"value":1676},{"title":7,"searchDepth":168,"depth":168,"links":2317},[2318,2319,2320,2321,2322,2323],{"id":1743,"depth":168,"text":1746},{"id":1791,"depth":168,"text":1794},{"id":1851,"depth":168,"text":1854},{"id":1997,"depth":168,"text":2000},{"id":2105,"depth":168,"text":2108},{"id":2280,"depth":168,"text":2283},"content:blog:tildewin-macos-style-window-switching-on-windows.md","blog\u002Ftildewin-macos-style-window-switching-on-windows.md","blog\u002Ftildewin-macos-style-window-switching-on-windows",[2328,2362],{"_path":2329,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2330,"description":2331,"date":2332,"topics":2333,"body":2335,"_type":1687,"_id":2359,"_source":1689,"_file":2360,"_stem":2361,"_extension":1692},"\u002Fblog\u002Freflections-on-handling-mistakes-as-a-programmer","Handling mistakes as a web developer","One thing I appreciate about being a web developer is that most of our mistakes are fixable.","2023-04-07T14:33:00+07:00",[2334,12],"career",{"type":16,"children":2336,"toc":2357},[2337,2342,2347,2352],{"type":19,"tag":20,"props":2338,"children":2339},{},[2340],{"type":24,"value":2341},"One thing I appreciate about being a web developer is that most of our mistakes are fixable. Messed something up? Hit undo, revert the commit, push again. Sure, there are consequences - wasted time, angry clients, maybe some data loss - but most of the time you can recover from it.",{"type":19,"tag":20,"props":2343,"children":2344},{},[2345],{"type":24,"value":2346},"Compare that to doctors, engineers, or pilots - if they mess up, people can actually die. That doesn't make our job less important, but the stakes are definitely different.",{"type":19,"tag":20,"props":2348,"children":2349},{},[2350],{"type":24,"value":2351},"That said, knowing you can always revert stuff can make you sloppy if you're not careful. I've caught myself skipping things because \"I can just fix it later\" and that's a bad habit. The safety net is nice, but it shouldn't be an excuse to cut corners.",{"type":19,"tag":20,"props":2353,"children":2354},{},[2355],{"type":24,"value":2356},"I try to look back at my past screw-ups every now and then. Not to beat myself up, but because that's honestly where I learn the most. And let's be real, reverting a broken deploy at 2am is not fun - better to get it right the first time when you can.",{"title":7,"searchDepth":168,"depth":168,"links":2358},[],"content:blog:reflections-on-handling-mistakes-as-a-programmer.md","blog\u002Freflections-on-handling-mistakes-as-a-programmer.md","blog\u002Freflections-on-handling-mistakes-as-a-programmer",{"_path":29,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2363,"description":2364,"date":2365,"topics":2366,"body":2367,"_type":1687,"_id":3347,"_source":1689,"_file":3348,"_stem":3349,"_extension":1692},"Comment driven development","Comment Driven Development is a practice where you think through the task and write down the stages in the form of code comments before writing actual code.","2021-12-19T07:52:00+07:00",[12,13],{"type":16,"children":2368,"toc":3345},[2369,2374,2379,2384,2392,2469,2474,3282,3287,3308,3313,3318,3336,3341],{"type":19,"tag":20,"props":2370,"children":2371},{},[2372],{"type":24,"value":2373},"I tend to sketch out the stages or pseudo-code everything using comments whether I'm coding a large or complicated usecase or something where things could quickly spiral out of hand. Of course, we're talking about coding simple usecases here, not system design and architecture, for which you'll need a lot more than comments.",{"type":19,"tag":20,"props":2375,"children":2376},{},[2377],{"type":24,"value":2378},"When a buddy of mine realized what I was doing, he informed me that what I was doing was called Comment Driven Development. That's when I discovered that \"Comment First\" is a practice known as Comment Driven Development or Comment Programming, in which you think through the task and write down the phases in the form of code comments, then start translating those comments into actual code after everything is clear.",{"type":19,"tag":20,"props":2380,"children":2381},{},[2382],{"type":24,"value":2383},"You might even be doing the same thing without realizing it since you have CDD. Allow me to illustrate it with an example of how I go about creating something, or in other words, what Comment Driven Development is.",{"type":19,"tag":51,"props":2385,"children":2386},{},[2387],{"type":19,"tag":20,"props":2388,"children":2389},{},[2390],{"type":24,"value":2391},"Disclaimer: Do not take this seriously. Ignore the existence of any such thing as OOP. Ignore the SOLID principles entirely. Allow the architect inside you to rest for a while and use this example solely to grasp Comment Driven Development.",{"type":19,"tag":145,"props":2393,"children":2395},{"className":147,"code":2394,"language":149,"meta":7,"style":7},"\u002F\u002F Purchase a book\n\n\u002F\u002F Check book availability\n\u002F\u002F Check user balance\n\u002F\u002F Deduct user balance\n\u002F\u002F Add payment information\n\u002F\u002F Add book to library\n\u002F\u002F Generate email body\n\u002F\u002F Send purchase confirmation to email\n",[2396],{"type":19,"tag":87,"props":2397,"children":2398},{"__ignoreMap":7},[2399,2406,2413,2421,2429,2437,2445,2453,2461],{"type":19,"tag":155,"props":2400,"children":2401},{"class":157,"line":158},[2402],{"type":19,"tag":155,"props":2403,"children":2404},{"style":162},[2405],{"type":24,"value":165},{"type":19,"tag":155,"props":2407,"children":2408},{"class":157,"line":168},[2409],{"type":19,"tag":155,"props":2410,"children":2411},{"emptyLinePlaceholder":533},[2412],{"type":24,"value":536},{"type":19,"tag":155,"props":2414,"children":2415},{"class":157,"line":177},[2416],{"type":19,"tag":155,"props":2417,"children":2418},{"style":162},[2419],{"type":24,"value":2420},"\u002F\u002F Check book availability\n",{"type":19,"tag":155,"props":2422,"children":2423},{"class":157,"line":186},[2424],{"type":19,"tag":155,"props":2425,"children":2426},{"style":162},[2427],{"type":24,"value":2428},"\u002F\u002F Check user balance\n",{"type":19,"tag":155,"props":2430,"children":2431},{"class":157,"line":195},[2432],{"type":19,"tag":155,"props":2433,"children":2434},{"style":162},[2435],{"type":24,"value":2436},"\u002F\u002F Deduct user balance\n",{"type":19,"tag":155,"props":2438,"children":2439},{"class":157,"line":204},[2440],{"type":19,"tag":155,"props":2441,"children":2442},{"style":162},[2443],{"type":24,"value":2444},"\u002F\u002F Add payment information\n",{"type":19,"tag":155,"props":2446,"children":2447},{"class":157,"line":213},[2448],{"type":19,"tag":155,"props":2449,"children":2450},{"style":162},[2451],{"type":24,"value":2452},"\u002F\u002F Add book to library\n",{"type":19,"tag":155,"props":2454,"children":2455},{"class":157,"line":222},[2456],{"type":19,"tag":155,"props":2457,"children":2458},{"style":162},[2459],{"type":24,"value":2460},"\u002F\u002F Generate email body\n",{"type":19,"tag":155,"props":2462,"children":2463},{"class":157,"line":231},[2464],{"type":19,"tag":155,"props":2465,"children":2466},{"style":162},[2467],{"type":24,"value":2468},"\u002F\u002F Send purchase confirmation to email\n",{"type":19,"tag":20,"props":2470,"children":2471},{},[2472],{"type":24,"value":2473},"As you can see, the steps to purchase a book are now apparent, and we can move on to converting it to actual code, which I might change to something like this.",{"type":19,"tag":145,"props":2475,"children":2477},{"className":147,"code":2476,"language":149,"meta":7,"style":7},"\u002F\u002F Purchase a book\npublic async Task PurchaseBook(Book book)\n{\n    \u002F\u002F Check book availability\n    var isAvailable = _bookService.IsAvailable(book);\n    if (!isAvailable)\n    {\n        throw new Exception($\"{book.Title} is currently unavailable\");\n    }\n\n    \u002F\u002F Check user balance\n    var isBalanceAvailable = _userService.HasEnoughBalanceToPurchase(book.Price);\n    if (!isBalanceAvailable)\n    {\n        throw new Exception(\"You don't have enough balance\");\n    }\n\n    \u002F\u002F Deduct user balance\n    _userService.ReduceBalance(book.Price);\n\n    \u002F\u002F Add payment information\n    var payment = _paymentService.AddHistory(new Payment {\n        Status = PaymentStatus.Paid,\n        Amount = book.Price\n    });\n\n    \u002F\u002F Add book to library\n    _libraryService.Add(new Library {\n        Book = book,\n        Payment = payment\n    });\n\n    \u002F\u002F Generate email body\n    var emailBody = _emailRenderService.Render(EmailTemplate.PurchaseConfirmation, payment);\n\n    \u002F\u002F Send purchase confirmation to email\n    _emailQueueService.Add(new EmailQueue {\n        Recipient = _userService.GetEmail(),\n        Subject = \"Thank you for your purchase\",\n        Body = emailBody,\n    });\n\n    await _dbContext.SaveChanges();\n}\n",[2478],{"type":19,"tag":87,"props":2479,"children":2480},{"__ignoreMap":7},[2481,2488,2523,2530,2538,2580,2605,2612,2663,2670,2677,2685,2733,2757,2764,2791,2798,2805,2813,2849,2856,2864,2905,2933,2957,2965,2972,2980,3009,3029,3045,3052,3059,3067,3125,3132,3140,3169,3197,3217,3237,3244,3251,3275],{"type":19,"tag":155,"props":2482,"children":2483},{"class":157,"line":158},[2484],{"type":19,"tag":155,"props":2485,"children":2486},{"style":162},[2487],{"type":24,"value":165},{"type":19,"tag":155,"props":2489,"children":2490},{"class":157,"line":168},[2491,2495,2499,2503,2507,2511,2515,2519],{"type":19,"tag":155,"props":2492,"children":2493},{"style":406},[2494],{"type":24,"value":409},{"type":19,"tag":155,"props":2496,"children":2497},{"style":406},[2498],{"type":24,"value":414},{"type":19,"tag":155,"props":2500,"children":2501},{"style":417},[2502],{"type":24,"value":420},{"type":19,"tag":155,"props":2504,"children":2505},{"style":423},[2506],{"type":24,"value":426},{"type":19,"tag":155,"props":2508,"children":2509},{"style":429},[2510],{"type":24,"value":432},{"type":19,"tag":155,"props":2512,"children":2513},{"style":417},[2514],{"type":24,"value":437},{"type":19,"tag":155,"props":2516,"children":2517},{"style":417},[2518],{"type":24,"value":442},{"type":19,"tag":155,"props":2520,"children":2521},{"style":429},[2522],{"type":24,"value":447},{"type":19,"tag":155,"props":2524,"children":2525},{"class":157,"line":177},[2526],{"type":19,"tag":155,"props":2527,"children":2528},{"style":429},[2529],{"type":24,"value":455},{"type":19,"tag":155,"props":2531,"children":2532},{"class":157,"line":186},[2533],{"type":19,"tag":155,"props":2534,"children":2535},{"style":162},[2536],{"type":24,"value":2537},"    \u002F\u002F Check book availability\n",{"type":19,"tag":155,"props":2539,"children":2540},{"class":157,"line":195},[2541,2546,2551,2555,2560,2564,2568,2572,2576],{"type":19,"tag":155,"props":2542,"children":2543},{"style":406},[2544],{"type":24,"value":2545},"    var",{"type":19,"tag":155,"props":2547,"children":2548},{"style":484},[2549],{"type":24,"value":2550}," isAvailable",{"type":19,"tag":155,"props":2552,"children":2553},{"style":490},[2554],{"type":24,"value":493},{"type":19,"tag":155,"props":2556,"children":2557},{"style":417},[2558],{"type":24,"value":2559}," _bookService",{"type":19,"tag":155,"props":2561,"children":2562},{"style":429},[2563],{"type":24,"value":508},{"type":19,"tag":155,"props":2565,"children":2566},{"style":423},[2567],{"type":24,"value":592},{"type":19,"tag":155,"props":2569,"children":2570},{"style":429},[2571],{"type":24,"value":432},{"type":19,"tag":155,"props":2573,"children":2574},{"style":484},[2575],{"type":24,"value":601},{"type":19,"tag":155,"props":2577,"children":2578},{"style":429},[2579],{"type":24,"value":675},{"type":19,"tag":155,"props":2581,"children":2582},{"class":157,"line":204},[2583,2588,2592,2596,2601],{"type":19,"tag":155,"props":2584,"children":2585},{"style":406},[2586],{"type":24,"value":2587},"    if",{"type":19,"tag":155,"props":2589,"children":2590},{"style":429},[2591],{"type":24,"value":573},{"type":19,"tag":155,"props":2593,"children":2594},{"style":490},[2595],{"type":24,"value":578},{"type":19,"tag":155,"props":2597,"children":2598},{"style":484},[2599],{"type":24,"value":2600},"isAvailable",{"type":19,"tag":155,"props":2602,"children":2603},{"style":429},[2604],{"type":24,"value":447},{"type":19,"tag":155,"props":2606,"children":2607},{"class":157,"line":213},[2608],{"type":19,"tag":155,"props":2609,"children":2610},{"style":429},[2611],{"type":24,"value":552},{"type":19,"tag":155,"props":2613,"children":2614},{"class":157,"line":222},[2615,2619,2623,2627,2631,2635,2639,2643,2647,2651,2655,2659],{"type":19,"tag":155,"props":2616,"children":2617},{"style":406},[2618],{"type":24,"value":1515},{"type":19,"tag":155,"props":2620,"children":2621},{"style":429},[2622],{"type":24,"value":627},{"type":19,"tag":155,"props":2624,"children":2625},{"style":417},[2626],{"type":24,"value":632},{"type":19,"tag":155,"props":2628,"children":2629},{"style":429},[2630],{"type":24,"value":432},{"type":19,"tag":155,"props":2632,"children":2633},{"style":639},[2634],{"type":24,"value":642},{"type":19,"tag":155,"props":2636,"children":2637},{"style":429},[2638],{"type":24,"value":647},{"type":19,"tag":155,"props":2640,"children":2641},{"style":417},[2642],{"type":24,"value":601},{"type":19,"tag":155,"props":2644,"children":2645},{"style":429},[2646],{"type":24,"value":508},{"type":19,"tag":155,"props":2648,"children":2649},{"style":417},[2650],{"type":24,"value":660},{"type":19,"tag":155,"props":2652,"children":2653},{"style":429},[2654],{"type":24,"value":665},{"type":19,"tag":155,"props":2656,"children":2657},{"style":639},[2658],{"type":24,"value":670},{"type":19,"tag":155,"props":2660,"children":2661},{"style":429},[2662],{"type":24,"value":675},{"type":19,"tag":155,"props":2664,"children":2665},{"class":157,"line":231},[2666],{"type":19,"tag":155,"props":2667,"children":2668},{"style":429},[2669],{"type":24,"value":1464},{"type":19,"tag":155,"props":2671,"children":2672},{"class":157,"line":240},[2673],{"type":19,"tag":155,"props":2674,"children":2675},{"emptyLinePlaceholder":533},[2676],{"type":24,"value":536},{"type":19,"tag":155,"props":2678,"children":2679},{"class":157,"line":248},[2680],{"type":19,"tag":155,"props":2681,"children":2682},{"style":162},[2683],{"type":24,"value":2684},"    \u002F\u002F Check user balance\n",{"type":19,"tag":155,"props":2686,"children":2687},{"class":157,"line":257},[2688,2692,2697,2701,2705,2709,2713,2717,2721,2725,2729],{"type":19,"tag":155,"props":2689,"children":2690},{"style":406},[2691],{"type":24,"value":2545},{"type":19,"tag":155,"props":2693,"children":2694},{"style":484},[2695],{"type":24,"value":2696}," isBalanceAvailable",{"type":19,"tag":155,"props":2698,"children":2699},{"style":490},[2700],{"type":24,"value":493},{"type":19,"tag":155,"props":2702,"children":2703},{"style":417},[2704],{"type":24,"value":1272},{"type":19,"tag":155,"props":2706,"children":2707},{"style":429},[2708],{"type":24,"value":508},{"type":19,"tag":155,"props":2710,"children":2711},{"style":423},[2712],{"type":24,"value":727},{"type":19,"tag":155,"props":2714,"children":2715},{"style":429},[2716],{"type":24,"value":432},{"type":19,"tag":155,"props":2718,"children":2719},{"style":417},[2720],{"type":24,"value":601},{"type":19,"tag":155,"props":2722,"children":2723},{"style":429},[2724],{"type":24,"value":508},{"type":19,"tag":155,"props":2726,"children":2727},{"style":417},[2728],{"type":24,"value":744},{"type":19,"tag":155,"props":2730,"children":2731},{"style":429},[2732],{"type":24,"value":675},{"type":19,"tag":155,"props":2734,"children":2735},{"class":157,"line":266},[2736,2740,2744,2748,2753],{"type":19,"tag":155,"props":2737,"children":2738},{"style":406},[2739],{"type":24,"value":2587},{"type":19,"tag":155,"props":2741,"children":2742},{"style":429},[2743],{"type":24,"value":573},{"type":19,"tag":155,"props":2745,"children":2746},{"style":490},[2747],{"type":24,"value":578},{"type":19,"tag":155,"props":2749,"children":2750},{"style":484},[2751],{"type":24,"value":2752},"isBalanceAvailable",{"type":19,"tag":155,"props":2754,"children":2755},{"style":429},[2756],{"type":24,"value":447},{"type":19,"tag":155,"props":2758,"children":2759},{"class":157,"line":275},[2760],{"type":19,"tag":155,"props":2761,"children":2762},{"style":429},[2763],{"type":24,"value":552},{"type":19,"tag":155,"props":2765,"children":2766},{"class":157,"line":284},[2767,2771,2775,2779,2783,2787],{"type":19,"tag":155,"props":2768,"children":2769},{"style":406},[2770],{"type":24,"value":1515},{"type":19,"tag":155,"props":2772,"children":2773},{"style":429},[2774],{"type":24,"value":627},{"type":19,"tag":155,"props":2776,"children":2777},{"style":417},[2778],{"type":24,"value":632},{"type":19,"tag":155,"props":2780,"children":2781},{"style":429},[2782],{"type":24,"value":432},{"type":19,"tag":155,"props":2784,"children":2785},{"style":639},[2786],{"type":24,"value":779},{"type":19,"tag":155,"props":2788,"children":2789},{"style":429},[2790],{"type":24,"value":675},{"type":19,"tag":155,"props":2792,"children":2793},{"class":157,"line":293},[2794],{"type":19,"tag":155,"props":2795,"children":2796},{"style":429},[2797],{"type":24,"value":1464},{"type":19,"tag":155,"props":2799,"children":2800},{"class":157,"line":302},[2801],{"type":19,"tag":155,"props":2802,"children":2803},{"emptyLinePlaceholder":533},[2804],{"type":24,"value":536},{"type":19,"tag":155,"props":2806,"children":2807},{"class":157,"line":310},[2808],{"type":19,"tag":155,"props":2809,"children":2810},{"style":162},[2811],{"type":24,"value":2812},"    \u002F\u002F Deduct user balance\n",{"type":19,"tag":155,"props":2814,"children":2815},{"class":157,"line":319},[2816,2821,2825,2829,2833,2837,2841,2845],{"type":19,"tag":155,"props":2817,"children":2818},{"style":417},[2819],{"type":24,"value":2820},"    _userService",{"type":19,"tag":155,"props":2822,"children":2823},{"style":429},[2824],{"type":24,"value":508},{"type":19,"tag":155,"props":2826,"children":2827},{"style":423},[2828],{"type":24,"value":814},{"type":19,"tag":155,"props":2830,"children":2831},{"style":429},[2832],{"type":24,"value":432},{"type":19,"tag":155,"props":2834,"children":2835},{"style":417},[2836],{"type":24,"value":601},{"type":19,"tag":155,"props":2838,"children":2839},{"style":429},[2840],{"type":24,"value":508},{"type":19,"tag":155,"props":2842,"children":2843},{"style":417},[2844],{"type":24,"value":744},{"type":19,"tag":155,"props":2846,"children":2847},{"style":429},[2848],{"type":24,"value":675},{"type":19,"tag":155,"props":2850,"children":2851},{"class":157,"line":328},[2852],{"type":19,"tag":155,"props":2853,"children":2854},{"emptyLinePlaceholder":533},[2855],{"type":24,"value":536},{"type":19,"tag":155,"props":2857,"children":2858},{"class":157,"line":337},[2859],{"type":19,"tag":155,"props":2860,"children":2861},{"style":162},[2862],{"type":24,"value":2863},"    \u002F\u002F Add payment information\n",{"type":19,"tag":155,"props":2865,"children":2866},{"class":157,"line":346},[2867,2871,2875,2879,2883,2887,2891,2895,2900],{"type":19,"tag":155,"props":2868,"children":2869},{"style":406},[2870],{"type":24,"value":2545},{"type":19,"tag":155,"props":2872,"children":2873},{"style":484},[2874],{"type":24,"value":854},{"type":19,"tag":155,"props":2876,"children":2877},{"style":490},[2878],{"type":24,"value":493},{"type":19,"tag":155,"props":2880,"children":2881},{"style":417},[2882],{"type":24,"value":863},{"type":19,"tag":155,"props":2884,"children":2885},{"style":429},[2886],{"type":24,"value":508},{"type":19,"tag":155,"props":2888,"children":2889},{"style":423},[2890],{"type":24,"value":92},{"type":19,"tag":155,"props":2892,"children":2893},{"style":429},[2894],{"type":24,"value":876},{"type":19,"tag":155,"props":2896,"children":2897},{"style":417},[2898],{"type":24,"value":2899},"Payment",{"type":19,"tag":155,"props":2901,"children":2902},{"style":429},[2903],{"type":24,"value":2904}," {\n",{"type":19,"tag":155,"props":2906,"children":2907},{"class":157,"line":355},[2908,2913,2917,2921,2925,2929],{"type":19,"tag":155,"props":2909,"children":2910},{"style":484},[2911],{"type":24,"value":2912},"        Status",{"type":19,"tag":155,"props":2914,"children":2915},{"style":490},[2916],{"type":24,"value":493},{"type":19,"tag":155,"props":2918,"children":2919},{"style":417},[2920],{"type":24,"value":906},{"type":19,"tag":155,"props":2922,"children":2923},{"style":429},[2924],{"type":24,"value":508},{"type":19,"tag":155,"props":2926,"children":2927},{"style":417},[2928],{"type":24,"value":915},{"type":19,"tag":155,"props":2930,"children":2931},{"style":429},[2932],{"type":24,"value":920},{"type":19,"tag":155,"props":2934,"children":2935},{"class":157,"line":364},[2936,2941,2945,2949,2953],{"type":19,"tag":155,"props":2937,"children":2938},{"style":484},[2939],{"type":24,"value":2940},"        Amount",{"type":19,"tag":155,"props":2942,"children":2943},{"style":490},[2944],{"type":24,"value":493},{"type":19,"tag":155,"props":2946,"children":2947},{"style":417},[2948],{"type":24,"value":442},{"type":19,"tag":155,"props":2950,"children":2951},{"style":429},[2952],{"type":24,"value":508},{"type":19,"tag":155,"props":2954,"children":2955},{"style":417},[2956],{"type":24,"value":946},{"type":19,"tag":155,"props":2958,"children":2959},{"class":157,"line":891},[2960],{"type":19,"tag":155,"props":2961,"children":2962},{"style":429},[2963],{"type":24,"value":2964},"    });\n",{"type":19,"tag":155,"props":2966,"children":2967},{"class":157,"line":923},[2968],{"type":19,"tag":155,"props":2969,"children":2970},{"emptyLinePlaceholder":533},[2971],{"type":24,"value":536},{"type":19,"tag":155,"props":2973,"children":2974},{"class":157,"line":949},[2975],{"type":19,"tag":155,"props":2976,"children":2977},{"style":162},[2978],{"type":24,"value":2979},"    \u002F\u002F Add book to library\n",{"type":19,"tag":155,"props":2981,"children":2982},{"class":157,"line":958},[2983,2988,2992,2996,3000,3005],{"type":19,"tag":155,"props":2984,"children":2985},{"style":417},[2986],{"type":24,"value":2987},"    _libraryService",{"type":19,"tag":155,"props":2989,"children":2990},{"style":429},[2991],{"type":24,"value":508},{"type":19,"tag":155,"props":2993,"children":2994},{"style":423},[2995],{"type":24,"value":981},{"type":19,"tag":155,"props":2997,"children":2998},{"style":429},[2999],{"type":24,"value":876},{"type":19,"tag":155,"props":3001,"children":3002},{"style":417},[3003],{"type":24,"value":3004},"Library",{"type":19,"tag":155,"props":3006,"children":3007},{"style":429},[3008],{"type":24,"value":2904},{"type":19,"tag":155,"props":3010,"children":3011},{"class":157,"line":966},[3012,3017,3021,3025],{"type":19,"tag":155,"props":3013,"children":3014},{"style":484},[3015],{"type":24,"value":3016},"        Book",{"type":19,"tag":155,"props":3018,"children":3019},{"style":490},[3020],{"type":24,"value":493},{"type":19,"tag":155,"props":3022,"children":3023},{"style":484},[3024],{"type":24,"value":442},{"type":19,"tag":155,"props":3026,"children":3027},{"style":429},[3028],{"type":24,"value":920},{"type":19,"tag":155,"props":3030,"children":3031},{"class":157,"line":993},[3032,3037,3041],{"type":19,"tag":155,"props":3033,"children":3034},{"style":484},[3035],{"type":24,"value":3036},"        Payment",{"type":19,"tag":155,"props":3038,"children":3039},{"style":490},[3040],{"type":24,"value":493},{"type":19,"tag":155,"props":3042,"children":3043},{"style":484},[3044],{"type":24,"value":1037},{"type":19,"tag":155,"props":3046,"children":3047},{"class":157,"line":1001},[3048],{"type":19,"tag":155,"props":3049,"children":3050},{"style":429},[3051],{"type":24,"value":2964},{"type":19,"tag":155,"props":3053,"children":3054},{"class":157,"line":1022},[3055],{"type":19,"tag":155,"props":3056,"children":3057},{"emptyLinePlaceholder":533},[3058],{"type":24,"value":536},{"type":19,"tag":155,"props":3060,"children":3061},{"class":157,"line":1040},[3062],{"type":19,"tag":155,"props":3063,"children":3064},{"style":162},[3065],{"type":24,"value":3066},"    \u002F\u002F Generate email body\n",{"type":19,"tag":155,"props":3068,"children":3069},{"class":157,"line":1048},[3070,3074,3078,3082,3086,3090,3094,3098,3103,3107,3111,3116,3121],{"type":19,"tag":155,"props":3071,"children":3072},{"style":406},[3073],{"type":24,"value":2545},{"type":19,"tag":155,"props":3075,"children":3076},{"style":484},[3077],{"type":24,"value":1153},{"type":19,"tag":155,"props":3079,"children":3080},{"style":490},[3081],{"type":24,"value":493},{"type":19,"tag":155,"props":3083,"children":3084},{"style":417},[3085],{"type":24,"value":1162},{"type":19,"tag":155,"props":3087,"children":3088},{"style":429},[3089],{"type":24,"value":508},{"type":19,"tag":155,"props":3091,"children":3092},{"style":423},[3093],{"type":24,"value":1171},{"type":19,"tag":155,"props":3095,"children":3096},{"style":429},[3097],{"type":24,"value":432},{"type":19,"tag":155,"props":3099,"children":3100},{"style":417},[3101],{"type":24,"value":3102},"EmailTemplate",{"type":19,"tag":155,"props":3104,"children":3105},{"style":429},[3106],{"type":24,"value":508},{"type":19,"tag":155,"props":3108,"children":3109},{"style":417},[3110],{"type":24,"value":1194},{"type":19,"tag":155,"props":3112,"children":3113},{"style":429},[3114],{"type":24,"value":3115},", ",{"type":19,"tag":155,"props":3117,"children":3118},{"style":484},[3119],{"type":24,"value":3120},"payment",{"type":19,"tag":155,"props":3122,"children":3123},{"style":429},[3124],{"type":24,"value":675},{"type":19,"tag":155,"props":3126,"children":3127},{"class":157,"line":1056},[3128],{"type":19,"tag":155,"props":3129,"children":3130},{"emptyLinePlaceholder":533},[3131],{"type":24,"value":536},{"type":19,"tag":155,"props":3133,"children":3134},{"class":157,"line":1082},[3135],{"type":19,"tag":155,"props":3136,"children":3137},{"style":162},[3138],{"type":24,"value":3139},"    \u002F\u002F Send purchase confirmation to email\n",{"type":19,"tag":155,"props":3141,"children":3142},{"class":157,"line":1108},[3143,3148,3152,3156,3160,3165],{"type":19,"tag":155,"props":3144,"children":3145},{"style":417},[3146],{"type":24,"value":3147},"    _emailQueueService",{"type":19,"tag":155,"props":3149,"children":3150},{"style":429},[3151],{"type":24,"value":508},{"type":19,"tag":155,"props":3153,"children":3154},{"style":423},[3155],{"type":24,"value":981},{"type":19,"tag":155,"props":3157,"children":3158},{"style":429},[3159],{"type":24,"value":876},{"type":19,"tag":155,"props":3161,"children":3162},{"style":417},[3163],{"type":24,"value":3164},"EmailQueue",{"type":19,"tag":155,"props":3166,"children":3167},{"style":429},[3168],{"type":24,"value":2904},{"type":19,"tag":155,"props":3170,"children":3171},{"class":157,"line":1116},[3172,3177,3181,3185,3189,3193],{"type":19,"tag":155,"props":3173,"children":3174},{"style":484},[3175],{"type":24,"value":3176},"        Recipient",{"type":19,"tag":155,"props":3178,"children":3179},{"style":490},[3180],{"type":24,"value":493},{"type":19,"tag":155,"props":3182,"children":3183},{"style":417},[3184],{"type":24,"value":1272},{"type":19,"tag":155,"props":3186,"children":3187},{"style":429},[3188],{"type":24,"value":508},{"type":19,"tag":155,"props":3190,"children":3191},{"style":423},[3192],{"type":24,"value":1281},{"type":19,"tag":155,"props":3194,"children":3195},{"style":429},[3196],{"type":24,"value":1286},{"type":19,"tag":155,"props":3198,"children":3199},{"class":157,"line":1125},[3200,3205,3209,3213],{"type":19,"tag":155,"props":3201,"children":3202},{"style":484},[3203],{"type":24,"value":3204},"        Subject",{"type":19,"tag":155,"props":3206,"children":3207},{"style":490},[3208],{"type":24,"value":493},{"type":19,"tag":155,"props":3210,"children":3211},{"style":639},[3212],{"type":24,"value":1304},{"type":19,"tag":155,"props":3214,"children":3215},{"style":429},[3216],{"type":24,"value":920},{"type":19,"tag":155,"props":3218,"children":3219},{"class":157,"line":1134},[3220,3225,3229,3233],{"type":19,"tag":155,"props":3221,"children":3222},{"style":484},[3223],{"type":24,"value":3224},"        Body",{"type":19,"tag":155,"props":3226,"children":3227},{"style":490},[3228],{"type":24,"value":493},{"type":19,"tag":155,"props":3230,"children":3231},{"style":484},[3232],{"type":24,"value":1153},{"type":19,"tag":155,"props":3234,"children":3235},{"style":429},[3236],{"type":24,"value":920},{"type":19,"tag":155,"props":3238,"children":3239},{"class":157,"line":1142},[3240],{"type":19,"tag":155,"props":3241,"children":3242},{"style":429},[3243],{"type":24,"value":2964},{"type":19,"tag":155,"props":3245,"children":3246},{"class":157,"line":1179},[3247],{"type":19,"tag":155,"props":3248,"children":3249},{"emptyLinePlaceholder":533},[3250],{"type":24,"value":536},{"type":19,"tag":155,"props":3252,"children":3253},{"class":157,"line":1201},[3254,3258,3262,3266,3271],{"type":19,"tag":155,"props":3255,"children":3256},{"style":429},[3257],{"type":24,"value":471},{"type":19,"tag":155,"props":3259,"children":3260},{"style":417},[3261],{"type":24,"value":503},{"type":19,"tag":155,"props":3263,"children":3264},{"style":429},[3265],{"type":24,"value":508},{"type":19,"tag":155,"props":3267,"children":3268},{"style":423},[3269],{"type":24,"value":3270},"SaveChanges",{"type":19,"tag":155,"props":3272,"children":3273},{"style":429},[3274],{"type":24,"value":527},{"type":19,"tag":155,"props":3276,"children":3277},{"class":157,"line":1214},[3278],{"type":19,"tag":155,"props":3279,"children":3280},{"style":429},[3281],{"type":24,"value":1537},{"type":19,"tag":20,"props":3283,"children":3284},{},[3285],{"type":24,"value":3286},"Now that we have the code ready, we can start eliminating any comments that are no longer needed.",{"type":19,"tag":20,"props":3288,"children":3289},{},[3290,3292,3298,3300,3306],{"type":24,"value":3291},"Also, please note that I have only used a single ",{"type":19,"tag":87,"props":3293,"children":3295},{"className":3294},[],[3296],{"type":24,"value":3297},"method",{"type":24,"value":3299}," for demonstration purposes; I do not intend to promote the procedural approach to programming, nor am I suggesting that you create a single method\u002Ffunction and stuff it with everything, or that you ignore SOLID design principles and Design Patterns. Also, I'm not advocating that you should rely solely on these inline remarks without first considering the application's design. It's up to you to figure out how you want to organize things and what works best for your application. CDD, in my opinion, is useful when coding specific inner usecases of the program where certain sub-steps are involved, such as ",{"type":19,"tag":87,"props":3301,"children":3303},{"className":3302},[],[3304],{"type":24,"value":3305},"PurchaseBook",{"type":24,"value":3307},", where additional steps must be performed with it.",{"type":19,"tag":20,"props":3309,"children":3310},{},[3311],{"type":24,"value":3312},"For me, the aim of CDD is to simply understand and list down the steps needed in a usecase, and then when I've written the functionality and am entirely comfortable with the functionality and architecture that I've laid out, I delete any extraneous comments.",{"type":19,"tag":20,"props":3314,"children":3315},{},[3316],{"type":24,"value":3317},"That's all there is to it when it comes to Comment Driven Development. Now, here's why I use this method and why you should, too:",{"type":19,"tag":77,"props":3319,"children":3320},{},[3321,3326,3331],{"type":19,"tag":81,"props":3322,"children":3323},{},[3324],{"type":24,"value":3325},"It allows me to double-check that everything is obvious to me before I begin coding, which helps me to stay on track.",{"type":19,"tag":81,"props":3327,"children":3328},{},[3329],{"type":24,"value":3330},"You can use this method to diagram the stages and possibly instruct someone on the functionality you want them to develop.",{"type":19,"tag":81,"props":3332,"children":3333},{},[3334],{"type":24,"value":3335},"Documentation, although it only provides a high level but it might seem makes sense for some cases.",{"type":19,"tag":20,"props":3337,"children":3338},{},[3339],{"type":24,"value":3340},"That's all there is to it.",{"type":19,"tag":1672,"props":3342,"children":3343},{},[3344],{"type":24,"value":1676},{"title":7,"searchDepth":168,"depth":168,"links":3346},[],"content:blog:comment-driven-development.md","blog\u002Fcomment-driven-development.md","blog\u002Fcomment-driven-development",1783850763593]