User Journey
Beginning from the same point, we are going to present two distinct user journeys in which Frank uses different tools to achieve his goal:
- Branch A on the left describes a debugging session using traditional debugging techniques and practices as described by Alabor et al. [1]. Frank will use imperative debugging utilities built-in to Visual Studio Code and manual code modification to reach his goal.
- Branch B on the right describes how Frank uses the prototype of an extension for Visual Studio Code providing a less invasive debugging technique for RxJS-based source code.
Step 1 Build Hypothesis
After Frank recreated the behavior reported in the bug report, he
starts analyzing the source code of the application. In this
process, he formulates his first hypothesis about what could cause
the unexpected behavior: Frank suspects the
flatMap
operator in Line 19 to be responsible.
Frank wants to have a closer look on the operators runtime behavior, which is why he decides to use debugging utilities.

Step 2.A Instrument Hypothesis
Using the built-in debugger of Visual Studio Code, Frank adds a
breakpoint to Line 19 where the
flatMap
operator is called with the intention to stop
the program execution every time a values "flows" through the
operator.

Step 2.B Instrument Hypothesis
Frank navigates to the flatMap
operator in Line 19 and
selects the "Add Log Point to Operator..." code action provided by
the Visual Studio Code extension.

Step 3.A Test Hypothesis
Frank launches the application. Before the web browser can display anything, the debugger in Visual Studio Code halts the program execution at the breakpoint in Line 19.
Contrary to Franks expectation, the application was already paused
during the creation of the flatMap
operator rather than
when a value was processed by it.
Frank resumes the program execution, though the breakpoint never pauses the application again.

Step 3.B Test Hypothesis
Frank launches the application. While reproducing the reported bug
in the browser, the extension produces a log of all events detected
at the flatMap
operator in Line 19.
Frank recognizes a peculiar pattern: After the reset button was clicked, the log point reports multiple values emitted for each click on the increase/decrease button.
This confirms Franks hypothesis about the
flatMap
operator: After the user clicked the reset
button, the operator emits multiple values.

Step 4.A Instrument Hypothesis
After Franks first failed instrumentation attempt using breakpoints,
he decides to add trace log statements using the
tap
operator manually. He adds multiple of them on
Lines 19, 24, 28, and 32.

Step 4.B Resolve Bug
After researching the RxJS documentation, Frank realizes that the
flatMap
operator [3] does not
unsubscribe observables it created earlier. This sounds like a
reasonable explanation for the observed behavior.
Frank replaces the faulty operator with the
switchMap
[4] operator.

Step 5.A Test Hypothesis
Frank launches the application again. The manually added code generates the expected trace log in the debuggers console as Frank executes the steps necessary to recreate the reported bug.
Once the application produced enough logs, Frank starts to analyse them. Even though it is hard to reassign a log entry to a piece of code and a related action, Frank recognizes a peculiar pattern after some time: After the reset button was clicked, the log statement on Line 32 is executed multiple times, even though the increase/decrease button gets clicked only once.
This confirms Franks hypothesis about the
flatMap
operator: After the user clicked the reset
button, the operator emits multiple values.

Step 5.B Verify
Frank launches the application again and repeats the steps necessary to reproduce the reported bug.
The application appears to work correctly now. A quick look at the log point monitor confirms that the previously observed behavior of multiple values emitted is fixed.
Frank has reached his goal successfully.

Step 6.A Resolve Bug
After researching the RxJS documentation, Frank knows that the
flatMap
operator [3] does not
unsubscribe observables it created earlier. This sounds like a
reasonable explanation for the observed behavior.
Frank replaces the faulty operator with the
switchMap
[4] operator.

Step 7.A Verify
Frank launches the application again and repeats the steps necessary to reproduce the reported bug.
The application appears to work correctly now. A look at the trace log confirms that the previously observed behavior of multiple values emitted is gone.

Step 8.A Revert Hypothesis Instrumentation
Frank removes all tap
operators he added solely for the
trace log generation, except the one in Line 24.
Another engineer notices this leftover during the code review, fortunately. Frank removes the forgotten statement afterwards.
Finally, Frank has reached his goal.
