List

Techniques for Uncertain Times

Techniques for Uncertain Times

by Chelsea Troy

In her talk titled "Debugging Techniques for Uncertain Times" at RailsConf 2021, Chelsea Troy explores the parallels between debugging code and managing uncertainty in life. Recognizing that traditional programming education tends to focus on feature development under certainty, Troy argues that debugging, often perceived as an undeveloped skill, deserves more emphasis. She asserts that the techniques that enhance our debugging ability can also help us navigate unpredictable life changes.

Key Points Discussed:
- Background of the Speaker: Chelsea shares her diverse experiences before becoming a software engineer, highlighting her adaptability and the coping mechanisms developed through those challenges.
- The Reality of Debugging: The speaker explains that debugging occurs in a context of uncertainty, contrasting it with the comfort of feature development where developers usually understand the code's behavior.
- Acknowledgment of Uncertainty: To debug effectively, it is crucial to accept that one does not understand their code's behavior.
- Mode Switching: When debugging, developers should switch from a progress-oriented mindset to an investigative approach, focusing on understanding the problem rather than hastily seeking solutions.
- The Flaw of the Standard Strategy: Troy critiques a common debugging strategy where programmers sequentially test their best guesses, emphasizing that this approach is ineffective when understanding is lacking.
- Assumption Testing: She introduces a binary search method as an effective strategy to identify specific erroneous assumptions about the code.
- Tools for Debugging: The speaker discusses various tools and techniques, such as automated tests, manual run-throughs, breakpoints, print statements, and logging, to gather essential feedback and test assumptions.
- Identifying Truth vs. Perspective: Troy stresses the importance of distinguishing between what one perceives to be true and verified facts when debugging.
- Long-Term Skills Development: She concludes that the skills gained in debugging can be transferred to other areas of life, allowing developers to handle uncertainty more effectively.

Conclusions and Takeaways:
- Acknowledging what we don't understand is the first step towards effective debugging.
- Slowing down during the debugging process can lead to better investigation outcomes.
- Differentiating personal perspectives from empirical evidence is vital for effective problem-solving.
- Every bug presents an opportunity for learning that can enhance both technical and life skills, helping individuals navigate future uncertainties more adeptly.

When we learn to code, we focus on writing features while we understand what the code is doing. When we debug, we don’t understand what our code is doing. The less we understand, the less likely it is that our usual programming mindset—the one we use for feature development—can solve the problem.

It turns out, the skills that make us calmer, more effective debuggers also equip us to deal with rapid, substantial changes to our lives.

Whether you’re uncertain about what’s going on in your code, your life, or both, in this talk you’ll learn debugging techniques to get you moving forward safely.

RailsConf 2021

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