00:00:05.940
this talk is called debugging techniques
00:00:08.700
for uncertain times
00:00:10.800
it's by Chelsea Troy
00:00:12.719
which is me
00:00:14.700
you can reach me at Chelsea Chelsea
00:00:16.859
troy.com
00:00:18.180
or you can reach out to me on Twitter at
00:00:20.640
hlc touring
00:00:27.180
before I was a software engineer
00:00:30.359
I was almost everything else
00:00:33.960
I coached rowing at a high school in
00:00:35.940
Miami
00:00:36.960
I blogged for a startup whose business
00:00:39.239
model turned out to be illegal
00:00:41.879
I attended a bar and performed stand-up
00:00:44.340
comedy I danced with fire on haunted
00:00:47.399
riverboats I edited a quack psychology
00:00:50.039
magazine
00:00:51.360
I did open source investigations for
00:00:53.640
international crime ranks
00:00:56.160
all that sounds very fun and exciting
00:00:59.100
in hindsight
00:01:01.320
but at the time it wasn't a fun journey
00:01:04.500
of self-discovery I was compelled to
00:01:08.400
adapt at frequent intervals in order to
00:01:11.159
stay afloat
00:01:13.439
I got into software engineering for the
00:01:16.200
job security not out of passion for
00:01:19.439
programming
00:01:21.180
but some of the coping mechanisms that I
00:01:23.700
learned from those frequent adaptations
00:01:26.180
followed me into the programming world
00:01:29.700
it turns out the skills that equip us to
00:01:32.820
deal with rapid substantial changes to
00:01:35.220
our lives also make us calmer more
00:01:38.520
effective debuggers
00:01:41.280
debugging in my opinion doesn't get the
00:01:44.939
attention it deserves from the
00:01:46.500
programming community
00:01:48.000
we imagine it is this amorphous skill
00:01:51.659
one we rarely teach for which we have no
00:01:55.860
apparent Praxis or pedagogy
00:01:59.939
instead we teach people how to write
00:02:02.820
features how to build something new in
00:02:06.840
the software that we know when we
00:02:09.599
understand what the code is doing when
00:02:12.780
we have certainty
00:02:15.720
I suspect you've watched a video or two
00:02:19.860
about programming
00:02:21.599
if I didn't know better I'd say you're
00:02:23.700
watching one right now
00:02:26.160
this one doesn't deal in code examples
00:02:28.400
but I suspect you've seen demos where
00:02:31.500
speakers share code on their screens or
00:02:34.379
demonstrate how to do something in a
00:02:36.480
code base during a video recording
00:02:39.780
here's the dirty secret and I suspect
00:02:43.019
you already know it
00:02:44.940
when we sling demos on stage or upload
00:02:48.660
them to YouTube that's definitely not
00:02:52.800
the first time we've written that code
00:02:55.620
we've probably written a feature like
00:02:57.840
that one in production before then we
00:03:00.959
modified it to make it fit in a talk or
00:03:04.140
a video
00:03:05.640
then we practice
00:03:07.680
over and over and over
00:03:11.760
we need to minimize all mistakes and
00:03:14.340
error messages we learn to avoid every
00:03:17.760
rake just
00:03:20.280
for that code
00:03:22.560
and sometimes in recording we still mess
00:03:25.140
it up we pause the recording we back it
00:03:28.739
up and we do it again
00:03:31.200
until it's perfect
00:03:36.300
we know what we're writing
00:03:39.959
and that's what gets modeled in
00:03:42.540
programming education
00:03:44.580
but that's not the case when we're
00:03:46.680
writing code on the job
00:03:48.840
in fact many of us spend most of our
00:03:52.620
time on the job writing something that's
00:03:54.959
a bit different from anything we've done
00:03:57.959
before
00:03:59.700
if we had done this exact thing before
00:04:01.920
our clients would be using the
00:04:04.019
off-the-shelf solution that we wrote the
00:04:05.819
first time not paying our exorbitant
00:04:08.400
rates to have it done custom
00:04:10.920
we spend the Lion's Share of our time
00:04:14.480
outside the comfort zone of code we
00:04:18.359
understand
00:04:20.419
debugging feels hard in part because we
00:04:25.199
take skills that we learn from feature
00:04:27.840
building in the context of certainty
00:04:31.560
and attempt to apply them in a new
00:04:34.680
context
00:04:36.360
a context where we don't understand what
00:04:40.020
our code is doing where we are
00:04:42.479
surrounded by uncertainty
00:04:47.040
and that is the first thing we need to
00:04:50.280
debug effectively
00:04:53.280
we need to acknowledge that we do not
00:04:57.600
already understand the behavior of our
00:05:02.100
code
00:05:03.900
this sounds like an obvious detail but
00:05:07.979
we often get it wrong
00:05:10.199
and it adds stress that makes it harder
00:05:13.620
for us to find the problem
00:05:16.580
because we've only seen models where the
00:05:20.160
programmer knew what was going on we
00:05:22.740
think we're supposed to do that we're
00:05:25.500
supposed to know what's going on and we
00:05:28.680
don't
00:05:29.400
we better hurry up and figure it out
00:05:32.340
but speed is precisely the enemy with
00:05:36.780
Insidious bucks
00:05:38.759
we'll get to why later
00:05:42.060
I struggled with this same thing in my
00:05:44.880
decade of odd jobs I felt inadequate
00:05:47.820
unfit for adulthood because I didn't
00:05:50.400
know how to do my taxes or find my next
00:05:53.160
gig or say the right thing to my family
00:05:55.800
or make my life meaningful
00:05:59.820
and how would I have known those things
00:06:03.600
but it topped off all my personal
00:06:06.240
struggles with this generous helping of
00:06:09.320
insecurity and guilt and inadequacy that
00:06:13.199
drove me to run away from issues rather
00:06:16.380
than address them
00:06:19.080
but failing enough times over a long
00:06:22.020
enough period made me realize not
00:06:25.080
understanding is normal
00:06:27.259
or at least it's my normal
00:06:31.139
so I learned to notice and acknowledge
00:06:34.500
my insecurity and not let it dictate my
00:06:38.400
actions
00:06:39.840
when my feelings of inadequacy screeched
00:06:42.780
at me to speed up
00:06:44.460
that's when I most needed to slow
00:06:48.300
down
00:06:50.460
to figure out why exactly I wasn't
00:06:55.319
getting what I expected
00:06:58.979
I needed to get out of progress mode and
00:07:02.940
into
00:07:03.800
investigation mode
00:07:06.539
and this is the second thing we need to
00:07:09.780
debug effectively
00:07:11.580
we need to switch modes when we debug
00:07:14.039
from focusing on progress to focusing on
00:07:18.000
Investigation
00:07:20.520
the most common debugging strategy I see
00:07:23.460
looks something like this
00:07:26.340
where
00:07:27.780
we try our best idea first
00:07:30.599
and if that doesn't work our second best
00:07:33.539
idea
00:07:34.740
and so forth
00:07:37.560
I call this the standard strategy
00:07:40.800
and if we understand the behavior of our
00:07:43.139
code then this is often the quickest way
00:07:45.300
to diagnose what's going on
00:07:47.520
so it is a useful strategy
00:07:50.639
the problem arises when we don't
00:07:53.759
understand the behavior of our code and
00:07:57.360
we keep repeating this strategy as if we
00:08:00.780
do
00:08:02.340
we hurt our own cause by operating as if
00:08:05.460
we understand code when we don't
00:08:08.340
in fact the less we understand the
00:08:10.979
behavior of our code the lower the
00:08:13.139
correlation between the things we think
00:08:14.880
are causing the bug and the thing that's
00:08:16.979
really causing the bug and the weaker
00:08:19.860
this strategy becomes
00:08:23.400
so instead
00:08:25.500
we get this
00:08:28.080
where we Circle among ideas that don't
00:08:30.539
work because we're not sure what's
00:08:32.640
happening but we don't know what else to
00:08:35.880
do
00:08:40.039
once we have established that we do not
00:08:42.959
understand the behavior of our code we
00:08:46.260
need to stop focusing on fixing the
00:08:49.620
problem and instead ask questions that
00:08:52.920
help us find the problem and by the
00:08:57.240
problem I mean specific invalid
00:09:01.440
assumptions we're making about this code
00:09:06.839
the precise place that is where we are
00:09:12.360
wrong
00:09:14.519
let me show you a couple of examples of
00:09:16.680
how we might do that
00:09:19.980
we could use a binary search strategy
00:09:22.920
in this strategy we assume the code
00:09:25.680
follows a single threaded linear flow
00:09:28.440
from the beginning of execution where we
00:09:30.600
run the code to the end of execution or
00:09:33.420
where the bug happens
00:09:36.300
we choose a spot more or less in the
00:09:39.360
middle of that and run tests on the
00:09:41.700
pieces that would contribute to the code
00:09:43.920
flow
00:09:45.060
and now by test I don't necessarily mean
00:09:48.360
an automated test though that's one
00:09:50.700
instrument we can use to do this
00:09:54.120
by test in this case I mean the process
00:09:58.080
of getting feedback as fast as possible
00:10:01.320
on whether our assumptions about the
00:10:04.260
state of the system at this point
00:10:06.240
match the values in the code
00:10:10.380
because it's not just that Insidious
00:10:14.160
bugs come from inaccurate assumptions
00:10:17.160
it's deeper than that
00:10:19.519
insidiousness as a characteristic of
00:10:23.220
bugs comes from inaccurate assumptions
00:10:28.260
we're looking in the code when the
00:10:31.260
problem is rooted in our understanding
00:10:34.740
it takes an awfully long time to find
00:10:37.440
something when we're looking in the
00:10:40.260
wrong place
00:10:43.080
it's hard for us to detect when our
00:10:45.360
assumptions about a system are wrong
00:10:47.519
because it's hard for us to detect when
00:10:50.399
we're making assumptions at all
00:10:53.220
assumptions by definition describe
00:10:56.220
things we're taking for granted they
00:10:58.980
include all the details into which we
00:11:00.959
are not putting thought
00:11:03.000
we're sure that that variable has to be
00:11:05.820
present at this point I mean the way
00:11:08.040
this whole thing is built it has to be
00:11:09.899
have we checked well
00:11:13.019
uh no
00:11:14.820
never thought to do that never thought
00:11:17.160
of this as an assumption it's just the
00:11:19.740
truth
00:11:21.540
but is it
00:11:24.779
this is where fast feedback becomes
00:11:27.000
useful
00:11:27.959
we can stop
00:11:29.640
create a list of our assumptions
00:11:32.100
and then use the instruments at our
00:11:34.079
disposal to test them
00:11:37.260
we have a number
00:11:38.940
automated tests are one such instrument
00:11:40.880
tests allow us to run a series of small
00:11:43.500
feedback loops simultaneously we can
00:11:46.200
check lots of paths through our code
00:11:48.060
quickly and all at once
00:11:50.160
tests aren't inherently a more moral way
00:11:53.220
to develop software or Assemble only
00:11:55.620
like that they just do really well on
00:11:58.380
the key metric that matters to us in
00:12:00.180
quality control the tight feedback loop
00:12:04.019
manual run-throughs are another
00:12:05.700
instrument developers start doing this
00:12:08.220
almost as soon as they start to write
00:12:10.079
code and we continue to do it when we
00:12:12.420
want to check things out
00:12:14.700
breakpoints we can stop the code at a
00:12:17.579
specific line and open a console to look
00:12:19.740
at the variables in scope at that point
00:12:22.320
we can even run methods in scope from
00:12:24.600
the command line and see what happens
00:12:27.660
print statements if breakpoints aren't
00:12:29.940
working or if the code is multi-threaded
00:12:31.980
or asynchronous in such a way that we
00:12:34.079
don't know whether the buggy code will
00:12:36.360
run before or after our breakpoint print
00:12:38.880
statements come in really handy
00:12:41.579
logging
00:12:43.019
for deployed code or code where we can't
00:12:45.600
access standard out we might need more
00:12:47.880
robust logging instead a bonus here is
00:12:51.420
that a more permanent logging framework
00:12:53.459
within our code can help us diagnose
00:12:55.440
issues after the fact or after deploying
00:12:59.399
and changing small things
00:13:01.620
if I think I know how a variable works I
00:13:04.560
can change its value a little bit and
00:13:06.839
predict how the program should react and
00:13:09.540
then see if it matches
00:13:11.579
this helps to establish my understanding
00:13:13.800
of what's in scope and which code is
00:13:15.839
affecting what
00:13:17.880
now here's where assumption detection
00:13:19.680
comes into play
00:13:21.660
we're likely to thoughtlessly assume
00:13:23.820
that we know things at this point that
00:13:25.800
variable X should be this that that
00:13:28.079
class should be instantiated
00:13:30.300
Etc
00:13:31.380
this is where Insidious bugs like to
00:13:34.079
hide
00:13:34.920
in the stuff we're not checking
00:13:38.540
and this is the third thing we need to
00:13:41.160
debug effectively
00:13:43.800
the ability to identify what is the
00:13:46.139
truth
00:13:47.160
and what is our perspective
00:13:50.760
I cannot tell you how many things in
00:13:54.000
those early years of my independent life
00:13:56.120
I knew beyond a shadow of a doubt to be
00:14:00.300
true
00:14:02.100
and maybe just maybe in a vanishingly
00:14:06.300
small fraction of cases
00:14:08.880
I was half right
00:14:11.940
but in all the other cases learning to
00:14:15.000
differentiate between My Views and
00:14:16.920
empirical evidence and learning to
00:14:19.579
reconsider my perspectives has been my
00:14:24.420
key to leveling up everywhere in my life
00:14:30.540
so let's whip out our programming
00:14:33.480
journals and try an exercise that will
00:14:36.120
help us learn to detect and question our
00:14:38.820
assumptions
00:14:40.560
at each step represented by a rounded
00:14:43.500
box in one of our debugging flow charts
00:14:45.540
we'll write down what step of the
00:14:47.579
process we're checking
00:14:49.560
and then we make a list for assumptions
00:14:52.199
and we make a list for checks
00:14:57.300
in this example the given section
00:14:59.579
attempts to explicitly State our
00:15:01.440
assumptions the things we are not
00:15:04.500
checking
00:15:06.060
the checking section lists the things we
00:15:09.360
are checking and we can Mark each one
00:15:11.820
with a check mark or an X depending on
00:15:13.680
whether they produce what we expect
00:15:16.860
this exercise seems tedious
00:15:20.579
right up until we've checked every
00:15:23.579
possible place in the code and all our
00:15:26.100
checks are working but the bug still
00:15:30.600
happens
00:15:32.519
at that point it's time to go back and
00:15:36.240
assess our Givens one by one
00:15:41.279
I recommend keeping these notes
00:15:44.880
how often do bugs thwart us for long
00:15:47.579
periods of time and end up hiding in our
00:15:51.060
assumptions
00:15:52.560
what can we learn from this about
00:15:55.500
spotting our assumptions and which of
00:15:58.560
our assumptions run the highest risk of
00:16:00.600
being incorrect
00:16:03.000
at each check whether we find something
00:16:05.519
amiss or not with a binary search we
00:16:08.279
should reduce the problem Space by half
00:16:10.079
and hopefully that way find the case of
00:16:12.959
our Insidious bug in relatively few
00:16:15.240
steps
00:16:17.579
but what we are establishing with notes
00:16:20.399
like these is a pattern of what we think
00:16:23.459
and where it lines up with a shared
00:16:25.320
reality
00:16:28.440
I should mention there are cases where
00:16:30.660
binary search won't work namely cases
00:16:33.300
where the code path doesn't follow a
00:16:35.160
single threaded linear flow from
00:16:36.839
beginning of execution to end and in
00:16:39.240
those cases we may need to trace the
00:16:41.759
entire code path from beginning to end
00:16:43.740
ourselves
00:16:45.959
but the concept remains we explicitly
00:16:50.160
list our assumptions and checks to
00:16:52.740
investigate our code like an expert
00:16:54.959
witness to gather answers that lead us
00:16:58.019
to the defect
00:17:00.839
we are training our brains to spot our
00:17:03.720
own assumptions we know it's working if
00:17:06.240
our given list starts getting longer we
00:17:10.079
especially remember to include Givens
00:17:12.419
that weren't what we thought when we
00:17:13.980
hunted down previous bugs it is
00:17:16.520
specifically this intuition that we are
00:17:19.980
building when we get better at debugging
00:17:22.740
through practice
00:17:25.199
however because we do not deliberately
00:17:27.480
practice it nor generalize the skill to
00:17:29.940
other languages and Frameworks our
00:17:31.919
disorganized approach to learning
00:17:33.419
debugging from experience tends to limit
00:17:35.400
our skills to the stacks we have written
00:17:38.280
by identifying common patterns instead
00:17:41.220
in the assumptions we tend to make that
00:17:43.620
end up being wrong and causing bugs we
00:17:47.220
can improve our language agnostic
00:17:49.919
debugging intuition
00:17:53.100
this is the final thing we need to debug
00:17:55.980
effectively
00:17:58.799
the ability to see how the things we're
00:18:01.440
doing now serve longer term goals
00:18:06.299
I am an expert
00:18:10.320
stressing myself out about things
00:18:13.320
I started Young
00:18:14.820
on a trip to Disney World my mom
00:18:16.679
remembers changing my diaper on a bench
00:18:18.600
as I cried careful careful afraid she'd
00:18:22.200
let me roll off
00:18:24.120
I continued my winning streak of stress
00:18:26.220
through high school where I decided that
00:18:28.020
college acceptances would determine my
00:18:29.700
fate in life and afterward as I
00:18:31.980
continued to sensationalize the results
00:18:33.600
of tests Sports competitions and job
00:18:35.820
interviews as make or break moments
00:18:39.179
I have since learned to see no
00:18:42.000
particular moments as make or break
00:18:44.580
I have taken the power back from my
00:18:47.280
evaluators
00:18:48.539
if I go to an interview now my goals are
00:18:51.360
to meet someone and to learn something
00:18:55.799
whether or not I get the job I came out
00:18:58.440
with more understanding than I went in
00:19:00.299
with and in that sense I have succeeded
00:19:03.600
everything is in service to something
00:19:06.299
else that's coming so that even if I
00:19:08.760
fail I have taken a step forward
00:19:13.559
in that same way
00:19:15.780
every Insidious bug presents a golden
00:19:18.840
opportunity to teach us something
00:19:22.980
maybe we hate what we learn
00:19:25.620
that's okay
00:19:27.059
we know it now and we can use it to save
00:19:29.940
trouble for someone else later
00:19:32.520
or maybe we learn something deep and
00:19:34.799
insightful that we can carry with us to
00:19:37.559
other code bases to other workplaces or
00:19:40.559
maybe even home to our hobbies and our
00:19:43.020
loved ones
00:19:44.640
but either way we get to hone our skills
00:19:48.240
at conversing with code
00:19:50.520
and with navigating uncertainty in our
00:19:53.580
lives
00:19:55.080
we can practice acknowledging what we
00:19:57.480
don't understand
00:19:59.100
learning to slow down
00:20:01.940
differentiating our views from a shared
00:20:04.860
reality
00:20:06.240
and finding ways to keep moving forward
00:20:11.280
and spending time on those skills is a
00:20:14.100
pretty good investment
00:20:15.960
thank you