<!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>
      <journal-title-group>
        <journal-title>ISEE</journal-title>
      </journal-title-group>
    </journal-meta>
    <article-meta>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Linus W. Dietz</string-name>
          <email>linus.dietz@tum.de</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Johannes Manner and Simon Harrer</string-name>
          <email>firstname.lastname@uni-bamberg.de</email>
          <xref ref-type="aff" rid="aff2">2</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Jörg Lenhard</string-name>
          <email>joerg.lenhard@kau.se</email>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Department of Informatics, Technical University of Munich</institution>
          ,
          <country country="DE">Germany</country>
        </aff>
        <aff id="aff1">
          <label>1</label>
          <institution>Department of Mathematics</institution>
          ,
          <addr-line>and Computer Science</addr-line>
          ,
          <institution>Karlstad University</institution>
          ,
          <country country="SE">Sweden</country>
        </aff>
        <aff id="aff2">
          <label>2</label>
          <institution>Distributed Systems Group, University of Bamberg</institution>
          ,
          <country country="DE">Germany</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2018</year>
      </pub-date>
      <volume>1</volume>
      <fpage>24</fpage>
      <lpage>27</lpage>
      <abstract>
        <p>-Learning programming is hard - teaching it well is even more challenging. At university, the focus is often on functional correctness and neglects the topic of clean and maintainable code, despite the dire need for developers with this skill set within the software industry. We present a feedbackdriven teaching concept for college students in their second to third year that we have applied and refined successfully over a period of more than six years and for which received the faculty's teaching award. Evaluating the learning process within a semester of student submissions (n=18) with static code analysis tools shows satisfying progress. Identifying the correction of the in-semester programming assignments as the bottleneck for scaling the number of students in the course, we propose using a knowledge base of code examples to decrease the time to feedback and increase feedback quality. From our experience in assessing student code, we have compiled such a knowledge base with the typical issues of Java learners' code in the format of before/after comparisons. By simply referencing the problem to the student, the quality of feedback can be improved, since such comparisons let the student understand the problem and the rationale behind the solution. Further speed-up is achieved by using a curated list of static code analysis checks to help the corrector in identifying violations in the code swiftly. We see this work as a foundational step towards online courses with hundreds of students learning how to write clean code.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>
        I. INTRODUCTION
emerging teaching method. However, the automated assessment
of programming assignments is challenging [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ] and most often
only focuses on functional correctness instead of code quality. A
study among 227 IT professionals finds that the most important
skill is the “ability to read, understand and modify programs
written by others” [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ]. Since low code quality has a direct
effect on maintainability, we argue that clean code should be
an integral part of the programming education. Consequently,
the motivating questions we seek to answer in this paper are:
• How to teach clean code at university?
• How to teach clean code at scale?
We present a didactic concept that describes how to effectively
teach programming to undergraduates with an emphasis on
writing and reviewing code. Identifying the correction of
assignments, (i.e., providing high-quality feedback) as the
bottleneck to scale the participants in the course, we use a
knowledge base [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ] and propose automated static code analysis
to speed up assessment while preserving the quality of feedback.
      </p>
      <p>The interplay between these two components is promising, as
it enables teachers with little prior experience to give students
the necessary information to improve their coding style.</p>
      <p>The driving idea behind this paper is to assess what academia
can learn from industry to achieve high code quality in teaching.</p>
      <p>Therefore, we briefly discuss the concept of code quality and
how it is achieved in industry in the next section. On this
basis, we present and evaluate our didactic concept based on
writing and reviewing code in Section III. In Section IV, we
present the knowledge base and a tool for automated static
code analysis for code quality in an educational context. We
conclude our findings and point out future work in Section V.</p>
      <p>Many computer science graduates lack programming
proficiency when starting their first software engineering job.</p>
      <p>Programming at university is traditionally taught in lectures
followed by practical exercises that usually revolve around
theoretical concepts like algorithms, data structures or specialized
aspects of programming paradigms (i.e., object-orientation or
functional programming). Such courses challenge the students
to develop software to prove that they can apply the theoretical
concepts. These prototypes, however, are usually trashed II. FOUNDATIONS
after the end of the course. Consequently, students have few From a pragmatic point of view, code quality is strongly
incentives to self-educate themselves in writing code that not linked to understandability: How easy is it for other developers
only works, but is also of high quality. to understand a piece of code and how well can it be extended</p>
      <p>
        Given the high demand for computer scientists with college and reused in other contexts? The concept is referred to in
