<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Towards Object-centric Time-traveling Debuggers</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Maximilian Ignacio Willembrinck Santander</string-name>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Steven Costiou</string-name>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Adrien Vanègue</string-name>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Anne Etien</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Univ. Lille, CNRS</institution>
          ,
          <addr-line>Inria, Centrale Lille, UMR 9189 CRIStAL</addr-line>
        </aff>
        <aff id="aff1">
          <label>1</label>
          <institution>Univ. Lille, Inria</institution>
          ,
          <addr-line>CNRS, Centrale Lille, UMR 9189 CRIStAL</addr-line>
        </aff>
      </contrib-group>
      <abstract>
        <p>Object-centric debugging aims at facilitating the debugging of object-oriented programs by focusing debugging operations on specific objects. This technique is tedious to use because developers have to manually find objects to debug, which is not straightforward. Time-traveling debuggers allows developers to explore executions back and forth in time. It has been shown that time-traveling features efectively facilitate debugging and program understanding. We propose to combine these techniques to benefit from both of them to debug objectoriented programs. Time-travel navigation could help finding and remembering objects by providing means to explore executions back and forth. Object-centric debugging could extend time-traveling debugging with object-centric exploration features. These techniques have never been combined, and the challenges and benefits of such combination have never been explored. We present SeekerOC, a time-traveling debugger prototype which provides object-centric debugging support. To combine both techniques, we use Time-Traveling Queries, a query system to automatically explore executions. We discuss the expected benefits of this combination, and we argue that exploring object-centric time-traveling debugging will open new research perspectives towards more efective debugging techniques and tools for object-oriented systems.</p>
      </abstract>
      <kwd-group>
        <kwd>eol&gt;Object-Centric Debugging</kwd>
        <kwd>Time-Travel Debugging</kwd>
        <kwd>Program Comprehension</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. Introduction and Motivation: Debugging Objects</title>
      <p>
        To debug their programs, developers use debuggers which traditionally provide a set of
