-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
executable file
·859 lines (717 loc) · 35.6 KB
/
Copy pathindex.html
File metadata and controls
executable file
·859 lines (717 loc) · 35.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="description" content="A step by step guide to debug any IT defect, and make them forever disappear! Authors: Yann Jacquot, Remy Luciani">
<meta name="viewport" content="width=device-width">
<title>20 simple steps to debug anything</title>
<link rel="icon" type="image/png" href="favicon.png">
<style>
/* webkit printing magic: print all background colors */
html {
-webkit-print-color-adjust: exact;
}
* {
box-sizing: border-box;
-webkit-print-color-adjust: exact;
}
html,
body {
margin: 0;
padding: 0;
}
@media only screen {
body {
margin: 2em auto;
padding: 1em;
max-width: 900px;
color: rgb(55, 53, 47);
}
}
body {
line-height: 1.5;
}
a,
a.visited {
color: inherit;
text-decoration: underline;
}
.pdf-relative-link-path {
font-size: 80%;
color: #444;
}
h1,
h2,
h3 {
letter-spacing: -0.01em;
line-height: 1.2;
font-weight: 600;
margin-bottom: 0;
}
.page-title {
font-size: 2.5rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.75em;
}
h1 {
font-size: 1.875rem;
margin-top: 1.875rem;
}
h2 {
font-size: 1.5rem;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
}
h3 {
font-size: 1.25rem;
margin-top: 1.25rem;
}
.source {
border: 1px solid #ddd;
border-radius: 3px;
padding: 1.5em;
word-break: break-all;
}
.callout {
border-radius: 3px;
padding: 1rem;
}
figure {
margin: 1.25em 0;
page-break-inside: avoid;
}
figcaption {
opacity: 0.5;
font-size: 85%;
margin-top: 0.5em;
}
mark {
background-color: transparent;
}
.indented {
padding-left: 1.5em;
}
hr {
background: transparent;
display: block;
width: 100%;
height: 1px;
visibility: visible;
border: none;
border-bottom: 1px solid rgba(55, 53, 47, 0.09);
}
img {
max-width: 100%;
}
@media only print {
img {
max-height: 100vh;
object-fit: contain;
}
}
@page {
margin: 1in;
}
.collection-content {
font-size: 0.875rem;
}
.column-list {
display: flex;
justify-content: space-between;
}
.column {
padding: 0 1em;
}
.column:first-child {
padding-left: 0;
}
.column:last-child {
padding-right: 0;
}
.table_of_contents-item {
display: block;
font-size: 0.875rem;
line-height: 1.3;
padding: 0.125rem;
}
.table_of_contents-indent-1 {
margin-left: 1.5rem;
}
.table_of_contents-indent-2 {
margin-left: 3rem;
}
.table_of_contents-indent-3 {
margin-left: 4.5rem;
}
.table_of_contents-link {
text-decoration: none;
opacity: 0.7;
border-bottom: 1px solid rgba(55, 53, 47, 0.18);
}
table,
th,
td {
border: 1px solid rgba(55, 53, 47, 0.09);
border-collapse: collapse;
}
table {
border-left: none;
border-right: none;
}
th,
td {
font-weight: normal;
padding: 0.25em 0.5em;
line-height: 1.5;
min-height: 1.5em;
text-align: left;
}
th {
color: rgba(55, 53, 47, 0.6);
}
ol,
ul {
margin: 0;
margin-block-start: 0.6em;
margin-block-end: 0.6em;
}
li > ol:first-child,
li > ul:first-child {
margin-block-start: 0.6em;
}
ul > li {
list-style: disc;
}
ul.to-do-list {
text-indent: -1.7em;
}
ul.to-do-list > li {
list-style: none;
}
.to-do-children-checked {
text-decoration: line-through;
opacity: 0.375;
}
ul.toggle > li {
list-style: none;
}
ul {
padding-inline-start: 1.7em;
}
ul > li {
padding-left: 0.1em;
}
ol {
padding-inline-start: 1.6em;
}
ol > li {
padding-left: 0.2em;
}
.mono ol {
padding-inline-start: 2em;
}
.mono ol > li {
text-indent: -0.4em;
}
.toggle {
padding-inline-start: 0em;
list-style-type: none;
}
/* Indent toggle children */
.toggle > li > details {
padding-left: 1.7em;
}
.toggle > li > details > summary {
margin-left: -1.1em;
}
.selected-value {
display: inline-block;
padding: 0 0.5em;
background: rgba(206, 205, 202, 0.5);
border-radius: 3px;
margin-right: 0.5em;
margin-top: 0.3em;
margin-bottom: 0.3em;
white-space: nowrap;
}
.collection-title {
display: inline-block;
margin-right: 1em;
}
time {
opacity: 0.5;
}
.icon {
display: inline-block;
max-width: 1.2em;
max-height: 1.2em;
text-decoration: none;
vertical-align: text-bottom;
margin-right: 0.5em;
}
img.icon {
border-radius: 3px;
}
.user-icon {
width: 1.5em;
height: 1.5em;
border-radius: 100%;
margin-right: 0.5rem;
}
.user-icon-inner {
font-size: 0.8em;
}
.text-icon {
border: 1px solid #000;
text-align: center;
}
.page-cover-image {
display: block;
object-fit: cover;
width: 100%;
height: 30vh;
}
.page-header-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.page-header-icon-with-cover {
margin-top: -0.72em;
margin-left: 0.07em;
}
.page-header-icon img {
border-radius: 3px;
}
.link-to-page {
margin: 1em 0;
padding: 0;
border: none;
font-weight: 500;
}
p > .user {
opacity: 0.5;
}
td > .user,
td > time {
white-space: nowrap;
}
input[type="checkbox"] {
transform: scale(1.5);
margin-right: 0.6em;
vertical-align: middle;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.image {
border: none;
margin: 1.5em 0;
padding: 0;
border-radius: 0;
text-align: center;
}
.code,
code {
background: rgba(135, 131, 120, 0.15);
border-radius: 3px;
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 85%;
tab-size: 2;
}
code {
color: #eb5757;
}
.code {
padding: 1.5em 1em;
}
.code-wrap {
white-space: pre-wrap;
word-break: break-all;
}
.code > code {
background: none;
padding: 0;
font-size: 100%;
color: inherit;
}
blockquote {
font-size: 1.25em;
margin: 1em 0;
padding-left: 1em;
border-left: 3px solid rgb(55, 53, 47);
}
.bookmark {
text-decoration: none;
max-height: 8em;
padding: 0;
display: flex;
width: 100%;
align-items: stretch;
}
.bookmark-title {
font-size: 0.85em;
overflow: hidden;
text-overflow: ellipsis;
height: 1.75em;
white-space: nowrap;
}
.bookmark-text {
display: flex;
flex-direction: column;
}
.bookmark-info {
flex: 4 1 180px;
padding: 12px 14px 14px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.bookmark-image {
width: 33%;
flex: 1 1 180px;
display: block;
position: relative;
object-fit: cover;
border-radius: 1px;
}
.bookmark-description {
color: rgba(55, 53, 47, 0.6);
font-size: 0.75em;
overflow: hidden;
max-height: 4.5em;
word-break: break-word;
}
.bookmark-href {
font-size: 0.75em;
margin-top: 0.25em;
}
.sans {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
}
.code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
.serif {
font-family: Lyon-Text, Georgia, YuMincho, "Yu Mincho", "Hiragino Mincho ProN", "Hiragino Mincho Pro", "Songti TC", "Songti SC", "SimSun", "Nanum Myeongjo", NanumMyeongjo, Batang, serif;
}
.mono {
font-family: iawriter-mono, Nitti, Menlo, Courier, monospace;
}
.pdf .sans {
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol", 'Twemoji', 'Noto Color Emoji', 'Noto Sans CJK SC', 'Noto Sans CJK KR';
}
.pdf .code {
font-family: Source Code Pro, "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace, 'Twemoji', 'Noto Color Emoji', 'Noto Sans Mono CJK SC', 'Noto Sans Mono CJK KR';
}
.pdf .serif {
font-family: PT Serif, Lyon-Text, Georgia, YuMincho, "Yu Mincho", "Hiragino Mincho ProN", "Hiragino Mincho Pro", "Songti TC", "Songti SC", "SimSun", "Nanum Myeongjo", NanumMyeongjo, Batang, serif, 'Twemoji', 'Noto Color Emoji', 'Noto Sans CJK SC', 'Noto Sans CJK KR';
}
.pdf .mono {
font-family: PT Mono, iawriter-mono, Nitti, Menlo, Courier, monospace, 'Twemoji', 'Noto Color Emoji', 'Noto Sans Mono CJK SC', 'Noto Sans Mono CJK KR';
}
.highlight-default {
}
.highlight-gray {
color: rgb(155, 154, 151);
}
.highlight-brown {
color: rgb(100, 71, 58);
}
.highlight-orange {
color: rgb(217, 115, 13);
}
.highlight-yellow {
color: rgb(223, 171, 1);
}
.highlight-teal {
color: rgb(15, 123, 108);
}
.highlight-blue {
color: rgb(11, 110, 153);
}
.highlight-purple {
color: rgb(105, 64, 165);
}
.highlight-pink {
color: rgb(173, 26, 114);
}
.highlight-red {
color: rgb(224, 62, 62);
}
.highlight-gray_background {
background: rgb(235, 236, 237);
}
.highlight-brown_background {
background: rgb(233, 229, 227);
}
.highlight-orange_background {
background: rgb(250, 235, 221);
}
.highlight-yellow_background {
background: rgb(251, 243, 219);
}
.highlight-teal_background {
background: rgb(221, 237, 234);
}
.highlight-blue_background {
background: rgb(221, 235, 241);
}
.highlight-purple_background {
background: rgb(234, 228, 242);
}
.highlight-pink_background {
background: rgb(244, 223, 235);
}
.highlight-red_background {
background: rgb(251, 228, 228);
}
.block-color-default {
color: inherit;
fill: inherit;
}
.block-color-gray {
color: rgba(55, 53, 47, 0.6);
fill: rgba(55, 53, 47, 0.6);
}
.block-color-brown {
color: rgb(100, 71, 58);
fill: rgb(100, 71, 58);
}
.block-color-orange {
color: rgb(217, 115, 13);
fill: rgb(217, 115, 13);
}
.block-color-yellow {
color: rgb(223, 171, 1);
fill: rgb(223, 171, 1);
}
.block-color-teal {
color: rgb(15, 123, 108);
fill: rgb(15, 123, 108);
}
.block-color-blue {
color: rgb(11, 110, 153);
fill: rgb(11, 110, 153);
}
.block-color-purple {
color: rgb(105, 64, 165);
fill: rgb(105, 64, 165);
}
.block-color-pink {
color: rgb(173, 26, 114);
fill: rgb(173, 26, 114);
}
.block-color-red {
color: rgb(224, 62, 62);
fill: rgb(224, 62, 62);
}
.block-color-gray_background {
background: rgb(235, 236, 237);
}
.block-color-brown_background {
background: rgb(233, 229, 227);
}
.block-color-orange_background {
background: rgb(250, 235, 221);
}
.block-color-yellow_background {
background: rgb(251, 243, 219);
}
.block-color-teal_background {
background: rgb(221, 237, 234);
}
.block-color-blue_background {
background: rgb(221, 235, 241);
}
.block-color-purple_background {
background: rgb(234, 228, 242);
}
.block-color-pink_background {
background: rgb(244, 223, 235);
}
.block-color-red_background {
background: rgb(251, 228, 228);
}
.select-value-color-default {
background-color: rgba(206, 205, 202, 0.5);
}
.select-value-color-gray {
background-color: rgba(155, 154, 151, 0.4);
}
.select-value-color-brown {
background-color: rgba(140, 46, 0, 0.2);
}
.select-value-color-orange {
background-color: rgba(245, 93, 0, 0.2);
}
.select-value-color-yellow {
background-color: rgba(233, 168, 0, 0.2);
}
.select-value-color-green {
background-color: rgba(0, 135, 107, 0.2);
}
.select-value-color-blue {
background-color: rgba(0, 120, 223, 0.2);
}
.select-value-color-purple {
background-color: rgba(103, 36, 222, 0.2);
}
.select-value-color-pink {
background-color: rgba(221, 0, 129, 0.2);
}
.select-value-color-red {
background-color: rgba(255, 0, 26, 0.2);
}
.checkbox {
display: inline-flex;
vertical-align: text-bottom;
width: 16;
height: 16;
background-size: 16px;
margin-left: 2px;
margin-right: 5px;
}
.checkbox-on {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Crect%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%2358A9D7%22%2F%3E%0A%3Cpath%20d%3D%22M6.71429%2012.2852L14%204.9995L12.7143%203.71436L6.71429%209.71378L3.28571%206.2831L2%207.57092L6.71429%2012.2852Z%22%20fill%3D%22white%22%2F%3E%0A%3C%2Fsvg%3E");
}
.checkbox-off {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Crect%20x%3D%220.75%22%20y%3D%220.75%22%20width%3D%2214.5%22%20height%3D%2214.5%22%20fill%3D%22white%22%20stroke%3D%22%2336352F%22%20stroke-width%3D%221.5%22%2F%3E%0A%3C%2Fsvg%3E");
}
</style>
</head>
<body>
<main class="page serif">
<header><h1 class="page-title">20 simple steps to debug anything</h1></header>
<div class="page-body">
<br>
<p>Debugging is an everyday task. Your webpack build failed locally? Debug it. Your CI failed? Debug it. You wrote some code and broke everything? Debug it. Bob from the marketing team called you because you MUST fix a bug into production right now? Debug it.</p>
<br>
<p>You want to learn how to debug? Be our guest.</p>
<h2><strong>1. Don't panic</strong></h2>
<p>Keep a cool head, it makes the hard bugs simple and the impossible ones possible. So, if you struggle, remove your hand from the keyboard. Take a breath, get a glass of water. And go back to your seat.</p>
<h2><strong>2. SERIOUSLY, do NOT panic</strong></h2>
<p>Even if you have to debug your production server. Stress causes mistakes, mistakes cause more bugs, more bugs cause more stress.</p>
<p>As you will see later, debugging is a scientific process, so it is necessary to keep your head cool.</p>
<p>By the way... If your production is down, it's time to roll back!</p>
<h2><strong>3. </strong><strong>Verify the bug is not actually a feature</strong></h2>
<p>As features and edge cases grow it becomes impossible for one developer to keep all this complexity in their head. You should spend the time to check the defect you are seeing is outside the expectations of the application.</p>
<h2><strong>4. Reproduce the error where it occurred</strong></h2>
<p>Don’t wait for the failure to reproduce by itself. Make it fail again as it was reported. If it was in production, don’t start by reproducing the failure locally: do it in production (unless it involves dropping your database). Don't focus on making your staging data look like the production environment, you'll waste time and be misled by the wrong bugs.</p>
<p>Bugs are scarcely random. Try as hard as possible to find a set of initial conditions and/or actions which lead to a deterministic way to reproduce the failure. It helps.</p>
<h2><strong>5. Use the </strong><strong>logs, Luke</strong></h2>
<p>If there is information about your bug, it’s in the logs. So, find the logs, and use them. “Where are they?” you may ask. Look at the docs or the config of your failing system and you’ll know.</p>
<p>Then, reproduce the error to see the logs in real time.</p>
<p>You must mentally bind the action producing the failure to a system reaction. Otherwise, you could be biased and take an error log for something unrelated to your problem.</p>
<p>No logs? Go to step 10.</p>
<h2><strong>6. Read the error message, from left to right, from top to bottom</strong></h2>
<p>An error is text. Read it like text. Don't try to wild guess the cause by jumping right to the end of the stack trace. Being calm helps take the time to acknowledge the whole error message.</p>
<h2><strong>7. Read the error, again</strong></h2>
<p>The first time, you decipher. The second time, you understand.</p>
<h2><strong>8. Solve the bug</strong></h2>
<p>In most of the cases, the error message is crystal clear. And maybe the cause is trivial. Hence, interrogate the usual suspects: seek typos, verify you are not debugging the wrong server or the wrong git branch, ensure your libraries are up to date, clear your application cache, check your keyboard is actually plugged in your computer... And look at the last thing you changed before the failure (now you know why your teammates blame you when you push a 43874 line changes Pull Request).</p>
<p>You made a mistake. It happens. Fix it. And go to step 19. If it is actually a difficult bug, keep hope and go to the next step.</p>
<h2><strong>9. Search the error message online</strong></h2>
<p>Remember: you are not alone (unless you are coding in a weird language). Use your favorite search engine and search for your error. You might find a StackOverflow thread or a GitHub issue helping you to solve the bug you are facing. No results? Ask your team if someone has already encountered this bug.</p>
<p>Otherwise, move forward to the next step.</p>
<h2><strong>10. Setup a clean debugging workspace</strong></h2>
<p>You have eliminated the obvious causes, and the bug is not fixed yet? Brace yourselves, debugging is coming!</p>
<ul class="bulleted-list">
<li>Warn your team, you may spend some time on this and they should know. You also want them to keep you updated regarding your bug in case they encounter it in the wild.</li>
<li>Home sweet home, try to reproduce the bug on your local environment where it is the most comfortable place to debug. Setup your favorite debugger if it is not already done.</li>
<li>Even better, find the <em>smallest</em> set of actions/data that make your system fail deterministically and automate it to have the feedback loop as short as possible.</li>
<li>Fix the bugs you are aware of, they can mask what is really happening or even be sidekicks of your main bug.</li>
<li>Finally, prepare a place to log your debugging expedition. You'll see later why it's useful.</li>
</ul>
<h2><strong>11. Setup a clean debugging mindset</strong></h2>
<p>You reduced the noise in your tools, now you need to reduce it in your brain. Remember it is more a cognitive process rather than a technical one.</p>
<p>Doubt more than Descartes, especially your own assumptions. It’s rarely because of a Linux Kernel bug, face it. Remove your beliefs, you know the issue is not really random, you just don’t know when it is triggered. Unless you can prove it is true, replace your “<em>cannot</em>” with “<em>shouldn’t</em>”.</p>
<h2><strong>12. Create a model of your system</strong></h2>
<p>You have the tool, you have the mind, now you need the map.</p>
<p>Make a diagram of how your system is supposed to work, from one end to another, from your end user to the place where data is stored. Here you should see your frontend, your backend, the server and the cache systems between them, the data stores, every cog that is part of your machine. Display the way these parts communicate with one another. Be exhaustive, but not too precise. “All models are wrong, but some are useful” to quote George Box.</p>
<p>If you don’t have the knowledge to make that diagram, don’t go any further until you are able to do so, it is mandatory for your everyday job. Would you trust a mechanic to repair your car if they don’t know how the engine’s power is transmitted to the wheels?</p>
<h2><strong>13. Make educated guesses</strong></h2>
<p>Now you have a diagram of your system behaving correctly. You already know how to reproduce your bug, hopefully with an error message indicating what is wrong with your system.</p>
<p>By putting together your model, the facts and your experience, you should be able to formulate the most likely causes about what is going wrong. Jot them down your notes.</p>
<p>If you only have weird patterns and coincidences instead of a deterministic way to reproduce your bug in step 4, don’t be carried away by them. For instance, an error happening only at certain periods of time can be linked to the ongoing traffic on your server or a cron.</p>
<h2><strong>14. Run and devise an experiment</strong></h2>
<p>Here, we want to confirm or refute our previous hypotheses, as fast as possible. Yes, this is the step where we have to talk about dichotomy.</p>
<p>Choose one of your hypotheses and start from there. If you think the issue comes from the call to your DB, don’t bother looking into your frontend code. Put a debugger breakpoint straight at the suspicious SQL query building.</p>
<p>You think the bug is in the code? Don’t read all the code. Checkout another branch and see if it still fails. The bug is merged on master for a while and you don’t know where to look? Learn how to use <a href="https://git-scm.com/docs/git-bisect">git-bisect</a>, now. Then, find the faulty commit in no time and reduce the number of lines of code to explore.</p>
<p>Verify your hypotheses one after each other (remember humans are not well wired for parallel computing). Strike out the wrong ones on the list you previously wrote.</p>
<p>For each experiment, write down the cause you wanted to assess, what you did, in what order, and what happened as a result. It will ensure you are not doing wild guesses and give you material in case of backtracking or if you ask for help.</p>
<p>If you have not found the cause of the bug yet, you are likely closer than you think. You might have hypotheses that you do not know how to test yet. Or you remain stuck in a part of your system and are still looking for a path to reach the bedrock. So, prepare to dive.</p>
<h2><strong>15. We need to go deeper</strong><strong></strong></h2>
<p>The model built previously was good enough to approach the bug cause but not to touch it. Because you can’t reason about something you don’t perceive, refine the model to sharpen your sight of the problem.</p>
<p>Most of the time the obstacle lies at a system boundary, like a function from a vendor library, an API provided by another team or even two modules inside your own software. So here are some ideas to scout through the fog:</p>
<ul class="bulleted-list">
<li><strong>Read the manual.</strong> Even if it looks big, the manual contains knowledge about how to use your vendor. Sometimes, you have to stop looking at your code to find the truth. And when the docs is really good, it provides you the small details that are actually very important for your issue. <em>Disclaimer: read manuals the same way you read your error logs</em>. ;-]</li>
<li><strong>Read your libraries source code.</strong> Don’t be afraid even if it is not <em>your code</em>, it’s still code. You are able to read it. Understand it might take more time because libraries have their own internal idioms. It will lead you closer to the bug cause. And make you a better developer.</li>
<li><strong>Look at the signal.</strong> If the problem happens between two nodes, the information you need to observe is on the wire. Learn how to read a <a href="https://www.tcpdump.org/manpages/tcpdump.1.html">tcpdump</a>/<a href="https://www.wireshark.org/">wireshark</a> trace. Follow your data with a debugger. Look at what your garbage collector keeps in the heap to understand a memory leak. Unravel your hanging process thanks to <a href="https://strace.io/">strace</a>. And don’t trust your understanding of the ORM you use, read the generated SQL query and execute it by yourself.</li>
<li><strong>Know your concurrency fundamentals.</strong> Deadlocks, live locks, shared memory, race conditions… Those are the worst and unless your software runtime includes a race detector, you need to use 100% of your brain to get rid of concurrency bugs. They deserve their own article.</li>
</ul>
<p>In any case, search for depth. Don’t go halfway to learn something new or your intuition will add more fog. Educated guesses are for mastered topics.</p>
<p>If you are not able to delve anymore, don’t get lost in limbo. Tag a partner!</p>
<h2><strong>16. Ask for help</strong></h2>
<p>You’ve dug as much as you could and still cannot pinpoint what’s wrong? That can happen, it’s okay, we are fallible beings.</p>
<p>You may have not seen the smoking gun because you are not lucid anymore. Sometimes all you need is to take a step back, and that can be offered by something as simple as <a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging">a rubber duck</a>.</p>
<p>If the duck doesn’t make the cut, set aside your ego and your shyness to ask for help from a fellow developer. Search first for an expert in the area you are investigating, but any help is welcome here.</p>
<p>Thanks to your debug log, present to them your debugging process. State all the facts, even the weird ones and keep away any results from your inductive reasoning as you do not want to influence them.</p>
<p>If the bug is still there after you’ve consulted every person likely to help in your team or surrounding ones, go online. Post a small portion of your code that can exhibit your problem. Describe how to reproduce your bug and ask politely for help. People like puzzles, are eager to help and will collaborate to find a solution. <a href="https://stackexchange.com/sites">70% of StackOverflow and 78% of ServerFault questions have at least one answer with upvotes</a>.</p>
<p>You have cast your hook to the water, now wait for the help to bite and give you a fix to try.</p>
<h2><strong>17. Ensure </strong><em><strong>this</strong></em><strong> failure is fixed</strong></h2>
<p>Here, we suppose you have found something that made your bug disappear.</p>
<p>Software engineering is <em>mostly</em> deterministic: you must have done something. A bug cannot simply vanish in the air. (If it happened don't celebrate and go back to step 10 instead.)</p>
<p>Assess your fix with the same scientific mindset as before:</p>
<ul class="bulleted-list">
<li>Keep only what you think is necessary for your fix to work.</li>
<li>Use the test from the step 10 to check that the bug is gone with the fix.</li>
<li>Remove the fix and use the same test to check that the bug is back.</li>
</ul>
<p>If the fix doesn’t pass this test, the two main hypotheses are that:</p>
<ul class="bulleted-list">
<li>Your fix is incomplete and need other changes made during the process. Something considered unnecessary might be required.</li>
<li>You had a lapse in concentration, your fix never really worked.</li>
</ul>
<p>In both cases, use this new data to refine your understanding of the problem and go back to step 13. Stay strong, you’re closing in!</p>
<p>If the fix passes the previous test, good job, the bug is dead!</p>
<h2><strong>18. Make it easier next time</strong></h2>
<p><em>This</em> bug is dead. But:</p>
<ol class="numbered-list" start="1">
<li>It could have been a trivial bug solved at step 8.</li>
<li>Bugs have friends.</li>
</ol>
<p>Face it, software engineers spend more time understanding why things do not work as intended than coding features. If you reduce the time to debug issues, you will coincidentally increase the time where you are creating value instead of repairing it.</p>
<p>Keep all the things you added into the codebase you wish you had at the beginning of your bug quest: log messages at debug levels with input/output values, HTTP status code respecting the RFC semantics, an actual crash in a previously silent catch block...</p>
<p>The same goes for tool created to investigate your problem, don’t discard it. Document why it’s here and how it works, and commit it with the bugfix.</p>
<p>Anyway, the easiest bug is the one that does not occur. You put out the fire, now make your code fireproof.</p>
<h2><strong>19. Ensure the bug never comes back</strong></h2>
<p>Before doing anything to prevent a bug to come back, ask yourself why it happened in the first place. The causes are often the same: an unmanaged edge case, a developer does not know how to use one of the tools, an abstraction is not representing the domain enough… In security you think of attack surface. Here, look at what is error prone. And it’s not always in the code.</p>
<p><em>Disclaimer: each of the following parts needs its own article or book.</em></p>
<p><strong>Remove other occurrences</strong></p>
<p>If a misconception introduced the bug, there are chances the same mistake has been made somewhere else. Search the bad snippet and replace it with the good one. It’s not enough but it’s a good start.</p>
<p><strong>Refactor</strong></p>
<p>Good code is mistake-proof. Some people think "no abstraction is better than bad abstraction". But both lead to bugs. Your job is to write good abstractions that last. So when a bug occurs, an engineer might have failed to bring such abstraction. Take the time to repair the broken parts. <a href="https://martinfowler.com/articles/is-quality-worth-cost.html">Investing in internal software quality leads to better external quality</a>.</p>
<p><strong>Add non regression testing</strong></p>
<p>If you can’t eradicate the bug cause, at least make it impossible to reach your master branch or production again. Basically, write the right test suite which detects the failure and run it on every commit/pull request. The test must fail if you stash your patch.</p>
<p><strong>Write a standard</strong></p>
<p>You learned how to fix the bad with the good. But to share the good, it must be written somewhere. Write down the pitfalls, give examples of the wrong way and the right way to use a tool, and share it to your team.</p>
<p><strong>Train your team</strong></p>
<p>Reading a standard is not enough to fully learn a skill. Take time to present the standard and use it in a pair programming session next time a fellow developer has to code by practicing what you just wrote.</p>
<p><strong>Automate the standard</strong></p>
<p>We can’t remember everything and the most error prone system in this chaos is our human selves. Automate good practices to reduce the risk of making mistakes. Use tools like code generation, declarative scripting, new linter rule...</p>
<h2><strong>20. Celebrate!</strong></h2>
<p>This bug is now definitely behind you. This is good, isn’t it?</p>
<p>To share this bliss, we encourage you to write down what happened and memorize it. War stories are always fun to tell, fun to hear. They are also a great way for others to remember obscure behaviors to look at when they have ruled out common hypotheses.</p>
<p>Now you’re ready to fight those bugs!</p>
<figure class="block-color-gray_background callout" style="white-space:pre-wrap;display:flex"
>
<div style="font-size:1.5em"><span class="icon">👤</span></div>
<div style="width:100%"><strong>Authors</strong>: <a href="https://blog.theodo.com/yann-jacquot/">Yann Jacquot</a> & <a href="https://twitter.com/RemyLuciani">Rémy Luciani</a></div>
</figure>
</div>
</main>
</body>
</html>