degrees in industry, many students choose this challenging several books, most prominently in Clean Code [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ], Code
Comcourse of studies. From 2009 onwards, the faculty for Informa- plete [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ], Effective Java [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ], The Pragmatic Programmer [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ]
tion Systems and Applied Computer Sciences at the University and Refactoring [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ]. From a business perspective it can also
of Bamberg grew from 340 students to 1200 in 2017. It is a be seen as a function of the maintenance costs, which typically
huge challenge for lecturers to keep up the quality of teaching, amounts to 40–80% of the total project costs [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ].
since they inevitably will have less time for providing individual To lower such costs, the software industry has introduced
feedback to the students. This is problematic, as teaching many ways to improve the coding process, most of them fitting
programming well is time-consuming [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. Therefore, e-learning, under the hyped term ‘agile’ [
        <xref ref-type="bibr" rid="ref12">12</xref>
        ]. For instance, Li et al. report
especially Massive Open Online Courses (MOOCs) [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] are an increased software code quality of a team using Scrum in a
longitudinal study [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ]. Code reviews and feedback play a vital
role in agile methods. In pair programming [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] the review is
done simultaneously with a partner. Mob programming [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ]
even extends this to a group of people. Besides pairing,
companies also use ‘pull requests’ with continuous integration (CI),
where the proposed patch for the upstream is automatically
tested and needs to be signed off by another developer. In
addition, companies often use static code analysis in their CI
pipeline to ensure that the code adheres to a predefined style.
      </p>
      <p>A number of static code analysis tools are freely available,
e.g., Checkstyle1, PMD2 or SpotBugs3. They operate on source
or bytecode level and automatically detect common code smells
and careless mistakes that are not easy to spot. To use them
efficiently, they need to be fine-tuned by an expert. A more
user-friendly solution are online code quality services like
SonarQube4 or Codacy5. They build upon the mentioned static
code analysis tools, however, they require in-depth integration
into the build pipeline.</p>
    </sec>
    <sec id="sec-2">
      <title>III. TEACHING CLEAN CODE AT UNIVERSITY</title>
      <p>The availability of a mentor who supports the learner is
a huge benefit. We argue that high-quality code in industry
is created when several people work together and review
each other’s code, either simultaneously in pair programming
sessions or when assessing each others code in pull requests.
From this insight, the following didactic concept has a strong
emphasis on reviewing code in various ways.</p>
      <sec id="sec-2-1">
        <title>A. Didactic Concept</title>
        <p>Programming</p>
        <p>Concept</p>
        <p>Exercise
Programming
Assignment
Theoretical
Concept
presented to the plenum of students, who review and improve
upon the solution with help and input from the lecturers. These
discussions on improving the code step-by-step are central to
the learning outcome, as this is where the students observe
the refactoring process, learn about the requirements in the
programing assignments, and experience the transformation of
a first working solution to clean code.</p>
        <p>
          2) Assignment: During the semester, students work on
multiple assignments in groups. The assignments require
the application of the previously introduced and practiced
programming concepts from the lectures, but put them in a
larger scope to address more realistic and complex problems
(e.g., programming a reference manager or an issue tracker).
The assignments have to be submitted within a given timeframe
using Git and are graded by the lecturers. The students receive
a detailed textual code review of their solution with a focus
on code quality, and refactoring opportunities, since they
usually get most functional aspects right. Besides the individual
feedback, the lecturers also publish a collection of common
issues found in the assignments to the course. These common
issues serve as a knowledge base for the course and have
resulted in a text book, Java by Comparison [
          <xref ref-type="bibr" rid="ref5">5</xref>
          ].
        </p>
        <p>3) Examination: Finally, during examination, both the
theoretical concepts of the course itself and clean code skills
are evaluated. The students are examined individually in an oral
examination. During this examination, a few initial theoretical
questions are used to check if the students understood the
general concepts. Then, the students are asked to explain how
they solved specific aspects in their own assignments’ code.
This is to evaluate whether they can make the transfer from
the theoretical concepts to practical knowledge and also to
assess whether they have contributed sufficiently to the group’s
submissions. Finally, the students are asked to review a small
snippet of unknown code regarding bugs and code smells.</p>
        <p>Since 2011, this concept has been used in two practical