standard debugging operations. Some of these debugging operations (e.g., breakpoints)
are defined for a class ( e.g., in a method) and apply to all instances of that class.
Meanwhile, object-centric debugging is a technique proposed to improve the debugging
of object-oriented systems by scoping object-centric debugging operations to specific
objects [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. This helps debugging by reducing user interactions to understand bugs [
        <xref ref-type="bibr" rid="ref1 ref2">1, 2</xref>
        ],
and by exposing and hot fixing buggy objects [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. However in practice, object-centric
debugging is dificult to use. Developers have to manually explore their executions to
ifnd objects to debug. This is tedious and error-prone. Developers have to repeat many
times the same program exploration process. Object-centric debugging operations also
generate false positives. For example, an object-centric breakpoint might halt the system
many times for a single object. Developers then need to go through numerous haltings
until finding useful information for debugging. This is as tedious as manually stepping
an execution with a standard debugger.
      </p>
      <p>
        Time-traveling debugging to the rescue. With time-traveling debuggers, developers
are able to deterministically explore a program execution back and forth in time [
        <xref ref-type="bibr" rid="ref4 ref5 ref6 ref7">4, 5, 6, 7</xref>
        ].
When they miss a critical point, developers can rewind an execution and replay it from a
few steps back. This prevents developers from the hassle of having to restart the entire
execution and to repeat the same debugging investigation [
        <xref ref-type="bibr" rid="ref8 ref9">8, 9</xref>
        ].
      </p>
      <p>We argue that this capability of navigating through time could improve the application
of object-centric debugging. Developers would be able to explore the execution to find
which object to debug without the risk of missing an interesting moment, and to navigate
directly to events of interest for those objects. Furthermore, time-traveling debuggers
could provide new support for tracking objects to debug. For example, we could specify
what objects we are looking for by using a predicate expression eg., objects of a specific
class, or with specific instance variables values , and automatically explore the execution
back and forth to find those objects. However, to the best of our knowledge, time-traveling
debuggers do not support object-centric debugging and vice-versa.</p>
      <p>
        Proposition: combining time-traveling and object-centric debugging. We argue that
enhancing object-centric debugging by time-traveling mechanisms would enable new
debugging tools (dedicated interfaces, requests, views...) that would improve the debugging
of object-oriented programs. In this paper, we illustrate our first probe combining both
techniques. We use our execution querying system named Time-Traveling Queries [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ]
(TTQs), which automatically and systematically explore an execution to find objects
and to define time-traveling debugging operations on them. We present SeekerOC, our
time-traveling debugger prototype that implements object-centric queries. We discuss
the benefits of joining both techniques in terms of debugging capabilities and efect, and
why it is worth pushing this research perspective further on.
      </p>
    </sec>
    <sec id="sec-2">
      <title>2. Identifying Particular Objects is Challenging: A Running</title>
    </sec>
    <sec id="sec-3">
      <title>Example</title>
      <p>In the following, we illustrate the dificulties developers go through when they try to
comprehend objects behavior during debugging. We explain how object-centric debugging
and time-traveling debugging support these challenges, and their limitations. As an
example, we use a test method from the Pharo 11 code base:</p>
      <p>Listing 1: The split-join test of collections in Pharo 11.</p>
      <p>S p l i t J o i n T e s t &gt;&gt; t e s t S p l i t O r d e r e d C o l l e c t i o n O n O r d e r e d C o l l e c t i o n
s e l f a s s e r t : ( ( ( 1 to : 10) a s O r d e r e d C o l l e c t i o n ) s p l i t O n : ( ( 4 to : 5)
a s O r d e r e d C o l l e c t i o n ) )
e q u a l s : {(1 to : 3) a s O r d e r e d C o l l e c t i o n . (6 to : 10) a s O r d e r e d C o l l e c t i o n }
a s O r d e r e d C o l l e c t i o n</p>
      <p>In this test, an OrderedCollection of 10 elements is split by another
OrderedCollection with two elements. This operation is expected to produce a new
OrderedCollection containing both left and right sides of the split operation (each
side of the split is an OrderedCollection). The developer, trying to understand this
execution, wants to obtain information about the behavior and state of instances of
OrderedCollection during the execution of the test. The standard procedure is to step
the execution until the desired object is instantiated. This potentially requires numerous
and carefully executed steps before the observation of the desired object can take place.
Moreover, the execution of this test produces several instances of OrderedCollection,
and these instantiation calls are not immediately visible in the test code. It is dificult
to track each object, as none of them is seemly stored in a variable. This makes such
manual approach even more tedious.</p>
      <p>Using an object-centric debugger, developers can improve over such approach by
using specific breakpoints that halts the execution whenever a class is instantiated.
With this technique, developers need to halt a certain number of times to reach the
OrderedCollection of interest. Once the object of interest has been reached, developers
can use object-centric breakpoints to observe the object’s behavior and the evolution
of its state. One downside of this technique is that it might take many halts to reach
the object of interest in the first place, and then several other object-centric breakpoints
to observe a relevant information. If the developer accidentally misses that relevant
information, then all this procedure has to be restarted from scratch.</p>
      <p>By using a time-traveling debugger, we can enhance this approach by navigating back
and forth in the execution. If developers miss the observation of one of the collections, or
if they passed it and want to observe it again, they reverse the execution and look for
that collection, without the need to redoing everything from the beginning.</p>
      <p>Object-centric debugging and time-traveling debugging both provide enhancements
over standard debugging tools on their own. We argue that they can complement each
other to improve debugging further. In the following, we start to explore how these
techniques can benefit from each other, what is required to enable this new joint approach
and how could we materialize this approach into a tool.</p>
    </sec>
    <sec id="sec-4">
      <title>3. Debugging Objects Through Time with SeekerOC</title>
      <p>In this section we present our debugger SeekerOC. We explain how it helps solving the
dificulties identified by using debugging queries and new specialized tools.</p>
      <sec id="sec-4-1">
        <title>3.1. SeekerOC : Debugging with Object-centric Time-Traveling Queries</title>
        <p>Our debugger ofers a list of general purpose queries that can be conveniently executed
from a context menu. We extended this menu with new queries to ease the task of
identifying and tracking objects, as described next.</p>
        <p>Figure 1 shows our debugger opened at the beginning of the execution of the code
from Listing 1. To find all collections created during the execution of that code, we
select the OrderedCollection string and we execute the query All instances creation
of class named as selection from the context menu (Figure 1(a)). Once the query has
been executed, the results are displayed in a table (Figure 1(b)). These results contain
the complete list of all the OrderedCollection objects that are instantiated during the
execution of the debugged program.</p>
        <p>From the results table, we efortlessly have access to each one of these objects by
right clicking the corresponding result item, and choosing the command inspect object
about to be instantiated (Figure 1(c)). This command opens an inspector on the object
corresponding to the selected result row, and shows the object state in the execution
state from which we executed the query. If the object has not yet been instantiated, the
execution is advanced to such event, so the object can be inspected.</p>
        <p>Every result entry of TTQs includes a timestamp (the step number) of every registered
event. Clicking in the step column of any result item will advance or reverse the
execution, time-traveling to the registered timestamp. This feature makes queries results
act as bookmarks of an execution, providing a practical and precise alternative to using
breakpoints and tedious stepping operations for program exploration.</p>
      </sec>
      <sec id="sec-4-2">
        <title>3.2. The SeekerOC Inspector : A Promising Object-centric Querying Hub</title>
        <p>Pharo traditionally ofers a graphical utility for object inspection — a view that displays
information about the state of an object, its API, and other useful information. During a
SeekerOC debugging session, inspecting any object of the debugged execution will open
an enhanced version of the Pharo Inspector.</p>
        <p>This specialized inspector synchronizes with the time-traveling debugger to keep an
updated view of the inspected object. Stepping the execution forward or backwards
triggers updates of the displayed information. This inspector contains a menu for
object-centric queries available for the inspected object (Figure 2):
• Time travel to instantiation instruction.</p>
        <p>• List all messages sent to the inspected object.</p>
        <p>Every TTQ provides a set of timestamp-indexed results in the Query Results Table.
Therefore, by clicking on the step column of every result item, we time-travel to the
timestamp of each registered event, without the inconveniences of stepping or halting.</p>
        <p>By using TTQs, the relevant debugging information of the execution is collected
efortlessly. This information is now directly accessible from the Query Results Table,
instead of requiring developers to go through the traditional manual debugging process.</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>4. Implementation</title>
      <p>
        We built our experimental object-centric prototype SeekerOC upon SeekerDebugger, our
queryable time-traveling debugger implemented for Pharo. SeekerDebugger provides
the base mechanism to perform general purpose Time-Traveling Queries[
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] over an
execution. SeekerOC improves upon it, ofering new specialized queries that focus on
objects and their events. SeekerOC and its implementation details are available online1.
Determinism: A hard requirement. A requirement for object-centric queries to work
is that the program must be re-executed deterministically. Determinism is ensured by
our debugger backend. Instantiated objects’ identities will remain constant upon multiple
executions. We can therefore write queries about those objects without being concerned
that objects have a diferent identity after being reinstantiated during a re-execution.
1https://github.com/Willembrinck/SeekerOC-2022/
      </p>
    </sec>
    <sec id="sec-6">
      <title>5. Discussion: Towards Object-centric Time-traveling</title>
    </sec>
    <sec id="sec-7">
      <title>Debuggers</title>
      <p>Our work materializes an exploration step towards a new type of debugging tool: an
object-centric time-traveling debugger, based on debugging queries. In our proposition,
Time-Traveling Queries play the central role joining object-centric and time-traveling
debugging. Querying an execution ofers a traced representation of it, granting easy access
to objects. The time-traveling back-end ensures that the execution can be re-executed
following the same trace. Therefore, if an object can be identified in such trace, it can be
referenced in any re-execution of the program. This generates opportunities to explore
object-centric debugging in an new joint debugging paradigm, enabling techniques and
features previously unfeasible.</p>
      <p>These opportunities open many questions. Are TTQs the only mechanism required to
connect both techniques? If not, what are the required properties and/or mechanisms to
build object-centric time-traveling debuggers? What precisely are the benefits of such
debugger, and to what extent do they benefit to the debugging activity? In future work,
we plan to investigate these questions by pursuing our implementation of object-centric
TTQs and analyzing their requirements and efectiveness through empirical experiments.</p>
    </sec>
    <sec id="sec-8">
      <title>6. Related Work</title>
      <p>
        Object-centric debugging and time traveling debugging have been the subject of research
in the recent years. However, and to the best of our knowledge, they have never been
combined to support each other. Here we discuss how some of these works relate to ours.
Object-centric debuggers. Object Miners [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ] is a set of object-centric tools to acquire,
capture and replay objects from specific expressions of a program. Developers select
(sub)expressions from the program from which objects are automatically captured and
debugged during the execution. Specific objects’ state can be recorded, then replayed
and traversed to observe the evolution of that state. While the tool allows for exploring
the past state of an object, it does not support time-traveling operations.
      </p>
      <p>
        Other work [
        <xref ref-type="bibr" rid="ref12 ref13">12, 13</xref>
        ] keep track of changes in objects during the execution of programs.
Developers can visualize past states of objects and their behavior. This is a post-mortem
approach without time-traveling capabilities.
      </p>
      <p>
        Time-traveling debuggers. Expositor [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ] combines scripting and time-travel debugging
to allow programmers to automate complex debugging tasks. From an execution, Expositor
generates traces that developers manipulate as lists with operations such as map and filter.
Our query model provides a similar behavior, where execution traces can be created,
operated, and evaluated to generate results. However, Expositor does not provide a tool
to visualize and exploit results, and does not support object-centric operations.
      </p>
      <p>
        Whyline [
        <xref ref-type="bibr" rid="ref14 ref15">14, 15</xref>
        ] ofers contextual queries for program comprehension. It ofers certains
object-centric queries, but they are dificult to extend. In contrast, SeekerOC is extensible
through user defined TTQs, giving developers the means to create new specialized queries.
In this paper we argued that time-traveling debuggers could provide support to the
practical application of object-centric debugging. We explored this concept by building
SeekerOC, a time-traveling debugger using Time-Traveling Queries. TTQs provide the
means for quick execution exploration which enhances developers capabilities for seeking
the important object-related events during debugging. Our queries include information in
their results that facilitates object identification, enabling our new proposed specialized
object-centric tools, such as the improved object Inspector and its object-centric TTQs
menu. Due to the importance of TTQs in our proposition, an interesting prospect of
research is to explore what new queries can boost object-centric debugging activities.
      </p>
    </sec>
    <sec id="sec-9">
      <title>Acknowledgments References</title>
      <p>This work is funded by the ANR project OCRE https://anr.fr/Projet-ANR-21-CE25-0004
and Inria.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>J.</given-names>
            <surname>Ressia</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Bergel</surname>
          </string-name>
          ,
          <string-name>
            <given-names>O.</given-names>
            <surname>Nierstrasz</surname>
          </string-name>
          ,
          <article-title>Object-centric debugging</article-title>
          ,
          <source>in: Proceeding of the 34rd international conference on Software engineering, ICSE '12</source>
          ,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>C.</given-names>
            <surname>Corrodi</surname>
          </string-name>
          ,
          <article-title>Towards eficient object-centric debugging with declarative breakpoints</article-title>
          ,
          <source>in: SATToSE</source>
          <year>2016</year>
          ,
          <year>2016</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>S.</given-names>
            <surname>Costiou</surname>
          </string-name>
          ,
          <article-title>Unanticipated behavior adaptation : application to the debugging of running programs</article-title>
          ,
          <source>Ph.D. thesis</source>
          , Université de Bretagne occidentale - Brest,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>K. Y.</given-names>
            <surname>Phang</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J. S.</given-names>
            <surname>Foster</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Hicks</surname>
          </string-name>
          , Expositor:
          <article-title>Scriptable time-travel debugging with first-class traces</article-title>
          ,
          <source>in: 2013 35th International Conference on Software Engineering (ICSE)</source>
          ,
          <year>2013</year>
          , pp.
          <fpage>352</fpage>
          -
          <lpage>361</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>Y.</given-names>
            <surname>Wang</surname>
          </string-name>
          ,
          <string-name>
            <given-names>H.</given-names>
            <surname>Patil</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            <surname>Pereira</surname>
          </string-name>
          , G. Lueck,
          <string-name>
            <given-names>R.</given-names>
            <surname>Gupta</surname>
          </string-name>
          ,
          <string-name>
            <surname>I. Neamtiu</surname>
          </string-name>
          , Drdebug:
          <article-title>Deterministic replay based cyclic debugging with dynamic slicing</article-title>
          ,
          <source>in: Proceedings of annual IEEE/ACM international symposium on code generation and optimization, ACM</source>
          ,
          <year>2014</year>
          , p.
          <fpage>98</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>P.</given-names>
            <surname>Montesinos</surname>
          </string-name>
          ,
          <string-name>
            <given-names>L.</given-names>
            <surname>Ceze</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Torrellas</surname>
          </string-name>
          ,
          <article-title>Delorean: Recording and deterministically replaying sharedmemory multiprocessor execution eficiently</article-title>
          ,
          <source>ACM SIGARCH Computer Architecture News</source>
          <volume>36</volume>
          (
          <year>2008</year>
          )
          <fpage>289</fpage>
          -
          <lpage>300</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>C.</given-names>
            <surname>Zamfir</surname>
          </string-name>
          , G. Altekar, G. Candea,
          <article-title>Debug determinism: The sweet spot for {Replay-Based} debugging</article-title>
          ,
          <source>in: 13th Workshop on Hot Topics in Operating Systems (HotOS XIII)</source>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>E. T.</given-names>
            <surname>Barr</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Marron</surname>
          </string-name>
          , Tardis:
          <article-title>Afordable time-travel debugging in managed runtimes</article-title>
          ,
          <source>in: Proceedings of International Conference on OOPSLA'14</source>
          , volume
          <volume>49</volume>
          , ACM,
          <year>2014</year>
          , pp.
          <fpage>67</fpage>
          -
          <lpage>82</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>J.</given-names>
            <surname>Hoey</surname>
          </string-name>
          , I. Lanese,
          <string-name>
            <given-names>N.</given-names>
            <surname>Nishida</surname>
          </string-name>
          , I. Ulidowski,
          <string-name>
            <surname>G.</surname>
          </string-name>
          <article-title>Vidal, A case study for reversible computing: Reversible debugging of concurrent programs</article-title>
          .,
          <year>2020</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>M.</given-names>
            <surname>Willembrinck</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Costiou</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Etien</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Ducasse</surname>
          </string-name>
          ,
          <article-title>Time-traveling debugging queries: Faster program exploration</article-title>
          ,
          <source>in: 2021 IEEE 21st International Conference on Software Quality, Reliability and Security (QRS)</source>
          ,
          <year>2021</year>
          , pp.
          <fpage>642</fpage>
          -
          <lpage>653</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>S.</given-names>
            <surname>Costiou</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Kerboeuf</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            <surname>Toullec</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Plantec</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Ducasse</surname>
          </string-name>
          ,
          <article-title>Object miners: Acquire, capture and replay objects to track elusive bugs</article-title>
          ,
          <source>Journal of Object Technology</source>
          <volume>19</volume>
          (
          <year>2020</year>
          ) 1:
          <fpage>1</fpage>
          -
          <lpage>32</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>A.</given-names>
            <surname>Lienhard</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Ducasse</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Gîrba</surname>
          </string-name>
          ,
          <string-name>
            <given-names>O.</given-names>
            <surname>Nierstrasz</surname>
          </string-name>
          ,
          <article-title>Capturing how objects flow at runtime</article-title>
          ,
          <source>in: Proceedings International Workshop on PCODA'06</source>
          ,
          <year>2006</year>
          , pp.
          <fpage>39</fpage>
          -
          <lpage>43</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>A.</given-names>
            <surname>Lienhard</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Gîrba</surname>
          </string-name>
          ,
          <string-name>
            <given-names>O.</given-names>
            <surname>Nierstrasz</surname>
          </string-name>
          ,
          <article-title>Practical object-oriented back-in-time debugging</article-title>
          ,
          <source>in: Proceedings of the 22nd ECOOP'08</source>
          , volume
          <volume>5142</volume>
          <source>of LNCS</source>
          , Springer,
          <year>2008</year>
          , pp.
          <fpage>592</fpage>
          -
          <lpage>615</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>A. J.</given-names>
            <surname>Ko</surname>
          </string-name>
          ,
          <string-name>
            <given-names>B. A.</given-names>
            <surname>Myers</surname>
          </string-name>
          ,
          <article-title>Designing the whyline: a debugging interface for asking questions about program behavior</article-title>
          ,
          <source>in: Proceedings of the 2004 conference on Human factors in computing systems</source>
          , ACM Press,
          <year>2004</year>
          , pp.
          <fpage>151</fpage>
          -
          <lpage>158</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <given-names>A. J.</given-names>
            <surname>Ko</surname>
          </string-name>
          ,
          <string-name>
            <given-names>B. A.</given-names>
            <surname>Myers</surname>
          </string-name>
          ,
          <article-title>Debugging reinvented: Asking and answering why and why not questions about program behavior</article-title>
          ,
          <source>in: In Proceedings of the 30th ICSE 08</source>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>