programming courses with 3 ECTS for undergraduate computer
science students at the University of Bamberg: ‘Advanced Java
Programming’ (AJP) covering XML serialization, testing, and
MVC-based GUIs, and ‘Introduction to Parallel and Distributed
Programming’ covering systems communicating through shared
memory and message passing on the JVM.</p>
        <p>These courses are taught in bi-weekly, four-hour lab sessions.
The students need to hand in four two-week assignments solved
by groups of three, and pass an individual 15-minute oral
examination. In addition, we also provide an optional student
help desk and forum support for any course-related questions.
Students have rated our courses on average 1.5 (on a Likert
scale from 1–very good to 5–very bad) within the last six years
in the university’s standardized evaluation form. Furthermore,
the lecturers were nominated six times for the excellent teaching
award of the faculty and won it once.</p>
      </sec>
      <sec id="sec-2-2">
        <title>C. Assignment Evaluation</title>
        <p>In the following, we present our findings from analyzing
student code submissions using static code analysis. First, we
Interactive
Code Review</p>
        <p>Lecturer
Code Review
Walk-Through
Code Review</p>
        <p>Lecture
Oral Exam
Assignment</p>
      </sec>
      <sec id="sec-2-3">
        <title>B. Application</title>
        <p>A sketch of the didactic concept is depicted in Fig. 1 and it
covers three parts: lecture, assignments, and the examination.
Note that at the end of each part, a different type of code
review is done. In the following, we detail each part.</p>
        <p>1) Lecture: Each course session is an alteration between
lecture time and practice. After having received a 10–30 minute
introduction to a programming concept, the students are asked
to solve a 20–40 minute exercise, in which they are to apply
this concept. After finishing the task, at least one solution is</p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>1Checkstyle, http://checkstyle.sourceforge.net</title>
      <p>2PMD https://pmd.github.io
3SpotBugs on Github: https://github.com/spotbugs/spotbugs
4https://www.sonarqube.org/
5https://www.codacy.com
CyclomaticComplexityCheck</p>
      <p>UnnecessaryFinalModifier</p>
      <p>ModifierOrderCheck
EqualsAvoidNullCheck</p>
      <p>CollapsibleIfStatements
AvoidFieldNameMatchingMethodName</p>
      <p>NeedBracesCheck</p>
      <p>UselessParentheses
AvoidInstantiatingObjectsInLoops</p>
      <p>PrematureDeclaration
UnnecessaryConstructor</p>
      <p>LogicInversion
MultipleVariableDeclarationsCheck</p>
      <p>AvoidCatchingNPE
MagicNumberCheck</p>
      <p>SingularField</p>
      <p>HiddenFieldCheck</p>
      <p>AbbreviationAsWordInNameCheck
VariableDeclarationUsageDistanceCheck</p>
      <p>VisibilityModifierCheck</p>
      <p>InnerAssignmentCheck</p>
      <p>ClassFanOutComplexityCheck
SignatureDeclareThrowsException
UncommentedEmptyMethodBody</p>
      <p>CompareObjectsWithEquals</p>
      <p>Normalized
Frequency
43 ! 0
37 ! 0
33 ! 0
23 ! 0
13 ! 0
128 ! 3
67 ! 2
226 ! 9
37 ! 2
16 ! 1
67 ! 63
3 ! 3
6 ! 6
10 ! 10
580 ! 633
27 ! 82
13 ! 50
43 ! 200
13 ! 72
6 ! 54
0 ! 8
0 ! 10
0 ! 17
0 ! 19
0 ! 19
provide an overview of the most frequent violations and then
we analyze the relative change of code quality violations. The
analysis is based on a curated list of static code analysis checks
described in Section IV-B.</p>
      <p>Table I lists the ten most frequent code style violations.
The magic number check is an outlier, as students did not
encapsulate all numbers into final static fields in the
beginning, and it was violated frequently in the last two
assignments (testing and GUI programming). The others
are typical problems of unprofessional code: bad naming,
unnecessary elements, and bad habits such as re-assigning
parameters or not preserving the stack trace when re-throwing
exceptions. Some, like the usage of the ternary ‘?’ operator,
might be opinionated, but we argue that it is nevertheless a
good didactic exercise to think about the use of such constructs.</p>
      <p>To obtain an impression of the overall learning process
between the beginning and the end of the course, we compare
the number of violations between the first and the last
assignment. Since the assignments differ in size, we normalize
the number of violations to make them comparable. There are
several metrics for normalizing code sizes, e.g., the lines of
code, the number of methods/classes, etc. We use the number
of non-final method parameters per assignment, since lines of
code would give the fourth assignment with GUI programming
too much weight. The non-final method parameters are better
than just counting the number of methods, as this metric also
accounts for how complex a method is. Finally, the metric was
already computed using the MethodArgumentCouldBeFinal rule
and we knew from the manual correction that our students did
not mark method parameters as final.</p>
      <p>Table II is subdivided into five categories that describe the
amount of change that happened to the violations. The first part
lists violations that disappeared entirely from the first to the last
assignment, followed by violations in which numbers decreased
strongly. Then, the table lists violations in which numbers
remained stable, followed by increasing and new violations.
Due to space constraints, we just show five violations per
category. Overall, the result is satisfying: Out of a total of 107
rules, 18 were not violated at all. The number of violations of
three rules was stable, and 44 decreased of which 21 were not
violated anymore. Of the 42 that increased, 32 did not occur in
the first assignment, so they can be seen as rather specialized.</p>
      <p>TABLE II</p>
      <p>CHANGE OF VIOLATIONS</p>
      <p>In summary, there is an improvement in the structure of the
code in the last assignment: problems regarding the cyclomatic
complexity diminish, and only few variables are prematurely
declared. Braces are almost always placed, and most
unnecessary parentheses are removed. Furthermore, bad habits, like
checking references with equals() and instantiating objects
in loops plummeted.</p>
      <p>On the increasing side, we note that there are still issues
with naming and declaring variables. The number of fields
only used in one method tripled, the number of local variables
shadowing a field went up by 284%, and variables were often
defined too far from their usage. We partially attribute these
issues to the topic of the last assignment, GUI programming,
where UI classes can be cluttered due to the UI framework.</p>
      <sec id="sec-3-1">
        <title>D. Validity Concerns</title>
        <p>These findings are meant to be understood as a tendency,
rather than strong empirical evidence. The reason for this is that
the data is from one semester with only 18 groups. Also, we
cannot attribute the effects to the teaching concept only, since
this is only a case study without a control group of submissions
that have not participated in the course. Nevertheless, the groups
did not know that their assignments would be analyzed with
static code analyses, so they did not program to conform with
a standard.</p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>IV. TEACHING CLEAN CODE AT SCALE</title>
      <p>Giving valuable feedback in programming is time consuming.
Marking about two dozen assignments that students without
prior experience can solve within two weeks usually requires
about a week of full-time work. We present two approaches
to reduce this time and improve the review quality.</p>
      <sec id="sec-4-1">
        <title>A. Knowledge Base</title>
        <p>During the assessment of assignments, we found that students
make similar mistakes that result in the same feedback. With a
knowledge base of issue, one can simply provide links to the
issues, thereby saving time and relieving the corrector from
repetitive actions. It also leads to shorter code reviews. We
propose the following structure for issues in the knowledge
base:</p>
        <p>Name A concise name capturing the solution to a code
quality problem as an action, for example “Avoid
Negations”.</p>
        <p>Code Two code snippets within the same context, one
containing the highlighted problem and the other
one the solution. For example, a snippet containing
a negation named !done and a snippet with the
refactored solution like inProgress.</p>
        <p>Text Two detailed explanations making an argument
explaining the problem and supporting the solution, e.g.,
negations are harder to understand and the refactored
solution reads much easier.</p>
        <p>
          At first, we created a knowledge base for each assignment in
the form of a markdown document named “common issues”.
We noticed a time reduction in marking itself, more consistent
and comparable markings, and, therefore, a reduction in the
number of questions regarding the markings and comments.
Furthermore, the knowledge base created a common
terminology for the discussions in the courses. We have turned these
“common issues” per assignment into a larger knowledge base in
the form of a book [
          <xref ref-type="bibr" rid="ref5">5</xref>
          ], covering the most common “common
issues” with high-quality code and text.
        </p>
      </sec>
      <sec id="sec-4-2">
        <title>B. Automated Didactic Code Review</title>
        <p>With a universal knowledge base in place, the correction
is essentially reduced to spotting the problematic parts in the
code and referring the students to the corresponding items. In
practice, this is not trivial, since the corrector must determine
the functional correctness before assessing code quality. For
this we recommend using a large set of integration tests.</p>
        <p>For automating the code quality review, we have developed
a static code analysis meta tool6 that can be integrated into
existing build setups using Gradle. Currently, it scans the code
for 107 code quality violations using PMD and Checkstyle and
produces a .csv output that contains the violated rule, the
identifier of the submission, and the location of the violation
(file, line, column). As mentioned before, static code analysis
tools need to be fine-tuned to be valuable. We picked these
107 rules based on our knowledge from the course, making
them suitable for most learners, without enforcing a specific
style of programming and producing too many false positives.
Furthermore, the lecturer can adjust them to perfectly fit the
needs of the students. Naturally, the rules cannot cover all
issues in the code, since some problems are impossible to detect
automatically. Nevertheless, the detection of many issues can
be improved, without much effort on the side of the corrector.</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>V. CONCLUSIONS</title>
      <p>This paper is motivated by the question of how
universities can learn from software companies to improve their
programming education. We presented and evaluated a code
review-driven course concept for undergraduates that has been
executed and awarded at the University of Bamberg. Facing
the challenges of scaling the concept to an increasing number
of students while keeping up the quality of code reviews, we
proposed using static code analysis combined with a book on
code quality that is suited for the target group of the learners.</p>
      <p>
        In the future, we aim to empirically evaluate the didactic
concept along with the knowledge base and the tool at multiple
universities through experiments. Furthermore, we plan to
integrate the knowledge base and tool into existing automatic
educational code assessment frameworks like ArTEMiS [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ].
      </p>
    </sec>
    <sec id="sec-6">
      <title>ACKNOWLEDGMENTS</title>
      <p>The authors would like to thank Guido Wirtz for giving us the
freedom to develop these courses. Moreover, we thank our student
assistants Christian Preißinger, Gabriel Nikol, Michael Träger, Henrik
Cech, and Tobias Jakubowitz who helped us lecture those courses.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>A.</given-names>
            <surname>Vihavainen</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Paksula</surname>
          </string-name>
          , and
          <string-name>
            <given-names>M.</given-names>
            <surname>Luukkainen</surname>
          </string-name>
          , “
          <article-title>Extreme apprenticeship method in teaching programming for beginners,”</article-title>
          <source>in Proceedings of the 42nd ACM Technical Symposium on Computer Science Education</source>
          . New York, NY, USA: ACM,
          <year>2011</year>
          , pp.
          <fpage>93</fpage>
          -
          <lpage>98</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>F. G.</given-names>
            <surname>Martin</surname>
          </string-name>
          , “
          <article-title>Will massive open online courses change how we teach?” Communications of the ACM</article-title>
          , vol.
          <volume>55</volume>
          , no.
          <issue>8</issue>
          , pp.
          <fpage>26</fpage>
          -
          <lpage>28</lpage>
          , Aug.
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>T.</given-names>
            <surname>Staubitz</surname>
          </string-name>
          ,
          <string-name>
            <given-names>H.</given-names>
            <surname>Klement</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Renz</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Teusner</surname>
          </string-name>
          , and
          <string-name>
            <given-names>C.</given-names>
            <surname>Meinel</surname>
          </string-name>
          , “
          <article-title>Towards practical programming exercises and automated assessment in massive open online courses</article-title>
          ,” in IEEE TALE,
          <year>2015</year>
          , pp.
          <fpage>23</fpage>
          -
          <lpage>30</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>J.</given-names>
            <surname>Bailey</surname>
          </string-name>
          and R. B. Mitchell, “
          <article-title>Industry perceptions of the competencies needed by computer programmers: Technical, business</article-title>
          , and soft skills,”
          <source>Computer Information Systems</source>
          , vol.
          <volume>47</volume>
          , no.
          <issue>2</issue>
          , pp.
          <fpage>28</fpage>
          -
          <lpage>33</lpage>
          , Jan.
          <year>2006</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>S.</given-names>
            <surname>Harrer</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Lenhard</surname>
          </string-name>
          , and
          <string-name>
            <given-names>L.</given-names>
            <surname>Dietz</surname>
          </string-name>
          , Java by Comparison:
          <article-title>Become a Java Craftsman in 70 Examples</article-title>
          . Pragmatic Bookshelf,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>R. C.</given-names>
            <surname>Martin</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Clean</given-names>
            <surname>Code</surname>
          </string-name>
          . Prentice Hall,
          <year>2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <surname>S. McConnell</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Code</given-names>
            <surname>Complete</surname>
          </string-name>
          . Microsoft Press,
          <year>2004</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>J.</given-names>
            <surname>Bloch</surname>
          </string-name>
          , Effective Java, 3rd ed.
          <source>Addison Wesley</source>
          , Nov.
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>A.</given-names>
            <surname>Hunt</surname>
          </string-name>
          and
          <string-name>
            <given-names>D.</given-names>
            <surname>Thomas</surname>
          </string-name>
          , The Pragmatic Programmer: From Journeyman to Master. Boston, MA, USA: Addison Wesley,
          <year>1999</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>M.</given-names>
            <surname>Fowler</surname>
          </string-name>
          , Refactoring.
          <source>Addison Wesley</source>
          ,
          <year>1999</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>R.</given-names>
            <surname>Glass</surname>
          </string-name>
          , “
          <article-title>Frequently forgotten fundamental facts about software engineering</article-title>
          ,
          <source>” IEEE Software</source>
          , vol.
          <volume>18</volume>
          , no.
          <issue>3</issue>
          , pp.
          <fpage>112</fpage>
          -
          <lpage>111</lpage>
          , May
          <year>2001</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>P.</given-names>
            <surname>Abrahamsson</surname>
          </string-name>
          ,
          <string-name>
            <given-names>O.</given-names>
            <surname>Salo</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Ronkainen</surname>
          </string-name>
          , and
          <string-name>
            <given-names>J.</given-names>
            <surname>Warsta</surname>
          </string-name>
          , “
          <article-title>Agile software development methods: Review and analysis</article-title>
          ,
          <source>” CoRR</source>
          , vol.
          <source>abs/1709.08439</source>
          ,
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>J.</given-names>
            <surname>Li</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N. B.</given-names>
            <surname>Moe</surname>
          </string-name>
          , and T. Dybå, “
          <article-title>Transition from a plan-driven process to scrum: A longitudinal case study on software quality,” in Proceedings of the 2010 ACM-IEEE International Symposium on Empirical Software Engineering and Measurement</article-title>
          . ACM Press,
          <year>2010</year>
          , pp.
          <fpage>1</fpage>
          -
          <lpage>10</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>J. T.</given-names>
            <surname>Nosek</surname>
          </string-name>
          , “
          <article-title>The case for collaborative programming</article-title>
          ,
          <source>” Communications of the ACM</source>
          , vol.
          <volume>41</volume>
          , no.
          <issue>3</issue>
          , pp.
          <fpage>105</fpage>
          -
          <lpage>108</lpage>
          , mar
          <year>1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <given-names>A.</given-names>
            <surname>Wilson</surname>
          </string-name>
          , “
          <article-title>Mob programming - what works, what doesn't,” in Agile Processes in Software Engineering</article-title>
          and
          <string-name>
            <given-names>Extreme</given-names>
            <surname>Programming</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            <surname>Lassenius</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Dingsøyr</surname>
          </string-name>
          , and M. Paasivaara, Eds. Cham: Springer,
          <year>2015</year>
          , pp.
          <fpage>319</fpage>
          -
          <lpage>325</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          [16]
          <string-name>
            <given-names>S.</given-names>
            <surname>Krusche</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Seitz</surname>
          </string-name>
          , “
          <article-title>ArTEMiS - an automatic assessment management system for interactive learning,” in SIGCSE</article-title>
          . ACM,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>